Example #1
0
 def setUp(self):
     super(TestLibrarianStuff, self).setUp()
     switch_dbuser('librarian')
     self.store = IStore(LibraryFileContent)
     self.content_id = db.Library().add('deadbeef', 1234, 'abababab', 'ba')
     self.file_content = self._getTestFileContent()
     transaction.commit()
 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())
Example #3
0
    def becomeTheApprover(self):
        """Assume the database role of the translations branch scanner.

        This is the role that the TranslationsBranchApprover is actually
        run under.
        """
        switch_dbuser('translationsbranchscanner')
Example #4
0
 def test_instruction_branch_recipe(self):
     """On tip change, recipes including this branch become stale."""
     recipe = self.factory.makeSourcePackageRecipe(branches=[self.factory.makeBranch(), self.db_branch])
     removeSecurityProxy(recipe).is_stale = False
     switch_dbuser("branchscanner")
     self.makeBzrSync(self.db_branch).syncBranchAndClose()
     self.assertEqual(True, recipe.is_stale)
 def setUp(self):
     # This test needs the privileges of rosettaadmin (to update
     # TranslationMessages) but it also needs to set up test conditions
     # which requires other privileges.
     switch_dbuser('postgres')
     super(TestMigrateCurrentFlag, self).setUp(user='******')
     self.migrate_process = MigrateCurrentFlagProcess(self.layer.txn)
    def test_robustness(self):
        """Test that a broken package doesn't block the publication of other
        packages."""
        # Attempt to upload one source to a supported series.
        # The record is created first and then the status of the series
        # is changed from DEVELOPMENT to SUPPORTED, otherwise it's impossible
        # to create the record.
        distroseries = self.factory.makeDistroSeries(distribution=self.distro)
        # This creates a broken publication.
        self.createWaitingAcceptancePackage(
            distroseries=distroseries, sourcename="notaccepted")
        distroseries.status = SeriesStatus.SUPPORTED
        # Also upload some other things.
        other_distroseries = self.factory.makeDistroSeries(
            distribution=self.distro)
        self.createWaitingAcceptancePackage(distroseries=other_distroseries)
        script = self.getScript([])
        switch_dbuser(self.dbuser)
        script.main()

        # The other source should be published now.
        published_main = self.distro.main_archive.getPublishedSources(
            name=self.test_package_name)
        self.assertEqual(published_main.count(), 1)

        # And an oops should be filed for the first.
        self.assertEqual(1, len(self.oopses))
        error_report = self.oopses[0]
        expected_error = "Failure processing queue_item"
        self.assertStartsWith(
                error_report['req_vars']['error-explanation'],
                expected_error)
    def test_order_by_soyuz_package_karma(self):
        # Returned archives are ordered by the soyuz karma of the
        # package uploaders for the particular package

        related_archives = self.source_package.findRelatedArchives()
        related_archive_names = [
            archive.name for archive in related_archives]

        self.assertEqual(related_archive_names, [
            'gedit-nightly',
            'gedit-beta',
            ])

        # Update the soyuz karma for person_beta for this package so that
        # it is greater than person_nightly's.
        switch_dbuser('karma')
        self.person_beta_karma.karma_total = 202
        switch_dbuser('launchpad')

        related_archives = self.source_package.findRelatedArchives()
        related_archive_names = [
            archive.name for archive in related_archives]

        self.assertEqual(related_archive_names, [
            'gedit-beta',
            'gedit-nightly',
            ])
    def setUp(self):
        super(TestRemoveTranslations, self).setUp()
        # Acquire privileges to delete TranslationMessages.  That's not
        # something we normally do.  Actually we should test under
        # rosettaadmin, but that user does not have all the privileges
        # needed to set up this test.  A separate doctest
        # remove-translations-by.txt tests a realistic run of the
        # remove-translations-by.py script under the actual rosettaadmin
        # db user.
        switch_dbuser('postgres')

        # Set up a template with Dutch and German translations.  The
        # messages we set up here are invariant; they remain untouched
        # by deletions done in the test case.
        self.factory = LaunchpadObjectFactory()
        self.nl_pofile = self.factory.makePOFile('nl')
        self.potemplate = self.nl_pofile.potemplate
        self.de_pofile = self.factory.makePOFile(
            'de', potemplate=self.potemplate)

        self.nl_message, self.de_message = self._makeMessages(
            "This message is not to be deleted.",
            "Dit bericht mag niet worden verwijderd.",
            "Diese Nachricht soll nicht erloescht werden.")

        self.untranslated_message = self.factory.makePOTMsgSet(
            self.potemplate, 'This message is untranslated.', sequence=0)

        self._checkInvariant()
Example #9
0
    def test_multiple_parents_do_not_close_bugs(self):
        # The initialization does not close the bugs on the copied
        # publications (and thus does not try to access the bug table).
        parent1, parent2 = self.setUpParents(packages1={'p1': '0.1-1'},
                                             packages2={'p2': '2.1'})
        child = self.factory.makeDistroSeries()
        switch_dbuser('initializedistroseries')

        # Patch close_bugs_for_sourcepublication to be able to record if
        # the method has been called.
        fakeCloseBugs = FakeMethod()
        from lp.soyuz.scripts import packagecopier as packagecopier_module
        self.patch(packagecopier_module, 'close_bugs_for_sourcepublication',
                   fakeCloseBugs)

        child = self._fullInitialize([parent1, parent2], child=child)
        # Make sure the initialization was successful.
        self.assertBinPackagesAndVersions(child, [(u'p1', u'0.1-1'),
                                                  (u'p2', u'2.1')])
        # Assert that close_bugs_for_sourcepublication has not been
        # called.
        self.assertEqual(0, fakeCloseBugs.call_count)
        # Switch back to launchpad_main to be able to cleanup the
        # feature flags.
        switch_dbuser('launchpad_main')
