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 #2
0
 def setUp(self):
     login(ANONYMOUS)
     self._original_launch_bag = getUtility(ILaunchBag)
     self.factory = LaunchpadObjectFactory()
     self.launch_bag = self.installLaunchBag(
         user=self.factory.makePerson(), product=self.factory.makeProduct())
     self.popup = self.makeBranchPopup()
    def setUp(self):
        super(TestHandleStatusMixin, self).setUp()
        self.factory = LaunchpadObjectFactory()
        self.build = self.makeBuild()
        # For the moment, we require a builder for the build so that
        # handleStatus_OK can get a reference to the slave.
        self.builder = self.factory.makeBuilder()
        self.build.buildqueue_record.markAsBuilding(self.builder)
        self.slave = WaitingSlave('BuildStatus.OK')
        self.slave.valid_file_hashes.append('test_file_hash')
        self.interactor = BuilderInteractor()
        self.behaviour = self.interactor.getBuildBehaviour(
            self.build.buildqueue_record, self.builder, self.slave)

        # We overwrite the buildmaster root to use a temp directory.
        tempdir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, tempdir)
        self.upload_root = tempdir
        tmp_builddmaster_root = """
        [builddmaster]
        root: %s
        """ % self.upload_root
        config.push('tmp_builddmaster_root', tmp_builddmaster_root)

        # We stub out our builds getUploaderCommand() method so
        # we can check whether it was called as well as
        # verifySuccessfulUpload().
        removeSecurityProxy(
            self.build).verifySuccessfulUpload = FakeMethod(result=True)
Example #4
0
def example(request, data):
    # This is a test fixture.  You will want to write your own, and
    # delete this one.  See the parallel
    # standard_yuixhr_test_template.js to see how to call fixtures
    # from your Javascript tests.
    #
    # A test fixture prepares the application for your test.  You can
    # do whatever you need here, including creating objects with an
    # object factory and logging the browser in as a given user.
    # You'll see an example below.
    #
    # Test fixtures can also return information back to your test.
    # Simply stuff the information you want into the "data" dict.  It
    # will be converted into JSON and sent back to the Javascript
    # caller.  Even Launchpad objects are converted, using the
    # standard lazr.restful mechanism.  This can be useful in several
    # ways.  Here are three examples.
    #
    # First, you can communicate information about the objects you
    # have created in the setup so that the Javascript knows what URLs
    # to use.  The code in this function has an example of this,
    # below.
    #
    # Second, you can return information about verifying some aspect
    # of the database state, so your Javascript test can easily assert
    # some fact that is not usually easily exposed to it.
    #
    # Finally, you can stash information that your teardown might
    # need.  You shouldn't usually need to clean anything up, because
    # the database and librarian are reset after every test, but if
    # you do set something up that needs an explicit teardown, you can
    # stash JSON-serializable information in "data" that the teardown
    # can use to know what to clean up.
    #
    # You can compose these setups and teardowns as well, using .extend.
    # There is a small example of this as well, below.
    #
    # As a full example, we will create an administrator and another
    # person; we will have the administrator create an object; we will
    # log the browser in as the other person; and we will stash
    # information about the object and the two people in the data
    # object.
    #
    # Again, this is a semi-random example.  Rip this whole fixture
    # out, and write the ones that you need.
    factory = LaunchpadObjectFactory()
    data['admin'] = factory.makeAdministrator()
    data['user'] = factory.makePerson()
    with person_logged_in(data['admin']):
        data['product'] = factory.makeProduct(owner=data['admin'])
    # This logs the browser in as a given person.  You need to use
    # this function for that purpose--the standard lp.testing login
    # functions are insufficient.
    login_as_person(data['user'])
    # Now we've done everything we said we would.  Let's imagine that
    # we had to also write some file to disk that would need to be
    # cleaned up at the end of the test.  We might stash information
    # about that in "data" too.
    data['some random data we might need for cleaning up'] = 'rutebega'
 def test_scan_with_nothing_to_dispatch(self):
     factory = LaunchpadObjectFactory()
     builder = factory.makeBuilder()
     self.patch(BuilderSlave, 'makeBuilderSlave', FakeMethod(OkSlave()))
     transaction.commit()
     scanner = self._getScanner(builder_name=builder.name)
     d = scanner.scan()
     return d.addCallback(self._checkNoDispatch, builder)
 def setUp(self):
     """Set up context to test in."""
     super(TestGetGuessedPOFile, self).setUp()
     self.queue = getUtility(ITranslationImportQueue)
     self.factory = LaunchpadObjectFactory()
     self.distribution = self.factory.makeDistribution('boohoo')
     self.distroseries = self.factory.makeDistroSeries(self.distribution)
     self.uploaderperson = self.factory.makePerson()
Example #7
0
def create_ppa(distribution, person, name):
    """Create a PPA for `person`."""
    ppa = LaunchpadObjectFactory().makeArchive(
        distribution=distribution, owner=person, name=name, virtualized=False,
        description="Automatically created test PPA.")
    ppa.external_dependencies = (
        "deb http://archive.ubuntu.com/ubuntu %(series)s "
        "main restricted universe multiverse\n")
 def test_scan_with_nothing_to_dispatch(self):
     factory = LaunchpadObjectFactory()
     builder = factory.makeBuilder()
     self.patch(BuilderSlave, 'makeBuilderSlave', FakeMethod(OkSlave()))
     transaction.commit()
     scanner = self._getScanner(builder_name=builder.name)
     d = scanner.scan()
     return d.addCallback(self._checkNoDispatch, builder)
Example #9
0
    def create_test_product(self):
        """Create a test product with `LaunchpadObjectFactory`.

        Returns the new object's name.
        """
        factory = LaunchpadObjectFactory()
        product = factory.makeProduct(official_malone=True)
        transaction.commit()
        return product.name
Example #10
0
    def create_test_product(self):
        """Create a test product with `LaunchpadObjectFactory`.

        Returns the new object's name.
        """
        factory = LaunchpadObjectFactory()
        product = factory.makeProduct(official_malone=True)
        transaction.commit()
        return product.name
Example #11
0
 def setUp(self):
     BzrTestCase.setUp(self)
     login('*****@*****.**')
     self.factory = LaunchpadObjectFactory()
     nuke_codeimport_sample_data()
     self.repo_path = tempfile.mkdtemp()
     self.disable_directory_isolation()
     self.addCleanup(shutil.rmtree, self.repo_path)
     self.foreign_commit_count = 0
Example #12
0
class TestBuildNotifications(TrialTestCase):

    layer = LaunchpadZopelessLayer

    def setUp(self):
        super(TestBuildNotifications, self).setUp()
        from lp.testing.factory import LaunchpadObjectFactory
        self.factory = LaunchpadObjectFactory()

    def prepareBehavior(self, fake_successful_upload=False):
        self.queue_record = self.factory.makeSourcePackageRecipeBuildJob()
        build = self.queue_record.specific_job.build
        build.updateStatus(BuildStatus.FULLYBUILT)
        if fake_successful_upload:
            removeSecurityProxy(build).verifySuccessfulUpload = FakeMethod(
                result=True)
            # We overwrite the buildmaster root to use a temp directory.
            tempdir = tempfile.mkdtemp()
            self.addCleanup(shutil.rmtree, tempdir)
            self.upload_root = tempdir
            tmp_builddmaster_root = """
            [builddmaster]
            root: %s
            """ % self.upload_root
            config.push('tmp_builddmaster_root', tmp_builddmaster_root)
            self.addCleanup(config.pop, 'tmp_builddmaster_root')
        self.queue_record.builder = self.factory.makeBuilder()
        slave = WaitingSlave('BuildStatus.OK')
        return BuilderInteractor.getBuildBehavior(self.queue_record,
                                                  self.queue_record.builder,
                                                  slave)

    def assertDeferredNotifyCount(self, status, behavior, expected_count):
        d = behavior.handleStatus(self.queue_record, status, {'filemap': {}})

        def cb(result):
            self.assertEqual(expected_count, len(pop_notifications()))

        d.addCallback(cb)
        return d

    def test_handleStatus_PACKAGEFAIL(self):
        """Failing to build the package immediately sends a notification."""
        return self.assertDeferredNotifyCount("PACKAGEFAIL",
                                              self.prepareBehavior(), 1)

    def test_handleStatus_OK(self):
        """Building the source package does _not_ immediately send mail.

        (The archive uploader mail send one later.
        """
        return self.assertDeferredNotifyCount("OK", self.prepareBehavior(), 0)

    def test_handleStatus_OK_successful_upload(self):
        return self.assertDeferredNotifyCount("OK", self.prepareBehavior(True),
                                              0)
class TestBuildNotifications(TrialTestCase):

    layer = LaunchpadZopelessLayer

    def setUp(self):
        super(TestBuildNotifications, self).setUp()
        from lp.testing.factory import LaunchpadObjectFactory

        self.factory = LaunchpadObjectFactory()

    def prepareBehavior(self, fake_successful_upload=False):
        self.queue_record = self.factory.makeSourcePackageRecipeBuildJob()
        build = self.queue_record.specific_job.build
        build.updateStatus(BuildStatus.FULLYBUILT)
        if fake_successful_upload:
            removeSecurityProxy(build).verifySuccessfulUpload = FakeMethod(result=True)
            # We overwrite the buildmaster root to use a temp directory.
            tempdir = tempfile.mkdtemp()
            self.addCleanup(shutil.rmtree, tempdir)
            self.upload_root = tempdir
            tmp_builddmaster_root = (
                """
            [builddmaster]
            root: %s
            """
                % self.upload_root
            )
            config.push("tmp_builddmaster_root", tmp_builddmaster_root)
            self.addCleanup(config.pop, "tmp_builddmaster_root")
        self.queue_record.builder = self.factory.makeBuilder()
        slave = WaitingSlave("BuildStatus.OK")
        return BuilderInteractor.getBuildBehavior(self.queue_record, self.queue_record.builder, slave)

    def assertDeferredNotifyCount(self, status, behavior, expected_count):
        d = behavior.handleStatus(self.queue_record, status, {"filemap": {}})

        def cb(result):
            self.assertEqual(expected_count, len(pop_notifications()))

        d.addCallback(cb)
        return d

    def test_handleStatus_PACKAGEFAIL(self):
        """Failing to build the package immediately sends a notification."""
        return self.assertDeferredNotifyCount("PACKAGEFAIL", self.prepareBehavior(), 1)

    def test_handleStatus_OK(self):
        """Building the source package does _not_ immediately send mail.

        (The archive uploader mail send one later.
        """
        return self.assertDeferredNotifyCount("OK", self.prepareBehavior(), 0)

    def test_handleStatus_OK_successful_upload(self):
        return self.assertDeferredNotifyCount("OK", self.prepareBehavior(True), 0)
Example #14
0
def set_service_usage(pillar_name, **kw):
    factory = LaunchpadObjectFactory()
    with celebrity_logged_in('admin'):
        pillar = getUtility(IPillarNameSet)[pillar_name]
        for attr, service_usage_name in kw.items():
            service_usage = getattr(ServiceUsage, service_usage_name)
            if attr == 'bug_tracking_usage':
                pillar.official_malone = (
                    service_usage == ServiceUsage.LAUNCHPAD)
                if service_usage == ServiceUsage.EXTERNAL:
                    pillar.bugtracker = factory.makeBugTracker()

            # if we're setting codehosting on product things get trickier.
            elif attr == 'codehosting_usage' and IProduct.providedBy(pillar):
                if service_usage == ServiceUsage.LAUNCHPAD:
                    branch = factory.makeProductBranch(product=pillar)
                    product_series = factory.makeProductSeries(product=pillar,
                                                               branch=branch)
                    pillar.development_focus = product_series
                elif service_usage == ServiceUsage.EXTERNAL:
                    branch = factory.makeProductBranch(
                        product=pillar, branch_type=BranchType.MIRRORED)
                    product_series = factory.makeProductSeries(product=pillar,
                                                               branch=branch)
                    pillar.development_focus = product_series
                elif service_usage == ServiceUsage.UNKNOWN:
                    branch = factory.makeProductBranch(product=pillar)
                    product_series = factory.makeProductSeries(product=pillar)
                    pillar.development_focus = product_series
            else:
                setattr(pillar, attr, service_usage)
