# 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/. import os from talos import filter """ test definitions for Talos """ _TESTS = {} # internal dict of Talos test classes def register_test(): """Decorator to register Talos test classes""" def wrapper(klass): assert issubclass(klass, Test) assert klass.name() not in _TESTS _TESTS[klass.name()] = klass return klass return wrapper def test_dict(): """Return the dict of the registered test classes""" return _TESTS class Test(object): """abstract base class for a Talos test case""" __test__ = False # not pytest cycles = None # number of cycles keys = [] desktop = True filters = filter.ignore_first.prepare(1) + filter.median.prepare() lower_is_better = True alert_threshold = 2.0 perfherder_framework = "talos" subtest_alerts = False suite_should_alert = True # Default number of entries for the gecko profiler which is 128MiB. # This value is calculated by dividing the 128MiB of memory by 8 because # the profiler uses 8 bytes per entry. gecko_profile_entries = int(128 * 1024 * 1024 / 8) @classmethod def name(cls): return cls.__name__ @classmethod def description(cls): if cls.__doc__ is None: return "No documentation available yet." else: doc = cls.__doc__ description_lines = [i.strip() for i in doc.strip().splitlines()] return "\n".join(description_lines) def __init__(self, **kw): self.update(**kw) def update(self, **kw): self.__dict__.update(kw) def items(self): """ returns a list of 2-tuples """ retval = [("name", self.name())] for key in self.keys: value = getattr(self, key, None) if value is not None: retval.append((key, value)) return retval def __str__(self): """string form appropriate for YAML output""" items = self.items() key, value = items.pop(0) lines = ["- %s: %s" % (key, value)] for key, value in items: lines.append(" %s: %s" % (key, value)) return "\n".join(lines) # ts-style startup tests (ts, twinopen, ts_cold, etc) # The overall test number is calculated by excluding the max opening time # and taking an average of the remaining numbers. class TsBase(Test): """abstract base class for ts-style tests""" keys = [ "url", "url_timestamp", "timeout", "cycles", "profile_path", # The path containing the template profile. This # directory is copied to the temporary profile during # initialization of the test. If some of the files may # be overwritten by Firefox and need to be reinstalled # before each pass, use key |reinstall| "gecko_profile", "gecko_profile_interval", "gecko_profile_entries", "gecko_profile_features", "gecko_profile_threads", "gecko_profile_extra_threads", "gecko_profile_startup", "preferences", "xperf_counters", "xperf_providers", "xperf_user_providers", "xperf_stackwalk", "tpmozafterpaint", "fnbpaint", "tphero", "tpmanifest", "profile", "firstpaint", "userready", "testeventmap", "base_vs_ref", "extensions", "filters", "setup", "cleanup", "pine", "skip_reason", "webextensions", "webextensions_folder", "reinstall", # A list of files from the profile directory that # should be copied to the temporary profile prior to # running each cycle, to avoid one cycle overwriting # the data used by the next another cycle (may be used # e.g. for sessionstore.js to ensure that all cycles # use the exact same sessionstore.js, rather than a # more recent copy). ] def __init__(self, **kw): super(TsBase, self).__init__(**kw) # Unless set to False explicitly, all TsBase tests will have the blocklist # enabled by default in order to more accurately test the startup paths. BLOCKLIST_PREF = "extensions.blocklist.enabled" if not hasattr(self, "preferences"): self.preferences = { BLOCKLIST_PREF: True, } elif BLOCKLIST_PREF not in self.preferences: self.preferences[BLOCKLIST_PREF] = True @register_test() class ts_paint(TsBase): """ Launches tspaint_test.html with the current timestamp in the url, waits for [MozAfterPaint and onLoad] to fire, then records the end time and calculates the time to startup. """ cycles = 20 timeout = 150 gecko_profile_startup = True url = "startup_test/tspaint_test.html" xperf_counters = [] win7_counters = [] filters = filter.ignore_first.prepare(1) + filter.median.prepare() tpmozafterpaint = True mainthread = False responsiveness = False unit = "ms" @register_test() class ts_paint_webext(ts_paint): webextensions = "${talos}/webextensions/dummy/dummy.xpi" preferences = {"xpinstall.signatures.required": False} @register_test() class ts_paint_heavy(ts_paint): """ ts_paint test ran against a heavy-user profile """ profile = "simple" @register_test() class startup_about_home_paint(ts_paint): """ Tests loading about:home on startup with the about:home startup cache disabled, to more accurately simulate startup when the cache does not exist. """ url = None cycles = 20 timeout = 600 extensions = ["${talos}/startup_test/startup_about_home_paint/addon"] tpmanifest = "${talos}/startup_test/startup_about_home_paint/startup_about_home_paint.manifest" preferences = { "browser.startup.homepage.abouthome_cache.enabled": False, } pine = False @register_test() class startup_about_home_paint_cached(ts_paint): """ Tests loading about:home on startup with the about:home startup cache enabled. """ url = None cycles = 20 extensions = ["${talos}/startup_test/startup_about_home_paint/addon"] tpmanifest = "${talos}/startup_test/startup_about_home_paint/startup_about_home_paint.manifest" preferences = { "browser.startup.homepage.abouthome_cache.enabled": True, } pine = False @register_test() class startup_about_home_paint_realworld_webextensions(ts_paint): url = None cycles = 20 extensions = [ "${talos}/startup_test/startup_about_home_paint/addon", "${talos}/getinfooffline", ] tpmanifest = "${talos}/startup_test/startup_about_home_paint/startup_about_home_paint.manifest" webextensions_folder = "${talos}/webextensions" preferences = { "browser.startup.homepage.abouthome_cache.enabled": False, } pine = False @register_test() class sessionrestore(TsBase): """ A start up test measuring the time it takes to load a sessionstore.js file. 1. Set up Firefox to restore from a given sessionstore.js file. 2. Launch Firefox. 3. Measure the delta between firstPaint and sessionRestored. """ extensions = ["${talos}/startup_test/sessionrestore/addon"] cycles = 10 timeout = 900 gecko_profile_startup = True profile_path = "${talos}/startup_test/sessionrestore/profile" reinstall = ["sessionstore.jsonlz4", "sessionstore.js", "sessionCheckpoints.json"] # Restore the session. We have to provide a URL, otherwise Talos # asks for a manifest URL. url = "about:home" preferences = {"browser.startup.page": 3} unit = "ms" pine = False @register_test() class sessionrestore_no_auto_restore(sessionrestore): """ A start up test measuring the time it takes to load a sessionstore.js file. 1. Set up Firefox to *not* restore automatically from sessionstore.js file. 2. Launch Firefox. 3. Measure the delta between firstPaint and sessionRestored. """ timeout = 300 preferences = { "browser.startup.page": 1, "talos.sessionrestore.norestore": True, } @register_test() class sessionrestore_many_windows(sessionrestore): """ A start up test measuring the time it takes to load a sessionstore.js file. 1. Set up Firefox to restore automatically from sessionstore.js file. 2. Launch Firefox. 3. Measure the delta between firstPaint and sessionRestored. """ profile_path = "${talos}/startup_test/sessionrestore/profile-manywindows" # pageloader tests(tp5, etc) # The overall test number is determined by first calculating the median # page load time for each page in the set (excluding the max page load # per individual page). The max median from that set is then excluded and # the average is taken; that becomes the number reported to the tinderbox # waterfall. class PageloaderTest(Test): """abstract base class for a Talos Pageloader test""" extensions = ["${talos}/pageloader"] tpmanifest = None # test manifest tpcycles = 1 # number of time to run each page cycles = None timeout = None keys = [ "tpmanifest", "tpcycles", "tppagecycles", "tprender", "tpchrome", "tpmozafterpaint", "fnbpaint", "tphero", "tploadnocache", "firstpaint", "userready", "testeventmap", "base_vs_ref", "mainthread", "resolution", "cycles", "gecko_profile", "gecko_profile_interval", "gecko_profile_entries", "gecko_profile_features", "gecko_profile_threads", "gecko_profile_extra_threads", "tptimeout", "win_counters", "linux_counters", "mac_counters", "tpscrolltest", "xperf_counters", "timeout", "responsiveness", "profile_path", "xperf_providers", "xperf_user_providers", "xperf_stackwalk", "format_pagename", "filters", "preferences", "extensions", "setup", "cleanup", "pine", "skip_reason", "lower_is_better", "alert_threshold", "unit", "webextensions", "profile", "suite_should_alert", "subtest_alerts", "perfherder_framework", "pdfpaint", "webextensions_folder", "a11y", ] class QuantumPageloadTest(PageloaderTest): """ Base class for a Quantum Pageload test """ tpcycles = 1 tppagecycles = 25 gecko_profile_interval = 1 filters = filter.ignore_first.prepare(5) + filter.median.prepare() unit = "ms" lower_is_better = True fnbpaint = True @register_test() class twinopen(PageloaderTest): """ Tests the amount of time it takes an open browser to open a new browser window and paint the browser chrome. This test does not include startup time. Multiple test windows are opened in succession. (Measures ctrl-n performance.) """ extensions = ["${talos}/pageloader", "${talos}/tests/twinopen"] tpmanifest = "${talos}/tests/twinopen/twinopen.manifest" tppagecycles = 20 timeout = 300 gecko_profile_interval = 1 tpmozafterpaint = True filters = filter.ignore_first.prepare(5) + filter.median.prepare() unit = "ms" preferences = {"browser.startup.homepage": "about:blank"} @register_test() class pdfpaint(PageloaderTest): """ Tests the amount of time it takes for the the first page of a PDF to be rendered. """ tpmanifest = "${talos}/tests/pdfpaint/pdfpaint.manifest" tppagecycles = 1 timeout = 1800 tptimeout = 60000 pdfpaint = True unit = "ms" @register_test() class cpstartup(PageloaderTest): """ Tests the amount of time it takes to start up a new content process and initialize it to the point where it can start processing incoming URLs to load. """ extensions = ["${talos}/pageloader", "${talos}/tests/cpstartup/extension"] tpmanifest = "${talos}/tests/cpstartup/cpstartup.manifest" tppagecycles = 20 timeout = 600 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 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", "${talos}/pageloader"] tpmanifest = "${talos}/tests/tabpaint/tabpaint.manifest" tppagecycles = 20 timeout = 600 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, "browser.newtab.preload": False, } @register_test() class tabswitch(PageloaderTest): """ Tests the amount of time it takes to switch between tabs """ extensions = ["${talos}/tests/tabswitch", "${talos}/pageloader"] tpmanifest = "${talos}/tests/tabswitch/tabswitch.manifest" tppagecycles = 5 timeout = 900 tploadnocache = True preferences = { "addon.test.tabswitch.urlfile": os.path.join("${talos}", "tests", "tp5o.html"), "addon.test.tabswitch.webserver": "${webserver}", "addon.test.tabswitch.maxurls": -1, } unit = "ms" @register_test() class cross_origin_pageload(PageloaderTest): """ Tests the amount of time it takes to load a page which has 20 cross origin iframes """ preferences = {"dom.ipc.processPrelaunch.fission.number": 30} extensions = ["${talos}/pageloader"] tpmanifest = "${talos}/tests/cross_origin_pageload/cross_origin_pageload.manifest" tppagecycles = 10 timeout = 100 tploadnocache = True unit = "ms" @register_test() class tart(PageloaderTest): """ Tab Animation Regression Test Tests tab animation on these cases: 1. Simple: single new tab of about:blank open/close without affecting (shrinking/expanding) other tabs. 2. icon: same as above with favicons and long title instead of about:blank. 3. Newtab: newtab open with thumbnails preview - without affecting other tabs, with and without preload. 4. Fade: opens a tab, then measures fadeout/fadein (tab animation without the overhead of opening/closing a tab). - Case 1 is tested with DPI scaling of 1. - Case 2 is tested with DPI scaling of 1.0 and 2.0. - Case 3 is tested with the default scaling of the test system. - Case 4 is tested with DPI scaling of 2.0 with the "icon" tab (favicon and long title). - Each animation produces 3 test results: - error: difference between the designated duration and the actual completion duration from the trigger. - half: average interval over the 2nd half of the animation. - all: average interval over all recorded intervals. """ tpmanifest = "${talos}/tests/tart/tart.manifest" extensions = ["${talos}/pageloader", "${talos}/tests/tart/addon"] tpcycles = 1 tppagecycles = 25 tploadnocache = True tpmozafterpaint = False gecko_profile_interval = 10 win_counters = linux_counters = mac_counters = None """ ASAP mode The recording API is broken with OMTC before ~2013-11-27 After ~2013-11-27, disabling OMTC will also implicitly disable OGL HW composition to disable OMTC with older firefox builds, also set 'layers.offmainthreadcomposition.enabled': False """ preferences = { "layout.frame_rate": 0, "docshell.event_starvation_delay_hint": 1, "dom.send_after_paint_to_content": False, } filters = filter.ignore_first.prepare(1) + filter.median.prepare() unit = "ms" pine = False @register_test() class damp(PageloaderTest): """ Devtools At Maximum Performance Tests the speed of DevTools toolbox open, close, and page reload for each tool, across a very simple and very complicated page. """ tpmanifest = "${talos}/tests/devtools/damp.manifest" extensions = ["${talos}/pageloader", "${talos}/tests/devtools/addon"] cycles = 5 tpcycles = 1 tppagecycles = 5 tploadnocache = True tpmozafterpaint = False gecko_profile_interval = 10 gecko_profile_extra_threads = "DOM Worker" win_counters = linux_counters = mac_counters = None filters = filter.ignore_first.prepare(1) + filter.median.prepare() preferences = {"devtools.memory.enabled": True} unit = "ms" subtest_alerts = True perfherder_framework = "devtools" @register_test() class glterrain(PageloaderTest): """ Simple rotating WebGL scene with moving light source over a textured terrain. Measures average frame intervals. The same sequence is measured 4 times for combinations of alpha and antialias as canvas properties. Each of these 4 runs is reported as a different test name. """ tpmanifest = "${talos}/tests/webgl/glterrain.manifest" tpcycles = 1 tppagecycles = 25 tploadnocache = True tpmozafterpaint = False tpchrome = False timeout = 600 gecko_profile_interval = 10 win_counters = linux_counters = mac_counters = None """ ASAP mode """ preferences = { "layout.frame_rate": 0, "docshell.event_starvation_delay_hint": 1, "dom.send_after_paint_to_content": False, } filters = filter.ignore_first.prepare(1) + filter.median.prepare() unit = "frame interval" @register_test() class glvideo(PageloaderTest): """ WebGL video texture update with 1080p video. Measures mean tick time across 100 ticks. (each tick is texImage2D(