Example #10
0
    def test_CodeImportEventPruner(self):
        now = datetime.now(UTC)
        store = IMasterStore(CodeImportResult)

        switch_dbuser('testadmin')
        machine = self.factory.makeCodeImportMachine()
        requester = self.factory.makePerson()
        # Create 6 code import events for this machine, 3 on each side of 30
        # days. Use the event set to the extra event data rows get created
        # too.
        event_set = getUtility(ICodeImportEventSet)
        for age in (35, 33, 31, 29, 27, 15):
            event_set.newOnline(
                machine, user=requester, message='Hello',
                _date_created=(now - timedelta(days=age)))
        transaction.commit()

        # Run the garbage collector
        self.runDaily()

        # Only the three most recent results are left.
        events = list(machine.events)
        self.assertEqual(3, len(events))
        # We now have no CodeImportEvents older than 30 days
        self.failUnless(
            store.find(
                Min(CodeImportEvent.date_created)).one().replace(tzinfo=UTC)
            >= now - timedelta(days=30))
Example #11
0
    def _test_AnswerContactPruner(self, status, interval, expected_count=0):
        # Garbo should remove answer contacts for accounts with given 'status'
        # which was set more than 'interval' days ago.
        switch_dbuser('testadmin')
        store = IMasterStore(AnswerContact)

        person = self.factory.makePerson()
        person.addLanguage(getUtility(ILanguageSet)['en'])
        question = self.factory.makeQuestion()
        with person_logged_in(question.owner):
            question.target.addAnswerContact(person, person)
        Store.of(question).flush()
        self.assertEqual(
            store.find(
                AnswerContact,
                AnswerContact.person == person.id).count(),
                1)

        account = person.account
        account.status = status
        # We flush because a trigger sets the date_status_set and we need to
        # modify it ourselves.
        Store.of(account).flush()
        if interval is not None:
            account.date_status_set = interval

        self.runDaily()

        switch_dbuser('testadmin')
        self.assertEqual(
            store.find(
                AnswerContact,
                AnswerContact.person == person.id).count(),
                expected_count)
 def test_getBranchMergeProposalInvalid(self):
     """InvalidBranchMergeProposalAddress is raised if appropriate."""
     switch_dbuser(config.processmail.dbuser)
     self.assertRaises(InvalidBranchMergeProposalAddress,
                       self.code_handler.getBranchMergeProposal, '')
     self.assertRaises(InvalidBranchMergeProposalAddress,
                       self.code_handler.getBranchMergeProposal, 'mp+abc@')
Example #13
0
    def test_LoginTokenPruner(self):
        store = IMasterStore(LoginToken)
        now = datetime.now(UTC)
        switch_dbuser('testadmin')

        # It is configured as a daily task.
        self.assertTrue(
            LoginTokenPruner in DailyDatabaseGarbageCollector.tunable_loops)

        # Create a token that will be pruned.
        old_token = LoginToken(
            email='whatever', tokentype=LoginTokenType.NEWACCOUNT)
        old_token.date_created = now - timedelta(days=666)
        old_token_id = old_token.id
        store.add(old_token)

        # Create a token that will not be pruned.
        current_token = LoginToken(
            email='whatever', tokentype=LoginTokenType.NEWACCOUNT)
        current_token_id = current_token.id
        store.add(current_token)

        # Run the pruner. Batching is tested by the BulkPruner tests so
        # no need to repeat here.
        switch_dbuser('garbo_daily')
        pruner = LoginTokenPruner(logging.getLogger('garbo'))
        while not pruner.isDone():
            pruner(10)
        pruner.cleanUp()

        # Only the old LoginToken is gone.
        self.assertEqual(
            store.find(LoginToken, id=old_token_id).count(), 0)
        self.assertEqual(
            store.find(LoginToken, id=current_token_id).count(), 1)
Example #14
0
 def test_getDerivedSeries(self):
     # Check that DB users can query derived series.
     script_users = ['queued']
     dsp = self.factory.makeDistroSeriesParent()
     for user in script_users:
         switch_dbuser(user)
         list(dsp.parent_series.getDerivedSeries())
    def test_process_for_imported_branch(self):
        """Make sure that the database user is able refer to import branches.

        Import branches have different permission checks than other branches.

        Permission to mark a merge proposal as approved checks launchpad.Edit
        of the target branch, or membership of the review team on the target
        branch.  For import branches launchpad.Edit also checks the registrant
        of the code import if there is one, and membership of vcs-imports.  So
        if someone is attempting to review something on an import branch, but
        they don't have launchpad.Edit but are a member of the review team,
        then a check against the code import is done.
        """
        mail = self.factory.makeSignedMessage(body=' merge approved')
        code_import = self.factory.makeCodeImport()
        bmp = self.factory.makeBranchMergeProposal(
            target_branch=code_import.branch)
        email_addr = bmp.address
        switch_dbuser(config.processmail.dbuser)
        pop_notifications()
        self.code_handler.process(mail, email_addr, None)
        notification = pop_notifications()[0]
        # The returned message is a multipart message, the first part is
        # the message, and the second is the original message.
        message, original = notification.get_payload()
        self.assertTrue(
            "You are not a reviewer for the branch" in
            message.get_payload(decode=True))