Example #15
0
    def setUp(self):
        login('*****@*****.**')

        factory = LaunchpadObjectFactory()
        branches = [factory.makeAnyBranch() for count in range(5)]
        branch_ids = [branch.id for branch in branches]
        for branch in branches:
            factory.makeRevisionsForBranch(branch)
        # Retrieve the updated branches (due to transaction boundaries).
        branch_set = getUtility(IBranchLookup)
        self.branches = [branch_set.get(id) for id in branch_ids]
        self.revision_set = getUtility(IRevisionSet)
    def setUp(self):
        login('*****@*****.**')

        factory = LaunchpadObjectFactory()
        branches = [factory.makeAnyBranch() for count in range(5)]
        branch_ids = [branch.id for branch in branches]
        for branch in branches:
            factory.makeRevisionsForBranch(branch)
        # Retrieve the updated branches (due to transaction boundaries).
        branch_set = getUtility(IBranchLookup)
        self.branches = [branch_set.get(id) for id in branch_ids]
        self.revision_set = getUtility(IRevisionSet)
    def test_checkForNewBuilders(self):
        # Test that checkForNewBuilders() detects a new builder

        # The basic case, where no builders are added.
        builder_scanner = self._getScanner()
        self.assertEqual([], builder_scanner.checkForNewBuilders())

        # Add two builders and ensure they're returned.
        new_builders = ["scooby", "lassie"]
        factory = LaunchpadObjectFactory()
        for builder_name in new_builders:
            factory.makeBuilder(name=builder_name)
        self.assertEqual(new_builders, builder_scanner.checkForNewBuilders())
def set_service_usage(pillar_name, **kw):
    factory = LaunchpadObjectFactory()
    with celebrity_logged_in('admin'):
        pillar = getUtility(IPillarNameSet)[pillar_name]
        for attr, service_usage_name in kw.items():
            service_usage = getattr(ServiceUsage, service_usage_name)
            if attr == 'bug_tracking_usage':
                pillar.official_malone = (
                    service_usage == ServiceUsage.LAUNCHPAD)
                if service_usage == ServiceUsage.EXTERNAL:
                    pillar.bugtracker = factory.makeBugTracker()

            # if we're setting codehosting on product things get trickier.
            elif attr == 'codehosting_usage' and IProduct.providedBy(pillar):
                if service_usage == ServiceUsage.LAUNCHPAD:
                    branch = factory.makeProductBranch(product=pillar)
                    product_series = factory.makeProductSeries(
                        product=pillar,
                        branch=branch)
                    pillar.development_focus = product_series
                elif service_usage == ServiceUsage.EXTERNAL:
                    branch = factory.makeProductBranch(
                        product=pillar,
                        branch_type=BranchType.MIRRORED)
                    product_series = factory.makeProductSeries(
                        product=pillar,
                        branch=branch)
                    pillar.development_focus = product_series
                elif service_usage == ServiceUsage.UNKNOWN:
                    branch = factory.makeProductBranch(product=pillar)
                    product_series = factory.makeProductSeries(
                        product=pillar)
                    pillar.development_focus = product_series
            else:
                setattr(pillar, attr, service_usage)
    def test_checkForNewBuilders(self):
        # Test that checkForNewBuilders() detects a new builder

        # The basic case, where no builders are added.
        builder_scanner = self._getScanner()
        self.assertEqual([], builder_scanner.checkForNewBuilders())

        # Add two builders and ensure they're returned.
        new_builders = ["scooby", "lassie"]
        factory = LaunchpadObjectFactory()
        for builder_name in new_builders:
            factory.makeBuilder(name=builder_name)
        self.assertEqual(
            new_builders, builder_scanner.checkForNewBuilders())
Example #20
0
def setGlobs(test, future=False):
    """Add the common globals for testing system documentation."""
    test.globs['ANONYMOUS'] = ANONYMOUS
    test.globs['login'] = login
    test.globs['login_person'] = login_person
    test.globs['logout'] = logout
    test.globs['ILaunchBag'] = ILaunchBag
    test.globs['getUtility'] = getUtility
    test.globs['transaction'] = transaction
    test.globs['flush_database_updates'] = flush_database_updates
    test.globs['create_view'] = create_view
    test.globs['create_initialized_view'] = create_initialized_view
    test.globs['factory'] = LaunchpadObjectFactory()
    test.globs['ordered_dict_as_string'] = ordered_dict_as_string
    test.globs['verifyObject'] = verifyObject
    test.globs['pretty'] = pprint.PrettyPrinter(width=1).pformat
    test.globs['stop'] = stop
    test.globs['launchpadlib_for'] = launchpadlib_for
    test.globs['launchpadlib_credentials_for'] = launchpadlib_credentials_for
    test.globs['oauth_access_token_for'] = oauth_access_token_for

    if future:
        import __future__
        for future_item in ('absolute_import', 'print_function',
                            'unicode_literals'):
            test.globs[future_item] = getattr(__future__, future_item)
 def test_checkForNewBuilders_detects_builder_only_once(self):
     # checkForNewBuilders() only detects a new builder once.
     builder_scanner = self._getScanner()
     self.assertEqual([], builder_scanner.checkForNewBuilders())
     LaunchpadObjectFactory().makeBuilder(name="sammy")
     self.assertEqual(["sammy"], builder_scanner.checkForNewBuilders())
     self.assertEqual([], builder_scanner.checkForNewBuilders())
    def setUp(self):
        super(TestHandleStatusMixin, self).setUp()
        self.factory = LaunchpadObjectFactory()
        self.build = self.makeBuild()
        # For the moment, we require a builder for the build so that
        # handleStatus_OK can get a reference to the slave.
        self.builder = self.factory.makeBuilder()
        self.build.buildqueue_record.markAsBuilding(self.builder)
        self.slave = WaitingSlave('BuildStatus.OK')
        self.slave.valid_file_hashes.append('test_file_hash')
        self.interactor = BuilderInteractor()
        self.behavior = self.interactor.getBuildBehavior(
            self.build.buildqueue_record, self.builder, self.slave)

        # We overwrite the buildmaster root to use a temp directory.
        tempdir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, tempdir)
        self.upload_root = tempdir
        tmp_builddmaster_root = """
        [builddmaster]
        root: %s
        """ % self.upload_root
        config.push('tmp_builddmaster_root', tmp_builddmaster_root)

        # We stub out our builds getUploaderCommand() method so
        # we can check whether it was called as well as
        # verifySuccessfulUpload().
        removeSecurityProxy(self.build).verifySuccessfulUpload = FakeMethod(
            result=True)
    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()
 def setUp(self):
     login(ANONYMOUS)
     self._original_launch_bag = getUtility(ILaunchBag)
     self.factory = LaunchpadObjectFactory()
     self.launch_bag = self.installLaunchBag(
         user=self.factory.makePerson(),
         product=self.factory.makeProduct())
     self.popup = self.makeBranchPopup()
 def setUp(self):
     """Set up context to test in."""
     super(TestGetGuessedPOFile, self).setUp()
     self.queue = getUtility(ITranslationImportQueue)
     self.factory = LaunchpadObjectFactory()
     self.distribution = self.factory.makeDistribution('boohoo')
     self.distroseries = self.factory.makeDistroSeries(self.distribution)
     self.uploaderperson = self.factory.makePerson()
 def setUp(self):
     BzrTestCase.setUp(self)
     login('*****@*****.**')
     self.factory = LaunchpadObjectFactory()
     nuke_codeimport_sample_data()
     self.repo_path = tempfile.mkdtemp()
     self.disable_directory_isolation()
     self.addCleanup(shutil.rmtree, self.repo_path)
     self.foreign_commit_count = 0
Example #27
0
def setUpGlobs(test):
    test.globs['transaction'] = transaction
    test.globs['http'] = UnstickyCookieHTTPCaller()
    test.globs['webservice'] = LaunchpadWebServiceCaller(
        'launchpad-library', 'salgado-change-anything')
    test.globs['public_webservice'] = LaunchpadWebServiceCaller(
        'foobar123451432', 'salgado-read-nonprivate')
    test.globs['user_webservice'] = LaunchpadWebServiceCaller(
        'launchpad-library', 'nopriv-read-nonprivate')
    test.globs['anon_webservice'] = LaunchpadWebServiceCaller(
        'launchpad-library', '')
    test.globs['setupBrowser'] = setupBrowser
    test.globs['setupDTCBrowser'] = setupDTCBrowser
    test.globs['setupRosettaExpertBrowser'] = setupRosettaExpertBrowser
    test.globs['browser'] = setupBrowser()
    test.globs['anon_browser'] = setupBrowser()
    test.globs['user_browser'] = setupBrowser(
        auth="Basic [email protected]:test")
    test.globs['admin_browser'] = setupBrowser(
        auth="Basic [email protected]:test")

    test.globs['ANONYMOUS'] = ANONYMOUS
    # If a unicode URL is opened by the test browswer, later navigation
    # raises ValueError exceptions in /usr/lib/python2.4/Cookie.py
    test.globs['canonical_url'] = safe_canonical_url
    test.globs['factory'] = LaunchpadObjectFactory()
    test.globs['find_tag_by_id'] = find_tag_by_id
    test.globs['first_tag_by_class'] = first_tag_by_class
    test.globs['find_tags_by_class'] = find_tags_by_class
    test.globs['find_portlet'] = find_portlet
    test.globs['find_main_content'] = find_main_content
    test.globs['print_feedback_messages'] = print_feedback_messages
    test.globs['print_table'] = print_table
    test.globs['extract_link_from_tag'] = extract_link_from_tag
    test.globs['extract_text'] = extract_text
    test.globs['launchpadlib_for'] = launchpadlib_for
    test.globs['login'] = login
    test.globs['login_person'] = login_person
    test.globs['logout'] = logout
    test.globs['parse_relationship_section'] = parse_relationship_section
    test.globs['pretty'] = pprint.PrettyPrinter(width=1).pformat
    test.globs['print_action_links'] = print_action_links
    test.globs['print_errors'] = print_errors
    test.globs['print_location'] = print_location
    test.globs['print_location_apps'] = print_location_apps
    test.globs['print_navigation_links'] = print_navigation_links
    test.globs['print_portlet_links'] = print_portlet_links
    test.globs['print_comments'] = print_comments
    test.globs['print_submit_buttons'] = print_submit_buttons
    test.globs['print_radio_button_field'] = print_radio_button_field
    test.globs['print_batch_header'] = print_batch_header
    test.globs['print_ppa_packages'] = print_ppa_packages
    test.globs['print_self_link_of_entries'] = print_self_link_of_entries
    test.globs['print_tag_with_id'] = print_tag_with_id
    test.globs['PageTestLayer'] = PageTestLayer
    test.globs['stop'] = stop
Example #28
0
def make_running_import(code_import=None,
                        machine=None,
                        date_started=None,
                        factory=None,
                        logtail=None):
    """Return a code import with a running job.

    :param code_import: The code import to create the job for.  If None, an
        anonymous CodeImport is created.
    :param machine: The `CodeImportMachine` to associate with the running
        job.  If None, an anonymous CodeImportMachine is created.
    :param date_started: If specified this overrides the UTC_NOW timestamp
        of the newly started job.
    :param factory: The LaunchpadObjectFactory to use for the creation of
        the objects.  If None, one is created.
    :param logtail: An optional string to put in the logtail field of the job.
    """
    if factory is None:
        factory = LaunchpadObjectFactory()
    if code_import is None:
        code_import = factory.makeCodeImport()
    if machine is None:
        machine = factory.makeCodeImportMachine(set_online=True)
    # The code import must be in a reviewed state.
    if code_import.review_status != CodeImportReviewStatus.REVIEWED:
        code_import.updateFromData(
            {'review_status': CodeImportReviewStatus.REVIEWED},
            code_import.registrant)

    CodeImportJobWorkflow().startJob(code_import.import_job, machine)
    if logtail:
        CodeImportJobWorkflow().updateHeartbeat(code_import.import_job,
                                                logtail)

    assert code_import.import_job.state == CodeImportJobState.RUNNING

    if date_started is not None:
        # Override the job date_started.
        naked_job = removeSecurityProxy(code_import.import_job)
        naked_job.date_started = date_started

    return code_import
Example #29
0
def login_team(team, participation=None):
    """Login as a member of 'team'."""
    # Prevent import loop.
    from lp.testing.factory import LaunchpadObjectFactory
    if not team.is_team:
        raise ValueError("Got person, expected team: %r" % (team, ))
    login(ADMIN_EMAIL)
    person = LaunchpadObjectFactory().makePerson()
    team.addMember(person, person)
    login_person(person, participation=participation)
    return person
Example #30
0
def extended_example(request, data):
    # We have declared a new fixture named "extended_example", but
    # instead of using "setup" we used the "extend" method of the
    # "example" fixture.  You can think of "example" wrapping
    # "extended_example".  During test setup, the "example" setup will
    # be called first.  Then this function, in "extended_example,"
    # will be called.  During test teardown, the "extended_example"
    # cleanups will be called first, followed by the "example"
    # cleanups.
    #
    # The "data" dict is the same one that was passed to the wrapping
    # fixture.  You can look at it, mutate it, or do what you need.
    # You are also responsible for not overwriting or mangling the
    # dict so that the wrapping fixtures data and/or teardown is
    # compromised.
    #
    # For this example, we will log in as the user and make something.
    factory = LaunchpadObjectFactory()
    with person_logged_in(data['user']):
        data['another_product'] = factory.makeProduct(owner=data['user'])
