def test_validate_invalid_name_full_validation_true(self): """ Due to a bug[0], we don't want to allow an ISO named PULP_MANIFEST. This test asserts that the name is validated when full_validation is set to True. [0] https://bugzilla.redhat.com/show_bug.cgi?id=973678 """ name = 'PULP_MANIFEST' destination = os.path.join(self.temp_dir, name) with open(destination, 'w') as test_file: test_file.write( "I heard there was this band called 1023MB, they haven't got any gigs yet.") unit = mock.MagicMock() unit.storage_path = destination iso = models.ISO(name, 73, '36891c265290bf4610b488a8eb884d32a29fd17bb9886d899e75f4cf29d3f464', unit) # This should raise a ValueError with an appropriate error message try: # We'll set full_validation to True for this test iso.validate(full_validation=True) self.fail('A ValueError should have been raised, but it was not.') except ValueError, e: self.assertEqual( str(e), 'An ISO may not be named PULP_MANIFEST, as it conflicts with the name of ' 'the manifest during publishing.')
def test_download_succeeded(self, download_failed): destination = os.path.join(self.temp_dir, 'test.txt') with open(destination, 'w') as test_file: test_file.write( 'Descartes walks into a bar and sits down, the bartender walks up to him and says ' '"You, my ' 'man, look like you need a stiff drink." Descartes considers this, and shakes his ' 'head "No, ' 'I don\'t think-" and ceases to exist.') unit = MagicMock() unit.storage_path = destination iso = models.ISO( 'test.txt', 217, 'a1552efee6f04012bc7e1f3e02c00c6177b08217cead958c47ec83cb8f97f835', unit) iso.url = 'http://fake.com' report = DownloadReport(iso.url, destination, iso) # Simulate having downloaded the whole file iso.bytes_downloaded = iso.size report.bytes_downloaded = iso.size self.iso_sync_run.progress_report._state = SyncProgressReport.STATE_ISOS_IN_PROGRESS self.iso_sync_run.download_succeeded(report) # The sync conduit should have been called to save the unit self.sync_conduit.save_unit.assert_any_call(unit) # The download should not fail self.assertEqual(download_failed.call_count, 0)
def test_validate_wrong_size_full_validation_true(self): """ Assert that validate() raises a ValueError when given an incorrect size and full_validation is True (default). """ destination = os.path.join(self.temp_dir, 'test.txt') try: test_file = open(destination, 'w') test_file.write( "Hey girl, what's your sine? It must be math.pi/2 because you're the 1." ) finally: test_file.close() unit = mock.MagicMock() unit.storage_path = destination iso = models.ISO( 'test.txt', math.pi, '2b046422425d6f01a920278c55d8842a8989bacaea05b29d1d2082fae91c6041', unit) # This should raise a ValueError with an appropriate error message try: iso.validate() self.fail('A ValueError should have been raised, but it was not.') except ValueError, e: self.assertEqual( str(e), 'Downloading <test.txt> failed validation. The manifest specified that the ' 'file should be 3.14159265359 bytes, but the downloaded file is 70 bytes.' )
def test_validate_wrong_checksum_full_validation_true(self): """ Assert that validate() raises a ValueError when the checksum is not correct and full_validation is True (default). """ destination = os.path.join(self.temp_dir, 'test.txt') try: test_file = open(destination, 'w') test_file.write( 'Two chemists walk into a bar, the first one says "I\'ll have some H2O." to ' 'which the other adds "I\'ll have some H2O, too." The second chemist died.' ) finally: test_file.close() unit = mock.MagicMock() unit.storage_path = destination iso = models.ISO('test.txt', 146, 'terrible_pun', unit) # This should raise a ValueError with an appropriate error message try: iso.validate() self.fail('A ValueError should have been raised, but it was not.') except ValueError, e: self.assertEqual( str(e), 'Downloading <test.txt> failed checksum validation. The manifest specified the ' 'checksum to be terrible_pun, but it was ' 'dfec884065223f24c3ef333d4c7dcc0eb785a683cfada51ce071410b32a905e8.' )
def test_download_succeeded_fails_checksum(self, download_failed): """ This test verifies that download_succeeded does the right thing if the checksum fails. Note that we are also implicitly testing that the default behavior is to validate downloads by not setting it in this test. There are two other tests that verify that setting the boolean explicitly is honored. """ self.config.override_config[importer_constants.KEY_VALIDATE] = True iso_sync_run = ISOSyncRun(self.sync_conduit, self.config) destination = os.path.join(self.temp_dir, 'test.txt') with open(destination, 'w') as test_file: test_file.write('Boring test data.') unit = MagicMock() unit.storage_path = destination iso = models.ISO('test.txt', 114, 'wrong checksum', unit) iso.url = 'http://fake.com' report = DownloadReport(iso.url, destination, iso) # Let's fake having downloaded the whole file iso.bytes_downloaded = iso.size report.bytes_downloaded = iso.size iso_sync_run.progress_report._state = SyncProgressReport.STATE_ISOS_IN_PROGRESS iso_sync_run.download_succeeded(report) # Because we fail validation, the save_unit step will not be called self.assertEqual(self.sync_conduit.save_unit.call_count, 0) # The download should be marked failed self.assertEqual(download_failed.call_count, 1) download_failed.assert_called_once_with(report)
def test_save_unit(self): unit = mock.MagicMock() iso = models.ISO('name', 42, 'checksum', unit) conduit = mock.MagicMock() iso.save_unit(conduit) conduit.save_unit.assert_called_once_with(unit)
def test___init__(self): """ Make sure __init__() sets all the proper attributes. """ iso = models.ISO('name', 42, 'checksum') self.assertEqual(iso.name, 'name') self.assertEqual(iso.size, 42) self.assertEqual(iso.checksum, 'checksum') self.assertEqual(iso._unit, None)
def test_storage_path(self): """ Make sure the storage_path() method returns the underlying Unit's storage_path attribute. """ unit = mock.MagicMock() unit.storage_path = '/some/path' iso = models.ISO('name', 42, 'checksum', unit) storage_path = iso.storage_path self.assertEqual(storage_path, unit.storage_path)
def test_download_failed_during_iso_download(self, _logger): self.iso_sync_run.progress_report._state = SyncProgressReport.STATE_ISOS_IN_PROGRESS url = 'http://www.theonion.com/articles/american-airlines-us-airways-merge-to-form' \ '-worlds,31302/' iso = models.ISO('test.txt', 217, 'a1552efee6f04012bc7e1f3e02c00c6177b08217cead958c47ec83cb8f97f835') report = DownloadReport(url, '/fake/destination', iso) report.error_msg = 'uh oh' self.iso_sync_run.download_failed(report) self.assertEqual(_logger.error.call_count, 1) log_msg = _logger.error.mock_calls[0][1][0] self.assertTrue('uh oh' in log_msg)
def test_validate_wrong_size_full_validation_false(self): """ Assert that validate() does not raise a ValueError when given an incorrect size and full_validation is False. """ destination = os.path.join(self.temp_dir, 'test.txt') with open(destination, 'w') as test_file: test_file.write( "Hey girl, what's your sine? It must be math.pi/2 because you're the 1.") unit = mock.MagicMock() unit.storage_path = destination iso = models.ISO('test.txt', math.pi, '2b046422425d6f01a920278c55d8842a8989bacaea05b29d1d2082fae91c6041', unit) # This should not raise an Exception because full_validation is set to False iso.validate(full_validation=False)
def test_validate_wrong_checksum_full_validation_false(self): """ Assert that validate() does not raise a ValueError when the checksum is not correct and full_validation is False. """ destination = os.path.join(self.temp_dir, 'test.txt') with open(destination, 'w') as test_file: test_file.write( 'Two chemists walk into a bar, the first one says "I\'ll have some H2O." to ' 'which the other adds "I\'ll have some H2O, too." The second chemist died.') unit = mock.MagicMock() unit.storage_path = destination iso = models.ISO('test.txt', 146, 'terrible_pun', unit) # This should not raise a ValueError since full_validation is False iso.validate(full_validation=False)
def test_init_unit(self): """ Assert correct behavior from the init_unit() method. """ unit = mock.MagicMock() conduit = mock.MagicMock() conduit.init_unit = mock.MagicMock(return_value=unit) iso = models.ISO('name', 42, 'checksum') iso.init_unit(conduit) self.assertEqual(iso._unit, unit) expected_relative_path = os.path.join('name', 'checksum', '42', 'name') conduit.init_unit.assert_called_once_with( ids.TYPE_ID_ISO, {'name': 'name', 'size': 42, 'checksum': 'checksum'}, {}, expected_relative_path)
def upload_unit(self, transfer_repo, type_id, unit_key, metadata, file_path, conduit, config): """ Handles the creation and association of an ISO. :param repo: The repository to import the package into :type repo: pulp.server.db.model.Repository :param type_id: The type_id of the package being uploaded :type type_id: str :param unit_key: A dictionary of fields to overwrite introspected field values :type unit_key: dict :param metadata: A dictionary of fields to overwrite introspected field values, or None :type metadata: dict or None :param file_path: The path to the uploaded package :type file_path: str :param conduit: provides access to relevant Pulp functionality :type conduit: pulp.plugins.conduits.upload.UploadConduit :param config: plugin configuration for the repository :type config: pulp.plugins.config.PluginCallConfiguration """ qs = models.ISO.objects.filter(**unit_key) if qs: # iso with this key already exists, use it iso = qs.first() else: # this is a new ISO, create it iso = models.ISO(**unit_key) validate = config.get_boolean(importer_constants.KEY_VALIDATE) validate = validate if validate is not None else constants.CONFIG_VALIDATE_DEFAULT try: # Let's validate the ISO. This will raise a # ValueError if the ISO does not validate correctly. iso.validate_iso(file_path, full_validation=validate) except ValueError, e: return { 'success_flag': False, 'summary': e.message, 'details': None }
def upload_unit(self, repo, type_id, unit_key, metadata, file_path, conduit, config): """ See super(self.__class__, self).upload_unit() for the docblock explaining this method. In short, it handles ISO uploads. """ iso = models.ISO(unit_key['name'], unit_key['size'], unit_key['checksum']) iso.init_unit(conduit) shutil.move(file_path, iso.storage_path) validate = config.get_boolean(importer_constants.KEY_VALIDATE) validate = validate if validate is not None else constants.CONFIG_VALIDATE_DEFAULT try: # Let's validate the ISO. This will raise a # ValueError if the ISO does not validate correctly. iso.validate(full_validation=validate) except ValueError, e: # If validation raises a ValueError, we should delete the file and raise os.remove(iso.storage_path) return {'success_flag': False, 'summary': e.message, 'details': None}
def test_validate(self): """ Assert that validate() raises no Exception when passed correct data. """ destination = os.path.join(self.temp_dir, 'test.txt') try: test_file = open(destination, 'w') test_file.write( "I heard there was this band called 1023MB, they haven't got any gigs yet.") finally: test_file.close() unit = mock.MagicMock() unit.storage_path = destination iso = models.ISO('test.txt', 73, '36891c265290bf4610b488a8eb884d32a29fd17bb9886d899e75f4cf29d3f464', unit) # This should validate, i.e., should not raise any Exception iso.validate()
def test_download_succeeded_honors_validate_units_set_false( self, download_failed): """ We have a setting that makes download validation optional. This test ensures that download_succeeded() honors that setting. """ # In this config, we will set validate_units to False, which should make our # "wrong_checksum" OK config = importer_mocks.get_basic_config( **{ importer_constants.KEY_FEED: 'http://fake.com/iso_feed/', importer_constants.KEY_VALIDATE: False }) iso_sync_run = ISOSyncRun(self.sync_conduit, config) destination = os.path.join(self.temp_dir, 'test.iso') with open(destination, 'w') as test_iso: test_iso.write( 'What happens when you combine a mosquito with a mountain climber? Nothing. You ' 'can\'t cross a vector with a scalar.') unit = MagicMock() unit.storage_path = destination iso = models.ISO('test.txt', 114, 'wrong checksum', unit) iso.url = 'http://fake.com' report = DownloadReport(iso.url, destination, iso) # Let's fake having downloaded the whole file iso.bytes_downloaded = iso.size report.bytes_downloaded = iso.size iso_sync_run.progress_report._state = SyncProgressReport.STATE_ISOS_IN_PROGRESS iso_sync_run.download_succeeded(report) # The sync conduit should have been called to save the unit self.sync_conduit.save_unit.assert_any_call(unit) # The download should not fail self.assertEqual(download_failed.call_count, 0)
def test_download_succeeded_honors_validate_units_set_true( self, download_failed): """ We have a setting that makes download validation optional. This test ensures that download_succeeded() honors that setting. """ # In this config, we will set validate_units to False, which should make our # "wrong_checksum" OK config = importer_mocks.get_basic_config( **{ importer_constants.KEY_FEED: 'http://fake.com/iso_feed/', importer_constants.KEY_VALIDATE: True }) iso_sync_run = ISOSyncRun(self.sync_conduit, config) destination = os.path.join(self.temp_dir, 'test.txt') with open(destination, 'w') as test_file: test_file.write('Boring test data.') unit = MagicMock() unit.storage_path = destination iso = models.ISO('test.txt', 114, 'wrong checksum', unit) iso.url = 'http://fake.com' report = DownloadReport(iso.url, destination, iso) # Let's fake having downloaded the whole file iso.bytes_downloaded = iso.size report.bytes_downloaded = iso.size iso_sync_run.progress_report._state = SyncProgressReport.STATE_ISOS_IN_PROGRESS iso_sync_run.download_succeeded(report) # Because we fail validation, the save_unit step will not be called self.assertEqual(self.sync_conduit.save_unit.call_count, 0) # The download should be marked failed self.assertEqual(download_failed.call_count, 1) download_failed.assert_called_once_with(report)