Example #16
0
 def runJob(self, job):
     switch_dbuser('distroseriesdifferencejob')
     dsdjob = DistroSeriesDifferenceJob(job)
     dsdjob.start()
     dsdjob.run()
     dsdjob.complete()
     switch_dbuser('launchpad')
    def test_generateEmailWithInlineComments(self):
        """Review comments emails consider the inline comments.

        See `build_inline_comments_section` tests for formatting details.
        """
        comment = self.makeCommentWithInlineComments(
            inline_comments={'3': 'Is this from Pl\u0060net Earth ?'})
        switch_dbuser(config.IBranchMergeProposalJobSource.dbuser)
        mailer = CodeReviewCommentMailer.forCreation(comment)
        commenter = comment.branch_merge_proposal.registrant
        ctrl = mailer.generateEmail(commenter.preferredemail.email, commenter)

        expected_lines = [
            '',
            'Diff comments:',
            '',
            ("> === zbqvsvrq svyr 'yvo/yc/pbqr/vagresnprf/qvss.cl'"),
            ('> --- yvo/yc/pbqr/vagresnprf/qvss.cl      '
             '2009-10-01 13:25:12 +0000'),
            ('> +++ yvo/yc/pbqr/vagresnprf/qvss.cl      '
             '2010-02-02 15:48:56 +0000'),
            '',
            'Is this from Pl\u0060net Earth ?',
            '',
        ]
        self.assertEqual(expected_lines, ctrl.body.splitlines()[1:10])
Example #18
0
 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())
Example #19
0
    def test_VoucherRedeemer(self):
        switch_dbuser('testadmin')

        voucher_proxy = TestSalesforceVoucherProxy()
        self.registerUtility(voucher_proxy, ISalesforceVoucherProxy)

        # Mark has some unredeemed vouchers so set one of them as pending.
        mark = getUtility(IPersonSet).getByName('mark')
        voucher = voucher_proxy.getUnredeemedVouchers(mark)[0]
        product = self.factory.makeProduct(owner=mark)
        redeemed_id = voucher.voucher_id
        self.factory.makeCommercialSubscription(
            product, False, 'pending-%s' % redeemed_id)
        transaction.commit()

        self.runFrequently()

        # There should now be 0 pending vouchers in Launchpad.
        num_rows = IMasterStore(CommercialSubscription).find(
            CommercialSubscription,
            Like(CommercialSubscription.sales_system_id, u'pending-%')
            ).count()
        self.assertThat(num_rows, Equals(0))
        # Salesforce should also now have redeemed the voucher.
        unredeemed_ids = [
            v.voucher_id for v in voucher_proxy.getUnredeemedVouchers(mark)]
        self.assertNotIn(redeemed_id, unredeemed_ids)
Example #20
0
    def setUp(self):
        """Set up bugs, watches and questions to test with."""
        super(TestUpdateBugsWithLinkedQuestions, self).setUp()

        # For test_can_update_bug_with_questions we need a bug that has
        # a question linked to it.
        bug_with_question = getUtility(IBugSet).get(10)
        question = getUtility(IQuestionSet).get(1)

        sample_person = getUtility(IPersonSet).getByEmail('*****@*****.**')
        question.linkBug(bug_with_question, sample_person)

        # We subscribe launchpad_developers to the question since this
        # indirectly subscribes [email protected] to it, too. We can
        # then use this to test the updating of a question with indirect
        # subscribers from a bug watch.
        question.subscribe(
            getUtility(ILaunchpadCelebrities).launchpad_developers)

        # We now need to switch to the checkwatches DB user so that
        # we're testing with the correct set of permissions.
        switch_dbuser(config.checkwatches.dbuser)

        # For test_can_update_bug_with_questions we also need a bug
        # watch and by extension a bug tracker.
        bugtracker = new_bugtracker(BugTrackerType.ROUNDUP)
        self.bugtask_with_question = getUtility(IBugTaskSet).createTask(
            bug_with_question, sample_person,
            getUtility(IProductSet).getByName('firefox'))
        self.bugwatch_with_question = bug_with_question.addWatch(
            bugtracker, '1',
            getUtility(ILaunchpadCelebrities).janitor)
        self.bugtask_with_question.bugwatch = self.bugwatch_with_question
        transaction.commit()
Example #21
0
    def test_UnusedAccessPolicyPruner(self):
        # UnusedAccessPolicyPruner removes access policies that aren't
        # in use by artifacts or allowed by the project sharing policy.
        switch_dbuser('testadmin')
        product = self.factory.makeProduct()
        self.factory.makeCommercialSubscription(product=product)
        self.factory.makeAccessPolicy(product, InformationType.PROPRIETARY)
        naked_product = removeSecurityProxy(product)
        naked_product.bug_sharing_policy = BugSharingPolicy.PROPRIETARY
        naked_product.branch_sharing_policy = BranchSharingPolicy.PROPRIETARY
        [ap] = getUtility(IAccessPolicySource).find(
            [(product, InformationType.PRIVATESECURITY)])
        self.factory.makeAccessPolicyArtifact(policy=ap)

        # Private and Private Security were created with the project.
        # Proprietary was created when the branch sharing policy was set.
        self.assertContentEqual(
            [InformationType.PRIVATESECURITY, InformationType.USERDATA,
             InformationType.PROPRIETARY],
            self.getAccessPolicyTypes(product))

        self.runDaily()

        # Proprietary is permitted by the sharing policy, and there's a
        # Private Security artifact. But Private isn't in use or allowed
        # by a sharing policy, so garbo deleted it.
        self.assertContentEqual(
            [InformationType.PRIVATESECURITY, InformationType.PROPRIETARY],
            self.getAccessPolicyTypes(product))
Example #22
0
    def test_pruneBugWatchActivity_leaves_most_recent(self):
        # BugWatchActivityPruner.pruneBugWatchActivity() will delete all
        # but the n most recent BugWatchActivity items for a bug watch,
        # where n is determined by checkwatches.scheduler.MAX_SAMPLE_SIZE.
        for i in range(5):
            self.bug_watch.addActivity(message="Activity %s" % i)

        switch_dbuser('garbo')
        self.pruner = BugWatchActivityPruner(BufferLogger())
        self.addCleanup(self.pruner.cleanUp)

        # MAX_SAMPLE_SIZE + 1 created in setUp(), and 5 more created
        # just above.
        self.assertEqual(MAX_SAMPLE_SIZE + 6, self.bug_watch.activity.count())

        # Run the pruner
        while not self.pruner.isDone():
            self.pruner(chunk_size=3)

        # Only MAX_SAMPLE_SIZE items should be left.
        self.assertEqual(MAX_SAMPLE_SIZE, self.bug_watch.activity.count())

        # They should be the most recent items - the ones created at the
        # start of this test.
        messages = [activity.message for activity in self.bug_watch.activity]
        for i in range(MAX_SAMPLE_SIZE):
            self.assertIn("Activity %s" % i, messages)