Example #31
0
def setupDTCBrowser():
    """Testbrowser configured for Distribution Translations Coordinators.

    Ubuntu is the configured distribution.
    """
    login('*****@*****.**')
    try:
        dtg_member = LaunchpadObjectFactory().makePerson(
            name='ubuntu-translations-coordinator', email="*****@*****.**")
    except NameAlreadyTaken:
        # We have already created the translations coordinator
        pass
    else:
        dtg = LaunchpadObjectFactory().makeTranslationGroup(
            name="ubuntu-translators",
            title="Ubuntu Translators",
            owner=dtg_member)
        ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
        ubuntu.translationgroup = dtg
    logout()
    return setupBrowser(auth='Basic [email protected]:test')
Example #32
0
def make_finished_import(code_import=None,
                         status=None,
                         date_finished=None,
                         factory=None):
    """Return a code import with a new finished job.

    :param code_import: The code import to create the job for.  If None, an
        anonymous CodeImport is created.
    :param status: The result status.  If not specified it is set to
        SUCCESSFUL.
    :param date_finished: If specified this overrides the date_last_successful
        attribute of the code_import if the state is SUCCESSFUL.
    :param factory: The LaunchpadObjectFactory to use for the creation of
        the objects.  If None, one is created.
    """
    if factory is None:
        factory = LaunchpadObjectFactory()
    if code_import is None:
        code_import = factory.makeCodeImport()
    if status is None:
        status = CodeImportResultStatus.SUCCESS
    # The code import must be in a reviewed state.
    if code_import.review_status != CodeImportReviewStatus.REVIEWED:
        code_import.updateFromData(
            {'review_status': CodeImportReviewStatus.REVIEWED},
            code_import.registrant)

    # If the job isn't running, make it run.
    if code_import.import_job.state != CodeImportJobState.RUNNING:
        machine = factory.makeCodeImportMachine(set_online=True)
        CodeImportJobWorkflow().startJob(code_import.import_job, machine)

    CodeImportJobWorkflow().finishJob(code_import.import_job, status, None)

    if date_finished is not None and status == CodeImportResultStatus.SUCCESS:
        # Override the code import date last successful.
        naked_import = removeSecurityProxy(code_import)
        naked_import.date_last_successful = date_finished

    return code_import
Example #33
0
def _get_locals():
    if len(sys.argv) > 1:
        dbuser = sys.argv[1]
    else:
        dbuser = None
    dbconfig.override(dbuser=dbuser)
    execute_zcml_for_scripts()
    readline.parse_and_bind('tab: complete')
    # Mimic the real interactive interpreter's loading of any
    # $PYTHONSTARTUP file.
    startup = os.environ.get('PYTHONSTARTUP')
    if startup:
        execfile(startup)
    store = IMasterStore(Person)

    if dbuser == 'launchpad':
        # Create a few variables "in case they come in handy."
        # Do we really use these?  Are they worth carrying around?
        d = Distribution.get(1)
        p = Person.get(1)
        ds = DistroSeries.get(1)
        prod = Product.get(1)
        proj = ProjectGroup.get(1)
        b2 = Bug.get(2)
        b1 = Bug.get(1)
        s = Specification.get(1)
        q = Question.get(1)
        # Silence unused name warnings
        d, p, ds, prod, proj, b2, b1, s, q

    # Having a factory instance is handy.
    factory = LaunchpadObjectFactory()

    def browser_open(obj, *args, **kwargs):
        """Open a (possibly newly-created) object's view in a web browser.

        Accepts the same parameters as canonical_url.

        Performs a commit before invoking the browser, so
        "browser_open(factory.makeFoo())" works.
        """
        transaction.commit()
        webbrowser.open(canonical_url(obj, *args, **kwargs))

    # Silence unused name warnings
    factory, store

    res = {}
    res.update(locals())
    res.update(globals())
    del res['_get_locals']
    return res
def make_running_import(code_import=None, machine=None, date_started=None,
                        factory=None, logtail=None):
    """Return a code import with a running job.

    :param code_import: The code import to create the job for.  If None, an
        anonymous CodeImport is created.
    :param machine: The `CodeImportMachine` to associate with the running
        job.  If None, an anonymous CodeImportMachine is created.
    :param date_started: If specified this overrides the UTC_NOW timestamp
        of the newly started job.
    :param factory: The LaunchpadObjectFactory to use for the creation of
        the objects.  If None, one is created.
    :param logtail: An optional string to put in the logtail field of the job.
    """
    if factory is None:
        factory = LaunchpadObjectFactory()
    if code_import is None:
        code_import = factory.makeCodeImport()
    if machine is None:
        machine = factory.makeCodeImportMachine(set_online=True)
    # The code import must be in a reviewed state.
    if code_import.review_status != CodeImportReviewStatus.REVIEWED:
        code_import.updateFromData(
            {'review_status': CodeImportReviewStatus.REVIEWED},
            code_import.registrant)

    CodeImportJobWorkflow().startJob(code_import.import_job, machine)
    if logtail:
        CodeImportJobWorkflow().updateHeartbeat(
            code_import.import_job, logtail)

    assert code_import.import_job.state == CodeImportJobState.RUNNING

    if date_started is not None:
        # Override the job date_started.
        naked_job = removeSecurityProxy(code_import.import_job)
        naked_job.date_started = date_started

    return code_import
def make_finished_import(code_import=None, status=None, date_finished=None,
                         factory=None):
    """Return a code import with a new finished job.

    :param code_import: The code import to create the job for.  If None, an
        anonymous CodeImport is created.
    :param status: The result status.  If not specified it is set to
        SUCCESSFUL.
    :param date_finished: If specified this overrides the date_last_successful
        attribute of the code_import if the state is SUCCESSFUL.
    :param factory: The LaunchpadObjectFactory to use for the creation of
        the objects.  If None, one is created.
    """
    if factory is None:
        factory = LaunchpadObjectFactory()
    if code_import is None:
        code_import = factory.makeCodeImport()
    if status is None:
        status = CodeImportResultStatus.SUCCESS
    # The code import must be in a reviewed state.
    if code_import.review_status != CodeImportReviewStatus.REVIEWED:
        code_import.updateFromData(
            {'review_status': CodeImportReviewStatus.REVIEWED},
            code_import.registrant)

    # If the job isn't running, make it run.
    if code_import.import_job.state != CodeImportJobState.RUNNING:
        machine = factory.makeCodeImportMachine(set_online=True)
        CodeImportJobWorkflow().startJob(code_import.import_job, machine)

    CodeImportJobWorkflow().finishJob(code_import.import_job, status, None)

    if date_finished is not None and status == CodeImportResultStatus.SUCCESS:
        # Override the code import date last successful.
        naked_import = removeSecurityProxy(code_import)
        naked_import.date_last_successful = date_finished

    return code_import
Example #36
0
def sign_code_of_conduct(person, log):
    """Sign Ubuntu Code of Conduct for `person`, if necessary."""
    if person.is_ubuntu_coc_signer:
        # Already signed.
        return

    log.info("Signing Ubuntu code of conduct.")
    signedcocset = getUtility(ISignedCodeOfConductSet)
    person_id = person.id
    if signedcocset.searchByUser(person_id).count() == 0:
        fake_gpg_key = LaunchpadObjectFactory().makeGPGKey(person)
        Store.of(person).add(SignedCodeOfConduct(
            owner=person, signing_key_fingerprint=fake_gpg_key.fingerprint,
            signing_key_owner=fake_gpg_key.owner,
            signedcode="Normally a signed CoC would go here.", active=True))
Example #37
0
def setupRosettaExpertBrowser():
    """Testbrowser configured for Rosetta Experts."""

    login('*****@*****.**')
    try:
        rosetta_expert = LaunchpadObjectFactory().makePerson(
            name='rosetta-experts-member', email='*****@*****.**')
    except NameAlreadyTaken:
        # We have already created an Rosetta expert
        pass
    else:
        rosetta_experts_team = removeSecurityProxy(
            getUtility(ILaunchpadCelebrities).rosetta_experts)
        rosetta_experts_team.addMember(rosetta_expert,
                                       reviewer=rosetta_experts_team,
                                       status=TeamMembershipStatus.ADMIN)
    logout()
    return setupBrowser(auth='Basic [email protected]:test')
Example #38
0
class SFTPTestMixin:
    """Mixin used to check getAttrs."""
    def setUp(self):
        self._factory = LaunchpadObjectFactory()

    def checkAttrs(self, attrs, stat_value):
        """Check that an attrs dictionary matches a stat result."""
        self.assertEqual(stat_value.st_size, attrs['size'])
        self.assertEqual(os.getuid(), attrs['uid'])
        self.assertEqual(os.getgid(), attrs['gid'])
        self.assertEqual(stat_value.st_mode, attrs['permissions'])
        self.assertEqual(stat_value.st_mtime, attrs['mtime'])
        self.assertEqual(stat_value.st_atime, attrs['atime'])

    def getPathSegment(self):
        """Return a unique path segment for testing.

        This returns a path segment such that 'path != unescape(path)'. This
        exercises the interface between the sftp server and the Bazaar
        transport, which expects escaped URL segments.
        """
        return self._factory.getUniqueString('%41%42%43-')
Example #39
0
class SFTPTestMixin:
    """Mixin used to check getAttrs."""

    def setUp(self):
        self._factory = LaunchpadObjectFactory()

    def checkAttrs(self, attrs, stat_value):
        """Check that an attrs dictionary matches a stat result."""
        self.assertEqual(stat_value.st_size, attrs['size'])
        self.assertEqual(os.getuid(), attrs['uid'])
        self.assertEqual(os.getgid(), attrs['gid'])
        self.assertEqual(stat_value.st_mode, attrs['permissions'])
        self.assertEqual(stat_value.st_mtime, attrs['mtime'])
        self.assertEqual(stat_value.st_atime, attrs['atime'])

    def getPathSegment(self):
        """Return a unique path segment for testing.

        This returns a path segment such that 'path != unescape(path)'. This
        exercises the interface between the sftp server and the Bazaar
        transport, which expects escaped URL segments.
        """
        return self._factory.getUniqueString('%41%42%43-')
Example #40
0
 def setUp(self):
     self._factory = LaunchpadObjectFactory()
