Bug 1362866 - Fix browser_tabSpinnerProbe.js now that tabs must be presented to spin. Also remove browser_tabSpinnerTypeProbe.js. r?billm draft
authorMike Conley <mconley@mozilla.com>
Mon, 08 May 2017 21:46:06 -0400
changeset 583127 fae8537ea3ff06755ddf5edab2a5c17406a442bf
parent 583126 80ee5b1e6392224192eb0837d8e860310e8c3594
child 583128 ef57af6910d61a2913430bbc6fc37041ad1e6360
push id60287
push usermconley@mozilla.com
push dateTue, 23 May 2017 17:22:48 +0000
reviewersbillm
bugs1362866
milestone55.0a1
Bug 1362866 - Fix browser_tabSpinnerProbe.js now that tabs must be presented to spin. Also remove browser_tabSpinnerTypeProbe.js. r?billm browser_tabSpinnerTypeProbe.js isn't necessary anymore since it should not possible to show spinners for tabs that have never been presented. MozReview-Commit-ID: AD4ppdhe346
browser/base/content/test/tabs/browser.ini
browser/base/content/test/tabs/browser_tabSpinnerProbe.js
browser/base/content/test/tabs/browser_tabSpinnerTypeProbe.js
--- a/browser/base/content/test/tabs/browser.ini
+++ b/browser/base/content/test/tabs/browser.ini
@@ -4,18 +4,16 @@ support-files =
   test_bug1358314.html
 
 [browser_abandonment_telemetry.js]
 [browser_allow_process_switches_despite_related_browser.js]
 [browser_contextmenu_openlink_after_tabnavigated.js]
 [browser_tabCloseProbes.js]
 [browser_tabSpinnerProbe.js]
 skip-if = !e10s # Tab spinner is e10s only.
-[browser_tabSpinnerTypeProbe.js]
-skip-if = !e10s # Tab spinner is e10s only.
 [browser_tabSwitchPrintPreview.js]
 skip-if = os == 'mac'
 [browser_navigatePinnedTab.js]
 [browser_new_web_tab_in_file_process_pref.js]
 skip-if = !e10s # Pref and test only relevant for e10s.
 [browser_opened_file_tab_navigated_to_web.js]
 [browser_reload_deleted_file.js]
 [browser_tabswitch_updatecommands.js]
--- a/browser/base/content/test/tabs/browser_tabSpinnerProbe.js
+++ b/browser/base/content/test/tabs/browser_tabSpinnerProbe.js
@@ -1,89 +1,88 @@
 "use strict";
 
 /**
  * Tests the FX_TAB_SWITCH_SPINNER_VISIBLE_MS and
  * FX_TAB_SWITCH_SPINNER_VISIBLE_LONG_MS telemetry probes
  */
-let gMinHangTime = 500; // ms
-let gMaxHangTime = 5 * 1000; // ms
-
-/**
- * Make a data URI for a generic webpage with a script that hangs for a given
- * amount of time.
- * @param  {?Number} aHangMs Number of milliseconds that the hang should last.
- *                   Defaults to 0.
- * @return {String}  The data URI generated.
- */
-function makeDataURI(aHangMs = 0) {
-  return `data:text/html,
-    <html>
-      <head>
-        <meta charset="utf-8"/>
-        <title>Tab Spinner Test</title>
-        <script>
-          function hang() {
-            let hangDuration = ${aHangMs};
-            if (hangDuration > 0) {
-              let startTime = window.performance.now();
-              while(window.performance.now() - startTime < hangDuration) {}
-            }
-          }
-        </script>
-      </head>
-      <body>
-        <h1 id='header'>Tab Spinner Test</h1>
-      </body>
-    </html>`;
-}
+const MIN_HANG_TIME = 500; // ms
+const MAX_HANG_TIME = 5 * 1000; // ms
 
 /**
  * Returns the sum of all values in an array.
  * @param  {Array}  aArray An array of integers
  * @return {Number} The sum of the integers in the array
  */
 function sum(aArray) {
   return aArray.reduce(function(previousValue, currentValue) {
     return previousValue + currentValue;
   });
 }
 
 /**
+ * Causes the content process for a remote <xul:browser> to run
+ * some busy JS for aMs milliseconds.
+ *
+ * @param {<xul:browser>} browser
+ *        The browser that's running in the content process that we're
+ *        going to hang.
+ * @param {int} aMs
+ *        The amount of time, in milliseconds, to hang the content process.
+ *
+ * @return {Promise}
+ *        Resolves once the hang is done.
+ */
+function hangContentProcess(browser, aMs) {
+  return ContentTask.spawn(browser, aMs, function*(ms) {
+    let then = Date.now();
+    while (Date.now() - then < ms) {
+      // Let's burn some CPU...
+    }
+  });
+}
+
+/**
  * A generator intended to be run as a Task. It tests one of the tab spinner
  * telemetry probes.
  * @param {String} aProbe The probe to test. Should be one of:
  *                  - FX_TAB_SWITCH_SPINNER_VISIBLE_MS
  *                  - FX_TAB_SWITCH_SPINNER_VISIBLE_LONG_MS
  */
 async function testProbe(aProbe) {
   info(`Testing probe: ${aProbe}`);
   let histogram = Services.telemetry.getHistogramById(aProbe);
   let buckets = histogram.snapshot().ranges.filter(function(value) {
-    return (value > gMinHangTime && value < gMaxHangTime);
+    return (value > MIN_HANG_TIME && value < MAX_HANG_TIME);
   });
   let delayTime = buckets[0]; // Pick a bucket arbitrarily
 
   // The tab spinner does not show up instantly. We need to hang for a little
   // bit of extra time to account for the tab spinner delay.
   delayTime += gBrowser.selectedTab.linkedBrowser.getTabBrowser()._getSwitcher().TAB_SWITCH_TIMEOUT;
-  let dataURI1 = makeDataURI(delayTime);
-  let dataURI2 = makeDataURI();
 
-  let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, dataURI1);
+  // In order for a spinner to be shown, the tab must have presented before.
+  let origTab = gBrowser.selectedTab;
+  let hangTab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
+  let hangBrowser = hangTab.linkedBrowser;
+  ok(hangBrowser.isRemoteBrowser, "New tab should be remote.");
+  ok(hangBrowser.frameLoader.tabParent.hasPresented, "New tab has presented.");
+
+  // Now switch back to the original tab and set up our hang.
+  await BrowserTestUtils.switchTab(gBrowser, origTab);
+
+  let tabHangPromise = hangContentProcess(hangBrowser, delayTime);
   histogram.clear();
