tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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))