diff --git a/src/tito/bugtracker.py b/src/tito/bugtracker.py new file mode 100644 index 0000000..e191155 --- /dev/null +++ b/src/tito/bugtracker.py @@ -0,0 +1,124 @@ +import os +import re +from bugzilla.rhbugzilla import RHBugzilla +from tito.common import debug, error_out +from tito.exception import TitoException +from tito.compat import xmlrpclib + + +class MissingBugzillaCredsException(TitoException): + pass + + +class BugzillaExtractor(object): + """ + Parses output of a dist-git commit diff looking for changelog + entries that look like they reference bugzilla commits. + + Optionally can check bugzilla for required flags on each bug. + """ + def __init__(self, diff_output, required_flags=None, + placeholder_bz=None): + + self.diff_output = diff_output + self.required_flags = required_flags + self.placeholder_bz = placeholder_bz + + # Tuples of bugzilla ID + commit message we extracted: + self.bzs = [] + + def extract(self): + + self.bzs = self._extract_bzs() + + if self.required_flags: + self._check_for_bugzilla_creds() + self.bzs = self._filter_bzs_with_flags() + + return self._format_lines() + + def _check_for_bugzilla_creds(self): + if not os.path.exists(os.path.expanduser("~/.bugzillarc")): + raise MissingBugzillaCredsException("Missing ~/.bugzillarc") + else: + debug("Found bugzilla credentials in ~/.bugzillarc") + + def _extract_bzs(self): + """ + Parses the output of CVS diff or a series of git commit log entries, + looking for new lines which look like a commit of the format: + + ######: Commit message + + Returns a list of lines of text similar to: + + Resolves: #XXXXXX - Commit message + + If the releaser specifies any required bugzilla flags we will + check each bug found and see if it has all required flags. If not + we skip it. If we end up with *no* bugs with the required flags + our build is likely to fail, so we look for a placeholder bugzilla + defined in relaser config and use that instead if possible, otherwise + error out. + + Returns a list of lines to write to the commit message as is. + """ + regex = re.compile(r"^- (\d*)\s?[:-]+\s?(.*)") + diff_regex = re.compile(r"^(\+- )+(\d*)\s?[:-]+\s?(.*)") + bzs = [] + for line in self.diff_output.split("\n"): + match = re.match(regex, line) + match2 = re.match(diff_regex, line) + if match: + bzs.append((match.group(1), match.group(2))) + elif match2: + bzs.append((match2.group(2), match2.group(3))) + return bzs + + def _format_lines(self): + output = [] + for bz in self.bzs: + output.append("Resolves: #%s - %s" % (bz[0], bz[1])) + if len(output) == 0 and self.required_flags: + # No bugzillas had required flags, use a placeholder if + # we have one, otherwise we have to error out. + if self.placeholder_bz: + print("No bugs with required flags were found, using placeholder: %s" % self.placeholder_bz) + output.append("Related: #%s" % self.placeholder_bz) + else: + error_out("No bugzillas found with required flags: %s" % + self.required_flags) + return output + + def _filter_bzs_with_flags(self): + print("Checking flags on bugs: %s" % self.bzs) + print(" required flags: %s" % self.required_flags) + + # TODO: Would be nice to load bugs in bulk here but for now we'll + # keep it simple. + filtered_bzs = [] + for bz_tuple in self.bzs: + bug_id = bz_tuple[0] + try: + bug = self._load_bug(bug_id) + except xmlrpclib.Fault: + print("WARNING: Bug %s does not seem to exist." % bug_id) + continue + debug("Bug %s has flags: %s" % (bug_id, bug.flags)) + flags_missing = False + for flag in self.required_flags: + if bug.get_flag_status(flag[0:-1]) != flag[-1]: + print("WARNING: Bug %s missing required flag: %s" % + (bug_id, flag)) + flags_missing = True + break + else: + debug("Bug %s has required flag: %s" % + (bug_id, flag)) + if not flags_missing: + filtered_bzs.append(bz_tuple) + return filtered_bzs + + def _load_bug(self, bug_id): + bugzilla = RHBugzilla(url='https://bugzilla.redhat.com/xmlrpc.cgi') + return bugzilla.getbug(bug_id, include_fields=['id', 'flags']) diff --git a/src/tito/common.py b/src/tito/common.py index a794101..2b942ef 100644 --- a/src/tito/common.py +++ b/src/tito/common.py @@ -30,10 +30,7 @@ import tempfile from blessed import Terminal -from bugzilla.rhbugzilla import RHBugzilla - -from tito.compat import xmlrpclib, getstatusoutput -from tito.exception import TitoException +from tito.compat import getstatusoutput from tito.exception import RunCommandException from tito.tar import TarFixer @@ -89,124 +86,6 @@ def extract_sources(spec_file_lines): return filenames -class MissingBugzillaCredsException(TitoException): - pass - - -class BugzillaExtractor(object): - """ - Parses output of a dist-git commit diff looking for changelog - entries that look like they reference bugzilla commits. - - Optionally can check bugzilla for required flags on each bug. - """ - def __init__(self, diff_output, required_flags=None, - placeholder_bz=None): - - self.diff_output = diff_output - self.required_flags = required_flags - self.placeholder_bz = placeholder_bz - - # Tuples of bugzilla ID + commit message we extracted: - self.bzs = [] - - def extract(self): - - self.bzs = self._extract_bzs() - - if self.required_flags: - self._check_for_bugzilla_creds() - self.bzs = self._filter_bzs_with_flags() - - return self._format_lines() - - def _check_for_bugzilla_creds(self): - if not os.path.exists(os.path.expanduser("~/.bugzillarc")): - raise MissingBugzillaCredsException("Missing ~/.bugzillarc") - else: - debug("Found bugzilla credentials in ~/.bugzillarc") - - def _extract_bzs(self): - """ - Parses the output of CVS diff or a series of git commit log entries, - looking for new lines which look like a commit of the format: - - ######: Commit message - - Returns a list of lines of text similar to: - - Resolves: #XXXXXX - Commit message - - If the releaser specifies any required bugzilla flags we will - check each bug found and see if it has all required flags. If not - we skip it. If we end up with *no* bugs with the required flags - our build is likely to fail, so we look for a placeholder bugzilla - defined in relaser config and use that instead if possible, otherwise - error out. - - Returns a list of lines to write to the commit message as is. - """ - regex = re.compile(r"^- (\d*)\s?[:-]+\s?(.*)") - diff_regex = re.compile(r"^(\+- )+(\d*)\s?[:-]+\s?(.*)") - bzs = [] - for line in self.diff_output.split("\n"): - match = re.match(regex, line) - match2 = re.match(diff_regex, line) - if match: - bzs.append((match.group(1), match.group(2))) - elif match2: - bzs.append((match2.group(2), match2.group(3))) - return bzs - - def _format_lines(self): - output = [] - for bz in self.bzs: - output.append("Resolves: #%s - %s" % (bz[0], bz[1])) - if len(output) == 0 and self.required_flags: - # No bugzillas had required flags, use a placeholder if - # we have one, otherwise we have to error out. - if self.placeholder_bz: - print("No bugs with required flags were found, using placeholder: %s" % self.placeholder_bz) - output.append("Related: #%s" % self.placeholder_bz) - else: - error_out("No bugzillas found with required flags: %s" % - self.required_flags) - return output - - def _filter_bzs_with_flags(self): - print("Checking flags on bugs: %s" % self.bzs) - print(" required flags: %s" % self.required_flags) - - # TODO: Would be nice to load bugs in bulk here but for now we'll - # keep it simple. - filtered_bzs = [] - for bz_tuple in self.bzs: - bug_id = bz_tuple[0] - try: - bug = self._load_bug(bug_id) - except xmlrpclib.Fault: - print("WARNING: Bug %s does not seem to exist." % bug_id) - continue - debug("Bug %s has flags: %s" % (bug_id, bug.flags)) - flags_missing = False - for flag in self.required_flags: - if bug.get_flag_status(flag[0:-1]) != flag[-1]: - print("WARNING: Bug %s missing required flag: %s" % - (bug_id, flag)) - flags_missing = True - break - else: - debug("Bug %s has required flag: %s" % - (bug_id, flag)) - if not flags_missing: - filtered_bzs.append(bz_tuple) - return filtered_bzs - - def _load_bug(self, bug_id): - bugzilla = RHBugzilla(url='https://bugzilla.redhat.com/xmlrpc.cgi') - return bugzilla.getbug(bug_id, include_fields=['id', 'flags']) - - def _out(msgs, prefix, color_func, stream=sys.stdout): if prefix is None: fmt = "%(msg)s" diff --git a/src/tito/release/distgit.py b/src/tito/release/distgit.py index 8c02705..6f24477 100644 --- a/src/tito/release/distgit.py +++ b/src/tito/release/distgit.py @@ -16,13 +16,14 @@ import subprocess import sys import tempfile -from tito.common import run_command, BugzillaExtractor, debug, extract_sources, \ - MissingBugzillaCredsException, error_out, chdir, warn_out, info_out, find_mead_chain_file +from tito.common import run_command, debug, extract_sources, \ + error_out, chdir, warn_out, info_out, find_mead_chain_file from tito.compat import getoutput, getstatusoutput, write from tito.release import Releaser from tito.release.main import PROTECTED_BUILD_SYS_FILES from tito.buildparser import BuildTargetParser from tito.exception import RunCommandException +from tito.bugtracker import BugzillaExtractor, MissingBugzillaCredsException import getpass from string import Template diff --git a/src/tito/release/obs.py b/src/tito/release/obs.py index 8be0cd5..6da3bba 100644 --- a/src/tito/release/obs.py +++ b/src/tito/release/obs.py @@ -16,9 +16,10 @@ import tempfile import subprocess import sys -from tito.common import run_command, debug, BugzillaExtractor +from tito.common import run_command, debug from tito.compat import getoutput, write, getstatusoutput from tito.release.distgit import FedoraGitReleaser +from tito.bugtracker import BugzillaExtractor class ObsReleaser(FedoraGitReleaser): diff --git a/test/unit/bugtracker_tests.py b/test/unit/bugtracker_tests.py new file mode 100644 index 0000000..23a73f7 --- /dev/null +++ b/test/unit/bugtracker_tests.py @@ -0,0 +1,216 @@ +import unittest +from tito.bugtracker import BugzillaExtractor +from mock import Mock, patch + + +class ExtractBugzillasTest(unittest.TestCase): + + def test_single_line(self): + commit_log = "- 123456: Did something interesting." + extractor = BugzillaExtractor(commit_log) + results = extractor.extract() + self.assertEquals(1, len(results)) + self.assertEquals("Resolves: #123456 - Did something interesting.", + results[0]) + + def test_single_with_dash(self): + commit_log = "- 123456 - Did something interesting." + extractor = BugzillaExtractor(commit_log) + results = extractor.extract() + self.assertEquals(1, len(results)) + self.assertEquals("Resolves: #123456 - Did something interesting.", + results[0]) + + def test_single_with_no_spaces(self): + commit_log = "- 123456-Did something interesting." + extractor = BugzillaExtractor(commit_log) + results = extractor.extract() + self.assertEquals(1, len(results)) + self.assertEquals("Resolves: #123456 - Did something interesting.", + results[0]) + + def test_diff_format(self): + commit_log = "+- 123456: Did something interesting." + extractor = BugzillaExtractor(commit_log) + results = extractor.extract() + self.assertEquals(1, len(results)) + self.assertEquals("Resolves: #123456 - Did something interesting.", + results[0]) + + def test_single_line_no_bz(self): + commit_log = "- Did something interesting." + extractor = BugzillaExtractor(commit_log) + results = extractor.extract() + self.assertEquals(0, len(results)) + + def test_multi_line(self): + commit_log = "- 123456: Did something interesting.\n- Another commit.\n" \ + "- 456789: A third commit." + extractor = BugzillaExtractor(commit_log) + results = extractor.extract() + self.assertEquals(2, len(results)) + self.assertEquals("Resolves: #123456 - Did something interesting.", + results[0]) + self.assertEquals("Resolves: #456789 - A third commit.", + results[1]) + + def test_single_required_flag_found(self): + + extractor = BugzillaExtractor("", required_flags=[ + 'myos-1.0+', 'pm_ack+']) + bug1 = ('123456', 'Did something interesting.') + extractor._extract_bzs = Mock(return_value=[ + bug1]) + extractor._check_for_bugzilla_creds = Mock() + + extractor._load_bug = Mock( + return_value=MockBug(bug1[0], ['myos-1.0+', 'pm_ack+'])) + + results = extractor.extract() + + self.assertEquals(1, len(extractor.bzs)) + self.assertEquals(bug1[0], extractor.bzs[0][0]) + self.assertEquals(bug1[1], extractor.bzs[0][1]) + + self.assertEquals(1, len(results)) + self.assertEquals("Resolves: #123456 - Did something interesting.", + results[0]) + + def test_required_flags_found(self): + + extractor = BugzillaExtractor("", required_flags=[ + 'myos-1.0+', 'pm_ack+']) + bug1 = ('123456', 'Did something interesting.') + bug2 = ('444555', 'Something else.') + bug3 = ('987654', 'Such amaze!') + extractor._extract_bzs = Mock(return_value=[ + bug1, bug2, bug3]) + extractor._check_for_bugzilla_creds = Mock() + + bug_mocks = [ + MockBug(bug1[0], ['myos-1.0+', 'pm_ack+']), + MockBug(bug2[0], ['myos-2.0?', 'pm_ack?']), + MockBug(bug3[0], ['myos-1.0+', 'pm_ack+'])] + + def next_bug(*args): + return bug_mocks.pop(0) + + extractor._load_bug = Mock(side_effect=next_bug) + + results = extractor.extract() + + self.assertEquals(2, len(extractor.bzs)) + self.assertEquals(bug1[0], extractor.bzs[0][0]) + self.assertEquals(bug1[1], extractor.bzs[0][1]) + self.assertEquals(bug3[0], extractor.bzs[1][0]) + self.assertEquals(bug3[1], extractor.bzs[1][1]) + + self.assertEquals(2, len(results)) + self.assertEquals("Resolves: #123456 - Did something interesting.", + results[0]) + self.assertEquals("Resolves: #987654 - Such amaze!", + results[1]) + + @patch("tito.bugtracker.error_out") + def test_required_flags_missing(self, mock_error): + required_flags = ['myos-2.0+'] + extractor = BugzillaExtractor("", required_flags) + bug1 = ('123456', 'Did something interesting.') + bug2 = ('444555', 'Something else.') + bug3 = ('987654', 'Such amaze!') + extractor._extract_bzs = Mock(return_value=[ + bug1, bug2, bug3]) + extractor._check_for_bugzilla_creds = Mock() + + bug_mocks = [ + MockBug(bug1[0], ['myos-1.0+', 'pm_ack+']), + MockBug(bug2[0], ['myos-2.0?', 'pm_ack?']), + MockBug(bug3[0], ['myos-1.0+', 'pm_ack+'])] + + def next_bug(*args): + return bug_mocks.pop(0) + + extractor._load_bug = Mock(side_effect=next_bug) + + results = extractor.extract() + + self.assertEquals(0, len(extractor.bzs)) + self.assertEquals(0, len(results)) + mock_error.assert_called_once_with("No bugzillas found with required flags: %s" % required_flags) + + def test_required_flags_missing_with_placeholder(self): + + extractor = BugzillaExtractor("", required_flags=[ + 'myos-2.0+'], placeholder_bz="54321") + bug1 = ('123456', 'Did something interesting.') + extractor._extract_bzs = Mock(return_value=[ + bug1]) + extractor._check_for_bugzilla_creds = Mock() + + extractor._load_bug = Mock( + return_value=MockBug(bug1[0], ['myos-1.0+', 'pm_ack+'])) + + results = extractor.extract() + + self.assertEquals(0, len(extractor.bzs)) + + self.assertEquals(1, len(results)) + self.assertEquals("Related: #54321", results[0]) + + def test_same_id_multiple_times(self): + + extractor = BugzillaExtractor("", required_flags=[ + 'myos-1.0+', 'pm_ack+']) + bug1 = ('123456', 'Did something interesting.') + bug3 = ('123456', 'Oops, lets try again.') + extractor._extract_bzs = Mock(return_value=[ + bug1, bug3]) + extractor._check_for_bugzilla_creds = Mock() + + extractor._load_bug = Mock( + return_value=MockBug(bug1[0], ['myos-1.0+', 'pm_ack+'])) + + results = extractor.extract() + + self.assertEquals(2, len(extractor.bzs)) + self.assertEquals(bug1[0], extractor.bzs[0][0]) + self.assertEquals(bug1[1], extractor.bzs[0][1]) + self.assertEquals(bug3[0], extractor.bzs[1][0]) + self.assertEquals(bug3[1], extractor.bzs[1][1]) + + self.assertEquals(2, len(results)) + self.assertEquals("Resolves: #123456 - Did something interesting.", + results[0]) + self.assertEquals("Resolves: #123456 - Oops, lets try again.", + results[1]) + + @patch("tito.bugtracker.error_out") + def test_bug_doesnt_exist(self, mock_error): + required_flags = ['myos-1.0+', 'pm_ack+'] + extractor = BugzillaExtractor("", required_flags) + bug1 = ('123456', 'Did something interesting.') + extractor._extract_bzs = Mock(return_value=[ + bug1]) + extractor._check_for_bugzilla_creds = Mock() + + from tito.compat import xmlrpclib + extractor._load_bug = Mock(side_effect=xmlrpclib.Fault("", "")) + + results = extractor.extract() + + self.assertEquals(0, len(extractor.bzs)) + self.assertEquals(0, len(results)) + mock_error.assert_called_once_with("No bugzillas found with required flags: %s" % required_flags) + + +class MockBug(object): + def __init__(self, bug_id, flags): + self.flags = {} + for flag in flags: + self.flags[flag[0:-1]] = flag[-1] + + def get_flag_status(self, flag): + if flag in self.flags: + return self.flags[flag] + else: + return None diff --git a/test/unit/common_tests.py b/test/unit/common_tests.py index d048c50..5407c96 100644 --- a/test/unit/common_tests.py +++ b/test/unit/common_tests.py @@ -16,7 +16,7 @@ from tito.common import (replace_version, find_spec_like_file, increase_version, search_for, compare_version, run_command_print, find_wrote_in_rpmbuild_output, render_cheetah, increase_zstream, reset_release, find_file_with_extension, - normalize_class_name, extract_sha1, BugzillaExtractor, DEFAULT_BUILD_DIR, munge_specfile, + normalize_class_name, extract_sha1, DEFAULT_BUILD_DIR, munge_specfile, munge_setup_macro, get_project_name, _out) @@ -496,219 +496,6 @@ class VersionMathTest(unittest.TestCase): self.assertEquals(expected, reset_release(line)) -class ExtractBugzillasTest(unittest.TestCase): - - def test_single_line(self): - commit_log = "- 123456: Did something interesting." - extractor = BugzillaExtractor(commit_log) - results = extractor.extract() - self.assertEquals(1, len(results)) - self.assertEquals("Resolves: #123456 - Did something interesting.", - results[0]) - - def test_single_with_dash(self): - commit_log = "- 123456 - Did something interesting." - extractor = BugzillaExtractor(commit_log) - results = extractor.extract() - self.assertEquals(1, len(results)) - self.assertEquals("Resolves: #123456 - Did something interesting.", - results[0]) - - def test_single_with_no_spaces(self): - commit_log = "- 123456-Did something interesting." - extractor = BugzillaExtractor(commit_log) - results = extractor.extract() - self.assertEquals(1, len(results)) - self.assertEquals("Resolves: #123456 - Did something interesting.", - results[0]) - - def test_diff_format(self): - commit_log = "+- 123456: Did something interesting." - extractor = BugzillaExtractor(commit_log) - results = extractor.extract() - self.assertEquals(1, len(results)) - self.assertEquals("Resolves: #123456 - Did something interesting.", - results[0]) - - def test_single_line_no_bz(self): - commit_log = "- Did something interesting." - extractor = BugzillaExtractor(commit_log) - results = extractor.extract() - self.assertEquals(0, len(results)) - - def test_multi_line(self): - commit_log = "- 123456: Did something interesting.\n- Another commit.\n" \ - "- 456789: A third commit." - extractor = BugzillaExtractor(commit_log) - results = extractor.extract() - self.assertEquals(2, len(results)) - self.assertEquals("Resolves: #123456 - Did something interesting.", - results[0]) - self.assertEquals("Resolves: #456789 - A third commit.", - results[1]) - - def test_single_required_flag_found(self): - - extractor = BugzillaExtractor("", required_flags=[ - 'myos-1.0+', 'pm_ack+']) - bug1 = ('123456', 'Did something interesting.') - extractor._extract_bzs = Mock(return_value=[ - bug1]) - extractor._check_for_bugzilla_creds = Mock() - - extractor._load_bug = Mock( - return_value=MockBug(bug1[0], ['myos-1.0+', 'pm_ack+'])) - - results = extractor.extract() - - self.assertEquals(1, len(extractor.bzs)) - self.assertEquals(bug1[0], extractor.bzs[0][0]) - self.assertEquals(bug1[1], extractor.bzs[0][1]) - - self.assertEquals(1, len(results)) - self.assertEquals("Resolves: #123456 - Did something interesting.", - results[0]) - - def test_required_flags_found(self): - - extractor = BugzillaExtractor("", required_flags=[ - 'myos-1.0+', 'pm_ack+']) - bug1 = ('123456', 'Did something interesting.') - bug2 = ('444555', 'Something else.') - bug3 = ('987654', 'Such amaze!') - extractor._extract_bzs = Mock(return_value=[ - bug1, bug2, bug3]) - extractor._check_for_bugzilla_creds = Mock() - - bug_mocks = [ - MockBug(bug1[0], ['myos-1.0+', 'pm_ack+']), - MockBug(bug2[0], ['myos-2.0?', 'pm_ack?']), - MockBug(bug3[0], ['myos-1.0+', 'pm_ack+'])] - - def next_bug(*args): - return bug_mocks.pop(0) - - extractor._load_bug = Mock(side_effect=next_bug) - - results = extractor.extract() - - self.assertEquals(2, len(extractor.bzs)) - self.assertEquals(bug1[0], extractor.bzs[0][0]) - self.assertEquals(bug1[1], extractor.bzs[0][1]) - self.assertEquals(bug3[0], extractor.bzs[1][0]) - self.assertEquals(bug3[1], extractor.bzs[1][1]) - - self.assertEquals(2, len(results)) - self.assertEquals("Resolves: #123456 - Did something interesting.", - results[0]) - self.assertEquals("Resolves: #987654 - Such amaze!", - results[1]) - - @patch("tito.common.error_out") - def test_required_flags_missing(self, mock_error): - required_flags = ['myos-2.0+'] - extractor = BugzillaExtractor("", required_flags) - bug1 = ('123456', 'Did something interesting.') - bug2 = ('444555', 'Something else.') - bug3 = ('987654', 'Such amaze!') - extractor._extract_bzs = Mock(return_value=[ - bug1, bug2, bug3]) - extractor._check_for_bugzilla_creds = Mock() - - bug_mocks = [ - MockBug(bug1[0], ['myos-1.0+', 'pm_ack+']), - MockBug(bug2[0], ['myos-2.0?', 'pm_ack?']), - MockBug(bug3[0], ['myos-1.0+', 'pm_ack+'])] - - def next_bug(*args): - return bug_mocks.pop(0) - - extractor._load_bug = Mock(side_effect=next_bug) - - results = extractor.extract() - - self.assertEquals(0, len(extractor.bzs)) - self.assertEquals(0, len(results)) - mock_error.assert_called_once_with("No bugzillas found with required flags: %s" % required_flags) - - def test_required_flags_missing_with_placeholder(self): - - extractor = BugzillaExtractor("", required_flags=[ - 'myos-2.0+'], placeholder_bz="54321") - bug1 = ('123456', 'Did something interesting.') - extractor._extract_bzs = Mock(return_value=[ - bug1]) - extractor._check_for_bugzilla_creds = Mock() - - extractor._load_bug = Mock( - return_value=MockBug(bug1[0], ['myos-1.0+', 'pm_ack+'])) - - results = extractor.extract() - - self.assertEquals(0, len(extractor.bzs)) - - self.assertEquals(1, len(results)) - self.assertEquals("Related: #54321", results[0]) - - def test_same_id_multiple_times(self): - - extractor = BugzillaExtractor("", required_flags=[ - 'myos-1.0+', 'pm_ack+']) - bug1 = ('123456', 'Did something interesting.') - bug3 = ('123456', 'Oops, lets try again.') - extractor._extract_bzs = Mock(return_value=[ - bug1, bug3]) - extractor._check_for_bugzilla_creds = Mock() - - extractor._load_bug = Mock( - return_value=MockBug(bug1[0], ['myos-1.0+', 'pm_ack+'])) - - results = extractor.extract() - - self.assertEquals(2, len(extractor.bzs)) - self.assertEquals(bug1[0], extractor.bzs[0][0]) - self.assertEquals(bug1[1], extractor.bzs[0][1]) - self.assertEquals(bug3[0], extractor.bzs[1][0]) - self.assertEquals(bug3[1], extractor.bzs[1][1]) - - self.assertEquals(2, len(results)) - self.assertEquals("Resolves: #123456 - Did something interesting.", - results[0]) - self.assertEquals("Resolves: #123456 - Oops, lets try again.", - results[1]) - - @patch("tito.common.error_out") - def test_bug_doesnt_exist(self, mock_error): - required_flags = ['myos-1.0+', 'pm_ack+'] - extractor = BugzillaExtractor("", required_flags) - bug1 = ('123456', 'Did something interesting.') - extractor._extract_bzs = Mock(return_value=[ - bug1]) - extractor._check_for_bugzilla_creds = Mock() - - from tito.compat import xmlrpclib - extractor._load_bug = Mock(side_effect=xmlrpclib.Fault("", "")) - - results = extractor.extract() - - self.assertEquals(0, len(extractor.bzs)) - self.assertEquals(0, len(results)) - mock_error.assert_called_once_with("No bugzillas found with required flags: %s" % required_flags) - - -class MockBug(object): - def __init__(self, bug_id, flags): - self.flags = {} - for flag in flags: - self.flags[flag[0:-1]] = flag[-1] - - def get_flag_status(self, flag): - if flag in self.flags: - return self.flags[flag] - else: - return None - - class MungeSetupMacroTests(unittest.TestCase): SOURCE = "tito-git-3.20362dd"