summaryrefslogtreecommitdiffstats
path: root/browser/modules/test/unit/test_TabUnloader.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/modules/test/unit/test_TabUnloader.js')
-rw-r--r--browser/modules/test/unit/test_TabUnloader.js449
1 files changed, 449 insertions, 0 deletions
diff --git a/browser/modules/test/unit/test_TabUnloader.js b/browser/modules/test/unit/test_TabUnloader.js
new file mode 100644
index 0000000000..2177fe14e2
--- /dev/null
+++ b/browser/modules/test/unit/test_TabUnloader.js
@@ -0,0 +1,449 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+"use strict";
+
+const { TabUnloader } = ChromeUtils.import(
+ "resource:///modules/TabUnloader.jsm"
+);
+
+let TestTabUnloaderMethods = {
+ isNonDiscardable(tab, weight) {
+ return /\bselected\b/.test(tab.keywords) ? weight : 0;
+ },
+
+ isParentProcess(tab, weight) {
+ return /\bparent\b/.test(tab.keywords) ? weight : 0;
+ },
+
+ isPinned(tab, weight) {
+ return /\bpinned\b/.test(tab.keywords) ? weight : 0;
+ },
+
+ isLoading(tab, weight) {
+ return /\bloading\b/.test(tab.keywords) ? weight : 0;
+ },
+
+ usingPictureInPicture(tab, weight) {
+ return /\bpictureinpicture\b/.test(tab.keywords) ? weight : 0;
+ },
+
+ playingMedia(tab, weight) {
+ return /\bmedia\b/.test(tab.keywords) ? weight : 0;
+ },
+
+ usingWebRTC(tab, weight) {
+ return /\bwebrtc\b/.test(tab.keywords) ? weight : 0;
+ },
+
+ isPrivate(tab, weight) {
+ return /\bprivate\b/.test(tab.keywords) ? weight : 0;
+ },
+
+ getMinTabCount() {
+ // Use a low number for testing.
+ return 3;
+ },
+
+ getNow() {
+ return 100;
+ },
+
+ *iterateProcesses(tab) {
+ for (let process of tab.process.split(",")) {
+ yield Number(process);
+ }
+ },
+
+ async calculateMemoryUsage(processMap, tabs) {
+ let memory = tabs[0].memory;
+ for (let pid of processMap.keys()) {
+ processMap.get(pid).memory = memory ? memory[pid - 1] : 1;
+ }
+ },
+};
+
+let unloadTests = [
+ // Each item in the array represents one test. The test is a subarray
+ // containing an element per tab. This is a string of keywords that
+ // identify which criteria apply. The first part of the string may contain
+ // a number that represents the last visit time, where higher numbers
+ // are later. The last element in the subarray is special and identifies
+ // the expected order of the tabs sorted by weight. The first tab in
+ // this list is the one that is expected to selected to be discarded.
+ { tabs: ["1 selected", "2", "3"], result: "1,2,0" },
+ { tabs: ["1", "2 selected", "3"], result: "0,2,1" },
+ { tabs: ["1 selected", "2", "3"], process: ["1", "2", "3"], result: "1,2,0" },
+ {
+ tabs: ["1 selected", "2 selected", "3 selected"],
+ process: ["1", "2", "3"],
+ result: "0,1,2",
+ },
+ {
+ tabs: ["1 selected", "2", "3"],
+ process: ["1,2,3", "2", "3"],
+ result: "1,2,0",
+ },
+ {
+ tabs: ["9", "8", "6", "5 selected", "2", "3", "4", "1"],
+ result: "7,4,5,6,2,1,0,3",
+ },
+ {
+ tabs: ["9", "8 pinned", "6", "5 selected", "2", "3 pinned", "4", "1"],
+ result: "7,4,6,2,0,5,1,3",
+ },
+ {
+ tabs: [
+ "9",
+ "8 pinned",
+ "6",
+ "5 selected pinned",
+ "2",
+ "3 pinned",
+ "4",
+ "1",
+ ],
+ result: "7,4,6,2,0,5,1,3",
+ },
+ {
+ tabs: [
+ "9",
+ "8 pinned",
+ "6",
+ "5 selected pinned",
+ "2",
+ "3 selected pinned",
+ "4",
+ "1",
+ ],
+ result: "7,4,6,2,0,1,5,3",
+ },
+ {
+ tabs: ["1", "2 selected", "3", "4 media", "5", "6"],
+ result: "0,2,4,5,1,3",
+ },
+ {
+ tabs: ["1 media", "2 selected media", "3", "4 media", "5", "6"],
+ result: "2,4,5,0,3,1",
+ },
+ {
+ tabs: ["1 media", "2 media pinned", "3", "4 media", "5 pinned", "6"],
+ result: "2,5,4,0,3,1",
+ },
+ {
+ tabs: [
+ "1 media",
+ "2 media pinned",
+ "3",
+ "4 media",
+ "5 media pinned",
+ "6 selected",
+ ],
+ result: "2,0,3,5,1,4",
+ },
+ {
+ tabs: [
+ "10 selected",
+ "20 private",
+ "30 webrtc",
+ "40 pictureinpicture",
+ "50 loading pinned",
+ "60",
+ ],
+ result: "5,4,0,1,2,3",
+ },
+ {
+ // Since TestTabUnloaderMethods.getNow() returns 100 and the test
+ // passes minInactiveDuration = 0 to TabUnloader.getSortedTabs(),
+ // tab 200 and 300 are excluded from the result.
+ tabs: ["300", "10", "50", "100", "200"],
+ result: "1,2,3",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6"],
+ process: ["1", "2", "1", "1", "1", "1"],
+ result: "1,0,2,3,4,5",
+ },
+ {
+ tabs: ["1", "2 selected", "3", "4", "5", "6"],
+ process: ["1", "2", "1", "1", "1", "1"],
+ result: "0,2,3,4,5,1",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6"],
+ process: ["1", "2", "2", "1", "1", "1"],
+ result: "0,1,2,3,4,5",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6"],
+ process: ["1", "2", "3", "1", "1", "1"],
+ result: "1,0,2,3,4,5",
+ },
+ {
+ tabs: ["1", "2 media", "3", "4", "5", "6"],
+ process: ["1", "2", "3", "1", "1", "1"],
+ result: "2,0,3,4,5,1",
+ },
+ {
+ tabs: ["1", "2 media", "3", "4", "5", "6"],
+ process: ["1", "2", "3", "1", "1,2,3", "1"],
+ result: "0,2,3,4,5,1",
+ },
+ {
+ tabs: ["1", "2 media", "3", "4", "5", "6"],
+ process: ["1", "2", "3", "1", "1,4,5", "1"],
+ result: "2,0,3,4,5,1",
+ },
+ {
+ tabs: ["1", "2 media", "3 media", "4", "5 media", "6"],
+ process: ["1", "2", "3", "1", "1,4,5", "1"],
+ result: "0,3,5,1,2,4",
+ },
+ {
+ tabs: ["1", "2 media", "3 media", "4", "5 media", "6"],
+ process: ["1", "1", "3", "1", "1,4,5", "1"],
+ result: "0,3,5,1,2,4",
+ },
+ {
+ tabs: ["1", "2 media", "3 media", "4", "5 media", "6"],
+ process: ["1", "2", "3", "4", "1,4,5", "5"],
+ result: "0,3,5,1,2,4",
+ },
+ {
+ tabs: ["1", "2 media", "3 media", "4", "5 media", "6"],
+ process: ["1", "1", "3", "4", "1,4,5", "5"],
+ result: "0,3,5,1,2,4",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6"],
+ process: ["1", "1", "1", "2", "1,3,4,5,6,7,8", "1"],
+ result: "0,1,2,3,4,5",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6", "7", "8"],
+ process: ["1", "1", "1", "2", "1,3,4,5,6,7,8", "1", "1", "1"],
+ result: "4,0,3,1,2,5,6,7",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5 selected", "6"],
+ process: ["1", "1", "1", "2", "1,3,4,5,6,7,8", "1"],
+ result: "0,1,2,3,5,4",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5 media", "6"],
+ process: ["1", "1", "1", "2", "1,3,4,5,6,7,8", "1"],
+ result: "0,1,2,3,5,4",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
+ process: ["1", "1", "1", "2", "1,3,4,5,6,7,8", "1", "1", "1"],
+ result: "0,3,1,2,5,6,7,4",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
+ process: ["1", "1,3,4,5,6,7,8", "1", "1", "1", "1", "1", "1"],
+ result: "1,0,2,3,5,6,7,4",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
+ process: ["1", "1", "1,3,4,5,6,7,8", "1", "1", "1", "1", "1"],
+ result: "2,0,1,3,5,6,7,4",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
+ process: ["1", "1", "1,1,1,1,1,1,1", "1", "1", "1", "1,1,1,1,1", "1"],
+ result: "0,1,2,3,5,6,7,4",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
+ process: ["1", "1", "1,2,3,4,5", "1", "1", "1", "1,2,3,4,5", "1"],
+ result: "0,1,2,3,5,6,7,4",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
+ process: ["1", "1", "1,6", "1", "1", "1", "1,2,3,4,5", "1"],
+ result: "0,2,1,3,5,6,7,4",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
+ process: ["1", "1", "1,6", "1,7", "1,8", "1,9", "1,2,3,4,5", "1"],
+ result: "2,3,0,5,1,6,7,4",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5 media", "6", "7", "8"],
+ process: ["1,10,11", "1", "1,2", "1,7", "1,8", "1,9", "1,2,3,4,5", "1"],
+ result: "0,3,1,5,2,6,7,4",
+ },
+ {
+ tabs: [
+ "1 media",
+ "2 media",
+ "3 media",
+ "4 media",
+ "5 media",
+ "6",
+ "7",
+ "8",
+ ],
+ process: ["1,10,11", "1", "1,2", "1,7", "1,8", "1,9", "1,2,3,4,5", "1"],
+ result: "6,5,7,0,1,2,3,4",
+ },
+ {
+ tabs: ["1", "2", "3"],
+ process: ["1", "2", "3"],
+ memory: ["100", "200", "300"],
+ result: "0,1,2",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
+ process: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
+ memory: [
+ "100",
+ "200",
+ "300",
+ "400",
+ "500",
+ "600",
+ "700",
+ "800",
+ "900",
+ "1000",
+ ],
+ result: "0,1,2,3,4,5,6,7,8,9",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
+ process: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
+ memory: [
+ "100",
+ "900",
+ "300",
+ "500",
+ "400",
+ "700",
+ "600",
+ "1000",
+ "200",
+ "200",
+ ],
+ result: "1,0,2,3,5,4,6,7,8,9",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
+ process: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
+ memory: [
+ "1000",
+ "900",
+ "300",
+ "500",
+ "400",
+ "1000",
+ "600",
+ "1000",
+ "200",
+ "200",
+ ],
+ result: "0,1,2,3,5,4,6,7,8,9",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6"],
+ process: ["1", "2,7", "3", "4", "5", "6"],
+ memory: ["100", "200", "300", "400", "500", "600", "700"],
+ result: "1,0,2,3,4,5",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6", "7", "8"],
+ process: ["1,6", "2,7", "3,8", "4,1,2", "5", "6", "7", "8"],
+ memory: ["100", "200", "300", "400", "500", "600", "700", "800"],
+ result: "2,3,0,1,4,5,6,7",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6", "7", "8"],
+ process: ["1", "1", "1", "2", "1", "1", "1", "1"],
+ memory: ["700", "1000"],
+ result: "0,3,1,2,4,5,6,7",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6", "7", "8"],
+ process: ["1", "1", "1", "1", "2,1", "2,1", "3", "3"],
+ memory: ["1000", "2000", "3000"],
+ result: "0,1,2,4,3,5,6,7",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6", "7", "8"],
+ process: ["2", "2", "2", "2", "2,1", "2,1", "3", "3"],
+ memory: ["1000", "600", "1000"],
+ result: "0,1,2,4,3,5,6,7",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6", "7", "8"],
+ process: ["1", "1", "1", "2", "2,1,1,1", "2,1", "3", "3"],
+ memory: ["1000", "1800", "1000"],
+ result: "0,1,3,2,4,5,6,7",
+ },
+ {
+ tabs: ["1", "2", "3", "4", "5", "6", "7", "8"],
+ process: ["1", "1", "1", "2", "2,1,1,1", "2,1", "3", "3"],
+ memory: ["4000", "1800", "1000"],
+ result: "0,1,2,4,3,5,6,7",
+ },
+ {
+ // The tab "1" contains 4 frames, but its uniqueCount is 1 because
+ // all of those frames are backed by the process "1". As a result,
+ // TabUnloader puts the tab "1" first based on the last access time.
+ tabs: ["1", "2", "3", "4", "5"],
+ process: ["1,1,1,1", "2", "3", "3", "3"],
+ memory: ["100", "100", "100"],
+ result: "0,1,2,3,4",
+ },
+ {
+ // The uniqueCount of the tab "1", "2", and "3" is 1, 2, and 3,
+ // respectively. As a result the first three tabs are sorted as 2,1,0.
+ tabs: ["1", "2", "3", "4", "5", "6"],
+ process: ["1,7,1,7,1,1,7,1", "7,3,7,2", "4,5,7,4,6,7", "7", "7", "7"],
+ memory: ["100", "100", "100", "100", "100", "100", "100"],
+ result: "2,1,0,3,4,5",
+ },
+];
+
+let globalBrowser = {
+ discardBrowser() {
+ return true;
+ },
+};
+
+add_task(async function doTests() {
+ for (let test of unloadTests) {
+ function* iterateTabs() {
+ let tabs = test.tabs;
+ for (let t = 0; t < tabs.length; t++) {
+ let tab = {
+ tab: {
+ originalIndex: t,
+ lastAccessed: Number(/^[0-9]+/.exec(tabs[t])[0]),
+ keywords: tabs[t],
+ process: "process" in test ? test.process[t] : "1",
+ },
+ memory: test.memory,
+ gBrowser: globalBrowser,
+ };
+ yield tab;
+ }
+ }
+ TestTabUnloaderMethods.iterateTabs = iterateTabs;
+
+ let expectedOrder = "";
+ const sortedTabs = await TabUnloader.getSortedTabs(
+ 0,
+ TestTabUnloaderMethods
+ );
+ for (let tab of sortedTabs) {
+ if (expectedOrder) {
+ expectedOrder += ",";
+ }
+ expectedOrder += tab.tab.originalIndex;
+ }
+
+ Assert.equal(expectedOrder, test.result);
+ }
+});