Example #23
0
 def runHourly(self, maximum_chunk_size=2, test_args=()):
     switch_dbuser('garbo_hourly')
     collector = HourlyDatabaseGarbageCollector(test_args=list(test_args))
     collector._maximum_chunk_size = maximum_chunk_size
     collector.logger = self.log
     collector.main()
     return collector
    def test_pruneBugWatchActivity_leaves_most_recent(self):
        # BugWatchActivityPruner.pruneBugWatchActivity() will delete all
        # but the n most recent BugWatchActivity items for a bug watch,
        # where n is determined by checkwatches.scheduler.MAX_SAMPLE_SIZE.
        for i in range(5):
            self.bug_watch.addActivity(message="Activity %s" % i)

        switch_dbuser('garbo')
        self.pruner = BugWatchActivityPruner(BufferLogger())
        self.addCleanup(self.pruner.cleanUp)

        # MAX_SAMPLE_SIZE + 1 created in setUp(), and 5 more created
        # just above.
        self.assertEqual(MAX_SAMPLE_SIZE + 6, self.bug_watch.activity.count())

        # Run the pruner
        while not self.pruner.isDone():
            self.pruner(chunk_size=3)

        # Only MAX_SAMPLE_SIZE items should be left.
        self.assertEqual(MAX_SAMPLE_SIZE, self.bug_watch.activity.count())

        # They should be the most recent items - the ones created at the
        # start of this test.
        messages = [activity.message for activity in self.bug_watch.activity]
        for i in range(MAX_SAMPLE_SIZE):
            self.failUnless("Activity %s" % i in messages)
Example #25
0
    def test_PersonPruner(self):
        personset = getUtility(IPersonSet)
        # Switch the DB user because the garbo_daily user isn't allowed to
        # create person entries.
        switch_dbuser('testadmin')

        # Create two new person entries, both not linked to anything. One of
        # them will have the present day as its date created, and so will not
        # be deleted, whereas the other will have a creation date far in the
        # past, so it will be deleted.
        self.factory.makePerson(name='test-unlinked-person-new')
        person_old = self.factory.makePerson(name='test-unlinked-person-old')
        removeSecurityProxy(person_old).datecreated = datetime(
            2008, 01, 01, tzinfo=UTC)

        # Normally, the garbage collector will do nothing because the
        # PersonPruner is experimental
        self.runDaily()
        self.assertIsNot(
            personset.getByName('test-unlinked-person-new'), None)
        self.assertIsNot(
            personset.getByName('test-unlinked-person-old'), None)

        # When we run the garbage collector with experimental jobs turned
        # on, the old unlinked Person is removed.
        self.runDaily(test_args=['--experimental'])
        self.assertIsNot(
            personset.getByName('test-unlinked-person-new'), None)
        self.assertIs(personset.getByName('test-unlinked-person-old'), None)
    def test_accept_copy_archives(self):
        """Test that publications in a copy archive are accepted properly."""
        # Upload some pending packages in a copy archive.
        distroseries = self.factory.makeDistroSeries(distribution=self.distro)
        copy_archive = self.factory.makeArchive(
            distribution=self.distro, purpose=ArchivePurpose.COPY)
        copy_source = self.createWaitingAcceptancePackage(
            archive=copy_archive, distroseries=distroseries)
        # Also upload some stuff in the main archive.
        self.createWaitingAcceptancePackage(distroseries=distroseries)

        # Before accepting, the package should not be published at all.
        published_copy = copy_archive.getPublishedSources(
            name=self.test_package_name)
        # Using .count() until Storm fixes __nonzero__ on SQLObj result
        # sets, then we can use bool() which is far more efficient than
        # counting.
        self.assertEqual(published_copy.count(), 0)

        # Accept the packages.
        script = self.getScript(['--copy-archives'])
        switch_dbuser(self.dbuser)
        script.main()

        # Packages in main archive should not be accepted and published.
        published_main = self.distro.main_archive.getPublishedSources(
            name=self.test_package_name)
        self.assertEqual(published_main.count(), 0)

        # Check the copy archive source was accepted.
        published_copy = copy_archive.getPublishedSources(
            name=self.test_package_name).one()
        self.assertEqual(
            published_copy.status, PackagePublishingStatus.PENDING)
        self.assertEqual(copy_source, published_copy.sourcepackagerelease)
