test_profile_management.py (10180B)
1 # coding=UTF-8 2 3 # This Source Code Form is subject to the terms of the Mozilla Public 4 # License, v. 2.0. If a copy of the MPL was not distributed with this 5 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 7 import os 8 import shutil 9 import tempfile 10 11 import mozprofile 12 13 from marionette_driver import errors 14 from marionette_harness import MarionetteTestCase, parameterized 15 16 17 class BaseProfileManagement(MarionetteTestCase): 18 def setUp(self): 19 super(BaseProfileManagement, self).setUp() 20 21 self.orig_profile_path = self.profile_path 22 23 def tearDown(self): 24 shutil.rmtree(self.orig_profile_path, ignore_errors=True) 25 self.marionette.profile = None 26 27 self.marionette.quit(in_app=False, clean=True) 28 29 super(BaseProfileManagement, self).tearDown() 30 31 @property 32 def profile(self): 33 return self.marionette.instance.profile 34 35 @property 36 def profile_path(self): 37 return self.marionette.instance.profile.profile 38 39 40 class WorkspaceProfileManagement(BaseProfileManagement): 41 def setUp(self): 42 super(WorkspaceProfileManagement, self).setUp() 43 44 # Set a new workspace for the instance, which will be used 45 # the next time a new profile is requested by a test. 46 self.workspace = tempfile.mkdtemp() 47 self.marionette.instance.workspace = self.workspace 48 49 def tearDown(self): 50 self.marionette.instance.workspace = None 51 52 shutil.rmtree(self.workspace, ignore_errors=True) 53 54 super(WorkspaceProfileManagement, self).tearDown() 55 56 57 class ExternalProfileMixin(object): 58 def setUp(self): 59 super(ExternalProfileMixin, self).setUp() 60 61 # Create external profile 62 tmp_dir = tempfile.mkdtemp(suffix="external") 63 shutil.rmtree(tmp_dir, ignore_errors=True) 64 65 # Re-use all the required profile arguments (preferences) 66 profile_args = self.marionette.instance.profile_args 67 profile_args["profile"] = tmp_dir 68 self.external_profile = mozprofile.Profile(**profile_args) 69 70 # Prevent profile from being removed during cleanup 71 self.external_profile.create_new = False 72 73 def tearDown(self): 74 shutil.rmtree(self.external_profile.profile, ignore_errors=True) 75 76 super(ExternalProfileMixin, self).tearDown() 77 78 79 class TestQuitRestartWithoutWorkspace(BaseProfileManagement): 80 @parameterized("safe", True) 81 @parameterized("forced", False) 82 def test_quit_keeps_same_profile(self, in_app): 83 self.marionette.quit(in_app=in_app) 84 self.marionette.start_session() 85 86 self.assertEqual(self.profile_path, self.orig_profile_path) 87 self.assertTrue(os.path.exists(self.orig_profile_path)) 88 89 def test_quit_clean_creates_new_profile(self): 90 self.marionette.quit(in_app=False, clean=True) 91 self.marionette.start_session() 92 93 self.assertNotEqual(self.profile_path, self.orig_profile_path) 94 self.assertFalse(os.path.exists(self.orig_profile_path)) 95 96 @parameterized("safe", True) 97 @parameterized("forced", False) 98 def test_restart_keeps_same_profile(self, in_app): 99 self.marionette.restart(in_app=in_app) 100 101 self.assertEqual(self.profile_path, self.orig_profile_path) 102 self.assertTrue(os.path.exists(self.orig_profile_path)) 103 104 def test_restart_clean_creates_new_profile(self): 105 self.marionette.restart(in_app=False, clean=True) 106 107 self.assertNotEqual(self.profile_path, self.orig_profile_path) 108 self.assertFalse(os.path.exists(self.orig_profile_path)) 109 110 111 class TestQuitRestartWithWorkspace(WorkspaceProfileManagement): 112 @parameterized("safe", True) 113 @parameterized("forced", False) 114 def test_quit_keeps_same_profile(self, in_app): 115 self.marionette.quit(in_app=in_app) 116 self.marionette.start_session() 117 118 self.assertEqual(self.profile_path, self.orig_profile_path) 119 self.assertNotIn(self.workspace, self.profile_path) 120 self.assertTrue(os.path.exists(self.orig_profile_path)) 121 122 def test_quit_clean_creates_new_profile(self): 123 self.marionette.quit(in_app=False, clean=True) 124 self.marionette.start_session() 125 126 self.assertNotEqual(self.profile_path, self.orig_profile_path) 127 self.assertIn(self.workspace, self.profile_path) 128 self.assertFalse(os.path.exists(self.orig_profile_path)) 129 130 @parameterized("safe", True) 131 @parameterized("forced", False) 132 def test_restart_keeps_same_profile(self, in_app): 133 self.marionette.restart(in_app=in_app) 134 135 self.assertEqual(self.profile_path, self.orig_profile_path) 136 self.assertNotIn(self.workspace, self.profile_path) 137 self.assertTrue(os.path.exists(self.orig_profile_path)) 138 139 def test_restart_clean_creates_new_profile(self): 140 self.marionette.restart(in_app=False, clean=True) 141 142 self.assertNotEqual(self.profile_path, self.orig_profile_path) 143 self.assertIn(self.workspace, self.profile_path) 144 self.assertFalse(os.path.exists(self.orig_profile_path)) 145 146 147 class TestSwitchProfileFailures(BaseProfileManagement): 148 def test_raise_for_switching_profile_while_instance_is_running(self): 149 with self.assertRaisesRegex( 150 errors.MarionetteException, "instance is not running" 151 ): 152 self.marionette.instance.switch_profile() 153 154 155 class TestSwitchProfileWithoutWorkspace(ExternalProfileMixin, BaseProfileManagement): 156 def setUp(self): 157 super(TestSwitchProfileWithoutWorkspace, self).setUp() 158 159 self.marionette.quit() 160 161 def test_do_not_call_cleanup_of_profile_for_path_only(self): 162 # If a path to a profile has been given (eg. via the --profile command 163 # line argument) and the profile hasn't been created yet, switching the 164 # profile should not try to call `cleanup()` on a string. 165 self.marionette.instance._profile = self.external_profile.profile 166 self.marionette.instance.switch_profile() 167 168 def test_new_random_profile_name(self): 169 self.marionette.instance.switch_profile() 170 self.marionette.start_session() 171 172 self.assertNotEqual(self.profile_path, self.orig_profile_path) 173 self.assertFalse(os.path.exists(self.orig_profile_path)) 174 175 def test_new_named_profile(self): 176 self.marionette.instance.switch_profile("foobar") 177 self.marionette.start_session() 178 179 self.assertNotEqual(self.profile_path, self.orig_profile_path) 180 self.assertIn("foobar", self.profile_path) 181 self.assertFalse(os.path.exists(self.orig_profile_path)) 182 183 def test_new_named_profile_unicode(self): 184 """Test using unicode string with 1-4 bytes encoding works.""" 185 self.marionette.instance.switch_profile("$¢€🍪") 186 self.marionette.start_session() 187 188 self.assertNotEqual(self.profile_path, self.orig_profile_path) 189 self.assertIn("$¢€🍪", self.profile_path) 190 self.assertFalse(os.path.exists(self.orig_profile_path)) 191 192 def test_new_named_profile_unicode_escape_characters(self): 193 """Test using escaped unicode string with 1-4 bytes encoding works.""" 194 self.marionette.instance.switch_profile("\u0024\u00A2\u20AC\u1F36A") 195 self.marionette.start_session() 196 197 self.assertNotEqual(self.profile_path, self.orig_profile_path) 198 self.assertIn("\u0024\u00A2\u20AC\u1F36A", self.profile_path) 199 self.assertFalse(os.path.exists(self.orig_profile_path)) 200 201 def test_clone_existing_profile(self): 202 self.marionette.instance.switch_profile(clone_from=self.external_profile) 203 self.marionette.start_session() 204 205 self.assertIn( 206 os.path.basename(self.external_profile.profile), self.profile_path 207 ) 208 self.assertTrue(os.path.exists(self.external_profile.profile)) 209 210 def test_replace_with_current_profile(self): 211 self.marionette.instance.profile = self.profile 212 self.marionette.start_session() 213 214 self.assertEqual(self.profile_path, self.orig_profile_path) 215 self.assertTrue(os.path.exists(self.orig_profile_path)) 216 217 def test_replace_with_external_profile(self): 218 self.marionette.instance.profile = self.external_profile 219 self.marionette.start_session() 220 221 self.assertEqual(self.profile_path, self.external_profile.profile) 222 self.assertFalse(os.path.exists(self.orig_profile_path)) 223 224 # Check that required preferences have been correctly set 225 self.assertFalse(self.marionette.get_pref("remote.prefs.recommended")) 226 227 # Set a new profile and ensure the external profile has not been deleted 228 self.marionette.quit() 229 self.marionette.instance.profile = None 230 231 self.assertNotEqual(self.profile_path, self.external_profile.profile) 232 self.assertTrue(os.path.exists(self.external_profile.profile)) 233 234 235 class TestSwitchProfileWithWorkspace(ExternalProfileMixin, WorkspaceProfileManagement): 236 def setUp(self): 237 super(TestSwitchProfileWithWorkspace, self).setUp() 238 239 self.marionette.quit() 240 241 def test_new_random_profile_name(self): 242 self.marionette.instance.switch_profile() 243 self.marionette.start_session() 244 245 self.assertNotEqual(self.profile_path, self.orig_profile_path) 246 self.assertIn(self.workspace, self.profile_path) 247 self.assertFalse(os.path.exists(self.orig_profile_path)) 248 249 def test_new_named_profile(self): 250 self.marionette.instance.switch_profile("foobar") 251 self.marionette.start_session() 252 253 self.assertNotEqual(self.profile_path, self.orig_profile_path) 254 self.assertIn("foobar", self.profile_path) 255 self.assertIn(self.workspace, self.profile_path) 256 self.assertFalse(os.path.exists(self.orig_profile_path)) 257 258 def test_clone_existing_profile(self): 259 self.marionette.instance.switch_profile(clone_from=self.external_profile) 260 self.marionette.start_session() 261 262 self.assertNotEqual(self.profile_path, self.orig_profile_path) 263 self.assertIn(self.workspace, self.profile_path) 264 self.assertIn( 265 os.path.basename(self.external_profile.profile), self.profile_path 266 ) 267 self.assertTrue(os.path.exists(self.external_profile.profile))