def test_merge_pkglists_oldstyle_newstyle_different_collection( self, mock_save): """ Assert that new collection is added to the pkglist if the collection is different from the existing one where _pulp_repo_id is absent. """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() # oldstyle erratum does not contain _pulp_repo_id, while the newstyle one does collection_wo_pulp_repo_id = copy.deepcopy( self.collection_wo_pulp_repo_id) existing_erratum.pkglist = [collection_wo_pulp_repo_id] different_collection = copy.deepcopy(self.collection_pulp_repo_id) different_collection['packages'][0]['version'] = '2.0' uploaded_erratum.pkglist = [different_collection] existing_erratum.merge_pkglists_and_save(uploaded_erratum) # make sure additional collection is added self.assertEqual(len(existing_erratum.pkglist), 2) self.assertEqual(existing_erratum.pkglist[1]['packages'][0]['version'], uploaded_erratum.pkglist[0]['packages'][0]['version']) self.assertEqual(existing_erratum.pkglist[1]['_pulp_repo_id'], uploaded_erratum.pkglist[0]['_pulp_repo_id']) # make sure _pulp_repo_id is not added to the existing collection self.assertFalse('_pulp_repo_id' in existing_erratum.pkglist[0])
def test_merge_pkglists_newstyle_same_repo_older(self, mock_update_needed, mock_save): """ Assert that the existing collecton is untouched, if the uploaded erratum is older than the existing one. """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() existing_collection = copy.deepcopy(self.collection_pulp_repo_id) collection_same_repo_id_different_packages = copy.deepcopy( self.collection_pulp_repo_id) collection_same_repo_id_different_packages['packages'][0][ 'version'] = '2.0' existing_erratum.pkglist = [existing_collection] uploaded_erratum.pkglist = [collection_same_repo_id_different_packages] mock_update_needed.return_value = False existing_erratum.merge_pkglists_and_save(uploaded_erratum) # make sure no additional collections are added self.assertEqual(len(existing_erratum.pkglist), 1) # make sure the existing collection is untouched self.assertEqual(existing_erratum.pkglist[0], self.collection_pulp_repo_id)
def test_merge_pkglists_same_repo_older(self, mock_update_needed, mock_errata_obj, mock_pkglist_obj, mock_save): """ Assert that the existing pkglist is untouched, if the uploaded erratum is older than the existing one. """ existing_collection = copy.deepcopy(self.collection) uploaded_collection = copy.deepcopy(self.collection) uploaded_collection['packages'][0]['version'] = '2.0' existing_pkglist_data = { 'errata_id': 'some erratum', 'collections': [existing_collection] } uploaded_erratum_data = { 'errata_id': 'some erratum', 'pkglist': [uploaded_collection] } existing_pkglist = models.ErratumPkglist(**existing_pkglist_data) uploaded_erratum = models.Errata(**uploaded_erratum_data) mock_pkglist_obj.filter.return_value.first.return_value = existing_pkglist mock_errata_obj.filter.return_value.first.return_value = models.Errata( ) mock_update_needed.return_value = False mock_save.side_effect = NotUniqueError errata_controller.create_or_update_pkglist(uploaded_erratum, 'my_repo') # make sure save() is called once since existing pkglist is untouched self.assertEqual(mock_save.call_count, 1) # make sure pkglist on the Erratum model is empty anyway self.assertEqual(uploaded_erratum.pkglist, [])
def test_update_needed_empty_date_uploaded(self): """ Test that an empty uploaded erratum `updated` field returns False. """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() existing_erratum.updated = '2016-01-01 00:00:00 UTC' uploaded_erratum.updated = '' self.assertFalse(existing_erratum.update_needed(uploaded_erratum))
def test_update_needed_different_supported_date_formats(self): """ Assert that the supported datetime format are handled correctly and without any warning """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() existing_erratum.updated = '2015-01-01' uploaded_erratum.updated = '2016-01-01 00:00:00' ret = existing_erratum.update_needed(uploaded_erratum) self.assertTrue(ret)
def test_update_needed_bad_date_uploaded(self): """ Assert that if the `updated` date of the uploaded erratum is in the unknown format, then a ValueError is raised. """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() existing_erratum.updated = '2016-01-01 00:00:00 UTC' uploaded_erratum.updated = 'Fri Apr 1 00:00:00 UTC 2016' self.assertRaises(ValueError, existing_erratum.update_needed, uploaded_erratum)
def test_update_needed_older_erratum(self): """ Assert that if the older erratum is uploaded, then the update is not needed. """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() existing_erratum.updated = '2016-01-01 00:00:00 UTC' uploaded_erratum.updated = '2015-01-01 00:00:00 UTC' ret = existing_erratum.update_needed(uploaded_erratum) self.assertFalse(ret)
def test_update_needed_older_erratum_newer_version(self): """ Assert that if the older erratum is uploaded, but has a newer version then the update is not needed. """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() existing_erratum.updated = '2016-01-01 00:00:00 UTC' existing_erratum.version = 1 uploaded_erratum.updated = '2015-01-01 00:00:00 UTC' uploaded_erratum.version = 2 self.assertFalse(existing_erratum.update_needed(uploaded_erratum))
def test_update_needed_empty_date_uploaded_newer_version(self): """ Test that an empty uploaded erratum `updated` field, but a newer version returns True """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() existing_erratum.updated = '2016-01-01 00:00:00 UTC' existing_erratum.version = 1 uploaded_erratum.updated = '' uploaded_erratum.version = 2 self.assertTrue(existing_erratum.update_needed(uploaded_erratum))
def test_update_needed_empty_date_existing(self): """ Test an empty existing `updated` erratum field. Assert that an empty existing `updated` field is considered older than an uploaded erratum with a valid `updated` field. """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() existing_erratum.updated = '' uploaded_erratum.updated = '2016-04-01 00:00:00 UTC' self.assertTrue(existing_erratum.update_needed(uploaded_erratum))
def test_update_needed_same_updated_erratum_newer_version(self): """ Assert that if the updated times of 2 erratum are the same but one has a newer version then the update is needed. """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() existing_erratum.updated = '2016-01-01 00:00:00 UTC' existing_erratum.version = 1 uploaded_erratum.updated = '2016-01-01 00:00:00 UTC' uploaded_erratum.version = 2 self.assertTrue(existing_erratum.update_needed(uploaded_erratum))
def test_merge_preserves_reboot_needed(self, mock_update_needed): """ Test that the reboot_suggested value is preserved when both are True. """ existing_erratum, new_erratum = models.Errata(), models.Errata() mock_update_needed.return_value = False existing_erratum.reboot_suggested = True new_erratum.reboot_suggested = True existing_erratum.merge_errata(new_erratum) self.assertTrue(existing_erratum.reboot_suggested)
def test_merge_fixes_reboot_needed(self, mock_update_needed): """ Test that the reboot_suggested value is overwritten by the one on the erratum being merged. """ existing_erratum, new_erratum = models.Errata(), models.Errata() mock_update_needed.return_value = False existing_erratum.reboot_suggested = True new_erratum.reboot_suggested = False existing_erratum.merge_errata(new_erratum) self.assertFalse(existing_erratum.reboot_suggested)
def test_update_needed_bad_date_uploaded(self): """ Assert that if the `updated` date of the uploaded erratum is in the unknown format, then the PulpCodedValidationException is raised. """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() existing_erratum.updated = '2016-01-01 00:00:00 UTC' uploaded_erratum.updated = 'Fri Apr 1 00:00:00 UTC 2016' with self.assertRaisesRegexp(PulpCodedValidationException, 'uploaded erratum') as cm: existing_erratum.update_needed(uploaded_erratum) self.assertEqual('RPM1007', cm.exception.error_code.code)
def test_rpm_search_dicts_sanitizes_checksum_type_sums( self, mock_erratumpkglist_objects): """ Assert that the rpm_search_dicts() method properly sanitizes checksum types with the sum is specified with the 'type' attribute. """ errata = models.Errata() errata_pkglist = models.ErratumPkglist() errata_pkglist.collections = [{ 'packages': [{ 'name': 'name', 'epoch': '0', 'version': '0.0', 'sums': ['sum1', 'sum2'], 'release': 'release', 'arch': 'arch', 'type': 'sha' }] }] mock_erratumpkglist_objects.return_value = [errata_pkglist] ret = errata.rpm_search_dicts self.assertEqual(len(ret), 1) self.assertEqual(ret[0]['checksumtype'], 'sha1')
def test_check_packages_different_length(self): """Assert that not equal lists of packages are compared properly.""" erratum = models.Errata() other_packages = [] ret = erratum._check_packages(self.existing_packages, other_packages) self.assertFalse(ret)
def test_check_packages_equal(self): """Assert that equal lists of packages are compared properly.""" erratum = models.Errata() other_packages = copy.deepcopy(self.existing_packages) ret = erratum._check_packages(self.existing_packages, other_packages) self.assertTrue(ret)
def test_rpm_search_dicts_no_checksum(self, mock_erratumpkglist_objects): """ Assert that the rpm_search_dicts() method tolerates a missing checksumtype, as is found when using this demo repo: https://repos.fedorapeople.org/repos/pulp/pulp/demo_repos/zoo/ """ errata = models.Errata() errata_pkglist = models.ErratumPkglist() errata_pkglist.collections = [{ 'packages': [{ 'name': 'foo', 'epoch': '0', 'version': '0.0', 'sum': None, 'release': 'release', 'arch': 'arch' }] }] mock_erratumpkglist_objects.return_value = [errata_pkglist] ret = errata.rpm_search_dicts # sanity-check that there is one result with the correct name self.assertEqual(len(ret), 1) self.assertEqual(ret[0]['name'], 'foo') # make sure this field is still not present self.assertTrue('checksumtype' not in ret[0])
def test_merge_errata_newer_erratum(self, mock_update_needed, mock_merge_pkglists): """ Assert that the existing erratum is updated if the uploaded erratum is newer. """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() mock_update_needed.return_value = True existing_erratum.mutable_erratum_fields = ('field1', 'field2') existing_erratum.field1 = 'existing field1' existing_erratum.field2 = 'existing field2' uploaded_erratum.field1 = 'uploaded field1' uploaded_erratum.field2 = 'uploaded field2' existing_erratum.merge_errata(uploaded_erratum) # make sure the erratum metadata is updated self.assertEqual(existing_erratum.field1, uploaded_erratum.field1) self.assertEqual(existing_erratum.field2, uploaded_erratum.field2)
def test_merge_errata_older_erratum(self, mock_update_needed): """ Assert that the existing erratum is not updated if the uploaded erratum is older. """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() mock_update_needed.return_value = False existing_erratum.mutable_erratum_fields = ('field1', 'field2') existing_erratum.field1 = 'existing field1' existing_erratum.field2 = 'existing field2' uploaded_erratum.field1 = 'uploaded field1' uploaded_erratum.field2 = 'uploaded field2' existing_erratum.merge_errata(uploaded_erratum) # make sure the existing erratum is not changed self.assertNotEqual(existing_erratum.field1, uploaded_erratum.field1) self.assertNotEqual(existing_erratum.field2, uploaded_erratum.field2)
def _generate_erratum_unit(self): """ Generate erratum unit. """ packages = [{ 'src': 'pulp-test-package-0.3.1-1.fc22.src.rpm', 'name': 'pulp-test-package', 'arch': 'x86_64', 'sums': 'sums', 'filename': 'pulp-test-package-0.3.1-1.fc22.x86_64.rpm', 'epoch': '0', 'version': '0.3.1', 'release': '1.fc22', 'type': 'sha256' }] unit_data = { 'errata_id': 'RHSA-2014:0042', 'title': 'Some Title', 'release': '2', 'rights': 'You have the right to remain silent.', 'solution': 'Open Source is the solution to your problems.', 'severity': 'High', 'summary': 'A Summary', # Note that pushcount is an int. This should be OK (no exceptions). 'pushcount': 1, 'status': 'symbol', 'type': 'security', 'version': '2.4.1', 'issued': '2014-05-27 00:00:00', 'references': [{ 'href': 'https://bugzilla.hostname/bug.cgi?id=XXXXX', 'type': 'bugzilla', 'id': 'XXXXX', 'title': 'some title' }], 'updated': '2014-05-28 00:00:00', 'pkglist': [{ 'packages': packages, 'name': 'test-name', 'short': '' }, { 'packages': packages, 'name': 'test-name', 'short': '' }] } return models.Errata(**unit_data)
def test_check_packages_not_equal(self): """Assert that not equal lists of packages are compared properly.""" erratum = models.Errata() other_packages = copy.deepcopy(self.existing_packages) other_packages[0]["version"] = "0.3.2" ret = erratum._check_packages(self.existing_packages, other_packages) self.assertFalse(ret)
def test_merge_pkglists_newstyle_new_collection(self, mock_save): """ Assert that new collection is added to the pkglist if the collection has different name. """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() existing_collection = copy.deepcopy(self.collection_pulp_repo_id) new_collection = copy.deepcopy(self.collection_pulp_repo_id) new_collection['name'] = 'new test-name' existing_erratum.pkglist = [existing_collection] uploaded_erratum.pkglist = [new_collection] existing_erratum.merge_pkglists_and_save(uploaded_erratum) # make sure additional collection is added self.assertEqual(len(existing_erratum.pkglist), 2) self.assertEqual(existing_erratum.pkglist[0]['name'], self.collection_pulp_repo_id['name']) self.assertEqual(existing_erratum.pkglist[1]['name'], uploaded_erratum.pkglist[0]['name'])
def test_merge_pkglists_oldstyle_newstyle_same_collection(self, mock_save): """ Assert that _pulp_repo_id is added to the collection if it was absent and collection in the uploaded erratum is the same as in the existing one. """ existing_erratum, uploaded_erratum = models.Errata(), models.Errata() # oldstyle erratum does not contain _pulp_repo_id, while the newstyle one does collection_wo_pulp_repo_id = copy.deepcopy(self.collection_wo_pulp_repo_id) existing_erratum.pkglist = [collection_wo_pulp_repo_id] uploaded_erratum.pkglist = [self.collection_pulp_repo_id] existing_erratum.merge_pkglists_and_save(uploaded_erratum) # make sure no additional collections are added self.assertEqual(len(existing_erratum.pkglist), 1) # make sure _pulp_repo_id is added to the existing collection self.assertEqual(existing_erratum.pkglist[0]['_pulp_repo_id'], uploaded_erratum.pkglist[0]['_pulp_repo_id']) # make sure save() is called self.assertEqual(mock_save.call_count, 2)
def test_rpm_search_dicts_sanitizes_checksum_type_sum(self): """ Assert that the rpm_search_dicts() method properly sanitizes checksum types with the sum is specified with the 'sum' attribute. """ errata = models.Errata() errata.pkglist = [ {'packages': [ {'name': 'name', 'epoch': '0', 'version': '0.0', 'sum': ['sha', 'sum'], 'release': 'release', 'arch': 'arch'}]}] ret = errata.rpm_search_dicts self.assertEqual(len(ret), 1) self.assertEqual(ret[0]['checksumtype'], 'sha1')
def errata_models(num): ret = [] count = _errata_counter.next() for i in range(num): rpms = [r.unit_key for r in rpm_models(2)] for r in rpms: del r['checksum'] del r['checksumtype'] ret.append( models.Errata('name-%d' % count, { 'pkglist': [{ 'packages': rpms, 'name': 'somerepo-%d' % count }] })) count = _errata_counter.next() return ret
def test_new_pkglist(self, mock_update_needed, mock_errata_obj, mock_pkglist_obj, mock_save): """ Assert that new pkglist is created if there is no existing one. """ uploaded_collection = copy.deepcopy(self.collection) uploaded_erratum_data = { 'errata_id': 'some erratum', 'pkglist': [uploaded_collection] } uploaded_erratum = models.Errata(**uploaded_erratum_data) errata_controller.create_or_update_pkglist(uploaded_erratum, 'my_repo') # make sure save() is called once self.assertEqual(mock_save.call_count, 1) # make sure pkglist on the Erratum model is empty self.assertEqual(uploaded_erratum.pkglist, [])
def test_merge_pkglists_same_repo_newer(self, mock_update_needed, mock_errata_obj, mock_pkglist_obj, mock_save): """ Assert that the existing pkglist is overwritten, if the uploaded erratum is newer than the existing one. """ existing_collection = copy.deepcopy(self.collection) uploaded_collection = copy.deepcopy(self.collection) uploaded_collection['packages'][0]['version'] = '2.0' existing_pkglist_data = { 'errata_id': 'some erratum', 'collections': [existing_collection] } uploaded_erratum_data = { 'errata_id': 'some erratum', 'pkglist': [uploaded_collection] } existing_pkglist = models.ErratumPkglist(**existing_pkglist_data) uploaded_erratum = models.Errata(**uploaded_erratum_data) mock_pkglist_obj.filter.return_value.first.return_value = existing_pkglist mock_update_needed.return_value = True mock_save.side_effect = [NotUniqueError, None] errata_controller.create_or_update_pkglist(uploaded_erratum, 'my_repo') # make sure the existing collection is changed self.assertEqual( existing_pkglist.collections[0]['packages'][0]['version'], uploaded_collection['packages'][0]['version']) # make sure save() is called twice since existing pkglist was updated self.assertEqual(mock_save.call_count, 2) # make sure pkglist on the Erratum model is empty self.assertEqual(uploaded_erratum.pkglist, [])
def process_package_element(element): """ Process one XML block from updateinfo.xml and return a dict describing and errata :param element: object representing one "errata" block from the XML file :type element: xml.etree.ElementTree.Element :return: dictionary describing an errata :rtype: dict """ description_element = element.find('description') if description_element is not None: description_text = description_element.text else: description_text = '' package_info = { 'description': description_text, 'errata_from': element.attrib['from'], 'errata_id': element.find('id').text, 'issued': '', 'pushcount': '', # yum defaults this to False, and sets it to True if any package in # any collection has an element present with tag 'reboot_suggested'. # Note that yum, as of 3.4.3, does not check the contents of that element. 'reboot_suggested': False, 'references': map(_parse_reference, element.find('references') or []), 'release': '', 'rights': '', 'pkglist': map(_parse_collection, element.find('pkglist') or []), 'severity': '', 'solution': '', 'status': element.attrib['status'], 'summary': '', 'title': element.find('title').text, 'type': element.attrib['type'], 'updated': '', 'version': element.attrib['version'], } # see comment above about 'reboot_suggested' to explain this behavior for collection in package_info['pkglist']: for package in collection['packages']: if package.get('reboot_suggested') is not None: package_info['reboot_suggested'] = True break for attr_name in ('rights', 'severity', 'summary', 'solution', 'release', 'pushcount'): child = element.find(attr_name) if child is not None: package_info[attr_name] = child.text issued_element = element.find('issued') if issued_element is not None: package_info['issued'] = issued_element.attrib['date'] updated_element = element.find('updated') if updated_element is not None: package_info['updated'] = updated_element.attrib['date'] return models.Errata(**package_info)