From ca9987def8880dc42ca780f96e791f6b2943e07f Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Tue, 11 Aug 2015 08:01:04 +0200 Subject: [PATCH] Don't promote packages with unbuilt reverse dependencies If a reverse dependency D of a package P is not built yet, then D will be in "exclusions" as we can't sensibly run D's tests at that time. In that case, don't just ignore the missing test result but consider D's test as "in progress". Note that this might lead to stalling an innocent P if a broken (FTBFS) D gets uploaded at the same time. This can/should be handled by overrides if fixing D isn't appropriate, but this is better than allowing P to break D in that situation. --- autopkgtest.py | 16 +++++++-- tests/test_autopkgtest.py | 68 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/autopkgtest.py b/autopkgtest.py index e1bf838..b1b60fa 100644 --- a/autopkgtest.py +++ b/autopkgtest.py @@ -77,6 +77,7 @@ class AutoPackageTest(object): self.distribution = distribution self.series = series self.debug = debug + self.excludes = set() self.test_state_dir = os.path.join(britney.options.unstable, 'autopkgtest') # map of requested tests from request() @@ -395,12 +396,13 @@ class AutoPackageTest(object): def request(self, packages, excludes=None): if excludes is None: excludes = [] + self.excludes.update(excludes) self.log_verbose('Requested autopkgtests for %s, exclusions: %s' % (['%s/%s' % i for i in packages], str(excludes))) for src, ver in packages: for (testsrc, testver) in self.tests_for_source(src, ver): - if testsrc not in excludes: + if testsrc not in self.excludes: for arch in self.britney.options.adt_arches.split(): self.add_test_request(testsrc, testver, arch, src, ver) @@ -522,8 +524,16 @@ class AutoPackageTest(object): arch_status[arch] = 'RUNNING' passed = False except KeyError: - # neither done nor pending -> exclusion, or disabled - continue + # neither done nor pending; excluded? + if testsrc in self.excludes: + arch_status[arch] = 'RUNNING' + passed = False + continue + + # ignore if Swift results are disabled + if not hasattr(self.britney.options, 'adt_swift_url'): + continue + raise # disabled or ignored? if not arch_status: diff --git a/tests/test_autopkgtest.py b/tests/test_autopkgtest.py index 1ee49e6..79780cc 100644 --- a/tests/test_autopkgtest.py +++ b/tests/test_autopkgtest.py @@ -345,6 +345,74 @@ lightgreen 1 i386 green 2 # not expecting any failures to retrieve from swift self.assertNotIn('Failure', out, out) + def test_unbuilt(self): + '''Unbuilt package should not trigger tests or get considered''' + + self.data.add_src('green', True, {'Version': '2', 'Testsuite': 'autopkgtest'}) + self.do_test( + [], + NOT_CONSIDERED, + [r'\bgreen\b.*>1 to .*>2<', + r'missing build on.*amd64.*green, libgreen1'], + ['autopkgtest']) + + def test_rdepends_unbuilt(self): + '''Unbuilt reverse dependency''' + + # old lightgreen fails, thus new green should be held back + self.swift.set_results({'autopkgtest-series': { + 'series/i386/d/darkgreen/20150101_100000@': (0, 'darkgreen 1'), + 'series/amd64/d/darkgreen/20150101_100001@': (0, 'darkgreen 1'), + 'series/i386/l/lightgreen/20150101_100000@': (0, 'lightgreen 1'), + 'series/i386/l/lightgreen/20150101_100100@': (4, 'lightgreen 1'), + 'series/amd64/l/lightgreen/20150101_100000@': (0, 'lightgreen 1'), + 'series/amd64/l/lightgreen/20150101_100100@': (4, 'lightgreen 1'), + 'series/i386/g/green/20150101_020000@': (0, 'green 1'), + 'series/amd64/g/green/20150101_020000@': (0, 'green 1'), + 'series/i386/g/green/20150101_100200@': (0, 'green 2'), + 'series/amd64/g/green/20150101_100201@': (0, 'green 2'), + }}) + # run britney once to pick up previous results + self.do_test( + [('libgreen1', {'Version': '2', 'Source': 'green', 'Depends': 'libc6'}, 'autopkgtest')], + NOT_CONSIDERED) + os.unlink(self.fake_amqp) + + # add unbuilt lightgreen + self.data.add_src('lightgreen', True, {'Version': '2', 'Testsuite': 'autopkgtest'}) + self.do_test( + [], + NOT_CONSIDERED, + [r'\bgreen\b.*>1 to .*>2<', + r'\blightgreen\b.*>1 to .*>2<', + r'autopkgtest for green 2: .*amd64.*Pass.*i386.*Pass', + r'autopkgtest for darkgreen 1: .*amd64.*Pass.*i386.*Pass', + r'autopkgtest for lightgreen 2: .*amd64.*in progress.*i386.*in progress', + r'lightgreen has no up-to-date binaries on any arch'], + ['Valid candidate']) + + # lightgreen's tests should not be triggered yet while it is unbuilt + self.assertEqual(self.amqp_requests, set()) + + # now lightgreen gets built and a test result + self.swift.set_results({'autopkgtest-series': { + 'series/i386/l/lightgreen/20150101_100200@': (0, 'lightgreen 2'), + 'series/amd64/l/lightgreen/20150101_102000@': (0, 'lightgreen 2'), + }}) + self.data.remove_all(True) + self.do_test( + [('libgreen1', {'Version': '2', 'Source': 'green', 'Depends': 'libc6'}, 'autopkgtest'), + ('lightgreen', {'Version': '2'}, 'autopkgtest')], + VALID_CANDIDATE, + [r'\bgreen\b.*>1 to .*>2<', + r'\blightgreen\b.*>1 to .*>2<', + r'autopkgtest for green 2: .*amd64.*Pass.*i386.*Pass', + r'autopkgtest for darkgreen 1: .*amd64.*Pass.*i386.*Pass', + r'autopkgtest for lightgreen 2: .*amd64.*Pass.*i386.*Pass'], + ['Not considered']) + self.assertEqual(self.amqp_requests, + set(['debci-series-amd64:lightgreen', 'debci-series-i386:lightgreen'])) + def test_hint_force_badtest(self): '''force-badtest hint'''