Merge ~juliank/britney/+git/britney2-ubuntu:lp1688516 into ~ubuntu-release/britney/+git/britney2-ubuntu:master

Proposed by Julian Andres Klode
Status: Merged
Merge reported by: Julian Andres Klode
Merged at revision: 04c3cdb382c2a94382187fd76139d88dec3c5f8d
Proposed branch: ~juliank/britney/+git/britney2-ubuntu:lp1688516
Merge into: ~ubuntu-release/britney/+git/britney2-ubuntu:master
Diff against target: 229 lines (+162/-6)
3 files modified
britney2/policies/autopkgtest.py (+31/-4)
britney2/utils.py (+0/-2)
tests/test_autopkgtest.py (+131/-0)
Reviewer Review Type Date Requested Status
Iain Lane Needs Fixing
Review via email: mp+344902@code.launchpad.net

Commit message

needs some name bikeshedding

To post a comment you must log in.
Revision history for this message
Julian Andres Klode (juliank) wrote :

Might want to do something other than the revert of the excuses removal.

Revision history for this message
Julian Andres Klode (juliank) wrote :

We can make ALWAYSFAIL an IGNORE-FAIL in such a case, or add a new state?

Revision history for this message
Iain Lane (laney) wrote :

Basic approach is good, thanks!

As discussed, we should handle the multiple hint case differently: find the highest version that is at most the current trigger and look at that one. If there are multiple versions in play - a version in testing and a version (possibly this is one of many uploads!) in unstable, we want to be able to hint them independently.

I think an 'excuse' should be added so that it's clear on update_excuses.html that a test is only ALWAYSFAIL because it's been hinted - for force-skiptest we say "Should wait for tests relating to %s %s, but forced by %s". Our string could be very similar.

Does /arch work and can we have a test for that?

Revision history for this message
Iain Lane (laney) :
review: Needs Fixing
Revision history for this message
Julian Andres Klode (juliank) wrote :

We don't correctly handle multiple hints, need to fix that.

Revision history for this message
Paul Gevers (paul-climbing) wrote :

Are you aware of the changes I made in Debian to reset the base line?

In Debian I have a migration-reference/0 trigger that tests purely in testing. When there is a new result with this trigger, the baseline gets reset to that. Otherwise any pass in testing, except for the package itself when taken from unstable put the baseline to passing.

Revision history for this message
Iain Lane (laney) wrote :

Paul - I think you could use a hint like this to effect a 'reset the baseline to testing' check like you & Steve are proposing? I'm not sure that I've considered all the implications, but it sounds like you want consider that the baseline is always the version that's in testing? Maybe slightly modified to consider only the test runs where the triggering package/version is the one in testing.

@juliank - can you check https://code.launchpad.net/~laney/britney/+git/britney2-ubuntu/+ref/force-reset-test please? I bikeshedded the name, but more importantly made force-reset-test foo/N apply to all versions <= N and ALWAYSFAIL them too. Seems more intuitive, do you think?

Revision history for this message
Iain Lane (laney) wrote :

Any comments or should I just merge this?

Revision history for this message
Julian Andres Klode (juliank) wrote :

I must say that I prefer the Debian approach somewhat, as it solves two problems:
(a) Testing against the release pocket, and
(b) resetting the baseline
in one operation. That's somewhat easier than manually retrying it with a fake trigger like hello and then if that fails too force-reset-test it.

Revision history for this message
Iain Lane (laney) wrote :

1) Why a fake trigger rather than the package/version in release?

