Bug 1342464 - Add regression tests for the FX_TAB_SWITCH_SPINNER_TYPE probe. r?Mossop draft
authorMike Conley <mconley@mozilla.com>
Mon, 06 Mar 2017 14:10:58 -0500
changeset 495478 9bca018b7cc6192ed1e107863b32e6ff3e5894fd
parent 495477 0a095cccd2b35d336f3d33119d7db2ed238e1117
child 548388 a268bbf523e68d6e6fa1bd5c0fb4e0cd802f064b
push id48345
push usermconley@mozilla.com
push dateWed, 08 Mar 2017 21:41:20 +0000
reviewersMossop
bugs1342464
milestone55.0a1
Bug 1342464 - Add regression tests for the FX_TAB_SWITCH_SPINNER_TYPE probe. r?Mossop MozReview-Commit-ID: 7w6rT8uT4I3
browser/base/content/test/tabs/browser.ini
browser/base/content/test/tabs/browser_tabSpinnerTypeProbe.js
--- a/browser/base/content/test/tabs/browser.ini
+++ b/browser/base/content/test/tabs/browser.ini
@@ -1,13 +1,15 @@
 [DEFAULT]
 support-files =
   dummy_page.html
 
 [browser_abandonment_telemetry.js]
 [browser_allow_process_switches_despite_related_browser.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_opened_file_tab_navigated_to_web.js]
 [browser_reload_deleted_file.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabs/browser_tabSpinnerTypeProbe.js
@@ -0,0 +1,188 @@
+"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(function* setup() {
+  yield 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, function*(aMs) {
+    let then = Date.now();
+    while (Date.now() - then < aMs) {
+      // 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(function* test_seen_spinner_type_probe() {
+  let originalTab = gBrowser.selectedTab;
+
+  yield BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: "http://example.com",
+  }, 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;
+    yield BrowserTestUtils.switchTab(gBrowser, originalTab);
+    gHistogram.clear();
+
+    let tabHangPromise = hangContentProcess(browser, 1000);
+    let hangTabSwitch = BrowserTestUtils.switchTab(gBrowser, testTab);
+    yield tabHangPromise;
+    yield 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(function* test_unseenOld_spinner_type_probe() {
+  yield BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: "http://example.com",
+  }, function*(browser) {
+    const NEWNESS_THRESHOLD = gBrowser._getSwitcher().NEWNESS_THRESHOLD;
+    let originalTab = gBrowser.getTabForBrowser(browser);
+    // First, create a new background tab, ensuring that it's in the same process
+    // as the current one.
+    let bgTab = gBrowser.addTab("about:blank", {
+      sameProcessAsFrameLoader: browser.frameLoader,
+      inBackground: true,
+    });
+
+    yield 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);
+    yield tabHangPromise;
+    yield hangTabSwitch;
+
+    // Okay, we should have gotten an entry in our Histogram for that one.
+    let snapshot = gHistogram.snapshot();
+    assertOnlyOneTypeSet(snapshot, "unseenOld");
+
+    yield 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(function* test_unseenNew_spinner_type_probe() {
+  yield BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: "http://example.com",
+  }, function*(browser) {
+    let originalTab = gBrowser.getTabForBrowser(browser);
+    // First, create a new background tab, ensuring that it's in the same process
+    // as the current one.
+    let bgTab = gBrowser.addTab("about:blank", {
+      sameProcessAsFrameLoader: browser.frameLoader,
+      inBackground: true,
+    });
+
+    yield 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);
+    yield tabHangPromise;
+    yield hangTabSwitch;
+
+    // Okay, we should have gotten an entry in our Histogram for that one.
+    let snapshot = gHistogram.snapshot();
+    assertOnlyOneTypeSet(snapshot, "unseenNew");
+
+    yield BrowserTestUtils.removeTab(bgTab);
+  });
+});