Bug 1498195 - adapt the browser_aboutperformance.js test to cover the new about:performance, r=felipe.
authorFlorian Quèze <florian@queze.net>
Wed, 09 Jan 2019 12:43:42 +0100
changeset 510144 99fad7aa0cb7756e0960f3c456d27a1cdfc99c5c
parent 510143 99db2eabbf072cc9915d0b4956d20b1ec2f2eb28
child 510145 2c7c37b0ce9ca5f6745140b6551e9faa79e6c099
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfelipe
bugs1498195
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1498195 - adapt the browser_aboutperformance.js test to cover the new about:performance, r=felipe.
toolkit/components/aboutperformance/content/aboutPerformance.js
toolkit/components/aboutperformance/tests/browser/browser.ini
toolkit/components/aboutperformance/tests/browser/browser_aboutperformance.js
toolkit/components/aboutperformance/tests/browser/browser_compartments.html
toolkit/components/aboutperformance/tests/browser/browser_compartments_frame.html
toolkit/components/aboutperformance/tests/browser/browser_compartments_script.js
toolkit/components/aboutperformance/tests/browser/head.js
--- a/toolkit/components/aboutperformance/content/aboutPerformance.js
+++ b/toolkit/components/aboutperformance/content/aboutPerformance.js
@@ -298,16 +298,19 @@ var State = {
                   title: found.tab.linkedBrowser.contentTitle};
         }
       } else if (id == 1) {
         name = BRAND_NAME;
         image = "chrome://branding/content/icon32.png";
         type = "browser";
       } else if (/^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$/.test(host)) {
         let addon = WebExtensionPolicy.getByHostname(host);
+        if (!addon) {
+          continue;
+        }
         name = `${addon.name} (${addon.id})`;
         image = "chrome://mozapps/skin/extensions/extensionGeneric-16.svg";
         type = gSystemAddonIds.has(addon.id) ? "system-addon" : "addon";
       } else if (id == 0 && !tab.isWorker) {
         name = {id: "ghost-windows"};
       }
 
       if (type != "tab" && type != "addon" &&
--- a/toolkit/components/aboutperformance/tests/browser/browser.ini
+++ b/toolkit/components/aboutperformance/tests/browser/browser.ini
@@ -1,9 +1,7 @@
 [DEFAULT]
-head = head.js
 support-files = 
   browser_compartments.html
   browser_compartments_frame.html
   browser_compartments_script.js
 
 [browser_aboutperformance.js]
-skip-if = true
--- a/toolkit/components/aboutperformance/tests/browser/browser_aboutperformance.js
+++ b/toolkit/components/aboutperformance/tests/browser/browser_aboutperformance.js
@@ -1,308 +1,64 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-/* eslint-env mozilla/frame-script */
-/* eslint-disable mozilla/no-arbitrary-setTimeout */
-
 "use strict";
 
-ChromeUtils.import("resource://testing-common/ContentTask.jsm", this);
-
 const URL = "http://example.com/browser/toolkit/components/aboutperformance/tests/browser/browser_compartments.html?test=" + Math.random();
 
-// This function is injected as source as a frameScript
-function frameScript() {
-  "use strict";
-
-  addMessageListener("aboutperformance-test:done", () => {
-    content.postMessage("stop", "*");
-    sendAsyncMessage("aboutperformance-test:done", null);
-  });
-  addMessageListener("aboutperformance-test:setTitle", ({data: title}) => {
-    content.document.title = title;
-    sendAsyncMessage("aboutperformance-test:setTitle", null);
-  });
+add_task(async function init() {
+  info("Setting up about:performance");
+  let tabAboutPerformance = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:performance");
 
-  addMessageListener("aboutperformance-test:closeTab", ({data: options}) => {
-    let observer = function(subject, topic, mode) {
-      dump(`aboutperformance-test:closeTab 1 ${options.url}\n`);
-      Services.obs.removeObserver(observer, "about:performance-update-complete");
+  await BrowserTestUtils.browserLoaded(tabAboutPerformance.linkedBrowser);
 
-      let exn;
-      let found = false;
-      try {
-        for (let eltContent of content.document.querySelectorAll("li.delta")) {
-          let eltName = eltContent.querySelector("li.name");
-          if (!eltName.textContent.includes(options.url)) {
-            continue;
-          }
+  info(`Setting up ${URL}`);
+  let tabContent = BrowserTestUtils.addTab(gBrowser, URL);
+  await BrowserTestUtils.browserLoaded(tabContent.linkedBrowser);
 
-          found = true;
-          let [eltCloseTab, eltReloadTab] = eltContent.querySelectorAll("button");
-          let button;
-          if (options.mode == "reload") {
-            button = eltReloadTab;
-          } else if (options.mode == "close") {
-            button = eltCloseTab;
-          } else {
-            throw new TypeError(options.mode);
-          }
-          dump(`aboutperformance-test:closeTab clicking on ${button.textContent}\n`);
-          button.click();
-          return;
-        }
-      } catch (ex) {
-        dump(`aboutperformance-test:closeTab: error ${ex}\n`);
-        exn = ex;
-      } finally {
-        if (exn) {
-          sendAsyncMessage("aboutperformance-test:closeTab", { error: {message: exn.message, lineNumber: exn.lineNumber, fileName: exn.fileName}, found});
-        } else {
-          sendAsyncMessage("aboutperformance-test:closeTab", { ok: true, found });
-        }
-      }
-    };
-    Services.obs.addObserver(observer, "about:performance-update-complete");
-    Services.obs.notifyObservers(null, "test-about:performance-test-driver", JSON.stringify(options));
+  let doc = tabAboutPerformance.linkedBrowser.contentDocument;
+  let tbody = doc.getElementById("dispatch-tbody");
+
+  // Wait until the table has first been populated.
+  await TestUtils.waitForCondition(() => tbody.childElementCount);
+
+  // And wait for another update using a mutation observer, to give our newly created test tab some time
+  // to burn some CPU.
+  await new Promise(resolve => {
+    let observer = new doc.ownerGlobal.MutationObserver(() => {
+      observer.disconnect();
+      resolve();
+    });
+    observer.observe(tbody, {childList: true});
   });
 
-  addMessageListener("aboutperformance-test:checkSanity", ({data: options}) => {
-    let exn = null;
-    try {
-      let reFullname = /Full name: (.+)/;
-      let reFps = /Impact on framerate: ((\d+) high-impacts, (\d+) medium-impact|(\d+)\/10)?/;
-      let reCPU = /CPU usage: (\d+)%/;
-      let reCpow = /Blocking process calls: (\d+)%( \((\d+) alerts\))?/;
-
-      let getContentOfSelector = function(eltContainer, selector, re) {
-        let elt = eltContainer.querySelector(selector);
-        if (!elt) {
-          throw new Error(`No item ${selector}`);
-        }
-
-        if (!re) {
-          return undefined;
-        }
-
-        let match = elt.textContent.match(re);
-        if (!match) {
-          throw new Error(`Item ${selector} doesn't match regexp ${re}: ${elt.textContent}`);
-        }
-        return match;
-      };
-
-      // Additional sanity check
-      let deltas = content.document.querySelectorAll(".delta");
-      if (!deltas.length) {
-        throw new Error("No deltas found to check!");
-      }
-
-      for (let eltContent of deltas) {
-        // Do we have an attribute "impact"? Is it a number between 0 and 10?
-        let impact = eltContent.getAttribute("impact");
-        let value = Number.parseInt(impact);
-        if (isNaN(value) || value < 0 || value > 10) {
-          throw new Error(`Incorrect value ${value}`);
-        }
-
-        // Do we have a button "more"?
-        getContentOfSelector(eltContent, "a.more");
-
-        // Do we have details?
-        getContentOfSelector(eltContent, "ul.details");
-
-        // Do we have a full name? Does it make sense?
-        getContentOfSelector(eltContent, "li.name", reFullname);
-
-        let eltDetails = eltContent.querySelector("ul.details");
+  // Find the row for our test tab.
+  let row = tbody.firstChild;
+  while (row && row.firstChild.textContent != "Main frame for test browser_aboutperformance.js")
+    row = row.nextSibling;
+  Assert.ok(row, "found a table row for our test tab");
+  Assert.equal(row.windowId, tabContent.linkedBrowser.outerWindowID, "the correct window id is set");
 
-        // Do we have an impact on framerate? Does it make sense?
-        if (!eltDetails.querySelector("li.fps").textContent.includes("no impact")) {
-          let [, jankStr,, alertsStr] = getContentOfSelector(eltDetails, "li.fps", reFps);
-          let jank = Number.parseInt(jankStr);
-          if (jank < 0 || jank > 10 || isNaN(jank)) {
-            throw new Error(`Invalid jank ${jankStr}`);
-          }
-          if (alertsStr) {
-            let alerts = Number.parseInt(alertsStr);
-            if (alerts < 0 || isNaN(alerts)) {
-              throw new Error(`Invalid alerts ${alertsStr}`);
-            }
-          }
-        }
-
-        // Do we have a CPU usage? Does it make sense?
-        let [, cpuStr] = getContentOfSelector(eltDetails, "li.cpu", reCPU);
-        let cpu = Number.parseInt(cpuStr);
-        if (cpu < 0 || isNaN(cpu)) { // Note that cpu can be > 100%.
-          throw new Error(`Invalid CPU ${cpuStr}`);
-        }
+  // Ensure it is reported as a medium or high energy impact.
+  let l10nId = row.children[2].getAttribute("data-l10n-id");
+  Assert.ok(["energy-impact-medium", "energy-impact-high"].includes(l10nId),
+            "our test tab is medium or high energy impact");
 
-        // Do we have CPOW? Does it make sense?
-        let [, cpowStr,, alertsStr2] = getContentOfSelector(eltDetails, "li.cpow", reCpow);
-        let cpow = Number.parseInt(cpowStr);
-        if (cpow < 0 || isNaN(cpow)) {
-          throw new Error(`Invalid cpow ${cpowStr}`);
-        }
-        if (alertsStr2) {
-          let alerts = Number.parseInt(alertsStr2);
-          if (alerts < 0 || isNaN(alerts)) {
-            throw new Error(`Invalid alerts ${alertsStr2}`);
-          }
-        }
-      }
-    } catch (ex) {
-      dump(`aboutperformance-test:checkSanity: error ${ex}\n`);
-      exn = ex;
-    }
-    if (exn) {
-      sendAsyncMessage("aboutperformance-test:checkSanity", { error: {message: exn.message, lineNumber: exn.lineNumber, fileName: exn.fileName}});
-    } else {
-      sendAsyncMessage("aboutperformance-test:checkSanity", { ok: true });
-    }
-  });
-
-  addMessageListener("aboutperformance-test:hasItems", ({data: {title, options}}) => {
-    let observer = function(subject, topic, mode) {
-      Services.obs.removeObserver(observer, "about:performance-update-complete");
-      let hasTitleInWebpages = false;
-
-      try {
-        let eltWeb = content.document.getElementById("webpages");
-        if (!eltWeb) {
-          dump(`aboutperformance-test:hasItems: the page is not ready yet webpages:${eltWeb}\n`);
-          return;
-        }
-
-        let webTitles = Array.from(eltWeb.querySelectorAll("span.title"), elt => elt.textContent);
+  // Verify selecting a row works.
+  await BrowserTestUtils.synthesizeMouseAtCenter(row, {}, tabAboutPerformance.linkedBrowser);
+  Assert.equal(row.getAttribute("selected"), "true", "doing a single click selects the row");
 
-        hasTitleInWebpages = webTitles.includes(title);
-      } catch (ex) {
-        Cu.reportError("Error in content: " + ex);
-        Cu.reportError(ex.stack);
-      } finally {
-        sendAsyncMessage("aboutperformance-test:hasItems", {hasTitleInWebpages, mode});
-      }
-    };
-    Services.obs.addObserver(observer, "about:performance-update-complete");
-    Services.obs.notifyObservers(null, "test-about:performance-test-driver", JSON.stringify(options));
-  });
-}
-
-var gTabAboutPerformance = null;
-var gTabContent = null;
-
-add_task(async function init() {
-  info("Setting up about:performance");
-  gTabAboutPerformance = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:performance");
-  await ContentTask.spawn(gTabAboutPerformance.linkedBrowser, null, frameScript);
-
-  info(`Setting up ${URL}`);
-  gTabContent = BrowserTestUtils.addTab(gBrowser, URL);
-  await ContentTask.spawn(gTabContent.linkedBrowser, null, frameScript);
-});
-
-var promiseExpectContent = async function(options) {
-  let title = "Testing about:performance " + Math.random();
-  for (let i = 0; i < 30; ++i) {
-    await new Promise(resolve => setTimeout(resolve, 100));
-    await promiseContentResponse(gTabContent.linkedBrowser, "aboutperformance-test:setTitle", title);
-    let {hasTitleInWebpages, mode} = (await promiseContentResponse(gTabAboutPerformance.linkedBrowser, "aboutperformance-test:hasItems", {title, options}));
-
-    info(`aboutperformance-test:hasItems ${hasTitleInWebpages}, ${mode}, ${options.displayRecent}`);
-    if (!hasTitleInWebpages) {
-      info(`Title not found in webpages`);
-      continue;
-    }
-    if ((mode == "recent") != options.displayRecent) {
-      info(`Wrong mode`);
-      continue;
-    }
-
-    let { ok, error } = await promiseContentResponse(gTabAboutPerformance.linkedBrowser, "aboutperformance-test:checkSanity", {options});
-    if (ok) {
-      info("aboutperformance-test:checkSanity: success");
-    }
-    if (error) {
-      Assert.ok(false, `aboutperformance-test:checkSanity error: ${JSON.stringify(error)}`);
-    }
-    return true;
-  }
-  return false;
-};
-
-// Test that we can find the title of a webpage in about:performance
-add_task(async function test_find_title() {
-    for (let displayRecent of [true, false]) {
-      info(`Testing with autoRefresh, in ${displayRecent ? "recent" : "global"} mode`);
-      let found = await promiseExpectContent({autoRefresh: 100, displayRecent});
-      Assert.ok(found, `The page title appears when about:performance is set to auto-refresh`);
-    }
-});
+  // Verify selecting a tab with a double click.
+  Assert.equal(gBrowser.selectedTab, tabAboutPerformance, "the about:performance tab is selected");
+  await BrowserTestUtils.synthesizeMouseAtCenter(row, {clickCount: 2}, tabAboutPerformance.linkedBrowser);
+  Assert.equal(gBrowser.selectedTab, tabContent, "after a double click the test tab is selected");
 
-// Test that we can close/reload tabs using the corresponding buttons
-add_task(async function test_close_tab() {
-  let tabs = new Map();
-  let closeObserver = function({type, originalTarget: tab}) {
-    dump(`closeObserver: ${tab}, ${tab.constructor.name}, ${tab.tagName}, ${type}\n`);
-    let cb = tabs.get(tab);
-    if (cb) {
-      cb(type);
-    }
-  };
-  let promiseTabClosed = function(tab) {
-    return new Promise(resolve => tabs.set(tab, resolve));
-  };
-  window.gBrowser.tabContainer.addEventListener("TabClose", closeObserver);
-  let promiseTabReloaded = function(tab) {
-    return new Promise(resolve =>
-      tab.linkedBrowser.contentDocument.addEventListener("readystatechange", resolve)
-    );
-  };
-  for (let displayRecent of [true, false]) {
-    for (let mode of ["close", "reload"]) {
-      let URL = `about:about?display-recent=${displayRecent}&mode=${mode}&salt=${Math.random()}`;
-      info(`Setting up ${URL}`);
-      let tab = BrowserTestUtils.addTab(gBrowser, URL);
-      await ContentTask.spawn(tab.linkedBrowser, null, frameScript);
-      let promiseClosed = promiseTabClosed(tab);
-      let promiseReloaded = promiseTabReloaded(tab);
-
-      info(`Requesting close`);
-      do {
-        await new Promise(resolve => setTimeout(resolve, 100));
-        await promiseContentResponse(tab.linkedBrowser, "aboutperformance-test:setTitle", URL);
+  // Verify we can close a tab using the X button.
+  // Switch back to about:performance...
+  await BrowserTestUtils.switchTab(gBrowser, tabAboutPerformance);
+  // ... and click the X button at the end of the row.
+  let tabClosing = BrowserTestUtils.waitForTabClosing(tabContent);
+  await BrowserTestUtils.synthesizeMouseAtCenter(row.children[4], {}, tabAboutPerformance.linkedBrowser);
+  await tabClosing;
 
-        let {ok, found, error} = await promiseContentResponse(gTabAboutPerformance.linkedBrowser, "aboutperformance-test:closeTab", {url: URL, autoRefresh: true, mode, displayRecent});
-        Assert.ok(ok, `Message aboutperformance-test:closeTab was handled correctly ${JSON.stringify(error)}`);
-        info(`URL ${URL} ${found ? "found" : "hasn't been found yet"}`);
-        if (found) {
-          break;
-        }
-      } while (true);
-
-      if (mode == "close") {
-        info(`Waiting for close`);
-        await promiseClosed;
-      } else {
-        info(`Waiting for reload`);
-        await promiseReloaded;
-        BrowserTestUtils.removeTab(tab);
-      }
-    }
-  }
+  BrowserTestUtils.removeTab(tabAboutPerformance);
 });
-
-add_task(async function cleanup() {
-  // Cleanup
-  info("Cleaning up");
-  await promiseContentResponse(gTabAboutPerformance.linkedBrowser, "aboutperformance-test:done", null);
-
-  info("Closing tabs");
-  for (let tab of gBrowser.tabs) {
-    BrowserTestUtils.removeTab(tab);
-  }
-
-  info("Done");
-  gBrowser.selectedTab = null;
-});
--- a/toolkit/components/aboutperformance/tests/browser/browser_compartments.html
+++ b/toolkit/components/aboutperformance/tests/browser/browser_compartments.html
@@ -1,11 +1,12 @@
 <!DOCTYPE html>
 <html>
 <head>
+  <meta charset="UTF-8">
   <title>
     Main frame for test browser_aboutperformance.js
   </title>
 </head>
 <body>
 Main frame.
 
 <iframe src="browser_compartments_frame.html?frame=1">
--- a/toolkit/components/aboutperformance/tests/browser/browser_compartments_frame.html
+++ b/toolkit/components/aboutperformance/tests/browser/browser_compartments_frame.html
@@ -1,11 +1,12 @@
 <!DOCTYPE html>
 <html>
 <head>
+  <meta charset="UTF-8">
   <title>
     Subframe for test browser_compartments.html (do not change this title)
   </title>
   <script src="browser_compartments_script.js"></script>
 </head>
 <body>
 Subframe loaded.
 </body>
--- a/toolkit/components/aboutperformance/tests/browser/browser_compartments_script.js
+++ b/toolkit/components/aboutperformance/tests/browser/browser_compartments_script.js
@@ -1,28 +1,11 @@
-
-var carryOn = true;
-
-window.addEventListener("message", e => {
-  console.log("frame content", "message", e);
-  if ("title" in e.data) {
-    document.title = e.data.title;
-  }
-  if ("stop" in e.data) {
-    carryOn = false;
-  }
-});
 
 // Use some CPU.
 var interval = window.setInterval(() => {
-  if (!carryOn) {
-    window.clearInterval(interval);
-    return;
-  }
-
   // Compute an arbitrary value, print it out to make sure that the JS
   // engine doesn't discard all our computation.
   var date = Date.now();
   var array = [];
   var i = 0;
   while (Date.now() - date <= 100) {
     array[i % 2] = i++;
   }
deleted file mode 100644
--- a/toolkit/components/aboutperformance/tests/browser/head.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-ChromeUtils.import("resource://gre/modules/Services.jsm", this);
-
-function promiseContentResponse(browser, name, message) {
-  let mm = browser.messageManager;
-  let promise = new Promise(resolve => {
-    function removeListener() {
-      mm.removeMessageListener(name, listener);
-    }
-
-    function listener(msg) {
-      removeListener();
-      resolve(msg.data);
-    }
-
-    mm.addMessageListener(name, listener);
-    registerCleanupFunction(removeListener);
-  });
-  mm.sendAsyncMessage(name, message);
-  return promise;
-}
-function promiseContentResponseOrNull(browser, name, message) {
-  if (!browser.messageManager) {
-    return null;
-  }
-  return promiseContentResponse(browser, name, message);
-}
-
-/**
- * `true` if we are running an OS in which the OS performance
- * clock has a low precision and might unpredictably
- * never be updated during the execution of the test.
- */
-function hasLowPrecision() {
-  let [sysName, sysVersion] = [Services.sysinfo.getPropertyAsAString("name"), Services.sysinfo.getPropertyAsDouble("version")];
-  info(`Running ${sysName} version ${sysVersion}`);
-
-  if (sysName == "Windows_NT" && sysVersion < 6) {
-    info("Running old Windows, need to deactivate tests due to bad precision.");
-    return true;
-  }
-  if (sysName == "Linux" && sysVersion <= 2.6) {
-    info("Running old Linux, need to deactivate tests due to bad precision.");
-    return true;
-  }
-  info("This platform has good precision.");
-  return false;
-}