class TestRemoveTranslations(TestCase):
    """Test `remove_translations`."""
    layer = LaunchpadZopelessLayer

    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()

    def _setTranslation(self, potmsgset, pofile, text, submitter=None,
                        is_current_upstream=False):
        """Set translation for potmsgset in pofile to text."""
        if submitter is None:
            submitter = self.potemplate.owner
        return self.factory.makeCurrentTranslationMessage(
            pofile, potmsgset, translator=submitter,
            translations={0: text}, current_other=is_current_upstream)

    def _makeMessages(self, template_text, nl_text, de_text,
                      submitter=None, is_current_upstream=False):
        """Create message, and translate it to Dutch & German."""
        message = self.factory.makePOTMsgSet(self.potemplate, template_text,
                                             sequence=0)
        new_nl_message = self._setTranslation(
            message, self.nl_pofile, nl_text, submitter=submitter,
            is_current_upstream=is_current_upstream)
        new_de_message = self._setTranslation(
            message, self.de_pofile, de_text, submitter=submitter,
            is_current_upstream=is_current_upstream)
        return new_nl_message, new_de_message

    def _getContents(self, pofile):
        return sorted(
            message.msgstr0.translation
            for message in pofile.translation_messages
            if message.msgstr0 is not None)

    def _checkInvariant(self):
        """Check that our translations are in their original state.

        Tests in this test case don't work in the usual way, by making
        changes and then testing for them.  Instead they make changes by
        creating new messages, and then using `remove_translations` to
        undo those changes.

        We see that a removal worked correctly by verifying that the
        invariant is restored.
        """
        # First make sure we're not reading out of cache.
        Store.of(self.nl_pofile).flush()

        self.assertEqual(
            self._getContents(self.nl_pofile),
            ["Dit bericht mag niet worden verwijderd."])
        self.assertEqual(
            self._getContents(self.de_pofile),
            ["Diese Nachricht soll nicht erloescht werden."])

    def _removeMessages(self, **kwargs):
        """Front-end for `remove_translations`.  Flushes changes first."""
        Store.of(self.potemplate).flush()
        return remove_translations(**kwargs)

    def test_RemoveNone(self):
        # If no messages match the given constraints, nothing is
        # deleted.
        rowcount = self._removeMessages(
            submitter=1, ids=[self.de_message.id], language_code='br')
        self.assertEqual(rowcount, 0)
        self._checkInvariant()

    def test_RemoveById(self):
        # We can remove messages by id.  Other messages are not
        # affected.
        new_nl_message1 = self._setTranslation(
            self.untranslated_message, self.nl_pofile, "A Dutch translation")
        new_nl_message2 = self._setTranslation(
            self.untranslated_message, self.nl_pofile, "Double Dutch")
        self.assertEqual(
            self._getContents(self.nl_pofile), [
                "A Dutch translation",
                "Dit bericht mag niet worden verwijderd.",
                "Double Dutch",
                ])

        rowcount = self._removeMessages(
            ids=[new_nl_message1.id, new_nl_message2.id])

        self.assertEqual(rowcount, 2)
        self._checkInvariant()

    def test_RemoveBySubmitter(self):
        # Remove messages by submitter id.
        carlos = getUtility(IPersonSet).getByName('carlos')
        (new_nl_message, new_de_message) = self._makeMessages(
            "Submitted by Carlos", "Ingevoerd door Carlos",
            "Von Carlos eingefuehrt", submitter=carlos)

        # Ensure that at least one message's reviewer is not the same
        # as the submitter, so we know we're not accidentally matching
        # on reviewer instead.
        new_nl_message.reviewer = self.potemplate.owner

        self._removeMessages(submitter=carlos)
        self._checkInvariant()

    def test_RemoveByReviewer(self):
        # Remove messages by reviewer id.
        carlos = getUtility(IPersonSet).getByName('carlos')
        (new_nl_message, new_de_message) = self._makeMessages(
            "Submitted by Carlos", "Ingevoerd door Carlos",
            "Von Carlos eingefuehrt")
        new_nl_message.reviewer = carlos
        new_de_message.reviewer = carlos

        self._removeMessages(reviewer=carlos)
        self._checkInvariant()

    def test_RemoveByTemplate(self):
        # Remove messages by template.  Limit this deletion by ids as
        # well to avoid breaking the test invariant.  To show that the
        # template limitation really does add a limit on top of the ids
        # themselves, we also pass the id of another message in a
        # different template.  That message is not deleted.
        (new_nl_message, new_de_message) = self._makeMessages(
            "Foo", "Foe", "Fu")

        unrelated_nl_pofile = self.factory.makePOFile('nl')
        potmsgset = self.factory.makePOTMsgSet(
            unrelated_nl_pofile.potemplate, 'Foo',
            sequence=0)
        unrelated_nl_message = self.factory.makeCurrentTranslationMessage(
            unrelated_nl_pofile, potmsgset,
            translator=unrelated_nl_pofile.potemplate.owner,
            translations={0: "Foe"})

        ids = [new_nl_message.id, new_de_message.id, unrelated_nl_message.id]
        self._removeMessages(
            ids=ids, potemplate=self.potemplate.id)

        self._checkInvariant()
        self.assertEqual(self._getContents(unrelated_nl_pofile), ["Foe"])

    def test_RemoveByLanguage(self):
        # Remove messages by language.  Pass the ids of one Dutch
        # message and one German message, but specify Dutch as the
        # language to delete from; only the Dutch message is deleted.
        potmsgset = self.factory.makePOTMsgSet(self.potemplate, 'Bar',
                                               sequence=0)
        message = self._setTranslation(potmsgset, self.nl_pofile, 'Cafe')

        self._removeMessages(
            ids=[message.id, self.de_message.id], language_code='nl')

        self._checkInvariant()

    def test_RemoveByNotLanguage(self):
        # Remove messages, but spare otherwise matching messages that
        # are in German.
        potmsgset = self.factory.makePOTMsgSet(self.potemplate, 'Hi',
                                               sequence=0)
        message = self._setTranslation(potmsgset, self.nl_pofile, 'Hoi')

        self._removeMessages(
            ids=[message.id, self.de_message.id], language_code='de',
            not_language=True)

        self._checkInvariant()

    def test_RemoveCurrent(self):
        # Remove current messages, but not non-current messages.
        (new_nl_message, new_de_message) = self._makeMessages(
            "translate", "vertalen", "uebersetzen")
        self.nl_message.is_current_upstream = False

        messages_to_delete = [self.nl_message, new_nl_message, new_de_message]
        current_upstream_messages = [
            message for message in messages_to_delete
            if message.is_current_upstream]
        ids = [message.id for message in messages_to_delete]
        logger = logging.getLogger('test_remove_translations')
        logger.setLevel(logging.WARN)
        loghandler = Handler(self)
        loghandler.add(logger.name)
        self._removeMessages(ids=ids, is_current_upstream=True, logger=logger)

        self.nl_message.is_current_upstream = True
        self._checkInvariant()
        loghandler.assertLogsMessage(
            'Deleting messages currently in use:', level=logging.WARN)
        for message in current_upstream_messages:
            loghandler.assertLogsMessage(
                'Message %i is a current translation in upstream'
                % message.id,
                level=logging.WARN)
        self.assertEqual(
            1 + len(current_upstream_messages), len(loghandler.records))

    def test_RemoveNotCurrent(self):
        # Remove current messages, but not non-current messages.
        (new_nl_message, new_de_message) = self._makeMessages(
            "write", "schrijven", "schreiben")
        new_nl_message.is_current_upstream = False
        new_de_message.is_current_upstream = False

        ids = [self.nl_message.id, new_nl_message.id, new_de_message.id]
        self._removeMessages(ids=ids, is_current_upstream=False)

        self._checkInvariant()

    def test_RemoveImported(self):
        # Remove current messages, but not non-current messages.
        (new_nl_message, new_de_message) = self._makeMessages(
            "book", "boek", "Buch")
        new_nl_message.is_current_ubuntu = True
        new_de_message.is_current_ubuntu = True

        ids = [self.nl_message.id, new_nl_message.id, new_de_message.id]
        self._removeMessages(ids=ids, is_current_ubuntu=True)

        self._checkInvariant()

    def test_RemoveNotImported(self):
        # Remove current messages, but not non-current messages.
        (new_nl_message, new_de_message) = self._makeMessages(
            "helicopter", "helikopter", "Hubschauber")
        self.nl_message.is_current_ubuntu = True

        ids = [self.nl_message.id, new_nl_message.id, new_de_message.id]
        self._removeMessages(ids=ids, is_current_ubuntu=False)

        self.nl_message.is_current_ubuntu = False
        self._checkInvariant()

    def test_RemoveMsgId(self):
        # Remove translations by msgid_singular.
        (new_nl_message, new_de_message) = self._makeMessages(
            "save", "bewaren", "speichern")

        self._removeMessages(msgid_singular="save")

        self._checkInvariant()

    def test_RemoveOrigin(self):
        # Remove translations by origin.
        self.assertEqual(
            self.nl_message.origin, RosettaTranslationOrigin.ROSETTAWEB)
        (new_nl_message, new_de_message) = self._makeMessages(
            "new", "nieuw", "neu", is_current_upstream=True)
        removeSecurityProxy(new_nl_message).origin = (
            RosettaTranslationOrigin.SCM)
        removeSecurityProxy(new_de_message).origin = (
            RosettaTranslationOrigin.SCM)

        self._removeMessages(
            potemplate=self.potemplate, origin=RosettaTranslationOrigin.SCM)

        self._checkInvariant()

    def test_remove_by_license_rejection(self):
        # Remove translations submitted by users who rejected the
        # licensing agreement.
        refusenik = self.factory.makePerson()

        self._makeMessages(
            "Don't download this song", "Niet delen", "Nicht teilen",
            submitter=refusenik)

        TranslationRelicensingAgreement(
            person=refusenik, allow_relicensing=False)

        self._removeMessages(reject_license=True)

        self._checkInvariant()

    def test_remove_unlicensed_none(self):
        # Removing translations whose submitters rejected our
        # translations licence does not affect translations by those who
        # haven't answered the question yet.
        self._removeMessages(reject_license=True)

        self._checkInvariant()

    def test_remove_unlicensed_when_licensed(self):
        # Removing translations whose submitters rejected our
        # translations licence does not affect translations by those who
        # agreed to license.
        answer = TranslationRelicensingAgreement(
            person=self.nl_message.submitter, allow_relicensing=True)

        try:
            self._removeMessages(reject_license=True)
            self._checkInvariant()
        finally:
            # Clean up.
            answer.destroySelf()

    def test_remove_unlicensed_restriction(self):
        # When removing unlicensed translations, other restrictions
        # still apply.
        self.nl_message.is_current_upstream = True
        self.de_message.is_current_upstream = True
        answer = TranslationRelicensingAgreement(
            person=self.nl_message.submitter, allow_relicensing=False)

        try:
            self._removeMessages(
                reject_license=True, is_current_upstream=False)
            self._checkInvariant()
        finally:
            # Clean up.
            answer.destroySelf()
