def test_afterCompletion_COMMITTED(self): txn = FakeTransaction() txn.status = TransactionStatus.COMMITTED fake_session = FakeRabbitSession() sync = RabbitSessionTransactionSync(fake_session) sync.afterCompletion(txn) self.assertEqual(["finish"], fake_session.log)
def test_afterCompletion_ACTIVE(self): txn = FakeTransaction() txn.status = TransactionStatus.ACTIVE fake_session = FakeRabbitSession() sync = RabbitSessionTransactionSync(fake_session) sync.afterCompletion(txn) self.assertEqual(["reset"], fake_session.log)
def test_publishArchive_honours_disable_options(self): # The various --disable-* options disable the corresponding # publisher steps. possible_options = { "--disable-publishing": ["A_publish"], "--disable-domination": [ "A2_markPocketsWithDeletionsDirty", "B_dominate", ], "--disable-apt": ["C_doFTPArchive", "createSeriesAliases"], "--disable-release": ["D_writeReleaseFiles"], } for option in possible_options: distro = self.makeDistro() script = self.makeScript(distro, args=[option]) script.txn = FakeTransaction() publisher = FakePublisher() script.publishArchive(FakeArchive(), publisher) for check_option, steps in possible_options.items(): for step in steps: publisher_step = getattr(publisher, step) if check_option == option: self.assertEqual(0, publisher_step.call_count) else: self.assertEqual(1, publisher_step.call_count)
def test_dominate_imported_source_packages_dominates_deletions(self): # dominate_imported_source_packages dominates the source # packages that have been deleted from the Sources lists that # Gina imports. series = self.factory.makeDistroSeries() pocket = PackagePublishingPocket.RELEASE package = self.factory.makeSourcePackageName() pubs = [ self.factory.makeSourcePackagePublishingHistory( archive=series.main_archive, distroseries=series, pocket=pocket, status=PackagePublishingStatus.PUBLISHED, sourcepackagerelease=self.factory.makeSourcePackageRelease( sourcepackagename=package, version=version)) for version in ['1.0', '1.1', '1.1a']] # In this scenario, 1.0 is a superseded release. pubs[0].supersede() logger = DevNullLogger() txn = FakeTransaction() dominate_imported_source_packages( txn, logger, series.distribution.name, series.name, pocket, FakePackagesMap({})) # The older, superseded release stays superseded; but the # releases that dropped out of the imported Sources list without # known successors are marked deleted. self.assertPublishingStates( pubs, [PackagePublishingStatus.SUPERSEDED, PackagePublishingStatus.DELETED, PackagePublishingStatus.DELETED])
def _getKeyGenerator(self, archive_reference=None, txn=None): """Return a `PPAKeyGenerator` instance. Monkey-patch the script object with a fake transaction manager and also make it use an alternative (fake and lighter) procedure to generate keys for each PPA. """ test_args = [] if archive_reference is not None: test_args.extend(['-A', archive_reference]) key_generator = PPAKeyGenerator( name='ppa-generate-keys', test_args=test_args) if txn is None: txn = FakeTransaction() key_generator.txn = txn def fake_key_generation(archive): a_key = getUtility(IGPGKeySet).getByFingerprint( 'ABCDEF0123456789ABCDDCBA0000111112345678') archive.signing_key_fingerprint = a_key.fingerprint archive.signing_key_owner = a_key.owner del get_property_cache(archive).signing_key key_generator.generateKey = fake_key_generation return key_generator
class TestCopying(TestCase): layer = LaunchpadZopelessLayer txn = FakeTransaction() def test_flagsHandling(self): """Flags are correctly restored, no matter what their values.""" sid = getUtility(IDistributionSet)['debian']['sid'] sid.hide_all_translations = True sid.defer_translation_imports = True copy_distroseries_translations(sid, self.txn, logging) self.assertTrue(sid.hide_all_translations) self.assertTrue(sid.defer_translation_imports) sid.hide_all_translations = True sid.defer_translation_imports = False copy_distroseries_translations(sid, self.txn, logging) self.assertTrue(sid.hide_all_translations) self.assertFalse(sid.defer_translation_imports) sid.hide_all_translations = False sid.defer_translation_imports = True copy_distroseries_translations(sid, self.txn, logging) self.assertFalse(sid.hide_all_translations) self.assertTrue(sid.defer_translation_imports) sid.hide_all_translations = False sid.defer_translation_imports = False copy_distroseries_translations(sid, self.txn, logging) self.assertFalse(sid.hide_all_translations) self.assertFalse(sid.defer_translation_imports)
def _getKeyGenerator(self, ppa_owner_name=None, txn=None): """Return a `PPAKeyGenerator` instance. Monkey-patch the script object with a fake transaction manager and also make it use an alternative (fake and lighter) procedure to generate keys for each PPA. """ test_args = [] if ppa_owner_name is not None: test_args.extend(['-p', ppa_owner_name]) key_generator = PPAKeyGenerator(name='ppa-generate-keys', test_args=test_args) if txn is None: txn = FakeTransaction() key_generator.txn = txn def fake_key_generation(archive): a_key = getUtility(IGPGKeySet).get(1) archive.signing_key = a_key key_generator.generateKey = fake_key_generation return key_generator
def test_dominate_imported_source_packages_dominates_imports(self): # dominate_imported_source_packages dominates the source # packages that Gina imports. logger = DevNullLogger() txn = FakeTransaction() series = self.factory.makeDistroSeries() pocket = PackagePublishingPocket.RELEASE package = self.factory.makeSourcePackageName() # Realistic situation: there's an older, superseded publication; # a series of active ones; and a newer, pending publication # that's not in the Sources lists yet. # Gina dominates the Published ones and leaves the rest alone. old_spph = self.factory.makeSourcePackagePublishingHistory( distroseries=series, archive=series.main_archive, pocket=pocket, status=PackagePublishingStatus.SUPERSEDED, sourcepackagerelease=self.factory.makeSourcePackageRelease( sourcepackagename=package, version='1.0')) active_spphs = [ self.factory.makeSourcePackagePublishingHistory( distroseries=series, archive=series.main_archive, pocket=pocket, status=PackagePublishingStatus.PUBLISHED, sourcepackagerelease=self.factory.makeSourcePackageRelease( sourcepackagename=package, version=version)) for version in ['1.1', '1.1.1', '1.1.1.1'] ] new_spph = self.factory.makeSourcePackagePublishingHistory( distroseries=series, archive=series.main_archive, pocket=pocket, status=PackagePublishingStatus.PENDING, sourcepackagerelease=self.factory.makeSourcePackageRelease( sourcepackagename=package, version='1.2')) spphs = [old_spph] + active_spphs + [new_spph] # Of the active publications, in this scenario, only one version # matches what Gina finds in the Sources list. It stays # published; older active publications are superseded, newer # ones deleted. dominate_imported_source_packages( txn, logger, series.distribution.name, series.name, pocket, FakePackagesMap({package.name: [{ 'Version': '1.1.1' }]})) self.assertEqual([ PackagePublishingStatus.SUPERSEDED, PackagePublishingStatus.SUPERSEDED, PackagePublishingStatus.PUBLISHED, PackagePublishingStatus.DELETED, PackagePublishingStatus.PENDING, ], [pub.status for pub in spphs])
def test_publishArchive_uses_apt_ftparchive_for_main_archive(self): # For some types of archive, publishArchive invokes the # publisher's C_doFTPArchive method as a way of generating # indexes. distro = self.makeDistro() script = self.makeScript(distro) script.txn = FakeTransaction() publisher = FakePublisher() script.publishArchive(FakeArchive(), publisher) self.assertEqual(1, publisher.C_doFTPArchive.call_count) self.assertEqual(0, publisher.C_writeIndexes.call_count)
def test_publishArchive_writes_own_indexes_for_ppa(self): # For some types of archive, publishArchive invokes the # publisher's C_writeIndexes as an alternative to # C_doFTPArchive. distro = self.makeDistro() script = self.makeScript(distro) script.txn = FakeTransaction() publisher = FakePublisher() script.publishArchive(FakeArchive(ArchivePurpose.PPA), publisher) self.assertEqual(0, publisher.C_doFTPArchive.call_count) self.assertEqual(1, publisher.C_writeIndexes.call_count)
def makeScript(self, distribution=None, run_setup=True): """Create a script for testing.""" if distribution is None: distribution = self.makeDistro() script = GenerateContentsFiles(test_args=['-d', distribution.name]) script.logger = DevNullLogger() script.txn = FakeTransaction() if run_setup: script.setUp() else: script.distribution = distribution return script
def test_does_not_overwrite_existing_pofile(self): # Sometimes a POFile we're about to copy to a new distroseries # has already been created there due to message sharing. In # that case, the copying code leaves the existing POFile in # place and does not copy it. (Nor does it raise an error.) existing_series = self.factory.makeDistroSeries(name='existing') new_series = self.factory.makeDistroSeries( name='new', distribution=existing_series.distribution, previous_series=existing_series) template = self.factory.makePOTemplate(distroseries=existing_series) pofile = self.factory.makePOFile(potemplate=template) self.factory.makeCurrentTranslationMessage( language=pofile.language, potmsgset=self.factory.makePOTMsgSet(potemplate=template)) # Sabotage the pouring code so that when it's about to hit the # POFile table, it returns to us and we can simulate a race # condition. pour_table = MultiTableCopy._pourTable def pour_or_stop_at_pofile(self, holding_table, table, *args, **kwargs): args = (self, holding_table, table) + args if table.lower() == "pofile": raise EarlyExit(*args, **kwargs) else: return pour_table(*args, **kwargs) MultiTableCopy._pourTable = pour_or_stop_at_pofile try: copy_active_translations(new_series, FakeTransaction(), DevNullLogger()) except EarlyExit as e: pour_args = e.args pour_kwargs = e.kwargs finally: MultiTableCopy._pourTable = pour_table # Simulate another POFile being created for new_series while the # copier was working. new_template = new_series.getTranslationTemplateByName(template.name) new_pofile = self.factory.makePOFile(potemplate=new_template, language=pofile.language) # Now continue pouring the POFile table. pour_table(*pour_args, **pour_kwargs) # The POFile we just created in our race condition stays in # place. There is no error. resulting_pofile = new_template.getPOFileByLang(pofile.language.code) self.assertEqual(new_pofile, resulting_pofile)
def test_publishArchive_drives_publisher(self): # publishArchive puts a publisher through its paces. This work # ought to be in the publisher itself, so if you find this way # of doing things annoys you, that's your cue to help clean up! distro = self.makeDistro() script = self.makeScript(distro) script.txn = FakeTransaction() publisher = FakePublisher() script.publishArchive(FakeArchive(), publisher) self.assertEqual(1, publisher.A_publish.call_count) self.assertEqual(1, publisher.A2_markPocketsWithDeletionsDirty.call_count) self.assertEqual(1, publisher.B_dominate.call_count) self.assertEqual(1, publisher.D_writeReleaseFiles.call_count)
def makeScript(self, distribution, run_setup=True, extra_args=None): """Create a script for testing.""" test_args = [] if distribution is not None: test_args.extend(["-d", distribution.name]) if extra_args is not None: test_args.extend(extra_args) script = GenerateExtraOverrides(test_args=test_args) script.logger = DevNullLogger() script.txn = FakeTransaction() if distribution is not None and run_setup: script.setUp() else: script.distribution = distribution return script
def testGenerateKeyForASinglePPA(self): """Signing key generation for a single PPA. The 'signing_key' for the specified PPA is generated and the transaction is committed once. """ cprov = getUtility(IPersonSet).getByName('cprov') self._fixArchiveForKeyGeneration(cprov.archive) self.assertTrue(cprov.archive.signing_key is None) txn = FakeTransaction() key_generator = self._getKeyGenerator(ppa_owner_name='cprov', txn=txn) key_generator.main() self.assertTrue(cprov.archive.signing_key is not None) self.assertEquals(txn.commit_count, 1)
def testGenerateKeyForAllPPA(self): """Signing key generation for all PPAs. The 'signing_key' for all 'pending-signing-key' PPAs are generated and the transaction is committed once for each PPA. """ archives = list(getUtility(IArchiveSet).getPPAsPendingSigningKey()) for archive in archives: self._fixArchiveForKeyGeneration(archive) self.assertTrue(archive.signing_key is None) txn = FakeTransaction() key_generator = self._getKeyGenerator(txn=txn) key_generator.main() for archive in archives: self.assertTrue(archive.signing_key is not None) self.assertEqual(txn.commit_count, len(archives))
def test_publishes_only_selected_archives(self): # The script publishes only the archives returned by # getTargetArchives, for the distributions returned by # findDistros. distro = self.makeDistro() # The script gets a distribution and archive of its own, to # prove that any distros and archives other than what # findDistros and getTargetArchives return are ignored. script = self.makeScript() script.txn = FakeTransaction() script.findDistros = FakeMethod([distro]) archive = FakeArchive() script.getTargetArchives = FakeMethod([archive]) publisher = FakePublisher() script.getPublisher = FakeMethod(publisher) script.publishArchive = FakeMethod() script.main() [(args, kwargs)] = script.getPublisher.calls distro_arg, archive_arg = args[:2] self.assertEqual(distro, distro_arg) self.assertEqual(archive, archive_arg) self.assertEqual([((archive, publisher), {})], script.publishArchive.calls)
def test_dominate_imported_sources_dominates_supported_series(self): series = self.factory.makeDistroSeries() pocket = PackagePublishingPocket.RELEASE package = self.factory.makeSourcePackageName() pubs = [ self.factory.makeSourcePackagePublishingHistory( archive=series.main_archive, distroseries=series, pocket=pocket, status=PackagePublishingStatus.PUBLISHED, sourcepackagerelease=self.factory.makeSourcePackageRelease( sourcepackagename=package, version=version)) for version in ['1.0', '1.1', '1.1a']] # In this scenario, 1.0 is a superseded release. pubs[0].supersede() # Now set the series to SUPPORTED. series.status = SeriesStatus.SUPPORTED logger = DevNullLogger() txn = FakeTransaction() dominate_imported_source_packages( txn, logger, series.distribution.name, series.name, pocket, FakePackagesMap({})) self.assertPublishingStates( pubs, [PackagePublishingStatus.SUPERSEDED, PackagePublishingStatus.DELETED, PackagePublishingStatus.DELETED])
def runScript( self, archive_name=None, suite='hoary', user='******', exists_before=None, exists_after=None, exception_type=None, exception_text=None, extra_args=None, copy_archive_name=None, reason=None, output_substr=None, nonvirtualized=False): """Run the script to test. :type archive_name: `str` :param archive_name: the name of the copy archive to create. :type suite: `str` :param suite: the name of the copy archive suite. :type user: `str` :param user: the name of the user creating the archive. :type exists_before: `bool` :param exists_before: copy archive with given name should already exist if True. :type exists_after: `True` :param exists_after: the copy archive is expected to exist after script invocation if True. :type exception_type: type :param exception_type: the type of exception expected in case of failure. :type exception_text: `str` :param exception_text: expected exception text prefix in case of failure. :type extra_args: list of strings :param extra_args: additional arguments to be passed to the script (if any). :type copy_archive_name: `IArchive` :param copy_archive_name: optional copy archive instance, used for merge copy testing. :param reason: if empty do not provide '--reason' cmd line arg to the script :param output_substr: this must be part of the script's output """ if copy_archive_name is None: now = int(time.time()) if archive_name is None: archive_name = "ra%s" % now else: archive_name = copy_archive_name distro_name = 'ubuntu' distro = getUtility(IDistributionSet).getByName(distro_name) copy_archive = getUtility(IArchiveSet).getByDistroPurpose( distro, ArchivePurpose.COPY, archive_name) # Enforce these assertions only if the 'exists_before' flag was # specified in first place. if exists_before is not None: if exists_before: self.assertTrue(copy_archive is not None) else: self.assertTrue(copy_archive is None) # Command line arguments required for the invocation of the # 'populate-archive.py' script. script_args = [ '--from-distribution', distro_name, '--from-suite', suite, '--to-distribution', distro_name, '--to-suite', suite, '--to-archive', archive_name, '--to-user', user, ] # Empty reason string indicates that the '--reason' command line # argument should be ommitted. if reason is not None and not reason.isspace(): script_args.extend(['--reason', reason]) elif reason is None: reason = "copy archive, %s" % datetime.ctime(datetime.utcnow()) script_args.extend(['--reason', reason]) if nonvirtualized: script_args.append('--nonvirtualized') if extra_args is not None: script_args.extend(extra_args) script = ArchivePopulator( 'populate-archive', dbuser=config.uploader.dbuser, test_args=script_args) script.logger = BufferLogger() script.txn = FakeTransaction() if exception_type is not None: self.assertRaisesWithContent( exception_type, exception_text, script.mainTask) else: script.mainTask() # Does the script's output contain the specified sub-string? if output_substr is not None and not output_substr.isspace(): output = script.logger.getLogBuffer() self.assertTrue(output_substr in output) copy_archive = getUtility(IArchiveSet).getByDistroPurpose( distro, ArchivePurpose.COPY, archive_name) # Enforce these assertions only if the 'exists_after' flag was # specified in first place. if exists_after is not None: if exists_after: self.assertTrue(copy_archive is not None) else: self.assertTrue(copy_archive is None) return copy_archive
class TestCopying(TestCaseWithFactory): layer = LaunchpadZopelessLayer txn = FakeTransaction() def test_flagsHandling(self): """Flags are correctly restored, no matter what their values.""" sid = getUtility(IDistributionSet)['debian']['sid'] source = sid.previous_series sid.hide_all_translations = True sid.defer_translation_imports = True copy_distroseries_translations(source, sid, self.txn, logging) self.assertTrue(sid.hide_all_translations) self.assertTrue(sid.defer_translation_imports) sid.hide_all_translations = True sid.defer_translation_imports = False copy_distroseries_translations(source, sid, self.txn, logging) self.assertTrue(sid.hide_all_translations) self.assertFalse(sid.defer_translation_imports) sid.hide_all_translations = False sid.defer_translation_imports = True copy_distroseries_translations(source, sid, self.txn, logging) self.assertFalse(sid.hide_all_translations) self.assertTrue(sid.defer_translation_imports) sid.hide_all_translations = False sid.defer_translation_imports = False copy_distroseries_translations(source, sid, self.txn, logging) self.assertFalse(sid.hide_all_translations) self.assertFalse(sid.defer_translation_imports) def test_published_packages_only(self): # copy_distroseries_translations's published_sources_only flag # restricts the copied templates to those with a corresponding # published source package in the target. distro = self.factory.makeDistribution(name='notbuntu') dapper = self.factory.makeDistroSeries(distribution=distro, name='dapper') spns = [self.factory.makeSourcePackageName() for i in range(3)] for spn in spns: self.factory.makePOTemplate(distroseries=dapper, sourcepackagename=spn) def get_template_spns(series): return [ pot.sourcepackagename for pot in getUtility(IPOTemplateSet).getSubset( distroseries=series) ] # Create a fresh series with two sources published. edgy = self.factory.makeDistroSeries(distribution=distro, name='edgy') self.factory.makeSourcePackagePublishingHistory( archive=edgy.main_archive, distroseries=edgy, sourcepackagename=spns[0], status=PackagePublishingStatus.PUBLISHED) self.factory.makeSourcePackagePublishingHistory( archive=edgy.main_archive, distroseries=edgy, sourcepackagename=spns[2], status=PackagePublishingStatus.PENDING) self.assertContentEqual(spns, get_template_spns(dapper)) self.assertContentEqual([], get_template_spns(edgy)) copy_distroseries_translations(dapper, edgy, self.txn, logging, published_sources_only=True) self.assertContentEqual([spns[0], spns[2]], get_template_spns(edgy)) def test_published_packages_only_different_archive(self): # If an archive parameter is passed, # copy_distroseries_translations's published_sources_only flag # checks source package publications in that archive rather than in # the target's main archive. distro = self.factory.makeDistribution(name='notbuntu') dapper = self.factory.makeDistroSeries(distribution=distro, name='dapper') spns = [self.factory.makeSourcePackageName() for i in range(3)] for spn in spns: self.factory.makePOTemplate(distroseries=dapper, sourcepackagename=spn) ppa = self.factory.makeArchive(purpose=ArchivePurpose.PPA) def get_template_spns(series): return [ pot.sourcepackagename for pot in getUtility(IPOTemplateSet).getSubset( distroseries=series) ] edgy = self.factory.makeDistroSeries(distribution=distro, name='edgy') edgy_derived = self.factory.makeDistroSeries( distribution=ppa.distribution, name='edgy-derived') self.factory.makeSourcePackagePublishingHistory( archive=ppa, distroseries=edgy_derived, sourcepackagename=spns[0], status=PackagePublishingStatus.PUBLISHED) self.factory.makeSourcePackagePublishingHistory( archive=edgy.main_archive, distroseries=edgy, sourcepackagename=spns[1], status=PackagePublishingStatus.PUBLISHED) self.factory.makeSourcePackagePublishingHistory( archive=ppa, distroseries=edgy_derived, sourcepackagename=spns[2], status=PackagePublishingStatus.PENDING) self.assertContentEqual(spns, get_template_spns(dapper)) self.assertContentEqual([], get_template_spns(edgy)) copy_distroseries_translations(dapper, edgy, self.txn, logging, published_sources_only=True, check_archive=ppa, check_distroseries=edgy_derived) self.assertContentEqual([spns[0], spns[2]], get_template_spns(edgy))
def makeScript(self, test_args): script = SuspendBotAccountScript(test_args=test_args) script.logger = DevNullLogger() script.txn = FakeTransaction() return script