test_TabUnloader.js (11730B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ 3 */ 4 "use strict"; 5 6 const { TabUnloader } = ChromeUtils.importESModule( 7 "moz-src:///browser/components/tabbrowser/TabUnloader.sys.mjs" 8 ); 9 10 let TestTabUnloaderMethods = { 11 isNonDiscardable(tab, weight) { 12 return /\bselected\b/.test(tab.keywords) ? weight : 0; 13 }, 14 15 isParentProcess(tab, weight) { 16 return /\bparent\b/.test(tab.keywords) ? weight : 0; 17 }, 18 19 isPinned(tab, weight) { 20 return /\bpinned\b/.test(tab.keywords) ? weight : 0; 21 }, 22 23 isLoading(tab, weight) { 24 return /\bloading\b/.test(tab.keywords) ? weight : 0; 25 }, 26 27 usingPictureInPicture(tab, weight) { 28 return /\bpictureinpicture\b/.test(tab.keywords) ? weight : 0; 29 }, 30 31 playingMedia(tab, weight) { 32 return /\bmedia\b/.test(tab.keywords) ? weight : 0; 33 }, 34 35 usingWebRTC(tab, weight) { 36 return /\bwebrtc\b/.test(tab.keywords) ? weight : 0; 37 }, 38 39 isPrivate(tab, weight) { 40 return /\bprivate\b/.test(tab.keywords) ? weight : 0; 41 }, 42 43 getMinTabCount() { 44 // Use a low number for testing. 45 return 3; 46 }, 47 48 getNow() { 49 return 100; 50 }, 51 52 *iterateProcesses(tab) { 53 for (let process of tab.process.split(",")) { 54 yield Number(process); 55 } 56 }, 57 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 }, 64 }; 65 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 }, 407 ]; 408 409 let globalBrowser = { 410 discardBrowser() { 411 return true; 412 }, 413 }; 414 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; 434 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 } 446 447 Assert.equal(expectedOrder, test.result); 448 } 449 });