2) While systematically forcing to the version in release is one potential use of this, I think that is a *policy* question that is as yet undecided in Ubuntu. In the absence of such a policy, release team members can use this hint when they decide that a regression should not be treated as one - for example if there is a 'fluke' pass, which sometimes happens. In other words, I think the "Debian" approach is the answer to a different question that we're not asking here.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/britney2/policies/autopkgtest.py b/britney2/policies/autopkgtest.py
2index 806debd..fbf83f8 100644
3--- a/britney2/policies/autopkgtest.py
4+++ b/britney2/policies/autopkgtest.py
5@@ -102,6 +102,7 @@ class AutopkgtestPolicy(BasePolicy):
6
7 def register_hints(self, hint_parser):
8 hint_parser.register_hint_type('force-badtest', britney2.hints.split_into_one_hint_per_package)
9+ hint_parser.register_hint_type('force-badtest-until', britney2.hints.split_into_one_hint_per_package)
10 hint_parser.register_hint_type('force-skiptest', britney2.hints.split_into_one_hint_per_package)
11
12 def initialise(self, britney):
13@@ -658,12 +659,22 @@ class AutopkgtestPolicy(BasePolicy):
14 # save pending.json right away, so that we don't re-request if britney crashes
15 self.save_pending_json()
16
17- def check_ever_passed(self, src, arch):
18- '''Check if tests for src ever passed on arch'''
19+ def check_ever_passed_before(self, src, max_ver, arch, min_ver=None):
20+ '''Check if tests for src ever passed on arch for specified range
21+
22+ If min_ver is specified, it checks that all versions in
23+ [min_ver, max_ver) have passed; otherwise it checks that
24+ [min_ver, inf) have passed.'''
25
26 # FIXME: add caching
27 for srcmap in self.test_results.values():
28 try:
29+ too_high = apt_pkg.version_compare(srcmap[src][arch][1], max_ver) > 0
30+ too_low = apt_pkg.version_compare(srcmap[src][arch][1], min_ver) <= 0 if min_ver else False
31+
32+ if too_high or too_low:
33+ continue
34+
35 if srcmap[src][arch][0]:
36 return True
37 except KeyError:
38@@ -677,7 +688,8 @@ class AutopkgtestPolicy(BasePolicy):
39 EXCUSES_LABELS. log_url is None if the test is still running.
40 '''
41 # determine current test result status
42- ever_passed = self.check_ever_passed(src, arch)
43+ until = self.find_max_force_badtest_until(src, ver, arch)
44+ ever_passed = self.check_ever_passed_before(src, ver, arch, until)
45 url = None
46 try:
47 r = self.test_results[trigger][src][arch]
48@@ -724,6 +736,22 @@ class AutopkgtestPolicy(BasePolicy):
49
50 return (result, ver, url)
51
52+ def find_max_force_badtest_until(self, src, ver, arch):
53+ '''Find the maximum force-badtest-until hint before/including ver'''
54+ hints = self.britney.hints.search('force-badtest-until', package=src)
55+ found_ver = None
56+
57+ if hints:
58+ for hint in hints:
59+ for mi in hint.packages:
60+ if (mi.architecture in ['source', arch] and
61+ mi.version != 'all' and
62+ apt_pkg.version_compare(mi.version, ver) <= 0 and
63+ (found_ver is None or apt_pkg.version_compare(found_ver, mi.version) < 0)):
64+ found_ver = mi.version
65+
66+ return found_ver
67+
68 def has_force_badtest(self, src, ver, arch):
69 '''Check if src/ver/arch has a force-badtest hint'''
70
71@@ -736,4 +764,3 @@ class AutopkgtestPolicy(BasePolicy):
72 return True
73
74 return False
75-
76diff --git a/britney2/utils.py b/britney2/utils.py
77index 837dad6..25223c8 100644
78--- a/britney2/utils.py
79+++ b/britney2/utils.py
80@@ -368,8 +368,6 @@ def write_excuses(excuselist, dest_file, output_format="yaml"):
81 ensuredir(os.path.dirname(dest_file))
82 with open(dest_file, 'w', encoding='utf-8') as f:
83 edatalist = [e.excusedata() for e in excuselist]
84- for e in edatalist:
85- del(e['excuses'])
86 excusesdata = {
87 'sources': edatalist,
88 'generated-date': datetime.utcnow(),
89diff --git a/tests/test_autopkgtest.py b/tests/test_autopkgtest.py
90index bc736ae..a780845 100755
91--- a/tests/test_autopkgtest.py
92+++ b/tests/test_autopkgtest.py
93@@ -1555,6 +1555,137 @@ class T(TestBase):
94 {'green': [('old-version', '1'), ('new-version', '2')]
95 })
96
97+ def test_hint_force_badtest_until_goodbad_alwaysfail(self):
98+ '''force-badtest-until hint marks as alwaysfail'''
99+
100+ self.swift.set_results({'autopkgtest-series': {
101+ 'series/amd64/l/lightgreen/20150101_100100@': (0, 'lightgreen 1', tr('lightgreen/1')),
102+ 'series/amd64/l/lightgreen/20150101_100101@': (4, 'lightgreen 2', tr('lightgreen/2')),
103+ }})
104+
105+ self.create_hint('pitti', 'force-badtest-until lightgreen/1')
106+
107+ self.do_test(
108+ [('lightgreen', {'Version': '2', 'Source': 'lightgreen', 'Depends': 'libc6'}, 'autopkgtest')],
109+ {'lightgreen': (True, {
110+ 'lightgreen/2': {'amd64': 'ALWAYSFAIL'},
111+ }),
112+ },
113+ {'lightgreen': [('old-version', '1'), ('new-version', '2')]
114+ })
115+
116+ def test_hint_force_badtest_until_goodbad_alwaysfail_arch(self):
117+ '''force-badtest-until hint marks as alwaysfail per arch'''
118+
119+ self.swift.set_results({'autopkgtest-series': {
120+ 'series/amd64/l/lightgreen/20150101_100100@': (0, 'lightgreen 1', tr('lightgreen/1')),
121+ 'series/amd64/l/lightgreen/20150101_100101@': (4, 'lightgreen 2', tr('lightgreen/2')),
122+ 'series/i386/l/lightgreen/20150101_100100@': (0, 'lightgreen 1', tr('lightgreen/1')),
123+ 'series/i386/l/lightgreen/20150101_100101@': (4, 'lightgreen 2', tr('lightgreen/2')),
124+ }})
125+
126+ self.create_hint('pitti', 'force-badtest-until lightgreen/1/amd64')
127+
128+ self.do_test(
129+ [('lightgreen', {'Version': '2', 'Source': 'lightgreen', 'Depends': 'libc6'}, 'autopkgtest')],
130+ {'lightgreen': (False, {
131+ 'lightgreen/2': {'amd64': 'ALWAYSFAIL', 'i386': 'REGRESSION'},
132+ }),
133+ },
134+ {'lightgreen': [('old-version', '1'), ('new-version', '2')]
135+ })
136+
137+ def test_hint_force_badtest_until_bad_good_pass(self):
138+ '''force-badtest-until hint followed by pass is pass'''
139+
140+ self.swift.set_results({'autopkgtest-series': {
141+ 'series/amd64/l/lightgreen/20150101_100100@': (4, 'lightgreen 1', tr('lightgreen/1')),
142+ 'series/amd64/l/lightgreen/20150102_100101@': (0, 'lightgreen 2', tr('lightgreen/2')),
143+ }})
144+
145+ self.create_hint('pitti', 'force-badtest-until lightgreen/1')
146+
147+ self.do_test(
148+ [('lightgreen', {'Version': '2', 'Source': 'lightgreen', 'Depends': 'libc6'}, 'autopkgtest')],
149+ {'lightgreen': (True, {
150+ 'lightgreen/2': {'amd64': 'PASS'},
151+ }),
152+ },
153+ {'lightgreen': [('old-version', '1'), ('new-version', '2')]
154+ })
155+
156+ def test_hint_force_badtest_until_bad_good_bad_regression(self):
157+ '''force-badtest-until hint followed by good, bad is regression'''
158+
159+ self.swift.set_results({'autopkgtest-series': {
160+ 'series/amd64/l/lightgreen/20150101_100100@': (4, 'lightgreen 1', tr('lightgreen/1')),
161+ 'series/amd64/l/lightgreen/20150102_100101@': (0, 'lightgreen 2', tr('lightgreen/2')),
162+ 'series/amd64/l/lightgreen/20150103_100101@': (4, 'lightgreen 3', tr('lightgreen/3')),
163+ }})
164+
165+ self.create_hint('pitti', 'force-badtest-until lightgreen/1')
166+
167+ self.do_test(
168+ [('lightgreen', {'Version': '3', 'Source': 'lightgreen', 'Depends': 'libc6'}, 'autopkgtest')],
169+ {'lightgreen': (False, {
170+ 'lightgreen/3': {'amd64': 'REGRESSION'},
171+ }),
172+ },
173+ {'lightgreen': [('old-version', '1'), ('new-version', '3')]
174+ })
175+
176+ def test_hint_force_badtest_until_multiple_hints(self):
177+ '''force-badtest-until multiple hints check ranges'''
178+
179+ self.swift.set_results({'autopkgtest-series': {
180+ 'series/amd64/l/lightgreen/20150100_100100@': (0, 'lightgreen 1', tr('lightgreen/1')),
181+ 'series/amd64/l/lightgreen/20150101_100100@': (4, 'lightgreen 1', tr('green/2')),
182+ 'series/amd64/l/lightgreen/20150102_100101@': (0, 'lightgreen 2', tr('lightgreen/2')),
183+ 'series/amd64/l/lightgreen/20150103_100101@': (4, 'lightgreen 3', tr('lightgreen/3')),
184+ }})
185+
186+
187+ self.do_test(
188+ [('libgreen1', {'Version': '2', 'Source': 'green', 'Depends': 'libc6'}, 'autopkgtest'),
189+ ('lightgreen', {'Version': '3', 'Source': 'lightgreen', 'Depends': 'libc6'}, 'autopkgtest')],
190+ {'green': (False, {
191+ 'lightgreen/1': {'amd64': 'REGRESSION'},
192+ }),
193+ },
194+ {'green': [('old-version', '1'), ('new-version', '2')],
195+ 'lightgreen': [('old-version', '1'), ('new-version', '3')],
196+ })
197+
198+ self.create_hint('pitti', 'force-badtest-until lightgreen/1')
199+ self.do_test(
200+ [],
201+ {'green': (True, {
202+ 'lightgreen/1': {'amd64': 'ALWAYSFAIL'},
203+ }),
204+ 'lightgreen': (False, {
205+ 'lightgreen/3': {'amd64': 'REGRESSION'},
206+ }),
207+
208+ },
209+ {'green': [('old-version', '1'), ('new-version', '2')],
210+ 'lightgreen': [('old-version', '1'), ('new-version', '3')],
211+ })
212+ self.create_hint('pitti', 'force-badtest-until lightgreen/3')
213+ self.do_test(
214+ [],
215+ {'green': (True, {
216+ 'lightgreen/1': {'amd64': 'ALWAYSFAIL'},
217+ }),
218+ 'lightgreen': (True, {
219+ 'lightgreen/3': {'amd64': 'ALWAYSFAIL'},
220+ }),
221+
222+ },
223+ {'green': [('old-version', '1'), ('new-version', '2')],
224+ 'lightgreen': [('old-version', '1'), ('new-version', '3')],
225+ })
226+
227+
228 def test_hint_force_badtest_multi_version(self):
229 '''force-badtest hint'''
230

Subscribers

People subscribed via source and target branches