Merge lp:~cprov/britney/test-refactoring into lp:~ubuntu-release/britney/britney2-ubuntu
- test-refactoring
- Merge into britney2-ubuntu
Proposed by
Celso Providelo
Status: | Merged |
---|---|
Merged at revision: | 430 |
Proposed branch: | lp:~cprov/britney/test-refactoring |
Merge into: | lp:~ubuntu-release/britney/britney2-ubuntu |
Diff against target: |
441 lines (+209/-183) 2 files modified
tests/__init__.py (+159/-0) tests/test_autopkgtest.py (+50/-183) |
To merge this branch: | bzr merge lp:~cprov/britney/test-refactoring |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Colin Watson (community) | Approve | ||
Ubuntu Release Team | Pending | ||
Review via email: mp+247319@code.launchpad.net |
Commit message
Basic testing refactoring before we can implement "boottest" support.
Description of the change
Basic testing refactoring before we can implement "boottest" support.
To post a comment you must log in.
- 431. By Celso Providelo
-
Reverting whitespace cleanup.
Revision history for this message
Colin Watson (cjwatson) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'tests/__init__.py' |
2 | --- tests/__init__.py 1970-01-01 00:00:00 +0000 |
3 | +++ tests/__init__.py 2015-01-22 17:16:43 +0000 |
4 | @@ -0,0 +1,159 @@ |
5 | +# (C) 2015 Canonical Ltd. |
6 | +# |
7 | +# This program is free software; you can redistribute it and/or modify |
8 | +# it under the terms of the GNU General Public License as published by |
9 | +# the Free Software Foundation; either version 2 of the License, or |
10 | +# (at your option) any later version. |
11 | + |
12 | +import os |
13 | +import shutil |
14 | +import subprocess |
15 | +import tempfile |
16 | +import unittest |
17 | + |
18 | + |
19 | +PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
20 | + |
21 | +architectures = ['amd64', 'arm64', 'armhf', 'i386', 'powerpc', 'ppc64el'] |
22 | + |
23 | + |
24 | +class TestData: |
25 | + |
26 | + def __init__(self): |
27 | + '''Construct local test package indexes. |
28 | + |
29 | + The archive is initially empty. You can create new packages with |
30 | + create_deb(). self.path contains the path of the archive, and |
31 | + self.apt_source provides an apt source "deb" line. |
32 | + |
33 | + It is kept in a temporary directory which gets removed when the Archive |
34 | + object gets deleted. |
35 | + ''' |
36 | + self.path = tempfile.mkdtemp(prefix='testarchive.') |
37 | + self.apt_source = 'deb file://%s /' % self.path |
38 | + self.series = 'series' |
39 | + self.dirs = {False: os.path.join(self.path, 'data', self.series), |
40 | + True: os.path.join( |
41 | + self.path, 'data', '%s-proposed' % self.series)} |
42 | + os.makedirs(self.dirs[False]) |
43 | + os.mkdir(self.dirs[True]) |
44 | + self.added_sources = {False: set(), True: set()} |
45 | + self.added_binaries = {False: set(), True: set()} |
46 | + |
47 | + # pre-create all files for all architectures |
48 | + for arch in architectures: |
49 | + for dir in self.dirs.values(): |
50 | + with open(os.path.join(dir, 'Packages_' + arch), 'w'): |
51 | + pass |
52 | + for dir in self.dirs.values(): |
53 | + for fname in ['Dates', 'Blocks']: |
54 | + with open(os.path.join(dir, fname), 'w'): |
55 | + pass |
56 | + for dname in ['Hints']: |
57 | + os.mkdir(os.path.join(dir, dname)) |
58 | + |
59 | + os.mkdir(os.path.join(self.path, 'output')) |
60 | + |
61 | + # create temporary home dir for proposed-migration autopktest status |
62 | + self.home = os.path.join(self.path, 'home') |
63 | + os.environ['HOME'] = self.home |
64 | + os.makedirs(os.path.join(self.home, 'proposed-migration', |
65 | + 'autopkgtest', 'work')) |
66 | + |
67 | + def __del__(self): |
68 | + shutil.rmtree(self.path) |
69 | + |
70 | + def add(self, name, unstable, fields={}, add_src=True): |
71 | + '''Add a binary package to the index file. |
72 | + |
73 | + You need to specify at least the package name and in which list to put |
74 | + it (unstable==True for unstable/proposed, or False for |
75 | + testing/release). fields specifies all additional entries, e. g. |
76 | + {'Depends': 'foo, bar', 'Conflicts: baz'}. There are defaults for most |
77 | + fields. |
78 | + |
79 | + Unless add_src is set to False, this will also automatically create a |
80 | + source record, based on fields['Source'] and name. |
81 | + ''' |
82 | + assert (name not in self.added_binaries[unstable]) |
83 | + self.added_binaries[unstable].add(name) |
84 | + |
85 | + fields.setdefault('Architecture', architectures[0]) |
86 | + fields.setdefault('Version', '1') |
87 | + fields.setdefault('Priority', 'optional') |
88 | + fields.setdefault('Section', 'devel') |
89 | + fields.setdefault('Description', 'test pkg') |
90 | + if fields['Architecture'] == 'all': |
91 | + for a in architectures: |
92 | + self._append(name, unstable, 'Packages_' + a, fields) |
93 | + else: |
94 | + self._append(name, unstable, 'Packages_' + fields['Architecture'], |
95 | + fields) |
96 | + |
97 | + if add_src: |
98 | + src = fields.get('Source', name) |
99 | + if src not in self.added_sources[unstable]: |
100 | + self.add_src(src, unstable, {'Version': fields['Version'], |
101 | + 'Section': fields['Section']}) |
102 | + |
103 | + def add_src(self, name, unstable, fields={}): |
104 | + '''Add a source package to the index file. |
105 | + |
106 | + You need to specify at least the package name and in which list to put |
107 | + it (unstable==True for unstable/proposed, or False for |
108 | + testing/release). fields specifies all additional entries, which can be |
109 | + Version (default: 1), Section (default: devel), and Extra-Source-Only. |
110 | + ''' |
111 | + assert (name not in self.added_sources[unstable]) |
112 | + self.added_sources[unstable].add(name) |
113 | + |
114 | + fields.setdefault('Version', '1') |
115 | + fields.setdefault('Section', 'devel') |
116 | + self._append(name, unstable, 'Sources', fields) |
117 | + |
118 | + def _append(self, name, unstable, file_name, fields): |
119 | + with open(os.path.join(self.dirs[unstable], file_name), 'a') as f: |
120 | + f.write('''Package: %s |
121 | +Maintainer: Joe <joe@example.com> |
122 | +''' % name) |
123 | + |
124 | + for k, v in fields.items(): |
125 | + f.write('%s: %s\n' % (k, v)) |
126 | + f.write('\n') |
127 | + |
128 | + |
129 | +class TestBase(unittest.TestCase): |
130 | + |
131 | + def setUp(self): |
132 | + super(TestBase, self).setUp() |
133 | + self.data = TestData() |
134 | + self.britney = os.path.join(PROJECT_DIR, 'britney.py') |
135 | + self.britney_conf = os.path.join(PROJECT_DIR, 'britney.conf') |
136 | + assert os.path.exists(self.britney) |
137 | + assert os.path.exists(self.britney_conf) |
138 | + |
139 | + def tearDown(self): |
140 | + del self.data |
141 | + |
142 | + def run_britney(self, args=[]): |
143 | + '''Run britney. |
144 | + |
145 | + Assert that it succeeds and does not produce anything on stderr. |
146 | + Return (excuses.html, britney_out). |
147 | + ''' |
148 | + britney = subprocess.Popen([self.britney, '-v', '-c', self.britney_conf, |
149 | + '--distribution=ubuntu', |
150 | + '--series=%s' % self.data.series], |
151 | + stdout=subprocess.PIPE, |
152 | + stderr=subprocess.PIPE, |
153 | + cwd=self.data.path, |
154 | + universal_newlines=True) |
155 | + (out, err) = britney.communicate() |
156 | + self.assertEqual(britney.returncode, 0, out + err) |
157 | + self.assertEqual(err, '') |
158 | + |
159 | + with open(os.path.join(self.data.path, 'output', self.data.series, |
160 | + 'excuses.html')) as f: |
161 | + excuses = f.read() |
162 | + |
163 | + return (excuses, out) |
164 | |
165 | === modified file 'tests/test_autopkgtest.py' |
166 | --- tests/test_autopkgtest.py 2014-12-10 10:42:27 +0000 |
167 | +++ tests/test_autopkgtest.py 2015-01-22 17:16:43 +0000 |
168 | @@ -6,133 +6,40 @@ |
169 | # the Free Software Foundation; either version 2 of the License, or |
170 | # (at your option) any later version. |
171 | |
172 | -import tempfile |
173 | -import shutil |
174 | +import apt_pkg |
175 | +import operator |
176 | import os |
177 | import sys |
178 | import subprocess |
179 | import unittest |
180 | -import apt_pkg |
181 | -import operator |
182 | - |
183 | -apt_pkg.init() |
184 | -architectures = ['amd64', 'arm64', 'armhf', 'i386', 'powerpc', 'ppc64el'] |
185 | - |
186 | -my_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
187 | + |
188 | +PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
189 | +sys.path.insert(0, PROJECT_DIR) |
190 | + |
191 | +from autopkgtest import ADT_EXCUSES_LABELS |
192 | +from tests import TestBase |
193 | |
194 | NOT_CONSIDERED = False |
195 | VALID_CANDIDATE = True |
196 | |
197 | -sys.path.insert(0, my_dir) |
198 | -from autopkgtest import ADT_EXCUSES_LABELS |
199 | - |
200 | - |
201 | -class TestData: |
202 | - def __init__(self): |
203 | - '''Construct local test package indexes. |
204 | - |
205 | - The archive is initially empty. You can create new packages with |
206 | - create_deb(). self.path contains the path of the archive, and |
207 | - self.apt_source provides an apt source "deb" line. |
208 | - |
209 | - It is kept in a temporary directory which gets removed when the Archive |
210 | - object gets deleted. |
211 | - ''' |
212 | - self.path = tempfile.mkdtemp(prefix='testarchive.') |
213 | - self.apt_source = 'deb file://%s /' % self.path |
214 | - self.series = 'series' |
215 | - self.dirs = {False: os.path.join(self.path, 'data', self.series), |
216 | - True: os.path.join(self.path, 'data', '%s-proposed' % self.series)} |
217 | - os.makedirs(self.dirs[False]) |
218 | - os.mkdir(self.dirs[True]) |
219 | - self.added_sources = {False: set(), True: set()} |
220 | - self.added_binaries = {False: set(), True: set()} |
221 | - |
222 | - # pre-create all files for all architectures |
223 | - for arch in architectures: |
224 | - for dir in self.dirs.values(): |
225 | - with open(os.path.join(dir, 'Packages_' + arch), 'w'): |
226 | - pass |
227 | - for dir in self.dirs.values(): |
228 | - for fname in ['Dates', 'Blocks']: |
229 | - with open(os.path.join(dir, fname), 'w'): |
230 | - pass |
231 | - for dname in ['Hints']: |
232 | - os.mkdir(os.path.join(dir, dname)) |
233 | - |
234 | - os.mkdir(os.path.join(self.path, 'output')) |
235 | - |
236 | - # create temporary home dir for proposed-migration autopktest status |
237 | - self.home = os.path.join(self.path, 'home') |
238 | - os.environ['HOME'] = self.home |
239 | - os.makedirs(os.path.join(self.home, 'proposed-migration', |
240 | - 'autopkgtest', 'work')) |
241 | - |
242 | - def __del__(self): |
243 | - shutil.rmtree(self.path) |
244 | - |
245 | - def add(self, name, unstable, fields={}, add_src=True): |
246 | - '''Add a binary package to the index file. |
247 | - |
248 | - You need to specify at least the package name and in which list to put |
249 | - it (unstable==True for unstable/proposed, or False for |
250 | - testing/release). fields specifies all additional entries, e. g. |
251 | - {'Depends': 'foo, bar', 'Conflicts: baz'}. There are defaults for most |
252 | - fields. |
253 | - |
254 | - Unless add_src is set to False, this will also automatically create a |
255 | - source record, based on fields['Source'] and name. |
256 | - ''' |
257 | - assert (name not in self.added_binaries[unstable]) |
258 | - self.added_binaries[unstable].add(name) |
259 | - |
260 | - fields.setdefault('Architecture', architectures[0]) |
261 | - fields.setdefault('Version', '1') |
262 | - fields.setdefault('Priority', 'optional') |
263 | - fields.setdefault('Section', 'devel') |
264 | - fields.setdefault('Description', 'test pkg') |
265 | - if fields['Architecture'] == 'all': |
266 | - for a in architectures: |
267 | - self._append(name, unstable, 'Packages_' + a, fields) |
268 | - else: |
269 | - self._append(name, unstable, 'Packages_' + fields['Architecture'], |
270 | - fields) |
271 | - |
272 | - if add_src: |
273 | - src = fields.get('Source', name) |
274 | - if src not in self.added_sources[unstable]: |
275 | - self.add_src(src, unstable, {'Version': fields['Version'], |
276 | - 'Section': fields['Section']}) |
277 | - |
278 | - def add_src(self, name, unstable, fields={}): |
279 | - '''Add a source package to the index file. |
280 | - |
281 | - You need to specify at least the package name and in which list to put |
282 | - it (unstable==True for unstable/proposed, or False for |
283 | - testing/release). fields specifies all additional entries, which can be |
284 | - Version (default: 1), Section (default: devel), and Extra-Source-Only. |
285 | - ''' |
286 | - assert (name not in self.added_sources[unstable]) |
287 | - self.added_sources[unstable].add(name) |
288 | - |
289 | - fields.setdefault('Version', '1') |
290 | - fields.setdefault('Section', 'devel') |
291 | - self._append(name, unstable, 'Sources', fields) |
292 | - |
293 | - def _append(self, name, unstable, file_name, fields): |
294 | - with open(os.path.join(self.dirs[unstable], file_name), 'a') as f: |
295 | - f.write('''Package: %s |
296 | -Maintainer: Joe <joe@example.com> |
297 | -''' % name) |
298 | - |
299 | - for k, v in fields.items(): |
300 | - f.write('%s: %s\n' % (k, v)) |
301 | - f.write('\n') |
302 | - |
303 | - |
304 | -class Test(unittest.TestCase): |
305 | + |
306 | +apt_pkg.init() |
307 | + |
308 | + |
309 | +class TestAutoPkgTest(TestBase): |
310 | + |
311 | def setUp(self): |
312 | - self.data = TestData() |
313 | + super(TestAutoPkgTest, self).setUp() |
314 | + |
315 | + # fake adt-britney script |
316 | + self.adt_britney = os.path.join( |
317 | + self.data.home, 'auto-package-testing', 'jenkins', 'adt-britney') |
318 | + os.makedirs(os.path.dirname(self.adt_britney)) |
319 | + |
320 | + with open(self.adt_britney, 'w') as f: |
321 | + f.write('''#!/bin/sh -e |
322 | +echo "$@" >> /%s/adt-britney.log ''' % self.data.path) |
323 | + os.chmod(self.adt_britney, 0o755) |
324 | |
325 | # add a bunch of packages to testing to avoid repetition |
326 | self.data.add('libc6', False) |
327 | @@ -146,24 +53,6 @@ |
328 | 'Conflicts': 'green'}) |
329 | self.data.add('justdata', False, {'Architecture': 'all'}) |
330 | |
331 | - self.britney = os.path.join(my_dir, 'britney.py') |
332 | - self.britney_conf = os.path.join(my_dir, 'britney.conf') |
333 | - assert os.path.exists(self.britney) |
334 | - assert os.path.exists(self.britney_conf) |
335 | - |
336 | - # fake adt-britney script |
337 | - self.adt_britney = os.path.join(self.data.home, 'auto-package-testing', |
338 | - 'jenkins', 'adt-britney') |
339 | - os.makedirs(os.path.dirname(self.adt_britney)) |
340 | - |
341 | - with open(self.adt_britney, 'w') as f: |
342 | - f.write('''#!/bin/sh -e |
343 | -echo "$@" >> /%s/adt-britney.log ''' % self.data.path) |
344 | - os.chmod(self.adt_britney, 0o755) |
345 | - |
346 | - def tearDown(self): |
347 | - del self.data |
348 | - |
349 | def __merge_records(self, results, history=""): |
350 | '''Merges a list of results with records in history. |
351 | |
352 | @@ -235,28 +124,29 @@ |
353 | 'rq': request, |
354 | 'res': self.__merge_records(request, history)}) |
355 | |
356 | - def run_britney(self, args=[]): |
357 | - '''Run britney. |
358 | - |
359 | - Assert that it succeeds and does not produce anything on stderr. |
360 | - Return (excuses.html, britney_out). |
361 | - ''' |
362 | - britney = subprocess.Popen([self.britney, '-v', '-c', self.britney_conf, |
363 | - '--distribution=ubuntu', |
364 | - '--series=%s' % self.data.series], |
365 | - stdout=subprocess.PIPE, |
366 | - stderr=subprocess.PIPE, |
367 | - cwd=self.data.path, |
368 | - universal_newlines=True) |
369 | - (out, err) = britney.communicate() |
370 | - self.assertEqual(britney.returncode, 0, out + err) |
371 | - self.assertEqual(err, '') |
372 | - |
373 | - with open(os.path.join(self.data.path, 'output', self.data.series, |
374 | - 'excuses.html')) as f: |
375 | - excuses = f.read() |
376 | - |
377 | - return (excuses, out) |
378 | + def do_test(self, unstable_add, adt_request, considered, expect=None, |
379 | + no_expect=None, history=""): |
380 | + for (pkg, fields) in unstable_add: |
381 | + self.data.add(pkg, True, fields) |
382 | + |
383 | + self.make_adt_britney(adt_request, history) |
384 | + |
385 | + (excuses, out) = self.run_britney() |
386 | + #print('-------\nexcuses: %s\n-----' % excuses) |
387 | + #print('-------\nout: %s\n-----' % out) |
388 | + #print('run:\n%s -c %s\n' % (self.britney, self.britney_conf)) |
389 | + #subprocess.call(['bash', '-i'], cwd=self.data.path) |
390 | + if considered: |
391 | + self.assertIn('Valid candidate', excuses) |
392 | + else: |
393 | + self.assertIn('Not considered', excuses) |
394 | + |
395 | + if expect: |
396 | + for re in expect: |
397 | + self.assertRegexpMatches(excuses, re) |
398 | + if no_expect: |
399 | + for re in no_expect: |
400 | + self.assertNotRegexpMatches(excuses, re) |
401 | |
402 | def test_no_request_for_uninstallable(self): |
403 | '''Does not request a test for an uninstallable package''' |
404 | @@ -557,30 +447,6 @@ |
405 | history="lightgreen 1 PASS lightgreen 1" |
406 | ) |
407 | |
408 | - def do_test(self, unstable_add, adt_request, considered, expect=None, |
409 | - no_expect=None, history=""): |
410 | - for (pkg, fields) in unstable_add: |
411 | - self.data.add(pkg, True, fields) |
412 | - |
413 | - self.make_adt_britney(adt_request, history) |
414 | - |
415 | - (excuses, out) = self.run_britney() |
416 | - #print('-------\nexcuses: %s\n-----' % excuses) |
417 | - #print('-------\nout: %s\n-----' % out) |
418 | - #print('run:\n%s -c %s\n' % (self.britney, self.britney_conf)) |
419 | - #subprocess.call(['bash', '-i'], cwd=self.data.path) |
420 | - if considered: |
421 | - self.assertIn('Valid candidate', excuses) |
422 | - else: |
423 | - self.assertIn('Not considered', excuses) |
424 | - |
425 | - if expect: |
426 | - for re in expect: |
427 | - self.assertRegexpMatches(excuses, re) |
428 | - if no_expect: |
429 | - for re in no_expect: |
430 | - self.assertNotRegexpMatches(excuses, re) |
431 | - |
432 | def shell(self): |
433 | # uninstallable unstable version |
434 | self.data.add('yellow', True, {'Version': '1.1~beta', |
435 | @@ -593,4 +459,5 @@ |
436 | subprocess.call(['bash', '-i'], cwd=self.data.path) |
437 | |
438 | |
439 | -unittest.main() |
440 | +if __name__ == '__main__': |
441 | + unittest.main() |