Bug 1890689 Don't pretend to pre-buffer with DynamicResampler r=pehrsons
[gecko.git] / browser / modules / test / unit / test_TabUnloader.js
blob3d125828bb296834b106a252e78502df18336c65
1 /* Any copyright is dedicated to the Public Domain.
2  * http://creativecommons.org/publicdomain/zero/1.0/
3  */
4 "use strict";
6 const { TabUnloader } = ChromeUtils.importESModule(
7   "resource:///modules/TabUnloader.sys.mjs"
8 );
10 let TestTabUnloaderMethods = {
11   isNonDiscardable(tab, weight) {
12     return /\bselected\b/.test(tab.keywords) ? weight : 0;
13   },
15   isParentProcess(tab, weight) {
16     return /\bparent\b/.test(tab.keywords) ? weight : 0;
17   },
19   isPinned(tab, weight) {
20     return /\bpinned\b/.test(tab.keywords) ? weight : 0;
21   },
23   isLoading(tab, weight) {
24     return /\bloading\b/.test(tab.keywords) ? weight : 0;
25   },
27   usingPictureInPicture(tab, weight) {
28     return /\bpictureinpicture\b/.test(tab.keywords) ? weight : 0;
29   },
31   playingMedia(tab, weight) {
32     return /\bmedia\b/.test(tab.keywords) ? weight : 0;
33   },
35   usingWebRTC(tab, weight) {
36     return /\bwebrtc\b/.test(tab.keywords) ? weight : 0;
37   },
39   isPrivate(tab, weight) {
40     return /\bprivate\b/.test(tab.keywords) ? weight : 0;
41   },
43   getMinTabCount() {
44     // Use a low number for testing.
45     return 3;
46   },
48   getNow() {
49     return 100;
50   },
52   *iterateProcesses(tab) {
53     for (let process of tab.process.split(",")) {
54       yield Number(process);
55     }
56   },
58   async calculateMemoryUsage(processMap, tabs) {
59     let memory = tabs[0].memory;
60     for (let pid of processMap.keys()) {
61       processMap.get(pid).memory = memory ? memory[pid - 1] : 1;
62     }
63   },
66 let unloadTests = [
67   // Each item in the array represents one test. The test is a subarray
68   // containing an element per tab. This is a string of keywords that
69   // identify which criteria apply. The first part of the string may contain
70   // a number that represents the last visit time, where higher numbers
71   // are later. The last element in the subarray is special and identifies
72   // the expected order of the tabs sorted by weight. The first tab in
73   // this list is the one that is expected to selected to be discarded.
74   { tabs: ["1 selected", "2", "3"], result: "1,2,0" },
75   { tabs: ["1", "2 selected", "3"], result: "0,2,1" },
76   { tabs: ["1 selected", "2", "3"], process: ["1", "2", "3"], result: "1,2,0" },
77   {
78     tabs: ["1 selected", "2 selected", "3 selected"],
79     process: ["1", "2", "3"],
80     result: "0,1,2",
81   },
82   {
83     tabs: ["1 selected", "2", "3"],
84     process: ["1,2,3", "2", "3"],
85     result: "1,2,0",
86   },
87   {
88     tabs: ["9", "8", "6", "5 selected", "2", "3", "4", "1"],
89     result: "7,4,5,6,2,1,0,3",
90   },
91   {
92     tabs: ["9", "8 pinned", "6", "5 selected", "2", "3 pinned", "4", "1"],
93     result: "7,4,6,2,0,5,1,3",
94   },
95   {
96     tabs: [
97       "9",
98       "8 pinned",
99       "6",
100       "5 selected pinned",
101       "2",
102       "3 pinned",
103       "4",
104       "1",
105     ],
106     result: "7,4,6,2,0,5,1,3",
107   },
108   {
109     tabs: [
110       "9",
111       "8 pinned",
112       "6",
113       "5 selected pinned",
114       "2",
115       "3 selected pinned",
116       "4",
117       "1",
118     ],
119     result: "7,4,6,2,0,1,5,3",
120   },
121   {
122     tabs: ["1", "2 selected", "3", "4 media", "5", "6"],
123     result: "0,2,4,5,1,3",
124   },
125   {
126     tabs: ["1 media", "2 selected media", "3", "4 media", "5", "6"],
127     result: "2,4,5,0,3,1",
128   },
129   {
130     tabs: ["1 media", "2 media pinned", "3", "4 media", "5 pinned", "6"],
131     result: "2,5,4,0,3,1",
132   },
133   {
134     tabs: [
135       "1 media",
136       "2 media pinned",
137       "3",
138       "4 media",
139       "5 media pinned",
140       "6 selected",
141     ],
142     result: "2,0,3,5,1,4",
143   },
144   {
145     tabs: [
146       "10 selected",
147       "20 private",
148       "30 webrtc",
149       "40 pictureinpicture",
150       "50 loading pinned",
151       "60",
152     ],
153     result: "5,4,0,1,2,3",
154   },
155   {
156     // Since TestTabUnloaderMethods.getNow() returns 100 and the test
157     // passes minInactiveDuration = 0 to TabUnloader.getSortedTabs(),
158     // tab 200 and 300 are excluded from the result.
159     tabs: ["300", "10", "50", "100", "200"],
160     result: "1,2,3",
161   },
162   {
163     tabs: ["1", "2", "3", "4", "5", "6"],
164     process: ["1", "2", "1", "1", "1", "1"],
165     result: "1,0,2,3,4,5",
166   },
167   {
168     tabs: ["1", "2 selected", "3", "4", "5", "6"],
169     process: ["1", "2", "1", "1", "1", "1"],
170     result: "0,2,3,4,5,1",
171   },
172   {
173     tabs: ["1", "2", "3", "4", "5", "6"],
174     process: ["1", "2", "2", "1", "1", "1"],
175     result: "0,1,2,3,4,5",
176   },
177   {
178     tabs: ["1", "2", "3", "4", "5", "6"],
179     process: ["1", "2", "3", "1", "1", "1"],
180     result: "1,0,2,3,4,5",
181   },
182   {
183     tabs: ["1", "2 media", "3", "4", "5", "6"],
184     process: ["1", "2", "3", "1", "1", "1"],
185     result: "2,0,3,4,5,1",
186   },
187   {
188     tabs: ["1", "2 media", "3", "4", "5", "6"],
189     process: ["1", "2", "3", "1", "1,2,3", "1"],
190     result: "0,2,3,4,5,1",
191   },
192   {
193     tabs: ["1", "2 media", "3", "4", "5", "6"],
194     process: ["1", "2", "3", "1", "1,4,5", "1"],
195     result: "2,0,3,4,5,1",
196   },
197   {
198     tabs: ["1", "2 media", "3 media", "4", "5 media", "6"],
199     process: ["1", "2", "3", "1", "1,4,5", "1"],
200     result: "0,3,5,1,2,4",
201   },
202   {
203     tabs: ["1", "2 media", "3 media", "4", "5 media", "6"],
204     process: ["1", "1", "3", "1", "1,4,5", "1"],
205     result: "0,3,5,1,2,4",
206   },
207   {
208     tabs: ["1", "2 media", "3 media", "4", "5 media", "6"],
209     process: ["1", "2", "3", "4", "1,4,5", "5"],
210     result: "0,3,5,1,2,4",
211   },
212   {
213     tabs: ["1", "2 media", "3 media", "4", "5 media", "6"],
214     process: ["1", "1", "3", "4", "1,4,5", "5"],
215     result: "0,3,5,1,2,4",
216   },
217   {
218     tabs: ["1", "2", "3", "4", "5", "6"],
219     process: ["1", "1", "1", "2", "1,3,4,5,6,7,8", "1"],
220     result: "0,1,2,3,4,5",
221   },
222   {
223     tabs: ["1", "2", "3", "4", "5", "6", "7", "8"],
224     process: ["1", "1", "1", "2", "1,3,4,5,6,7,8", "1", "1", "1"],
225     result: "4,0,3,1,2,5,6,7",
226   },
227   {
228     tabs: ["1", "2", "3", "4", "5 selected", "6"],
229     process: ["1", "1", "1", "2", "1,3,4,5,6,7,8", "1"],
230     result: "0,1,2,3,5,4",
231   },
232   {
233     tabs: ["1", "2", "3", "4", "5 media", "6"],
234     process: ["1", "1", "1", "2", "1,3,4,5,6,7,8", "1"],
235     result: "0,1,2,3,5,4",
236   },
237   {
238     tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
239     process: ["1", "1", "1", "2", "1,3,4,5,6,7,8", "1", "1", "1"],
240     result: "0,3,1,2,5,6,7,4",
241   },
242   {
243     tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
244     process: ["1", "1,3,4,5,6,7,8", "1", "1", "1", "1", "1", "1"],
245     result: "1,0,2,3,5,6,7,4",
246   },
247   {
248     tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
249     process: ["1", "1", "1,3,4,5,6,7,8", "1", "1", "1", "1", "1"],
250     result: "2,0,1,3,5,6,7,4",
251   },
252   {
253     tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
254     process: ["1", "1", "1,1,1,1,1,1,1", "1", "1", "1", "1,1,1,1,1", "1"],
255     result: "0,1,2,3,5,6,7,4",
256   },
257   {
258     tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
259     process: ["1", "1", "1,2,3,4,5", "1", "1", "1", "1,2,3,4,5", "1"],
260     result: "0,1,2,3,5,6,7,4",
261   },
262   {
263     tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
264     process: ["1", "1", "1,6", "1", "1", "1", "1,2,3,4,5", "1"],
265     result: "0,2,1,3,5,6,7,4",
266   },
267   {
268     tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
269     process: ["1", "1", "1,6", "1,7", "1,8", "1,9", "1,2,3,4,5", "1"],
270     result: "2,3,0,5,1,6,7,4",
271   },
272   {
273     tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
274     process: ["1,10,11", "1", "1,2", "1,7", "1,8", "1,9", "1,2,3,4,5", "1"],
275     result: "0,3,1,5,2,6,7,4",
276   },
277   {
278     tabs: [
279       "1 media",
280       "2 media",
281       "3 media",
282       "4 media",
283       "5 media",
284       "6",
285       "7",
286       "8",
287     ],
288     process: ["1,10,11", "1", "1,2", "1,7", "1,8", "1,9", "1,2,3,4,5", "1"],
289     result: "6,5,7,0,1,2,3,4",
290   },
291   {
292     tabs: ["1", "2", "3"],
293     process: ["1", "2", "3"],
294     memory: ["100", "200", "300"],
295     result: "0,1,2",
296   },
297   {
298     tabs: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
299     process: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
300     memory: [
301       "100",
302       "200",
303       "300",
304       "400",
305       "500",
306       "600",
307       "700",
308       "800",
309       "900",
310       "1000",
311     ],
312     result: "0,1,2,3,4,5,6,7,8,9",
313   },
314   {
315     tabs: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
316     process: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
317     memory: [
318       "100",
319       "900",
320       "300",
321       "500",
322       "400",
323       "700",
324       "600",
325       "1000",
326       "200",
327       "200",
328     ],
329     result: "1,0,2,3,5,4,6,7,8,9",
330   },
331   {
332     tabs: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
333     process: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
334     memory: [
335       "1000",
336       "900",
337       "300",
338       "500",
339       "400",
340       "1000",
341       "600",
342       "1000",
343       "200",
344       "200",
345     ],
346     result: "0,1,2,3,5,4,6,7,8,9",
347   },
348   {
349     tabs: ["1", "2", "3", "4", "5", "6"],
350     process: ["1", "2,7", "3", "4", "5", "6"],
351     memory: ["100", "200", "300", "400", "500", "600", "700"],
352     result: "1,0,2,3,4,5",
353   },
354   {
355     tabs: ["1", "2", "3", "4", "5", "6", "7", "8"],
356     process: ["1,6", "2,7", "3,8", "4,1,2", "5", "6", "7", "8"],
357     memory: ["100", "200", "300", "400", "500", "600", "700", "800"],
358     result: "2,3,0,1,4,5,6,7",
359   },
360   {
361     tabs: ["1", "2", "3", "4", "5", "6", "7", "8"],
362     process: ["1", "1", "1", "2", "1", "1", "1", "1"],
363     memory: ["700", "1000"],
364     result: "0,3,1,2,4,5,6,7",
365   },
366   {
367     tabs: ["1", "2", "3", "4", "5", "6", "7", "8"],
368     process: ["1", "1", "1", "1", "2,1", "2,1", "3", "3"],
369     memory: ["1000", "2000", "3000"],
370     result: "0,1,2,4,3,5,6,7",
371   },
372   {
373     tabs: ["1", "2", "3", "4", "5", "6", "7", "8"],
374     process: ["2", "2", "2", "2", "2,1", "2,1", "3", "3"],
375     memory: ["1000", "600", "1000"],
376     result: "0,1,2,4,3,5,6,7",
377   },
378   {
379     tabs: ["1", "2", "3", "4", "5", "6", "7", "8"],
380     process: ["1", "1", "1", "2", "2,1,1,1", "2,1", "3", "3"],
381     memory: ["1000", "1800", "1000"],
382     result: "0,1,3,2,4,5,6,7",
383   },
384   {
385     tabs: ["1", "2", "3", "4", "5", "6", "7", "8"],
386     process: ["1", "1", "1", "2", "2,1,1,1", "2,1", "3", "3"],
387     memory: ["4000", "1800", "1000"],
388     result: "0,1,2,4,3,5,6,7",
389   },
390   {
391     // The tab "1" contains 4 frames, but its uniqueCount is 1 because
392     // all of those frames are backed by the process "1".  As a result,
393     // TabUnloader puts the tab "1" first based on the last access time.
394     tabs: ["1", "2", "3", "4", "5"],
395     process: ["1,1,1,1", "2", "3", "3", "3"],
396     memory: ["100", "100", "100"],
397     result: "0,1,2,3,4",
398   },
399   {
400     // The uniqueCount of the tab "1", "2", and "3" is 1, 2, and 3,
401     // respectively.  As a result the first three tabs are sorted as 2,1,0.
402     tabs: ["1", "2", "3", "4", "5", "6"],
403     process: ["1,7,1,7,1,1,7,1", "7,3,7,2", "4,5,7,4,6,7", "7", "7", "7"],
404     memory: ["100", "100", "100", "100", "100", "100", "100"],
405     result: "2,1,0,3,4,5",
406   },
409 let globalBrowser = {
410   discardBrowser() {
411     return true;
412   },
415 add_task(async function doTests() {
416   for (let test of unloadTests) {
417     function* iterateTabs() {
418       let tabs = test.tabs;
419       for (let t = 0; t < tabs.length; t++) {
420         let tab = {
421           tab: {
422             originalIndex: t,
423             lastAccessed: Number(/^[0-9]+/.exec(tabs[t])[0]),
424             keywords: tabs[t],
425             process: "process" in test ? test.process[t] : "1",
426           },
427           memory: test.memory,
428           gBrowser: globalBrowser,
429         };
430         yield tab;
431       }
432     }
433     TestTabUnloaderMethods.iterateTabs = iterateTabs;
435     let expectedOrder = "";
436     const sortedTabs = await TabUnloader.getSortedTabs(
437       0,
438       TestTabUnloaderMethods
439     );
440     for (let tab of sortedTabs) {
441       if (expectedOrder) {
442         expectedOrder += ",";
443       }
444       expectedOrder += tab.tab.originalIndex;
445     }
447     Assert.equal(expectedOrder, test.result);
448   }