Example #27
0
    def test_BranchJobPruner(self):
        # Garbo should remove jobs completed over 30 days ago.
        switch_dbuser('testadmin')
        store = IMasterStore(Job)

        db_branch = self.factory.makeAnyBranch()
        db_branch.branch_format = BranchFormat.BZR_BRANCH_5
        db_branch.repository_format = RepositoryFormat.BZR_KNIT_1
        Store.of(db_branch).flush()
        branch_job = BranchUpgradeJob.create(
            db_branch, self.factory.makePerson())
        branch_job.job.date_finished = THIRTY_DAYS_AGO

        self.assertEqual(
            store.find(
                BranchJob,
                BranchJob.branch == db_branch.id).count(),
                1)

        self.runDaily()

        switch_dbuser('testadmin')
        self.assertEqual(
            store.find(
                BranchJob,
                BranchJob.branch == db_branch.id).count(),
                0)
    def test_commits_after_each_item(self):
        # Test that the script commits after each item, not just at the end.
        uploads = [
            self.createWaitingAcceptancePackage(
                distroseries=self.factory.makeDistroSeries(
                    distribution=self.distro),
                sourcename='source%d' % i)
            for i in range(3)]

        class UploadCheckingSynchronizer:

            commit_count = 0

            def beforeCompletion(inner_self, txn):
                pass

            def afterCompletion(inner_self, txn):
                if txn.status != 'Committed':
                    return
                inner_self.commit_count += 1
                done_count = len([
                    upload for upload in uploads
                    if upload.package_upload.status ==
                        PackageUploadStatus.DONE])
                self.assertEqual(
                    min(len(uploads), inner_self.commit_count),
                    done_count)

        script = self.getScript([])
        switch_dbuser(self.dbuser)
        synch = UploadCheckingSynchronizer()
        transaction.manager.registerSynch(synch)
        script.main()
        self.assertThat(len(uploads), LessThan(synch.commit_count))
Example #29
0
 def test_unrelated_branch_recipe(self):
     """On tip unrelated recipes are left alone."""
     recipe = self.factory.makeSourcePackageRecipe()
     removeSecurityProxy(recipe).is_stale = False
     switch_dbuser("branchscanner")
     self.makeBzrSync(self.db_branch).syncBranchAndClose()
     self.assertEqual(False, recipe.is_stale)
Example #30
0
    def test_delete_unwanted_files_follows_symlinks(self):
        # In production, our tree has symlinks in it now.  We need to be able
        # to cope.
        # First, let's make sure we have some trash.
        switch_dbuser('testadmin')
        content = 'foo'
        self.client.addFile(
            'foo.txt', len(content), StringIO(content), 'text/plain')
        # Roll back the database changes, leaving the file on disk.
        transaction.abort()

        switch_dbuser(config.librarian_gc.dbuser)

        # Now, we will move the directory containing the trash somewhere else
        # and make a symlink to it.
        original = os.path.join(config.librarian_server.root, '00', '00')
        newdir = tempfile.mkdtemp()
        alt = os.path.join(newdir, '00')
        shutil.move(original, alt)
        os.symlink(alt, original)

        # Now we will do our thing.  This is the actual test.  It used to
        # fail.
        librariangc.delete_unwanted_files(self.con)

        # Clean up.
        os.remove(original)
        shutil.move(alt, original)
        shutil.rmtree(newdir)
    def test_makeOneNewBranch_avoids_need_for_scan(self):
        # makeOneNewBranch sets the appropriate properties of the new branch
        # so a scan is unnecessary.  This can be done because we are making a
        # copy of the source branch.
        db_branch = self.makeOfficialPackageBranch()
        self.factory.makeRevisionsForBranch(db_branch, count=10)
        tip_revision_id = db_branch.last_mirrored_id
        self.assertIsNot(None, tip_revision_id)
        # The makeRevisionsForBranch will create a scan job for the db_branch.
        # We don't really care about that, but what we do care about is that
        # no new jobs are created.
        existing_scan_job_count = len(list(getUtility(IBranchScanJobSource).iterReady()))

        brancher = self.makeNewSeriesAndBrancher(db_branch.distroseries)
        brancher.makeOneNewBranch(db_branch)
        new_branch = brancher.new_distroseries.getSourcePackage(db_branch.sourcepackage.name).getBranch(RELEASE)

        self.assertEqual(tip_revision_id, new_branch.last_mirrored_id)
        self.assertEqual(tip_revision_id, new_branch.last_scanned_id)
        # Make sure that the branch revisions have been copied.
        old_ancestry, old_history = removeSecurityProxy(db_branch).getScannerData()
        new_ancestry, new_history = removeSecurityProxy(new_branch).getScannerData()
        self.assertEqual(old_ancestry, new_ancestry)
        self.assertEqual(old_history, new_history)
        self.assertFalse(new_branch.pending_writes)
        self.assertIs(None, new_branch.stacked_on)
        self.assertEqual(new_branch, db_branch.stacked_on)
        # The script doesn't have permission to create branch jobs, but just
        # to be insanely paranoid.
        switch_dbuser("launchpad")
        scan_jobs = list(getUtility(IBranchScanJobSource).iterReady())
        self.assertEqual(existing_scan_job_count, len(scan_jobs))
Example #32
0
 def test_unrelated_branch(self):
     # On tip change, unrelated snap packages are left alone.
     snap = self.factory.makeSnap()
     removeSecurityProxy(snap).is_stale = False
     switch_dbuser("branchscanner")
     self.makeBzrSync(self.db_branch).syncBranchAndClose()
     self.assertFalse(snap.is_stale)
Example #33
0
 def test_same_branch(self):
     # On tip change, snap packages using this branch become stale.
     snap = self.factory.makeSnap(branch=self.db_branch)
     removeSecurityProxy(snap).is_stale = False
     switch_dbuser("branchscanner")
     self.makeBzrSync(self.db_branch).syncBranchAndClose()
     self.assertTrue(snap.is_stale)
    def setUp(self):
        super(TestRemoveTranslations, self).setUp()
        # Acquire privileges to delete TranslationMessages.  That's not
        # something we normally do.  Actually we should test under
        # rosettaadmin, but that user does not have all the privileges
        # needed to set up this test.  A separate doctest
        # remove-translations-by.txt tests a realistic run of the
        # remove-translations-by.py script under the actual rosettaadmin
        # db user.
        switch_dbuser('postgres')

        # Set up a template with Dutch and German translations.  The
        # messages we set up here are invariant; they remain untouched
        # by deletions done in the test case.
        self.factory = LaunchpadObjectFactory()
        self.nl_pofile = self.factory.makePOFile('nl')
        self.potemplate = self.nl_pofile.potemplate
        self.de_pofile = self.factory.makePOFile('de',
                                                 potemplate=self.potemplate)

        self.nl_message, self.de_message = self._makeMessages(
            "This message is not to be deleted.",
            "Dit bericht mag niet worden verwijderd.",
            "Diese Nachricht soll nicht erloescht werden.")

        self.untranslated_message = self.factory.makePOTMsgSet(
            self.potemplate, 'This message is untranslated.', sequence=0)

        self._checkInvariant()
