def test_retry_delay(self): # The job is retried every minute, unless it just made one of its # first four attempts to poll the status endpoint, in which case the # delays are 15/15/30/30 seconds. self.useFixture(FakeLogger()) snapbuild = self.makeSnapBuild() job = SnapStoreUploadJob.create(snapbuild) client = FakeSnapStoreClient() client.upload.failure = UploadFailedResponse("Proxy error", can_retry=True) self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient)) with dbuser(config.ISnapStoreUploadJobSource.dbuser): JobRunner([job]).runAll() self.assertNotIn("status_url", job.metadata) self.assertEqual(timedelta(seconds=60), job.retry_delay) job.scheduled_start = None client.upload.failure = None client.upload.result = self.status_url client.checkStatus.failure = UploadNotScannedYetResponse() for expected_delay in (15, 15, 30, 30, 60): with dbuser(config.ISnapStoreUploadJobSource.dbuser): JobRunner([job]).runAll() self.assertIn("status_url", job.snapbuild.store_upload_metadata) self.assertIsNone(job.store_url) self.assertEqual(timedelta(seconds=expected_delay), job.retry_delay) job.scheduled_start = None client.checkStatus.failure = None client.checkStatus.result = (self.store_url, 1) with dbuser(config.ISnapStoreUploadJobSource.dbuser): JobRunner([job]).runAll() self.assertEqual(self.store_url, job.store_url) self.assertIsNone(job.error_message) self.assertEqual([], pop_notifications()) self.assertEqual(JobStatus.COMPLETED, job.job.status)
def test_triggers_webhooks(self): # On tip change, any relevant webhooks are triggered. self.useFixture(FeatureFixture({"code.bzr.webhooks.enabled": "on"})) self.syncAndCount() old_revid = self.db_branch.last_scanned_id with dbuser(config.launchpad.dbuser): hook = self.factory.makeWebhook(target=self.db_branch, event_types=["bzr:push:0.1"]) self.commitRevision() new_revid = self.bzr_branch.last_revision() self.makeBzrSync(self.db_branch).syncBranchAndClose() delivery = hook.deliveries.one() self.assertThat( delivery, MatchesStructure(event_type=Equals("bzr:push:0.1"), payload=MatchesDict({ "bzr_branch": Equals("/" + self.db_branch.unique_name), "bzr_branch_path": Equals(self.db_branch.shortened_path), "old": Equals({"revision_id": old_revid}), "new": Equals({"revision_id": new_revid}), }))) with dbuser(config.IWebhookDeliveryJobSource.dbuser): self.assertEqual( "<WebhookDeliveryJob for webhook %d on %r>" % (hook.id, hook.target), repr(delivery))
def test_handles_packaging_references(self): person = self.factory.makePerson() person_id = person.id account_id = person.account.id self.factory.makeGPGKey(person) publisher = SoyuzTestPublisher() publisher.person = person ubuntu = getUtility(ILaunchpadCelebrities).ubuntu spph = publisher.getPubSource(status=PackagePublishingStatus.PUBLISHED, distroseries=ubuntu.currentseries, maintainer=person, creator=person) with dbuser('garbo_frequently'): job = PopulateLatestPersonSourcePackageReleaseCache( DevNullLogger()) while not job.isDone(): job(chunk_size=100) self.assertTrue(person.hasMaintainedPackages()) script = self.makeScript([six.ensure_str(person.name)]) with dbuser('launchpad'): self.runScript(script) self.assertRemoved(account_id, person_id) self.assertEqual(person, spph.package_maintainer) self.assertEqual(person, spph.package_creator) self.assertFalse(person.hasMaintainedPackages())
def test_apply_bugsummary_changes(self): # apply_bugsummary_changes takes a target and a tuple of changes # from calculate_bugsummary_changes and flushes the changes to # the DB. product = self.factory.makeProduct() self.assertContentEqual([], get_bugsummary_rows(product)) NEW = BugTaskStatus.NEW TRIAGED = BugTaskStatus.TRIAGED LOW = BugTaskImportance.LOW HIGH = BugTaskImportance.HIGH # Add a couple of rows to start. with dbuser('bugsummaryrebuild'): apply_bugsummary_changes( product, {(NEW, None, HIGH, False, None, None, None): 2, (TRIAGED, None, LOW, False, None, None, None): 4}, {}, []) self.assertContentEqual( [(NEW, None, HIGH, False, None, None, None, 2), (TRIAGED, None, LOW, False, None, None, None, 4)], get_bugsummary_rows(product)) # Delete one, mutate the other. with dbuser('bugsummaryrebuild'): apply_bugsummary_changes( product, {}, {(NEW, None, HIGH, False, None, None, None): 3}, [(TRIAGED, None, LOW, False, None, None, None)]) self.assertContentEqual( [(NEW, None, HIGH, False, None, None, None, 3)], get_bugsummary_rows(product))
def test_triggers_webhooks(self): # Jobs trigger any relevant webhooks when they're enabled. self.useFixture(FeatureFixture({'code.git.webhooks.enabled': 'on'})) repository = self.factory.makeGitRepository() self.factory.makeGitRefs( repository, paths=['refs/heads/master', 'refs/tags/1.0']) hook = self.factory.makeWebhook( target=repository, event_types=['git:push:0.1']) job = GitRefScanJob.create(repository) paths = ('refs/heads/master', 'refs/tags/2.0') self.useFixture(GitHostingFixture(refs=self.makeFakeRefs(paths))) with dbuser('branchscanner'): JobRunner([job]).runAll() delivery = hook.deliveries.one() sha1 = lambda s: hashlib.sha1(s).hexdigest() self.assertThat( delivery, MatchesStructure( event_type=Equals('git:push:0.1'), payload=MatchesDict({ 'git_repository': Equals('/' + repository.unique_name), 'git_repository_path': Equals(repository.unique_name), 'ref_changes': Equals({ 'refs/tags/1.0': { 'old': {'commit_sha1': sha1('refs/tags/1.0')}, 'new': None}, 'refs/tags/2.0': { 'old': None, 'new': {'commit_sha1': sha1('refs/tags/2.0')}}, })}))) with dbuser(config.IWebhookDeliveryJobSource.dbuser): self.assertEqual( "<WebhookDeliveryJob for webhook %d on %r>" % ( hook.id, hook.target), repr(delivery))
def test_handles_hardware_submissions(self): person = self.factory.makePerson() submission = self.factory.makeHWSubmission( emailaddress=person.preferredemail.email) other_submission = self.factory.makeHWSubmission() device = getUtility(IHWDeviceSet).getByDeviceID( HWBus.PCI, '0x10de', '0x0455') with dbuser('hwdb-submission-processor'): parent_submission_device = self.factory.makeHWSubmissionDevice( submission, device, None, None, 1) self.factory.makeHWSubmissionDevice(submission, device, None, parent_submission_device, 2) other_submission_device = self.factory.makeHWSubmissionDevice( other_submission, device, None, None, 1) key = submission.submission_key other_key = other_submission.submission_key hw_submission_set = getUtility(IHWSubmissionSet) self.assertNotEqual([], list(hw_submission_set.getByOwner(person))) self.assertEqual(submission, hw_submission_set.getBySubmissionKey(key)) person_id = person.id account_id = person.account.id script = self.makeScript([six.ensure_str(person.name)]) with dbuser('launchpad'): self.runScript(script) self.assertRemoved(account_id, person_id) self.assertEqual([], list(hw_submission_set.getByOwner(person))) self.assertIsNone(hw_submission_set.getBySubmissionKey(key)) self.assertEqual(other_submission, hw_submission_set.getBySubmissionKey(other_key)) self.assertEqual([other_submission_device], list(other_submission.devices))
def test_handleStatus_ABORTED_cancels_cancelling(self): with dbuser(config.builddmaster.dbuser): self.build.updateStatus(BuildStatus.CANCELLING) yield self.behaviour.handleStatus(self.build.buildqueue_record, "ABORTED", {}) self.assertEqual(0, len(pop_notifications()), "Notifications received") self.assertEqual(BuildStatus.CANCELLED, self.build.status)
def test_givenback_collection(self): with ExpectedException( BuildDaemonError, "Build returned unexpected status: u'GIVENBACK'"): with dbuser(config.builddmaster.dbuser): yield self.behaviour.handleStatus(self.build.buildqueue_record, "GIVENBACK", {})
def test_nominateReview_email_content(self): # The email that is sent contains the description of the proposal, and # a link to the proposal. bmp = self.factory.makeBranchMergeProposal( set_state=BranchMergeProposalStatus.NEEDS_REVIEW) reviewer = self.factory.makePerson() with person_logged_in(bmp.registrant): bmp.description = 'This branch is awesome.' bmp.nominateReviewer(reviewer, bmp.registrant, None) review_request_job = self.getReviewNotificationEmail(bmp) with dbuser(config.IBranchMergeProposalJobSource.dbuser): review_request_job.run() [sent_mail] = pop_notifications() expected = dedent("""\ You have been requested to review the proposed merge of""" """ %(source)s into %(target)s. For more details, see: %(bmp)s This branch is awesome. --\x20 You are requested to review the proposed merge of %(source)s""" """ into %(target)s. """ % { 'source': bmp.source_branch.bzr_identity, 'target': bmp.target_branch.bzr_identity, 'bmp': canonical_url(bmp)}) self.assertEqual(expected, sent_mail.get_payload(decode=True))
def test_extraBuildArgs_prefers_store_name(self): # For the "name" argument, extraBuildArgs prefers Snap.store_name # over Snap.name if the former is set. job = self.makeJob(store_name="something-else") with dbuser(config.builddmaster.dbuser): args = yield job.extraBuildArgs() self.assertEqual("something-else", args["name"])
def test_notify_successfully_built(self): # Successful builds don't notify anyone. self.create_builds(self.archive) build = self.builds[BuildStatus.FULLYBUILT.value] with dbuser(config.builddmaster.dbuser): build.notify() self.assertEqual([], pop_notifications())
def test_attachTranslationFiles__translation_sharing(self): # If translation sharing is enabled, attachTranslationFiles() only # attaches templates. distroseries = self.factory.makeDistroSeries() sourcepackagename = self.factory.getOrMakeSourcePackageName( "foobar") self.factory.makeSourcePackage(sourcepackagename=sourcepackagename, distroseries=distroseries, publish=True) spr = self.factory.makeSourcePackageRelease( sourcepackagename=sourcepackagename, distroseries=distroseries) productseries = self.factory.makeProductSeries() sourcepackage = spr.upload_distroseries.getSourcePackage( spr.sourcepackagename) self.factory.makePOTemplate(productseries=productseries) with person_logged_in(sourcepackage.distroseries.owner): sourcepackage.setPackaging( productseries, sourcepackage.distroseries.owner) spr, _, job = self.makeJob(sourcepackagerelease=spr) self.assertTrue(sourcepackage.has_sharing_translation_templates) transaction.commit() with dbuser('upload_package_translations_job'): job.attachTranslationFiles(True) translation_import_queue = getUtility(ITranslationImportQueue) entries = translation_import_queue.getAllEntries(target=sourcepackage) self.assertEqual(1, entries.count()) self.assertTrue(entries[0].path.endswith('.pot'))
def test_scheduleStoreUpload_triggers_webhooks(self): # Scheduling a store upload triggers webhooks on the corresponding # snap. self.setUpStoreUpload() self.build.updateStatus(BuildStatus.FULLYBUILT) self.factory.makeSnapFile( snapbuild=self.build, libraryfile=self.factory.makeLibraryFileAlias(db_only=True)) hook = self.factory.makeWebhook(target=self.build.snap, event_types=["snap:build:0.1"]) self.build.scheduleStoreUpload() expected_payload = { "snap_build": Equals(canonical_url(self.build, force_local_path=True)), "action": Equals("status-changed"), "snap": Equals(canonical_url(self.build.snap, force_local_path=True)), "build_request": Is(None), "status": Equals("Successfully built"), "store_upload_status": Equals("Pending"), } delivery = hook.deliveries.one() self.assertThat( delivery, MatchesStructure(event_type=Equals("snap:build:0.1"), payload=MatchesDict(expected_payload))) with dbuser(config.IWebhookDeliveryJobSource.dbuser): self.assertEqual( "<WebhookDeliveryJob for webhook %d on %r>" % (hook.id, hook.target), repr(delivery))
def test_updateStatus_triggers_webhooks(self): # Updating the status of a SnapBuild triggers webhooks on the # corresponding Snap. hook = self.factory.makeWebhook(target=self.build.snap, event_types=["snap:build:0.1"]) self.build.updateStatus(BuildStatus.FULLYBUILT) expected_payload = { "snap_build": Equals(canonical_url(self.build, force_local_path=True)), "action": Equals("status-changed"), "snap": Equals(canonical_url(self.build.snap, force_local_path=True)), "build_request": Is(None), "status": Equals("Successfully built"), "store_upload_status": Equals("Unscheduled"), } delivery = hook.deliveries.one() self.assertThat( delivery, MatchesStructure(event_type=Equals("snap:build:0.1"), payload=MatchesDict(expected_payload))) with dbuser(config.IWebhookDeliveryJobSource.dbuser): self.assertEqual( "<WebhookDeliveryJob for webhook %d on %r>" % (hook.id, hook.target), repr(delivery))
def test_dbuser(self): switch_dbuser(config.uploader.dbuser) self.assertEqual(config.uploader.dbuser, self.get_current_dbuser()) with dbuser(config.archivepublisher.dbuser): self.assertEqual(config.archivepublisher.dbuser, self.get_current_dbuser()) self.assertEqual(config.uploader.dbuser, self.get_current_dbuser())
def assertWebhookDeliveries(self, snapbuild, expected_store_upload_statuses): hook = snapbuild.snap.webhooks.one() deliveries = list(hook.deliveries) deliveries.reverse() expected_payloads = [{ "snap_build": Equals(canonical_url(snapbuild, force_local_path=True)), "action": Equals("status-changed"), "snap": Equals(canonical_url(snapbuild.snap, force_local_path=True)), "build_request": Is(None), "status": Equals("Successfully built"), "store_upload_status": Equals(expected), } for expected in expected_store_upload_statuses] matchers = [ MatchesStructure(event_type=Equals("snap:build:0.1"), payload=MatchesDict(expected_payload)) for expected_payload in expected_payloads ] self.assertThat(deliveries, MatchesListwise(matchers)) with dbuser(config.IWebhookDeliveryJobSource.dbuser): for delivery in deliveries: self.assertEqual( "<WebhookDeliveryJob for webhook %d on %r>" % (hook.id, hook.target), repr(delivery))
def test_builderfail_collection(self): with ExpectedException( BuildDaemonError, "Build returned unexpected status: u'BUILDERFAIL'"): with dbuser(config.builddmaster.dbuser): yield self.behaviour.handleStatus(self.build.buildqueue_record, "BUILDERFAIL", {})
def test_extraBuildArgs_build_source_tarball(self): # If the snap requests building of a source tarball, extraBuildArgs # sends the appropriate arguments. job = self.makeJob(build_source_tarball=True) with dbuser(config.builddmaster.dbuser): args = yield job.extraBuildArgs() self.assertTrue(args["build_source_tarball"])
def test_upload_no_discharge(self): root_key = hashlib.sha256(self.factory.getUniqueString()).hexdigest() root_macaroon = Macaroon(key=root_key) snapbuild = self.makeUploadableSnapBuild( store_secrets={"root": root_macaroon.serialize()}) transaction.commit() self._addUnscannedUploadResponse() self._addSnapPushResponse() with dbuser(config.ISnapStoreUploadJobSource.dbuser): self.assertEqual( "http://sca.example/dev/api/snaps/1/builds/1/status", self.client.upload(snapbuild)) requests = [call.request for call in responses.calls] self.assertThat(requests, MatchesListwise([ RequestMatches( url=Equals("http://updown.example/unscanned-upload/"), method=Equals("POST"), form_data={ "binary": MatchesStructure.byEquality( name="binary", filename="test-snap.snap", value="dummy snap content", type="application/octet-stream", )}), RequestMatches( url=Equals("http://sca.example/dev/api/snap-push/"), method=Equals("POST"), headers=ContainsDict( {"Content-Type": Equals("application/json")}), auth=("Macaroon", MacaroonsVerify(root_key)), json_data={ "name": "test-snap", "updown_id": 1, "series": "rolling", }), ]))
def test_team(self): team = self.factory.makeTeam() script = self.makeScript([team.name]) with dbuser('launchpad'): self.assertRaisesWithContent(LaunchpadScriptFailure, '%s is a team' % team.name, self.runScript, script)
def test_nonexistent(self): script = self.makeScript(['nonexistent-person']) with dbuser('launchpad'): self.assertRaisesWithContent( LaunchpadScriptFailure, 'User nonexistent-person does not exist', self.runScript, script)
def test_run_all(self): """The job can be run under the JobRunner successfully.""" job = make_runnable_incremental_diff_job(self) with dbuser("merge-proposal-jobs"): runner = JobRunner([job]) runner.runAll() self.assertEqual([job], runner.completed_jobs)
def test_dry_run(self): person, person_id, account_id = self.makePopulatedUser() script = self.makeScript(['--dry-run', six.ensure_str(person.name)]) with dbuser('launchpad'): self.runScript(script) self.assertIn('Dry run, so not committing changes', script.logger.getLogBuffer()) self.assertNotRemoved(account_id, person_id)
def addKarma(self, person, value, product=None, distribution=None): if product: kwargs = dict(product_id=product.id) elif distribution: kwargs = dict(distribution_id=distribution.id) with dbuser('karma'): getUtility(IKarmaCacheManager).new( value, person.id, None, **kwargs)
def test_run_missing_ready_not_enabled(self): """run_missing_ready does nothing if the class isn't enabled.""" self.createMissingJob() with monitor_celery() as responses: with dbuser("run_missing_ready"): with TransactionFreeOperation.require(): self.RunMissingReady().run(_no_init=True) self.assertEqual([], responses)
def test_extraBuildArgs_private(self): # If the snap is private, extraBuildArgs sends the appropriate # arguments. self.useFixture(FeatureFixture({SNAP_PRIVATE_FEATURE_FLAG: "on"})) job = self.makeJob(private=True) with dbuser(config.builddmaster.dbuser): args = yield job.extraBuildArgs() self.assertTrue(args["private"])
def test_handleStatus_ABORTED_cancelling_sets_build_log(self): # If a build is intentionally cancelled, the build log is set. self.assertEqual(None, self.build.log) with dbuser(config.builddmaster.dbuser): self.build.updateStatus(BuildStatus.CANCELLING) yield self.behaviour.handleStatus(self.build.buildqueue_record, "ABORTED", {}) self.assertNotEqual(None, self.build.log)
def test_run_missing_ready_not_enabled(self): """run_missing_ready does nothing if the class isn't enabled.""" self.createMissingJob() with monitor_celery() as responses: with dbuser('run_missing_ready'): with TransactionFreeOperation.require(): self.RunMissingReady().run(_no_init=True) self.assertEqual([], responses)
def setUp(self): # Create a revision author that doesn't have a user yet. super(TestNewlyValidatedEmailsLinkRevisionAuthors, self).setUp() with dbuser("branchscanner"): self.author = RevisionSet()._createRevisionAuthor( '"Harry Potter" <*****@*****.**>') # Reget the revision author as we have crossed a transaction boundary. self.author = RevisionAuthor.byName(self.author.name)
def test_extraBuildArgs_disallow_internet(self): # If external network access is not allowed for the snap, # extraBuildArgs does not dispatch a proxy token. job = self.makeJob(allow_internet=False) with dbuser(config.builddmaster.dbuser): args = yield job.extraBuildArgs() self.assertNotIn("proxy_url", args) self.assertNotIn("revocation_endpoint", args)
def test_database_permissions(self): # The script has sufficient database privileges to do its job. sides = [TranslationSide.UPSTREAM, TranslationSide.UBUNTU] pofiles = [ self._makeNonemptyPOFile(side) for side in sides] with dbuser('pofilestats'): for pofile in pofiles: pofile.updateStatistics()
def addKarma(self, person, value, product=None, distribution=None): if product: kwargs = dict(product_id=product.id) elif distribution: kwargs = dict(distribution_id=distribution.id) with dbuser('karma'): getUtility(IKarmaCacheManager).new(value, person.id, None, **kwargs)
def test_run_missing_ready(self): """run_missing_ready requests the job to run if not scheduled.""" self.createMissingJob() self.useFixture(FeatureFixture({"jobs.celery.enabled_classes": "BranchScanJob"})) with monitor_celery() as responses: with dbuser("run_missing_ready"): with TransactionFreeOperation.require(): self.RunMissingReady().run(_no_init=True) self.assertEqual(1, len(responses))
def test_10_minute_lease(self): """Newly-created jobs have a ten-minute lease.""" self.useBzrBranches(direct_database=True) bmp = create_example_merge(self)[0] job = GenerateIncrementalDiffJob.create(bmp, 'old', 'new') with dbuser("merge-proposal-jobs"): job.acquireLease() expiry_delta = job.lease_expires - datetime.now(pytz.UTC) self.assertTrue(500 <= expiry_delta.seconds, expiry_delta)
def test_run(self): self.useBzrBranches(direct_database=True) bmp = create_example_merge(self)[0] job = UpdatePreviewDiffJob.create(bmp) self.factory.makeRevisionsForBranch(bmp.source_branch, count=1) bmp.source_branch.next_mirror_time = None with dbuser("merge-proposal-jobs"): JobRunner([job]).runAll() self.checkExampleMerge(bmp.preview_diff.text)
def test_create(self): # bugtask_flatten() returns true if the BugTaskFlat is missing, # and optionally creates it. task = self.factory.makeBugTask() self.assertTrue(self.checkFlattened(task)) with dbuser('testadmin'): IStore(Bug).execute( "DELETE FROM BugTaskFlat WHERE bugtask = ?", (task.id,)) self.assertFlattens(task)
def _process_triggers(self, mode): with dbuser("postgres"): for table, trigger in self.table_triggers.items(): sql = ("ALTER TABLE %(table)s %(mode)s trigger " "%(trigger)s") % { "table": table, "mode": mode, "trigger": trigger, } IStore(LibraryFileAlias).execute(sql)
def test_update(self): # bugtask_flatten() returns true if the BugTaskFlat is out of # date, and optionally updates it. task = self.factory.makeBugTask() self.assertTrue(self.checkFlattened(task)) with dbuser('testadmin'): IStore(Bug).execute( "UPDATE BugTaskFlat SET status = ? WHERE bugtask = ?", (BugTaskStatus.UNKNOWN.value, task.id)) self.assertFlattens(task)
def test_delete_no_notifications(self): team = self.factory.makeTeam() owner = team.teamowner transaction.commit() with dbuser(config.IPersonMergeJobSource.dbuser): merge_people( team, getUtility(ILaunchpadCelebrities).registry_experts, owner, delete=True) notification_set = getUtility(IPersonNotificationSet) notifications = notification_set.getNotificationsToSend() self.assertEqual(0, notifications.count())
def setUp(self): super(TestTranslatorsCounts, self).setUp() self.translated_lang = self.factory.makeLanguage(pluralforms=None) self.untranslated_lang = self.factory.makeLanguage(pluralforms=None) for i in range(3): translator = self.factory.makePerson() translator.addLanguage(self.translated_lang) with dbuser('karma'): translations_category = IStore(KarmaCategory).find( KarmaCategory, name='translations').one() getUtility(IKarmaCacheManager).new( person_id=translator.id, category_id=translations_category.id, value=100)
def test_attachTranslationFiles__no_translation_sharing(self): # If translation sharing is disabled, # SourcePackageRelease.attachTranslationFiles() creates a job # in the translation import queue. spr = self.factory.makeSourcePackageRelease() self.assertFalse(spr.sourcepackage.has_sharing_translation_templates) lfa = self.makeTranslationsLFA() transaction.commit() with dbuser('upload_package_translations_job'): spr.attachTranslationFiles(lfa, True, spr.maintainer) translation_import_queue = getUtility(ITranslationImportQueue) entries_in_queue = translation_import_queue.getAllEntries( target=spr.sourcepackage).count() self.assertEqual(2, entries_in_queue)
def test_delete(self): # bugtask_flatten() returns true if the BugTaskFlat exists but # the task doesn't, and optionally deletes it. self.assertTrue(self.checkFlattened(200)) with dbuser('testadmin'): IStore(Bug).execute( "INSERT INTO bugtaskflat " "(bug, bugtask, bug_owner, information_type, " " date_last_updated, heat, status, importance, owner, " " active) " "VALUES " "(1, 200, 1, 1, " " current_timestamp at time zone 'UTC', 999, 1, 1, 1, true);") self.assertFlattens(200)
def test_MergeProposalCreateJob_with_sourcepackage_branch(self): """Jobs for merge proposals with sourcepackage branches work.""" self.useBzrBranches(direct_database=True) bmp = self.factory.makeBranchMergeProposal( target_branch=self.factory.makePackageBranch()) tree = self.create_branch_and_tree(db_branch=bmp.target_branch)[1] # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is # required to generate the revision-id. with override_environ(BZR_EMAIL='*****@*****.**'): tree.commit('Initial commit') self.createBzrBranch(bmp.source_branch, tree.branch) self.factory.makeRevisionsForBranch(bmp.source_branch, count=1) job = MergeProposalNeedsReviewEmailJob.create(bmp) with dbuser("merge-proposal-jobs"): job.run()
def test_run(self): # Running a job causes the POFile statistics to be updated. singular = self.factory.getUniqueString() pofile = self.factory.makePOFile(side=TranslationSide.UPSTREAM) # Create a message so we have something to have statistics about. self.factory.makePOTMsgSet(pofile.potemplate, singular) # The statistics start at 0. self.assertEqual(pofile.potemplate.messageCount(), 0) job = pofilestatsjob.schedule(pofile.id) # Just scheduling the job doesn't update the statistics. self.assertEqual(pofile.potemplate.messageCount(), 0) with dbuser('pofilestats'): job.run() # Now that the job ran, the statistics have been updated. self.assertEqual(pofile.potemplate.messageCount(), 1)
def test_rebuild_bugsummary_for_target(self): # rebuild_bugsummary_for_target rebuilds BugSummary for a # specific target from BugTaskFlat. Since it ignores the # journal, it also removes any relevant journal entries. product = self.factory.makeProduct() self.factory.makeBug(target=product) self.assertEqual(0, get_bugsummary_rows(product).count()) self.assertEqual(1, get_bugsummaryjournal_rows(product).count()) log = BufferLogger() with dbuser('bugsummaryrebuild'): rebuild_bugsummary_for_target(product, log) self.assertEqual(1, get_bugsummary_rows(product).count()) self.assertEqual(0, get_bugsummaryjournal_rows(product).count()) self.assertThat( log.getLogBufferAndClear(), MatchesRegex( 'DEBUG Rebuilding %s\nDEBUG Added {.*: 1L}' % product.name))
def test_run_with_product(self): product = self.factory.makeProduct( translations_usage=ServiceUsage.LAUNCHPAD) productseries = self.factory.makeProductSeries(product=product) potemplate = self.factory.makePOTemplate(productseries=productseries) pofile = self.factory.makePOFile('en', potemplate) # Create a message so we have something to have statistics about. singular = self.factory.getUniqueString() self.factory.makePOTMsgSet(pofile.potemplate, singular) # The statistics are still at 0, even though there is a message. self.assertEqual(potemplate.messageCount(), 0) job = pofilestatsjob.schedule(pofile.id) # Just scheduling the job doesn't update the statistics. self.assertEqual(pofile.potemplate.messageCount(), 0) with dbuser('pofilestats'): job.run() # Now that the job ran, the statistics have been updated. self.assertEqual(pofile.potemplate.messageCount(), 1)
def test_run_object_events(self): # While the job runs a single IObjectModifiedEvent is issued when the # preview diff has been calculated. self.useBzrBranches(direct_database=True) bmp = create_example_merge(self)[0] job = UpdatePreviewDiffJob.create(bmp) self.factory.makeRevisionsForBranch(bmp.source_branch, count=1) bmp.source_branch.next_mirror_time = None with dbuser("merge-proposal-jobs"): with EventRecorder() as event_recorder: JobRunner([job]).runAll() bmp_object_events = [ event for event in event_recorder.events if (IObjectModifiedEvent.providedBy(event) and event.object == bmp)] self.assertEqual( 1, len(bmp_object_events), "Expected one event, got: %r" % bmp_object_events) self.assertEqual( ["preview_diff"], bmp_object_events[0].edited_fields)
def assertJobUpdatesStats(self, pofile1, pofile2): # Create a single POTMsgSet and add it to only one of the POTemplates. self.factory.makeSuggestion(pofile1) self.factory.makeSuggestion(pofile2) # The statistics start at 0. self.assertEqual(pofile1.getStatistics(), (0, 0, 0, 0)) self.assertEqual(pofile2.getStatistics(), (0, 0, 0, 0)) job = pofilestatsjob.schedule(pofile1.id) # Just scheduling the job doesn't update the statistics. self.assertEqual(pofile1.getStatistics(), (0, 0, 0, 0)) self.assertEqual(pofile2.getStatistics(), (0, 0, 0, 0)) with dbuser('pofilestats'): job.run() # Now that the job ran, the statistics for the POFile have been # updated. self.assertEqual(pofile1.getStatistics(), (0, 0, 0, 1)) # The statistics for the other POFile is also updated as a result of # running the job for the other POFile because they share # translations. self.assertEqual(pofile2.getStatistics(), (0, 0, 0, 1))
def test_attachTranslationFiles__translation_sharing(self): # If translation sharing is enabled, # SourcePackageRelease.attachTranslationFiles() only attaches # templates. spr = self.factory.makeSourcePackageRelease() sourcepackage = spr.sourcepackage productseries = self.factory.makeProductSeries() self.factory.makePOTemplate(productseries=productseries) with person_logged_in(sourcepackage.distroseries.owner): sourcepackage.setPackaging( productseries, sourcepackage.distroseries.owner) self.assertTrue(sourcepackage.has_sharing_translation_templates) lfa = self.makeTranslationsLFA() transaction.commit() with dbuser('upload_package_translations_job'): spr.attachTranslationFiles(lfa, True, spr.maintainer) translation_import_queue = getUtility(ITranslationImportQueue) entries = translation_import_queue.getAllEntries( target=sourcepackage) self.assertEqual(1, entries.count()) self.assertTrue(entries[0].path.endswith('.pot'))
def expireLFAsForSource(self, source, expire=True, delete=True): """Expire the files associated with the given source package in the librarian.""" assert expire or delete query = "UPDATE LibraryFileAlias lfa SET " if expire: query += "expires = %s" % sqlvalues(datetime.utcnow()) if expire and delete: query += ", " if delete: query += "content = NULL" query += """ FROM SourcePackageRelease spr, SourcePackageReleaseFile sprf WHERE spr.id = %s AND sprf.SourcePackageRelease = spr.id AND sprf.libraryfile = lfa.id """ % sqlvalues(source.id) with dbuser('launchpad'): IStore(Archive).execute(query)
def test_deactivate(self): job = self.makeJob() team = self.factory.makeTeam(members=[job.person]) owned_team = self.factory.makeTeam(owner=job.person) bug = self.factory.makeBug(owner=job.person) with person_logged_in(job.person): bug.default_bugtask.transitionToAssignee(job.person) spec = self.factory.makeSpecification(assignee=job.person) product = self.factory.makeProduct( owner=job.person, bug_supervisor=job.person) distro = self.factory.makeDistribution(driver=job.person) expected_name = job.person.name + '-deactivatedaccount' with dbuser('person-merge-job'): job.run() self.assertIs(None, bug.default_bugtask.assignee) self.assertIs(None, spec.assignee) self.assertNotIn(job.person, list(team.activemembers)) self.assertNotEqual(job.person, owned_team.teamowner) self.assertNotEqual(job.person, product.owner) self.assertIs(None, product.bug_supervisor) self.assertIs(None, distro.driver) self.assertEqual(expected_name, job.person.name)
def test_cache_attribute_when_two_cache_objects(self): # We have situations where there are cache objects for each # distro archive - we need to handle this situation without # OOPSing - see bug 580181. distro_archive_1 = self.distribution.main_archive distro_archive_2 = self.distribution.all_distro_archives[1] # Publish the same binary in another distro archive. self.publisher.getPubBinaries( binaryname='foo-bin', summary='Foo is the best', archive=distro_archive_2) logger = BufferLogger() with dbuser(config.statistician.dbuser): DistroSeriesPackageCache._update( self.distroseries, self.binary_package_name, distro_archive_1, logger) DistroSeriesPackageCache._update( self.distroseries, self.binary_package_name, distro_archive_2, logger) self.failUnlessEqual( 'Foo is the best', self.distroseries_binary_package.summary)
def decorated(*args, **kwargs): with dbuser(username): return f(*args, **kwargs)
def test_run(self): """The job runs successfully, and its results can be committed.""" job = make_runnable_incremental_diff_job(self) with dbuser("merge-proposal-jobs"): job.run()
def _do_merge(self, from_person, to_person, reviewer=None): # Perform the merge as the db user that will be used by the jobs. with dbuser(config.IPersonMergeJobSource.dbuser): merge_people(from_person, to_person, reviewer=reviewer) return from_person, to_person