diff options
author | Paul Eggleton <paul.eggleton@linux.intel.com> | 2014-12-19 11:41:57 +0000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2014-12-23 10:18:16 +0000 |
commit | 8d46255a56f85f0d9fe1d00138f3855a54e3b510 (patch) | |
tree | bb1c5192e607728f71aec31b6800f534547318c7 | |
parent | 0d686ccc7c7facdaa36df5c340d000c3674e58c5 (diff) | |
download | poky-8d46255a56f85f0d9fe1d00138f3855a54e3b510.tar.gz |
devtool: add QA tests
Add some QA tests for devtool (and recipetool). These aren't
comprehensive but at least they are a start, and have already helped me
catch and fix a number of regressions.
(From OE-Core rev: 79486a8aea7af138535e139e696fbdbd5d57581b)
Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | meta/lib/oeqa/selftest/devtool.py | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/meta/lib/oeqa/selftest/devtool.py b/meta/lib/oeqa/selftest/devtool.py new file mode 100644 index 0000000000..e8ff536c16 --- /dev/null +++ b/meta/lib/oeqa/selftest/devtool.py | |||
@@ -0,0 +1,239 @@ | |||
1 | import unittest | ||
2 | import os | ||
3 | import logging | ||
4 | import re | ||
5 | import shutil | ||
6 | import tempfile | ||
7 | import glob | ||
8 | |||
9 | import oeqa.utils.ftools as ftools | ||
10 | from oeqa.selftest.base import oeSelfTest | ||
11 | from oeqa.utils.commands import runCmd, bitbake, get_bb_var | ||
12 | from oeqa.utils.decorators import testcase | ||
13 | |||
14 | class DevtoolTests(oeSelfTest): | ||
15 | |||
16 | def test_create_workspace(self): | ||
17 | # Check preconditions | ||
18 | workspacedir = os.path.join(self.builddir, 'workspace') | ||
19 | self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory') | ||
20 | result = runCmd('bitbake-layers show-layers') | ||
21 | self.assertTrue('/workspace' not in result.output, 'This test cannot be run with a workspace layer in bblayers.conf') | ||
22 | # Try creating a workspace layer with a specific path | ||
23 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
24 | self.track_for_cleanup(tempdir) | ||
25 | result = runCmd('devtool create-workspace %s' % tempdir) | ||
26 | self.assertTrue(os.path.isfile(os.path.join(tempdir, 'conf', 'layer.conf'))) | ||
27 | result = runCmd('bitbake-layers show-layers') | ||
28 | self.assertTrue(tempdir in result.output) | ||
29 | # Try creating a workspace layer with the default path | ||
30 | self.track_for_cleanup(workspacedir) | ||
31 | self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') | ||
32 | result = runCmd('devtool create-workspace') | ||
33 | self.assertTrue(os.path.isfile(os.path.join(workspacedir, 'conf', 'layer.conf'))) | ||
34 | result = runCmd('bitbake-layers show-layers') | ||
35 | self.assertTrue(tempdir not in result.output) | ||
36 | self.assertTrue(workspacedir in result.output) | ||
37 | |||
38 | def test_recipetool_create(self): | ||
39 | # Try adding a recipe | ||
40 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
41 | self.track_for_cleanup(tempdir) | ||
42 | tempsrc = os.path.join(tempdir, 'srctree') | ||
43 | os.makedirs(tempsrc) | ||
44 | recipefile = os.path.join(tempdir, 'logrotate_3.8.7.bb') | ||
45 | srcuri = 'https://fedorahosted.org/releases/l/o/logrotate/logrotate-3.8.7.tar.gz' | ||
46 | result = runCmd('recipetool create -o %s %s -x %s' % (recipefile, srcuri, tempsrc)) | ||
47 | self.assertTrue(os.path.isfile(recipefile)) | ||
48 | checkvars = {} | ||
49 | checkvars['LICENSE'] = 'GPLv2' | ||
50 | checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=18810669f13b87348459e611d31ab760' | ||
51 | checkvars['SRC_URI'] = 'https://fedorahosted.org/releases/l/o/logrotate/logrotate-${PV}.tar.gz' | ||
52 | checkvars['SRC_URI[md5sum]'] = '99e08503ef24c3e2e3ff74cc5f3be213' | ||
53 | checkvars['SRC_URI[sha256sum]'] = 'f6ba691f40e30e640efa2752c1f9499a3f9738257660994de70a45fe00d12b64' | ||
54 | with open(recipefile, 'r') as f: | ||
55 | for line in f: | ||
56 | if '=' in line: | ||
57 | splitline = line.split('=', 1) | ||
58 | var = splitline[0].rstrip() | ||
59 | value = splitline[1].strip().strip('"') | ||
60 | if var in checkvars: | ||
61 | needvalue = checkvars.pop(var) | ||
62 | self.assertEqual(value, needvalue) | ||
63 | if line.startswith('inherit '): | ||
64 | inherits = line.split()[1:] | ||
65 | |||
66 | self.assertEqual(checkvars, {}, 'Some variables not found') | ||
67 | |||
68 | def test_recipetool_create_git(self): | ||
69 | # Try adding a recipe | ||
70 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
71 | self.track_for_cleanup(tempdir) | ||
72 | tempsrc = os.path.join(tempdir, 'srctree') | ||
73 | os.makedirs(tempsrc) | ||
74 | recipefile = os.path.join(tempdir, 'libmatchbox.bb') | ||
75 | srcuri = 'git://git.yoctoproject.org/libmatchbox' | ||
76 | result = runCmd('recipetool create -o %s %s -x %s' % (recipefile, srcuri, tempsrc)) | ||
77 | self.assertTrue(os.path.isfile(recipefile)) | ||
78 | checkvars = {} | ||
79 | checkvars['LICENSE'] = 'LGPLv2.1' | ||
80 | checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=7fbc338309ac38fefcd64b04bb903e34' | ||
81 | checkvars['S'] = '${WORKDIR}/git' | ||
82 | checkvars['PV'] = '1.0+git${SRCPV}' | ||
83 | checkvars['SRC_URI'] = srcuri | ||
84 | checkvars['DEPENDS'] = 'libpng pango libx11 libxext' | ||
85 | inherits = [] | ||
86 | with open(recipefile, 'r') as f: | ||
87 | for line in f: | ||
88 | if '=' in line: | ||
89 | splitline = line.split('=', 1) | ||
90 | var = splitline[0].rstrip() | ||
91 | value = splitline[1].strip().strip('"') | ||
92 | if var in checkvars: | ||
93 | needvalue = checkvars.pop(var) | ||
94 | self.assertEqual(value, needvalue) | ||
95 | if line.startswith('inherit '): | ||
96 | inherits = line.split()[1:] | ||
97 | |||
98 | self.assertEqual(checkvars, {}, 'Some variables not found') | ||
99 | |||
100 | self.assertIn('autotools', inherits, 'Missing inherit of autotools') | ||
101 | self.assertIn('pkgconfig', inherits, 'Missing inherit of pkgconfig') | ||
102 | |||
103 | def test_devtool_add(self): | ||
104 | # Check preconditions | ||
105 | workspacedir = os.path.join(self.builddir, 'workspace') | ||
106 | self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory') | ||
107 | # Fetch source | ||
108 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
109 | self.track_for_cleanup(tempdir) | ||
110 | url = 'http://www.ivarch.com/programs/sources/pv-1.5.3.tar.bz2' | ||
111 | result = runCmd('wget %s' % url, cwd=tempdir) | ||
112 | result = runCmd('tar xfv pv-1.5.3.tar.bz2', cwd=tempdir) | ||
113 | srcdir = os.path.join(tempdir, 'pv-1.5.3') | ||
114 | self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure'))) | ||
115 | # Test devtool add | ||
116 | self.track_for_cleanup(workspacedir) | ||
117 | self.add_command_to_tearDown('bitbake -c cleansstate pv') | ||
118 | self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') | ||
119 | result = runCmd('devtool add pv %s' % srcdir) | ||
120 | self.assertTrue(os.path.exists(os.path.join(workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created') | ||
121 | # Test devtool status | ||
122 | result = runCmd('devtool status') | ||
123 | self.assertIn('pv', result.output) | ||
124 | self.assertIn(srcdir, result.output) | ||
125 | # Clean up anything in the workdir/sysroot/sstate cache (have to do this *after* devtool add since the recipe only exists then) | ||
126 | bitbake('pv -c cleansstate') | ||
127 | # Test devtool build | ||
128 | result = runCmd('devtool build pv') | ||
129 | installdir = get_bb_var('D', 'pv') | ||
130 | self.assertTrue(installdir) | ||
131 | bindir = get_bb_var('bindir', 'pv') | ||
132 | self.assertTrue(bindir) | ||
133 | if bindir[0] == '/': | ||
134 | bindir = bindir[1:] | ||
135 | self.assertTrue(os.path.isfile(os.path.join(installdir, bindir, 'pv')), 'pv binary not found in D') | ||
136 | |||
137 | def test_devtool_modify(self): | ||
138 | # Check preconditions | ||
139 | workspacedir = os.path.join(self.builddir, 'workspace') | ||
140 | self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory') | ||
141 | # Clean up anything in the workdir/sysroot/sstate cache | ||
142 | bitbake('mdadm -c cleansstate') | ||
143 | # Try modifying a recipe | ||
144 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
145 | self.track_for_cleanup(tempdir) | ||
146 | self.track_for_cleanup(workspacedir) | ||
147 | self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') | ||
148 | self.add_command_to_tearDown('bitbake -c clean mdadm') | ||
149 | result = runCmd('devtool modify mdadm -x %s' % tempdir) | ||
150 | self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile')), 'Extracted source could not be found') | ||
151 | self.assertTrue(os.path.isdir(os.path.join(tempdir, '.git')), 'git repository for external source tree not found') | ||
152 | self.assertTrue(os.path.exists(os.path.join(workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created') | ||
153 | matches = glob.glob(os.path.join(workspacedir, 'appends', 'mdadm_*.bbappend')) | ||
154 | self.assertTrue(matches, 'bbappend not created') | ||
155 | # Test devtool status | ||
156 | result = runCmd('devtool status') | ||
157 | self.assertIn('mdadm', result.output) | ||
158 | self.assertIn(tempdir, result.output) | ||
159 | # Check git repo | ||
160 | result = runCmd('git status --porcelain', cwd=tempdir) | ||
161 | self.assertEqual(result.output.strip(), "", 'Created git repo is not clean') | ||
162 | result = runCmd('git symbolic-ref HEAD', cwd=tempdir) | ||
163 | self.assertEqual(result.output.strip(), "refs/heads/devtool", 'Wrong branch in git repo') | ||
164 | # Try building | ||
165 | bitbake('mdadm') | ||
166 | # Try making (minor) modifications to the source | ||
167 | result = runCmd("sed -i 's!^\.TH.*!.TH MDADM 8 \"\" v9.999-custom!' %s" % os.path.join(tempdir, 'mdadm.8.in')) | ||
168 | bitbake('mdadm -c package') | ||
169 | pkgd = get_bb_var('PKGD', 'mdadm') | ||
170 | self.assertTrue(pkgd) | ||
171 | mandir = get_bb_var('mandir', 'mdadm') | ||
172 | self.assertTrue(mandir) | ||
173 | if mandir[0] == '/': | ||
174 | mandir = mandir[1:] | ||
175 | with open(os.path.join(pkgd, mandir, 'man8', 'mdadm.8'), 'r') as f: | ||
176 | for line in f: | ||
177 | if line.startswith('.TH'): | ||
178 | self.assertEqual(line.rstrip(), '.TH MDADM 8 "" v9.999-custom', 'man file not modified') | ||
179 | # Test devtool reset | ||
180 | result = runCmd('devtool reset mdadm') | ||
181 | result = runCmd('devtool status') | ||
182 | self.assertNotIn('mdadm', result.output) | ||
183 | |||
184 | def test_devtool_update_recipe(self): | ||
185 | # Check preconditions | ||
186 | workspacedir = os.path.join(self.builddir, 'workspace') | ||
187 | self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory') | ||
188 | testrecipe = 'minicom' | ||
189 | recipefile = get_bb_var('FILE', testrecipe) | ||
190 | result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile)) | ||
191 | self.assertEqual(result.output.strip(), "", '%s recipe is not clean' % testrecipe) | ||
192 | # First, modify a recipe | ||
193 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
194 | self.track_for_cleanup(tempdir) | ||
195 | self.track_for_cleanup(workspacedir) | ||
196 | self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') | ||
197 | # (don't bother with cleaning the recipe on teardown, we won't be building it) | ||
198 | result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir)) | ||
199 | # Check git repo | ||
200 | self.assertTrue(os.path.isdir(os.path.join(tempdir, '.git')), 'git repository for external source tree not found') | ||
201 | result = runCmd('git status --porcelain', cwd=tempdir) | ||
202 | self.assertEqual(result.output.strip(), "", 'Created git repo is not clean') | ||
203 | result = runCmd('git symbolic-ref HEAD', cwd=tempdir) | ||
204 | self.assertEqual(result.output.strip(), "refs/heads/devtool", 'Wrong branch in git repo') | ||
205 | # Add a couple of commits | ||
206 | # FIXME: this only tests adding, need to also test update and remove | ||
207 | result = runCmd('echo "Additional line" >> README', cwd=tempdir) | ||
208 | result = runCmd('git commit -a -m "Change the README"', cwd=tempdir) | ||
209 | result = runCmd('echo "A new file" > devtool-new-file', cwd=tempdir) | ||
210 | result = runCmd('git add devtool-new-file', cwd=tempdir) | ||
211 | result = runCmd('git commit -m "Add a new file"', cwd=tempdir) | ||
212 | self.add_command_to_tearDown('cd %s; rm %s/*.patch; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile))) | ||
213 | result = runCmd('devtool update-recipe %s' % testrecipe) | ||
214 | result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile)) | ||
215 | self.assertNotEqual(result.output.strip(), "", '%s recipe should be modified' % testrecipe) | ||
216 | status = result.output.splitlines() | ||
217 | self.assertEqual(len(status), 3, 'Less/more files modified than expected. Entire status:\n%s' % result.output) | ||
218 | for line in status: | ||
219 | if line.endswith('0001-Change-the-README.patch'): | ||
220 | self.assertEqual(line[:3], '?? ', 'Unexpected status in line: %s' % line) | ||
221 | elif line.endswith('0002-Add-a-new-file.patch'): | ||
222 | self.assertEqual(line[:3], '?? ', 'Unexpected status in line: %s' % line) | ||
223 | elif re.search('minicom_[^_]*.bb$', line): | ||
224 | self.assertEqual(line[:3], ' M ', 'Unexpected status in line: %s' % line) | ||
225 | else: | ||
226 | self.assertTrue(False, 'Unexpected modified file in status: %s' % line) | ||
227 | |||
228 | def test_devtool_extract(self): | ||
229 | # Check preconditions | ||
230 | workspacedir = os.path.join(self.builddir, 'workspace') | ||
231 | self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory') | ||
232 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
233 | # Try devtool extract | ||
234 | self.track_for_cleanup(tempdir) | ||
235 | self.track_for_cleanup(workspacedir) | ||
236 | self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') | ||
237 | result = runCmd('devtool extract remake %s' % tempdir) | ||
238 | self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile.am')), 'Extracted source could not be found') | ||
239 | self.assertTrue(os.path.isdir(os.path.join(tempdir, '.git')), 'git repository for external source tree not found') | ||