diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /testing/marionette/client/marionette_driver/geckoinstance.py | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'testing/marionette/client/marionette_driver/geckoinstance.py')
-rw-r--r-- | testing/marionette/client/marionette_driver/geckoinstance.py | 467 |
1 files changed, 467 insertions, 0 deletions
diff --git a/testing/marionette/client/marionette_driver/geckoinstance.py b/testing/marionette/client/marionette_driver/geckoinstance.py new file mode 100644 index 000000000..7e2048187 --- /dev/null +++ b/testing/marionette/client/marionette_driver/geckoinstance.py @@ -0,0 +1,467 @@ +# 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 +import sys +import tempfile +import time + +from copy import deepcopy + +import mozversion + +from mozprofile import Profile +from mozrunner import Runner, FennecEmulatorRunner + + +class GeckoInstance(object): + required_prefs = { + # Increase the APZ content response timeout in tests to 1 minute. + # This is to accommodate the fact that test environments tends to be slower + # than production environments (with the b2g emulator being the slowest of them + # all), resulting in the production timeout value sometimes being exceeded + # and causing false-positive test failures. See bug 1176798, bug 1177018, + # bug 1210465. + "apz.content_response_timeout": 60000, + + # Do not send Firefox health reports to the production server + "datareporting.healthreport.documentServerURI": "http://%(server)s/dummy/healthreport/", + "datareporting.healthreport.about.reportUrl": "http://%(server)s/dummy/abouthealthreport/", + + # Do not show datareporting policy notifications which can interfer with tests + "datareporting.policy.dataSubmissionPolicyBypassNotification": True, + + # Until Bug 1238095 is fixed, we have to enable CPOWs in order + # for Marionette tests to work properly. + "dom.ipc.cpows.forbid-unsafe-from-browser": False, + "dom.ipc.reportProcessHangs": False, + + # No slow script dialogs + "dom.max_chrome_script_run_time": 0, + "dom.max_script_run_time": 0, + + # Only load extensions from the application and user profile + # AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION + "extensions.autoDisableScopes": 0, + "extensions.enabledScopes": 5, + # don't block add-ons for e10s + "extensions.e10sBlocksEnabling": False, + # Disable metadata caching for installed add-ons by default + "extensions.getAddons.cache.enabled": False, + # Disable intalling any distribution add-ons + "extensions.installDistroAddons": False, + "extensions.showMismatchUI": False, + # Turn off extension updates so they don't bother tests + "extensions.update.enabled": False, + "extensions.update.notifyUser": False, + # Make sure opening about:addons won"t hit the network + "extensions.webservice.discoverURL": "http://%(server)s/dummy/discoveryURL", + + # Allow the application to have focus even it runs in the background + "focusmanager.testmode": True, + + # Disable useragent updates + "general.useragent.updates.enabled": False, + + # Always use network provider for geolocation tests + # so we bypass the OSX dialog raised by the corelocation provider + "geo.provider.testing": True, + # Do not scan Wifi + "geo.wifi.scan": False, + + # No hang monitor + "hangmonitor.timeout": 0, + + "javascript.options.showInConsole": True, + "marionette.defaultPrefs.enabled": True, + "media.volume_scale": "0.01", + + # Make sure the disk cache doesn't get auto disabled + "network.http.bypass-cachelock-threshold": 200000, + # Do not prompt for temporary redirects + "network.http.prompt-temp-redirect": False, + # Disable speculative connections so they aren"t reported as leaking when they"re + # hanging around + "network.http.speculative-parallel-limit": 0, + # Do not automatically switch between offline and online + "network.manage-offline-status": False, + # Make sure SNTP requests don't hit the network + "network.sntp.pools": "%(server)s", + + # Tests don't wait for the notification button security delay + "security.notification_enable_delay": 0, + + # Ensure blocklist updates don't hit the network + "services.settings.server": "http://%(server)s/dummy/blocklist/", + + # Disable password capture, so that tests that include forms aren"t + # influenced by the presence of the persistent doorhanger notification + "signon.rememberSignons": False, + + # Prevent starting into safe mode after application crashes + "toolkit.startup.max_resumed_crashes": -1, + + # We want to collect telemetry, but we don't want to send in the results + "toolkit.telemetry.server": "https://%(server)s/dummy/telemetry/", + } + + def __init__(self, host=None, port=None, bin=None, profile=None, addons=None, + app_args=None, symbols_path=None, gecko_log=None, prefs=None, + workspace=None, verbose=0): + self.runner_class = Runner + self.app_args = app_args or [] + self.runner = None + self.symbols_path = symbols_path + self.binary = bin + + self.marionette_host = host + self.marionette_port = port + # Alternative to default temporary directory + self.workspace = workspace + self.addons = addons + # Check if it is a Profile object or a path to profile + self.profile = None + if isinstance(profile, Profile): + self.profile = profile + else: + self.profile_path = profile + self.prefs = prefs + self.required_prefs = deepcopy(self.required_prefs) + if prefs: + self.required_prefs.update(prefs) + + self._gecko_log_option = gecko_log + self._gecko_log = None + self.verbose = verbose + + @property + def gecko_log(self): + if self._gecko_log: + return self._gecko_log + + path = self._gecko_log_option + if path != "-": + if path is None: + path = "gecko.log" + elif os.path.isdir(path): + fname = "gecko-{}.log".format(time.time()) + path = os.path.join(path, fname) + + path = os.path.realpath(path) + if os.access(path, os.F_OK): + os.remove(path) + + self._gecko_log = path + return self._gecko_log + + def _update_profile(self): + profile_args = {"preferences": deepcopy(self.required_prefs)} + profile_args["preferences"]["marionette.defaultPrefs.port"] = self.marionette_port + if self.prefs: + profile_args["preferences"].update(self.prefs) + if self.verbose: + level = "TRACE" if self.verbose >= 2 else "DEBUG" + profile_args["preferences"]["marionette.logging"] = level + if "-jsdebugger" in self.app_args: + profile_args["preferences"].update({ + "devtools.browsertoolbox.panel": "jsdebugger", + "devtools.debugger.remote-enabled": True, + "devtools.chrome.enabled": True, + "devtools.debugger.prompt-connection": False, + "marionette.debugging.clicktostart": True, + }) + if self.addons: + profile_args["addons"] = self.addons + + if hasattr(self, "profile_path") and self.profile is None: + if not self.profile_path: + if self.workspace: + profile_args["profile"] = tempfile.mkdtemp( + suffix=".mozrunner-{:.0f}".format(time.time()), + dir=self.workspace) + self.profile = Profile(**profile_args) + else: + profile_args["path_from"] = self.profile_path + profile_name = "{}-{:.0f}".format( + os.path.basename(self.profile_path), + time.time() + ) + if self.workspace: + profile_args["path_to"] = os.path.join(self.workspace, + profile_name) + self.profile = Profile.clone(**profile_args) + + @classmethod + def create(cls, app=None, *args, **kwargs): + try: + if not app and kwargs["bin"] is not None: + app_id = mozversion.get_version(binary=kwargs["bin"])["application_id"] + app = app_ids[app_id] + + instance_class = apps[app] + except (IOError, KeyError): + exc, val, tb = sys.exc_info() + msg = 'Application "{0}" unknown (should be one of {1})' + raise NotImplementedError, msg.format(app, apps.keys()), tb + + return instance_class(*args, **kwargs) + + def start(self): + self._update_profile() + self.runner = self.runner_class(**self._get_runner_args()) + self.runner.start() + + def _get_runner_args(self): + process_args = { + "processOutputLine": [NullOutput()], + } + + if self.gecko_log == "-": + process_args["stream"] = sys.stdout + else: + process_args["logfile"] = self.gecko_log + + env = os.environ.copy() + + # environment variables needed for crashreporting + # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting + env.update({"MOZ_CRASHREPORTER": "1", + "MOZ_CRASHREPORTER_NO_REPORT": "1", + "MOZ_CRASHREPORTER_SHUTDOWN": "1", + }) + + return { + "binary": self.binary, + "profile": self.profile, + "cmdargs": ["-no-remote", "-marionette"] + self.app_args, + "env": env, + "symbols_path": self.symbols_path, + "process_args": process_args + } + + def close(self, restart=False): + if not restart: + self.profile = None + + if self.runner: + self.runner.stop() + self.runner.cleanup() + + def restart(self, prefs=None, clean=True): + self.close(restart=True) + + if clean and self.profile: + self.profile.cleanup() + self.profile = None + + if prefs: + self.prefs = prefs + else: + self.prefs = None + self.start() + + +class FennecInstance(GeckoInstance): + fennec_prefs = { + # Enable output of dump() + "browser.dom.window.dump.enabled": True, + + # Disable Android snippets + "browser.snippets.enabled": False, + "browser.snippets.syncPromo.enabled": False, + "browser.snippets.firstrunHomepage.enabled": False, + + # Disable safebrowsing components + "browser.safebrowsing.downloads.enabled": False, + + # Do not restore the last open set of tabs if the browser has crashed + "browser.sessionstore.resume_from_crash": False, + + # Disable e10s by default + "browser.tabs.remote.autostart.1": False, + "browser.tabs.remote.autostart.2": False, + "browser.tabs.remote.autostart": False, + + # Do not allow background tabs to be zombified, otherwise for tests that + # open additional tabs, the test harness tab itself might get unloaded + "browser.tabs.disableBackgroundZombification": True, + } + + def __init__(self, emulator_binary=None, avd_home=None, avd=None, + adb_path=None, serial=None, connect_to_running_emulator=False, + package_name=None, *args, **kwargs): + super(FennecInstance, self).__init__(*args, **kwargs) + self.required_prefs.update(FennecInstance.fennec_prefs) + + self.runner_class = FennecEmulatorRunner + # runner args + self._package_name = package_name + self.emulator_binary = emulator_binary + self.avd_home = avd_home + self.adb_path = adb_path + self.avd = avd + self.serial = serial + self.connect_to_running_emulator = connect_to_running_emulator + + @property + def package_name(self): + """ + Name of app to run on emulator. + + Note that FennecInstance does not use self.binary + """ + if self._package_name is None: + self._package_name = "org.mozilla.fennec" + user = os.getenv("USER") + if user: + self._package_name += "_" + user + return self._package_name + + def start(self): + self._update_profile() + self.runner = self.runner_class(**self._get_runner_args()) + try: + if self.connect_to_running_emulator: + self.runner.device.connect() + self.runner.start() + except Exception as e: + exc, val, tb = sys.exc_info() + message = "Error possibly due to runner or device args: {}" + raise exc, message.format(e.message), tb + # gecko_log comes from logcat when running with device/emulator + logcat_args = { + "filterspec": "Gecko", + "serial": self.runner.device.dm._deviceSerial + } + if self.gecko_log == "-": + logcat_args["stream"] = sys.stdout + else: + logcat_args["logfile"] = self.gecko_log + self.runner.device.start_logcat(**logcat_args) + + # forward marionette port (localhost:2828) + self.runner.device.dm.forward( + local="tcp:{}".format(self.marionette_port), + remote="tcp:{}".format(self.marionette_port)) + + def _get_runner_args(self): + process_args = { + "processOutputLine": [NullOutput()], + } + + runner_args = { + "app": self.package_name, + "avd_home": self.avd_home, + "adb_path": self.adb_path, + "binary": self.emulator_binary, + "profile": self.profile, + "cmdargs": ["-marionette"] + self.app_args, + "symbols_path": self.symbols_path, + "process_args": process_args, + "logdir": self.workspace or os.getcwd(), + "serial": self.serial, + } + if self.avd: + runner_args["avd"] = self.avd + + return runner_args + + def close(self, restart=False): + super(FennecInstance, self).close(restart) + if self.runner and self.runner.device.connected: + self.runner.device.dm.remove_forward( + "tcp:{}".format(self.marionette_port)) + + +class DesktopInstance(GeckoInstance): + desktop_prefs = { + # Disable application updates + "app.update.enabled": False, + + # Enable output of dump() + "browser.dom.window.dump.enabled": True, + + # Indicate that the download panel has been shown once so that whichever + # download test runs first doesn"t show the popup inconsistently + "browser.download.panel.shown": True, + + # Do not show the EULA notification which can interfer with tests + "browser.EULA.override": True, + + # Turn off about:newtab and make use of about:blank instead for new opened tabs + "browser.newtabpage.enabled": False, + # Assume the about:newtab page"s intro panels have been shown to not depend on + # which test runs first and happens to open about:newtab + "browser.newtabpage.introShown": True, + + # Background thumbnails in particular cause grief, and disabling thumbnails + # in general can"t hurt - we re-enable them when tests need them + "browser.pagethumbnails.capturing_disabled": True, + + # Avoid performing Reader Mode intros during tests + "browser.reader.detectedFirstArticle": True, + + # Disable safebrowsing components + "browser.safebrowsing.blockedURIs.enabled": False, + "browser.safebrowsing.downloads.enabled": False, + "browser.safebrowsing.forbiddenURIs.enabled": False, + "browser.safebrowsing.malware.enabled": False, + "browser.safebrowsing.phishing.enabled": False, + + # Disable updates to search engines + "browser.search.update": False, + + # Do not restore the last open set of tabs if the browser has crashed + "browser.sessionstore.resume_from_crash": False, + + # Don't check for the default web browser during startup + "browser.shell.checkDefaultBrowser": False, + + # Disable e10s by default + "browser.tabs.remote.autostart.1": False, + "browser.tabs.remote.autostart.2": False, + "browser.tabs.remote.autostart": False, + + # Needed for branded builds to prevent opening a second tab on startup + "browser.startup.homepage_override.mstone": "ignore", + # Start with a blank page by default + "browser.startup.page": 0, + + # Disable tab animation + "browser.tabs.animate": False, + + # Do not warn on exit when multiple tabs are open + "browser.tabs.warnOnClose": False, + # Do not warn when closing all other open tabs + "browser.tabs.warnOnCloseOtherTabs": False, + # Do not warn when multiple tabs will be opened + "browser.tabs.warnOnOpen": False, + + # Disable the UI tour + "browser.uitour.enabled": False, + + # Disable first-run welcome page + "startup.homepage_welcome_url": "about:blank", + "startup.homepage_welcome_url.additional": "", + } + + def __init__(self, *args, **kwargs): + super(DesktopInstance, self).__init__(*args, **kwargs) + self.required_prefs.update(DesktopInstance.desktop_prefs) + + +class NullOutput(object): + def __call__(self, line): + pass + + +apps = { + 'fennec': FennecInstance, + 'fxdesktop': DesktopInstance, +} + +app_ids = { + '{aa3c5121-dab2-40e2-81ca-7ea25febc110}': 'fennec', + '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}': 'fxdesktop', +} |