class TestRemoveTranslations(TestCase):
    """Test `remove_translations`."""
    layer = LaunchpadZopelessLayer

    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()

    def _setTranslation(self,
                        potmsgset,
                        pofile,
                        text,
                        submitter=None,
                        is_current_upstream=False):
        """Set translation for potmsgset in pofile to text."""
        if submitter is None:
            submitter = self.potemplate.owner
        return self.factory.makeCurrentTranslationMessage(
            pofile,
            potmsgset,
            translator=submitter,
            translations={0: text},
            current_other=is_current_upstream)

    def _makeMessages(self,
                      template_text,
                      nl_text,
                      de_text,
                      submitter=None,
                      is_current_upstream=False):
        """Create message, and translate it to Dutch & German."""
        message = self.factory.makePOTMsgSet(self.potemplate,
                                             template_text,
                                             sequence=0)
        new_nl_message = self._setTranslation(
            message,
            self.nl_pofile,
            nl_text,
            submitter=submitter,
            is_current_upstream=is_current_upstream)
        new_de_message = self._setTranslation(
            message,
            self.de_pofile,
            de_text,
            submitter=submitter,
            is_current_upstream=is_current_upstream)
        return new_nl_message, new_de_message

    def _getContents(self, pofile):
        return sorted(message.msgstr0.translation
                      for message in pofile.translation_messages
                      if message.msgstr0 is not None)

    def _checkInvariant(self):
        """Check that our translations are in their original state.

        Tests in this test case don't work in the usual way, by making
        changes and then testing for them.  Instead they make changes by
        creating new messages, and then using `remove_translations` to
        undo those changes.

        We see that a removal worked correctly by verifying that the
        invariant is restored.
        """
        # First make sure we're not reading out of cache.
        Store.of(self.nl_pofile).flush()

        self.assertEqual(self._getContents(self.nl_pofile),
                         ["Dit bericht mag niet worden verwijderd."])
        self.assertEqual(self._getContents(self.de_pofile),
                         ["Diese Nachricht soll nicht erloescht werden."])

    def _removeMessages(self, **kwargs):
        """Front-end for `remove_translations`.  Flushes changes first."""
        Store.of(self.potemplate).flush()
        return remove_translations(**kwargs)

    def test_RemoveNone(self):
        # If no messages match the given constraints, nothing is
        # deleted.
        rowcount = self._removeMessages(submitter=1,
                                        ids=[self.de_message.id],
                                        language_code='br')
        self.assertEqual(rowcount, 0)
        self._checkInvariant()

    def test_RemoveById(self):
        # We can remove messages by id.  Other messages are not
        # affected.
        new_nl_message1 = self._setTranslation(self.untranslated_message,
                                               self.nl_pofile,
                                               "A Dutch translation")
        new_nl_message2 = self._setTranslation(self.untranslated_message,
                                               self.nl_pofile, "Double Dutch")
        self.assertEqual(self._getContents(self.nl_pofile), [
            "A Dutch translation",
            "Dit bericht mag niet worden verwijderd.",
            "Double Dutch",
        ])

        rowcount = self._removeMessages(
            ids=[new_nl_message1.id, new_nl_message2.id])

        self.assertEqual(rowcount, 2)
        self._checkInvariant()

    def test_RemoveBySubmitter(self):
        # Remove messages by submitter id.
        carlos = getUtility(IPersonSet).getByName('carlos')
        (new_nl_message,
         new_de_message) = self._makeMessages("Submitted by Carlos",
                                              "Ingevoerd door Carlos",
                                              "Von Carlos eingefuehrt",
                                              submitter=carlos)

        # Ensure that at least one message's reviewer is not the same
        # as the submitter, so we know we're not accidentally matching
        # on reviewer instead.
        new_nl_message.reviewer = self.potemplate.owner

        self._removeMessages(submitter=carlos)
        self._checkInvariant()

    def test_RemoveByReviewer(self):
        # Remove messages by reviewer id.
        carlos = getUtility(IPersonSet).getByName('carlos')
        (new_nl_message,
         new_de_message) = self._makeMessages("Submitted by Carlos",
                                              "Ingevoerd door Carlos",
                                              "Von Carlos eingefuehrt")
        new_nl_message.reviewer = carlos
        new_de_message.reviewer = carlos

        self._removeMessages(reviewer=carlos)
        self._checkInvariant()

    def test_RemoveByTemplate(self):
        # Remove messages by template.  Limit this deletion by ids as
        # well to avoid breaking the test invariant.  To show that the
        # template limitation really does add a limit on top of the ids
        # themselves, we also pass the id of another message in a
        # different template.  That message is not deleted.
        (new_nl_message,
         new_de_message) = self._makeMessages("Foo", "Foe", "Fu")

        unrelated_nl_pofile = self.factory.makePOFile('nl')
        potmsgset = self.factory.makePOTMsgSet(unrelated_nl_pofile.potemplate,
                                               'Foo',
                                               sequence=0)
        unrelated_nl_message = self.factory.makeCurrentTranslationMessage(
            unrelated_nl_pofile,
            potmsgset,
            translator=unrelated_nl_pofile.potemplate.owner,
            translations={0: "Foe"})

        ids = [new_nl_message.id, new_de_message.id, unrelated_nl_message.id]
        self._removeMessages(ids=ids, potemplate=self.potemplate.id)

        self._checkInvariant()
        self.assertEqual(self._getContents(unrelated_nl_pofile), ["Foe"])

    def test_RemoveByLanguage(self):
        # Remove messages by language.  Pass the ids of one Dutch
        # message and one German message, but specify Dutch as the
        # language to delete from; only the Dutch message is deleted.
        potmsgset = self.factory.makePOTMsgSet(self.potemplate,
                                               'Bar',
                                               sequence=0)
        message = self._setTranslation(potmsgset, self.nl_pofile, 'Cafe')

        self._removeMessages(ids=[message.id, self.de_message.id],
                             language_code='nl')

        self._checkInvariant()

    def test_RemoveByNotLanguage(self):
        # Remove messages, but spare otherwise matching messages that
        # are in German.
        potmsgset = self.factory.makePOTMsgSet(self.potemplate,
                                               'Hi',
                                               sequence=0)
        message = self._setTranslation(potmsgset, self.nl_pofile, 'Hoi')

        self._removeMessages(ids=[message.id, self.de_message.id],
                             language_code='de',
                             not_language=True)

        self._checkInvariant()

    def test_RemoveCurrent(self):
        # Remove current messages, but not non-current messages.
        (new_nl_message,
         new_de_message) = self._makeMessages("translate", "vertalen",
                                              "uebersetzen")
        self.nl_message.is_current_upstream = False

        messages_to_delete = [self.nl_message, new_nl_message, new_de_message]
        current_upstream_messages = [
            message for message in messages_to_delete
            if message.is_current_upstream
        ]
        ids = [message.id for message in messages_to_delete]
        logger = logging.getLogger('test_remove_translations')
        logger.setLevel(logging.WARN)
        loghandler = Handler(self)
        loghandler.add(logger.name)
        self._removeMessages(ids=ids, is_current_upstream=True, logger=logger)

        self.nl_message.is_current_upstream = True
        self._checkInvariant()
        loghandler.assertLogsMessage('Deleting messages currently in use:',
                                     level=logging.WARN)
        for message in current_upstream_messages:
            loghandler.assertLogsMessage(
                'Message %i is a current translation in upstream' % message.id,
                level=logging.WARN)
        self.assertEqual(1 + len(current_upstream_messages),
                         len(loghandler.records))

    def test_RemoveNotCurrent(self):
        # Remove current messages, but not non-current messages.
        (new_nl_message,
         new_de_message) = self._makeMessages("write", "schrijven",
                                              "schreiben")
        new_nl_message.is_current_upstream = False
        new_de_message.is_current_upstream = False

        ids = [self.nl_message.id, new_nl_message.id, new_de_message.id]
        self._removeMessages(ids=ids, is_current_upstream=False)

        self._checkInvariant()

    def test_RemoveImported(self):
        # Remove current messages, but not non-current messages.
        (new_nl_message,
         new_de_message) = self._makeMessages("book", "boek", "Buch")
        new_nl_message.is_current_ubuntu = True
        new_de_message.is_current_ubuntu = True

        ids = [self.nl_message.id, new_nl_message.id, new_de_message.id]
        self._removeMessages(ids=ids, is_current_ubuntu=True)

        self._checkInvariant()

    def test_RemoveNotImported(self):
        # Remove current messages, but not non-current messages.
        (new_nl_message,
         new_de_message) = self._makeMessages("helicopter", "helikopter",
                                              "Hubschauber")
        self.nl_message.is_current_ubuntu = True

        ids = [self.nl_message.id, new_nl_message.id, new_de_message.id]
        self._removeMessages(ids=ids, is_current_ubuntu=False)

        self.nl_message.is_current_ubuntu = False
        self._checkInvariant()

    def test_RemoveMsgId(self):
        # Remove translations by msgid_singular.
        (new_nl_message,
         new_de_message) = self._makeMessages("save", "bewaren", "speichern")

        self._removeMessages(msgid_singular="save")

        self._checkInvariant()

    def test_RemoveOrigin(self):
        # Remove translations by origin.
        self.assertEqual(self.nl_message.origin,
                         RosettaTranslationOrigin.ROSETTAWEB)
        (new_nl_message,
         new_de_message) = self._makeMessages("new",
                                              "nieuw",
                                              "neu",
                                              is_current_upstream=True)
        removeSecurityProxy(new_nl_message).origin = (
            RosettaTranslationOrigin.SCM)
        removeSecurityProxy(new_de_message).origin = (
            RosettaTranslationOrigin.SCM)

        self._removeMessages(potemplate=self.potemplate,
                             origin=RosettaTranslationOrigin.SCM)

        self._checkInvariant()

    def test_remove_by_license_rejection(self):
        # Remove translations submitted by users who rejected the
        # licensing agreement.
        refusenik = self.factory.makePerson()

        self._makeMessages("Don't download this song",
                           "Niet delen",
                           "Nicht teilen",
                           submitter=refusenik)

        TranslationRelicensingAgreement(person=refusenik,
                                        allow_relicensing=False)

        self._removeMessages(reject_license=True)

        self._checkInvariant()

    def test_remove_unlicensed_none(self):
        # Removing translations whose submitters rejected our
        # translations licence does not affect translations by those who
        # haven't answered the question yet.
        self._removeMessages(reject_license=True)

        self._checkInvariant()

    def test_remove_unlicensed_when_licensed(self):
        # Removing translations whose submitters rejected our
        # translations licence does not affect translations by those who
        # agreed to license.
        answer = TranslationRelicensingAgreement(
            person=self.nl_message.submitter, allow_relicensing=True)

        try:
            self._removeMessages(reject_license=True)
            self._checkInvariant()
        finally:
            # Clean up.
            answer.destroySelf()

    def test_remove_unlicensed_restriction(self):
        # When removing unlicensed translations, other restrictions
        # still apply.
        self.nl_message.is_current_upstream = True
        self.de_message.is_current_upstream = True
        answer = TranslationRelicensingAgreement(
            person=self.nl_message.submitter, allow_relicensing=False)

        try:
            self._removeMessages(reject_license=True,
                                 is_current_upstream=False)
            self._checkInvariant()
        finally:
            # Clean up.
            answer.destroySelf()
Example #43
0
class TestMirroredBranchPolicy(TestCase):
    """Tests specific to `MirroredBranchPolicy`."""

    def setUp(self):
        super(TestMirroredBranchPolicy, self).setUp()
        self.factory = LaunchpadObjectFactory()

    def testNoFileURL(self):
        policy = MirroredBranchPolicy()
        self.assertRaises(
            BadUrlScheme, policy.checkOneURL,
            self.factory.getUniqueURL(scheme='file'))

    def testNoUnknownSchemeURLs(self):
        policy = MirroredBranchPolicy()
        self.assertRaises(
            BadUrlScheme, policy.checkOneURL,
            self.factory.getUniqueURL(scheme='decorator+scheme'))

    def testNoSSHURL(self):
        policy = MirroredBranchPolicy()
        self.assertRaises(
            BadUrlSsh, policy.checkOneURL,
            self.factory.getUniqueURL(scheme='bzr+ssh'))

    def testNoSftpURL(self):
        policy = MirroredBranchPolicy()
        self.assertRaises(
            BadUrlSsh, policy.checkOneURL,
            self.factory.getUniqueURL(scheme='sftp'))

    def testNoLaunchpadURL(self):
        policy = MirroredBranchPolicy()
        self.assertRaises(
            BadUrlLaunchpad, policy.checkOneURL,
            self.factory.getUniqueURL(host='bazaar.launchpad.dev'))

    def testNoHTTPSLaunchpadURL(self):
        policy = MirroredBranchPolicy()
        self.assertRaises(
            BadUrlLaunchpad, policy.checkOneURL,
            self.factory.getUniqueURL(
                host='bazaar.launchpad.dev', scheme='https'))

    def testNoOtherHostLaunchpadURL(self):
        policy = MirroredBranchPolicy()
        self.assertRaises(
            BadUrlLaunchpad, policy.checkOneURL,
            self.factory.getUniqueURL(host='code.launchpad.dev'))

    def testLocalhost(self):
        self.pushConfig(
            'codehosting', blacklisted_hostnames='localhost,127.0.0.1')
        policy = MirroredBranchPolicy()
        localhost_url = self.factory.getUniqueURL(host='localhost')
        self.assertRaises(BadUrl, policy.checkOneURL, localhost_url)
        localhost_url = self.factory.getUniqueURL(host='127.0.0.1')
        self.assertRaises(BadUrl, policy.checkOneURL, localhost_url)

    def test_no_stacked_on_url(self):
        # By default, a MirroredBranchPolicy does not stack branches.
        policy = MirroredBranchPolicy()
        # This implementation of the method doesn't actually care about the
        # arguments.
        self.assertIs(
            None, policy.getStackedOnURLForDestinationBranch(None, None))

    def test_specified_stacked_on_url(self):
        # If a default stacked-on URL is specified, then the
        # MirroredBranchPolicy will tell branches to be stacked on that.
        stacked_on_url = '/foo'
        policy = MirroredBranchPolicy(stacked_on_url)
        destination_url = 'http://example.com/bar'
        self.assertEqual(
            '/foo',
            policy.getStackedOnURLForDestinationBranch(None, destination_url))

    def test_stacked_on_url_for_mirrored_branch(self):
        # If the default stacked-on URL is also the URL for the branch being
        # mirrored, then the stacked-on URL for destination branch is None.
        stacked_on_url = '/foo'
        policy = MirroredBranchPolicy(stacked_on_url)
        destination_url = 'http://example.com/foo'
        self.assertIs(
            None,
            policy.getStackedOnURLForDestinationBranch(None, destination_url))
