def test_resources_parse_error(self): """ If VCSResource() raises a ParseError while loading, log an error and skip the resource. """ self.vcs_project.relative_resource_paths = Mock( return_value=['failure', 'success']) # Fail only if the path is failure so we can test the ignore. def vcs_resource_constructor(project, path, locales=None): if path == 'failure': raise ParseError('error message') else: return 'successful resource' changed_vcs_resources = {'success': [], 'failure': []} with patch('pontoon.sync.vcs.models.VCSResource') as MockVCSResource, \ patch('pontoon.sync.vcs.models.log') as mock_log, \ patch.object( VCSProject, 'changed_files', new_callable=PropertyMock, return_value=changed_vcs_resources ): MockVCSResource.side_effect = vcs_resource_constructor assert_equal(self.vcs_project.resources, {'success': 'successful resource'}) mock_log.error.assert_called_with( CONTAINS('failure', 'error message'))
def test_parametrized_serial_task(self): """ Serial task should be able to work simultaneously for different parameters. """ with patch('pontoon.sync.core.cache') as mock_cache: @serial_task(3, lock_key="param={0}") def task_lock_key(self, param): return param first_call = task_lock_key.delay(42) second_call = task_lock_key.delay(24) assert_true(first_call.successful()) assert_true(second_call.successful()) assert_true(first_call.get(), 42) assert_true(second_call.get(), 24) mock_cache.add.assert_any_call(CONTAINS('task_lock_key[param=42]'), ANY, timeout=3) mock_cache.add.assert_any_call(CONTAINS('task_lock_key[param=24]'), ANY, timeout=3)
def test_commit_changes_error(self): """If commit_changes returns an error object, log it.""" self.command.stdout = Mock() self.mock_commit_to_vcs.return_value = {'message': 'Whoops!'} self.command.commit_changes(self.db_project, self.vcs_project, self.changeset) self.command.stdout.write.assert_called_with( CONTAINS('db-project', 'failed', 'Whoops!') )
def test_missing_log(self): """ If a log with the given PK doesn't exist, log it and exit. """ with patch('pontoon.sync.tasks.log') as mock_log: with assert_raises(SyncLog.DoesNotExist): sync_project(self.db_project.pk, 99999) mock_log.error.assert_called_with(CONTAINS('99999')) assert_false(self.mock_perform_sync_project.called)
def test_missing_project(self): """ If a project with the given PK doesn't exist, log it and exit. """ with patch('pontoon.sync.tasks.log') as mock_log: with assert_raises(Project.DoesNotExist): sync_project(99999, self.sync_log.pk) mock_log.error.assert_called_with(CONTAINS('99999')) assert_false(self.mock_update_originals.called)
def test_missing_log(self): """ If a log with the given PK doesn't exist, log it and exit. """ with patch("pontoon.sync.tasks.log") as mock_log: with pytest.raises(SyncLog.DoesNotExist): sync_project(self.db_project.pk, 99999) mock_log.error.assert_called_with(CONTAINS("99999")) assert not self.mock_update_originals.called
def test_missing_project(self): """ If a project with the given PK doesn't exist, log it and exit. """ with patch('pontoon.sync.tasks.log') as mock_log, \ patch('pontoon.sync.tasks.perform_sync') as mock_perform_sync: sync_project(99999) mock_log.error.assert_called_with(CONTAINS('99999')) assert_false(mock_perform_sync.called)
def test_error(self): """If commit_changes returns an error object, log it.""" self.repository.commit.return_value = {'message': 'Whoops!'} self.db_project.repository_for_path = Mock( return_value=self.repository) with patch('pontoon.sync.core.log') as mock_log: commit_changes(self.db_project, self.vcs_project, self.changeset) mock_log.info.assert_called_with( CONTAINS('db-project', 'failed', 'Whoops!'))
def test_commit_changes_raised_exception(self): """ If commit_changes raises a CommitToRepositoryException, log it. """ self.command.stdout = Mock() self.mock_commit_to_vcs.side_effect = CommitToRepositoryException('Whoops!') self.command.commit_changes(self.db_project, self.vcs_project, self.changeset) self.command.stdout.write.assert_called_with( CONTAINS('db-project', 'failed', 'Whoops!') )
def test_raised_valueerror(self): """ If db_project.repository_for_path raises a ValueError, log it. """ self.db_project.repository_for_path = Mock( side_effect=ValueError('Whoops!')) with patch('pontoon.sync.core.log') as mock_log: commit_changes(self.db_project, self.vcs_project, self.changeset) mock_log.info.assert_called_with( CONTAINS('db-project', 'failed', 'Whoops!'))
def test_basic(self): user = UserFactory.create() self.changeset.commit_authors_per_locale = { self.translated_locale.code: [user] } self.db_project.repository_for_path = Mock( return_value=self.repository) commit_changes(self.db_project, self.vcs_project, self.changeset) self.repository.commit.assert_called_with( CONTAINS(user.display_name), user, os.path.join(FAKE_CHECKOUT_PATH, self.translated_locale.code))
def test_raised_committorepositoryexception(self): """ If repo.commit raises a CommitToRepositoryException, log it. """ self.repository.commit.side_effect = CommitToRepositoryException( 'Whoops!') self.db_project.repository_for_path = Mock( return_value=self.repository) with patch('pontoon.sync.core.log') as mock_log: commit_changes(self.db_project, self.vcs_project, self.changeset) mock_log.info.assert_called_with( CONTAINS('db-project', 'failed', 'Whoops!'))
def test_commit_changes(self): user = UserFactory.create() self.changeset.commit_authors_per_locale = { self.translated_locale.code: [user] } self.command.commit_changes(self.db_project, self.vcs_project, self.changeset) self.mock_commit_to_vcs.assert_called_with( 'git', os.path.join(FAKE_CHECKOUT_PATH, self.translated_locale.code), CONTAINS(user.display_name), user, 'https://example.com/git' )
def test_execute_log_error(self): """ If the return code from execute is non-zero and log_errors is True, log an error message. """ repo = VCSRepository('/path') with patch('pontoon.sync.vcs.repositories.execute') as mock_execute, \ patch('pontoon.sync.vcs.repositories.log') as mock_log: mock_execute.return_value = 1, 'output', 'stderr' assert_equal( repo.execute('command', cwd='working_dir', log_errors=True), (1, 'output', 'stderr')) mock_log.error.assert_called_with( CONTAINS('stderr', 'command', 'working_dir'))
def test_db_changed_no_repo_changed(self): """ If the database has changes and VCS doesn't, skip syncing resources, but sync translations. """ self.mock_pull_source_repo_changes.return_value = False self.mock_project_needs_sync.return_value = True with patch("pontoon.sync.tasks.log") as mock_log: sync_project(self.db_project.pk, self.sync_log.pk) sync_project(self.db_project.pk, self.sync_log.pk) assert not self.mock_update_originals.called mock_log.info.assert_called_with( CONTAINS("Skipping syncing sources", self.db_project.slug))
def test_no_changes_skip(self): """ If the database and VCS both have no changes, skip sync and log a message. """ self.mock_pull_changes.return_value = False self.mock_project_needs_sync.return_value = False with patch('pontoon.sync.core.log') as mock_log, \ patch('pontoon.sync.core.handle_entity') as mock_handle_entity: sync_project(self.db_project) assert_false(mock_handle_entity.called) mock_log.info.assert_called_with( CONTAINS('Skipping', self.db_project.slug))
def test_no_changes_skip(self): """ If the database and the source repository both have no changes, and project has a single repository, skip sync. """ self.mock_pull_source_repo_changes.return_value = False self.mock_project_needs_sync.return_value = False with patch("pontoon.sync.tasks.log") as mock_log: sync_project(self.db_project.pk, self.sync_log.pk) assert not self.mock_update_originals.called mock_log.info.assert_called_with( CONTAINS("Skipping project", self.db_project.slug)) # When skipping, mark the project log properly. assert ProjectSyncLog.objects.get(project=self.db_project).skipped
def test_execute_log_error(self): """ If the return code from execute is non-zero and log_errors is True, log an error message. """ repo = VCSRepository("/path") with patch("pontoon.sync.vcs.repositories.execute" ) as mock_execute, patch( "pontoon.sync.vcs.repositories.log") as mock_log: mock_execute.return_value = 1, "output", "stderr" assert_equal( repo.execute("command", cwd="working_dir", log_errors=True), (1, "output", "stderr"), ) mock_log.error.assert_called_with( CONTAINS("stderr", "command", "working_dir"))
def test_author_with_multiple_contributions(self): """ Tests if author with multiple contributions occurs once in commit message. """ author = UserFactory.create() self.changeset.commit_authors_per_locale = { self.translated_locale.code: [author, author] } self.db_project.repository_for_path = Mock( return_value=self.repository) commit_changes(self.db_project, self.vcs_project, self.changeset, self.translated_locale) self.repository.commit.assert_called_with( CONTAINS(author.display_name_and_email), author, os.path.join(FAKE_CHECKOUT_PATH, self.translated_locale.code)) commit_message = self.repository.commit.mock_calls[0][1][0] assert_equal(commit_message.count(author.display_name_and_email), 1)
def test_no_changes_skip(self): """ If the database and VCS both have no changes, skip sync and log a message. """ self.mock_pull_changes.return_value = False self.mock_project_needs_sync.return_value = False with patch('pontoon.sync.tasks.log') as mock_log: sync_project(self.db_project.pk, self.sync_log.pk) assert_false(self.mock_perform_sync_project.called) mock_log.info.assert_called_with( CONTAINS('Skipping', self.db_project.slug) ) # When skipping, mark the project log properly. assert_true(ProjectSyncLog.objects.get(project=self.db_project).skipped)
def test_multiple_authors(self): """ Tests if multiple authors are passed to commit message. The author with the most occurrences for the locale should be set as the commit author. """ first_author, second_author = UserFactory.create_batch(2) self.changeset.commit_authors_per_locale = { self.translated_locale.code: [first_author, first_author, second_author] } self.db_project.repository_for_path = Mock(return_value=self.repository) commit_changes(self.db_project, self.vcs_project, self.changeset, self.translated_locale) self.repository.commit.assert_called_with( CONTAINS(first_author.display_name_and_email, second_author.display_name_and_email), first_author, os.path.join(FAKE_CHECKOUT_PATH, self.translated_locale.code) )
def test_no_authors(self): """ If no authors are found in the changeset, default to a fake "Pontoon" user. """ self.changeset.commit_authors_per_locale = { self.translated_locale.code: [] } self.db_project.repository_for_path = Mock( return_value=self.repository) commit_changes(self.db_project, self.vcs_project, self.changeset) self.repository.commit.assert_called_with( NOT(CONTAINS('Authors:')), # Don't list authors in commit ANY, os.path.join(FAKE_CHECKOUT_PATH, self.translated_locale.code)) user = self.mock_repo_commit.call_args[0][1] assert_equal(user.first_name, 'Pontoon') assert_equal(user.email, '*****@*****.**')
def test_commit_changes_no_authors(self): """ If no authors are found in the changeset, default to a fake "Pontoon" user. """ self.changeset.commit_authors_per_locale = { self.translated_locale.code: [] } self.command.commit_changes(self.db_project, self.vcs_project, self.changeset) self.mock_commit_to_vcs.assert_called_with( 'git', os.path.join(FAKE_CHECKOUT_PATH, self.translated_locale.code), NOT(CONTAINS('Authors:')), # Don't list authors in commit ANY, 'https://example.com/git' ) user = self.mock_commit_to_vcs.call_args[0][3] assert_equal(user.first_name, 'Pontoon') assert_equal(user.email, '*****@*****.**')