Example #35
0
 def test_getBranchMergeProposalInvalid(self):
     """InvalidBranchMergeProposalAddress is raised if appropriate."""
     switch_dbuser(config.processmail.dbuser)
     self.assertRaises(InvalidBranchMergeProposalAddress,
                       self.code_handler.getBranchMergeProposal, '')
     self.assertRaises(InvalidBranchMergeProposalAddress,
                       self.code_handler.getBranchMergeProposal, 'mp+abc@')
Example #36
0
 def test_forReviewRequestMessageId(self):
     """Test creating a mailer for a review request."""
     request, requester = self.makeReviewRequest()
     switch_dbuser(config.IBranchMergeProposalJobSource.dbuser)
     mailer = BMPMailer.forReviewRequest(
         request, request.merge_proposal, requester)
     assert mailer.message_id is not None, 'message_id not set'
    def test_permissions(self):
        script_users = [
            'archivepublisher',
            'gina',
            'queued',
            'uploader',
            ]
        dsp = self.factory.makeDistroSeriesParent()
        parent = dsp.parent_series
        derived = dsp.derived_series
        packages = dict(
            (user, self.factory.makeSourcePackageName())
            for user in script_users)
        for user in script_users:
            switch_dbuser(user)
            try:
                create_job(derived, packages[user], parent)
            except ProgrammingError as e:
                self.assertTrue(
                    False,
                    "Database role %s was unable to create a job.  "
                    "Error was: %s" % (user, e))

        # The test is that we get here without exceptions.
        pass
