blob: d5b6a46d4912c0a1cd3a418ad3eda2e7c4e4caf5 [file] [log] [blame]
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001import os
2import re
3import shutil
4import tempfile
5import glob
6import fnmatch
7
8import oeqa.utils.ftools as ftools
9from oeqa.selftest.case import OESelftestTestCase
10from oeqa.utils.commands import runCmd, bitbake, get_bb_var, create_temp_layer
11from oeqa.utils.commands import get_bb_vars, runqemu, get_test_layer
12from oeqa.core.decorator.oeid import OETestID
13
14class DevtoolBase(OESelftestTestCase):
15
16 buffer = True
17
18 def _test_recipe_contents(self, recipefile, checkvars, checkinherits):
19 with open(recipefile, 'r') as f:
20 invar = None
21 invalue = None
22 for line in f:
23 var = None
24 if invar:
25 value = line.strip().strip('"')
26 if value.endswith('\\'):
27 invalue += ' ' + value[:-1].strip()
28 continue
29 else:
30 invalue += ' ' + value.strip()
31 var = invar
32 value = invalue
33 invar = None
34 elif '=' in line:
35 splitline = line.split('=', 1)
36 var = splitline[0].rstrip()
37 value = splitline[1].strip().strip('"')
38 if value.endswith('\\'):
39 invalue = value[:-1].strip()
40 invar = var
41 continue
42 elif line.startswith('inherit '):
43 inherits = line.split()[1:]
44
45 if var and var in checkvars:
46 needvalue = checkvars.pop(var)
47 if needvalue is None:
48 self.fail('Variable %s should not appear in recipe, but value is being set to "%s"' % (var, value))
49 if isinstance(needvalue, set):
50 if var == 'LICENSE':
51 value = set(value.split(' & '))
52 else:
53 value = set(value.split())
54 self.assertEqual(value, needvalue, 'values for %s do not match' % var)
55
56
57 missingvars = {}
58 for var, value in checkvars.items():
59 if value is not None:
60 missingvars[var] = value
61 self.assertEqual(missingvars, {}, 'Some expected variables not found in recipe: %s' % checkvars)
62
63 for inherit in checkinherits:
64 self.assertIn(inherit, inherits, 'Missing inherit of %s' % inherit)
65
66 def _check_bbappend(self, testrecipe, recipefile, appenddir):
67 result = runCmd('bitbake-layers show-appends', cwd=self.builddir)
68 resultlines = result.output.splitlines()
69 inrecipe = False
70 bbappends = []
71 bbappendfile = None
72 for line in resultlines:
73 if inrecipe:
74 if line.startswith(' '):
75 bbappends.append(line.strip())
76 else:
77 break
78 elif line == '%s:' % os.path.basename(recipefile):
79 inrecipe = True
80 self.assertLessEqual(len(bbappends), 2, '%s recipe is being bbappended by another layer - bbappends found:\n %s' % (testrecipe, '\n '.join(bbappends)))
81 for bbappend in bbappends:
82 if bbappend.startswith(appenddir):
83 bbappendfile = bbappend
84 break
85 else:
86 self.fail('bbappend for recipe %s does not seem to be created in test layer' % testrecipe)
87 return bbappendfile
88
89 def _create_temp_layer(self, templayerdir, addlayer, templayername, priority=999, recipepathspec='recipes-*/*'):
90 create_temp_layer(templayerdir, templayername, priority, recipepathspec)
91 if addlayer:
92 self.add_command_to_tearDown('bitbake-layers remove-layer %s || true' % templayerdir)
93 result = runCmd('bitbake-layers add-layer %s' % templayerdir, cwd=self.builddir)
94
95 def _process_ls_output(self, output):
96 """
97 Convert ls -l output to a format we can reasonably compare from one context
98 to another (e.g. from host to target)
99 """
100 filelist = []
101 for line in output.splitlines():
102 splitline = line.split()
103 if len(splitline) < 8:
104 self.fail('_process_ls_output: invalid output line: %s' % line)
105 # Remove trailing . on perms
106 splitline[0] = splitline[0].rstrip('.')
107 # Remove leading . on paths
108 splitline[-1] = splitline[-1].lstrip('.')
109 # Drop fields we don't want to compare
110 del splitline[7]
111 del splitline[6]
112 del splitline[5]
113 del splitline[4]
114 del splitline[1]
115 filelist.append(' '.join(splitline))
116 return filelist
117
118
119class DevtoolTests(DevtoolBase):
120
121 @classmethod
122 def setUpClass(cls):
123 super(DevtoolTests, cls).setUpClass()
124 bb_vars = get_bb_vars(['TOPDIR', 'SSTATE_DIR'])
125 cls.original_sstate = bb_vars['SSTATE_DIR']
126 cls.devtool_sstate = os.path.join(bb_vars['TOPDIR'], 'sstate_devtool')
127 cls.sstate_conf = 'SSTATE_DIR = "%s"\n' % cls.devtool_sstate
128 cls.sstate_conf += ('SSTATE_MIRRORS += "file://.* file:///%s/PATH"\n'
129 % cls.original_sstate)
130
131 @classmethod
132 def tearDownClass(cls):
133 cls.logger.debug('Deleting devtool sstate cache on %s' % cls.devtool_sstate)
134 runCmd('rm -rf %s' % cls.devtool_sstate)
135 super(DevtoolTests, cls).tearDownClass()
136
137 def setUp(self):
138 """Test case setup function"""
139 super(DevtoolTests, self).setUp()
140 self.workspacedir = os.path.join(self.builddir, 'workspace')
141 self.assertTrue(not os.path.exists(self.workspacedir),
142 'This test cannot be run with a workspace directory '
143 'under the build directory')
144 self.append_config(self.sstate_conf)
145
146 def _check_src_repo(self, repo_dir):
147 """Check srctree git repository"""
148 self.assertTrue(os.path.isdir(os.path.join(repo_dir, '.git')),
149 'git repository for external source tree not found')
150 result = runCmd('git status --porcelain', cwd=repo_dir)
151 self.assertEqual(result.output.strip(), "",
152 'Created git repo is not clean')
153 result = runCmd('git symbolic-ref HEAD', cwd=repo_dir)
154 self.assertEqual(result.output.strip(), "refs/heads/devtool",
155 'Wrong branch in git repo')
156
157 def _check_repo_status(self, repo_dir, expected_status):
158 """Check the worktree status of a repository"""
159 result = runCmd('git status . --porcelain',
160 cwd=repo_dir)
161 for line in result.output.splitlines():
162 for ind, (f_status, fn_re) in enumerate(expected_status):
163 if re.match(fn_re, line[3:]):
164 if f_status != line[:2]:
165 self.fail('Unexpected status in line: %s' % line)
166 expected_status.pop(ind)
167 break
168 else:
169 self.fail('Unexpected modified file in line: %s' % line)
170 if expected_status:
171 self.fail('Missing file changes: %s' % expected_status)
172
173 @OETestID(1158)
174 def test_create_workspace(self):
175 # Check preconditions
176 result = runCmd('bitbake-layers show-layers')
Brad Bishop316dfdd2018-06-25 12:45:53 -0400177 self.assertTrue('\nworkspace' not in result.output, 'This test cannot be run with a workspace layer in bblayers.conf')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500178 # Try creating a workspace layer with a specific path
179 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
180 self.track_for_cleanup(tempdir)
181 result = runCmd('devtool create-workspace %s' % tempdir)
182 self.assertTrue(os.path.isfile(os.path.join(tempdir, 'conf', 'layer.conf')), msg = "No workspace created. devtool output: %s " % result.output)
183 result = runCmd('bitbake-layers show-layers')
184 self.assertIn(tempdir, result.output)
185 # Try creating a workspace layer with the default path
186 self.track_for_cleanup(self.workspacedir)
187 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
188 result = runCmd('devtool create-workspace')
189 self.assertTrue(os.path.isfile(os.path.join(self.workspacedir, 'conf', 'layer.conf')), msg = "No workspace created. devtool output: %s " % result.output)
190 result = runCmd('bitbake-layers show-layers')
191 self.assertNotIn(tempdir, result.output)
192 self.assertIn(self.workspacedir, result.output)
193
194 @OETestID(1159)
195 def test_devtool_add(self):
196 # Fetch source
197 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
198 self.track_for_cleanup(tempdir)
199 pn = 'pv'
200 pv = '1.5.3'
201 url = 'http://www.ivarch.com/programs/sources/pv-1.5.3.tar.bz2'
202 result = runCmd('wget %s' % url, cwd=tempdir)
203 result = runCmd('tar xfv %s' % os.path.basename(url), cwd=tempdir)
204 srcdir = os.path.join(tempdir, '%s-%s' % (pn, pv))
205 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure')), 'Unable to find configure script in source directory')
206 # Test devtool add
207 self.track_for_cleanup(self.workspacedir)
208 self.add_command_to_tearDown('bitbake -c cleansstate %s' % pn)
209 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
210 result = runCmd('devtool add %s %s' % (pn, srcdir))
211 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
212 # Test devtool status
213 result = runCmd('devtool status')
214 recipepath = '%s/recipes/%s/%s_%s.bb' % (self.workspacedir, pn, pn, pv)
215 self.assertIn(recipepath, result.output)
216 self.assertIn(srcdir, result.output)
217 # Test devtool find-recipe
218 result = runCmd('devtool -q find-recipe %s' % pn)
219 self.assertEqual(recipepath, result.output.strip())
220 # Test devtool edit-recipe
221 result = runCmd('VISUAL="echo 123" devtool -q edit-recipe %s' % pn)
222 self.assertEqual('123 %s' % recipepath, result.output.strip())
223 # Clean up anything in the workdir/sysroot/sstate cache (have to do this *after* devtool add since the recipe only exists then)
224 bitbake('%s -c cleansstate' % pn)
225 # Test devtool build
226 result = runCmd('devtool build %s' % pn)
227 bb_vars = get_bb_vars(['D', 'bindir'], pn)
228 installdir = bb_vars['D']
229 self.assertTrue(installdir, 'Could not query installdir variable')
230 bindir = bb_vars['bindir']
231 self.assertTrue(bindir, 'Could not query bindir variable')
232 if bindir[0] == '/':
233 bindir = bindir[1:]
234 self.assertTrue(os.path.isfile(os.path.join(installdir, bindir, 'pv')), 'pv binary not found in D')
235
236 @OETestID(1423)
237 def test_devtool_add_git_local(self):
238 # Fetch source from a remote URL, but do it outside of devtool
239 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
240 self.track_for_cleanup(tempdir)
241 pn = 'dbus-wait'
242 srcrev = '6cc6077a36fe2648a5f993fe7c16c9632f946517'
243 # We choose an https:// git URL here to check rewriting the URL works
244 url = 'https://git.yoctoproject.org/git/dbus-wait'
245 # Force fetching to "noname" subdir so we verify we're picking up the name from autoconf
246 # instead of the directory name
247 result = runCmd('git clone %s noname' % url, cwd=tempdir)
248 srcdir = os.path.join(tempdir, 'noname')
249 result = runCmd('git reset --hard %s' % srcrev, cwd=srcdir)
250 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure.ac')), 'Unable to find configure script in source directory')
251 # Test devtool add
252 self.track_for_cleanup(self.workspacedir)
253 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
254 # Don't specify a name since we should be able to auto-detect it
255 result = runCmd('devtool add %s' % srcdir)
256 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
257 # Check the recipe name is correct
258 recipefile = get_bb_var('FILE', pn)
259 self.assertIn('%s_git.bb' % pn, recipefile, 'Recipe file incorrectly named')
260 self.assertIn(recipefile, result.output)
261 # Test devtool status
262 result = runCmd('devtool status')
263 self.assertIn(pn, result.output)
264 self.assertIn(srcdir, result.output)
265 self.assertIn(recipefile, result.output)
266 checkvars = {}
267 checkvars['LICENSE'] = 'GPLv2'
268 checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263'
269 checkvars['S'] = '${WORKDIR}/git'
270 checkvars['PV'] = '0.1+git${SRCPV}'
271 checkvars['SRC_URI'] = 'git://git.yoctoproject.org/git/dbus-wait;protocol=https'
272 checkvars['SRCREV'] = srcrev
273 checkvars['DEPENDS'] = set(['dbus'])
274 self._test_recipe_contents(recipefile, checkvars, [])
275
276 @OETestID(1162)
277 def test_devtool_add_library(self):
278 # Fetch source
279 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
280 self.track_for_cleanup(tempdir)
281 version = '1.1'
282 url = 'https://www.intra2net.com/en/developer/libftdi/download/libftdi1-%s.tar.bz2' % version
283 result = runCmd('wget %s' % url, cwd=tempdir)
284 result = runCmd('tar xfv libftdi1-%s.tar.bz2' % version, cwd=tempdir)
285 srcdir = os.path.join(tempdir, 'libftdi1-%s' % version)
286 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'CMakeLists.txt')), 'Unable to find CMakeLists.txt in source directory')
287 # Test devtool add (and use -V so we test that too)
288 self.track_for_cleanup(self.workspacedir)
289 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
290 result = runCmd('devtool add libftdi %s -V %s' % (srcdir, version))
291 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
292 # Test devtool status
293 result = runCmd('devtool status')
294 self.assertIn('libftdi', result.output)
295 self.assertIn(srcdir, result.output)
296 # Clean up anything in the workdir/sysroot/sstate cache (have to do this *after* devtool add since the recipe only exists then)
297 bitbake('libftdi -c cleansstate')
298 # libftdi's python/CMakeLists.txt is a bit broken, so let's just disable it
299 # There's also the matter of it installing cmake files to a path we don't
300 # normally cover, which triggers the installed-vs-shipped QA test we have
301 # within do_package
302 recipefile = '%s/recipes/libftdi/libftdi_%s.bb' % (self.workspacedir, version)
303 result = runCmd('recipetool setvar %s EXTRA_OECMAKE -- \'-DPYTHON_BINDINGS=OFF -DLIBFTDI_CMAKE_CONFIG_DIR=${datadir}/cmake/Modules\'' % recipefile)
304 with open(recipefile, 'a') as f:
305 f.write('\nFILES_${PN}-dev += "${datadir}/cmake/Modules"\n')
306 # We don't have the ability to pick up this dependency automatically yet...
307 f.write('\nDEPENDS += "libusb1"\n')
308 f.write('\nTESTLIBOUTPUT = "${COMPONENTS_DIR}/${TUNE_PKGARCH}/${PN}/${libdir}"\n')
309 # Test devtool build
310 result = runCmd('devtool build libftdi')
311 bb_vars = get_bb_vars(['TESTLIBOUTPUT', 'STAMP'], 'libftdi')
312 staging_libdir = bb_vars['TESTLIBOUTPUT']
313 self.assertTrue(staging_libdir, 'Could not query TESTLIBOUTPUT variable')
314 self.assertTrue(os.path.isfile(os.path.join(staging_libdir, 'libftdi1.so.2.1.0')), "libftdi binary not found in STAGING_LIBDIR. Output of devtool build libftdi %s" % result.output)
315 # Test devtool reset
316 stampprefix = bb_vars['STAMP']
317 result = runCmd('devtool reset libftdi')
318 result = runCmd('devtool status')
319 self.assertNotIn('libftdi', result.output)
320 self.assertTrue(stampprefix, 'Unable to get STAMP value for recipe libftdi')
321 matches = glob.glob(stampprefix + '*')
322 self.assertFalse(matches, 'Stamp files exist for recipe libftdi that should have been cleaned')
323 self.assertFalse(os.path.isfile(os.path.join(staging_libdir, 'libftdi1.so.2.1.0')), 'libftdi binary still found in STAGING_LIBDIR after cleaning')
324
325 @OETestID(1160)
326 def test_devtool_add_fetch(self):
327 # Fetch source
328 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
329 self.track_for_cleanup(tempdir)
330 testver = '0.23'
331 url = 'https://pypi.python.org/packages/source/M/MarkupSafe/MarkupSafe-%s.tar.gz' % testver
332 testrecipe = 'python-markupsafe'
333 srcdir = os.path.join(tempdir, testrecipe)
334 # Test devtool add
335 self.track_for_cleanup(self.workspacedir)
336 self.add_command_to_tearDown('bitbake -c cleansstate %s' % testrecipe)
337 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
338 result = runCmd('devtool add %s %s -f %s' % (testrecipe, srcdir, url))
339 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created. %s' % result.output)
340 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'setup.py')), 'Unable to find setup.py in source directory')
341 self.assertTrue(os.path.isdir(os.path.join(srcdir, '.git')), 'git repository for external source tree was not created')
342 # Test devtool status
343 result = runCmd('devtool status')
344 self.assertIn(testrecipe, result.output)
345 self.assertIn(srcdir, result.output)
346 # Check recipe
347 recipefile = get_bb_var('FILE', testrecipe)
348 self.assertIn('%s_%s.bb' % (testrecipe, testver), recipefile, 'Recipe file incorrectly named')
349 checkvars = {}
350 checkvars['S'] = '${WORKDIR}/MarkupSafe-${PV}'
351 checkvars['SRC_URI'] = url.replace(testver, '${PV}')
352 self._test_recipe_contents(recipefile, checkvars, [])
353 # Try with version specified
354 result = runCmd('devtool reset -n %s' % testrecipe)
355 shutil.rmtree(srcdir)
356 fakever = '1.9'
357 result = runCmd('devtool add %s %s -f %s -V %s' % (testrecipe, srcdir, url, fakever))
358 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'setup.py')), 'Unable to find setup.py in source directory')
359 # Test devtool status
360 result = runCmd('devtool status')
361 self.assertIn(testrecipe, result.output)
362 self.assertIn(srcdir, result.output)
363 # Check recipe
364 recipefile = get_bb_var('FILE', testrecipe)
365 self.assertIn('%s_%s.bb' % (testrecipe, fakever), recipefile, 'Recipe file incorrectly named')
366 checkvars = {}
367 checkvars['S'] = '${WORKDIR}/MarkupSafe-%s' % testver
368 checkvars['SRC_URI'] = url
369 self._test_recipe_contents(recipefile, checkvars, [])
370
371 @OETestID(1161)
372 def test_devtool_add_fetch_git(self):
373 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
374 self.track_for_cleanup(tempdir)
375 url = 'gitsm://git.yoctoproject.org/mraa'
376 checkrev = 'ae127b19a50aa54255e4330ccfdd9a5d058e581d'
377 testrecipe = 'mraa'
378 srcdir = os.path.join(tempdir, testrecipe)
379 # Test devtool add
380 self.track_for_cleanup(self.workspacedir)
381 self.add_command_to_tearDown('bitbake -c cleansstate %s' % testrecipe)
382 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
383 result = runCmd('devtool add %s %s -a -f %s' % (testrecipe, srcdir, url))
384 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created: %s' % result.output)
385 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'imraa', 'imraa.c')), 'Unable to find imraa/imraa.c in source directory')
386 # Test devtool status
387 result = runCmd('devtool status')
388 self.assertIn(testrecipe, result.output)
389 self.assertIn(srcdir, result.output)
390 # Check recipe
391 recipefile = get_bb_var('FILE', testrecipe)
392 self.assertIn('_git.bb', recipefile, 'Recipe file incorrectly named')
393 checkvars = {}
394 checkvars['S'] = '${WORKDIR}/git'
395 checkvars['PV'] = '1.0+git${SRCPV}'
396 checkvars['SRC_URI'] = url
397 checkvars['SRCREV'] = '${AUTOREV}'
398 self._test_recipe_contents(recipefile, checkvars, [])
399 # Try with revision and version specified
400 result = runCmd('devtool reset -n %s' % testrecipe)
401 shutil.rmtree(srcdir)
402 url_rev = '%s;rev=%s' % (url, checkrev)
403 result = runCmd('devtool add %s %s -f "%s" -V 1.5' % (testrecipe, srcdir, url_rev))
404 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'imraa', 'imraa.c')), 'Unable to find imraa/imraa.c in source directory')
405 # Test devtool status
406 result = runCmd('devtool status')
407 self.assertIn(testrecipe, result.output)
408 self.assertIn(srcdir, result.output)
409 # Check recipe
410 recipefile = get_bb_var('FILE', testrecipe)
411 self.assertIn('_git.bb', recipefile, 'Recipe file incorrectly named')
412 checkvars = {}
413 checkvars['S'] = '${WORKDIR}/git'
414 checkvars['PV'] = '1.5+git${SRCPV}'
415 checkvars['SRC_URI'] = url
416 checkvars['SRCREV'] = checkrev
417 self._test_recipe_contents(recipefile, checkvars, [])
418
419 @OETestID(1391)
420 def test_devtool_add_fetch_simple(self):
421 # Fetch source from a remote URL, auto-detecting name
422 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
423 self.track_for_cleanup(tempdir)
424 testver = '1.6.0'
425 url = 'http://www.ivarch.com/programs/sources/pv-%s.tar.bz2' % testver
426 testrecipe = 'pv'
427 srcdir = os.path.join(self.workspacedir, 'sources', testrecipe)
428 # Test devtool add
429 self.track_for_cleanup(self.workspacedir)
430 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
431 result = runCmd('devtool add %s' % url)
432 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created. %s' % result.output)
433 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure')), 'Unable to find configure script in source directory')
434 self.assertTrue(os.path.isdir(os.path.join(srcdir, '.git')), 'git repository for external source tree was not created')
435 # Test devtool status
436 result = runCmd('devtool status')
437 self.assertIn(testrecipe, result.output)
438 self.assertIn(srcdir, result.output)
439 # Check recipe
440 recipefile = get_bb_var('FILE', testrecipe)
441 self.assertIn('%s_%s.bb' % (testrecipe, testver), recipefile, 'Recipe file incorrectly named')
442 checkvars = {}
443 checkvars['S'] = None
444 checkvars['SRC_URI'] = url.replace(testver, '${PV}')
445 self._test_recipe_contents(recipefile, checkvars, [])
446
447 @OETestID(1164)
448 def test_devtool_modify(self):
449 import oe.path
450
451 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
452 self.track_for_cleanup(tempdir)
453 self.track_for_cleanup(self.workspacedir)
454 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
455 self.add_command_to_tearDown('bitbake -c clean mdadm')
456 result = runCmd('devtool modify mdadm -x %s' % tempdir)
457 self.assertExists(os.path.join(tempdir, 'Makefile'), 'Extracted source could not be found')
458 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
459 matches = glob.glob(os.path.join(self.workspacedir, 'appends', 'mdadm_*.bbappend'))
460 self.assertTrue(matches, 'bbappend not created %s' % result.output)
461
462 # Test devtool status
463 result = runCmd('devtool status')
464 self.assertIn('mdadm', result.output)
465 self.assertIn(tempdir, result.output)
466 self._check_src_repo(tempdir)
467
468 bitbake('mdadm -C unpack')
469
470 def check_line(checkfile, expected, message, present=True):
471 # Check for $expected, on a line on its own, in checkfile.
472 with open(checkfile, 'r') as f:
473 if present:
474 self.assertIn(expected + '\n', f, message)
475 else:
476 self.assertNotIn(expected + '\n', f, message)
477
478 modfile = os.path.join(tempdir, 'mdadm.8.in')
479 bb_vars = get_bb_vars(['PKGD', 'mandir'], 'mdadm')
480 pkgd = bb_vars['PKGD']
481 self.assertTrue(pkgd, 'Could not query PKGD variable')
482 mandir = bb_vars['mandir']
483 self.assertTrue(mandir, 'Could not query mandir variable')
484 manfile = oe.path.join(pkgd, mandir, 'man8', 'mdadm.8')
485
486 check_line(modfile, 'Linux Software RAID', 'Could not find initial string')
487 check_line(modfile, 'antique pin sardine', 'Unexpectedly found replacement string', present=False)
488
489 result = runCmd("sed -i 's!^Linux Software RAID$!antique pin sardine!' %s" % modfile)
490 check_line(modfile, 'antique pin sardine', 'mdadm.8.in file not modified (sed failed)')
491
492 bitbake('mdadm -c package')
493 check_line(manfile, 'antique pin sardine', 'man file not modified. man searched file path: %s' % manfile)
494
495 result = runCmd('git checkout -- %s' % modfile, cwd=tempdir)
496 check_line(modfile, 'Linux Software RAID', 'man .in file not restored (git failed)')
497
498 bitbake('mdadm -c package')
499 check_line(manfile, 'Linux Software RAID', 'man file not updated. man searched file path: %s' % manfile)
500
501 result = runCmd('devtool reset mdadm')
502 result = runCmd('devtool status')
503 self.assertNotIn('mdadm', result.output)
504
505 @OETestID(1620)
506 def test_devtool_buildclean(self):
507 def assertFile(path, *paths):
508 f = os.path.join(path, *paths)
509 self.assertExists(f)
510 def assertNoFile(path, *paths):
511 f = os.path.join(path, *paths)
512 self.assertNotExists(f)
513
514 # Clean up anything in the workdir/sysroot/sstate cache
515 bitbake('mdadm m4 -c cleansstate')
516 # Try modifying a recipe
517 tempdir_mdadm = tempfile.mkdtemp(prefix='devtoolqa')
518 tempdir_m4 = tempfile.mkdtemp(prefix='devtoolqa')
519 builddir_m4 = tempfile.mkdtemp(prefix='devtoolqa')
520 self.track_for_cleanup(tempdir_mdadm)
521 self.track_for_cleanup(tempdir_m4)
522 self.track_for_cleanup(builddir_m4)
523 self.track_for_cleanup(self.workspacedir)
524 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
525 self.add_command_to_tearDown('bitbake -c clean mdadm m4')
526 self.write_recipeinc('m4', 'EXTERNALSRC_BUILD = "%s"\ndo_clean() {\n\t:\n}\n' % builddir_m4)
527 try:
528 runCmd('devtool modify mdadm -x %s' % tempdir_mdadm)
529 runCmd('devtool modify m4 -x %s' % tempdir_m4)
530 assertNoFile(tempdir_mdadm, 'mdadm')
531 assertNoFile(builddir_m4, 'src/m4')
532 result = bitbake('m4 -e')
533 result = bitbake('mdadm m4 -c compile')
534 self.assertEqual(result.status, 0)
535 assertFile(tempdir_mdadm, 'mdadm')
536 assertFile(builddir_m4, 'src/m4')
537 # Check that buildclean task exists and does call make clean
538 bitbake('mdadm m4 -c buildclean')
539 assertNoFile(tempdir_mdadm, 'mdadm')
540 assertNoFile(builddir_m4, 'src/m4')
541 bitbake('mdadm m4 -c compile')
542 assertFile(tempdir_mdadm, 'mdadm')
543 assertFile(builddir_m4, 'src/m4')
544 bitbake('mdadm m4 -c clean')
545 # Check that buildclean task is run before clean for B == S
546 assertNoFile(tempdir_mdadm, 'mdadm')
547 # Check that buildclean task is not run before clean for B != S
548 assertFile(builddir_m4, 'src/m4')
549 finally:
550 self.delete_recipeinc('m4')
551
552 @OETestID(1166)
553 def test_devtool_modify_invalid(self):
554 # Try modifying some recipes
555 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
556 self.track_for_cleanup(tempdir)
557 self.track_for_cleanup(self.workspacedir)
558 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
559
560 testrecipes = 'perf kernel-devsrc package-index core-image-minimal meta-toolchain packagegroup-core-sdk meta-ide-support'.split()
561 # Find actual name of gcc-source since it now includes the version - crude, but good enough for this purpose
562 result = runCmd('bitbake-layers show-recipes gcc-source*')
563 for line in result.output.splitlines():
564 # just match those lines that contain a real target
565 m = re.match('(?P<recipe>^[a-zA-Z0-9.-]+)(?P<colon>:$)', line)
566 if m:
567 testrecipes.append(m.group('recipe'))
568 for testrecipe in testrecipes:
569 # Check it's a valid recipe
570 bitbake('%s -e' % testrecipe)
571 # devtool extract should fail
572 result = runCmd('devtool extract %s %s' % (testrecipe, os.path.join(tempdir, testrecipe)), ignore_status=True)
573 self.assertNotEqual(result.status, 0, 'devtool extract on %s should have failed. devtool output: %s' % (testrecipe, result.output))
574 self.assertNotIn('Fetching ', result.output, 'devtool extract on %s should have errored out before trying to fetch' % testrecipe)
575 self.assertIn('ERROR: ', result.output, 'devtool extract on %s should have given an ERROR' % testrecipe)
576 # devtool modify should fail
577 result = runCmd('devtool modify %s -x %s' % (testrecipe, os.path.join(tempdir, testrecipe)), ignore_status=True)
578 self.assertNotEqual(result.status, 0, 'devtool modify on %s should have failed. devtool output: %s' % (testrecipe, result.output))
579 self.assertIn('ERROR: ', result.output, 'devtool modify on %s should have given an ERROR' % testrecipe)
580
581 @OETestID(1365)
582 def test_devtool_modify_native(self):
583 # Check preconditions
584 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
585 # Try modifying some recipes
586 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
587 self.track_for_cleanup(tempdir)
588 self.track_for_cleanup(self.workspacedir)
589 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
590
591 bbclassextended = False
592 inheritnative = False
593 testrecipes = 'mtools-native apt-native desktop-file-utils-native'.split()
594 for testrecipe in testrecipes:
595 checkextend = 'native' in (get_bb_var('BBCLASSEXTEND', testrecipe) or '').split()
596 if not bbclassextended:
597 bbclassextended = checkextend
598 if not inheritnative:
599 inheritnative = not checkextend
600 result = runCmd('devtool modify %s -x %s' % (testrecipe, os.path.join(tempdir, testrecipe)))
601 self.assertNotIn('ERROR: ', result.output, 'ERROR in devtool modify output: %s' % result.output)
602 result = runCmd('devtool build %s' % testrecipe)
603 self.assertNotIn('ERROR: ', result.output, 'ERROR in devtool build output: %s' % result.output)
604 result = runCmd('devtool reset %s' % testrecipe)
605 self.assertNotIn('ERROR: ', result.output, 'ERROR in devtool reset output: %s' % result.output)
606
607 self.assertTrue(bbclassextended, 'None of these recipes are BBCLASSEXTENDed to native - need to adjust testrecipes list: %s' % ', '.join(testrecipes))
608 self.assertTrue(inheritnative, 'None of these recipes do "inherit native" - need to adjust testrecipes list: %s' % ', '.join(testrecipes))
609
610
611 @OETestID(1165)
612 def test_devtool_modify_git(self):
613 # Check preconditions
Brad Bishop316dfdd2018-06-25 12:45:53 -0400614 testrecipe = 'psplash'
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500615 src_uri = get_bb_var('SRC_URI', testrecipe)
616 self.assertIn('git://', src_uri, 'This test expects the %s recipe to be a git recipe' % testrecipe)
617 # Clean up anything in the workdir/sysroot/sstate cache
618 bitbake('%s -c cleansstate' % testrecipe)
619 # Try modifying a recipe
620 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
621 self.track_for_cleanup(tempdir)
622 self.track_for_cleanup(self.workspacedir)
623 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
624 self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
625 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
Brad Bishop316dfdd2018-06-25 12:45:53 -0400626 self.assertExists(os.path.join(tempdir, 'Makefile.am'), 'Extracted source could not be found')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500627 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created. devtool output: %s' % result.output)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400628 matches = glob.glob(os.path.join(self.workspacedir, 'appends', 'psplash_*.bbappend'))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500629 self.assertTrue(matches, 'bbappend not created')
630 # Test devtool status
631 result = runCmd('devtool status')
632 self.assertIn(testrecipe, result.output)
633 self.assertIn(tempdir, result.output)
634 # Check git repo
635 self._check_src_repo(tempdir)
636 # Try building
637 bitbake(testrecipe)
638
639 @OETestID(1167)
640 def test_devtool_modify_localfiles(self):
641 # Check preconditions
642 testrecipe = 'lighttpd'
643 src_uri = (get_bb_var('SRC_URI', testrecipe) or '').split()
644 foundlocal = False
645 for item in src_uri:
646 if item.startswith('file://') and '.patch' not in item:
647 foundlocal = True
648 break
649 self.assertTrue(foundlocal, 'This test expects the %s recipe to fetch local files and it seems that it no longer does' % testrecipe)
650 # Clean up anything in the workdir/sysroot/sstate cache
651 bitbake('%s -c cleansstate' % testrecipe)
652 # Try modifying a recipe
653 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
654 self.track_for_cleanup(tempdir)
655 self.track_for_cleanup(self.workspacedir)
656 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
657 self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
658 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
659 self.assertExists(os.path.join(tempdir, 'configure.ac'), 'Extracted source could not be found')
660 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
661 matches = glob.glob(os.path.join(self.workspacedir, 'appends', '%s_*.bbappend' % testrecipe))
662 self.assertTrue(matches, 'bbappend not created')
663 # Test devtool status
664 result = runCmd('devtool status')
665 self.assertIn(testrecipe, result.output)
666 self.assertIn(tempdir, result.output)
667 # Try building
668 bitbake(testrecipe)
669
670 @OETestID(1378)
671 def test_devtool_modify_virtual(self):
672 # Try modifying a virtual recipe
673 virtrecipe = 'virtual/make'
674 realrecipe = 'make'
675 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
676 self.track_for_cleanup(tempdir)
677 self.track_for_cleanup(self.workspacedir)
678 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
679 result = runCmd('devtool modify %s -x %s' % (virtrecipe, tempdir))
680 self.assertExists(os.path.join(tempdir, 'Makefile.am'), 'Extracted source could not be found')
681 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
682 matches = glob.glob(os.path.join(self.workspacedir, 'appends', '%s_*.bbappend' % realrecipe))
683 self.assertTrue(matches, 'bbappend not created %s' % result.output)
684 # Test devtool status
685 result = runCmd('devtool status')
686 self.assertNotIn(virtrecipe, result.output)
687 self.assertIn(realrecipe, result.output)
688 # Check git repo
689 self._check_src_repo(tempdir)
690 # This is probably sufficient
691
692
693 @OETestID(1169)
694 def test_devtool_update_recipe(self):
695 # Check preconditions
696 testrecipe = 'minicom'
697 bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
698 recipefile = bb_vars['FILE']
699 src_uri = bb_vars['SRC_URI']
700 self.assertNotIn('git://', src_uri, 'This test expects the %s recipe to NOT be a git recipe' % testrecipe)
701 self._check_repo_status(os.path.dirname(recipefile), [])
702 # First, modify a recipe
703 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
704 self.track_for_cleanup(tempdir)
705 self.track_for_cleanup(self.workspacedir)
706 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
707 # (don't bother with cleaning the recipe on teardown, we won't be building it)
708 # We don't use -x here so that we test the behaviour of devtool modify without it
709 result = runCmd('devtool modify %s %s' % (testrecipe, tempdir))
710 # Check git repo
711 self._check_src_repo(tempdir)
712 # Add a couple of commits
713 # FIXME: this only tests adding, need to also test update and remove
714 result = runCmd('echo "Additional line" >> README', cwd=tempdir)
715 result = runCmd('git commit -a -m "Change the README"', cwd=tempdir)
716 result = runCmd('echo "A new file" > devtool-new-file', cwd=tempdir)
717 result = runCmd('git add devtool-new-file', cwd=tempdir)
718 result = runCmd('git commit -m "Add a new file"', cwd=tempdir)
719 self.add_command_to_tearDown('cd %s; rm %s/*.patch; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
720 result = runCmd('devtool update-recipe %s' % testrecipe)
721 expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)),
722 ('??', '.*/0001-Change-the-README.patch$'),
723 ('??', '.*/0002-Add-a-new-file.patch$')]
724 self._check_repo_status(os.path.dirname(recipefile), expected_status)
725
726 @OETestID(1172)
727 def test_devtool_update_recipe_git(self):
728 # Check preconditions
729 testrecipe = 'mtd-utils'
730 bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
731 recipefile = bb_vars['FILE']
732 src_uri = bb_vars['SRC_URI']
733 self.assertIn('git://', src_uri, 'This test expects the %s recipe to be a git recipe' % testrecipe)
734 patches = []
735 for entry in src_uri.split():
736 if entry.startswith('file://') and entry.endswith('.patch'):
737 patches.append(entry[7:].split(';')[0])
738 self.assertGreater(len(patches), 0, 'The %s recipe does not appear to contain any patches, so this test will not be effective' % testrecipe)
739 self._check_repo_status(os.path.dirname(recipefile), [])
740 # First, modify a recipe
741 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
742 self.track_for_cleanup(tempdir)
743 self.track_for_cleanup(self.workspacedir)
744 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
745 # (don't bother with cleaning the recipe on teardown, we won't be building it)
746 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
747 # Check git repo
748 self._check_src_repo(tempdir)
749 # Add a couple of commits
750 # FIXME: this only tests adding, need to also test update and remove
751 result = runCmd('echo "# Additional line" >> Makefile.am', cwd=tempdir)
752 result = runCmd('git commit -a -m "Change the Makefile"', cwd=tempdir)
753 result = runCmd('echo "A new file" > devtool-new-file', cwd=tempdir)
754 result = runCmd('git add devtool-new-file', cwd=tempdir)
755 result = runCmd('git commit -m "Add a new file"', cwd=tempdir)
756 self.add_command_to_tearDown('cd %s; rm -rf %s; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
757 result = runCmd('devtool update-recipe -m srcrev %s' % testrecipe)
758 expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile))] + \
759 [(' D', '.*/%s$' % patch) for patch in patches]
760 self._check_repo_status(os.path.dirname(recipefile), expected_status)
761
762 result = runCmd('git diff %s' % os.path.basename(recipefile), cwd=os.path.dirname(recipefile))
763 addlines = ['SRCREV = ".*"', 'SRC_URI = "git://git.infradead.org/mtd-utils.git"']
764 srcurilines = src_uri.split()
765 srcurilines[0] = 'SRC_URI = "' + srcurilines[0]
766 srcurilines.append('"')
767 removelines = ['SRCREV = ".*"'] + srcurilines
768 for line in result.output.splitlines():
769 if line.startswith('+++') or line.startswith('---'):
770 continue
771 elif line.startswith('+'):
772 matched = False
773 for item in addlines:
774 if re.match(item, line[1:].strip()):
775 matched = True
776 break
777 self.assertTrue(matched, 'Unexpected diff add line: %s' % line)
778 elif line.startswith('-'):
779 matched = False
780 for item in removelines:
781 if re.match(item, line[1:].strip()):
782 matched = True
783 break
784 self.assertTrue(matched, 'Unexpected diff remove line: %s' % line)
785 # Now try with auto mode
786 runCmd('cd %s; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, os.path.basename(recipefile)))
787 result = runCmd('devtool update-recipe %s' % testrecipe)
788 result = runCmd('git rev-parse --show-toplevel', cwd=os.path.dirname(recipefile))
789 topleveldir = result.output.strip()
790 relpatchpath = os.path.join(os.path.relpath(os.path.dirname(recipefile), topleveldir), testrecipe)
791 expected_status = [(' M', os.path.relpath(recipefile, topleveldir)),
792 ('??', '%s/0001-Change-the-Makefile.patch' % relpatchpath),
793 ('??', '%s/0002-Add-a-new-file.patch' % relpatchpath)]
794 self._check_repo_status(os.path.dirname(recipefile), expected_status)
795
796 @OETestID(1170)
797 def test_devtool_update_recipe_append(self):
798 # Check preconditions
799 testrecipe = 'mdadm'
800 bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
801 recipefile = bb_vars['FILE']
802 src_uri = bb_vars['SRC_URI']
803 self.assertNotIn('git://', src_uri, 'This test expects the %s recipe to NOT be a git recipe' % testrecipe)
804 self._check_repo_status(os.path.dirname(recipefile), [])
805 # First, modify a recipe
806 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
807 tempsrcdir = os.path.join(tempdir, 'source')
808 templayerdir = os.path.join(tempdir, 'layer')
809 self.track_for_cleanup(tempdir)
810 self.track_for_cleanup(self.workspacedir)
811 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
812 # (don't bother with cleaning the recipe on teardown, we won't be building it)
813 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempsrcdir))
814 # Check git repo
815 self._check_src_repo(tempsrcdir)
816 # Add a commit
817 result = runCmd("sed 's!\\(#define VERSION\\W*\"[^\"]*\\)\"!\\1-custom\"!' -i ReadMe.c", cwd=tempsrcdir)
818 result = runCmd('git commit -a -m "Add our custom version"', cwd=tempsrcdir)
819 self.add_command_to_tearDown('cd %s; rm -f %s/*.patch; git checkout .' % (os.path.dirname(recipefile), testrecipe))
820 # Create a temporary layer and add it to bblayers.conf
821 self._create_temp_layer(templayerdir, True, 'selftestupdaterecipe')
822 # Create the bbappend
823 result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir))
824 self.assertNotIn('WARNING:', result.output)
825 # Check recipe is still clean
826 self._check_repo_status(os.path.dirname(recipefile), [])
827 # Check bbappend was created
828 splitpath = os.path.dirname(recipefile).split(os.sep)
829 appenddir = os.path.join(templayerdir, splitpath[-2], splitpath[-1])
830 bbappendfile = self._check_bbappend(testrecipe, recipefile, appenddir)
831 patchfile = os.path.join(appenddir, testrecipe, '0001-Add-our-custom-version.patch')
832 self.assertExists(patchfile, 'Patch file not created')
833
834 # Check bbappend contents
835 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
836 '\n',
837 'SRC_URI += "file://0001-Add-our-custom-version.patch"\n',
838 '\n']
839 with open(bbappendfile, 'r') as f:
840 self.assertEqual(expectedlines, f.readlines())
841
842 # Check we can run it again and bbappend isn't modified
843 result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir))
844 with open(bbappendfile, 'r') as f:
845 self.assertEqual(expectedlines, f.readlines())
846 # Drop new commit and check patch gets deleted
847 result = runCmd('git reset HEAD^', cwd=tempsrcdir)
848 result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir))
849 self.assertNotExists(patchfile, 'Patch file not deleted')
850 expectedlines2 = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
851 '\n']
852 with open(bbappendfile, 'r') as f:
853 self.assertEqual(expectedlines2, f.readlines())
854 # Put commit back and check we can run it if layer isn't in bblayers.conf
855 os.remove(bbappendfile)
856 result = runCmd('git commit -a -m "Add our custom version"', cwd=tempsrcdir)
857 result = runCmd('bitbake-layers remove-layer %s' % templayerdir, cwd=self.builddir)
858 result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir))
859 self.assertIn('WARNING: Specified layer is not currently enabled in bblayers.conf', result.output)
860 self.assertExists(patchfile, 'Patch file not created (with disabled layer)')
861 with open(bbappendfile, 'r') as f:
862 self.assertEqual(expectedlines, f.readlines())
863 # Deleting isn't expected to work under these circumstances
864
865 @OETestID(1171)
866 def test_devtool_update_recipe_append_git(self):
867 # Check preconditions
868 testrecipe = 'mtd-utils'
869 bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
870 recipefile = bb_vars['FILE']
871 src_uri = bb_vars['SRC_URI']
872 self.assertIn('git://', src_uri, 'This test expects the %s recipe to be a git recipe' % testrecipe)
873 for entry in src_uri.split():
874 if entry.startswith('git://'):
875 git_uri = entry
876 break
877 self._check_repo_status(os.path.dirname(recipefile), [])
878 # First, modify a recipe
879 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
880 tempsrcdir = os.path.join(tempdir, 'source')
881 templayerdir = os.path.join(tempdir, 'layer')
882 self.track_for_cleanup(tempdir)
883 self.track_for_cleanup(self.workspacedir)
884 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
885 # (don't bother with cleaning the recipe on teardown, we won't be building it)
886 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempsrcdir))
887 # Check git repo
888 self._check_src_repo(tempsrcdir)
889 # Add a commit
890 result = runCmd('echo "# Additional line" >> Makefile.am', cwd=tempsrcdir)
891 result = runCmd('git commit -a -m "Change the Makefile"', cwd=tempsrcdir)
892 self.add_command_to_tearDown('cd %s; rm -f %s/*.patch; git checkout .' % (os.path.dirname(recipefile), testrecipe))
893 # Create a temporary layer
894 os.makedirs(os.path.join(templayerdir, 'conf'))
895 with open(os.path.join(templayerdir, 'conf', 'layer.conf'), 'w') as f:
896 f.write('BBPATH .= ":${LAYERDIR}"\n')
897 f.write('BBFILES += "${LAYERDIR}/recipes-*/*/*.bbappend"\n')
898 f.write('BBFILE_COLLECTIONS += "oeselftesttemplayer"\n')
899 f.write('BBFILE_PATTERN_oeselftesttemplayer = "^${LAYERDIR}/"\n')
900 f.write('BBFILE_PRIORITY_oeselftesttemplayer = "999"\n')
901 f.write('BBFILE_PATTERN_IGNORE_EMPTY_oeselftesttemplayer = "1"\n')
Brad Bishop316dfdd2018-06-25 12:45:53 -0400902 f.write('LAYERSERIES_COMPAT_oeselftesttemplayer = "${LAYERSERIES_COMPAT_core}"\n')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500903 self.add_command_to_tearDown('bitbake-layers remove-layer %s || true' % templayerdir)
904 result = runCmd('bitbake-layers add-layer %s' % templayerdir, cwd=self.builddir)
905 # Create the bbappend
906 result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir))
907 self.assertNotIn('WARNING:', result.output)
908 # Check recipe is still clean
909 self._check_repo_status(os.path.dirname(recipefile), [])
910 # Check bbappend was created
911 splitpath = os.path.dirname(recipefile).split(os.sep)
912 appenddir = os.path.join(templayerdir, splitpath[-2], splitpath[-1])
913 bbappendfile = self._check_bbappend(testrecipe, recipefile, appenddir)
914 self.assertNotExists(os.path.join(appenddir, testrecipe), 'Patch directory should not be created')
915
916 # Check bbappend contents
917 result = runCmd('git rev-parse HEAD', cwd=tempsrcdir)
918 expectedlines = set(['SRCREV = "%s"\n' % result.output,
919 '\n',
920 'SRC_URI = "%s"\n' % git_uri,
921 '\n'])
922 with open(bbappendfile, 'r') as f:
923 self.assertEqual(expectedlines, set(f.readlines()))
924
925 # Check we can run it again and bbappend isn't modified
926 result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir))
927 with open(bbappendfile, 'r') as f:
928 self.assertEqual(expectedlines, set(f.readlines()))
929 # Drop new commit and check SRCREV changes
930 result = runCmd('git reset HEAD^', cwd=tempsrcdir)
931 result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir))
932 self.assertNotExists(os.path.join(appenddir, testrecipe), 'Patch directory should not be created')
933 result = runCmd('git rev-parse HEAD', cwd=tempsrcdir)
934 expectedlines = set(['SRCREV = "%s"\n' % result.output,
935 '\n',
936 'SRC_URI = "%s"\n' % git_uri,
937 '\n'])
938 with open(bbappendfile, 'r') as f:
939 self.assertEqual(expectedlines, set(f.readlines()))
940 # Put commit back and check we can run it if layer isn't in bblayers.conf
941 os.remove(bbappendfile)
942 result = runCmd('git commit -a -m "Change the Makefile"', cwd=tempsrcdir)
943 result = runCmd('bitbake-layers remove-layer %s' % templayerdir, cwd=self.builddir)
944 result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir))
945 self.assertIn('WARNING: Specified layer is not currently enabled in bblayers.conf', result.output)
946 self.assertNotExists(os.path.join(appenddir, testrecipe), 'Patch directory should not be created')
947 result = runCmd('git rev-parse HEAD', cwd=tempsrcdir)
948 expectedlines = set(['SRCREV = "%s"\n' % result.output,
949 '\n',
950 'SRC_URI = "%s"\n' % git_uri,
951 '\n'])
952 with open(bbappendfile, 'r') as f:
953 self.assertEqual(expectedlines, set(f.readlines()))
954 # Deleting isn't expected to work under these circumstances
955
956 @OETestID(1370)
957 def test_devtool_update_recipe_local_files(self):
958 """Check that local source files are copied over instead of patched"""
959 testrecipe = 'makedevs'
960 recipefile = get_bb_var('FILE', testrecipe)
961 # Setup srctree for modifying the recipe
962 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
963 self.track_for_cleanup(tempdir)
964 self.track_for_cleanup(self.workspacedir)
965 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
966 # (don't bother with cleaning the recipe on teardown, we won't be
967 # building it)
968 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
969 # Check git repo
970 self._check_src_repo(tempdir)
971 # Try building just to ensure we haven't broken that
972 bitbake("%s" % testrecipe)
973 # Edit / commit local source
974 runCmd('echo "/* Foobar */" >> oe-local-files/makedevs.c', cwd=tempdir)
975 runCmd('echo "Foo" > oe-local-files/new-local', cwd=tempdir)
976 runCmd('echo "Bar" > new-file', cwd=tempdir)
977 runCmd('git add new-file', cwd=tempdir)
978 runCmd('git commit -m "Add new file"', cwd=tempdir)
979 self.add_command_to_tearDown('cd %s; git clean -fd .; git checkout .' %
980 os.path.dirname(recipefile))
981 runCmd('devtool update-recipe %s' % testrecipe)
982 expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)),
983 (' M', '.*/makedevs/makedevs.c$'),
984 ('??', '.*/makedevs/new-local$'),
985 ('??', '.*/makedevs/0001-Add-new-file.patch$')]
986 self._check_repo_status(os.path.dirname(recipefile), expected_status)
987
988 @OETestID(1371)
989 def test_devtool_update_recipe_local_files_2(self):
990 """Check local source files support when oe-local-files is in Git"""
Brad Bishop316dfdd2018-06-25 12:45:53 -0400991 testrecipe = 'devtool-test-local'
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500992 recipefile = get_bb_var('FILE', testrecipe)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400993 recipedir = os.path.dirname(recipefile)
994 result = runCmd('git status --porcelain .', cwd=recipedir)
995 if result.output.strip():
996 self.fail('Recipe directory for %s contains uncommitted changes' % testrecipe)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500997 # Setup srctree for modifying the recipe
998 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
999 self.track_for_cleanup(tempdir)
1000 self.track_for_cleanup(self.workspacedir)
1001 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1002 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
1003 # Check git repo
1004 self._check_src_repo(tempdir)
1005 # Add oe-local-files to Git
1006 runCmd('rm oe-local-files/.gitignore', cwd=tempdir)
1007 runCmd('git add oe-local-files', cwd=tempdir)
1008 runCmd('git commit -m "Add local sources"', cwd=tempdir)
1009 # Edit / commit local sources
Brad Bishop316dfdd2018-06-25 12:45:53 -04001010 runCmd('echo "# Foobar" >> oe-local-files/file1', cwd=tempdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001011 runCmd('git commit -am "Edit existing file"', cwd=tempdir)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001012 runCmd('git rm oe-local-files/file2', cwd=tempdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001013 runCmd('git commit -m"Remove file"', cwd=tempdir)
1014 runCmd('echo "Foo" > oe-local-files/new-local', cwd=tempdir)
1015 runCmd('git add oe-local-files/new-local', cwd=tempdir)
1016 runCmd('git commit -m "Add new local file"', cwd=tempdir)
1017 runCmd('echo "Gar" > new-file', cwd=tempdir)
1018 runCmd('git add new-file', cwd=tempdir)
1019 runCmd('git commit -m "Add new file"', cwd=tempdir)
1020 self.add_command_to_tearDown('cd %s; git clean -fd .; git checkout .' %
1021 os.path.dirname(recipefile))
1022 # Checkout unmodified file to working copy -> devtool should still pick
1023 # the modified version from HEAD
Brad Bishop316dfdd2018-06-25 12:45:53 -04001024 runCmd('git checkout HEAD^ -- oe-local-files/file1', cwd=tempdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001025 runCmd('devtool update-recipe %s' % testrecipe)
1026 expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)),
Brad Bishop316dfdd2018-06-25 12:45:53 -04001027 (' M', '.*/file1$'),
1028 (' D', '.*/file2$'),
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001029 ('??', '.*/new-local$'),
1030 ('??', '.*/0001-Add-new-file.patch$')]
1031 self._check_repo_status(os.path.dirname(recipefile), expected_status)
1032
1033 @OETestID(1627)
1034 def test_devtool_update_recipe_local_files_3(self):
1035 # First, modify the recipe
1036 testrecipe = 'devtool-test-localonly'
1037 bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
1038 recipefile = bb_vars['FILE']
1039 src_uri = bb_vars['SRC_URI']
1040 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1041 self.track_for_cleanup(tempdir)
1042 self.track_for_cleanup(self.workspacedir)
1043 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1044 # (don't bother with cleaning the recipe on teardown, we won't be building it)
1045 result = runCmd('devtool modify %s' % testrecipe)
1046 # Modify one file
1047 runCmd('echo "Another line" >> file2', cwd=os.path.join(self.workspacedir, 'sources', testrecipe, 'oe-local-files'))
1048 self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
1049 result = runCmd('devtool update-recipe %s' % testrecipe)
1050 expected_status = [(' M', '.*/%s/file2$' % testrecipe)]
1051 self._check_repo_status(os.path.dirname(recipefile), expected_status)
1052
1053 @OETestID(1629)
1054 def test_devtool_update_recipe_local_patch_gz(self):
1055 # First, modify the recipe
1056 testrecipe = 'devtool-test-patch-gz'
1057 if get_bb_var('DISTRO') == 'poky-tiny':
1058 self.skipTest("The DISTRO 'poky-tiny' does not provide the dependencies needed by %s" % testrecipe)
1059 bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
1060 recipefile = bb_vars['FILE']
1061 src_uri = bb_vars['SRC_URI']
1062 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1063 self.track_for_cleanup(tempdir)
1064 self.track_for_cleanup(self.workspacedir)
1065 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1066 # (don't bother with cleaning the recipe on teardown, we won't be building it)
1067 result = runCmd('devtool modify %s' % testrecipe)
1068 # Modify one file
1069 srctree = os.path.join(self.workspacedir, 'sources', testrecipe)
1070 runCmd('echo "Another line" >> README', cwd=srctree)
1071 runCmd('git commit -a --amend --no-edit', cwd=srctree)
1072 self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
1073 result = runCmd('devtool update-recipe %s' % testrecipe)
1074 expected_status = [(' M', '.*/%s/readme.patch.gz$' % testrecipe)]
1075 self._check_repo_status(os.path.dirname(recipefile), expected_status)
1076 patch_gz = os.path.join(os.path.dirname(recipefile), testrecipe, 'readme.patch.gz')
1077 result = runCmd('file %s' % patch_gz)
1078 if 'gzip compressed data' not in result.output:
1079 self.fail('New patch file is not gzipped - file reports:\n%s' % result.output)
1080
1081 @OETestID(1628)
1082 def test_devtool_update_recipe_local_files_subdir(self):
1083 # Try devtool update-recipe on a recipe that has a file with subdir= set in
1084 # SRC_URI such that it overwrites a file that was in an archive that
1085 # was also in SRC_URI
1086 # First, modify the recipe
1087 testrecipe = 'devtool-test-subdir'
1088 bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
1089 recipefile = bb_vars['FILE']
1090 src_uri = bb_vars['SRC_URI']
1091 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1092 self.track_for_cleanup(tempdir)
1093 self.track_for_cleanup(self.workspacedir)
1094 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1095 # (don't bother with cleaning the recipe on teardown, we won't be building it)
1096 result = runCmd('devtool modify %s' % testrecipe)
1097 testfile = os.path.join(self.workspacedir, 'sources', testrecipe, 'testfile')
1098 self.assertExists(testfile, 'Extracted source could not be found')
1099 with open(testfile, 'r') as f:
1100 contents = f.read().rstrip()
1101 self.assertEqual(contents, 'Modified version', 'File has apparently not been overwritten as it should have been')
1102 # Test devtool update-recipe without modifying any files
1103 self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
1104 result = runCmd('devtool update-recipe %s' % testrecipe)
1105 expected_status = []
1106 self._check_repo_status(os.path.dirname(recipefile), expected_status)
1107
1108 @OETestID(1163)
1109 def test_devtool_extract(self):
1110 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1111 # Try devtool extract
1112 self.track_for_cleanup(tempdir)
1113 self.track_for_cleanup(self.workspacedir)
1114 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1115 result = runCmd('devtool extract matchbox-terminal %s' % tempdir)
1116 self.assertExists(os.path.join(tempdir, 'Makefile.am'), 'Extracted source could not be found')
1117 self._check_src_repo(tempdir)
1118
1119 @OETestID(1379)
1120 def test_devtool_extract_virtual(self):
1121 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1122 # Try devtool extract
1123 self.track_for_cleanup(tempdir)
1124 self.track_for_cleanup(self.workspacedir)
1125 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1126 result = runCmd('devtool extract virtual/make %s' % tempdir)
1127 self.assertExists(os.path.join(tempdir, 'Makefile.am'), 'Extracted source could not be found')
1128 self._check_src_repo(tempdir)
1129
1130 @OETestID(1168)
1131 def test_devtool_reset_all(self):
1132 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1133 self.track_for_cleanup(tempdir)
1134 self.track_for_cleanup(self.workspacedir)
1135 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1136 testrecipe1 = 'mdadm'
1137 testrecipe2 = 'cronie'
1138 result = runCmd('devtool modify -x %s %s' % (testrecipe1, os.path.join(tempdir, testrecipe1)))
1139 result = runCmd('devtool modify -x %s %s' % (testrecipe2, os.path.join(tempdir, testrecipe2)))
1140 result = runCmd('devtool build %s' % testrecipe1)
1141 result = runCmd('devtool build %s' % testrecipe2)
1142 stampprefix1 = get_bb_var('STAMP', testrecipe1)
1143 self.assertTrue(stampprefix1, 'Unable to get STAMP value for recipe %s' % testrecipe1)
1144 stampprefix2 = get_bb_var('STAMP', testrecipe2)
1145 self.assertTrue(stampprefix2, 'Unable to get STAMP value for recipe %s' % testrecipe2)
1146 result = runCmd('devtool reset -a')
1147 self.assertIn(testrecipe1, result.output)
1148 self.assertIn(testrecipe2, result.output)
1149 result = runCmd('devtool status')
1150 self.assertNotIn(testrecipe1, result.output)
1151 self.assertNotIn(testrecipe2, result.output)
1152 matches1 = glob.glob(stampprefix1 + '*')
1153 self.assertFalse(matches1, 'Stamp files exist for recipe %s that should have been cleaned' % testrecipe1)
1154 matches2 = glob.glob(stampprefix2 + '*')
1155 self.assertFalse(matches2, 'Stamp files exist for recipe %s that should have been cleaned' % testrecipe2)
1156
1157 @OETestID(1272)
1158 def test_devtool_deploy_target(self):
1159 # NOTE: Whilst this test would seemingly be better placed as a runtime test,
1160 # unfortunately the runtime tests run under bitbake and you can't run
1161 # devtool within bitbake (since devtool needs to run bitbake itself).
1162 # Additionally we are testing build-time functionality as well, so
1163 # really this has to be done as an oe-selftest test.
1164 #
1165 # Check preconditions
1166 machine = get_bb_var('MACHINE')
1167 if not machine.startswith('qemu'):
1168 self.skipTest('This test only works with qemu machines')
1169 if not os.path.exists('/etc/runqemu-nosudo'):
1170 self.skipTest('You must set up tap devices with scripts/runqemu-gen-tapdevs before running this test')
1171 result = runCmd('PATH="$PATH:/sbin:/usr/sbin" ip tuntap show', ignore_status=True)
1172 if result.status != 0:
1173 result = runCmd('PATH="$PATH:/sbin:/usr/sbin" ifconfig -a', ignore_status=True)
1174 if result.status != 0:
1175 self.skipTest('Failed to determine if tap devices exist with ifconfig or ip: %s' % result.output)
1176 for line in result.output.splitlines():
1177 if line.startswith('tap'):
1178 break
1179 else:
1180 self.skipTest('No tap devices found - you must set up tap devices with scripts/runqemu-gen-tapdevs before running this test')
1181 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1182 # Definitions
1183 testrecipe = 'mdadm'
1184 testfile = '/sbin/mdadm'
1185 testimage = 'oe-selftest-image'
1186 testcommand = '/sbin/mdadm --help'
1187 # Build an image to run
1188 bitbake("%s qemu-native qemu-helper-native" % testimage)
1189 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
1190 self.add_command_to_tearDown('bitbake -c clean %s' % testimage)
1191 self.add_command_to_tearDown('rm -f %s/%s*' % (deploy_dir_image, testimage))
1192 # Clean recipe so the first deploy will fail
1193 bitbake("%s -c clean" % testrecipe)
1194 # Try devtool modify
1195 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1196 self.track_for_cleanup(tempdir)
1197 self.track_for_cleanup(self.workspacedir)
1198 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1199 self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
1200 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
1201 # Test that deploy-target at this point fails (properly)
1202 result = runCmd('devtool deploy-target -n %s root@localhost' % testrecipe, ignore_status=True)
1203 self.assertNotEqual(result.output, 0, 'devtool deploy-target should have failed, output: %s' % result.output)
1204 self.assertNotIn(result.output, 'Traceback', 'devtool deploy-target should have failed with a proper error not a traceback, output: %s' % result.output)
1205 result = runCmd('devtool build %s' % testrecipe)
1206 # First try a dry-run of deploy-target
1207 result = runCmd('devtool deploy-target -n %s root@localhost' % testrecipe)
1208 self.assertIn(' %s' % testfile, result.output)
1209 # Boot the image
1210 with runqemu(testimage) as qemu:
1211 # Now really test deploy-target
1212 result = runCmd('devtool deploy-target -c %s root@%s' % (testrecipe, qemu.ip))
1213 # Run a test command to see if it was installed properly
1214 sshargs = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
1215 result = runCmd('ssh %s root@%s %s' % (sshargs, qemu.ip, testcommand))
1216 # Check if it deployed all of the files with the right ownership/perms
1217 # First look on the host - need to do this under pseudo to get the correct ownership/perms
1218 bb_vars = get_bb_vars(['D', 'FAKEROOTENV', 'FAKEROOTCMD'], testrecipe)
1219 installdir = bb_vars['D']
1220 fakerootenv = bb_vars['FAKEROOTENV']
1221 fakerootcmd = bb_vars['FAKEROOTCMD']
1222 result = runCmd('%s %s find . -type f -exec ls -l {} \;' % (fakerootenv, fakerootcmd), cwd=installdir)
1223 filelist1 = self._process_ls_output(result.output)
1224
1225 # Now look on the target
1226 tempdir2 = tempfile.mkdtemp(prefix='devtoolqa')
1227 self.track_for_cleanup(tempdir2)
1228 tmpfilelist = os.path.join(tempdir2, 'files.txt')
1229 with open(tmpfilelist, 'w') as f:
1230 for line in filelist1:
1231 splitline = line.split()
1232 f.write(splitline[-1] + '\n')
1233 result = runCmd('cat %s | ssh -q %s root@%s \'xargs ls -l\'' % (tmpfilelist, sshargs, qemu.ip))
1234 filelist2 = self._process_ls_output(result.output)
1235 filelist1.sort(key=lambda item: item.split()[-1])
1236 filelist2.sort(key=lambda item: item.split()[-1])
1237 self.assertEqual(filelist1, filelist2)
1238 # Test undeploy-target
1239 result = runCmd('devtool undeploy-target -c %s root@%s' % (testrecipe, qemu.ip))
1240 result = runCmd('ssh %s root@%s %s' % (sshargs, qemu.ip, testcommand), ignore_status=True)
1241 self.assertNotEqual(result, 0, 'undeploy-target did not remove command as it should have')
1242
1243 @OETestID(1366)
1244 def test_devtool_build_image(self):
1245 """Test devtool build-image plugin"""
1246 # Check preconditions
1247 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1248 image = 'core-image-minimal'
1249 self.track_for_cleanup(self.workspacedir)
1250 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1251 self.add_command_to_tearDown('bitbake -c clean %s' % image)
1252 bitbake('%s -c clean' % image)
1253 # Add target and native recipes to workspace
1254 recipes = ['mdadm', 'parted-native']
1255 for recipe in recipes:
1256 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1257 self.track_for_cleanup(tempdir)
1258 self.add_command_to_tearDown('bitbake -c clean %s' % recipe)
1259 runCmd('devtool modify %s -x %s' % (recipe, tempdir))
1260 # Try to build image
1261 result = runCmd('devtool build-image %s' % image)
1262 self.assertNotEqual(result, 0, 'devtool build-image failed')
1263 # Check if image contains expected packages
1264 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
1265 image_link_name = get_bb_var('IMAGE_LINK_NAME', image)
1266 reqpkgs = [item for item in recipes if not item.endswith('-native')]
1267 with open(os.path.join(deploy_dir_image, image_link_name + '.manifest'), 'r') as f:
1268 for line in f:
1269 splitval = line.split()
1270 if splitval:
1271 pkg = splitval[0]
1272 if pkg in reqpkgs:
1273 reqpkgs.remove(pkg)
1274 if reqpkgs:
1275 self.fail('The following packages were not present in the image as expected: %s' % ', '.join(reqpkgs))
1276
1277 @OETestID(1367)
1278 def test_devtool_upgrade(self):
1279 # Check preconditions
1280 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1281 self.track_for_cleanup(self.workspacedir)
1282 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1283 # Check parameters
1284 result = runCmd('devtool upgrade -h')
1285 for param in 'recipename srctree --version -V --branch -b --keep-temp --no-patch'.split():
1286 self.assertIn(param, result.output)
1287 # For the moment, we are using a real recipe.
1288 recipe = 'devtool-upgrade-test1'
1289 version = '1.6.0'
1290 oldrecipefile = get_bb_var('FILE', recipe)
1291 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1292 self.track_for_cleanup(tempdir)
1293 # Check that recipe is not already under devtool control
1294 result = runCmd('devtool status')
1295 self.assertNotIn(recipe, result.output)
1296 # Check upgrade. Code does not check if new PV is older or newer that current PV, so, it may be that
1297 # we are downgrading instead of upgrading.
1298 result = runCmd('devtool upgrade %s %s -V %s' % (recipe, tempdir, version))
1299 # Check if srctree at least is populated
1300 self.assertTrue(len(os.listdir(tempdir)) > 0, 'srctree (%s) should be populated with new (%s) source code' % (tempdir, version))
1301 # Check new recipe subdirectory is present
1302 self.assertExists(os.path.join(self.workspacedir, 'recipes', recipe, '%s-%s' % (recipe, version)), 'Recipe folder should exist')
1303 # Check new recipe file is present
1304 newrecipefile = os.path.join(self.workspacedir, 'recipes', recipe, '%s_%s.bb' % (recipe, version))
1305 self.assertExists(newrecipefile, 'Recipe file should exist after upgrade')
1306 # Check devtool status and make sure recipe is present
1307 result = runCmd('devtool status')
1308 self.assertIn(recipe, result.output)
1309 self.assertIn(tempdir, result.output)
1310 # Check recipe got changed as expected
1311 with open(oldrecipefile + '.upgraded', 'r') as f:
1312 desiredlines = f.readlines()
1313 with open(newrecipefile, 'r') as f:
1314 newlines = f.readlines()
1315 self.assertEqual(desiredlines, newlines)
1316 # Check devtool reset recipe
1317 result = runCmd('devtool reset %s -n' % recipe)
1318 result = runCmd('devtool status')
1319 self.assertNotIn(recipe, result.output)
1320 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after resetting')
1321
1322 @OETestID(1433)
1323 def test_devtool_upgrade_git(self):
1324 # Check preconditions
1325 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1326 self.track_for_cleanup(self.workspacedir)
1327 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1328 recipe = 'devtool-upgrade-test2'
1329 commit = '6cc6077a36fe2648a5f993fe7c16c9632f946517'
1330 oldrecipefile = get_bb_var('FILE', recipe)
1331 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1332 self.track_for_cleanup(tempdir)
1333 # Check that recipe is not already under devtool control
1334 result = runCmd('devtool status')
1335 self.assertNotIn(recipe, result.output)
1336 # Check upgrade
1337 result = runCmd('devtool upgrade %s %s -S %s' % (recipe, tempdir, commit))
1338 # Check if srctree at least is populated
1339 self.assertTrue(len(os.listdir(tempdir)) > 0, 'srctree (%s) should be populated with new (%s) source code' % (tempdir, commit))
1340 # Check new recipe file is present
1341 newrecipefile = os.path.join(self.workspacedir, 'recipes', recipe, os.path.basename(oldrecipefile))
1342 self.assertExists(newrecipefile, 'Recipe file should exist after upgrade')
1343 # Check devtool status and make sure recipe is present
1344 result = runCmd('devtool status')
1345 self.assertIn(recipe, result.output)
1346 self.assertIn(tempdir, result.output)
1347 # Check recipe got changed as expected
1348 with open(oldrecipefile + '.upgraded', 'r') as f:
1349 desiredlines = f.readlines()
1350 with open(newrecipefile, 'r') as f:
1351 newlines = f.readlines()
1352 self.assertEqual(desiredlines, newlines)
1353 # Check devtool reset recipe
1354 result = runCmd('devtool reset %s -n' % recipe)
1355 result = runCmd('devtool status')
1356 self.assertNotIn(recipe, result.output)
1357 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after resetting')
1358
1359 @OETestID(1352)
1360 def test_devtool_layer_plugins(self):
1361 """Test that devtool can use plugins from other layers.
1362
1363 This test executes the selftest-reverse command from meta-selftest."""
1364
1365 self.track_for_cleanup(self.workspacedir)
1366 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1367
1368 s = "Microsoft Made No Profit From Anyone's Zunes Yo"
1369 result = runCmd("devtool --quiet selftest-reverse \"%s\"" % s)
1370 self.assertEqual(result.output, s[::-1])
1371
1372 def _copy_file_with_cleanup(self, srcfile, basedstdir, *paths):
1373 dstdir = basedstdir
1374 self.assertExists(dstdir)
1375 for p in paths:
1376 dstdir = os.path.join(dstdir, p)
1377 if not os.path.exists(dstdir):
1378 os.makedirs(dstdir)
1379 self.track_for_cleanup(dstdir)
1380 dstfile = os.path.join(dstdir, os.path.basename(srcfile))
1381 if srcfile != dstfile:
1382 shutil.copy(srcfile, dstfile)
1383 self.track_for_cleanup(dstfile)
1384
1385 @OETestID(1625)
1386 def test_devtool_load_plugin(self):
1387 """Test that devtool loads only the first found plugin in BBPATH."""
1388
1389 self.track_for_cleanup(self.workspacedir)
1390 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1391
1392 devtool = runCmd("which devtool")
1393 fromname = runCmd("devtool --quiet pluginfile")
1394 srcfile = fromname.output
1395 bbpath = get_bb_var('BBPATH')
1396 searchpath = bbpath.split(':') + [os.path.dirname(devtool.output)]
1397 plugincontent = []
1398 with open(srcfile) as fh:
1399 plugincontent = fh.readlines()
1400 try:
1401 self.assertIn('meta-selftest', srcfile, 'wrong bbpath plugin found')
1402 for path in searchpath:
1403 self._copy_file_with_cleanup(srcfile, path, 'lib', 'devtool')
1404 result = runCmd("devtool --quiet count")
1405 self.assertEqual(result.output, '1')
1406 result = runCmd("devtool --quiet multiloaded")
1407 self.assertEqual(result.output, "no")
1408 for path in searchpath:
1409 result = runCmd("devtool --quiet bbdir")
1410 self.assertEqual(result.output, path)
1411 os.unlink(os.path.join(result.output, 'lib', 'devtool', 'bbpath.py'))
1412 finally:
1413 with open(srcfile, 'w') as fh:
1414 fh.writelines(plugincontent)
1415
1416 def _setup_test_devtool_finish_upgrade(self):
1417 # Check preconditions
1418 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1419 self.track_for_cleanup(self.workspacedir)
1420 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1421 # Use a "real" recipe from meta-selftest
1422 recipe = 'devtool-upgrade-test1'
1423 oldversion = '1.5.3'
1424 newversion = '1.6.0'
1425 oldrecipefile = get_bb_var('FILE', recipe)
1426 recipedir = os.path.dirname(oldrecipefile)
1427 result = runCmd('git status --porcelain .', cwd=recipedir)
1428 if result.output.strip():
1429 self.fail('Recipe directory for %s contains uncommitted changes' % recipe)
1430 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1431 self.track_for_cleanup(tempdir)
1432 # Check that recipe is not already under devtool control
1433 result = runCmd('devtool status')
1434 self.assertNotIn(recipe, result.output)
1435 # Do the upgrade
1436 result = runCmd('devtool upgrade %s %s -V %s' % (recipe, tempdir, newversion))
1437 # Check devtool status and make sure recipe is present
1438 result = runCmd('devtool status')
1439 self.assertIn(recipe, result.output)
1440 self.assertIn(tempdir, result.output)
1441 # Make a change to the source
1442 result = runCmd('sed -i \'/^#include "pv.h"/a \\/* Here is a new comment *\\/\' src/pv/number.c', cwd=tempdir)
1443 result = runCmd('git status --porcelain', cwd=tempdir)
1444 self.assertIn('M src/pv/number.c', result.output)
1445 result = runCmd('git commit src/pv/number.c -m "Add a comment to the code"', cwd=tempdir)
1446 # Check if patch is there
1447 recipedir = os.path.dirname(oldrecipefile)
1448 olddir = os.path.join(recipedir, recipe + '-' + oldversion)
1449 patchfn = '0001-Add-a-note-line-to-the-quick-reference.patch'
1450 self.assertExists(os.path.join(olddir, patchfn), 'Original patch file does not exist')
1451 return recipe, oldrecipefile, recipedir, olddir, newversion, patchfn
1452
1453 @OETestID(1623)
1454 def test_devtool_finish_upgrade_origlayer(self):
1455 recipe, oldrecipefile, recipedir, olddir, newversion, patchfn = self._setup_test_devtool_finish_upgrade()
1456 # Ensure the recipe is where we think it should be (so that cleanup doesn't trash things)
1457 self.assertIn('/meta-selftest/', recipedir)
1458 # Try finish to the original layer
1459 self.add_command_to_tearDown('rm -rf %s ; cd %s ; git checkout %s' % (recipedir, os.path.dirname(recipedir), recipedir))
1460 result = runCmd('devtool finish %s meta-selftest' % recipe)
1461 result = runCmd('devtool status')
1462 self.assertNotIn(recipe, result.output, 'Recipe should have been reset by finish but wasn\'t')
1463 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish')
1464 self.assertNotExists(oldrecipefile, 'Old recipe file should have been deleted but wasn\'t')
1465 self.assertNotExists(os.path.join(olddir, patchfn), 'Old patch file should have been deleted but wasn\'t')
1466 newrecipefile = os.path.join(recipedir, '%s_%s.bb' % (recipe, newversion))
1467 newdir = os.path.join(recipedir, recipe + '-' + newversion)
1468 self.assertExists(newrecipefile, 'New recipe file should have been copied into existing layer but wasn\'t')
1469 self.assertExists(os.path.join(newdir, patchfn), 'Patch file should have been copied into new directory but wasn\'t')
1470 self.assertExists(os.path.join(newdir, '0002-Add-a-comment-to-the-code.patch'), 'New patch file should have been created but wasn\'t')
1471
1472 @OETestID(1624)
1473 def test_devtool_finish_upgrade_otherlayer(self):
1474 recipe, oldrecipefile, recipedir, olddir, newversion, patchfn = self._setup_test_devtool_finish_upgrade()
1475 # Ensure the recipe is where we think it should be (so that cleanup doesn't trash things)
1476 self.assertIn('/meta-selftest/', recipedir)
1477 # Try finish to a different layer - should create a bbappend
1478 # This cleanup isn't strictly necessary but do it anyway just in case it goes wrong and writes to here
1479 self.add_command_to_tearDown('rm -rf %s ; cd %s ; git checkout %s' % (recipedir, os.path.dirname(recipedir), recipedir))
1480 oe_core_dir = os.path.join(get_bb_var('COREBASE'), 'meta')
1481 newrecipedir = os.path.join(oe_core_dir, 'recipes-test', 'devtool')
1482 newrecipefile = os.path.join(newrecipedir, '%s_%s.bb' % (recipe, newversion))
1483 self.track_for_cleanup(newrecipedir)
1484 result = runCmd('devtool finish %s oe-core' % recipe)
1485 result = runCmd('devtool status')
1486 self.assertNotIn(recipe, result.output, 'Recipe should have been reset by finish but wasn\'t')
1487 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish')
1488 self.assertExists(oldrecipefile, 'Old recipe file should not have been deleted')
1489 self.assertExists(os.path.join(olddir, patchfn), 'Old patch file should not have been deleted')
1490 newdir = os.path.join(newrecipedir, recipe + '-' + newversion)
1491 self.assertExists(newrecipefile, 'New recipe file should have been copied into existing layer but wasn\'t')
1492 self.assertExists(os.path.join(newdir, patchfn), 'Patch file should have been copied into new directory but wasn\'t')
1493 self.assertExists(os.path.join(newdir, '0002-Add-a-comment-to-the-code.patch'), 'New patch file should have been created but wasn\'t')
1494
1495 def _setup_test_devtool_finish_modify(self):
1496 # Check preconditions
1497 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1498 # Try modifying a recipe
1499 self.track_for_cleanup(self.workspacedir)
1500 recipe = 'mdadm'
1501 oldrecipefile = get_bb_var('FILE', recipe)
1502 recipedir = os.path.dirname(oldrecipefile)
1503 result = runCmd('git status --porcelain .', cwd=recipedir)
1504 if result.output.strip():
1505 self.fail('Recipe directory for %s contains uncommitted changes' % recipe)
1506 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1507 self.track_for_cleanup(tempdir)
1508 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1509 result = runCmd('devtool modify %s %s' % (recipe, tempdir))
1510 self.assertExists(os.path.join(tempdir, 'Makefile'), 'Extracted source could not be found')
1511 # Test devtool status
1512 result = runCmd('devtool status')
1513 self.assertIn(recipe, result.output)
1514 self.assertIn(tempdir, result.output)
1515 # Make a change to the source
1516 result = runCmd('sed -i \'/^#include "mdadm.h"/a \\/* Here is a new comment *\\/\' maps.c', cwd=tempdir)
1517 result = runCmd('git status --porcelain', cwd=tempdir)
1518 self.assertIn('M maps.c', result.output)
1519 result = runCmd('git commit maps.c -m "Add a comment to the code"', cwd=tempdir)
1520 for entry in os.listdir(recipedir):
1521 filesdir = os.path.join(recipedir, entry)
1522 if os.path.isdir(filesdir):
1523 break
1524 else:
1525 self.fail('Unable to find recipe files directory for %s' % recipe)
1526 return recipe, oldrecipefile, recipedir, filesdir
1527
1528 @OETestID(1621)
1529 def test_devtool_finish_modify_origlayer(self):
1530 recipe, oldrecipefile, recipedir, filesdir = self._setup_test_devtool_finish_modify()
1531 # Ensure the recipe is where we think it should be (so that cleanup doesn't trash things)
1532 self.assertIn('/meta/', recipedir)
1533 # Try finish to the original layer
1534 self.add_command_to_tearDown('rm -rf %s ; cd %s ; git checkout %s' % (recipedir, os.path.dirname(recipedir), recipedir))
1535 result = runCmd('devtool finish %s meta' % recipe)
1536 result = runCmd('devtool status')
1537 self.assertNotIn(recipe, result.output, 'Recipe should have been reset by finish but wasn\'t')
1538 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish')
1539 expected_status = [(' M', '.*/%s$' % os.path.basename(oldrecipefile)),
1540 ('??', '.*/.*-Add-a-comment-to-the-code.patch$')]
1541 self._check_repo_status(recipedir, expected_status)
1542
1543 @OETestID(1622)
1544 def test_devtool_finish_modify_otherlayer(self):
1545 recipe, oldrecipefile, recipedir, filesdir = self._setup_test_devtool_finish_modify()
1546 # Ensure the recipe is where we think it should be (so that cleanup doesn't trash things)
1547 self.assertIn('/meta/', recipedir)
1548 relpth = os.path.relpath(recipedir, os.path.join(get_bb_var('COREBASE'), 'meta'))
1549 appenddir = os.path.join(get_test_layer(), relpth)
1550 self.track_for_cleanup(appenddir)
1551 # Try finish to the original layer
1552 self.add_command_to_tearDown('rm -rf %s ; cd %s ; git checkout %s' % (recipedir, os.path.dirname(recipedir), recipedir))
1553 result = runCmd('devtool finish %s meta-selftest' % recipe)
1554 result = runCmd('devtool status')
1555 self.assertNotIn(recipe, result.output, 'Recipe should have been reset by finish but wasn\'t')
1556 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish')
1557 result = runCmd('git status --porcelain .', cwd=recipedir)
1558 if result.output.strip():
1559 self.fail('Recipe directory for %s contains the following unexpected changes after finish:\n%s' % (recipe, result.output.strip()))
1560 recipefn = os.path.splitext(os.path.basename(oldrecipefile))[0]
1561 recipefn = recipefn.split('_')[0] + '_%'
1562 appendfile = os.path.join(appenddir, recipefn + '.bbappend')
1563 self.assertExists(appendfile, 'bbappend %s should have been created but wasn\'t' % appendfile)
1564 newdir = os.path.join(appenddir, recipe)
1565 files = os.listdir(newdir)
1566 foundpatch = None
1567 for fn in files:
1568 if fnmatch.fnmatch(fn, '*-Add-a-comment-to-the-code.patch'):
1569 foundpatch = fn
1570 if not foundpatch:
1571 self.fail('No patch file created next to bbappend')
1572 files.remove(foundpatch)
1573 if files:
1574 self.fail('Unexpected file(s) copied next to bbappend: %s' % ', '.join(files))
1575
1576 @OETestID(1626)
1577 def test_devtool_rename(self):
1578 # Check preconditions
1579 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1580 self.track_for_cleanup(self.workspacedir)
1581 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1582
1583 # First run devtool add
1584 # We already have this recipe in OE-Core, but that doesn't matter
1585 recipename = 'i2c-tools'
1586 recipever = '3.1.2'
1587 recipefile = os.path.join(self.workspacedir, 'recipes', recipename, '%s_%s.bb' % (recipename, recipever))
1588 url = 'http://downloads.yoctoproject.org/mirror/sources/i2c-tools-%s.tar.bz2' % recipever
1589 def add_recipe():
1590 result = runCmd('devtool add %s' % url)
1591 self.assertExists(recipefile, 'Expected recipe file not created')
1592 self.assertExists(os.path.join(self.workspacedir, 'sources', recipename), 'Source directory not created')
1593 checkvars = {}
1594 checkvars['S'] = None
1595 checkvars['SRC_URI'] = url.replace(recipever, '${PV}')
1596 self._test_recipe_contents(recipefile, checkvars, [])
1597 add_recipe()
1598 # Now rename it - change both name and version
1599 newrecipename = 'mynewrecipe'
1600 newrecipever = '456'
1601 newrecipefile = os.path.join(self.workspacedir, 'recipes', newrecipename, '%s_%s.bb' % (newrecipename, newrecipever))
1602 result = runCmd('devtool rename %s %s -V %s' % (recipename, newrecipename, newrecipever))
1603 self.assertExists(newrecipefile, 'Recipe file not renamed')
1604 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipename), 'Old recipe directory still exists')
1605 newsrctree = os.path.join(self.workspacedir, 'sources', newrecipename)
1606 self.assertExists(newsrctree, 'Source directory not renamed')
1607 checkvars = {}
1608 checkvars['S'] = '${WORKDIR}/%s-%s' % (recipename, recipever)
1609 checkvars['SRC_URI'] = url
1610 self._test_recipe_contents(newrecipefile, checkvars, [])
1611 # Try again - change just name this time
1612 result = runCmd('devtool reset -n %s' % newrecipename)
1613 shutil.rmtree(newsrctree)
1614 add_recipe()
1615 newrecipefile = os.path.join(self.workspacedir, 'recipes', newrecipename, '%s_%s.bb' % (newrecipename, recipever))
1616 result = runCmd('devtool rename %s %s' % (recipename, newrecipename))
1617 self.assertExists(newrecipefile, 'Recipe file not renamed')
1618 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipename), 'Old recipe directory still exists')
1619 self.assertExists(os.path.join(self.workspacedir, 'sources', newrecipename), 'Source directory not renamed')
1620 checkvars = {}
1621 checkvars['S'] = '${WORKDIR}/%s-${PV}' % recipename
1622 checkvars['SRC_URI'] = url.replace(recipever, '${PV}')
1623 self._test_recipe_contents(newrecipefile, checkvars, [])
1624 # Try again - change just version this time
1625 result = runCmd('devtool reset -n %s' % newrecipename)
1626 shutil.rmtree(newsrctree)
1627 add_recipe()
1628 newrecipefile = os.path.join(self.workspacedir, 'recipes', recipename, '%s_%s.bb' % (recipename, newrecipever))
1629 result = runCmd('devtool rename %s -V %s' % (recipename, newrecipever))
1630 self.assertExists(newrecipefile, 'Recipe file not renamed')
1631 self.assertExists(os.path.join(self.workspacedir, 'sources', recipename), 'Source directory no longer exists')
1632 checkvars = {}
1633 checkvars['S'] = '${WORKDIR}/${BPN}-%s' % recipever
1634 checkvars['SRC_URI'] = url
1635 self._test_recipe_contents(newrecipefile, checkvars, [])
1636
1637 @OETestID(1577)
1638 def test_devtool_virtual_kernel_modify(self):
1639 """
1640 Summary: The purpose of this test case is to verify that
1641 devtool modify works correctly when building
1642 the kernel.
1643 Dependencies: NA
1644 Steps: 1. Build kernel with bitbake.
1645 2. Save the config file generated.
1646 3. Clean the environment.
1647 4. Use `devtool modify virtual/kernel` to validate following:
1648 4.1 The source is checked out correctly.
1649 4.2 The resulting configuration is the same as
1650 what was get on step 2.
1651 4.3 The Kernel can be build correctly.
1652 4.4 Changes made on the source are reflected on the
1653 subsequent builds.
1654 4.5 Changes on the configuration are reflected on the
1655 subsequent builds
1656 Expected: devtool modify is able to checkout the source of the kernel
1657 and modification to the source and configurations are reflected
1658 when building the kernel.
1659 """
1660 kernel_provider = get_bb_var('PREFERRED_PROVIDER_virtual/kernel')
1661 # Clean up the enviroment
1662 bitbake('%s -c clean' % kernel_provider)
1663 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1664 tempdir_cfg = tempfile.mkdtemp(prefix='config_qa')
1665 self.track_for_cleanup(tempdir)
1666 self.track_for_cleanup(tempdir_cfg)
1667 self.track_for_cleanup(self.workspacedir)
1668 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1669 self.add_command_to_tearDown('bitbake -c clean %s' % kernel_provider)
1670 #Step 1
1671 #Here is just generated the config file instead of all the kernel to optimize the
1672 #time of executing this test case.
1673 bitbake('%s -c configure' % kernel_provider)
1674 bbconfig = os.path.join(get_bb_var('B', kernel_provider),'.config')
1675 #Step 2
1676 runCmd('cp %s %s' % (bbconfig, tempdir_cfg))
1677 self.assertExists(os.path.join(tempdir_cfg, '.config'), 'Could not copy .config file from kernel')
1678
1679 tmpconfig = os.path.join(tempdir_cfg, '.config')
1680 #Step 3
1681 bitbake('%s -c clean' % kernel_provider)
1682 #Step 4.1
1683 runCmd('devtool modify virtual/kernel -x %s' % tempdir)
1684 self.assertExists(os.path.join(tempdir, 'Makefile'), 'Extracted source could not be found')
1685 #Step 4.2
1686 configfile = os.path.join(tempdir,'.config')
1687 diff = runCmd('diff %s %s' % (tmpconfig, configfile))
1688 self.assertEqual(0,diff.status,'Kernel .config file is not the same using bitbake and devtool')
1689 #Step 4.3
1690 #NOTE: virtual/kernel is mapped to kernel_provider
1691 result = runCmd('devtool build %s' % kernel_provider)
1692 self.assertEqual(0,result.status,'Cannot build kernel using `devtool build`')
1693 kernelfile = os.path.join(get_bb_var('KBUILD_OUTPUT', kernel_provider), 'vmlinux')
1694 self.assertExists(kernelfile, 'Kernel was not build correctly')
1695
1696 #Modify the kernel source
1697 modfile = os.path.join(tempdir,'arch/x86/boot/header.S')
1698 modstring = "Use a boot loader. Devtool testing."
1699 modapplied = runCmd("sed -i 's/Use a boot loader./%s/' %s" % (modstring, modfile))
1700 self.assertEqual(0,modapplied.status,'Modification to %s on kernel source failed' % modfile)
1701 #Modify the configuration
1702 codeconfigfile = os.path.join(tempdir,'.config.new')
1703 modconfopt = "CONFIG_SG_POOL=n"
1704 modconf = runCmd("sed -i 's/CONFIG_SG_POOL=y/%s/' %s" % (modconfopt, codeconfigfile))
1705 self.assertEqual(0,modconf.status,'Modification to %s failed' % codeconfigfile)
1706 #Build again kernel with devtool
1707 rebuild = runCmd('devtool build %s' % kernel_provider)
1708 self.assertEqual(0,rebuild.status,'Fail to build kernel after modification of source and config')
1709 #Step 4.4
1710 bzimagename = 'bzImage-' + get_bb_var('KERNEL_VERSION_NAME', kernel_provider)
1711 bzimagefile = os.path.join(get_bb_var('D', kernel_provider),'boot', bzimagename)
1712 checkmodcode = runCmd("grep '%s' %s" % (modstring, bzimagefile))
1713 self.assertEqual(0,checkmodcode.status,'Modification on kernel source failed')
1714 #Step 4.5
1715 checkmodconfg = runCmd("grep %s %s" % (modconfopt, codeconfigfile))
1716 self.assertEqual(0,checkmodconfg.status,'Modification to configuration file failed')