def test_both_ports_disabled(self, config_d): # This ini file has both http and https ports disabled. shutil.copy(data_path('config.config_07.ini'), os.path.join(config_d, '01_override.ini')) config = Configuration() with self.assertRaises(ValueError) as cm: config.load(config_d) self.assertEqual(cm.exception.args[0], 'Cannot disable both http and https ports')
def test_constructor(self, config_d): # Configuration constructor takes an optional directory argument. config = Configuration(config_d) self.assertEqual(config.service.base, 'phablet.example.com') # Passing in a non-directory is not allowed. self.assertRaises(TypeError, Configuration, data_path('config.config_01.ini'))
def test_negative_port_number(self, config_d): # This ini file has a negative port number. shutil.copy(data_path('config.config_08.ini'), os.path.join(config_d, '01_override.ini')) with self.assertRaises(ValueError) as cm: Configuration(config_d) self.assertEqual(cm.exception.args[0], '-1')
def test_load_channel_bad_signature_gets_fixed(self, config_d): # Like above, but the second download of the image signing key results # in a properly signed channels.json file. sign(self._channels_path, 'spare.gpg') setup_keyrings() self._state.run_thru('get_channel') # At this point, the state machine has determined that the # channels.json file is not signed with the cached image signing key, # so it will try to download a new imaging signing key. Let's put one # on the server, but it will not match the key that channels.json is # signed with. self.assertIsNone(self._state.channels) setup_keyring_txz( 'spare.gpg', 'image-master.gpg', dict(type='image-signing'), os.path.join(self._serverdir, 'gpg', 'image-signing.tar.xz')) # This will succeed by grabbing a new image-signing key. config = Configuration(config_d) with open(config.gpg.image_signing, 'rb') as fp: checksum = hashlib.md5(fp.read()).digest() next(self._state) with open(config.gpg.image_signing, 'rb') as fp: self.assertNotEqual(checksum, hashlib.md5(fp.read()).digest()) # The next state transition will find that the channels.json file is # properly signed. next(self._state) self.assertIsNotNone(self._state.channels) self.assertEqual( self._state.channels.daily.devices.nexus7.keyring.signature, '/daily/nexus7/device-keyring.tar.xz.asc')
def test_always_downloads_gsm_allowed(self, config_d): # GSM downloads are allowed when always downloading. config = Configuration(config_d) Settings(config).set('auto_download', '2') get_download_manager().get_files(_http_pathify([ ('channel.channels_05.json', 'channels.json') ])) self.assertTrue(self._gsm_set_flag) self.assertTrue(self._gsm_get_flag)
def test_service_device(self, config_d): # A configuration file could have a [service]device variable, which # takes precedence. shutil.copy(data_path('config.config_11.ini'), os.path.join(config_d, '01_override.ini')) with patch('systemimage.device.check_output', return_value='nexus9'): config = Configuration(config_d) # This gets the [service]device value from the configuration file, # not the output of the hook. self.assertEqual(config.device, 'nexus8')
def test_wifi_downloads_gsm_disallowed(self, config_d): # Obviously GSM downloads are not allowed when downloading # automatically on wifi-only. config = Configuration(config_d) Settings(config).set('auto_download', '1') get_download_manager().get_files(_http_pathify([ ('channel.channels_05.json', 'channels.json') ])) self.assertFalse(self._gsm_set_flag) self.assertFalse(self._gsm_get_flag)
def test_manual_downloads_gsm_allowed(self, config_d): # When auto_download is 0, manual downloads are enabled so assuming # the user knows what they're doing, GSM downloads are allowed. config = Configuration(config_d) Settings(config).set('auto_download', '0') get_download_manager().get_files(_http_pathify([ ('channel.channels_05.json', 'channels.json') ])) self.assertTrue(self._gsm_set_flag) self.assertTrue(self._gsm_get_flag)
def test_date_unknown(self): # If there is no /userdata/.last_update file and no ini files, then # the last update date is unknown. with ExitStack() as stack: config_d = stack.enter_context(temporary_directory()) tempdir = stack.enter_context(temporary_directory()) userdata_path = os.path.join(tempdir, '.last_update') stack.enter_context( patch('systemimage.helpers.LAST_UPDATE_FILE', userdata_path)) config = Configuration(config_d) stack.enter_context(patch('systemimage.config._config', config)) self.assertEqual(last_update_date(), 'Unknown')
def test_ignore_some_files(self, config_d): # Any file that doesn't follow the NN_whatever.ini format isn't loaded. path_1 = os.path.join(config_d, 'dummy_file') with open(path_1, 'w', encoding='utf-8') as fp: print('ignore me', file=fp) path_2 = os.path.join(config_d, 'nounderscore.ini') with open(path_2, 'w', encoding='utf-8') as fp: print('ignore me', file=fp) path_3 = os.path.join(config_d, 'XX_almost.ini') with open(path_3, 'w', encoding='utf-8') as fp: print('ignore me', file=fp) config = Configuration(config_d) self.assertNotIn('dummy_file', config.ini_files) self.assertNotIn('nounderscore.ini', config.ini_files) self.assertNotIn('XX_almost.ini', config.ini_files)
def test_load_channel_blacklisted_signature(self, config_d): # We get an error if the signature on the channels.json file is good # but the key is blacklisted. sign(self._channels_path, 'image-signing.gpg') setup_keyrings() setup_keyring_txz( 'image-signing.gpg', 'image-master.gpg', dict(type='blacklist'), os.path.join(self._serverdir, 'gpg', 'blacklist.tar.xz')) self._state.run_thru('get_channel') # We now have an image-signing key which is blacklisted. This will # cause the state machine to try to download a new image signing key, # so let's put the cached one up on the server. This will still be # backlisted though. config = Configuration(config_d) key_path = os.path.join(self._serverdir, 'gpg', 'image-signing.tar.xz') shutil.copy(config.gpg.image_signing, key_path) shutil.copy(config.gpg.image_signing + '.asc', key_path + '.asc') # Run the state machine through _get_channel() again, only this time # because the key is still blacklisted, we'll get an exception. self.assertRaises(SignatureError, self._state.run_thru, 'get_channel')
def _wrapper(self, function, ini_files, *args, **kws): start = 0 # It would be preferable to simply add a device='nexus7' argument, but that # causes 'decorator() takes 1 positional argument but 2 were given' device = kws.get('device', 'nexus7') with ExitStack() as resources: # Create the config.d directory and copy all the source ini files to # this directory in sequential order, interpolating in the temporary # tmp and var directories. config_d = resources.enter_context(temporary_directory()) temp_tmpdir = resources.enter_context(temporary_directory()) temp_vardir = resources.enter_context(temporary_directory()) for ini_file in ini_files: dst = os.path.join(config_d, '{:02d}_override.ini'.format(start)) start += 1 template = resource_bytes('systemimage.tests.data', ini_file).decode('utf-8') with atomic(dst) as fp: print(template.format(tmpdir=temp_tmpdir, vardir=temp_vardir), file=fp) # Patch the global configuration object so that it can be used # directly, which is good enough in most cases. Also patch the bit of # code that detects the device name. config = Configuration(config_d) resources.enter_context(patch('systemimage.config._config', config)) resources.enter_context( patch('systemimage.device.check_output', return_value=device)) # Make sure the cache_partition and data_partition exist. makedirs(config.updater.cache_partition) makedirs(config.updater.data_partition) # The method under test is allowed to specify some additional # keyword arguments, in order to pass some variables in from the # wrapper. signature = inspect.signature(function) if 'config_d' in signature.parameters: kws['config_d'] = config_d if 'config' in signature.parameters: kws['config'] = config # Call the function with the given arguments and return the result. return function(self, *args)
def test_defaults(self): config = Configuration() # [service] self.assertEqual(config.service.base, 'system-image.ubports.com') self.assertEqual(config.http_base, 'http://system-image.ubports.com') self.assertEqual(config.https_base, 'https://system-image.ubports.com') self.assertEqual(config.service.channel, 'daily') self.assertEqual(config.service.build_number, 0) # [system] self.assertEqual(config.system.tempdir, '/tmp') self.assertEqual(config.system.logfile, '/var/log/system-image/client.log') self.assertEqual(config.system.loglevel, (logging.INFO, logging.ERROR)) self.assertEqual(config.system.settings_db, '/var/lib/system-image/settings.db') # [hooks] self.assertEqual(config.hooks.device, SystemProperty) self.assertEqual(config.hooks.scorer, WeightedScorer) self.assertEqual(config.hooks.apply, Reboot) # [gpg] self.assertEqual(config.gpg.archive_master, '/usr/share/system-image/archive-master.tar.xz') self.assertEqual(config.gpg.image_master, '/var/lib/system-image/keyrings/image-master.tar.xz') self.assertEqual( config.gpg.image_signing, '/var/lib/system-image/keyrings/image-signing.tar.xz') self.assertEqual( config.gpg.device_signing, '/var/lib/system-image/keyrings/device-signing.tar.xz') # [updater] self.assertEqual(config.updater.cache_partition, '/android/cache/recovery') self.assertEqual(config.updater.data_partition, '/var/lib/system-image') # [dbus] self.assertEqual(config.dbus.lifetime.total_seconds(), 600)
def test_should_have_reloaded(self, config_d): # If a configuration is already loaded, it cannot be loaded again. # Use .reload() instead. config = Configuration(config_d) self.assertRaises(RuntimeError, config.load, config_d)