Example #38
0
    def test_forCreation_with_review_request_and_private_bug(self):
        """Correctly format list of reviewers and bug info.

        Private bugs should not be listed in the email unless authorised.
        """
        reviewer = self.factory.makePerson(name='review-person')
        bmp, subscriber = self.makeProposalWithSubscriber(reviewer=reviewer)

        # Create and subscribe the owner of the private bug
        private_bug_owner = self.factory.makePerson(email="*****@*****.**")
        bmp.source_branch.subscribe(private_bug_owner,
            BranchSubscriptionNotificationLevel.NOEMAIL, None,
            CodeReviewNotificationLevel.FULL, private_bug_owner)

        # Create and link the bugs to the branch
        bug = self.factory.makeBug(title='I am a bug')
        bugtask = bug.default_bugtask
        bmp.source_branch.linkBug(bug, bmp.registrant)
        private_bug = self.factory.makeBug(
            title='I am a private bug', owner=private_bug_owner,
            information_type=InformationType.USERDATA)
        private_bugtask = private_bug.default_bugtask
        with person_logged_in(private_bug_owner):
            bmp.source_branch.linkBug(private_bug, bmp.registrant)

        # Set up the mailer
        bmp.nominateReviewer(reviewer, bmp.registrant, None)
        switch_dbuser(config.IBranchMergeProposalJobSource.dbuser)
        mailer = BMPMailer.forCreation(bmp, bmp.registrant)

        # A non authorised email recipient doesn't see the private bug.
        ctrl = mailer.generateEmail('*****@*****.**', subscriber)
        expected = (
            '\nRequested reviews:'
            '\n  Review-person (review-person)'
            '\nRelated bugs:'
            '\n  %s'
            '\n  %s\n'
            '\nFor more details, see:\n'
            '%s'
            '\n--' % (bugtask.title, canonical_url(bugtask),
                      canonical_url(bmp)))
        self.assertIn(expected, ctrl.body)

        # An authorised email recipient does see the private bug.
        ctrl = mailer.generateEmail('*****@*****.**', private_bug_owner)
        expected = (
            '\nRequested reviews:'
            '\n  Review-person (review-person)'
            '\nRelated bugs:'
            '\n  %s'
            '\n  %s'
            '\n  %s'
            '\n  %s\n'
            '\nFor more details, see:\n'
            '%s'
            '\n--' % (bugtask.title, canonical_url(bugtask),
                      private_bugtask.title, canonical_url(private_bugtask),
                      canonical_url(bmp)))
        self.assertIn(expected, ctrl.body)
    def becomeTheApprover(self):
        """Assume the database role of the translations branch scanner.

        This is the role that the TranslationsBranchApprover is actually
        run under.
        """
        switch_dbuser("translationsbranchscanner")
    def test_multiple_parents_do_not_close_bugs(self):
        # The initialization does not close the bugs on the copied
        # publications (and thus does not try to access the bug table).
        parent1, parent2 = self.setUpParents(
            packages1={'p1': '0.1-1'}, packages2={'p2': '2.1'})
        child = self.factory.makeDistroSeries()
        switch_dbuser('initializedistroseries')

        # Patch close_bugs_for_sourcepublication to be able to record if
        # the method has been called.
        fakeCloseBugs = FakeMethod()
        from lp.soyuz.scripts import packagecopier as packagecopier_module
        self.patch(
            packagecopier_module,
            'close_bugs_for_sourcepublication',
            fakeCloseBugs)

        child = self._fullInitialize(
            [parent1, parent2], child=child)
        # Make sure the initialization was successful.
        self.assertBinPackagesAndVersions(
            child,
            [(u'p1', u'0.1-1'), (u'p2', u'2.1')])
        # Assert that close_bugs_for_sourcepublication has not been
        # called.
        self.assertEqual(
            0,
            fakeCloseBugs.call_count)
        # Switch back to launchpad_main to be able to cleanup the
        # feature flags.
        switch_dbuser('launchpad_main')
 def runJob(self, job):
     switch_dbuser('distroseriesdifferencejob')
     dsdjob = DistroSeriesDifferenceJob(job)
     dsdjob.start()
     dsdjob.run()
     dsdjob.complete()
     switch_dbuser('launchpad')
 def test_unrelated_branch_recipe(self):
     """On tip unrelated recipes are left alone."""
     recipe = self.factory.makeSourcePackageRecipe()
     removeSecurityProxy(recipe).is_stale = False
     switch_dbuser("branchscanner")
     self.makeBzrSync(self.db_branch).syncBranchAndClose()
     self.assertEqual(False, recipe.is_stale)
 def setUp(self):
     super(EmailNotificationTestBase, self).setUp()
     login('*****@*****.**')
     self.product_owner = self.factory.makePerson(name="product-owner")
     self.person = self.factory.makePerson(name="sample-person")
     self.product = self.factory.makeProduct(owner=self.product_owner)
     self.product_subscriber = self.factory.makePerson(
         name="product-subscriber")
     self.product.addBugSubscription(
         self.product_subscriber, self.product_subscriber)
     self.bug_subscriber = self.factory.makePerson(name="bug-subscriber")
     self.bug_owner = self.factory.makePerson(name="bug-owner")
     self.bug = self.factory.makeBug(
         target=self.product, owner=self.bug_owner,
         information_type=InformationType.USERDATA)
     self.reporter = self.bug.owner
     self.bug.subscribe(self.bug_subscriber, self.reporter)
     [self.product_bugtask] = self.bug.bugtasks
     commit()
     login('*****@*****.**')
     switch_dbuser(config.malone.bugnotification_dbuser)
     self.now = datetime.now(pytz.UTC)
     self.ten_minutes_ago = self.now - timedelta(minutes=10)
     self.notification_set = getUtility(IBugNotificationSet)
     for notification in self.notification_set.getNotificationsToSend():
         notification.date_emailed = self.now
     flush_database_updates()
    def test_robustness(self):
        """Test that a broken package doesn't block the publication of other
        packages."""
        # Attempt to upload one source to a supported series.
        # The record is created first and then the status of the series
        # is changed from DEVELOPMENT to SUPPORTED, otherwise it's impossible
        # to create the record.
        distroseries = self.factory.makeDistroSeries(distribution=self.distro)
        # This creates a broken publication.
        self.createWaitingAcceptancePackage(distroseries=distroseries,
                                            sourcename="notaccepted")
        distroseries.status = SeriesStatus.SUPPORTED
        # Also upload some other things.
        other_distroseries = self.factory.makeDistroSeries(
            distribution=self.distro)
        self.createWaitingAcceptancePackage(distroseries=other_distroseries)
        script = self.getScript([])
        switch_dbuser(self.dbuser)
        script.main()

        # The other source should be published now.
        published_main = self.distro.main_archive.getPublishedSources(
            name=self.test_package_name)
        self.assertEqual(published_main.count(), 1)

        # And an oops should be filed for the first.
        self.assertEqual(1, len(self.oopses))
        error_report = self.oopses[0]
        expected_error = "Failure processing queue_item"
        self.assertStartsWith(error_report['req_vars']['error-explanation'],
                              expected_error)
    def test_accept_copy_archives(self):
        """Test that publications in a copy archive are accepted properly."""
        # Upload some pending packages in a copy archive.
        distroseries = self.factory.makeDistroSeries(distribution=self.distro)
        copy_archive = self.factory.makeArchive(distribution=self.distro,
                                                purpose=ArchivePurpose.COPY)
        copy_source = self.createWaitingAcceptancePackage(
            archive=copy_archive, distroseries=distroseries)
        # Also upload some stuff in the main archive.
        self.createWaitingAcceptancePackage(distroseries=distroseries)

        # Before accepting, the package should not be published at all.
        published_copy = copy_archive.getPublishedSources(
            name=self.test_package_name)
        # Using .count() until Storm fixes __nonzero__ on SQLObj result
        # sets, then we can use bool() which is far more efficient than
        # counting.
        self.assertEqual(published_copy.count(), 0)

        # Accept the packages.
        script = self.getScript(['--copy-archives'])
        switch_dbuser(self.dbuser)
        script.main()

        # Packages in main archive should not be accepted and published.
        published_main = self.distro.main_archive.getPublishedSources(
            name=self.test_package_name)
        self.assertEqual(published_main.count(), 0)

        # Check the copy archive source was accepted.
        published_copy = copy_archive.getPublishedSources(
            name=self.test_package_name).one()
        self.assertEqual(published_copy.status,
                         PackagePublishingStatus.PENDING)
        self.assertEqual(copy_source, published_copy.sourcepackagerelease)
    def test_commits_after_each_item(self):
        # Test that the script commits after each item, not just at the end.
        uploads = [
            self.createWaitingAcceptancePackage(
                distroseries=self.factory.makeDistroSeries(
                    distribution=self.distro),
                sourcename='source%d' % i) for i in range(3)
        ]

        class UploadCheckingSynchronizer:

            commit_count = 0

            def beforeCompletion(inner_self, txn):
                pass

            def afterCompletion(inner_self, txn):
                if txn.status != 'Committed':
                    return
                inner_self.commit_count += 1
                done_count = len([
                    upload for upload in uploads
                    if upload.package_upload.status == PackageUploadStatus.DONE
                ])
                self.assertEqual(min(len(uploads), inner_self.commit_count),
                                 done_count)

        script = self.getScript([])
        switch_dbuser(self.dbuser)
        synch = UploadCheckingSynchronizer()
        transaction.manager.registerSynch(synch)
        script.main()
        self.assertThat(len(uploads), LessThan(synch.commit_count))
