Merge lp:~cprov/britney/test-refactoring into lp:~ubuntu-release/britney/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
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.
lp:~cprov/britney/test-refactoring updated
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
=== added file 'tests/__init__.py'
--- tests/__init__.py 1970-01-01 00:00:00 +0000
+++ tests/__init__.py 2015-01-22 17:16:43 +0000
@@ -0,0 +1,159 @@
1# (C) 2015 Canonical Ltd.
2#
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2 of the License, or
6# (at your option) any later version.
7
8import os
9import shutil
10import subprocess
11import tempfile
12import unittest
13
14
15PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
16
17architectures = ['amd64', 'arm64', 'armhf', 'i386', 'powerpc', 'ppc64el']
18
19
20class TestData:
21
22 def __init__(self):
23 '''Construct local test package indexes.
24
25 The archive is initially empty. You can create new packages with
26 create_deb(). self.path contains the path of the archive, and
27 self.apt_source provides an apt source "deb" line.
28
29 It is kept in a temporary directory which gets removed when the Archive
30 object gets deleted.
31 '''
32 self.path = tempfile.mkdtemp(prefix='testarchive.')
33 self.apt_source = 'deb file://%s /' % self.path
34 self.series = 'series'
35 self.dirs = {False: os.path.join(self.path, 'data', self.series),
36 True: os.path.join(
37 self.path, 'data', '%s-proposed' % self.series)}
38 os.makedirs(self.dirs[False])
39 os.mkdir(self.dirs[True])
40 self.added_sources = {False: set(), True: set()}
41 self.added_binaries = {False: set(), True: set()}
42
43 # pre-create all files for all architectures
44 for arch in architectures:
45 for dir in self.dirs.values():
46 with open(os.path.join(dir, 'Packages_' + arch), 'w'):
47 pass
48 for dir in self.dirs.values():
49 for fname in ['Dates', 'Blocks']:
50 with open(os.path.join(dir, fname), 'w'):
51 pass
52 for dname in ['Hints']:
53 os.mkdir(os.path.join(dir, dname))
54
55 os.mkdir(os.path.join(self.path, 'output'))
56
57 # create temporary home dir for proposed-migration autopktest status
58 self.home = os.path.join(self.path, 'home')
59 os.environ['HOME'] = self.home
60 os.makedirs(os.path.join(self.home, 'proposed-migration',
61 'autopkgtest', 'work'))
62
63 def __del__(self):
64 shutil.rmtree(self.path)
65
66 def add(self, name, unstable, fields={}, add_src=True):
67 '''Add a binary package to the index file.
68
69 You need to specify at least the package name and in which list to put
70 it (unstable==True for unstable/proposed, or False for
71 testing/release). fields specifies all additional entries, e. g.
72 {'Depends': 'foo, bar', 'Conflicts: baz'}. There are defaults for most
73 fields.
74
75 Unless add_src is set to False, this will also automatically create a
76 source record, based on fields['Source'] and name.
77 '''
78 assert (name not in self.added_binaries[unstable])
79 self.added_binaries[unstable].add(name)
80
81 fields.setdefault('Architecture', architectures[0])
82 fields.setdefault('Version', '1')
83 fields.setdefault('Priority', 'optional')
84 fields.setdefault('Section', 'devel')
85 fields.setdefault('Description', 'test pkg')
86 if fields['Architecture'] == 'all':
87 for a in architectures:
88 self._append(name, unstable, 'Packages_' + a, fields)
89 else:
90 self._append(name, unstable, 'Packages_' + fields['Architecture'],
91 fields)
92
93 if add_src:
94 src = fields.get('Source', name)
95 if src not in self.added_sources[unstable]:
96 self.add_src(src, unstable, {'Version': fields['Version'],
97 'Section': fields['Section']})
98
99 def add_src(self, name, unstable, fields={}):
100 '''Add a source package to the index file.
101
102 You need to specify at least the package name and in which list to put
103 it (unstable==True for unstable/proposed, or False for
104 testing/release). fields specifies all additional entries, which can be
105 Version (default: 1), Section (default: devel), and Extra-Source-Only.
106 '''
107 assert (name not in self.added_sources[unstable])
108 self.added_sources[unstable].add(name)
109
110 fields.setdefault('Version', '1')
111 fields.setdefault('Section', 'devel')
112 self._append(name, unstable, 'Sources', fields)
113
114 def _append(self, name, unstable, file_name, fields):
115 with open(os.path.join(self.dirs[unstable], file_name), 'a') as f:
116 f.write('''Package: %s
117Maintainer: Joe <joe@example.com>
118''' % name)
119
120 for k, v in fields.items():
121 f.write('%s: %s\n' % (k, v))
122 f.write('\n')
123
124
125class TestBase(unittest.TestCase):
126
127 def setUp(self):
128 super(TestBase, self).setUp()
129 self.data = TestData()
130 self.britney = os.path.join(PROJECT_DIR, 'britney.py')
131 self.britney_conf = os.path.join(PROJECT_DIR, 'britney.conf')
132 assert os.path.exists(self.britney)
133 assert os.path.exists(self.britney_conf)
134
135 def tearDown(self):
136 del self.data
137
138 def run_britney(self, args=[]):
139 '''Run britney.
140
141 Assert that it succeeds and does not produce anything on stderr.
142 Return (excuses.html, britney_out).
143 '''
144 britney = subprocess.Popen([self.britney, '-v', '-c', self.britney_conf,
145 '--distribution=ubuntu',
146 '--series=%s' % self.data.series],
147 stdout=subprocess.PIPE,
148 stderr=subprocess.PIPE,
149 cwd=self.data.path,
150 universal_newlines=True)
151 (out, err) = britney.communicate()
152 self.assertEqual(britney.returncode, 0, out + err)
153 self.assertEqual(err, '')
154
155 with open(os.path.join(self.data.path, 'output', self.data.series,
156 'excuses.html')) as f:
157 excuses = f.read()
158
159 return (excuses, out)
0160
=== modified file 'tests/test_autopkgtest.py'
--- tests/test_autopkgtest.py 2014-12-10 10:42:27 +0000
+++ tests/test_autopkgtest.py 2015-01-22 17:16:43 +0000
@@ -6,133 +6,40 @@
6# the Free Software Foundation; either version 2 of the License, or6# the Free Software Foundation; either version 2 of the License, or
7# (at your option) any later version.7# (at your option) any later version.
88
9import tempfile9import apt_pkg
10import shutil10import operator
11import os11import os
12import sys12import sys
13import subprocess13import subprocess
14import unittest14import unittest
15import apt_pkg15
16import operator16PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
1717sys.path.insert(0, PROJECT_DIR)
18apt_pkg.init()18
19architectures = ['amd64', 'arm64', 'armhf', 'i386', 'powerpc', 'ppc64el']19from autopkgtest import ADT_EXCUSES_LABELS
2020from tests import TestBase
21my_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
2221
23NOT_CONSIDERED = False22NOT_CONSIDERED = False
24VALID_CANDIDATE = True23VALID_CANDIDATE = True
2524
26sys.path.insert(0, my_dir)25
27from autopkgtest import ADT_EXCUSES_LABELS26apt_pkg.init()
2827
2928
30class TestData:29class TestAutoPkgTest(TestBase):
31 def __init__(self):30
32 '''Construct local test package indexes.
33
34 The archive is initially empty. You can create new packages with
35 create_deb(). self.path contains the path of the archive, and
36 self.apt_source provides an apt source "deb" line.
37
38 It is kept in a temporary directory which gets removed when the Archive
39 object gets deleted.
40 '''
41 self.path = tempfile.mkdtemp(prefix='testarchive.')
42 self.apt_source = 'deb file://%s /' % self.path
43 self.series = 'series'
44 self.dirs = {False: os.path.join(self.path, 'data', self.series),
45 True: os.path.join(self.path, 'data', '%s-proposed' % self.series)}
46 os.makedirs(self.dirs[False])
47 os.mkdir(self.dirs[True])
48 self.added_sources = {False: set(), True: set()}
49 self.added_binaries = {False: set(), True: set()}
50
51 # pre-create all files for all architectures
52 for arch in architectures:
53 for dir in self.dirs.values():
54 with open(os.path.join(dir, 'Packages_' + arch), 'w'):
55 pass
56 for dir in self.dirs.values():
57 for fname in ['Dates', 'Blocks']:
58 with open(os.path.join(dir, fname), 'w'):
59 pass
60 for dname in ['Hints']:
61 os.mkdir(os.path.join(dir, dname))
62
63 os.mkdir(os.path.join(self.path, 'output'))
64
65 # create temporary home dir for proposed-migration autopktest status
66 self.home = os.path.join(self.path, 'home')
67 os.environ['HOME'] = self.home
68 os.makedirs(os.path.join(self.home, 'proposed-migration',
69 'autopkgtest', 'work'))
70
71 def __del__(self):
72 shutil.rmtree(self.path)
73
74 def add(self, name, unstable, fields={}, add_src=True):
75 '''Add a binary package to the index file.
76
77 You need to specify at least the package name and in which list to put
78 it (unstable==True for unstable/proposed, or False for
79 testing/release). fields specifies all additional entries, e. g.
80 {'Depends': 'foo, bar', 'Conflicts: baz'}. There are defaults for most
81 fields.
82
83 Unless add_src is set to False, this will also automatically create a
84 source record, based on fields['Source'] and name.
85 '''
86 assert (name not in self.added_binaries[unstable])
87 self.added_binaries[unstable].add(name)
88
89 fields.setdefault('Architecture', architectures[0])
90 fields.setdefault('Version', '1')
91 fields.setdefault('Priority', 'optional')
92 fields.setdefault('Section', 'devel')
93 fields.setdefault('Description', 'test pkg')
94 if fields['Architecture'] == 'all':
95 for a in architectures:
96 self._append(name, unstable, 'Packages_' + a, fields)
97 else:
98 self._append(name, unstable, 'Packages_' + fields['Architecture'],
99 fields)
100
101 if add_src:
102 src = fields.get('Source', name)
103 if src not in self.added_sources[unstable]:
104 self.add_src(src, unstable, {'Version': fields['Version'],
105 'Section': fields['Section']})
106
107 def add_src(self, name, unstable, fields={}):
108 '''Add a source package to the index file.
109
110 You need to specify at least the package name and in which list to put
111 it (unstable==True for unstable/proposed, or False for
112 testing/release). fields specifies all additional entries, which can be
113 Version (default: 1), Section (default: devel), and Extra-Source-Only.
114 '''
115 assert (name not in self.added_sources[unstable])
116 self.added_sources[unstable].add(name)
117
118 fields.setdefault('Version', '1')
119 fields.setdefault('Section', 'devel')
120 self._append(name, unstable, 'Sources', fields)
121
122 def _append(self, name, unstable, file_name, fields):
123 with open(os.path.join(self.dirs[unstable], file_name), 'a') as f:
124 f.write('''Package: %s
125Maintainer: Joe <joe@example.com>
126''' % name)
127
128 for k, v in fields.items():
129 f.write('%s: %s\n' % (k, v))
130 f.write('\n')
131
132
133class Test(unittest.TestCase):
134 def setUp(self):31 def setUp(self):
135 self.data = TestData()32 super(TestAutoPkgTest, self).setUp()
33
34 # fake adt-britney script
35 self.adt_britney = os.path.join(
36 self.data.home, 'auto-package-testing', 'jenkins', 'adt-britney')
37 os.makedirs(os.path.dirname(self.adt_britney))
38
39 with open(self.adt_britney, 'w') as f:
40 f.write('''#!/bin/sh -e
41echo "$@" >> /%s/adt-britney.log ''' % self.data.path)
42 os.chmod(self.adt_britney, 0o755)
13643
137 # add a bunch of packages to testing to avoid repetition44 # add a bunch of packages to testing to avoid repetition
138 self.data.add('libc6', False)45 self.data.add('libc6', False)
@@ -146,24 +53,6 @@
146 'Conflicts': 'green'})53 'Conflicts': 'green'})
147 self.data.add('justdata', False, {'Architecture': 'all'})54 self.data.add('justdata', False, {'Architecture': 'all'})
14855
149 self.britney = os.path.join(my_dir, 'britney.py')
150 self.britney_conf = os.path.join(my_dir, 'britney.conf')
151 assert os.path.exists(self.britney)
152 assert os.path.exists(self.britney_conf)
153
154 # fake adt-britney script
155 self.adt_britney = os.path.join(self.data.home, 'auto-package-testing',
156 'jenkins', 'adt-britney')
157 os.makedirs(os.path.dirname(self.adt_britney))
158
159 with open(self.adt_britney, 'w') as f:
160 f.write('''#!/bin/sh -e
161echo "$@" >> /%s/adt-britney.log ''' % self.data.path)
162 os.chmod(self.adt_britney, 0o755)
163
164 def tearDown(self):
165 del self.data
166
167 def __merge_records(self, results, history=""):56 def __merge_records(self, results, history=""):
168 '''Merges a list of results with records in history.57 '''Merges a list of results with records in history.
16958
@@ -235,28 +124,29 @@
235 'rq': request,124 'rq': request,
236 'res': self.__merge_records(request, history)})125 'res': self.__merge_records(request, history)})
237126
238 def run_britney(self, args=[]):127 def do_test(self, unstable_add, adt_request, considered, expect=None,
239 '''Run britney.128 no_expect=None, history=""):
240129 for (pkg, fields) in unstable_add:
241 Assert that it succeeds and does not produce anything on stderr.130 self.data.add(pkg, True, fields)
242 Return (excuses.html, britney_out).131
243 '''132 self.make_adt_britney(adt_request, history)
244 britney = subprocess.Popen([self.britney, '-v', '-c', self.britney_conf,133
245 '--distribution=ubuntu',134 (excuses, out) = self.run_britney()
246 '--series=%s' % self.data.series],135 #print('-------\nexcuses: %s\n-----' % excuses)
247 stdout=subprocess.PIPE,136 #print('-------\nout: %s\n-----' % out)
248 stderr=subprocess.PIPE,137 #print('run:\n%s -c %s\n' % (self.britney, self.britney_conf))
249 cwd=self.data.path,138 #subprocess.call(['bash', '-i'], cwd=self.data.path)
250 universal_newlines=True)139 if considered:
251 (out, err) = britney.communicate()140 self.assertIn('Valid candidate', excuses)
252 self.assertEqual(britney.returncode, 0, out + err)141 else:
253 self.assertEqual(err, '')142 self.assertIn('Not considered', excuses)
254143
255 with open(os.path.join(self.data.path, 'output', self.data.series,144 if expect:
256 'excuses.html')) as f:145 for re in expect:
257 excuses = f.read()146 self.assertRegexpMatches(excuses, re)
258147 if no_expect:
259 return (excuses, out)148 for re in no_expect:
149 self.assertNotRegexpMatches(excuses, re)
260150
261 def test_no_request_for_uninstallable(self):151 def test_no_request_for_uninstallable(self):
262 '''Does not request a test for an uninstallable package'''152 '''Does not request a test for an uninstallable package'''
@@ -557,30 +447,6 @@
557 history="lightgreen 1 PASS lightgreen 1"447 history="lightgreen 1 PASS lightgreen 1"
558 )448 )
559449
560 def do_test(self, unstable_add, adt_request, considered, expect=None,
561 no_expect=None, history=""):
562 for (pkg, fields) in unstable_add:
563 self.data.add(pkg, True, fields)
564
565 self.make_adt_britney(adt_request, history)
566
567 (excuses, out) = self.run_britney()
568 #print('-------\nexcuses: %s\n-----' % excuses)
569 #print('-------\nout: %s\n-----' % out)
570 #print('run:\n%s -c %s\n' % (self.britney, self.britney_conf))
571 #subprocess.call(['bash', '-i'], cwd=self.data.path)
572 if considered:
573 self.assertIn('Valid candidate', excuses)
574 else:
575 self.assertIn('Not considered', excuses)
576
577 if expect:
578 for re in expect:
579 self.assertRegexpMatches(excuses, re)
580 if no_expect:
581 for re in no_expect:
582 self.assertNotRegexpMatches(excuses, re)
583
584 def shell(self):450 def shell(self):
585 # uninstallable unstable version451 # uninstallable unstable version
586 self.data.add('yellow', True, {'Version': '1.1~beta',452 self.data.add('yellow', True, {'Version': '1.1~beta',
@@ -593,4 +459,5 @@
593 subprocess.call(['bash', '-i'], cwd=self.data.path)459 subprocess.call(['bash', '-i'], cwd=self.data.path)
594460
595461
596unittest.main()462if __name__ == '__main__':
463 unittest.main()

Subscribers

People subscribed via source and target branches