コード例 #1
0
ファイル: tests.py プロジェクト: pombredanne/DistroTracker
 def setUp(self):
     self.job_state = mock.create_autospec(JobState)
     self.job_state.events_for_task.return_value = []
     self.job = mock.create_autospec(Job)
     self.job.job_state = self.job_state
     self.generate_news_task = GenerateNewsFromRepositoryUpdates()
     self.generate_news_task.job = self.job
コード例 #2
0
ファイル: tests.py プロジェクト: pombredanne/DistroTracker
class GenerateNewsFromRepositoryUpdatesTest(TestCase):
    """
    Tests the news generated by various repository updates.
    """
    def setUp(self):
        self.job_state = mock.create_autospec(JobState)
        self.job_state.events_for_task.return_value = []
        self.job = mock.create_autospec(Job)
        self.job.job_state = self.job_state
        self.generate_news_task = GenerateNewsFromRepositoryUpdates()
        self.generate_news_task.job = self.job

    def add_mock_events(self, name, arguments):
        """
        Helper method adding mock events which the news generation task will
        see when it runs.
        """
        self.job_state.events_for_task.return_value.append(
            Event(name=name, arguments=arguments)
        )

    def run_task(self):
        self.generate_news_task.execute()

    def create_source_package(self, name, version, events=True):
        """
        Helper method which creates a new source package and makes sure all
        events that would have been raised on creating the package are
        passed to the news generation task if the ``events`` flag is set.

        :param name: The name of the source package to create
        :param version: The version of the source package which is created
        :param events: A flag indicating whether the corresponding events
            should be passed to the generation task when it runs.
        """
        # Make sure the source package name object exists
        src_pkg_name, _ = SourcePackageName.objects.get_or_create(name=name)
        src_pkg, _ = SourcePackage.objects.get_or_create(
            source_package_name=src_pkg_name, version=version)
        # Add all events for a newly created source package which the task will
        # receive.
        if events:
            self.add_mock_events('new-source-package-version', {
                'name': name,
                'version': version,
            })

        return src_pkg

    def add_source_package_to_repository(self, name, version, repository,
                                         events=True):
        """
        Helper method which adds a source package to the given repository
        and makes sure the corresponding events are received by the
        news generation task if the ``events`` flag is set.

        :param name: The name of the source package
        :param version: The version of the source package
        :param repository: The repository to which to add the source package
        :param events: A flag indicating whether the corresponding events
            should be passed to the generation task when it runs.
        """
        repo, _ = Repository.objects.get_or_create(name=repository, defaults={
            'shorthand': repository[:10],
            'suite': 'suite',
            'components': ['component']
        })

        source_package = SourcePackage.objects.get(
            source_package_name__name=name,
            version=version)

        entry = SourcePackageRepositoryEntry(
            repository=repo,
            source_package=source_package)
        entry.save()

        if events:
            self.add_mock_events('new-source-package-version-in-repository', {
                'name': name,
                'version': version,
                'repository': repository,
            })

    def remove_source_package_from_repository(self, name, version, repository,
                                              events=True):
        """
        Helper method which removes the given source package version from the
        given repository. It makes sure the corresponding events are received
        by the news generation task if the ``events`` flag is set.
        """
        SourcePackageRepositoryEntry.objects.filter(
            source_package__source_package_name__name=name,
            source_package__version=version,
            repository__name=repository).delete()
        if events:
            self.add_mock_events('lost-source-package-version-in-repository', {
                'name': name,
                'version': version,
                'repository': repository,
            })

    def assert_correct_accepted_message(self, title,
                                        package_name, version, repository):
        self.assertEqual(
            'Accepted {pkg} version {ver} to {repo}'.format(
                pkg=package_name, ver=version, repo=repository),
            title
        )

    def assert_correct_migrated_message(self, title,
                                        package_name, version, repository):
        self.assertEqual(
            '{pkg} version {ver} MIGRATED to {repo}'.format(
                pkg=package_name, ver=version, repo=repository),
            title
        )

    def assert_correct_removed_message(self, title, package_name, repository):
        self.assertEqual(
            '{pkg} REMOVED from {repo}'.format(
                pkg=package_name, repo=repository),
            title
        )

    def test_new_source_package(self):
        """
        Tests the case when a completely new source package is created (it was
        not seen in any repository previously).
        """
        source_package_name = 'dummy-package'
        source_package_version = '1.0.0'
        repository_name = 'some-repository'
        self.create_source_package(source_package_name, source_package_version)
        self.add_source_package_to_repository(
            source_package_name, source_package_version, repository_name)

        self.run_task()

        # A news item was created
        self.assertEqual(1, News.objects.count())
        news = News.objects.all()[0]
        self.assertEqual(news.package.name, source_package_name)
        self.assert_correct_accepted_message(
            news.title,
            source_package_name, source_package_version, repository_name)

    def test_new_source_package_version(self):
        """
        Tests the case when a new version of an already existing source package
        is created.
        """
        source_package_name = 'dummy-package'
        source_package_version = '1.1.0'
        repository_name = 'some-repository'
        # Create the package, but do not add those events to the task
        self.create_source_package(
            source_package_name, source_package_version, events=False)
        # Add the package to the repository
        self.add_source_package_to_repository(
            source_package_name, source_package_version, repository_name)

        self.run_task()

        # A news item was created
        self.assertEqual(1, News.objects.count())
        news = News.objects.all()[0]
        self.assertEqual(news.package.name, source_package_name)
        self.assert_correct_migrated_message(
            news.title,
            source_package_name, source_package_version, repository_name)

    def test_new_source_package_version_replaces_old_one(self):
        """
        Tests the case when a new version of an already existing source
        package is created and added to the repository which contains
        the old package version.
        """
        source_package_name = 'dummy-package'
        old_version = '1.0.0'
        new_version = '1.1.0'
        repository = 'repo'
        # Create the old version and make sure it is already in the
        # repository
        self.create_source_package(
            source_package_name, old_version, events=False)
        self.add_source_package_to_repository(
            source_package_name, old_version, repository, events=False)
        # Now create the new version and make it replace the old version
        # in the repository
        self.create_source_package(source_package_name, new_version)
        self.add_source_package_to_repository(
            source_package_name, new_version, repository)
        self.remove_source_package_from_repository(
            source_package_name, old_version, repository)

        self.run_task()

        # Only one news item is created
        self.assertEqual(1, News.objects.count())

    def test_multiple_new_versions_same_repo(self):
        """
        Tests the case when there are multiple new versions in a repository.
        """
        source_package_name = 'dummy-package'
        versions = ['1.0.0', '1.1.0']
        repository_name = 'some-repository'
        # Create the package versions
        for version in versions:
            self.create_source_package(source_package_name, version)
            self.add_source_package_to_repository(
                source_package_name, version, repository_name)

        self.run_task()

        # Two news items exist
        self.assertEqual(2, News.objects.count())
        titles = [news.title for news in News.objects.all()]
        ## This is actually a sort by version found in the title
        titles.sort()
        for title, version in zip(titles, versions):
            self.assert_correct_accepted_message(
                title,
                source_package_name, version, repository_name
            )

    def test_multiple_new_versions_different_repos(self):
        """
        Tests the case when there are mutliple new versions of a source package
        each in a different repository.
        """
        source_package_name = 'dummy-package'
        versions = ['1.0.0', '1.1.0']
        repositories = ['repo1', 'repo2']
        # Create these versions
        for version, repository in zip(versions, repositories):
            self.create_source_package(source_package_name, version)
            self.add_source_package_to_repository(
                source_package_name, version, repository)

        self.run_task()

        self.assertEqual(2, News.objects.count())
        titles = [news.title for news in News.objects.all()]
        ## This is actually a sort by version found in the title
        titles.sort()
        for title, version, repository_name in zip(titles, versions, repositories):
            self.assert_correct_accepted_message(
                title,
                source_package_name, version, repository_name
            )

    def test_package_version_add_different_repos(self):
        """
        Tests the case where a single existing package version is added to two
        repositories.
        """
        source_package_name = 'dummy-package'
        version = '1.1.0'
        repositories = ['repo1', 'repo2']
        self.create_source_package(source_package_name, version, events=False)
        for repository in repositories:
            self.add_source_package_to_repository(
                source_package_name, version, repository)

        self.run_task()

        self.assertEqual(2, News.objects.count())
        ## This is a sort by repository name
        titles = [news.title for news in News.objects.all()]
        for title, repository_name in zip(titles, repositories):
            self.assert_correct_migrated_message(
                title,
                source_package_name, version, repository_name
            )

    def test_package_version_updates_different_repos(self):
        """
        Tests the case where a single existing package version is added to two
        repositories replacing the versions previously found in those
        repositories.
        """
        source_package_name = 'dummy-package'
        old_version = '1.0.0'
        version = '1.1.0'
        repositories = ['repo1', 'repo2']
        self.create_source_package(source_package_name, version, events=False)
        self.create_source_package(
            source_package_name, old_version, events=False)
        for repository in repositories:
            # Old version
            self.add_source_package_to_repository(
                source_package_name, old_version, repository, events=False)
            # Replace the old version with the new one
            self.remove_source_package_from_repository(
                source_package_name, old_version, repository)
            self.add_source_package_to_repository(
                source_package_name, version, repository)

        self.run_task()

        # Only two news messages.
        self.assertEqual(2, News.objects.count())
        ## This is a sort by repository name
        titles = [news.title for news in News.objects.all()]
        for title, repository_name in zip(titles, repositories):
            self.assert_correct_migrated_message(
                title,
                source_package_name, version, repository_name
            )

    def test_multiple_package_updates_different_repos(self):
        """
        Tests the case where different repositories get different new package
        versions when they already previously had another version of the
        package.
        """
        source_package_name = 'dummy-package'
        versions = ['1.1.0', '1.2.0']
        old_version = '1.0.0'
        repositories = ['repo1', 'repo2']
        for repository in repositories:
            self.create_source_package(
                source_package_name, old_version, events=False)
            self.add_source_package_to_repository(
                source_package_name, old_version, repository, events=False)
        # Add the new package version to each repository
        for version, repository in zip(versions, repositories):
            self.create_source_package(source_package_name, version)
            self.add_source_package_to_repository(
                source_package_name, version, repository)

        self.run_task()

        self.assertEqual(2, News.objects.count())
        titles = [news.title for news in News.objects.all()]
        titles.sort()
        for title, version, repository in zip(titles, versions, repositories):
            self.assert_correct_accepted_message(
                title,
                source_package_name, version, repository)

    def test_source_package_removed(self):
        """
        Tests the case where a single source package version is removed
        from a repository.
        """
        source_package_name = 'dummy-package'
        version = '1.0.0'
        repository = 'repo'
        self.create_source_package(source_package_name, version, events=False)
        self.add_source_package_to_repository(
            source_package_name, version, repository, events=False)
        self.remove_source_package_from_repository(
            source_package_name, version, repository)

        self.run_task()

        # A news item is created.
        self.assertEqual(1, News.objects.count())
        self.assert_correct_removed_message(
            News.objects.all()[0].title,
            source_package_name, repository
        )

    def test_multiple_versions_removed_same_repo(self):
        """
        Tests the case where multiple versions of the same package are removed
        from the same repository and there are no more remaining versions of
        the package in that repository.
        """
        source_package_name = 'dummy-package'
        versions = ['1.0.0', '1.1.0']
        repository = 'repo'
        for version in versions:
            self.create_source_package(
                source_package_name, version, events=False)
            self.add_source_package_to_repository(
                source_package_name, version, repository, events=False)
            self.remove_source_package_from_repository(
                source_package_name, version, repository)

        self.run_task()

        # Only one news item should be created
        self.assertEqual(1, News.objects.count())
        news = News.objects.all()[0]
        self.assert_correct_removed_message(
            news.title,
            source_package_name, repository
        )

    def test_only_one_version_removed(self):
        """
        Tests the case where a version is removed from the repository, but the
        repository still contains other versions of the same package.
        """
        source_package_name = 'dummy-package'
        versions = ['1.0.0', '1.1.0']
        repository = 'repo'
        for version in versions:
            self.create_source_package(
                source_package_name, version, events=False)
            self.add_source_package_to_repository(
                source_package_name, version, repository, events=False)
        # Remove only one of the versions
        removed_version = versions[0]
        self.remove_source_package_from_repository(
            source_package_name, removed_version, repository)

        self.run_task()

        # No news are generated
        self.assertEqual(0, News.objects.count())

    def test_migrate_and_remove(self):
        """
        Tests the case where a single package version is simultaneously
        added to one repository and removed from another.
        """
        source_package_name = 'dummy-package'
        version = '1.0.0'
        repositories = ['repo1', 'repo2']

        self.create_source_package(
            source_package_name, version, events=False)
        self.add_source_package_to_repository(
            source_package_name, version, repositories[0], events=False)
        # Add the version to one repository
        self.add_source_package_to_repository(
            source_package_name, version, repositories[1])
        # Remove it from the one that already had it
        self.remove_source_package_from_repository(
            source_package_name, version, repositories[0])

        self.run_task()

        # Two news items - removed from one repositories, migrated to another
        self.assertEqual(2, News.objects.count())
        self.assert_correct_removed_message(
            News.objects.all()[0].title,
            source_package_name, repositories[0])
        self.assert_correct_migrated_message(
            News.objects.all()[1].title,
            source_package_name, version, repositories[1])

    def test_multiple_packages_added_same_repo(self):
        """
        Tests the case where multiple new packages are added to the same
        repository.
        """
        names = ['package1', 'package2']
        version = '1.0.0'
        repository = 'repo1'
        for name in names:
            self.create_source_package(name, version)
            self.add_source_package_to_repository(name, version, repository)

        self.run_task()

        self.assertEqual(2, News.objects.count())
        all_news = sorted(News.objects.all(), key=lambda x: x.title)
        for name, news in zip(names, all_news):
            self.assert_correct_accepted_message(
                news.title,
                name, version, repository)
            # The news is linked with the correct package
            self.assertEqual(news.package.name, name)

    def test_multiple_packages_removed_different_repos(self):
        """
        Tests the case where multiple packages are removed from different
        repositories.
        """
        names = ['package1', 'package2']
        version = '1.0.0'
        repositories = ['repo1', 'repo2']
        for name, repository in zip(names, repositories):
            self.create_source_package(name, version, events=False)
            self.add_source_package_to_repository(name, version, repository,
                                                  events=False)
            # Remove the source package from the repository
            self.remove_source_package_from_repository(
                name, version, repository)

        self.run_task()

        self.assertEqual(2, News.objects.count())
        all_news = sorted(News.objects.all(), key=lambda x: x.title)
        for name, news, repository in zip(names, all_news, repositories):
            self.assert_correct_removed_message(
                news.title,
                name, repository)
            # The news is linked with the correct package
            self.assertEqual(news.package.name, name)

    @mock.patch('pts.auto_news.pts_tasks.get_resource_content')
    def test_dsc_file_in_news_content(self, mock_get_resource_content):
        """
        Tests that the dsc file is found in the content of a news item created
        when a new package version appears.
        """
        name = 'package'
        version = '1.0.0'
        repository = 'repo'
        self.create_source_package(name, version)
        self.add_source_package_to_repository(name, version, repository)
        expected_content = 'This is fake content'
        mock_get_resource_content.return_value = expected_content.encode('utf-8')

        self.run_task()

        self.assertEqual(1, News.objects.count())
        news = News.objects.all()[0]
        self.assertEqual(news.content, expected_content)

    @temporary_media_dir
    def test_changelog_entry_in_news_content(self):
        """
        Tests that the news item created for new source package versions
        contains the changelog entry for the version.
        """
        name = 'package'
        version = '1.0.0'
        repository = 'repo'
        src_pkg = self.create_source_package(name, version)
        self.add_source_package_to_repository(name, version, repository)
        changelog_entry = (
            "package (1.0.0) suite; urgency=high\n\n"
            "  * New stable release:\n"
            "    - Feature 1\n"
            "    - Feature 2\n\n"
            " -- Maintainer <*****@*****.**>  Mon, 1 July 2013 09:00:00 +0000"
        )
        ExtractedSourceFile.objects.create(
            source_package=src_pkg,
            extracted_file=ContentFile(changelog_entry, name='changelog'),
            name='changelog')

        self.run_task()

        self.assertEqual(News.objects.count(), 1)
        news = News.objects.all()[0]
        self.assertIn(changelog_entry, news.content)