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