diff options
Diffstat (limited to '')
-rw-r--r-- | toolkit/xre/test/marionette/marionette.ini | 2 | ||||
-rw-r--r-- | toolkit/xre/test/marionette/test_exitcode.py | 33 | ||||
-rw-r--r-- | toolkit/xre/test/marionette/test_fission_autostart.py | 416 |
3 files changed, 451 insertions, 0 deletions
diff --git a/toolkit/xre/test/marionette/marionette.ini b/toolkit/xre/test/marionette/marionette.ini new file mode 100644 index 0000000000..f4beae89ea --- /dev/null +++ b/toolkit/xre/test/marionette/marionette.ini @@ -0,0 +1,2 @@ +[test_fission_autostart.py] +[test_exitcode.py] diff --git a/toolkit/xre/test/marionette/test_exitcode.py b/toolkit/xre/test/marionette/test_exitcode.py new file mode 100644 index 0000000000..32fd3d2bc0 --- /dev/null +++ b/toolkit/xre/test/marionette/test_exitcode.py @@ -0,0 +1,33 @@ +from marionette_harness import MarionetteTestCase + + +class TestFissionAutostart(MarionetteTestCase): + def test_normal_exit(self): + self.marionette.set_context(self.marionette.CONTEXT_CHROME) + + def call_quit(): + self.marionette.execute_script( + """ + const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); + Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit); + """, + sandbox="system", + ) + + self.marionette.quit(in_app=True, callback=call_quit) + self.assertEqual(self.marionette.instance.runner.returncode, 0) + + def test_exit_code(self): + self.marionette.set_context(self.marionette.CONTEXT_CHROME) + + def call_quit(): + self.marionette.execute_script( + """ + const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); + Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit, 5); + """, + sandbox="system", + ) + + self.marionette.quit(in_app=True, callback=call_quit) + self.assertEqual(self.marionette.instance.runner.returncode, 5) diff --git a/toolkit/xre/test/marionette/test_fission_autostart.py b/toolkit/xre/test/marionette/test_fission_autostart.py new file mode 100644 index 0000000000..b448307d2a --- /dev/null +++ b/toolkit/xre/test/marionette/test_fission_autostart.py @@ -0,0 +1,416 @@ +from __future__ import absolute_import, print_function + +from marionette_harness import MarionetteTestCase +from contextlib import contextmanager + + +class ExperimentStatus: + UNENROLLED = 0 + ENROLLED_CONTROL = 1 + ENROLLED_TREATMENT = 2 + DISQUALIFIED = 3 + + +class Prefs: + ENROLLMENT_STATUS = "fission.experiment.enrollmentStatus" + STARTUP_ENROLLMENT_STATUS = "fission.experiment.startupEnrollmentStatus" + FISSION_AUTOSTART = "fission.autostart" + FISSION_AUTOSTART_SESSION = "fission.autostart.session" + + +ENV_ENABLE_FISSION = "MOZ_FORCE_ENABLE_FISSION" +ENV_DISABLE_E10S = "MOZ_FORCE_DISABLE_E10S" + + +DECISION_STATUS = { + "experimentControl": 1, + "experimentTreatment": 2, + "disabledByE10sEnv": 3, + "enabledByEnv": 4, + "disabledBySafeMode": 5, + "enabledByDefault": 6, + "disabledByDefault": 7, + "enabledByUserPref": 8, + "disabledByUserPref": 9, + "disabledByE10sOther": 10, +} + + +class TestFissionAutostart(MarionetteTestCase): + SANDBOX_NAME = "fission-autostart" + + def execute_script(self, code, *args, **kwargs): + with self.marionette.using_context(self.marionette.CONTEXT_CHROME): + return self.marionette.execute_script( + code, new_sandbox=False, sandbox=self.SANDBOX_NAME, *args, **kwargs + ) + + def get_fission_status(self): + return self.execute_script( + r""" + let win = Services.wm.getMostRecentWindow("navigator:browser"); + return { + fissionAutostart: Services.appinfo.fissionAutostart, + fissionExperimentStatus: Services.appinfo.fissionExperimentStatus, + decisionStatus: Services.appinfo.fissionDecisionStatus, + decisionStatusString: Services.appinfo.fissionDecisionStatusString, + useRemoteSubframes: win.docShell.nsILoadContext.useRemoteSubframes, + fissionAutostartSession: Services.prefs.getBoolPref("fission.autostart.session"), + dynamicFissionAutostart: Services.prefs.getBoolPref("fission.autostart"), + }; + """ + ) + + def check_fission_status(self, enabled, experiment, decision, dynamic=None): + if dynamic is None: + dynamic = enabled + + expected = { + "fissionAutostart": enabled, + "fissionExperimentStatus": experiment, + "decisionStatus": DECISION_STATUS[decision], + "decisionStatusString": decision, + "useRemoteSubframes": enabled, + "fissionAutostartSession": enabled, + "dynamicFissionAutostart": dynamic, + } + + status = self.get_fission_status() + + for prop, value in expected.items(): + self.assertEqual( + status[prop], + value, + "%s should have the value `%r`, but has `%r`" + % (prop, value, status[prop]), + ) + + def check_pref_locked(self): + PREF = Prefs.FISSION_AUTOSTART + + if PREF in self.marionette.instance.required_prefs: + return True + + res = self.execute_script( + r""" + const { AppConstants } = ChromeUtils.import( + "resource://gre/modules/AppConstants.jsm" + ); + return { + prefLocked: Services.prefs.prefIsLocked(arguments[0]), + releaseOrBeta: AppConstants.RELEASE_OR_BETA, + }; + """, + script_args=(PREF,), + ) + + if res["prefLocked"]: + self.assertTrue( + res["releaseOrBeta"], "Preference should only be locked on release/beta" + ) + return True + return False + + def set_env(self, env, value): + self.execute_script( + "env.set(arguments[0], arguments[1]);", script_args=(env, value) + ) + + def get_env(self, env): + return self.execute_script("return env.get(arguments[0]);", script_args=(env,)) + + def set_enrollment_status(self, status): + self.marionette.set_pref(Prefs.ENROLLMENT_STATUS, status, default_branch=True) + + startup_status = self.marionette.get_pref(Prefs.STARTUP_ENROLLMENT_STATUS) + self.assertEqual( + startup_status, + status, + "Startup enrollment status (%r) should match new " + "session status (%r)" % (startup_status, status), + ) + + def restart(self, prefs=None, env=None): + if prefs: + self.marionette.set_prefs(prefs) + + if env: + for name, value in env.items(): + self.set_env(name, value) + + self.marionette.restart(in_app=True, clean=False) + self.setUpSession() + + # Sanity check our environment. + if prefs: + for key, val in prefs.items(): + if val is not None: + self.assertEqual(self.marionette.get_pref(key), val) + if env: + for key, val in env.items(): + self.assertEqual(self.get_env(key), val or "") + + def setUpSession(self): + self.marionette.set_context(self.marionette.CONTEXT_CHROME) + + self.execute_script( + r""" + // We're running in a function, in a sandbox, that inherits from an + // X-ray wrapped window. Anything we want to be globally available + // needs to be defined on that window. + ChromeUtils.import("resource://gre/modules/Services.jsm", window); + window.env = Cc["@mozilla.org/process/environment;1"] + .getService(Ci.nsIEnvironment); + """ + ) + + @contextmanager + def full_restart(self): + profile = self.marionette.instance.profile + try: + self.marionette.quit(in_app=True, clean=False) + yield profile + finally: + self.marionette.start_session() + self.setUpSession() + + def setUp(self): + super(TestFissionAutostart, self).setUp() + + self.setUpSession() + + def tearDown(self): + self.marionette.restart(clean=True) + + super(TestFissionAutostart, self).tearDown() + + def test_runtime_changes(self): + """Tests that changes to preferences during runtime do not have any + effect on the current session.""" + + if self.check_pref_locked(): + # Need to be able to flip Fission prefs for this test to work. + return + + self.check_fission_status( + enabled=False, + experiment=ExperimentStatus.UNENROLLED, + decision="disabledByDefault", + ) + + self.restart(prefs={Prefs.FISSION_AUTOSTART: True}) + + self.check_fission_status( + enabled=True, + experiment=ExperimentStatus.UNENROLLED, + decision="enabledByUserPref", + ) + + self.set_enrollment_status(ExperimentStatus.ENROLLED_CONTROL) + self.check_fission_status( + enabled=True, + experiment=ExperimentStatus.UNENROLLED, + decision="enabledByUserPref", + ) + + self.marionette.set_pref(Prefs.FISSION_AUTOSTART, False) + self.check_fission_status( + enabled=True, + experiment=ExperimentStatus.UNENROLLED, + decision="enabledByUserPref", + dynamic=False, + ) + + self.marionette.clear_pref(Prefs.FISSION_AUTOSTART) + self.check_fission_status( + enabled=True, + experiment=ExperimentStatus.UNENROLLED, + decision="enabledByUserPref", + dynamic=False, + ) + + self.restart() + self.check_fission_status( + enabled=False, + experiment=ExperimentStatus.ENROLLED_CONTROL, + decision="experimentControl", + ) + + self.marionette.set_pref( + Prefs.ENROLLMENT_STATUS, ExperimentStatus.UNENROLLED, default_branch=True + ) + self.check_fission_status( + enabled=False, + experiment=ExperimentStatus.ENROLLED_CONTROL, + decision="experimentControl", + ) + + self.set_env(ENV_ENABLE_FISSION, "1") + self.check_fission_status( + enabled=False, + experiment=ExperimentStatus.ENROLLED_CONTROL, + decision="experimentControl", + ) + + def test_fission_precedence(self): + if self.check_pref_locked(): + # Need to be able to flip Fission prefs for this test to work. + return + + self.check_fission_status( + enabled=False, + experiment=ExperimentStatus.UNENROLLED, + decision="disabledByDefault", + ) + + self.restart( + prefs={Prefs.FISSION_AUTOSTART: False}, env={ENV_ENABLE_FISSION: "1"} + ) + self.check_fission_status( + enabled=True, + experiment=ExperimentStatus.UNENROLLED, + decision="enabledByEnv", + dynamic=False, + ) + + self.restart( + prefs={Prefs.FISSION_AUTOSTART: True}, env={ENV_ENABLE_FISSION: ""} + ) + self.check_fission_status( + enabled=True, + experiment=ExperimentStatus.UNENROLLED, + decision="enabledByUserPref", + ) + + self.restart(prefs={Prefs.FISSION_AUTOSTART: None}) + self.check_fission_status( + enabled=False, + experiment=ExperimentStatus.UNENROLLED, + decision="disabledByDefault", + ) + + self.set_enrollment_status(ExperimentStatus.ENROLLED_TREATMENT) + self.restart() + self.check_fission_status( + enabled=True, + experiment=ExperimentStatus.ENROLLED_TREATMENT, + decision="experimentTreatment", + ) + + self.set_enrollment_status(ExperimentStatus.ENROLLED_CONTROL) + self.restart() + self.check_fission_status( + enabled=False, + experiment=ExperimentStatus.ENROLLED_CONTROL, + decision="experimentControl", + ) + + self.marionette.set_pref(Prefs.FISSION_AUTOSTART, True) + self.check_fission_status( + enabled=False, + experiment=ExperimentStatus.ENROLLED_CONTROL, + decision="experimentControl", + dynamic=True, + ) + + self.assertEqual( + self.marionette.get_pref(Prefs.ENROLLMENT_STATUS), + ExperimentStatus.DISQUALIFIED, + "Setting fission.autostart should disqualify", + ) + + self.restart() + self.check_fission_status( + enabled=True, + experiment=ExperimentStatus.DISQUALIFIED, + decision="enabledByUserPref", + ) + + app_version = self.execute_script("return Services.appinfo.version") + self.restart(env={ENV_DISABLE_E10S: app_version}) + self.check_fission_status( + enabled=False, + experiment=ExperimentStatus.DISQUALIFIED, + decision="disabledByE10sEnv", + dynamic=True, + ) + + def test_fission_startup(self): + if self.check_pref_locked(): + # Need to be able to flip Fission prefs for this test to work. + return + + # Starting the browser with STARTUP_ENROLLMENT_STATUS set to treatment + # should make the current session run under treatment. + with self.full_restart() as profile: + profile.set_preferences( + { + Prefs.STARTUP_ENROLLMENT_STATUS: ExperimentStatus.ENROLLED_TREATMENT, + }, + filename="prefs.js", + ) + + self.assertEqual( + self.marionette.get_pref(Prefs.ENROLLMENT_STATUS), + ExperimentStatus.UNENROLLED, + "Dynamic pref should be unenrolled", + ) + self.assertEqual( + self.marionette.get_pref(Prefs.STARTUP_ENROLLMENT_STATUS), + ExperimentStatus.ENROLLED_TREATMENT, + "Startup pref should be in treatment", + ) + self.check_fission_status( + enabled=True, + experiment=ExperimentStatus.ENROLLED_TREATMENT, + decision="experimentTreatment", + ) + + # If normandy doesn't re-set `ENROLLMENT_STATUS` during the session, it + # should be cleared back to disabled after a restart. + self.marionette.restart(in_app=True, clean=False) + + self.assertEqual( + self.marionette.get_pref(Prefs.ENROLLMENT_STATUS), + ExperimentStatus.UNENROLLED, + "Should unenroll dynamic pref after shutdown", + ) + self.assertEqual( + self.marionette.get_pref(Prefs.STARTUP_ENROLLMENT_STATUS), + ExperimentStatus.UNENROLLED, + "Should unenroll startup pref after shutdown", + ) + self.check_fission_status( + enabled=False, + experiment=ExperimentStatus.UNENROLLED, + decision="disabledByDefault", + ) + + # If the browser is started with a customized `fisison.autostart`, + # while also enrolled in an experiment, the experiment should be + # disqualified at startup. + with self.full_restart() as profile: + profile.set_preferences( + { + Prefs.FISSION_AUTOSTART: True, + Prefs.STARTUP_ENROLLMENT_STATUS: ExperimentStatus.ENROLLED_TREATMENT, + }, + filename="prefs.js", + ) + + self.assertEqual( + self.marionette.get_pref(Prefs.ENROLLMENT_STATUS), + ExperimentStatus.DISQUALIFIED, + "Should disqualify dynamic pref on startup", + ) + self.assertEqual( + self.marionette.get_pref(Prefs.STARTUP_ENROLLMENT_STATUS), + ExperimentStatus.DISQUALIFIED, + "Should disqualify startup pref on startup", + ) + + self.check_fission_status( + enabled=True, + experiment=ExperimentStatus.DISQUALIFIED, + decision="enabledByUserPref", + ) |