Example #44
0
class TestWorkerMonitorIntegration(BzrTestCase):

    layer = ZopelessAppServerLayer
    run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=60)

    def setUp(self):
        BzrTestCase.setUp(self)
        login('*****@*****.**')
        self.factory = LaunchpadObjectFactory()
        nuke_codeimport_sample_data()
        self.repo_path = tempfile.mkdtemp()
        self.disable_directory_isolation()
        self.addCleanup(shutil.rmtree, self.repo_path)
        self.foreign_commit_count = 0

    def tearDown(self):
        BzrTestCase.tearDown(self)
        logout()

    def makeCVSCodeImport(self):
        """Make a `CodeImport` that points to a real CVS repository."""
        cvs_server = CVSServer(self.repo_path)
        cvs_server.start_server()
        self.addCleanup(cvs_server.stop_server)

        cvs_server.makeModule('trunk', [('README', 'original\n')])
        self.foreign_commit_count = 2

        return self.factory.makeCodeImport(cvs_root=cvs_server.getRoot(),
                                           cvs_module='trunk')

    def makeSVNCodeImport(self):
        """Make a `CodeImport` that points to a real Subversion repository."""
        self.subversion_server = SubversionServer(self.repo_path)
        self.subversion_server.start_server()
        self.addCleanup(self.subversion_server.stop_server)
        url = self.subversion_server.makeBranch('trunk',
                                                [('README', 'contents')])
        self.foreign_commit_count = 2

        return self.factory.makeCodeImport(svn_branch_url=url)

    def makeBzrSvnCodeImport(self):
        """Make a `CodeImport` that points to a real Subversion repository."""
        self.subversion_server = SubversionServer(self.repo_path,
                                                  use_svn_serve=True)
        self.subversion_server.start_server()
        self.addCleanup(self.subversion_server.stop_server)
        url = self.subversion_server.makeBranch('trunk',
                                                [('README', 'contents')])
        self.foreign_commit_count = 2

        return self.factory.makeCodeImport(
            svn_branch_url=url, rcs_type=RevisionControlSystems.BZR_SVN)

    def makeGitCodeImport(self):
        """Make a `CodeImport` that points to a real Git repository."""
        self.git_server = GitServer(self.repo_path, use_server=False)
        self.git_server.start_server()
        self.addCleanup(self.git_server.stop_server)

        self.git_server.makeRepo([('README', 'contents')])
        self.foreign_commit_count = 1

        return self.factory.makeCodeImport(
            git_repo_url=self.git_server.get_url())

    def makeBzrCodeImport(self):
        """Make a `CodeImport` that points to a real Bazaar branch."""
        self.bzr_server = BzrServer(self.repo_path)
        self.bzr_server.start_server()
        self.addCleanup(self.bzr_server.stop_server)

        self.bzr_server.makeRepo([('README', 'contents')])
        self.foreign_commit_count = 1
        return self.factory.makeCodeImport(
            bzr_branch_url=self.bzr_server.get_url())

    def getStartedJobForImport(self, code_import):
        """Get a started `CodeImportJob` for `code_import`.

        This method approves the import, creates a job, marks it started and
        returns the job.  It also makes sure there are no branches or foreign
        trees in the default stores to interfere with processing this job.
        """
        source_details = CodeImportSourceDetails.fromCodeImport(code_import)
        clean_up_default_stores_for_import(source_details)
        self.addCleanup(clean_up_default_stores_for_import, source_details)
        if code_import.review_status != CodeImportReviewStatus.REVIEWED:
            code_import.updateFromData(
                {'review_status': CodeImportReviewStatus.REVIEWED},
                self.factory.makePerson())
        job = getUtility(ICodeImportJobSet).getJobForMachine('machine', 10)
        self.assertEqual(code_import, job.code_import)
        return job

    def assertCodeImportResultCreated(self, code_import):
        """Assert that a `CodeImportResult` was created for `code_import`."""
        self.assertEqual(len(list(code_import.results)), 1)
        result = list(code_import.results)[0]
        self.assertEqual(result.status, CodeImportResultStatus.SUCCESS)

    def assertBranchImportedOKForCodeImport(self, code_import):
        """Assert that a branch was pushed into the default branch store."""
        url = get_default_bazaar_branch_store()._getMirrorURL(
            code_import.branch.id)
        branch = Branch.open(url)
        self.assertEqual(self.foreign_commit_count, branch.revno())

    def assertImported(self, ignored, code_import_id):
        """Assert that the `CodeImport` of the given id was imported."""
        # In the in-memory tests, check that resetTimeout on the
        # CodeImportWorkerMonitorProtocol was called at least once.
        if self._protocol is not None:
            self.assertPositive(self._protocol.reset_calls)
        code_import = getUtility(ICodeImportSet).get(code_import_id)
        self.assertCodeImportResultCreated(code_import)
        self.assertBranchImportedOKForCodeImport(code_import)

    def performImport(self, job_id):
        """Perform the import job with ID job_id.

        Return a Deferred that fires when it the job is done.

        This implementation does it in-process.
        """
        logger = BufferLogger()
        monitor = CIWorkerMonitorForTesting(
            job_id, logger,
            xmlrpc.Proxy(config.codeimportdispatcher.codeimportscheduler_url),
            "anything")
        deferred = monitor.run()

        def save_protocol_object(result):
            """Save the process protocol object.

            We do this in an addBoth so that it's called after the process
            protocol is actually constructed but before we drop the last
            reference to the monitor object.
            """
            self._protocol = monitor._protocol
            return result

        return deferred.addBoth(save_protocol_object)

    def test_import_cvs(self):
        # Create a CVS CodeImport and import it.
        job = self.getStartedJobForImport(self.makeCVSCodeImport())
        code_import_id = job.code_import.id
        job_id = job.id
        self.layer.txn.commit()
        result = self.performImport(job_id)
        return result.addCallback(self.assertImported, code_import_id)

    def test_import_subversion(self):
        # Create a Subversion CodeImport and import it.
        job = self.getStartedJobForImport(self.makeSVNCodeImport())
        code_import_id = job.code_import.id
        job_id = job.id
        self.layer.txn.commit()
        result = self.performImport(job_id)
        return result.addCallback(self.assertImported, code_import_id)

    def test_import_git(self):
        # Create a Git CodeImport and import it.
        job = self.getStartedJobForImport(self.makeGitCodeImport())
        code_import_id = job.code_import.id
        job_id = job.id
        self.layer.txn.commit()
        result = self.performImport(job_id)
        return result.addCallback(self.assertImported, code_import_id)

    def test_import_bzr(self):
        # Create a Bazaar CodeImport and import it.
        job = self.getStartedJobForImport(self.makeBzrCodeImport())
        code_import_id = job.code_import.id
        job_id = job.id
        self.layer.txn.commit()
        result = self.performImport(job_id)
        return result.addCallback(self.assertImported, code_import_id)

    def test_import_bzrsvn(self):
        # Create a Subversion-via-bzr-svn CodeImport and import it.
        job = self.getStartedJobForImport(self.makeBzrSvnCodeImport())
        code_import_id = job.code_import.id
        job_id = job.id
        self.layer.txn.commit()
        result = self.performImport(job_id)
        return result.addCallback(self.assertImported, code_import_id)
Example #45
0
class TestBranchMergeProposalDelta(TestCase):

    layer = LaunchpadFunctionalLayer

    def setUp(self):
        TestCase.setUp(self)
        login('*****@*****.**')
        self.factory = LaunchpadObjectFactory()

    def test_snapshot(self):
        """Test that the snapshot method produces a reasonable snapshot"""
        merge_proposal = self.factory.makeBranchMergeProposal()
        merge_proposal.commit_message = 'foo'
        merge_proposal.whiteboard = 'bar'
        snapshot = BranchMergeProposalDelta.snapshot(merge_proposal)
        self.assertEqual('foo', snapshot.commit_message)
        self.assertEqual('bar', snapshot.whiteboard)

    def test_noModification(self):
        """When there are no modifications, no delta should be returned."""
        merge_proposal = self.factory.makeBranchMergeProposal()
        old_merge_proposal = BranchMergeProposalDelta.snapshot(merge_proposal)
        delta = BranchMergeProposalDelta.construct(
            old_merge_proposal, merge_proposal)
        assert delta is None

    def test_Modification(self):
        """When there are modifications, the delta reflects them."""
        registrant = self.factory.makePerson(
            displayname='Baz Qux', email='*****@*****.**')
        merge_proposal = self.factory.makeBranchMergeProposal(
            registrant=registrant)
        old_merge_proposal = BranchMergeProposalDelta.snapshot(merge_proposal)
        merge_proposal.commit_message = 'Change foo into bar.'
        merge_proposal.description = 'Set the description.'
        merge_proposal.markAsMerged()
        delta = BranchMergeProposalDelta.construct(
            old_merge_proposal, merge_proposal)
        assert delta is not None
        self.assertEqual('Change foo into bar.', delta.commit_message)
        self.assertEqual('Set the description.', delta.description)
        self.assertEqual(
            {'old': BranchMergeProposalStatus.WORK_IN_PROGRESS,
            'new': BranchMergeProposalStatus.MERGED},
            delta.queue_status)

    def test_monitor(self):
        """\
        `monitor` observes changes to a given merge proposal and issues
        `ObjectModifiedEvent` events if there are any.
        """
        merge_proposal = self.factory.makeBranchMergeProposal()
        with EventRecorder() as event_recorder:
            # No event is issued when nothing is changed.
            with BranchMergeProposalDelta.monitor(merge_proposal):
                pass  # Don't make changes.
            self.assertEqual(0, len(event_recorder.events))
            # When one or more properties (of interest to
            # BranchMergeProposalDelta) are changed, a single event is issued.
            with BranchMergeProposalDelta.monitor(merge_proposal):
                merge_proposal.commit_message = "foo"
                merge_proposal.whiteboard = "bar"
            self.assertEqual(1, len(event_recorder.events))
            [event] = event_recorder.events
            self.assertIsInstance(event, ObjectModifiedEvent)
            self.assertEqual(merge_proposal, event.object)
            self.assertContentEqual(
                ["commit_message", "whiteboard"],
                event.edited_fields)
 def _makeHarry(self, email_address_status=None):
     factory = LaunchpadObjectFactory()
     return factory.makePerson(
         email='*****@*****.**',
         name='harry',
         email_address_status=email_address_status)
    def setUp(self):
        super(TestBuildNotifications, self).setUp()
        from lp.testing.factory import LaunchpadObjectFactory

        self.factory = LaunchpadObjectFactory()
Example #48
0
 def setUp(self):
     self._factory = LaunchpadObjectFactory()
 def setUp(self):
     super(TestRemoveTranslationsOptionsHandling, self).setUp()
     self.factory = LaunchpadObjectFactory()
class TestWorkerMonitorIntegration(BzrTestCase):

    layer = ZopelessAppServerLayer
    run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=60)

    def setUp(self):
        BzrTestCase.setUp(self)
        login('*****@*****.**')
        self.factory = LaunchpadObjectFactory()
        nuke_codeimport_sample_data()
        self.repo_path = tempfile.mkdtemp()
        self.disable_directory_isolation()
        self.addCleanup(shutil.rmtree, self.repo_path)
        self.foreign_commit_count = 0

    def tearDown(self):
        BzrTestCase.tearDown(self)
        logout()

    def makeCVSCodeImport(self):
        """Make a `CodeImport` that points to a real CVS repository."""
        cvs_server = CVSServer(self.repo_path)
        cvs_server.start_server()
        self.addCleanup(cvs_server.stop_server)

        cvs_server.makeModule('trunk', [('README', 'original\n')])
        self.foreign_commit_count = 2

        return self.factory.makeCodeImport(
            cvs_root=cvs_server.getRoot(), cvs_module='trunk')

    def makeSVNCodeImport(self):
        """Make a `CodeImport` that points to a real Subversion repository."""
        self.subversion_server = SubversionServer(self.repo_path)
        self.subversion_server.start_server()
        self.addCleanup(self.subversion_server.stop_server)
        url = self.subversion_server.makeBranch(
            'trunk', [('README', 'contents')])
        self.foreign_commit_count = 2

        return self.factory.makeCodeImport(svn_branch_url=url)

    def makeBzrSvnCodeImport(self):
        """Make a `CodeImport` that points to a real Subversion repository."""
        self.subversion_server = SubversionServer(
            self.repo_path, use_svn_serve=True)
        self.subversion_server.start_server()
        self.addCleanup(self.subversion_server.stop_server)
        url = self.subversion_server.makeBranch(
            'trunk', [('README', 'contents')])
        self.foreign_commit_count = 2

        return self.factory.makeCodeImport(
            svn_branch_url=url, rcs_type=RevisionControlSystems.BZR_SVN)

    def makeGitCodeImport(self):
        """Make a `CodeImport` that points to a real Git repository."""
        self.git_server = GitServer(self.repo_path, use_server=False)
        self.git_server.start_server()
        self.addCleanup(self.git_server.stop_server)

        self.git_server.makeRepo([('README', 'contents')])
        self.foreign_commit_count = 1

        return self.factory.makeCodeImport(
            git_repo_url=self.git_server.get_url())

    def makeBzrCodeImport(self):
        """Make a `CodeImport` that points to a real Bazaar branch."""
        self.bzr_server = BzrServer(self.repo_path)
        self.bzr_server.start_server()
        self.addCleanup(self.bzr_server.stop_server)

        self.bzr_server.makeRepo([('README', 'contents')])
        self.foreign_commit_count = 1
        return self.factory.makeCodeImport(
            bzr_branch_url=self.bzr_server.get_url())

    def getStartedJobForImport(self, code_import):
        """Get a started `CodeImportJob` for `code_import`.

        This method approves the import, creates a job, marks it started and
        returns the job.  It also makes sure there are no branches or foreign
        trees in the default stores to interfere with processing this job.
        """
        source_details = CodeImportSourceDetails.fromCodeImport(code_import)
        clean_up_default_stores_for_import(source_details)
        self.addCleanup(clean_up_default_stores_for_import, source_details)
        if code_import.review_status != CodeImportReviewStatus.REVIEWED:
            code_import.updateFromData(
                {'review_status': CodeImportReviewStatus.REVIEWED},
                self.factory.makePerson())
        job = getUtility(ICodeImportJobSet).getJobForMachine('machine', 10)
        self.assertEqual(code_import, job.code_import)
        return job

    def assertCodeImportResultCreated(self, code_import):
        """Assert that a `CodeImportResult` was created for `code_import`."""
        self.assertEqual(len(list(code_import.results)), 1)
        result = list(code_import.results)[0]
        self.assertEqual(result.status, CodeImportResultStatus.SUCCESS)

    def assertBranchImportedOKForCodeImport(self, code_import):
        """Assert that a branch was pushed into the default branch store."""
        url = get_default_bazaar_branch_store()._getMirrorURL(
            code_import.branch.id)
        branch = Branch.open(url)
        self.assertEqual(self.foreign_commit_count, branch.revno())

    def assertImported(self, ignored, code_import_id):
        """Assert that the `CodeImport` of the given id was imported."""
        # In the in-memory tests, check that resetTimeout on the
        # CodeImportWorkerMonitorProtocol was called at least once.
        if self._protocol is not None:
            self.assertPositive(self._protocol.reset_calls)
        code_import = getUtility(ICodeImportSet).get(code_import_id)
        self.assertCodeImportResultCreated(code_import)
        self.assertBranchImportedOKForCodeImport(code_import)

    def performImport(self, job_id):
        """Perform the import job with ID job_id.

        Return a Deferred that fires when it the job is done.

        This implementation does it in-process.
        """
        logger = BufferLogger()
        monitor = CIWorkerMonitorForTesting(
            job_id, logger,
            xmlrpc.Proxy(config.codeimportdispatcher.codeimportscheduler_url),
            "anything")
        deferred = monitor.run()

        def save_protocol_object(result):
            """Save the process protocol object.

            We do this in an addBoth so that it's called after the process
            protocol is actually constructed but before we drop the last
            reference to the monitor object.
            """
            self._protocol = monitor._protocol
            return result

        return deferred.addBoth(save_protocol_object)

    def test_import_cvs(self):
        # Create a CVS CodeImport and import it.
        job = self.getStartedJobForImport(self.makeCVSCodeImport())
        code_import_id = job.code_import.id
        job_id = job.id
        self.layer.txn.commit()
        result = self.performImport(job_id)
        return result.addCallback(self.assertImported, code_import_id)

    def test_import_subversion(self):
        # Create a Subversion CodeImport and import it.
        job = self.getStartedJobForImport(self.makeSVNCodeImport())
        code_import_id = job.code_import.id
        job_id = job.id
        self.layer.txn.commit()
        result = self.performImport(job_id)
        return result.addCallback(self.assertImported, code_import_id)

    def test_import_git(self):
        # Create a Git CodeImport and import it.
        job = self.getStartedJobForImport(self.makeGitCodeImport())
        code_import_id = job.code_import.id
        job_id = job.id
        self.layer.txn.commit()
        result = self.performImport(job_id)
        return result.addCallback(self.assertImported, code_import_id)

    def test_import_bzr(self):
        # Create a Bazaar CodeImport and import it.
        job = self.getStartedJobForImport(self.makeBzrCodeImport())
        code_import_id = job.code_import.id
        job_id = job.id
        self.layer.txn.commit()
        result = self.performImport(job_id)
        return result.addCallback(self.assertImported, code_import_id)

    def test_import_bzrsvn(self):
        # Create a Subversion-via-bzr-svn CodeImport and import it.
        job = self.getStartedJobForImport(self.makeBzrSvnCodeImport())
        code_import_id = job.code_import.id
        job_id = job.id
        self.layer.txn.commit()
        result = self.performImport(job_id)
        return result.addCallback(self.assertImported, code_import_id)