-  // Queue a hang in the content process when the
-  // event loop breathes next.
-  ContentTask.spawn(tab1.linkedBrowser, null, async function() {
-    content.wrappedJSObject.hang();
-  });
-  let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, dataURI2);
+  let hangTabSwitch = BrowserTestUtils.switchTab(gBrowser, hangTab);
+  await tabHangPromise;
+  await hangTabSwitch;
+
+  // Now we should have a hang in our histogram.
   let snapshot = histogram.snapshot();
-  await BrowserTestUtils.removeTab(tab2);
-  await BrowserTestUtils.removeTab(tab1);
+  await BrowserTestUtils.removeTab(hangTab);
   ok(sum(snapshot.counts) > 0,
    `Spinner probe should now have a value in some bucket`);
 }
 
 add_task(async function setup() {
   await SpecialPowers.pushPrefEnv({
     set: [
       ["dom.ipc.processCount", 1],
deleted file mode 100644
--- a/browser/base/content/test/tabs/browser_tabSpinnerTypeProbe.js
+++ /dev/null
@@ -1,187 +0,0 @@
-"use strict";
-
-// Keep this in sync with the order in Histograms.json for
-// FX_TAB_SWITCH_SPINNER_TYPE
-const CATEGORIES = [
-  "seen",
-  "unseenOld",
-  "unseenNew",
-];
-
-add_task(async function setup() {
-  await SpecialPowers.pushPrefEnv({
-    set: [
-      // We can interrupt JS to paint now, which is great for
-      // users, but bad for testing spinners. We temporarily
-      // disable that feature for this test so that we can
-      // easily get ourselves into a predictable tab spinner
-      // state.
-      ["browser.tabs.remote.force-paint", false],
-    ]
-  });
-});
-
-/**
- * Causes the content process for a remote <xul:browser> to run
- * some busy JS for aMs milliseconds.
- *
- * @param {<xul:browser>} browser
- *        The browser that's running in the content process that we're
- *        going to hang.
- * @param {int} aMs
- *        The amount of time, in milliseconds, to hang the content process.
- *
- * @return {Promise}
- *        Resolves once the hang is done.
- */
-function hangContentProcess(browser, aMs) {
-  return ContentTask.spawn(browser, aMs, async function(ms) {
-    let then = Date.now();
-    while (Date.now() - then < ms) {
-      // Let's burn some CPU...
-    }
-  });
-}
-
-/**
- * Takes a Telemetry histogram snapshot and makes sure
- * that the index for that value (as defined by CATEGORIES)
- * has a count of 1, and that it's the only value that
- * has been incremented.
- *
- * @param snapshot (Object)
- *        The Telemetry histogram snapshot to examine.
- * @param category (String)
- *        The category in CATEGORIES whose index we expect to have
- *        been set to 1.
- */
-function assertOnlyOneTypeSet(snapshot, category) {
-  let categoryIndex = CATEGORIES.indexOf(category);
-  Assert.equal(snapshot.counts[categoryIndex], 1,
-               `Should have seen the ${category} count increment.`);
-  // Use Array.prototype.reduce to sum up all of the
-  // snapshot.count entries
-  Assert.equal(snapshot.counts.reduce((a, b) => a + b), 1,
-               "Should only be 1 collected value.");
-}
-
-Assert.ok(gMultiProcessBrowser,
-  "These tests only makes sense in an e10s-enabled window.");
-
-let gHistogram = Services.telemetry
-                         .getHistogramById("FX_TAB_SWITCH_SPINNER_TYPE");
-
-/**
- * This test tests that the "seen" category for the FX_TAB_SWITCH_SPINNER_TYPE
- * probe works. This means that we show a spinner for a tab that we've
- * presented before.
- */
-add_task(async function test_seen_spinner_type_probe() {
-  let originalTab = gBrowser.selectedTab;
-
-  await BrowserTestUtils.withNewTab({
-    gBrowser,
-    url: "http://example.com",
-  }, async function(browser) {
-    // We'll switch away from the current tab, then hang it, and then switch
-    // back to it. This should add to the "seen" type for the histogram.
-    let testTab = gBrowser.selectedTab;
-    await BrowserTestUtils.switchTab(gBrowser, originalTab);
-    gHistogram.clear();
-
-    let tabHangPromise = hangContentProcess(browser, 1000);
-    let hangTabSwitch = BrowserTestUtils.switchTab(gBrowser, testTab);
-    await tabHangPromise;
-    await hangTabSwitch;
-
-    // Okay, we should have gotten an entry in our Histogram for that one.
-    let snapshot = gHistogram.snapshot();
-    assertOnlyOneTypeSet(snapshot, "seen");
-    gHistogram.clear();
-  });
-});
-
-/**
- * This test tests that the "unseenOld" category for the FX_TAB_SWITCH_SPINNER_TYPE
- * probe works. This means that we show a spinner for a tab that we've never
- * seen before, and enough time has passed since its creation that we consider
- * it "old" (See the NEWNESS_THRESHOLD constant in the async tabswitcher for
- * the exact definition).
- */
-add_task(async function test_unseenOld_spinner_type_probe() {
-  await BrowserTestUtils.withNewTab({
-    gBrowser,
-    url: "http://example.com",
-  }, async function(browser) {
-    const NEWNESS_THRESHOLD = gBrowser._getSwitcher().NEWNESS_THRESHOLD;
-
-    // First, create a new background tab, ensuring that it's in the same process
-    // as the current one.
-    let bgTab = BrowserTestUtils.addTab(gBrowser, "about:blank", {
-      sameProcessAsFrameLoader: browser.frameLoader,
-      inBackground: true,
-    });
-
-    await BrowserTestUtils.browserLoaded(bgTab.linkedBrowser);
-
-    // Now, let's fudge with the creationTime of the background tab so that
-    // it seems old. We'll also add a fudge-factor to the NEWNESS_THRESHOLD of 100ms
-    // to try to avoid any potential timing issues.
-    bgTab._creationTime = bgTab._creationTime - NEWNESS_THRESHOLD - 100;
-
-    // Okay, tab should seem sufficiently old now so that a spinner in it should
-    // qualify for "unseenOld". Let's hang it and switch to it.
-    gHistogram.clear();
-    let tabHangPromise = hangContentProcess(browser, 1000);
-    let hangTabSwitch = BrowserTestUtils.switchTab(gBrowser, bgTab);
-    await tabHangPromise;
-    await hangTabSwitch;
-
-    // Okay, we should have gotten an entry in our Histogram for that one.
-    let snapshot = gHistogram.snapshot();
-    assertOnlyOneTypeSet(snapshot, "unseenOld");
-
-    await BrowserTestUtils.removeTab(bgTab);
-  });
-});
-
-/**
- * This test tests that the "unseenNew" category for the FX_TAB_SWITCH_SPINNER_TYPE
- * probe works. This means that we show a spinner for a tab that we've never
- * seen before, and not enough time has passed since its creation that we consider
- * it "old" (See the NEWNESS_THRESHOLD constant in the async tabswitcher for
- * the exact definition).
- */
-add_task(async function test_unseenNew_spinner_type_probe() {
-  await BrowserTestUtils.withNewTab({
-    gBrowser,
-    url: "http://example.com",
-  }, async function(browser) {
-    // First, create a new background tab, ensuring that it's in the same process
-    // as the current one.
-    let bgTab = BrowserTestUtils.addTab(gBrowser, "about:blank", {
-      sameProcessAsFrameLoader: browser.frameLoader,
-      inBackground: true,
-    });
-
-    await BrowserTestUtils.browserLoaded(bgTab.linkedBrowser);
-
-    // Now, let's fudge with the creationTime of the background tab so that
-    // it seems very new (created 1 minute into the future).
-    bgTab._creationTime = Date.now() + (60 * 1000);
-
-    // Okay, tab should seem sufficiently new now so that a spinner in it should
-    // qualify for "unseenNew". Let's hang it and switch to it.
-    gHistogram.clear();
-    let tabHangPromise = hangContentProcess(browser, 1000);
-    let hangTabSwitch = BrowserTestUtils.switchTab(gBrowser, bgTab);
-    await tabHangPromise;
-    await hangTabSwitch;
-
-    // Okay, we should have gotten an entry in our Histogram for that one.
-    let snapshot = gHistogram.snapshot();
-    assertOnlyOneTypeSet(snapshot, "unseenNew");
-
-    await BrowserTestUtils.removeTab(bgTab);
-  });
-});