Example #47
0
    def test_order_by_soyuz_package_karma(self):
        # Returned archives are ordered by the soyuz karma of the
        # package uploaders for the particular package

        related_archives = self.source_package.findRelatedArchives()
        related_archive_names = [archive.name for archive in related_archives]

        self.assertEqual(related_archive_names, [
            'gedit-nightly',
            'gedit-beta',
        ])

        # Update the soyuz karma for person_beta for this package so that
        # it is greater than person_nightly's.
        switch_dbuser('karma')
        self.person_beta_karma.karma_total = 202
        switch_dbuser('launchpad')

        related_archives = self.source_package.findRelatedArchives()
        related_archive_names = [archive.name for archive in related_archives]

        self.assertEqual(related_archive_names, [
            'gedit-beta',
            'gedit-nightly',
        ])
Example #48
0
 def test_forCreation_without_bugs(self):
     """If there are no related bugs, omit 'Related bugs'."""
     bmp, subscriber = self.makeProposalWithSubscriber()
     switch_dbuser(config.IBranchMergeProposalJobSource.dbuser)
     mailer = BMPMailer.forCreation(bmp, bmp.registrant)
     ctrl = mailer.generateEmail('*****@*****.**', subscriber)
     self.assertNotIn('Related bugs:\n', ctrl.body)
Example #49
0
    def test_process_for_imported_branch(self):
        """Make sure that the database user is able refer to import branches.

        Import branches have different permission checks than other branches.

        Permission to mark a merge proposal as approved checks launchpad.Edit
        of the target branch, or membership of the review team on the target
        branch.  For import branches launchpad.Edit also checks the registrant
        of the code import if there is one, and membership of vcs-imports.  So
        if someone is attempting to review something on an import branch, but
        they don't have launchpad.Edit but are a member of the review team,
        then a check against the code import is done.
        """
        mail = self.factory.makeSignedMessage(body=' merge approved')
        code_import = self.factory.makeCodeImport()
        bmp = self.factory.makeBranchMergeProposal(
            target_branch=code_import.branch)
        email_addr = bmp.address
        switch_dbuser(config.processmail.dbuser)
        pop_notifications()
        self.code_handler.process(mail, email_addr, None)
        notification = pop_notifications()[0]
        # The returned message is a multipart message, the first part is
        # the message, and the second is the original message.
        message, original = notification.get_payload()
        self.assertTrue(
            "You are not a reviewer for the branch" in
            message.get_payload(decode=True))
 def test_getDerivedSeries(self):
     # Check that DB users can query derived series.
     script_users = ['queued']
     dsp = self.factory.makeDistroSeriesParent()
     for user in script_users:
         switch_dbuser(user)
         list(dsp.parent_series.getDerivedSeries())
Example #51
0
 def test_forModificationHasMsgId(self):
     """Ensure the right delta is filled out if there is a change."""
     merge_proposal = self.factory.makeBranchMergeProposal()
     switch_dbuser(config.IBranchMergeProposalJobSource.dbuser)
     mailer = BMPMailer.forModification(
         merge_proposal, 'the diff', merge_proposal.registrant)
     self.assertIsNot(None, mailer.message_id, 'message_id not set')
Example #52
0
 def test_forCreation_without_commit_message(self):
     """If there is no commit message, email should say 'None Specified.'"""
     bmp, subscriber = self.makeProposalWithSubscriber()
     bmp.commit_message = None
     switch_dbuser(config.IBranchMergeProposalJobSource.dbuser)
     mailer = BMPMailer.forCreation(bmp, bmp.registrant)
     ctrl = mailer.generateEmail('*****@*****.**', subscriber)
     self.assertNotIn('Commit message:', ctrl.body)
 def test_instruction_branch_recipe(self):
     """On tip change, recipes including this branch become stale."""
     recipe = self.factory.makeSourcePackageRecipe(
         branches=[self.factory.makeBranch(), self.db_branch])
     removeSecurityProxy(recipe).is_stale = False
     switch_dbuser("branchscanner")
     self.makeBzrSync(self.db_branch).syncBranchAndClose()
     self.assertEqual(True, recipe.is_stale)
Example #54
0
 def test_inReplyTo(self):
     """Ensure that messages are in reply to the root"""
     bmp, subscriber = self.makeProposalWithSubscriber()
     bmp.root_message_id = '<root-message-id>'
     switch_dbuser(config.IBranchMergeProposalJobSource.dbuser)
     mailer = BMPMailer.forCreation(bmp, bmp.registrant)
     ctrl = mailer.generateEmail('*****@*****.**', subscriber)
     self.assertEqual('<root-message-id>', ctrl.headers['In-Reply-To'])
Example #55
0
 def test_forCreation_with_prerequisite_branch(self):
     """Correctly format list of reviewers."""
     bmp, subscriber = self.makeProposalWithSubscriber(prerequisite=True)
     switch_dbuser(config.IBranchMergeProposalJobSource.dbuser)
     mailer = BMPMailer.forCreation(bmp, bmp.registrant)
     ctrl = mailer.generateEmail('*****@*****.**', subscriber)
     prereq = bmp.prerequisite_branch.bzr_identity
     self.assertIn(' with %s as a prerequisite.' % prereq, ctrl.body)
    def setUp(self):
        super(TestBugSummary, self).setUp()

        # Some things we are testing are impossible as mere mortals,
        # but might happen from the SQL command line.
        switch_dbuser('testadmin')

        self.store = IMasterStore(BugSummary)
Example #57
0
    def testSetUp(cls):
        """Fixture replicating the process-mail.py environment.

        This zopeless script uses the regular security policy and
        connects as a specific DB user.
        """
        cls._old_policy = setSecurityPolicy(LaunchpadSecurityPolicy)
        switch_dbuser(config.processmail.dbuser)