class TestRemoveTranslationsOptionsHandling(TestCase):
    """Test `RemoveTranslations`' options parsing and type checking."""
    layer = LaunchpadZopelessLayer

    def setUp(self):
        super(TestRemoveTranslationsOptionsHandling, self).setUp()
        self.factory = LaunchpadObjectFactory()

    def test_WithNativeArgs(self):
        # Options can be passed as the string representations of the
        # types the script wants them in.
        options = parse_opts([
            '--submitter=1',
            '--reviewer=2',
            '--id=3',
            '--id=4',
            '--potemplate=5',
            '--language=te',
            '--not-language',
            '--is-current-ubuntu=True',
            '--is-current-upstream=False',
            '--msgid=Hello',
            '--origin=1',
            '--force',
            ])
        self.assertThat(options, MatchesStructure.byEquality(
            submitter=1,
            reviewer=2,
            ids=[3, 4],
            potemplate=5,
            language='te',
            not_language=True,
            is_current_ubuntu=True,
            is_current_upstream=False,
            origin=1,
            force=True))

    def test_WithLookups(self):
        # The script can also look up some items from different
        # representations: person names, numbers or different case
        # settings for booleans, and translation origin identifiers.
        submitter = self.factory.makePerson()
        reviewer = self.factory.makePerson()

        options = parse_opts([
            '--submitter=%s' % submitter.name,
            '--reviewer=%s' % reviewer.name,
            '--is-current-ubuntu=0',
            '--is-current-upstream=true',
            '--origin=SCM',
            ])
        self.assertThat(options, MatchesStructure.byEquality(
            submitter=submitter.id,
            reviewer=reviewer.id,
            is_current_ubuntu=False,
            is_current_upstream=True,
            origin=RosettaTranslationOrigin.SCM.value))

    def test_BadBool(self):
        self.assertRaises(Exception, parse_opts, '--is-current-ubuntu=None')

    def test_UnknownPerson(self):
        self.assertRaises(
            Exception, parse_opts, '--reviewer=unknownnonexistentpersonbird')

    def test_UnknownOrigin(self):
        self.assertRaises(Exception, parse_opts, '--origin=GAGA')
Example #52
0
 def setUp(self):
     TestCase.setUp(self)
     login('*****@*****.**')
     self.factory = LaunchpadObjectFactory()
Example #53
0
 def setUp(self):
     super(TestMirroredBranchPolicy, self).setUp()
     self.factory = LaunchpadObjectFactory()
 def setUp(self):
     super(TestRemoveTranslationsOptionsHandling, self).setUp()
     self.factory = LaunchpadObjectFactory()
class TestGetGuessedPOFile(TestCaseWithFactory):
    """Test matching of PO files with respective templates and languages."""

    layer = LaunchpadZopelessLayer

    def setUp(self):
        """Set up context to test in."""
        super(TestGetGuessedPOFile, self).setUp()
        self.queue = getUtility(ITranslationImportQueue)
        self.factory = LaunchpadObjectFactory()
        self.distribution = self.factory.makeDistribution('boohoo')
        self.distroseries = self.factory.makeDistroSeries(self.distribution)
        self.uploaderperson = self.factory.makePerson()

    def createSourcePackageAndPOTemplate(self, sourcepackagename, template):
        """Create and return a source package and a POTemplate.

        Creates a source package in the self.distroseries with the passed-in
        sourcepackagename, and a template in that sourcepackage named
        template with the identical translation domain.
        """
        target_sourcepackage = self.factory.makeSourcePackage(
            distroseries=self.distroseries)
        pot = self.factory.makePOTemplate(
            sourcepackagename=target_sourcepackage.sourcepackagename,
            distroseries=target_sourcepackage.distroseries,
            name=template, translation_domain=template)
        spn = self.factory.makeSourcePackageName(sourcepackagename)
        l10n_sourcepackage = self.factory.makeSourcePackage(
            sourcepackagename=spn,
            distroseries=self.distroseries)
        return (l10n_sourcepackage, pot)

    def _getGuessedPOFile(self, source_name, template_path):
        """Return new POTemplate and matched POFile for package and template.
        """
        template_name = os.path.basename(template_path)
        package, pot = self.createSourcePackageAndPOTemplate(
            source_name, template_name)
        queue_entry = self.queue.addOrUpdateEntry(
            '%s.po' % template_path, template_name, True, self.uploaderperson,
            distroseries=package.distroseries,
            sourcepackagename=package.sourcepackagename)
        pofile = queue_entry.getGuessedPOFile()
        return (pot, pofile)

    def test_KDE4_language(self):
        # PO files 'something.po' in a package named like 'kde-l10n-sr'
        # belong in the 'something' translation domain as Serbian (sr)
        # translations.
        potemplate, pofile = self._getGuessedPOFile(
            'kde-l10n-sr', 'template')
        serbian = getUtility(ILanguageSet).getLanguageByCode('sr')
        self.assertEquals(potemplate, pofile.potemplate)
        self.assertEquals(serbian, pofile.language)

    def test_KDE4_language_country(self):
        # If package name is kde-l10n-engb, it needs to be mapped
        # to British English (en_GB).
        potemplate, pofile = self._getGuessedPOFile(
            'kde-l10n-engb', 'template')
        real_english = getUtility(ILanguageSet).getLanguageByCode('en_GB')
        self.assertEquals(potemplate, pofile.potemplate)
        self.assertEquals(real_english, pofile.language)

    def test_KDE4_language_variant(self):
        # If package name is kde-l10n-ca-valencia, it needs to be mapped
        # to Valencian variant of Catalan (ca@valencia).
        catalan_valencia = self.factory.makeLanguage(
            'ca@valencia', 'Catalan Valencia')
        potemplate, pofile = self._getGuessedPOFile(
            'kde-l10n-ca-valencia', 'template')
        self.assertEquals(potemplate, pofile.potemplate)
        self.assertEquals(catalan_valencia, pofile.language)

    def test_KDE4_language_subvariant(self):
        # PO file 'sr@test/something.po' in a package named like
        # 'kde-l10n-sr' belong in the 'something' translation domain
        # for "sr@test" language translations.
        serbian_test = self.factory.makeLanguage('sr@test')
        potemplate, pofile = self._getGuessedPOFile(
            'kde-l10n-sr', 'sr@test/template')
        self.assertEquals(potemplate, pofile.potemplate)
        self.assertEquals(serbian_test, pofile.language)

    def test_KDE4_language_at_sign(self):
        # PO file 'blah@test/something.po' in a package named like
        # 'kde-l10n-sr' belong in the 'something' translation domain
        # for "sr" language translations.
        serbian = getUtility(ILanguageSet).getLanguageByCode('sr')
        potemplate, pofile = self._getGuessedPOFile(
            'kde-l10n-sr', 'source/blah@test/template')
        self.assertEquals(potemplate, pofile.potemplate)
        self.assertEquals(serbian, pofile.language)
class TestRemoveTranslationsOptionsHandling(TestCase):
    """Test `RemoveTranslations`' options parsing and type checking."""
    layer = LaunchpadZopelessLayer

    def setUp(self):
        super(TestRemoveTranslationsOptionsHandling, self).setUp()
        self.factory = LaunchpadObjectFactory()

    def test_WithNativeArgs(self):
        # Options can be passed as the string representations of the
        # types the script wants them in.
        options = parse_opts([
            '--submitter=1',
            '--reviewer=2',
            '--id=3',
            '--id=4',
            '--potemplate=5',
            '--language=te',
            '--not-language',
            '--is-current-ubuntu=True',
            '--is-current-upstream=False',
            '--msgid=Hello',
            '--origin=1',
            '--force',
        ])
        self.assertThat(
            options,
            MatchesStructure.byEquality(submitter=1,
                                        reviewer=2,
                                        ids=[3, 4],
                                        potemplate=5,
                                        language='te',
                                        not_language=True,
                                        is_current_ubuntu=True,
                                        is_current_upstream=False,
                                        origin=1,
                                        force=True))

    def test_WithLookups(self):
        # The script can also look up some items from different
        # representations: person names, numbers or different case
        # settings for booleans, and translation origin identifiers.
        submitter = self.factory.makePerson()
        reviewer = self.factory.makePerson()

        options = parse_opts([
            '--submitter=%s' % submitter.name,
            '--reviewer=%s' % reviewer.name,
            '--is-current-ubuntu=0',
            '--is-current-upstream=true',
            '--origin=SCM',
        ])
        self.assertThat(
            options,
            MatchesStructure.byEquality(
                submitter=submitter.id,
                reviewer=reviewer.id,
                is_current_ubuntu=False,
                is_current_upstream=True,
                origin=RosettaTranslationOrigin.SCM.value))

    def test_BadBool(self):
        self.assertRaises(Exception, parse_opts, '--is-current-ubuntu=None')

    def test_UnknownPerson(self):
        self.assertRaises(Exception, parse_opts,
                          '--reviewer=unknownnonexistentpersonbird')

    def test_UnknownOrigin(self):
        self.assertRaises(Exception, parse_opts, '--origin=GAGA')
