def setup_method(self, method): """Prepare for testing""" super().setup_method(method) self._sleep_patcher = mock.patch( 'bodhi.server.tasks.updates.time.sleep') self._sleep = self._sleep_patcher.start() self.h = updates.UpdatesHandler()
def test_request_testing(self, work_on_bugs, fetch_test_cases, sleep): """ Assert correct behavior when the message tells us that the update is requested for testing. """ h = updates.UpdatesHandler() h.db_factory = base.TransactionalSessionMaker(self.Session) update = models.Build.query.filter_by( nvr='bodhi-2.0-1.fc17').one().update h.run(api_version=1, data={ 'action': 'testing', 'update': { 'alias': update.alias, 'builds': [{ 'nvr': 'bodhi-2.0-1.fc17' }], 'user': { 'name': 'brodhi' }, 'status': str(update.status), 'request': str(update.request) } }) assert work_on_bugs.call_count == 1 assert isinstance(work_on_bugs.mock_calls[0][1][1], sqlalchemy.orm.session.Session) assert work_on_bugs.mock_calls[0][1][2].title == 'bodhi-2.0-1.fc17' # The update's bug list should have been used. assert [b.bug_id for b in work_on_bugs.mock_calls[0][1][3]] == [12345] assert fetch_test_cases.call_count == 1 assert isinstance(fetch_test_cases.mock_calls[0][1][1], sqlalchemy.orm.session.Session) sleep.assert_called_once_with(1)
def test_not_rawhide_update_signed_stays_pending(self, work_on_bugs, fetch_test_cases, sleep): """ Assert that a non rawhide pending update that was edited does not get moved to testing if all the builds in the update are signed. """ update = models.Build.query.filter_by( nvr='bodhi-2.0-1.fc17').one().update update.status = models.UpdateStatus.pending update.release.composed_by_bodhi = True update.builds[0].signed = True h = updates.UpdatesHandler() h.db_factory = base.TransactionalSessionMaker(self.Session) h.run(api_version=1, data={ 'action': 'edit', 'update': { 'alias': update.alias, 'builds': [{ 'nvr': 'bodhi-2.0-1.fc17' }], 'user': { 'name': 'bodhi' }, 'status': str(update.status), 'request': str(update.request) }, 'new_bugs': [] }) assert update.status == models.UpdateStatus.pending
def test_update_not_found(self, work_on_bugs, fetch_test_cases, sleep): """ If the message references an update that isn't found, assert that an Exception is raised. """ h = updates.UpdatesHandler() h.db_factory = base.TransactionalSessionMaker(self.Session) with pytest.raises(exceptions.BodhiException) as exc: h.run(api_version=1, data={ 'action': 'testing', 'update': { 'alias': 'does not exist', 'builds': [{ 'nvr': 'bodhi-2.0-1.fc17' }], 'user': { 'name': 'brodhi' }, 'status': 'pending', 'request': 'testing' } }) assert str(exc.value) == "Couldn't find alias 'does not exist' in DB" assert work_on_bugs.call_count == 0 assert fetch_test_cases.call_count == 0 sleep.assert_called_once_with(1)
def test_handle_bugs_bodhi_email_falsey(self): """ Assert that bug handling is disabled when bodhi_email is configured "falsey". """ with mock.patch.dict(updates.config, {'bodhi_email': ''}): h = updates.UpdatesHandler() assert not h.handle_bugs
def test_gating_required_true(self, sleep): """Assert that test_gating_status is updated when test_gating is enabled.""" update = models.Build.query.filter_by( nvr='bodhi-2.0-1.fc17').one().update update.test_gating_status = None h = updates.UpdatesHandler() h.db_factory = base.TransactionalSessionMaker(self.Session) with mock.patch('bodhi.server.models.util.greenwave_api_post' ) as mock_greenwave: greenwave_response = { 'policies_satisfied': False, 'summary': 'what have you done‽', 'applicable_policies': ['taskotron_release_critical_tasks'], 'unsatisfied_requirements': [{ 'testcase': 'dist.rpmdeplint', 'item': { 'item': 'bodhi-2.0-1.fc17', 'type': 'koji_build' }, 'type': 'test-result-missing', 'scenario': None }, { 'testcase': 'dist.rpmdeplint', 'item': { 'item': update.alias, 'type': 'bodhi_update' }, 'type': 'test-result-missing', 'scenario': None }] } mock_greenwave.return_value = greenwave_response h.run(api_version=1, data={ 'action': 'testing', 'update': { 'alias': update.alias, 'builds': [{ 'nvr': 'bodhi-2.0-1.fc17' }], 'user': { 'name': 'brodhi' }, 'status': str(update.status), 'request': str(update.request) }, 'new_bugs': [] }) update = models.Build.query.filter_by( nvr='bodhi-2.0-1.fc17').one().update self.assertEqual(update.test_gating_status, models.TestGatingStatus.failed) sleep.assert_called_once_with(1)
def test_typical_config(self): """ Test the method with a typical config. """ with mock.patch.dict(updates.config, {'bodhi_email': '*****@*****.**'}): h = updates.UpdatesHandler() assert h.handle_bugs assert type(h.db_factory) == util.TransactionalSessionMaker
def test_handle_bugs_bodhi_email_missing(self): """ Assert that bug handling is disabled when bodhi_email is not configured. """ replacement_config = copy.deepcopy(updates.config) del replacement_config['bodhi_email'] with mock.patch.dict(updates.config, replacement_config, clear=True): h = updates.UpdatesHandler() assert not h.handle_bugs
def test_unknown_api_version(self, log_error, work_on_bugs, fetch_test_cases): """Test an unknown API version""" h = updates.UpdatesHandler() h.db_factory = base.TransactionalSessionMaker(self.Session) h.run(api_version="unknown", data={}) work_on_bugs.assert_not_called() fetch_test_cases.assert_not_called() log_error.assert_called_with( "The Updates Handler doesn't know how to handle api_version unknown. " "Message was: {}")
def test_bodhi_email_undefined(self, warning, info): """work_on_bugs() should log a warning and return if bodhi_email is not defined.""" h = updates.UpdatesHandler() # The args don't matter because it should exit before trying to use any of them. h.work_on_bugs(None, None, None) # We should see warnings about bodhi_email being undefined. assert warning.mock_calls == [ mock.call('No bodhi_email defined; not fetching bug details'), mock.call('Not configured to handle bugs') ]
def test_fetch_test_cases_exception(self, warning, MediaWiki): """ Assert that fetch_test_cases logs a warning when an exception is raised. """ h = updates.UpdatesHandler() MediaWiki.return_value.call.side_effect = URLError("oh no!") update = self.db.query(models.Update).filter( models.Build.nvr == 'bodhi-2.0-1.fc17').one() h.fetch_test_cases(h.db_factory, update) warning.assert_called_once_with( 'Error occurred during fetching testcases', exc_info=True)
def test_edited_update_bug_not_in_update(self, work_on_bugs, fetch_test_cases, sleep): """ Test an update edition when the list of bugs contains one that UpdatesHandler does not find in the update. """ bug = models.Bug(bug_id=123456) self.db.add(bug) self.db.commit() h = updates.UpdatesHandler() h.db_factory = base.TransactionalSessionMaker(self.Session) update = models.Build.query.filter_by( nvr='bodhi-2.0-1.fc17').one().update h.run(api_version=1, data={ 'action': 'edit', 'update': { 'alias': update.alias, 'builds': [{ 'nvr': 'bodhi-2.0-1.fc17' }], 'user': { 'name': 'brodhi' }, 'status': str(update.status), 'request': str(update.request) }, 'new_bugs': [12345, 123456] }) self.assertEqual(work_on_bugs.call_count, 1) self.assertTrue( isinstance(work_on_bugs.mock_calls[0][1][0], sqlalchemy.orm.session.Session)) self.assertEqual(work_on_bugs.mock_calls[0][1][1].title, 'bodhi-2.0-1.fc17') self.assertEqual([b.bug_id for b in work_on_bugs.mock_calls[0][1][2]], [12345, 123456]) self.assertEqual(fetch_test_cases.call_count, 1) self.assertTrue( isinstance(fetch_test_cases.mock_calls[0][1][0], sqlalchemy.orm.session.Session)) sleep.assert_called_once_with(1) # Bug with id '123456' should be attached to update bug = models.Bug.query.filter_by(bug_id=123456).one() update = models.Build.query.filter_by( nvr='bodhi-2.0-1.fc17').one().update self.assertIn(bug, update.bugs)
def test_api_version_2_wrong_format(self, log_error, work_on_bugs, fetch_test_cases): """Test API version 2""" h = updates.UpdatesHandler() h.db_factory = base.TransactionalSessionMaker(self.Session) data = { 'action': 'testing', # No update_alias key. } h.run(api_version=2, data=data) work_on_bugs.assert_not_called() fetch_test_cases.assert_not_called() log_error.assert_called_with( f"Wrong message format for the handle_update task: {data}")
def test_work_on_bugs_exception(self, warning): """ Assert that work_on_bugs logs a warning when an exception is raised. """ h = updates.UpdatesHandler() h.db_factory = base.TransactionalSessionMaker(self.Session) update = self.db.query(models.Update).filter( models.Build.nvr == 'bodhi-2.0-1.fc17').one() bugs = self.db.query(models.Bug).all() with mock.patch( 'bodhi.server.tasks.updates.bug_module.bugtracker.getbug', side_effect=RuntimeError("oh no!")): h.work_on_bugs(h.db_factory, update, bugs) warning.assert_called_once_with( 'Error occurred during updating single bug', exc_info=True)
def test_security_bug_sets_update_to_security(self): """Assert that associating a security bug with an Update changes the Update to security.""" h = updates.UpdatesHandler() h.db_factory = base.TransactionalSessionMaker(self.Session) update = self.db.query(models.Update).filter( models.Build.nvr == 'bodhi-2.0-1.fc17').one() # The update should start out in a non-security state so we know that work_on_bugs() changed # it. assert update.type == models.UpdateType.bugfix bug = models.Bug.query.first() # Set this bug to security, so that the update gets switched to security. bug.security = True self.db.flush() bugs = self.db.query(models.Bug).all() h.work_on_bugs(h.db_factory, update, bugs) assert update.type == models.UpdateType.security
def test_edited_update_bug_not_in_database(self, work_on_bugs, fetch_test_cases, sleep): """ Test an update edition when the list of bugs contains one that UpdatesHandler does not find in the database. """ h = updates.UpdatesHandler() h.db_factory = base.TransactionalSessionMaker(self.Session) update = models.Build.query.filter_by( nvr='bodhi-2.0-1.fc17').one().update h.run(api_version=1, data={ 'action': 'edit', 'update': { 'alias': update.alias, 'builds': [{ 'nvr': 'bodhi-2.0-1.fc17' }], 'user': { 'name': 'brodhi' }, 'status': 'pending', 'request': 'testing' }, 'new_bugs': [12345, 123456] }) assert work_on_bugs.call_count == 1 assert isinstance(work_on_bugs.mock_calls[0][1][0], sqlalchemy.orm.session.Session) assert work_on_bugs.mock_calls[0][1][1].title == 'bodhi-2.0-1.fc17' assert [b.bug_id for b in work_on_bugs.mock_calls[0][1][2]] == [12345, 123456] assert fetch_test_cases.call_count == 1 assert isinstance(fetch_test_cases.mock_calls[0][1][0], sqlalchemy.orm.session.Session) sleep.assert_called_once_with(1) # Nonexistent bug with id '123456' should now exist in DB as a bug attached to update bug = models.Bug.query.filter_by(bug_id=123456).one() update = models.Build.query.filter_by( nvr='bodhi-2.0-1.fc17').one().update assert bug in update.bugs
def test_edited_update_bugs_in_update(self, work_on_bugs, fetch_test_cases, sleep): """ Test with a message that indicates that the update is being edited, and the list of bugs matches what UpdatesHandler finds in the database. """ h = updates.UpdatesHandler() h.db_factory = base.TransactionalSessionMaker(self.Session) update = models.Build.query.filter_by( nvr='bodhi-2.0-1.fc17').one().update h.run(api_version=1, data={ 'action': 'edit', 'update': { 'alias': update.alias, 'builds': [{ 'nvr': 'bodhi-2.0-1.fc17' }], 'user': { 'name': 'brodhi' }, 'status': str(update.status), 'request': str(update.request) }, 'new_bugs': [12345] }) self.assertEqual(work_on_bugs.call_count, 1) self.assertTrue( isinstance(work_on_bugs.mock_calls[0][1][1], sqlalchemy.orm.session.Session)) self.assertEqual(work_on_bugs.mock_calls[0][1][2].title, 'bodhi-2.0-1.fc17') self.assertEqual([b.bug_id for b in work_on_bugs.mock_calls[0][1][3]], [12345]) self.assertEqual(fetch_test_cases.call_count, 1) self.assertTrue( isinstance(fetch_test_cases.mock_calls[0][1][1], sqlalchemy.orm.session.Session)) sleep.assert_called_once_with(1)
def test_unknown_topic(self, work_on_bugs, fetch_test_cases, sleep): """ Assert that NotImplementedError gets raised when an unknown action is received. """ h = updates.UpdatesHandler() h.db_factory = base.TransactionalSessionMaker(self.Session) update = models.Build.query.filter_by( nvr='bodhi-2.0-1.fc17').one().update # Use a bogus action to trigger the NotImplementedError. pytest.raises(NotImplementedError, h.run, api_version=1, data={ 'action': 'update.nawjustkiddin', 'update': { 'alias': update.alias }, 'new_bugs': [12345] }) assert work_on_bugs.call_count == 0 assert fetch_test_cases.call_count == 0 sleep.assert_called_once_with(1)
def test_api_version_2(self, work_on_bugs, fetch_test_cases): """Test API version 2""" bug = models.Bug(bug_id=123456) self.db.add(bug) self.db.commit() h = updates.UpdatesHandler() h.db_factory = base.TransactionalSessionMaker(self.Session) update = models.Build.query.filter_by( nvr='bodhi-2.0-1.fc17').one().update h.run(api_version=2, data={ 'action': 'testing', 'update_alias': update.alias, }) assert work_on_bugs.call_count == 1 called_update = work_on_bugs.mock_calls[0][1][1] assert called_update.title == 'bodhi-2.0-1.fc17' assert fetch_test_cases.call_count == 1 called_update = fetch_test_cases.mock_calls[0][1][1] assert called_update.title == 'bodhi-2.0-1.fc17'
def test_rawhide_update_edit_move_to_testing(self, work_on_bugs, fetch_test_cases, sleep): """ Assert that a pending rawhide update that was edited gets moved to testing if all the builds in the update are signed. """ update = models.Build.query.filter_by( nvr='bodhi-2.0-1.fc17').one().update update.status = models.UpdateStatus.pending update.release.composed_by_bodhi = False update.builds[0].signed = True h = updates.UpdatesHandler() h.db_factory = base.TransactionalSessionMaker(self.Session) with fml_testing.mock_sends(update_schemas.UpdateReadyForTestingV1): with mock.patch('bodhi.server.models.util.greenwave_api_post' ) as mock_greenwave: greenwave_response = { 'policies_satisfied': False, 'summary': 'what have you done‽', 'applicable_policies': ['taskotron_release_critical_tasks'], 'unsatisfied_requirements': [{ 'testcase': 'dist.rpmdeplint', 'item': { 'item': 'bodhi-2.0-1.fc17', 'type': 'koji_build' }, 'type': 'test-result-missing', 'scenario': None }, { 'testcase': 'dist.rpmdeplint', 'item': { 'item': update.alias, 'type': 'bodhi_update' }, 'type': 'test-result-missing', 'scenario': None }] } mock_greenwave.return_value = greenwave_response h.run(api_version=1, data={ 'action': 'edit', 'update': { 'alias': update.alias, 'builds': [{ 'nvr': 'bodhi-2.0-1.fc17' }], 'user': { 'name': 'bodhi' }, 'status': str(update.status), 'request': str(update.request) }, 'new_bugs': [] }) assert update.status == models.UpdateStatus.testing assert update.test_gating_status == models.TestGatingStatus.failed