зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1429759 - Allow Marionette tests to change the user profile. r=automatedtester
If Marionette handles the instance of the application including the user profile, the tests should be able to change the user profile. This will enable tests to cover specific bugs in the application as caused by the profile name and path. To prevent dataloss changing the profile should only be allowed when the application is not running. MozReview-Commit-ID: JWQGV4JWP61 --HG-- extra : rebase_source : 18270e9790f11fffc2a33a231dbc8229a1bf12d2
This commit is contained in:
Родитель
4bee56a645
Коммит
a1474a6ed5
|
@ -16,6 +16,8 @@ from mozdevice import DMError
|
|||
from mozprofile import Profile
|
||||
from mozrunner import Runner, FennecEmulatorRunner
|
||||
|
||||
import errors
|
||||
|
||||
|
||||
class GeckoInstance(object):
|
||||
required_prefs = {
|
||||
|
@ -124,15 +126,7 @@ class GeckoInstance(object):
|
|||
|
||||
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:
|
||||
|
@ -142,9 +136,14 @@ class GeckoInstance(object):
|
|||
self._gecko_log = None
|
||||
self.verbose = verbose
|
||||
self.headless = headless
|
||||
|
||||
# keep track of errors to decide whether instance is unresponsive
|
||||
self.unresponsive_count = 0
|
||||
|
||||
# Alternative to default temporary directory
|
||||
self.workspace = workspace
|
||||
self.profile = profile
|
||||
|
||||
@property
|
||||
def gecko_log(self):
|
||||
if self._gecko_log:
|
||||
|
@ -165,42 +164,87 @@ class GeckoInstance(object):
|
|||
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
|
||||
@property
|
||||
def profile(self):
|
||||
return self._profile
|
||||
|
||||
@profile.setter
|
||||
def profile(self, value):
|
||||
self._update_profile(value)
|
||||
|
||||
def _update_profile(self, profile=None, profile_name=None):
|
||||
"""Check if the profile has to be created, or replaced
|
||||
|
||||
:param profile: A Profile instance to be used.
|
||||
:param name: Profile name to be used in the path.
|
||||
"""
|
||||
if self.runner and self.runner.is_running():
|
||||
raise errors.MarionetteException("The used profile can only be updated "
|
||||
"when the instance is not running")
|
||||
|
||||
if isinstance(profile, Profile):
|
||||
# Only replace the profile if it is not the current one
|
||||
if hasattr(self, "_profile") and profile is self._profile:
|
||||
return
|
||||
|
||||
else:
|
||||
profile_args = self.profile_args
|
||||
profile_path = profile
|
||||
|
||||
# If a path to a profile is given then clone it
|
||||
if isinstance(profile_path, basestring):
|
||||
profile_args["path_from"] = profile_path
|
||||
profile_args["path_to"] = tempfile.mkdtemp(
|
||||
suffix=".{}".format(profile_name or os.path.basename(profile_path)),
|
||||
dir=self.workspace)
|
||||
# The target must not exist yet
|
||||
os.rmdir(profile_args["path_to"])
|
||||
|
||||
profile = Profile.clone(**profile_args)
|
||||
|
||||
# Otherwise create a new profile
|
||||
else:
|
||||
profile_args["profile"] = tempfile.mkdtemp(
|
||||
suffix=".{}".format(profile_name or "mozrunner"),
|
||||
dir=self.workspace)
|
||||
profile = Profile(**profile_args)
|
||||
profile.create_new = True
|
||||
|
||||
if hasattr(self, "_profile") and self._profile:
|
||||
self._profile.cleanup()
|
||||
self._profile = profile
|
||||
|
||||
def switch_profile(self, profile_name=None, clone_from=None):
|
||||
if isinstance(clone_from, Profile):
|
||||
clone_from = clone_from.profile
|
||||
|
||||
self._update_profile(clone_from, profile_name=profile_name)
|
||||
|
||||
@property
|
||||
def profile_args(self):
|
||||
args = {"preferences": deepcopy(self.required_prefs)}
|
||||
args["preferences"]["marionette.defaultPrefs.port"] = self.marionette_port
|
||||
|
||||
if self.prefs:
|
||||
profile_args["preferences"].update(self.prefs)
|
||||
args["preferences"].update(self.prefs)
|
||||
|
||||
if self.verbose:
|
||||
level = "TRACE" if self.verbose >= 2 else "DEBUG"
|
||||
profile_args["preferences"]["marionette.logging"] = level
|
||||
args["preferences"]["marionette.logging"] = level
|
||||
|
||||
if "-jsdebugger" in self.app_args:
|
||||
profile_args["preferences"].update({
|
||||
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)
|
||||
if self.addons:
|
||||
args["addons"] = self.addons
|
||||
|
||||
return args
|
||||
|
||||
@classmethod
|
||||
def create(cls, app=None, *args, **kwargs):
|
||||
|
@ -218,7 +262,7 @@ class GeckoInstance(object):
|
|||
return instance_class(*args, **kwargs)
|
||||
|
||||
def start(self):
|
||||
self._update_profile()
|
||||
self._update_profile(self.profile)
|
||||
self.runner = self.runner_class(**self._get_runner_args())
|
||||
self.runner.start()
|
||||
|
||||
|
@ -279,12 +323,12 @@ class GeckoInstance(object):
|
|||
:param prefs: Dictionary of preference names and values.
|
||||
:param clean: If True, reset the profile before starting.
|
||||
"""
|
||||
self.close(clean=clean)
|
||||
|
||||
if prefs:
|
||||
self.prefs = prefs
|
||||
else:
|
||||
self.prefs = None
|
||||
|
||||
self.close(clean=clean)
|
||||
self.start()
|
||||
|
||||
|
||||
|
@ -347,7 +391,7 @@ class FennecInstance(GeckoInstance):
|
|||
return self._package_name
|
||||
|
||||
def start(self):
|
||||
self._update_profile()
|
||||
self._update_profile(self.profile)
|
||||
self.runner = self.runner_class(**self._get_runner_args())
|
||||
try:
|
||||
if self.connect_to_running_emulator:
|
||||
|
|
|
@ -165,3 +165,38 @@ class TestPreferences(MarionetteTestCase):
|
|||
pass
|
||||
|
||||
self.assertEquals(self.marionette.get_pref(self.prefs["string"]), "abc")
|
||||
|
||||
|
||||
class TestEnforcePreferences(MarionetteTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestEnforcePreferences, self).setUp()
|
||||
|
||||
self.marionette.enforce_gecko_prefs({
|
||||
"marionette.test.bool": True,
|
||||
"marionette.test.int": 3,
|
||||
"marionette.test.string": "testing",
|
||||
})
|
||||
self.marionette.set_context("chrome")
|
||||
|
||||
def tearDown(self):
|
||||
self.marionette.quit(clean=True)
|
||||
|
||||
super(TestEnforcePreferences, self).tearDown()
|
||||
|
||||
def test_preferences_are_set(self):
|
||||
self.assertTrue(self.marionette.get_pref("marionette.test.bool"))
|
||||
self.assertEqual(self.marionette.get_pref("marionette.test.string"), "testing")
|
||||
self.assertEqual(self.marionette.get_pref("marionette.test.int"), 3)
|
||||
|
||||
def test_change_preference(self):
|
||||
self.assertTrue(self.marionette.get_pref("marionette.test.bool"))
|
||||
|
||||
self.marionette.enforce_gecko_prefs({"marionette.test.bool": False})
|
||||
|
||||
self.assertFalse(self.marionette.get_pref("marionette.test.bool"))
|
||||
|
||||
def test_restart_with_clean_profile(self):
|
||||
self.marionette.restart(clean=True)
|
||||
|
||||
self.assertEqual(self.marionette.get_pref("marionette.test.bool"), None)
|
||||
|
|
|
@ -2,33 +2,197 @@
|
|||
# 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 shutil
|
||||
import tempfile
|
||||
|
||||
import mozprofile
|
||||
|
||||
from marionette_harness import MarionetteTestCase
|
||||
|
||||
|
||||
class TestProfileManagement(MarionetteTestCase):
|
||||
class BaseProfileManagement(MarionetteTestCase):
|
||||
|
||||
def setUp(self):
|
||||
MarionetteTestCase.setUp(self)
|
||||
self.marionette.enforce_gecko_prefs(
|
||||
{"marionette.test.bool": True,
|
||||
"marionette.test.string": "testing",
|
||||
"marionette.test.int": 3
|
||||
})
|
||||
self.marionette.set_context("chrome")
|
||||
super(BaseProfileManagement, self).setUp()
|
||||
|
||||
def test_preferences_are_set(self):
|
||||
self.assertTrue(self.marionette.get_pref("marionette.test.bool"))
|
||||
self.assertEqual(self.marionette.get_pref("marionette.test.string"), "testing")
|
||||
self.assertEqual(self.marionette.get_pref("marionette.test.int"), 3)
|
||||
self.orig_profile_path = self.profile_path
|
||||
|
||||
def test_change_preference(self):
|
||||
self.assertTrue(self.marionette.get_pref("marionette.test.bool"))
|
||||
# Create external profile and mark it as not-removable
|
||||
tmp_dir = tempfile.mkdtemp(suffix="external")
|
||||
shutil.rmtree(tmp_dir, ignore_errors=True)
|
||||
|
||||
self.marionette.enforce_gecko_prefs({"marionette.test.bool": False})
|
||||
self.external_profile = mozprofile.Profile(profile=tmp_dir)
|
||||
self.external_profile.create_new = False
|
||||
|
||||
self.assertFalse(self.marionette.get_pref("marionette.test.bool"))
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.external_profile.profile, ignore_errors=True)
|
||||
|
||||
def test_clean_profile(self):
|
||||
self.marionette.profile = None
|
||||
|
||||
super(BaseProfileManagement, self).tearDown()
|
||||
|
||||
@property
|
||||
def profile(self):
|
||||
return self.marionette.instance.profile
|
||||
|
||||
@property
|
||||
def profile_path(self):
|
||||
return self.marionette.instance.profile.profile
|
||||
|
||||
|
||||
class WorkspaceProfileManagement(BaseProfileManagement):
|
||||
|
||||
def setUp(self):
|
||||
super(WorkspaceProfileManagement, self).setUp()
|
||||
|
||||
self.workspace = tempfile.mkdtemp()
|
||||
self.marionette.instance.workspace = self.workspace
|
||||
|
||||
def tearDown(self):
|
||||
self.marionette.instance.workspace = None
|
||||
|
||||
shutil.rmtree(self.workspace, ignore_errors=True)
|
||||
|
||||
super(WorkspaceProfileManagement, self).tearDown()
|
||||
|
||||
|
||||
class TestQuitRestartWithoutWorkspace(BaseProfileManagement):
|
||||
|
||||
def test_quit_keeps_same_profile(self):
|
||||
self.marionette.quit()
|
||||
self.marionette.start_session()
|
||||
|
||||
self.assertEqual(self.profile_path, self.orig_profile_path)
|
||||
self.assertTrue(os.path.exists(self.orig_profile_path))
|
||||
|
||||
def test_quit_clean_creates_new_profile(self):
|
||||
self.marionette.quit(clean=True)
|
||||
self.marionette.start_session()
|
||||
|
||||
self.assertNotEqual(self.profile_path, self.orig_profile_path)
|
||||
self.assertFalse(os.path.exists(self.orig_profile_path))
|
||||
|
||||
def test_restart_keeps_same_profile(self):
|
||||
self.marionette.restart()
|
||||
|
||||
self.assertEqual(self.profile_path, self.orig_profile_path)
|
||||
self.assertTrue(os.path.exists(self.orig_profile_path))
|
||||
|
||||
def test_restart_clean_creates_new_profile(self):
|
||||
self.marionette.restart(clean=True)
|
||||
|
||||
self.assertEqual(self.marionette.get_pref("marionette.test.bool"), None)
|
||||
self.assertNotEqual(self.profile_path, self.orig_profile_path)
|
||||
self.assertFalse(os.path.exists(self.orig_profile_path))
|
||||
|
||||
|
||||
class TestQuitRestartWithWorkspace(WorkspaceProfileManagement):
|
||||
|
||||
def test_quit_keeps_same_profile(self):
|
||||
self.marionette.quit()
|
||||
self.marionette.start_session()
|
||||
|
||||
self.assertEqual(self.profile_path, self.orig_profile_path)
|
||||
self.assertNotIn(self.workspace, self.profile_path)
|
||||
self.assertTrue(os.path.exists(self.orig_profile_path))
|
||||
|
||||
def test_quit_clean_creates_new_profile(self):
|
||||
self.marionette.quit(clean=True)
|
||||
self.marionette.start_session()
|
||||
|
||||
self.assertNotEqual(self.profile_path, self.orig_profile_path)
|
||||
self.assertIn(self.workspace, self.profile_path)
|
||||
self.assertFalse(os.path.exists(self.orig_profile_path))
|
||||
|
||||
def test_restart_keeps_same_profile(self):
|
||||
self.marionette.restart()
|
||||
|
||||
self.assertEqual(self.profile_path, self.orig_profile_path)
|
||||
self.assertNotIn(self.workspace, self.profile_path)
|
||||
self.assertTrue(os.path.exists(self.orig_profile_path))
|
||||
|
||||
def test_restart_clean_creates_new_profile(self):
|
||||
self.marionette.restart(clean=True)
|
||||
|
||||
self.assertNotEqual(self.profile_path, self.orig_profile_path)
|
||||
self.assertIn(self.workspace, self.profile_path)
|
||||
self.assertFalse(os.path.exists(self.orig_profile_path))
|
||||
|
||||
|
||||
class TestSwitchProfileWithoutWorkspace(BaseProfileManagement):
|
||||
|
||||
def setUp(self):
|
||||
super(TestSwitchProfileWithoutWorkspace, self).setUp()
|
||||
|
||||
self.marionette.quit()
|
||||
|
||||
def tearDown(self):
|
||||
super(TestSwitchProfileWithoutWorkspace, self).tearDown()
|
||||
|
||||
def test_new_random_profile_name(self):
|
||||
self.marionette.instance.switch_profile()
|
||||
|
||||
self.assertNotEqual(self.profile_path, self.orig_profile_path)
|
||||
self.assertFalse(os.path.exists(self.orig_profile_path))
|
||||
|
||||
def test_new_named_profile(self):
|
||||
self.marionette.instance.switch_profile("foobar")
|
||||
|
||||
self.assertNotEqual(self.profile_path, self.orig_profile_path)
|
||||
self.assertIn("foobar", self.profile_path)
|
||||
self.assertFalse(os.path.exists(self.orig_profile_path))
|
||||
|
||||
def test_clone_existing_profile(self):
|
||||
self.marionette.instance.switch_profile(clone_from=self.external_profile)
|
||||
|
||||
self.assertIn(os.path.basename(self.external_profile.profile), self.profile_path)
|
||||
self.assertTrue(os.path.exists(self.external_profile.profile))
|
||||
|
||||
def test_replace_with_current_profile(self):
|
||||
self.marionette.instance.profile = self.profile
|
||||
|
||||
self.assertEqual(self.profile_path, self.orig_profile_path)
|
||||
self.assertTrue(os.path.exists(self.orig_profile_path))
|
||||
|
||||
def test_replace_with_external_profile(self):
|
||||
self.marionette.instance.profile = self.external_profile
|
||||
|
||||
self.assertEqual(self.profile_path, self.external_profile.profile)
|
||||
self.assertFalse(os.path.exists(self.orig_profile_path))
|
||||
|
||||
# Set a new profile and ensure the external profile has not been deleted
|
||||
self.marionette.instance.profile = None
|
||||
|
||||
self.assertNotEqual(self.profile_path, self.external_profile.profile)
|
||||
self.assertTrue(os.path.exists(self.external_profile.profile))
|
||||
|
||||
|
||||
class TestSwitchProfileWithWorkspace(WorkspaceProfileManagement):
|
||||
|
||||
def setUp(self):
|
||||
super(TestSwitchProfileWithWorkspace, self).setUp()
|
||||
|
||||
self.marionette.quit()
|
||||
|
||||
def test_new_random_profile_name(self):
|
||||
self.marionette.instance.switch_profile()
|
||||
|
||||
self.assertNotEqual(self.profile_path, self.orig_profile_path)
|
||||
self.assertIn(self.workspace, self.profile_path)
|
||||
self.assertFalse(os.path.exists(self.orig_profile_path))
|
||||
|
||||
def test_new_named_profile(self):
|
||||
self.marionette.instance.switch_profile("foobar")
|
||||
|
||||
self.assertNotEqual(self.profile_path, self.orig_profile_path)
|
||||
self.assertIn("foobar", self.profile_path)
|
||||
self.assertIn(self.workspace, self.profile_path)
|
||||
self.assertFalse(os.path.exists(self.orig_profile_path))
|
||||
|
||||
def test_clone_existing_profile(self):
|
||||
self.marionette.instance.switch_profile(clone_from=self.external_profile)
|
||||
|
||||
self.assertNotEqual(self.profile_path, self.orig_profile_path)
|
||||
self.assertIn(self.workspace, self.profile_path)
|
||||
self.assertIn(os.path.basename(self.external_profile.profile), self.profile_path)
|
||||
self.assertTrue(os.path.exists(self.external_profile.profile))
|
||||
|
|
Загрузка…
Ссылка в новой задаче