Bug 1253382 - Add a new tabpaint talos test. r?jmaher
tabpaint measures how long it takes to open a new tab and show its content.
MozReview-Commit-ID: IIVprFdvH1Z
--- a/testing/talos/talos.json
+++ b/testing/talos/talos.json
@@ -17,34 +17,34 @@
"dromaeojs": {
"tests": ["dromaeo_css", "kraken"]
},
"dromaeojs-e10s": {
"tests": ["dromaeo_css", "kraken"],
"talos_options": ["--e10s"]
},
"other": {
- "tests": ["a11yr", "ts_paint", "tpaint", "sessionrestore", "sessionrestore_no_auto_restore"]
+ "tests": ["a11yr", "ts_paint", "tpaint", "sessionrestore", "sessionrestore_no_auto_restore", "tabpaint"]
},
"other-e10s": {
- "tests": ["a11yr", "ts_paint", "tpaint", "sessionrestore", "sessionrestore_no_auto_restore"],
+ "tests": ["a11yr", "ts_paint", "tpaint", "sessionrestore", "sessionrestore_no_auto_restore", "tabpaint"],
"talos_options": ["--e10s"]
},
"other_nol64": {
- "tests": ["a11yr", "ts_paint", "tpaint", "sessionrestore", "sessionrestore_no_auto_restore"]
+ "tests": ["a11yr", "ts_paint", "tpaint", "sessionrestore", "sessionrestore_no_auto_restore", "tabpaint"]
},
"other-e10s_nol64": {
- "tests": ["a11yr", "ts_paint", "tpaint", "sessionrestore", "sessionrestore_no_auto_restore"],
+ "tests": ["a11yr", "ts_paint", "tpaint", "sessionrestore", "sessionrestore_no_auto_restore", "tabpaint"],
"talos_options": ["--e10s"]
},
"other_l64": {
- "tests": ["a11yr", "ts_paint", "tpaint", "sessionrestore", "sessionrestore_no_auto_restore"]
+ "tests": ["a11yr", "ts_paint", "tpaint", "sessionrestore", "sessionrestore_no_auto_restore", "tabpaint"]
},
"other-e10s_l64": {
- "tests": ["a11yr", "ts_paint", "tpaint", "sessionrestore", "sessionrestore_no_auto_restore"],
+ "tests": ["a11yr", "ts_paint", "tpaint", "sessionrestore", "sessionrestore_no_auto_restore", "tabpaint"],
"talos_options": ["--e10s"]
},
"g1": {
"tests": ["tp5o_scroll", "glterrain"],
"pagesets_url": "http://talos-bundles.pvt.build.mozilla.org/zips/tp5n.zip"
},
"g1-e10s": {
"tests": ["tp5o_scroll", "glterrain"],
--- a/testing/talos/talos/test.py
+++ b/testing/talos/talos/test.py
@@ -234,16 +234,39 @@ class PageloaderTest(Test):
'linux_counters', 'mac_counters', 'tpscrolltest', 'xperf_counters',
'timeout', 'shutdown', 'responsiveness', 'profile_path',
'xperf_providers', 'xperf_user_providers', 'xperf_stackwalk',
'filters', 'preferences', 'extensions', 'setup', 'cleanup',
'test_name_extension', 'lower_is_better', 'unit']
@register_test()
+class tabpaint(PageloaderTest):
+ """
+ Tests the amount of time it takes to open new tabs, triggered from
+ both the parent process and the content process.
+ """
+ extensions = '${talos}/tests/tabpaint/tabpaint-signed.xpi'
+ tpmanifest = '${talos}/tests/tabpaint/tabpaint.manifest'
+ tppagecycles = 20
+ sps_profile_entries = 1000000
+ tploadnocache = True
+ unit = 'ms'
+ preferences = {
+ # By default, Talos is configured to open links from
+ # content in new windows. We're overriding them so that
+ # they open in new tabs instead.
+ # See http://kb.mozillazine.org/Browser.link.open_newwindow
+ # and http://kb.mozillazine.org/Browser.link.open_newwindow.restriction
+ 'browser.link.open_newwindow': 3,
+ 'browser.link.open_newwindow.restriction': 2,
+ }
+
+
+@register_test()
class tps(PageloaderTest):
"""
Tests the amount of time it takes to switch between tabs
"""
extensions = '${talos}/tests/tabswitch/tabswitch-signed.xpi'
tpmanifest = '${talos}/tests/tabswitch/tps.manifest'
tppagecycles = 5
sps_profile_entries = 1000000
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/tabpaint/bootstrap.js
@@ -0,0 +1,259 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * This test will measure the performance of opening a tab and displaying
+ * the simplest content (a blank page). This test is concerned primarily
+ * with the time it takes to show the content area to the user, rather than
+ * the performance of the tab opening or closing animations (which are
+ * measured in the TART test). This is why this test disables tab animations.
+ *
+ * When opening tabs and showing content, there are two cases to consider:
+ *
+ * 1) The tab has been opened via a command from the parent process. For example,
+ * the user has clicked on a link in a separate application which is opening
+ * in this browser, so the message to open the tab and display the content
+ * comes from the operating system, to the parent.
+ *
+ * 2) The tab has been opened by clicking on a link in content. It is possible
+ * for certain types of links (_blank links for example) to open new tabs.
+ */
+
+var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
+Cu.import("resource:///modules/RecentWindow.jsm");
+
+const TAB_ANIMATION_PREF = "browser.tabs.animate";
+
+const TARGET_URI = "chrome://tabpaint/content/target.html";
+
+var TabPaint = {
+ MESSAGES: [
+ "TabPaint:Go",
+ "TabPaint:Painted",
+ ],
+
+ /**
+ * We'll hold the original tab animation preference here so
+ * we can restore it once the test is done.
+ */
+ originalTabsAnimate: null,
+
+ /**
+ * We'll store a callback here to be fired once the TARGET_URI
+ * reports that it has painted.
+ */
+ paintCallback: null,
+
+ /**
+ * Shortcut to getting at the TalosParentProfiler.
+ */
+ get Profiler() {
+ delete this.Profiler;
+ let context = {};
+ Services.scriptloader.loadSubScript("chrome://talos-powers-content/content/TalosParentProfiler.js", context);
+ return this.Profiler = context.TalosParentProfiler;
+ },
+
+ init() {
+ // We don't have a window in this scope, and in fact, there might
+ // not be any browser windows around. Since pageloader is loading
+ // this add-on, along with the tabpaint.html content, what we'll do
+ // is wait for the tabpaint.html content to send us a message to
+ // get us moving.
+ for (let msgName of this.MESSAGES) {
+ Services.mm.addMessageListener(msgName, this);
+ }
+
+ this.originalTabsAnimate = Services.prefs.getBoolPref(TAB_ANIMATION_PREF);
+ Services.prefs.setBoolPref(TAB_ANIMATION_PREF, false);
+ },
+
+ uninit() {
+ for (let msgName of this.MESSAGES) {
+ Services.mm.removeMessageListener(msgName, this);
+ }
+
+ Services.prefs.setBoolPref(TAB_ANIMATION_PREF, this.originalTabsAnimate);
+ },
+
+ receiveMessage(msg) {
+ let browser = msg.target;
+
+ let gBrowser = browser.ownerGlobal.gBrowser;
+
+ switch(msg.name) {
+ case "TabPaint:Go": {
+ // Our document has loaded, and we're off to the races!
+ this.go(gBrowser).then((results) => {
+ this.reportResults(results);
+ });
+
+ break;
+ }
+
+ case "TabPaint:Painted": {
+ // Content has reported that it has painted.
+ if (!this.paintCallback) {
+ throw new Error("TabPaint:Painted fired without a paintCallback set");
+ }
+
+ let tab = gBrowser.getTabForBrowser(browser);
+ let delta = msg.data.delta;
+ this.paintCallback({tab, delta});
+ break;
+ }
+ }
+ },
+
+ /**
+ * Start a single run of the test. This will measure the time
+ * to open a new tab from the parent, and then measure the time
+ * to open a new tab from content.
+ *
+ * @param gBrowser (<xul:tabbrowser>)
+ * The tabbrowser of the window to use.
+ *
+ * @return Promise
+ * Resolves with an object with two properties:
+ *
+ * fromParent (int):
+ * The time (ms) it took to present a tab that
+ * was opened from the parent.
+ *
+ * fromContent (int):
+ * The time (ms) it took to present a tab that
+ * was opened from content.
+ */
+ go: Task.async(function*(gBrowser) {
+ let fromParent = yield this.openTabFromParent(gBrowser);
+ let fromContent = yield this.openTabFromContent(gBrowser);
+
+ return { fromParent, fromContent };
+ }),
+
+ /**
+ * Opens a tab from the parent, waits until it is displayed, then
+ * removes the tab.
+ *
+ * @param gBrowser (<xul:tabbrowser>)
+ * The tabbrowser of the window to use.
+ *
+ * @return Promise
+ * Resolves once the tab has been fully removed. Resolves
+ * with the time (in ms) it took to open the tab from the parent.
+ */
+ openTabFromParent(gBrowser) {
+ let win = gBrowser.ownerGlobal;
+ return new Promise((resolve) => {
+ this.Profiler.resume("tabpaint parent start");
+
+ gBrowser.selectedTab = gBrowser.addTab(TARGET_URI + "?" + Date.now());
+
+ this.whenTabShown().then(({tab, delta}) => {
+ this.Profiler.pause("tabpaint parent end");
+ this.removeTab(tab).then(() => {
+ resolve(delta);
+ });
+ });
+ });
+ },
+
+ /**
+ * Opens a tab from content, waits until it is displayed, then
+ * removes the tab.
+ *
+ * @param gBrowser (<xul:tabbrowser>)
+ * The tabbrowser of the window to use.
+ *
+ * @return Promise
+ * Resolves once the tab has been fully removed. Resolves
+ * with the time (in ms) it took to open the tab from content.
+ */
+ openTabFromContent(gBrowser) {
+ let win = gBrowser.ownerGlobal;
+ return new Promise((resolve) => {
+ this.Profiler.resume("tabpaint content start");
+
+ Services.mm.broadcastAsyncMessage("TabPaint:OpenFromContent");
+
+ this.whenTabShown().then(({tab, delta}) => {
+ this.Profiler.pause("tabpaint content end");
+ this.removeTab(tab).then(() => {
+ resolve(delta);
+ });
+ });
+ });
+ },
+
+ /**
+ * Returns a Promise that will resolve once the next tab reports
+ * it has shown.
+ *
+ * @return Promise
+ */
+ whenTabShown() {
+ return new Promise((resolve) => {
+ this.paintCallback = resolve;
+ });
+ },
+
+ /**
+ * Returns a Promise that removes a tab, and resolves once the final
+ * message from that tab has come up.
+ *
+ * @param tab (<xul:tab>)
+ * The tab to remove.
+ *
+ * @return Promise
+ */
+ removeTab(tab) {
+ return new Promise((resolve) => {
+ let {messageManager: mm, frameLoader} = tab.linkedBrowser;
+ mm.addMessageListener("SessionStore:update", function onMessage(msg) {
+ if (msg.targetFrameLoader == frameLoader && msg.data.isFinal) {
+ mm.removeMessageListener("SessionStore:update", onMessage);
+ resolve();
+ }
+ }, true);
+
+ tab.ownerDocument.defaultView.gBrowser.removeTab(tab);
+ });
+ },
+
+ /**
+ * Sends the results down to the tabpaint-test.html page, which will
+ * pipe them out to the console.
+ *
+ * @param results (Object)
+ * An object with the following properties:
+ *
+ * fromParent (int):
+ * The time (ms) it took to present a tab that
+ * was opened from the parent.
+ *
+ * fromContent (int):
+ * The time (ms) it took to present a tab that
+ * was opened from content.
+ */
+ reportResults(results) {
+ Services.mm.broadcastAsyncMessage("TabPaint:FinalResults", results);
+ },
+};
+
+// Bootstrap functions below
+
+function install(aData, aReason) {}
+
+function startup(aData, aReason) {
+ TabPaint.init();
+}
+
+function shutdown(aData, aReason) {
+ TabPaint.uninit();
+}
+
+function uninstall(aData, aReason) {}
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/tabpaint/chrome.manifest
@@ -0,0 +1,1 @@
+content tabpaint content/ remoteenabled=yes contentaccessible=yes
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/tabpaint/content/tabpaint.html
@@ -0,0 +1,40 @@
+<html>
+ <head>
+ <script>
+ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+ function init() {
+ if (document.location.hash.indexOf("#auto") == 0) {
+ let mm = window.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIContentFrameMessageManager);
+
+ mm.addMessageListener("TabPaint:FinalResults", function onResults(msg) {
+ mm.removeMessageListener("TabPaint:FinalResults", onResults);
+
+ let { fromParent, fromContent } = msg.data;
+
+ tpRecordTime([fromParent, fromContent].join(','), 0, "tabpaint-from-parent, tabpaint-from-content");
+ });
+
+ mm.addMessageListener("TabPaint:OpenFromContent", function openFromContent() {
+ let target = document.getElementById("target");
+ let now = Date.now();
+ let href = "target.html?" + now;
+ target.href = href;
+ target.click();
+ });
+
+ mm.sendAsyncMessage("TabPaint:Go");
+ }
+ }
+
+ </script>
+ </head>
+ <body onload="init();">
+ Hello, Talos!
+
+ <a href="#" id="target" target="_blank">I'll open a new tab</a>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/tabpaint/install.rdf
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+ <Description about="urn:mozilla:install-manifest">
+ <em:id>tabpaint-test@mozilla.org</em:id>
+ <em:type>2</em:type>
+ <em:name>tabpaint test</em:name>
+ <em:version>1.0.0</em:version>
+ <em:bootstrap>true</em:bootstrap>
+ <em:description>Measures the performance of opening tabs</em:description>
+ <em:creator>Mike Conley</em:creator>
+ <em:multiprocessCompatible>true</em:multiprocessCompatible>
+
+ <!-- Desktop -->
+ <em:targetApplication>
+ <Description>
+ <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+ <em:minVersion>38.0</em:minVersion>
+ <em:maxVersion>*</em:maxVersion>
+ </Description>
+ </em:targetApplication>
+ </Description>
+ <em:description>https://wiki.mozilla.org/Buildbot/Talos/Tests</em:description>
+ <em:homepageURL>https://wiki.mozilla.org/Buildbot/Talos/Tests</em:homepageURL>
+</RDF>
new file mode 100644
index 0000000000000000000000000000000000000000..4956d03b09855cb8b48874c73cca51616487321e
GIT binary patch
literal 21764
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
bm;bHfqAUji3HX=s;sKPt_e`$*k6-@}^^R9B
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/tabpaint/tabpaint.manifest
@@ -0,0 +1,1 @@
+% chrome://tabpaint/content/tabpaint.html#auto
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/tabpaint/tabpaint.manifest.develop
@@ -0,0 +1,1 @@
+% chrome://tabpaint/content/tabpaint.html#auto