class TestBranchPopupWidget(unittest.TestCase):
    """Tests for the branch popup widget."""

    layer = LaunchpadFunctionalLayer

    def assertIs(self, first, second):
        """Assert `first` is `second`."""
        self.assertTrue(first is second, "%r is not %r" % (first, second))

    def installLaunchBag(self, user=None, product=None):
        bag = DummyLaunchBag(user, product)
        provideUtility(bag, ILaunchBag)
        return bag

    def makeBranchPopup(self, vocabulary=None):
        # Pick a random, semi-appropriate context.
        context = self.factory.makeProduct()
        if vocabulary is None:
            vocabulary = BranchVocabulary(context)
        request = self.makeRequest()
        return BranchPopupWidget(
            self.makeField(context, vocabulary), vocabulary, request)

    def makeField(self, context, vocabulary):
        field = Choice(
            title=_('Branch'), vocabulary=vocabulary, required=False,
            description=_("The Bazaar branch."))
        field.context = context
        return field

    def makeRequest(self):
        return LaunchpadTestRequest()

    def setUp(self):
        login(ANONYMOUS)
        self._original_launch_bag = getUtility(ILaunchBag)
        self.factory = LaunchpadObjectFactory()
        self.launch_bag = self.installLaunchBag(
            user=self.factory.makePerson(),
            product=self.factory.makeProduct())
        self.popup = self.makeBranchPopup()

    def tearDown(self):
        provideUtility(self._original_launch_bag, ILaunchBag)
        logout()

    def test_getProduct(self):
        """getProduct() returns the product in the LaunchBag."""
        self.assertEqual(self.launch_bag.product, self.popup.getProduct())

    def test_getPerson(self):
        """getPerson() returns the logged-in user."""
        self.assertEqual(self.launch_bag.user, self.popup.getPerson())

    def test_getBranchNameFromURL(self):
        """getBranchNameFromURL() gets a branch name from a url.

        In general, the name is the last path segment of the URL.
        """
        url = self.factory.getUniqueURL()
        name = self.popup.getBranchNameFromURL(url)
        self.assertEqual(URI(url).path.split('/')[-1], name)

    def test_makeBranchFromURL(self):
        """makeBranchFromURL(url) creates a mirrored branch at `url`.

        The owner and registrant are the currently logged-in user, as given by
        getPerson(), and the product is the product in the LaunchBag.
        """
        url = self.factory.getUniqueURL()
        expected_name = self.popup.getBranchNameFromURL(url)
        branch = self.popup.makeBranchFromURL(url)
        self.assertEqual(BranchType.MIRRORED, branch.branch_type)
        self.assertEqual(url, branch.url)
        self.assertEqual(self.popup.getPerson(), branch.owner)
        self.assertEqual(self.popup.getPerson(), branch.registrant)
        self.assertEqual(self.popup.getProduct(), branch.product)
        self.assertEqual(expected_name, branch.name)

    def test_makeBranch_used(self):
        # makeBranch makes up the branch name if the inferred one is already
        # used.
        url = self.factory.getUniqueURL()
        expected_name = self.popup.getBranchNameFromURL(url)
        self.factory.makeProductBranch(
            name=expected_name, product=self.popup.getProduct(),
            owner=self.popup.getPerson())
        branch = self.popup.makeBranchFromURL(url)
        self.assertEqual(expected_name + '-1', branch.name)

    def test_makeBranchRequestsMirror(self):
        """makeBranch requests a mirror on the branch it creates."""
        url = self.factory.getUniqueURL()
        branch = self.popup.makeBranchFromURL(url)
        self.assertNotEqual('None', str(branch.next_mirror_time))

    def test_makeBranchNoProduct(self):
        """makeBranchFromURL(url) returns None if there's no product.

        Not all contexts for branch registration have products. In particular,
        a bug can be on a source package. When we link a branch to that bug,
        there's no clear product to choose, so we don't choose any.
        """
        self.installLaunchBag(product=None, user=self.factory.makePerson())
        url = self.factory.getUniqueURL()
        self.assertRaises(NoProductError, self.popup.makeBranchFromURL, url)

    def test_makeBranchTrailingSlash(self):
        """makeBranch creates a mirrored branch even if the URL ends with /.
        """
        uri = URI(self.factory.getUniqueURL())
        expected_name = self.popup.getBranchNameFromURL(
            str(uri.ensureNoSlash()))
        branch = self.popup.makeBranchFromURL(str(uri.ensureSlash()))
        self.assertEqual(str(uri.ensureNoSlash()), branch.url)
        self.assertEqual(expected_name, branch.name)

    def test_toFieldValueFallsBackToMakingBranch(self):
        """_toFieldValue falls back to making a branch if it's given a URL."""
        url = self.factory.getUniqueURL()
        # Check that there's no branch with this URL.
        self.assertIs(None, getUtility(IBranchLookup).getByUrl(url))

        branch = self.popup._toFieldValue(url)
        self.assertEqual(url, branch.url)

    def test_toFieldValueFetchesTheExistingBranch(self):
        """_toFieldValue returns the existing branch that has that URL."""
        expected_branch = self.factory.makeAnyBranch(
            branch_type=BranchType.MIRRORED)
        branch = self.popup._toFieldValue(expected_branch.url)
        self.assertEqual(expected_branch, branch)

    def test_toFieldValueNonURL(self):
        """When the input isn't a URL, fall back to the original error."""
        empty_search = 'doesntexist'
        self.assertRaises(
            ConversionError, self.popup._toFieldValue, empty_search)

    def test_toFieldValueNoProduct(self):
        """When there's no product, fall back to the original error."""
        self.installLaunchBag(product=None, user=self.factory.makePerson())
        self.assertRaises(
            ConversionError, self.popup._toFieldValue,
            self.factory.getUniqueURL())

    def test_toFieldBadURL(self):
        """When the input is a bad URL, fall back to the original error.

        There are many valid URLs that are inappropriate for a mirrored
        branch. We don't want to register a mirrored branch when someone
        enters such a URL.
        """
        bad_url = 'svn://svn.example.com/repo/trunk'
        self.assertRaises(ConversionError, self.popup._toFieldValue, bad_url)

    def test_branchInRestrictedProduct(self):
        # There are two reasons for a URL not being in the vocabulary. One
        # reason is that it's there's no registered branch with that URL. The
        # other is that the vocabulary on this form is restricted to one
        # product, and there *is* a branch with that URL, but it's registered
        # on a different product.

        # Make a popup restricted to a particular product.
        vocab = BranchRestrictedOnProductVocabulary(self.launch_bag.product)
        self.assertEqual(vocab.product, self.launch_bag.product)
        popup = self.makeBranchPopup(vocab)

        # Make a branch on a different product.
        branch = self.factory.makeProductBranch(
            branch_type=BranchType.MIRRORED)
        self.assertNotEqual(self.launch_bag.product, branch.product)

        # Trying to make a branch with that URL will fail.
        self.assertRaises(ConversionError, popup._toFieldValue, branch.url)
class TestHandleStatusMixin:
    """Tests for `IPackageBuild`s handleStatus method.

    This should be run with a Trial TestCase.
    """

    layer = LaunchpadZopelessLayer

    def makeBuild(self):
        """Allow classes to override the build with which the test runs."""
        raise NotImplementedError

    def setUp(self):
        super(TestHandleStatusMixin, self).setUp()
        self.factory = LaunchpadObjectFactory()
        self.build = self.makeBuild()
        # For the moment, we require a builder for the build so that
        # handleStatus_OK can get a reference to the slave.
        self.builder = self.factory.makeBuilder()
        self.build.buildqueue_record.markAsBuilding(self.builder)
        self.slave = WaitingSlave('BuildStatus.OK')
        self.slave.valid_file_hashes.append('test_file_hash')
        self.interactor = BuilderInteractor()
        self.behavior = self.interactor.getBuildBehavior(
            self.build.buildqueue_record, self.builder, self.slave)

        # We overwrite the buildmaster root to use a temp directory.
        tempdir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, tempdir)
        self.upload_root = tempdir
        tmp_builddmaster_root = """
        [builddmaster]
        root: %s
        """ % self.upload_root
        config.push('tmp_builddmaster_root', tmp_builddmaster_root)

        # We stub out our builds getUploaderCommand() method so
        # we can check whether it was called as well as
        # verifySuccessfulUpload().
        removeSecurityProxy(self.build).verifySuccessfulUpload = FakeMethod(
            result=True)

    def assertResultCount(self, count, result):
        self.assertEquals(
            1, len(os.listdir(os.path.join(self.upload_root, result))))

    def test_handleStatus_OK_normal_file(self):
        # A filemap with plain filenames should not cause a problem.
        # The call to handleStatus will attempt to get the file from
        # the slave resulting in a URL error in this test case.
        def got_status(ignored):
            self.assertEqual(BuildStatus.UPLOADING, self.build.status)
            self.assertResultCount(1, "incoming")

        d = self.behavior.handleStatus(
            self.build.buildqueue_record, 'OK',
            {'filemap': {'myfile.py': 'test_file_hash'}})
        return d.addCallback(got_status)

    def test_handleStatus_OK_absolute_filepath(self):
        # A filemap that tries to write to files outside of
        # the upload directory will result in a failed upload.
        def got_status(ignored):
            self.assertEqual(BuildStatus.FAILEDTOUPLOAD, self.build.status)
            self.assertResultCount(0, "failed")
            self.assertIdentical(None, self.build.buildqueue_record)

        d = self.behavior.handleStatus(
            self.build.buildqueue_record, 'OK',
            {'filemap': {'/tmp/myfile.py': 'test_file_hash'}})
        return d.addCallback(got_status)

    def test_handleStatus_OK_relative_filepath(self):
        # A filemap that tries to write to files outside of
        # the upload directory will result in a failed upload.
        def got_status(ignored):
            self.assertEqual(BuildStatus.FAILEDTOUPLOAD, self.build.status)
            self.assertResultCount(0, "failed")

        d = self.behavior.handleStatus(
            self.build.buildqueue_record, 'OK',
            {'filemap': {'../myfile.py': 'test_file_hash'}})
        return d.addCallback(got_status)

    def test_handleStatus_OK_sets_build_log(self):
        # The build log is set during handleStatus.
        self.assertEqual(None, self.build.log)
        d = self.behavior.handleStatus(
            self.build.buildqueue_record, 'OK',
            {'filemap': {'myfile.py': 'test_file_hash'}})

        def got_status(ignored):
            self.assertNotEqual(None, self.build.log)

        return d.addCallback(got_status)

    def _test_handleStatus_notifies(self, status):
        # An email notification is sent for a given build status if
        # notifications are allowed for that status.

        expected_notification = (
            status in self.behavior.ALLOWED_STATUS_NOTIFICATIONS)

        def got_status(ignored):
            if expected_notification:
                self.failIf(
                    len(pop_notifications()) == 0,
                    "No notifications received")
            else:
                self.failIf(
                    len(pop_notifications()) > 0,
                    "Notifications received")

        d = self.behavior.handleStatus(
            self.build.buildqueue_record, status, {})
        return d.addCallback(got_status)

    def test_handleStatus_DEPFAIL_notifies(self):
        return self._test_handleStatus_notifies("DEPFAIL")

    def test_handleStatus_CHROOTFAIL_notifies(self):
        return self._test_handleStatus_notifies("CHROOTFAIL")

    def test_handleStatus_PACKAGEFAIL_notifies(self):
        return self._test_handleStatus_notifies("PACKAGEFAIL")

    def test_handleStatus_ABORTED_cancels_cancelling(self):
        self.build.updateStatus(BuildStatus.CANCELLING)

        def got_status(ignored):
            self.assertEqual(
                0, len(pop_notifications()), "Notifications received")
            self.assertEqual(BuildStatus.CANCELLED, self.build.status)

        d = self.behavior.handleStatus(
            self.build.buildqueue_record, "ABORTED", {})
        return d.addCallback(got_status)

    def test_handleStatus_ABORTED_recovers_building(self):
        self.builder.vm_host = "fake_vm_host"
        self.behavior = self.interactor.getBuildBehavior(
            self.build.buildqueue_record, self.builder, self.slave)
        self.build.updateStatus(BuildStatus.BUILDING)

        def got_status(ignored):
            self.assertEqual(
                0, len(pop_notifications()), "Notifications received")
            self.assertEqual(BuildStatus.NEEDSBUILD, self.build.status)
            self.assertEqual(1, self.builder.failure_count)
            self.assertEqual(1, self.build.failure_count)
            self.assertIn("clean", self.slave.call_log)

        d = self.behavior.handleStatus(
            self.build.buildqueue_record, "ABORTED", {})
        return d.addCallback(got_status)

    @defer.inlineCallbacks
    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)
        self.build.updateStatus(BuildStatus.CANCELLING)
        yield self.behavior.handleStatus(
            self.build.buildqueue_record, "ABORTED", {})
        self.assertNotEqual(None, self.build.log)

    def test_date_finished_set(self):
        # The date finished is updated during handleStatus_OK.
        self.assertEqual(None, self.build.date_finished)
        d = self.behavior.handleStatus(
            self.build.buildqueue_record, 'OK',
            {'filemap': {'myfile.py': 'test_file_hash'}})

        def got_status(ignored):
            self.assertNotEqual(None, self.build.date_finished)

        return d.addCallback(got_status)