summaryrefslogtreecommitdiffstats
path: root/toolkit/xre/test/marionette
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--toolkit/xre/test/marionette/marionette.ini2
-rw-r--r--toolkit/xre/test/marionette/test_exitcode.py33
-rw-r--r--toolkit/xre/test/marionette/test_fission_autostart.py416
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",
+ )