From dcff5a4739d26735ba6719c7e31c50fc75c40cba Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Thu, 6 Mar 2014 14:17:00 -0800 Subject: [PATCH] Make IRC bot list which failures were seen in which job. Instead of saying you failed x jobs, because of y bugs. Map the two. Some refactoring was needed to add unit tests. Change-Id: I1c49c8cd4df24c7fb4c152e188f74caa13dfed9c --- elastic_recheck/bot.py | 28 ++++---- elastic_recheck/tests/unit/test_bot.py | 99 ++++++++++++++++++++------ 2 files changed, 93 insertions(+), 34 deletions(-) diff --git a/elastic_recheck/bot.py b/elastic_recheck/bot.py index a84151f1..52c0f6a1 100755 --- a/elastic_recheck/bot.py +++ b/elastic_recheck/bot.py @@ -119,6 +119,18 @@ class RecheckWatch(threading.Thread): 'production', LPCACHEDIR) + def display(self, channel, event): + display = False + for project in self._get_bug_projects(event.get_all_bugs()): + if channel in self.channel_config.projects['all']: + display = True + break + elif project in self.channel_config.projects: + if channel in self.channel_config.projects[project]: + display = True + break + return display + def new_error(self, channel, event): # only on gate fails queue = event.queue() @@ -132,21 +144,11 @@ class RecheckWatch(threading.Thread): self.print_msg(channel, msg) def error_found(self, channel, event): - msg = ('%s change: %s failed %s because of: %s' % ( + msg = ('%s change: %s failed because of: %s' % ( event.project, event.url, - ", ".join(event.failed_job_names()), - " and ".join(event.bug_urls()))) - display = False - for project in self._get_bug_projects(event.get_all_bugs()): - if channel in self.channel_config.projects['all']: - display = True - break - elif project in self.channel_config.projects: - if channel in self.channel_config.projects[project]: - display = True - break - if display: + ", ".join(event.bug_urls_map()))) + if self.display(channel, event): self.print_msg(channel, msg) else: self.log.info("Didn't leave a message on channel %s for %s because" diff --git a/elastic_recheck/tests/unit/test_bot.py b/elastic_recheck/tests/unit/test_bot.py index a9f0335f..3d4b534a 100644 --- a/elastic_recheck/tests/unit/test_bot.py +++ b/elastic_recheck/tests/unit/test_bot.py @@ -16,9 +16,30 @@ import ConfigParser import unittest import yaml +import fixtures import mock from elastic_recheck import bot +from elastic_recheck import elasticRecheck +from elastic_recheck import tests +import elastic_recheck.tests.unit.fake_gerrit as fg + + +def _set_fake_config(fake_config): + fake_config.add_section('ircbot') + fake_config.add_section('gerrit') + # Set fake ircbot config + fake_config.set('ircbot', 'nick', 'Fake_User') + fake_config.set('ircbot', 'pass', '') + fake_config.set('ircbot', 'server', 'irc.fake.net') + fake_config.set('ircbot', 'port', 6667) + fake_config.set('ircbot', 'channel_config', + 'fake_recheck_watch_bot.yaml') + # Set fake gerrit config + fake_config.set('gerrit', 'user', 'fake_user') + fake_config.set('gerrit', 'query_file', 'fake_query_file') + fake_config.set('gerrit', 'host', 'fake_host.openstack.org') + fake_config.set('gerrit', 'key', 'abc123def456') # NOTE(mtreinish) Using unittest here because testtools TestCase.assertRaises @@ -27,7 +48,7 @@ class TestBot(unittest.TestCase): def setUp(self): super(TestBot, self).setUp() self.fake_config = ConfigParser.ConfigParser({'server_password': None}) - self._set_fake_config() + _set_fake_config(self.fake_config) self.channel_config = bot.ChannelConfig(yaml.load( open('recheckwatchbot.yaml'))) with mock.patch('launchpadlib.launchpad.Launchpad'): @@ -40,29 +61,13 @@ class TestBot(unittest.TestCase): self.fake_config.get('gerrit', 'key'), False) - def _set_fake_config(self): - self.fake_config.add_section('ircbot') - self.fake_config.add_section('gerrit') - # Set fake ircbot config - self.fake_config.set('ircbot', 'nick', 'Fake_User') - self.fake_config.set('ircbot', 'pass', '') - self.fake_config.set('ircbot', 'server', 'irc.fake.net') - self.fake_config.set('ircbot', 'port', 6667) - self.fake_config.set('ircbot', 'channel_config', - 'fake_recheck_watch_bot.yaml') - # Set fake gerrit config - self.fake_config.set('gerrit', 'user', 'fake_user') - self.fake_config.set('gerrit', 'query_file', 'fake_query_file') - self.fake_config.set('gerrit', 'host', 'fake_host.openstack.org') - self.fake_config.set('gerrit', 'key', 'abc123def456') - def test_read_channel_config_not_specified(self): self.fake_config.set('ircbot', 'channel_config', None) with self.assertRaises(Exception) as exc: bot._main([], self.fake_config) raised_exc = exc.exception - self.assertEquals(str(raised_exc), "Channel Config must be specified " - "in config file.") + self.assertEqual(str(raised_exc), "Channel Config must be specified " + "in config file.") def test_read_channel_config_invalid_path(self): self.fake_config.set('ircbot', 'channel_config', 'fake_path.yaml') @@ -70,11 +75,63 @@ class TestBot(unittest.TestCase): bot._main([], self.fake_config) raised_exc = exc.exception error_msg = "Unable to read layout config file at fake_path.yaml" - self.assertEquals(str(raised_exc), error_msg) + self.assertEqual(str(raised_exc), error_msg) def test__read_no_event_no_msg(self): with self.assertRaises(Exception) as exc: self.recheck_watch._read() raised_exc = exc.exception error_msg = 'No event or msg specified' - self.assertEquals(str(raised_exc), error_msg) + self.assertEqual(str(raised_exc), error_msg) + + +class TestBotWithTestTools(tests.TestCase): + + def setUp(self): + super(TestBotWithTestTools, self).setUp() + self.useFixture(fixtures.MonkeyPatch( + 'gerritlib.gerrit.Gerrit', + fg.Gerrit)) + self.fake_config = ConfigParser.ConfigParser({'server_password': None}) + _set_fake_config(self.fake_config) + self.channel_config = bot.ChannelConfig(yaml.load( + open('recheckwatchbot.yaml'))) + with mock.patch('launchpadlib.launchpad.Launchpad'): + self.recheck_watch = bot.RecheckWatch( + None, + self.channel_config, + self.fake_config.get('gerrit', 'user'), + self.fake_config.get('gerrit', 'query_file'), + self.fake_config.get('gerrit', 'host'), + self.fake_config.get('gerrit', 'key'), + False) + + def fake_print(self, channel, msg): + reference = ("openstack/keystone change: https://review.openstack.org/" + "64750 failed because of: gate-keystone-python27: " + "unrecognized error, gate-keystone-python2" + "6: https://bugs.launchpad.net/bugs/123456") + self.assertEqual(reference, msg) + + def fake_display(self, channel, msg): + return True + + def test_error_found(self): + self.useFixture(fixtures.MonkeyPatch( + 'elastic_recheck.bot.RecheckWatch.print_msg', + self.fake_print)) + self.useFixture(fixtures.MonkeyPatch( + 'elastic_recheck.bot.RecheckWatch.display', + self.fake_display)) + with mock.patch.object( + elasticRecheck.Stream, '_does_es_have_data') as mock_data: + mock_data.return_value = True + stream = elasticRecheck.Stream("", "", "") + event = stream.get_failed_tempest() + self.assertIsNone(event.bug_urls_map()) + # Add bugs + for job in event.failed_jobs: + if job.name == 'gate-keystone-python26': + job.bugs = ['123456'] + self.assertTrue(self.recheck_watch.display('channel', event)) + self.recheck_watch.error_found('channel', event)