blob: 81d02017c12d8e44e2d44bead1cd3da89bcdde7a [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001#
Patrick Williams92b42cb2022-09-03 06:53:57 -05002# Copyright OpenEmbedded Contributors
3#
Brad Bishopc342db32019-05-15 21:57:59 -04004# SPDX-License-Identifier: MIT
5#
6
Brad Bishopd7bf8c12018-02-25 22:55:05 -05007import os
8import re
9import shutil
10import tempfile
11import glob
12import fnmatch
13
Brad Bishopd7bf8c12018-02-25 22:55:05 -050014from oeqa.selftest.case import OESelftestTestCase
15from oeqa.utils.commands import runCmd, bitbake, get_bb_var, create_temp_layer
16from oeqa.utils.commands import get_bb_vars, runqemu, get_test_layer
Patrick Williams45852732022-04-02 08:58:32 -050017from oeqa.core.decorator import OETestTag
Brad Bishopd7bf8c12018-02-25 22:55:05 -050018
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080019oldmetapath = None
20
21def setUpModule():
22 import bb.utils
23
24 global templayerdir
25 templayerdir = tempfile.mkdtemp(prefix='devtoolqa')
26 corecopydir = os.path.join(templayerdir, 'core-copy')
27 bblayers_conf = os.path.join(os.environ['BUILDDIR'], 'conf', 'bblayers.conf')
28 edited_layers = []
29
30 # We need to take a copy of the meta layer so we can modify it and not
31 # have any races against other tests that might be running in parallel
32 # however things like COREBASE mean that you can't just copy meta, you
33 # need the whole repository.
34 def bblayers_edit_cb(layerpath, canonical_layerpath):
35 global oldmetapath
36 if not canonical_layerpath.endswith('/'):
37 # This helps us match exactly when we're using this path later
38 canonical_layerpath += '/'
39 if not edited_layers and canonical_layerpath.endswith('/meta/'):
40 canonical_layerpath = os.path.realpath(canonical_layerpath) + '/'
41 edited_layers.append(layerpath)
42 oldmetapath = os.path.realpath(layerpath)
43 result = runCmd('git rev-parse --show-toplevel', cwd=canonical_layerpath)
44 oldreporoot = result.output.rstrip()
45 newmetapath = os.path.join(corecopydir, os.path.relpath(oldmetapath, oldreporoot))
46 runCmd('git clone %s %s' % (oldreporoot, corecopydir), cwd=templayerdir)
47 # Now we need to copy any modified files
48 # You might ask "why not just copy the entire tree instead of
49 # cloning and doing this?" - well, the problem with that is
50 # TMPDIR or an equally large subdirectory might exist
51 # under COREBASE and we don't want to copy that, so we have
52 # to be selective.
53 result = runCmd('git status --porcelain', cwd=oldreporoot)
54 for line in result.output.splitlines():
55 if line.startswith(' M ') or line.startswith('?? '):
56 relpth = line.split()[1]
57 pth = os.path.join(oldreporoot, relpth)
58 if pth.startswith(canonical_layerpath):
59 if relpth.endswith('/'):
60 destdir = os.path.join(corecopydir, relpth)
Andrew Geisslerc3d88e42020-10-02 09:45:00 -050061 # avoid race condition by not copying .pyc files YPBZ#13421,13803
Andrew Geisslerd1e89492021-02-12 15:35:20 -060062 shutil.copytree(pth, destdir, ignore=shutil.ignore_patterns('*.pyc', '__pycache__'))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080063 else:
64 destdir = os.path.join(corecopydir, os.path.dirname(relpth))
65 bb.utils.mkdirhier(destdir)
66 shutil.copy2(pth, destdir)
67 return newmetapath
68 else:
69 return layerpath
70 bb.utils.edit_bblayers_conf(bblayers_conf, None, None, bblayers_edit_cb)
71
72def tearDownModule():
73 if oldmetapath:
74 edited_layers = []
75 def bblayers_edit_cb(layerpath, canonical_layerpath):
76 if not edited_layers and canonical_layerpath.endswith('/meta'):
77 edited_layers.append(layerpath)
78 return oldmetapath
79 else:
80 return layerpath
81 bblayers_conf = os.path.join(os.environ['BUILDDIR'], 'conf', 'bblayers.conf')
82 bb.utils.edit_bblayers_conf(bblayers_conf, None, None, bblayers_edit_cb)
83 shutil.rmtree(templayerdir)
84
Andrew Geissler595f6302022-01-24 19:11:47 +000085class DevtoolTestCase(OESelftestTestCase):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080086
87 def setUp(self):
88 """Test case setup function"""
Andrew Geissler595f6302022-01-24 19:11:47 +000089 super(DevtoolTestCase, self).setUp()
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080090 self.workspacedir = os.path.join(self.builddir, 'workspace')
91 self.assertTrue(not os.path.exists(self.workspacedir),
92 'This test cannot be run with a workspace directory '
93 'under the build directory')
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080094
95 def _check_src_repo(self, repo_dir):
96 """Check srctree git repository"""
97 self.assertTrue(os.path.isdir(os.path.join(repo_dir, '.git')),
98 'git repository for external source tree not found')
99 result = runCmd('git status --porcelain', cwd=repo_dir)
100 self.assertEqual(result.output.strip(), "",
101 'Created git repo is not clean')
102 result = runCmd('git symbolic-ref HEAD', cwd=repo_dir)
103 self.assertEqual(result.output.strip(), "refs/heads/devtool",
104 'Wrong branch in git repo')
105
106 def _check_repo_status(self, repo_dir, expected_status):
107 """Check the worktree status of a repository"""
108 result = runCmd('git status . --porcelain',
109 cwd=repo_dir)
110 for line in result.output.splitlines():
111 for ind, (f_status, fn_re) in enumerate(expected_status):
112 if re.match(fn_re, line[3:]):
113 if f_status != line[:2]:
114 self.fail('Unexpected status in line: %s' % line)
115 expected_status.pop(ind)
116 break
117 else:
118 self.fail('Unexpected modified file in line: %s' % line)
119 if expected_status:
120 self.fail('Missing file changes: %s' % expected_status)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500121
122 def _test_recipe_contents(self, recipefile, checkvars, checkinherits):
123 with open(recipefile, 'r') as f:
124 invar = None
125 invalue = None
Brad Bishop6dbb3162019-11-25 09:41:34 -0500126 inherits = set()
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500127 for line in f:
128 var = None
129 if invar:
130 value = line.strip().strip('"')
131 if value.endswith('\\'):
132 invalue += ' ' + value[:-1].strip()
133 continue
134 else:
135 invalue += ' ' + value.strip()
136 var = invar
137 value = invalue
138 invar = None
139 elif '=' in line:
140 splitline = line.split('=', 1)
141 var = splitline[0].rstrip()
142 value = splitline[1].strip().strip('"')
143 if value.endswith('\\'):
144 invalue = value[:-1].strip()
145 invar = var
146 continue
147 elif line.startswith('inherit '):
Brad Bishop6dbb3162019-11-25 09:41:34 -0500148 inherits.update(line.split()[1:])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500149
150 if var and var in checkvars:
151 needvalue = checkvars.pop(var)
152 if needvalue is None:
153 self.fail('Variable %s should not appear in recipe, but value is being set to "%s"' % (var, value))
154 if isinstance(needvalue, set):
155 if var == 'LICENSE':
156 value = set(value.split(' & '))
157 else:
158 value = set(value.split())
159 self.assertEqual(value, needvalue, 'values for %s do not match' % var)
160
161
162 missingvars = {}
163 for var, value in checkvars.items():
164 if value is not None:
165 missingvars[var] = value
166 self.assertEqual(missingvars, {}, 'Some expected variables not found in recipe: %s' % checkvars)
167
168 for inherit in checkinherits:
169 self.assertIn(inherit, inherits, 'Missing inherit of %s' % inherit)
170
171 def _check_bbappend(self, testrecipe, recipefile, appenddir):
172 result = runCmd('bitbake-layers show-appends', cwd=self.builddir)
173 resultlines = result.output.splitlines()
174 inrecipe = False
175 bbappends = []
176 bbappendfile = None
177 for line in resultlines:
178 if inrecipe:
179 if line.startswith(' '):
180 bbappends.append(line.strip())
181 else:
182 break
183 elif line == '%s:' % os.path.basename(recipefile):
184 inrecipe = True
185 self.assertLessEqual(len(bbappends), 2, '%s recipe is being bbappended by another layer - bbappends found:\n %s' % (testrecipe, '\n '.join(bbappends)))
186 for bbappend in bbappends:
187 if bbappend.startswith(appenddir):
188 bbappendfile = bbappend
189 break
190 else:
191 self.fail('bbappend for recipe %s does not seem to be created in test layer' % testrecipe)
192 return bbappendfile
193
194 def _create_temp_layer(self, templayerdir, addlayer, templayername, priority=999, recipepathspec='recipes-*/*'):
195 create_temp_layer(templayerdir, templayername, priority, recipepathspec)
196 if addlayer:
197 self.add_command_to_tearDown('bitbake-layers remove-layer %s || true' % templayerdir)
198 result = runCmd('bitbake-layers add-layer %s' % templayerdir, cwd=self.builddir)
199
200 def _process_ls_output(self, output):
201 """
202 Convert ls -l output to a format we can reasonably compare from one context
203 to another (e.g. from host to target)
204 """
205 filelist = []
206 for line in output.splitlines():
207 splitline = line.split()
208 if len(splitline) < 8:
209 self.fail('_process_ls_output: invalid output line: %s' % line)
210 # Remove trailing . on perms
211 splitline[0] = splitline[0].rstrip('.')
212 # Remove leading . on paths
213 splitline[-1] = splitline[-1].lstrip('.')
214 # Drop fields we don't want to compare
215 del splitline[7]
216 del splitline[6]
217 del splitline[5]
218 del splitline[4]
219 del splitline[1]
220 filelist.append(' '.join(splitline))
221 return filelist
222
Andrew Geissler615f2f12022-07-15 14:00:58 -0500223 def _check_diff(self, diffoutput, addlines, removelines):
224 """Check output from 'git diff' matches expectation"""
225 remaining_addlines = addlines[:]
226 remaining_removelines = removelines[:]
227 for line in diffoutput.splitlines():
228 if line.startswith('+++') or line.startswith('---'):
229 continue
230 elif line.startswith('+'):
231 matched = False
232 for item in addlines:
233 if re.match(item, line[1:].strip()):
234 matched = True
235 remaining_addlines.remove(item)
236 break
237 self.assertTrue(matched, 'Unexpected diff add line: %s' % line)
238 elif line.startswith('-'):
239 matched = False
240 for item in removelines:
241 if re.match(item, line[1:].strip()):
242 matched = True
243 remaining_removelines.remove(item)
244 break
245 self.assertTrue(matched, 'Unexpected diff remove line: %s' % line)
246 if remaining_addlines:
247 self.fail('Expected added lines not found: %s' % remaining_addlines)
248 if remaining_removelines:
249 self.fail('Expected removed lines not found: %s' % remaining_removelines)
250
Patrick Williams92b42cb2022-09-03 06:53:57 -0500251 def _test_devtool_add_git_url(self, git_url, version, pn, resulting_src_uri):
252 self.track_for_cleanup(self.workspacedir)
253 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
254 result = runCmd('devtool add --version %s %s %s' % (version, pn, git_url))
255 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
256 # Check the recipe name is correct
257 recipefile = get_bb_var('FILE', pn)
258 self.assertIn('%s_git.bb' % pn, recipefile, 'Recipe file incorrectly named')
259 self.assertIn(recipefile, result.output)
260 # Test devtool status
261 result = runCmd('devtool status')
262 self.assertIn(pn, result.output)
263 self.assertIn(recipefile, result.output)
264 checkvars = {}
265 checkvars['SRC_URI'] = resulting_src_uri
266 self._test_recipe_contents(recipefile, checkvars, [])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500267
Andrew Geissler595f6302022-01-24 19:11:47 +0000268class DevtoolBase(DevtoolTestCase):
269
270 @classmethod
271 def setUpClass(cls):
272 super(DevtoolBase, cls).setUpClass()
273 bb_vars = get_bb_vars(['TOPDIR', 'SSTATE_DIR'])
274 cls.original_sstate = bb_vars['SSTATE_DIR']
275 cls.devtool_sstate = os.path.join(bb_vars['TOPDIR'], 'sstate_devtool')
276 cls.sstate_conf = 'SSTATE_DIR = "%s"\n' % cls.devtool_sstate
277 cls.sstate_conf += ('SSTATE_MIRRORS += "file://.* file:///%s/PATH"\n'
278 % cls.original_sstate)
Andrew Geisslerfc113ea2023-03-31 09:59:46 -0500279 cls.sstate_conf += ('BB_HASHSERVE_UPSTREAM = "hashserv.yocto.io:8687"\n')
Andrew Geissler595f6302022-01-24 19:11:47 +0000280
281 @classmethod
282 def tearDownClass(cls):
283 cls.logger.debug('Deleting devtool sstate cache on %s' % cls.devtool_sstate)
284 runCmd('rm -rf %s' % cls.devtool_sstate)
285 super(DevtoolBase, cls).tearDownClass()
286
287 def setUp(self):
288 """Test case setup function"""
289 super(DevtoolBase, self).setUp()
290 self.append_config(self.sstate_conf)
291
292
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500293class DevtoolTests(DevtoolBase):
294
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500295 def test_create_workspace(self):
296 # Check preconditions
297 result = runCmd('bitbake-layers show-layers')
Brad Bishop316dfdd2018-06-25 12:45:53 -0400298 self.assertTrue('\nworkspace' not in result.output, 'This test cannot be run with a workspace layer in bblayers.conf')
Brad Bishop96ff1982019-08-19 13:50:42 -0400299 # remove conf/devtool.conf to avoid it corrupting tests
300 devtoolconf = os.path.join(self.builddir, 'conf', 'devtool.conf')
301 self.track_for_cleanup(devtoolconf)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500302 # Try creating a workspace layer with a specific path
303 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
304 self.track_for_cleanup(tempdir)
305 result = runCmd('devtool create-workspace %s' % tempdir)
306 self.assertTrue(os.path.isfile(os.path.join(tempdir, 'conf', 'layer.conf')), msg = "No workspace created. devtool output: %s " % result.output)
307 result = runCmd('bitbake-layers show-layers')
308 self.assertIn(tempdir, result.output)
309 # Try creating a workspace layer with the default path
310 self.track_for_cleanup(self.workspacedir)
311 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
312 result = runCmd('devtool create-workspace')
313 self.assertTrue(os.path.isfile(os.path.join(self.workspacedir, 'conf', 'layer.conf')), msg = "No workspace created. devtool output: %s " % result.output)
314 result = runCmd('bitbake-layers show-layers')
315 self.assertNotIn(tempdir, result.output)
316 self.assertIn(self.workspacedir, result.output)
317
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800318class DevtoolAddTests(DevtoolBase):
319
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500320 def test_devtool_add(self):
321 # Fetch source
322 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
323 self.track_for_cleanup(tempdir)
324 pn = 'pv'
325 pv = '1.5.3'
Andrew Geissler09209ee2020-12-13 08:44:15 -0600326 url = 'http://downloads.yoctoproject.org/mirror/sources/pv-1.5.3.tar.bz2'
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500327 result = runCmd('wget %s' % url, cwd=tempdir)
328 result = runCmd('tar xfv %s' % os.path.basename(url), cwd=tempdir)
329 srcdir = os.path.join(tempdir, '%s-%s' % (pn, pv))
330 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure')), 'Unable to find configure script in source directory')
331 # Test devtool add
332 self.track_for_cleanup(self.workspacedir)
333 self.add_command_to_tearDown('bitbake -c cleansstate %s' % pn)
334 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
335 result = runCmd('devtool add %s %s' % (pn, srcdir))
336 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
337 # Test devtool status
338 result = runCmd('devtool status')
339 recipepath = '%s/recipes/%s/%s_%s.bb' % (self.workspacedir, pn, pn, pv)
340 self.assertIn(recipepath, result.output)
341 self.assertIn(srcdir, result.output)
342 # Test devtool find-recipe
343 result = runCmd('devtool -q find-recipe %s' % pn)
344 self.assertEqual(recipepath, result.output.strip())
345 # Test devtool edit-recipe
346 result = runCmd('VISUAL="echo 123" devtool -q edit-recipe %s' % pn)
347 self.assertEqual('123 %s' % recipepath, result.output.strip())
348 # Clean up anything in the workdir/sysroot/sstate cache (have to do this *after* devtool add since the recipe only exists then)
349 bitbake('%s -c cleansstate' % pn)
350 # Test devtool build
351 result = runCmd('devtool build %s' % pn)
352 bb_vars = get_bb_vars(['D', 'bindir'], pn)
353 installdir = bb_vars['D']
354 self.assertTrue(installdir, 'Could not query installdir variable')
355 bindir = bb_vars['bindir']
356 self.assertTrue(bindir, 'Could not query bindir variable')
357 if bindir[0] == '/':
358 bindir = bindir[1:]
359 self.assertTrue(os.path.isfile(os.path.join(installdir, bindir, 'pv')), 'pv binary not found in D')
360
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500361 def test_devtool_add_git_local(self):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800362 # We need dbus built so that DEPENDS recognition works
363 bitbake('dbus')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500364 # Fetch source from a remote URL, but do it outside of devtool
365 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
366 self.track_for_cleanup(tempdir)
367 pn = 'dbus-wait'
368 srcrev = '6cc6077a36fe2648a5f993fe7c16c9632f946517'
369 # We choose an https:// git URL here to check rewriting the URL works
370 url = 'https://git.yoctoproject.org/git/dbus-wait'
371 # Force fetching to "noname" subdir so we verify we're picking up the name from autoconf
372 # instead of the directory name
373 result = runCmd('git clone %s noname' % url, cwd=tempdir)
374 srcdir = os.path.join(tempdir, 'noname')
375 result = runCmd('git reset --hard %s' % srcrev, cwd=srcdir)
376 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure.ac')), 'Unable to find configure script in source directory')
377 # Test devtool add
378 self.track_for_cleanup(self.workspacedir)
379 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
380 # Don't specify a name since we should be able to auto-detect it
381 result = runCmd('devtool add %s' % srcdir)
382 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
383 # Check the recipe name is correct
384 recipefile = get_bb_var('FILE', pn)
385 self.assertIn('%s_git.bb' % pn, recipefile, 'Recipe file incorrectly named')
386 self.assertIn(recipefile, result.output)
387 # Test devtool status
388 result = runCmd('devtool status')
389 self.assertIn(pn, result.output)
390 self.assertIn(srcdir, result.output)
391 self.assertIn(recipefile, result.output)
392 checkvars = {}
Andrew Geissler9aee5002022-03-30 16:27:02 +0000393 checkvars['LICENSE'] = 'GPL-2.0-only'
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500394 checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263'
395 checkvars['S'] = '${WORKDIR}/git'
396 checkvars['PV'] = '0.1+git${SRCPV}'
Andrew Geissler595f6302022-01-24 19:11:47 +0000397 checkvars['SRC_URI'] = 'git://git.yoctoproject.org/git/dbus-wait;protocol=https;branch=master'
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500398 checkvars['SRCREV'] = srcrev
399 checkvars['DEPENDS'] = set(['dbus'])
400 self._test_recipe_contents(recipefile, checkvars, [])
401
Patrick Williams92b42cb2022-09-03 06:53:57 -0500402 def test_devtool_add_git_style1(self):
403 version = 'v3.1.0'
404 pn = 'mbedtls'
405 # this will trigger reformat_git_uri with branch parameter in url
406 git_url = "'git://git@github.com/ARMmbed/mbedtls.git;branch=mbedtls-2.28;protocol=https'"
407 resulting_src_uri = "git://git@github.com/ARMmbed/mbedtls.git;branch=mbedtls-2.28;protocol=https"
408 self._test_devtool_add_git_url(git_url, version, pn, resulting_src_uri)
409
410 def test_devtool_add_git_style2(self):
411 version = 'v3.1.0'
412 pn = 'mbedtls'
413 # this will trigger reformat_git_uri with branch parameter in url
414 git_url = "'git://git@github.com/ARMmbed/mbedtls.git;protocol=https'"
415 resulting_src_uri = "git://git@github.com/ARMmbed/mbedtls.git;protocol=https;branch=master"
416 self._test_devtool_add_git_url(git_url, version, pn, resulting_src_uri)
417
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500418 def test_devtool_add_library(self):
419 # Fetch source
420 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
421 self.track_for_cleanup(tempdir)
422 version = '1.1'
423 url = 'https://www.intra2net.com/en/developer/libftdi/download/libftdi1-%s.tar.bz2' % version
424 result = runCmd('wget %s' % url, cwd=tempdir)
425 result = runCmd('tar xfv libftdi1-%s.tar.bz2' % version, cwd=tempdir)
426 srcdir = os.path.join(tempdir, 'libftdi1-%s' % version)
427 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'CMakeLists.txt')), 'Unable to find CMakeLists.txt in source directory')
428 # Test devtool add (and use -V so we test that too)
429 self.track_for_cleanup(self.workspacedir)
430 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
431 result = runCmd('devtool add libftdi %s -V %s' % (srcdir, version))
432 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
433 # Test devtool status
434 result = runCmd('devtool status')
435 self.assertIn('libftdi', result.output)
436 self.assertIn(srcdir, result.output)
437 # Clean up anything in the workdir/sysroot/sstate cache (have to do this *after* devtool add since the recipe only exists then)
438 bitbake('libftdi -c cleansstate')
439 # libftdi's python/CMakeLists.txt is a bit broken, so let's just disable it
440 # There's also the matter of it installing cmake files to a path we don't
441 # normally cover, which triggers the installed-vs-shipped QA test we have
442 # within do_package
443 recipefile = '%s/recipes/libftdi/libftdi_%s.bb' % (self.workspacedir, version)
444 result = runCmd('recipetool setvar %s EXTRA_OECMAKE -- \'-DPYTHON_BINDINGS=OFF -DLIBFTDI_CMAKE_CONFIG_DIR=${datadir}/cmake/Modules\'' % recipefile)
445 with open(recipefile, 'a') as f:
Patrick Williams213cb262021-08-07 19:21:33 -0500446 f.write('\nFILES:${PN}-dev += "${datadir}/cmake/Modules"\n')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500447 # We don't have the ability to pick up this dependency automatically yet...
448 f.write('\nDEPENDS += "libusb1"\n')
449 f.write('\nTESTLIBOUTPUT = "${COMPONENTS_DIR}/${TUNE_PKGARCH}/${PN}/${libdir}"\n')
450 # Test devtool build
451 result = runCmd('devtool build libftdi')
452 bb_vars = get_bb_vars(['TESTLIBOUTPUT', 'STAMP'], 'libftdi')
453 staging_libdir = bb_vars['TESTLIBOUTPUT']
454 self.assertTrue(staging_libdir, 'Could not query TESTLIBOUTPUT variable')
455 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)
456 # Test devtool reset
457 stampprefix = bb_vars['STAMP']
458 result = runCmd('devtool reset libftdi')
459 result = runCmd('devtool status')
460 self.assertNotIn('libftdi', result.output)
461 self.assertTrue(stampprefix, 'Unable to get STAMP value for recipe libftdi')
462 matches = glob.glob(stampprefix + '*')
463 self.assertFalse(matches, 'Stamp files exist for recipe libftdi that should have been cleaned')
464 self.assertFalse(os.path.isfile(os.path.join(staging_libdir, 'libftdi1.so.2.1.0')), 'libftdi binary still found in STAGING_LIBDIR after cleaning')
465
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500466 def test_devtool_add_fetch(self):
467 # Fetch source
468 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
469 self.track_for_cleanup(tempdir)
470 testver = '0.23'
Brad Bishop15ae2502019-06-18 21:44:24 -0400471 url = 'https://files.pythonhosted.org/packages/c0/41/bae1254e0396c0cc8cf1751cb7d9afc90a602353695af5952530482c963f/MarkupSafe-%s.tar.gz' % testver
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500472 testrecipe = 'python-markupsafe'
473 srcdir = os.path.join(tempdir, testrecipe)
474 # Test devtool add
475 self.track_for_cleanup(self.workspacedir)
476 self.add_command_to_tearDown('bitbake -c cleansstate %s' % testrecipe)
477 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
478 result = runCmd('devtool add %s %s -f %s' % (testrecipe, srcdir, url))
479 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created. %s' % result.output)
480 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'setup.py')), 'Unable to find setup.py in source directory')
481 self.assertTrue(os.path.isdir(os.path.join(srcdir, '.git')), 'git repository for external source tree was not created')
482 # Test devtool status
483 result = runCmd('devtool status')
484 self.assertIn(testrecipe, result.output)
485 self.assertIn(srcdir, result.output)
486 # Check recipe
487 recipefile = get_bb_var('FILE', testrecipe)
488 self.assertIn('%s_%s.bb' % (testrecipe, testver), recipefile, 'Recipe file incorrectly named')
489 checkvars = {}
490 checkvars['S'] = '${WORKDIR}/MarkupSafe-${PV}'
491 checkvars['SRC_URI'] = url.replace(testver, '${PV}')
492 self._test_recipe_contents(recipefile, checkvars, [])
493 # Try with version specified
494 result = runCmd('devtool reset -n %s' % testrecipe)
495 shutil.rmtree(srcdir)
496 fakever = '1.9'
497 result = runCmd('devtool add %s %s -f %s -V %s' % (testrecipe, srcdir, url, fakever))
498 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'setup.py')), 'Unable to find setup.py in source directory')
499 # Test devtool status
500 result = runCmd('devtool status')
501 self.assertIn(testrecipe, result.output)
502 self.assertIn(srcdir, result.output)
503 # Check recipe
504 recipefile = get_bb_var('FILE', testrecipe)
505 self.assertIn('%s_%s.bb' % (testrecipe, fakever), recipefile, 'Recipe file incorrectly named')
506 checkvars = {}
507 checkvars['S'] = '${WORKDIR}/MarkupSafe-%s' % testver
508 checkvars['SRC_URI'] = url
509 self._test_recipe_contents(recipefile, checkvars, [])
Andrew Geissler615f2f12022-07-15 14:00:58 -0500510
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500511 def test_devtool_add_fetch_git(self):
512 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
513 self.track_for_cleanup(tempdir)
514 url = 'gitsm://git.yoctoproject.org/mraa'
Andrew Geissler595f6302022-01-24 19:11:47 +0000515 url_branch = '%s;branch=master' % url
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500516 checkrev = 'ae127b19a50aa54255e4330ccfdd9a5d058e581d'
517 testrecipe = 'mraa'
518 srcdir = os.path.join(tempdir, testrecipe)
519 # Test devtool add
520 self.track_for_cleanup(self.workspacedir)
521 self.add_command_to_tearDown('bitbake -c cleansstate %s' % testrecipe)
522 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
523 result = runCmd('devtool add %s %s -a -f %s' % (testrecipe, srcdir, url))
524 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created: %s' % result.output)
525 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'imraa', 'imraa.c')), 'Unable to find imraa/imraa.c in source directory')
526 # Test devtool status
527 result = runCmd('devtool status')
528 self.assertIn(testrecipe, result.output)
529 self.assertIn(srcdir, result.output)
530 # Check recipe
531 recipefile = get_bb_var('FILE', testrecipe)
532 self.assertIn('_git.bb', recipefile, 'Recipe file incorrectly named')
533 checkvars = {}
534 checkvars['S'] = '${WORKDIR}/git'
535 checkvars['PV'] = '1.0+git${SRCPV}'
Andrew Geissler595f6302022-01-24 19:11:47 +0000536 checkvars['SRC_URI'] = url_branch
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500537 checkvars['SRCREV'] = '${AUTOREV}'
538 self._test_recipe_contents(recipefile, checkvars, [])
539 # Try with revision and version specified
540 result = runCmd('devtool reset -n %s' % testrecipe)
541 shutil.rmtree(srcdir)
542 url_rev = '%s;rev=%s' % (url, checkrev)
543 result = runCmd('devtool add %s %s -f "%s" -V 1.5' % (testrecipe, srcdir, url_rev))
544 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'imraa', 'imraa.c')), 'Unable to find imraa/imraa.c in source directory')
545 # Test devtool status
546 result = runCmd('devtool status')
547 self.assertIn(testrecipe, result.output)
548 self.assertIn(srcdir, result.output)
549 # Check recipe
550 recipefile = get_bb_var('FILE', testrecipe)
551 self.assertIn('_git.bb', recipefile, 'Recipe file incorrectly named')
552 checkvars = {}
553 checkvars['S'] = '${WORKDIR}/git'
554 checkvars['PV'] = '1.5+git${SRCPV}'
Andrew Geissler595f6302022-01-24 19:11:47 +0000555 checkvars['SRC_URI'] = url_branch
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500556 checkvars['SRCREV'] = checkrev
557 self._test_recipe_contents(recipefile, checkvars, [])
558
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500559 def test_devtool_add_fetch_simple(self):
560 # Fetch source from a remote URL, auto-detecting name
561 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
562 self.track_for_cleanup(tempdir)
563 testver = '1.6.0'
564 url = 'http://www.ivarch.com/programs/sources/pv-%s.tar.bz2' % testver
565 testrecipe = 'pv'
566 srcdir = os.path.join(self.workspacedir, 'sources', testrecipe)
567 # Test devtool add
568 self.track_for_cleanup(self.workspacedir)
569 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
570 result = runCmd('devtool add %s' % url)
571 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created. %s' % result.output)
572 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure')), 'Unable to find configure script in source directory')
573 self.assertTrue(os.path.isdir(os.path.join(srcdir, '.git')), 'git repository for external source tree was not created')
574 # Test devtool status
575 result = runCmd('devtool status')
576 self.assertIn(testrecipe, result.output)
577 self.assertIn(srcdir, result.output)
Patrick Williams92b42cb2022-09-03 06:53:57 -0500578 # Check recipedevtool add
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500579 recipefile = get_bb_var('FILE', testrecipe)
580 self.assertIn('%s_%s.bb' % (testrecipe, testver), recipefile, 'Recipe file incorrectly named')
581 checkvars = {}
582 checkvars['S'] = None
583 checkvars['SRC_URI'] = url.replace(testver, '${PV}')
584 self._test_recipe_contents(recipefile, checkvars, [])
585
Andrew Geissler82c905d2020-04-13 13:39:40 -0500586 def test_devtool_add_npm(self):
Andrew Geisslerf0343792020-11-18 10:42:21 -0600587 collections = get_bb_var('BBFILE_COLLECTIONS').split()
588 if "openembedded-layer" not in collections:
589 self.skipTest("Test needs meta-oe for nodejs")
590
Andrew Geissler82c905d2020-04-13 13:39:40 -0500591 pn = 'savoirfairelinux-node-server-example'
592 pv = '1.0.0'
593 url = 'npm://registry.npmjs.org;package=@savoirfairelinux/node-server-example;version=' + pv
594 # Test devtool add
595 self.track_for_cleanup(self.workspacedir)
596 self.add_command_to_tearDown('bitbake -c cleansstate %s' % pn)
597 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
598 result = runCmd('devtool add \'%s\'' % url)
599 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
600 self.assertExists(os.path.join(self.workspacedir, 'recipes', pn, '%s_%s.bb' % (pn, pv)), 'Recipe not created')
601 self.assertExists(os.path.join(self.workspacedir, 'recipes', pn, pn, 'npm-shrinkwrap.json'), 'Shrinkwrap not created')
602 # Test devtool status
603 result = runCmd('devtool status')
604 self.assertIn(pn, result.output)
605 # Clean up anything in the workdir/sysroot/sstate cache (have to do this *after* devtool add since the recipe only exists then)
606 bitbake('%s -c cleansstate' % pn)
607 # Test devtool build
608 result = runCmd('devtool build %s' % pn)
609
Andrew Geissler615f2f12022-07-15 14:00:58 -0500610 def test_devtool_add_python_egg_requires(self):
611 # Fetch source
612 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
613 self.track_for_cleanup(tempdir)
614 testver = '0.14.0'
615 url = 'https://files.pythonhosted.org/packages/e9/9e/25d59f5043cf763833b2581c8027fa92342c4cf8ee523b498ecdf460c16d/uvicorn-%s.tar.gz' % testver
616 testrecipe = 'python3-uvicorn'
617 srcdir = os.path.join(tempdir, testrecipe)
618 # Test devtool add
619 self.track_for_cleanup(self.workspacedir)
620 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
621 result = runCmd('devtool add %s %s -f %s' % (testrecipe, srcdir, url))
622
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800623class DevtoolModifyTests(DevtoolBase):
624
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500625 def test_devtool_modify(self):
626 import oe.path
627
628 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
629 self.track_for_cleanup(tempdir)
630 self.track_for_cleanup(self.workspacedir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500631 self.add_command_to_tearDown('bitbake -c clean mdadm')
Brad Bishop00e122a2019-10-05 11:10:57 -0400632 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500633 result = runCmd('devtool modify mdadm -x %s' % tempdir)
634 self.assertExists(os.path.join(tempdir, 'Makefile'), 'Extracted source could not be found')
635 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
636 matches = glob.glob(os.path.join(self.workspacedir, 'appends', 'mdadm_*.bbappend'))
637 self.assertTrue(matches, 'bbappend not created %s' % result.output)
638
639 # Test devtool status
640 result = runCmd('devtool status')
641 self.assertIn('mdadm', result.output)
642 self.assertIn(tempdir, result.output)
643 self._check_src_repo(tempdir)
644
645 bitbake('mdadm -C unpack')
646
647 def check_line(checkfile, expected, message, present=True):
648 # Check for $expected, on a line on its own, in checkfile.
649 with open(checkfile, 'r') as f:
650 if present:
651 self.assertIn(expected + '\n', f, message)
652 else:
653 self.assertNotIn(expected + '\n', f, message)
654
655 modfile = os.path.join(tempdir, 'mdadm.8.in')
656 bb_vars = get_bb_vars(['PKGD', 'mandir'], 'mdadm')
657 pkgd = bb_vars['PKGD']
658 self.assertTrue(pkgd, 'Could not query PKGD variable')
659 mandir = bb_vars['mandir']
660 self.assertTrue(mandir, 'Could not query mandir variable')
661 manfile = oe.path.join(pkgd, mandir, 'man8', 'mdadm.8')
662
663 check_line(modfile, 'Linux Software RAID', 'Could not find initial string')
664 check_line(modfile, 'antique pin sardine', 'Unexpectedly found replacement string', present=False)
665
666 result = runCmd("sed -i 's!^Linux Software RAID$!antique pin sardine!' %s" % modfile)
667 check_line(modfile, 'antique pin sardine', 'mdadm.8.in file not modified (sed failed)')
668
669 bitbake('mdadm -c package')
670 check_line(manfile, 'antique pin sardine', 'man file not modified. man searched file path: %s' % manfile)
671
672 result = runCmd('git checkout -- %s' % modfile, cwd=tempdir)
673 check_line(modfile, 'Linux Software RAID', 'man .in file not restored (git failed)')
674
675 bitbake('mdadm -c package')
676 check_line(manfile, 'Linux Software RAID', 'man file not updated. man searched file path: %s' % manfile)
677
678 result = runCmd('devtool reset mdadm')
679 result = runCmd('devtool status')
680 self.assertNotIn('mdadm', result.output)
681
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500682 def test_devtool_buildclean(self):
683 def assertFile(path, *paths):
684 f = os.path.join(path, *paths)
685 self.assertExists(f)
686 def assertNoFile(path, *paths):
687 f = os.path.join(path, *paths)
688 self.assertNotExists(f)
689
690 # Clean up anything in the workdir/sysroot/sstate cache
691 bitbake('mdadm m4 -c cleansstate')
692 # Try modifying a recipe
693 tempdir_mdadm = tempfile.mkdtemp(prefix='devtoolqa')
694 tempdir_m4 = tempfile.mkdtemp(prefix='devtoolqa')
695 builddir_m4 = tempfile.mkdtemp(prefix='devtoolqa')
696 self.track_for_cleanup(tempdir_mdadm)
697 self.track_for_cleanup(tempdir_m4)
698 self.track_for_cleanup(builddir_m4)
699 self.track_for_cleanup(self.workspacedir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500700 self.add_command_to_tearDown('bitbake -c clean mdadm m4')
Brad Bishop00e122a2019-10-05 11:10:57 -0400701 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500702 self.write_recipeinc('m4', 'EXTERNALSRC_BUILD = "%s"\ndo_clean() {\n\t:\n}\n' % builddir_m4)
703 try:
704 runCmd('devtool modify mdadm -x %s' % tempdir_mdadm)
705 runCmd('devtool modify m4 -x %s' % tempdir_m4)
706 assertNoFile(tempdir_mdadm, 'mdadm')
707 assertNoFile(builddir_m4, 'src/m4')
708 result = bitbake('m4 -e')
709 result = bitbake('mdadm m4 -c compile')
710 self.assertEqual(result.status, 0)
711 assertFile(tempdir_mdadm, 'mdadm')
712 assertFile(builddir_m4, 'src/m4')
713 # Check that buildclean task exists and does call make clean
714 bitbake('mdadm m4 -c buildclean')
715 assertNoFile(tempdir_mdadm, 'mdadm')
716 assertNoFile(builddir_m4, 'src/m4')
Brad Bishop00e122a2019-10-05 11:10:57 -0400717 runCmd('echo "#Trigger rebuild" >> %s/Makefile' % tempdir_mdadm)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500718 bitbake('mdadm m4 -c compile')
719 assertFile(tempdir_mdadm, 'mdadm')
720 assertFile(builddir_m4, 'src/m4')
721 bitbake('mdadm m4 -c clean')
722 # Check that buildclean task is run before clean for B == S
723 assertNoFile(tempdir_mdadm, 'mdadm')
724 # Check that buildclean task is not run before clean for B != S
725 assertFile(builddir_m4, 'src/m4')
726 finally:
727 self.delete_recipeinc('m4')
728
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500729 def test_devtool_modify_invalid(self):
730 # Try modifying some recipes
731 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
732 self.track_for_cleanup(tempdir)
733 self.track_for_cleanup(self.workspacedir)
734 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
735
Andrew Geissler5199d832021-09-24 16:47:35 -0500736 testrecipes = 'perf kernel-devsrc package-index core-image-minimal meta-toolchain packagegroup-core-sdk'.split()
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500737 # Find actual name of gcc-source since it now includes the version - crude, but good enough for this purpose
738 result = runCmd('bitbake-layers show-recipes gcc-source*')
739 for line in result.output.splitlines():
740 # just match those lines that contain a real target
741 m = re.match('(?P<recipe>^[a-zA-Z0-9.-]+)(?P<colon>:$)', line)
742 if m:
743 testrecipes.append(m.group('recipe'))
744 for testrecipe in testrecipes:
745 # Check it's a valid recipe
746 bitbake('%s -e' % testrecipe)
747 # devtool extract should fail
748 result = runCmd('devtool extract %s %s' % (testrecipe, os.path.join(tempdir, testrecipe)), ignore_status=True)
749 self.assertNotEqual(result.status, 0, 'devtool extract on %s should have failed. devtool output: %s' % (testrecipe, result.output))
750 self.assertNotIn('Fetching ', result.output, 'devtool extract on %s should have errored out before trying to fetch' % testrecipe)
751 self.assertIn('ERROR: ', result.output, 'devtool extract on %s should have given an ERROR' % testrecipe)
752 # devtool modify should fail
753 result = runCmd('devtool modify %s -x %s' % (testrecipe, os.path.join(tempdir, testrecipe)), ignore_status=True)
754 self.assertNotEqual(result.status, 0, 'devtool modify on %s should have failed. devtool output: %s' % (testrecipe, result.output))
755 self.assertIn('ERROR: ', result.output, 'devtool modify on %s should have given an ERROR' % testrecipe)
756
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500757 def test_devtool_modify_native(self):
758 # Check preconditions
759 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
760 # Try modifying some recipes
761 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
762 self.track_for_cleanup(tempdir)
763 self.track_for_cleanup(self.workspacedir)
764 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
765
766 bbclassextended = False
767 inheritnative = False
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500768 testrecipes = 'cdrtools-native mtools-native apt-native desktop-file-utils-native'.split()
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500769 for testrecipe in testrecipes:
770 checkextend = 'native' in (get_bb_var('BBCLASSEXTEND', testrecipe) or '').split()
771 if not bbclassextended:
772 bbclassextended = checkextend
773 if not inheritnative:
774 inheritnative = not checkextend
775 result = runCmd('devtool modify %s -x %s' % (testrecipe, os.path.join(tempdir, testrecipe)))
776 self.assertNotIn('ERROR: ', result.output, 'ERROR in devtool modify output: %s' % result.output)
777 result = runCmd('devtool build %s' % testrecipe)
778 self.assertNotIn('ERROR: ', result.output, 'ERROR in devtool build output: %s' % result.output)
779 result = runCmd('devtool reset %s' % testrecipe)
780 self.assertNotIn('ERROR: ', result.output, 'ERROR in devtool reset output: %s' % result.output)
781
782 self.assertTrue(bbclassextended, 'None of these recipes are BBCLASSEXTENDed to native - need to adjust testrecipes list: %s' % ', '.join(testrecipes))
783 self.assertTrue(inheritnative, 'None of these recipes do "inherit native" - need to adjust testrecipes list: %s' % ', '.join(testrecipes))
Andrew Geissler615f2f12022-07-15 14:00:58 -0500784
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600785 def test_devtool_modify_localfiles_only(self):
786 # Check preconditions
787 testrecipe = 'base-files'
788 src_uri = (get_bb_var('SRC_URI', testrecipe) or '').split()
789 foundlocalonly = False
790 correct_symlink = False
791 for item in src_uri:
792 if item.startswith('file://'):
793 if '.patch' not in item:
794 foundlocalonly = True
795 else:
796 foundlocalonly = False
797 break
798 self.assertTrue(foundlocalonly, 'This test expects the %s recipe to fetch local files only and it seems that it no longer does' % testrecipe)
799 # Clean up anything in the workdir/sysroot/sstate cache
800 bitbake('%s -c cleansstate' % testrecipe)
801 # Try modifying a recipe
802 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
803 self.track_for_cleanup(tempdir)
804 self.track_for_cleanup(self.workspacedir)
805 self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
806 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
807 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
808 srcfile = os.path.join(tempdir, 'oe-local-files/share/dot.bashrc')
809 srclink = os.path.join(tempdir, 'share/dot.bashrc')
810 self.assertExists(srcfile, 'Extracted source could not be found')
811 if os.path.islink(srclink) and os.path.exists(srclink) and os.path.samefile(srcfile, srclink):
812 correct_symlink = True
813 self.assertTrue(correct_symlink, 'Source symlink to oe-local-files is broken')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500814
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600815 matches = glob.glob(os.path.join(self.workspacedir, 'appends', '%s_*.bbappend' % testrecipe))
816 self.assertTrue(matches, 'bbappend not created')
817 # Test devtool status
818 result = runCmd('devtool status')
819 self.assertIn(testrecipe, result.output)
820 self.assertIn(tempdir, result.output)
821 # Try building
822 bitbake(testrecipe)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500823
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500824 def test_devtool_modify_git(self):
825 # Check preconditions
Brad Bishop316dfdd2018-06-25 12:45:53 -0400826 testrecipe = 'psplash'
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500827 src_uri = get_bb_var('SRC_URI', testrecipe)
828 self.assertIn('git://', src_uri, 'This test expects the %s recipe to be a git recipe' % testrecipe)
829 # Clean up anything in the workdir/sysroot/sstate cache
830 bitbake('%s -c cleansstate' % testrecipe)
831 # Try modifying a recipe
832 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
833 self.track_for_cleanup(tempdir)
834 self.track_for_cleanup(self.workspacedir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500835 self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
Brad Bishop00e122a2019-10-05 11:10:57 -0400836 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500837 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
Brad Bishop316dfdd2018-06-25 12:45:53 -0400838 self.assertExists(os.path.join(tempdir, 'Makefile.am'), 'Extracted source could not be found')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500839 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 -0400840 matches = glob.glob(os.path.join(self.workspacedir, 'appends', 'psplash_*.bbappend'))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500841 self.assertTrue(matches, 'bbappend not created')
842 # Test devtool status
843 result = runCmd('devtool status')
844 self.assertIn(testrecipe, result.output)
845 self.assertIn(tempdir, result.output)
846 # Check git repo
847 self._check_src_repo(tempdir)
848 # Try building
849 bitbake(testrecipe)
850
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500851 def test_devtool_modify_localfiles(self):
852 # Check preconditions
853 testrecipe = 'lighttpd'
854 src_uri = (get_bb_var('SRC_URI', testrecipe) or '').split()
855 foundlocal = False
856 for item in src_uri:
857 if item.startswith('file://') and '.patch' not in item:
858 foundlocal = True
859 break
860 self.assertTrue(foundlocal, 'This test expects the %s recipe to fetch local files and it seems that it no longer does' % testrecipe)
861 # Clean up anything in the workdir/sysroot/sstate cache
862 bitbake('%s -c cleansstate' % testrecipe)
863 # Try modifying a recipe
864 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
865 self.track_for_cleanup(tempdir)
866 self.track_for_cleanup(self.workspacedir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500867 self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
Brad Bishop00e122a2019-10-05 11:10:57 -0400868 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500869 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
870 self.assertExists(os.path.join(tempdir, 'configure.ac'), 'Extracted source could not be found')
871 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
872 matches = glob.glob(os.path.join(self.workspacedir, 'appends', '%s_*.bbappend' % testrecipe))
873 self.assertTrue(matches, 'bbappend not created')
874 # Test devtool status
875 result = runCmd('devtool status')
876 self.assertIn(testrecipe, result.output)
877 self.assertIn(tempdir, result.output)
878 # Try building
879 bitbake(testrecipe)
880
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500881 def test_devtool_modify_virtual(self):
882 # Try modifying a virtual recipe
883 virtrecipe = 'virtual/make'
884 realrecipe = 'make'
885 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
886 self.track_for_cleanup(tempdir)
887 self.track_for_cleanup(self.workspacedir)
888 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
889 result = runCmd('devtool modify %s -x %s' % (virtrecipe, tempdir))
890 self.assertExists(os.path.join(tempdir, 'Makefile.am'), 'Extracted source could not be found')
891 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created')
892 matches = glob.glob(os.path.join(self.workspacedir, 'appends', '%s_*.bbappend' % realrecipe))
893 self.assertTrue(matches, 'bbappend not created %s' % result.output)
894 # Test devtool status
895 result = runCmd('devtool status')
896 self.assertNotIn(virtrecipe, result.output)
897 self.assertIn(realrecipe, result.output)
898 # Check git repo
899 self._check_src_repo(tempdir)
900 # This is probably sufficient
901
Andrew Geisslerf0343792020-11-18 10:42:21 -0600902 def test_devtool_modify_overrides(self):
903 # Try modifying a recipe with patches in overrides
904 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
905 self.track_for_cleanup(tempdir)
906 self.track_for_cleanup(self.workspacedir)
907 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
908 result = runCmd('devtool modify devtool-patch-overrides -x %s' % (tempdir))
909
910 self._check_src_repo(tempdir)
911 source = os.path.join(tempdir, "source")
912 def check(branch, expected):
913 runCmd('git -C %s checkout %s' % (tempdir, branch))
914 with open(source, "rt") as f:
915 content = f.read()
916 self.assertEquals(content, expected)
917 check('devtool', 'This is a test for something\n')
918 check('devtool-no-overrides', 'This is a test for something\n')
919 check('devtool-override-qemuarm', 'This is a test for qemuarm\n')
920 check('devtool-override-qemux86', 'This is a test for qemux86\n')
921
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800922class DevtoolUpdateTests(DevtoolBase):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500923
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500924 def test_devtool_update_recipe(self):
925 # Check preconditions
926 testrecipe = 'minicom'
927 bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
928 recipefile = bb_vars['FILE']
929 src_uri = bb_vars['SRC_URI']
930 self.assertNotIn('git://', src_uri, 'This test expects the %s recipe to NOT be a git recipe' % testrecipe)
931 self._check_repo_status(os.path.dirname(recipefile), [])
932 # First, modify a recipe
933 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
934 self.track_for_cleanup(tempdir)
935 self.track_for_cleanup(self.workspacedir)
936 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
937 # (don't bother with cleaning the recipe on teardown, we won't be building it)
938 # We don't use -x here so that we test the behaviour of devtool modify without it
939 result = runCmd('devtool modify %s %s' % (testrecipe, tempdir))
940 # Check git repo
941 self._check_src_repo(tempdir)
942 # Add a couple of commits
943 # FIXME: this only tests adding, need to also test update and remove
944 result = runCmd('echo "Additional line" >> README', cwd=tempdir)
945 result = runCmd('git commit -a -m "Change the README"', cwd=tempdir)
946 result = runCmd('echo "A new file" > devtool-new-file', cwd=tempdir)
947 result = runCmd('git add devtool-new-file', cwd=tempdir)
948 result = runCmd('git commit -m "Add a new file"', cwd=tempdir)
949 self.add_command_to_tearDown('cd %s; rm %s/*.patch; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
950 result = runCmd('devtool update-recipe %s' % testrecipe)
951 expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)),
952 ('??', '.*/0001-Change-the-README.patch$'),
953 ('??', '.*/0002-Add-a-new-file.patch$')]
954 self._check_repo_status(os.path.dirname(recipefile), expected_status)
955
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500956 def test_devtool_update_recipe_git(self):
957 # Check preconditions
Patrick Williams7784c422022-11-17 07:29:11 -0600958 testrecipe = 'mtd-utils-selftest'
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500959 bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
960 recipefile = bb_vars['FILE']
961 src_uri = bb_vars['SRC_URI']
962 self.assertIn('git://', src_uri, 'This test expects the %s recipe to be a git recipe' % testrecipe)
963 patches = []
964 for entry in src_uri.split():
965 if entry.startswith('file://') and entry.endswith('.patch'):
966 patches.append(entry[7:].split(';')[0])
967 self.assertGreater(len(patches), 0, 'The %s recipe does not appear to contain any patches, so this test will not be effective' % testrecipe)
968 self._check_repo_status(os.path.dirname(recipefile), [])
969 # First, modify a recipe
970 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
971 self.track_for_cleanup(tempdir)
972 self.track_for_cleanup(self.workspacedir)
973 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
974 # (don't bother with cleaning the recipe on teardown, we won't be building it)
975 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
976 # Check git repo
977 self._check_src_repo(tempdir)
978 # Add a couple of commits
979 # FIXME: this only tests adding, need to also test update and remove
980 result = runCmd('echo "# Additional line" >> Makefile.am', cwd=tempdir)
981 result = runCmd('git commit -a -m "Change the Makefile"', cwd=tempdir)
982 result = runCmd('echo "A new file" > devtool-new-file', cwd=tempdir)
983 result = runCmd('git add devtool-new-file', cwd=tempdir)
984 result = runCmd('git commit -m "Add a new file"', cwd=tempdir)
985 self.add_command_to_tearDown('cd %s; rm -rf %s; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
986 result = runCmd('devtool update-recipe -m srcrev %s' % testrecipe)
987 expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile))] + \
988 [(' D', '.*/%s$' % patch) for patch in patches]
989 self._check_repo_status(os.path.dirname(recipefile), expected_status)
990
991 result = runCmd('git diff %s' % os.path.basename(recipefile), cwd=os.path.dirname(recipefile))
Andrew Geissler595f6302022-01-24 19:11:47 +0000992 addlines = ['SRCREV = ".*"', 'SRC_URI = "git://git.infradead.org/mtd-utils.git;branch=master"']
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500993 srcurilines = src_uri.split()
994 srcurilines[0] = 'SRC_URI = "' + srcurilines[0]
995 srcurilines.append('"')
996 removelines = ['SRCREV = ".*"'] + srcurilines
Andrew Geissler615f2f12022-07-15 14:00:58 -0500997 self._check_diff(result.output, addlines, removelines)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500998 # Now try with auto mode
999 runCmd('cd %s; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, os.path.basename(recipefile)))
1000 result = runCmd('devtool update-recipe %s' % testrecipe)
1001 result = runCmd('git rev-parse --show-toplevel', cwd=os.path.dirname(recipefile))
1002 topleveldir = result.output.strip()
1003 relpatchpath = os.path.join(os.path.relpath(os.path.dirname(recipefile), topleveldir), testrecipe)
1004 expected_status = [(' M', os.path.relpath(recipefile, topleveldir)),
1005 ('??', '%s/0001-Change-the-Makefile.patch' % relpatchpath),
1006 ('??', '%s/0002-Add-a-new-file.patch' % relpatchpath)]
1007 self._check_repo_status(os.path.dirname(recipefile), expected_status)
1008
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001009 def test_devtool_update_recipe_append(self):
1010 # Check preconditions
1011 testrecipe = 'mdadm'
1012 bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
1013 recipefile = bb_vars['FILE']
1014 src_uri = bb_vars['SRC_URI']
1015 self.assertNotIn('git://', src_uri, 'This test expects the %s recipe to NOT be a git recipe' % testrecipe)
1016 self._check_repo_status(os.path.dirname(recipefile), [])
1017 # First, modify a recipe
1018 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1019 tempsrcdir = os.path.join(tempdir, 'source')
1020 templayerdir = os.path.join(tempdir, 'layer')
1021 self.track_for_cleanup(tempdir)
1022 self.track_for_cleanup(self.workspacedir)
1023 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1024 # (don't bother with cleaning the recipe on teardown, we won't be building it)
1025 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempsrcdir))
1026 # Check git repo
1027 self._check_src_repo(tempsrcdir)
1028 # Add a commit
1029 result = runCmd("sed 's!\\(#define VERSION\\W*\"[^\"]*\\)\"!\\1-custom\"!' -i ReadMe.c", cwd=tempsrcdir)
1030 result = runCmd('git commit -a -m "Add our custom version"', cwd=tempsrcdir)
1031 self.add_command_to_tearDown('cd %s; rm -f %s/*.patch; git checkout .' % (os.path.dirname(recipefile), testrecipe))
1032 # Create a temporary layer and add it to bblayers.conf
1033 self._create_temp_layer(templayerdir, True, 'selftestupdaterecipe')
1034 # Create the bbappend
1035 result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir))
1036 self.assertNotIn('WARNING:', result.output)
1037 # Check recipe is still clean
1038 self._check_repo_status(os.path.dirname(recipefile), [])
1039 # Check bbappend was created
1040 splitpath = os.path.dirname(recipefile).split(os.sep)
1041 appenddir = os.path.join(templayerdir, splitpath[-2], splitpath[-1])
1042 bbappendfile = self._check_bbappend(testrecipe, recipefile, appenddir)
1043 patchfile = os.path.join(appenddir, testrecipe, '0001-Add-our-custom-version.patch')
1044 self.assertExists(patchfile, 'Patch file not created')
1045
1046 # Check bbappend contents
Patrick Williams213cb262021-08-07 19:21:33 -05001047 expectedlines = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001048 '\n',
1049 'SRC_URI += "file://0001-Add-our-custom-version.patch"\n',
1050 '\n']
1051 with open(bbappendfile, 'r') as f:
1052 self.assertEqual(expectedlines, f.readlines())
1053
1054 # Check we can run it again and bbappend isn't modified
1055 result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir))
1056 with open(bbappendfile, 'r') as f:
1057 self.assertEqual(expectedlines, f.readlines())
1058 # Drop new commit and check patch gets deleted
1059 result = runCmd('git reset HEAD^', cwd=tempsrcdir)
1060 result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir))
1061 self.assertNotExists(patchfile, 'Patch file not deleted')
Patrick Williams213cb262021-08-07 19:21:33 -05001062 expectedlines2 = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001063 '\n']
1064 with open(bbappendfile, 'r') as f:
1065 self.assertEqual(expectedlines2, f.readlines())
1066 # Put commit back and check we can run it if layer isn't in bblayers.conf
1067 os.remove(bbappendfile)
1068 result = runCmd('git commit -a -m "Add our custom version"', cwd=tempsrcdir)
1069 result = runCmd('bitbake-layers remove-layer %s' % templayerdir, cwd=self.builddir)
1070 result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir))
1071 self.assertIn('WARNING: Specified layer is not currently enabled in bblayers.conf', result.output)
1072 self.assertExists(patchfile, 'Patch file not created (with disabled layer)')
1073 with open(bbappendfile, 'r') as f:
1074 self.assertEqual(expectedlines, f.readlines())
1075 # Deleting isn't expected to work under these circumstances
1076
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001077 def test_devtool_update_recipe_append_git(self):
1078 # Check preconditions
Patrick Williams7784c422022-11-17 07:29:11 -06001079 testrecipe = 'mtd-utils-selftest'
Andrew Geissler517393d2023-01-13 08:55:19 -06001080 bb_vars = get_bb_vars(['FILE', 'SRC_URI', 'LAYERSERIES_CORENAMES'], testrecipe)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001081 recipefile = bb_vars['FILE']
1082 src_uri = bb_vars['SRC_URI']
Andrew Geissler517393d2023-01-13 08:55:19 -06001083 corenames = bb_vars['LAYERSERIES_CORENAMES']
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001084 self.assertIn('git://', src_uri, 'This test expects the %s recipe to be a git recipe' % testrecipe)
1085 for entry in src_uri.split():
1086 if entry.startswith('git://'):
1087 git_uri = entry
1088 break
1089 self._check_repo_status(os.path.dirname(recipefile), [])
1090 # First, modify a recipe
1091 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1092 tempsrcdir = os.path.join(tempdir, 'source')
1093 templayerdir = os.path.join(tempdir, 'layer')
1094 self.track_for_cleanup(tempdir)
1095 self.track_for_cleanup(self.workspacedir)
1096 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1097 # (don't bother with cleaning the recipe on teardown, we won't be building it)
1098 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempsrcdir))
1099 # Check git repo
1100 self._check_src_repo(tempsrcdir)
1101 # Add a commit
1102 result = runCmd('echo "# Additional line" >> Makefile.am', cwd=tempsrcdir)
1103 result = runCmd('git commit -a -m "Change the Makefile"', cwd=tempsrcdir)
1104 self.add_command_to_tearDown('cd %s; rm -f %s/*.patch; git checkout .' % (os.path.dirname(recipefile), testrecipe))
1105 # Create a temporary layer
1106 os.makedirs(os.path.join(templayerdir, 'conf'))
1107 with open(os.path.join(templayerdir, 'conf', 'layer.conf'), 'w') as f:
1108 f.write('BBPATH .= ":${LAYERDIR}"\n')
1109 f.write('BBFILES += "${LAYERDIR}/recipes-*/*/*.bbappend"\n')
1110 f.write('BBFILE_COLLECTIONS += "oeselftesttemplayer"\n')
1111 f.write('BBFILE_PATTERN_oeselftesttemplayer = "^${LAYERDIR}/"\n')
1112 f.write('BBFILE_PRIORITY_oeselftesttemplayer = "999"\n')
1113 f.write('BBFILE_PATTERN_IGNORE_EMPTY_oeselftesttemplayer = "1"\n')
Andrew Geissler517393d2023-01-13 08:55:19 -06001114 f.write('LAYERSERIES_COMPAT_oeselftesttemplayer = "%s"\n' % corenames)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001115 self.add_command_to_tearDown('bitbake-layers remove-layer %s || true' % templayerdir)
1116 result = runCmd('bitbake-layers add-layer %s' % templayerdir, cwd=self.builddir)
1117 # Create the bbappend
1118 result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir))
1119 self.assertNotIn('WARNING:', result.output)
1120 # Check recipe is still clean
1121 self._check_repo_status(os.path.dirname(recipefile), [])
1122 # Check bbappend was created
1123 splitpath = os.path.dirname(recipefile).split(os.sep)
1124 appenddir = os.path.join(templayerdir, splitpath[-2], splitpath[-1])
1125 bbappendfile = self._check_bbappend(testrecipe, recipefile, appenddir)
1126 self.assertNotExists(os.path.join(appenddir, testrecipe), 'Patch directory should not be created')
1127
1128 # Check bbappend contents
1129 result = runCmd('git rev-parse HEAD', cwd=tempsrcdir)
1130 expectedlines = set(['SRCREV = "%s"\n' % result.output,
1131 '\n',
1132 'SRC_URI = "%s"\n' % git_uri,
1133 '\n'])
1134 with open(bbappendfile, 'r') as f:
1135 self.assertEqual(expectedlines, set(f.readlines()))
1136
1137 # Check we can run it again and bbappend isn't modified
1138 result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir))
1139 with open(bbappendfile, 'r') as f:
1140 self.assertEqual(expectedlines, set(f.readlines()))
1141 # Drop new commit and check SRCREV changes
1142 result = runCmd('git reset HEAD^', cwd=tempsrcdir)
1143 result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir))
1144 self.assertNotExists(os.path.join(appenddir, testrecipe), 'Patch directory should not be created')
1145 result = runCmd('git rev-parse HEAD', cwd=tempsrcdir)
1146 expectedlines = set(['SRCREV = "%s"\n' % result.output,
1147 '\n',
1148 'SRC_URI = "%s"\n' % git_uri,
1149 '\n'])
1150 with open(bbappendfile, 'r') as f:
1151 self.assertEqual(expectedlines, set(f.readlines()))
1152 # Put commit back and check we can run it if layer isn't in bblayers.conf
1153 os.remove(bbappendfile)
1154 result = runCmd('git commit -a -m "Change the Makefile"', cwd=tempsrcdir)
1155 result = runCmd('bitbake-layers remove-layer %s' % templayerdir, cwd=self.builddir)
1156 result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir))
1157 self.assertIn('WARNING: Specified layer is not currently enabled in bblayers.conf', result.output)
1158 self.assertNotExists(os.path.join(appenddir, testrecipe), 'Patch directory should not be created')
1159 result = runCmd('git rev-parse HEAD', cwd=tempsrcdir)
1160 expectedlines = set(['SRCREV = "%s"\n' % result.output,
1161 '\n',
1162 'SRC_URI = "%s"\n' % git_uri,
1163 '\n'])
1164 with open(bbappendfile, 'r') as f:
1165 self.assertEqual(expectedlines, set(f.readlines()))
1166 # Deleting isn't expected to work under these circumstances
1167
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001168 def test_devtool_update_recipe_local_files(self):
1169 """Check that local source files are copied over instead of patched"""
1170 testrecipe = 'makedevs'
1171 recipefile = get_bb_var('FILE', testrecipe)
1172 # Setup srctree for modifying the recipe
1173 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1174 self.track_for_cleanup(tempdir)
1175 self.track_for_cleanup(self.workspacedir)
1176 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1177 # (don't bother with cleaning the recipe on teardown, we won't be
1178 # building it)
1179 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
1180 # Check git repo
1181 self._check_src_repo(tempdir)
1182 # Try building just to ensure we haven't broken that
1183 bitbake("%s" % testrecipe)
1184 # Edit / commit local source
1185 runCmd('echo "/* Foobar */" >> oe-local-files/makedevs.c', cwd=tempdir)
1186 runCmd('echo "Foo" > oe-local-files/new-local', cwd=tempdir)
1187 runCmd('echo "Bar" > new-file', cwd=tempdir)
1188 runCmd('git add new-file', cwd=tempdir)
1189 runCmd('git commit -m "Add new file"', cwd=tempdir)
1190 self.add_command_to_tearDown('cd %s; git clean -fd .; git checkout .' %
1191 os.path.dirname(recipefile))
1192 runCmd('devtool update-recipe %s' % testrecipe)
1193 expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)),
1194 (' M', '.*/makedevs/makedevs.c$'),
1195 ('??', '.*/makedevs/new-local$'),
1196 ('??', '.*/makedevs/0001-Add-new-file.patch$')]
1197 self._check_repo_status(os.path.dirname(recipefile), expected_status)
1198
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001199 def test_devtool_update_recipe_local_files_2(self):
1200 """Check local source files support when oe-local-files is in Git"""
Brad Bishop316dfdd2018-06-25 12:45:53 -04001201 testrecipe = 'devtool-test-local'
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001202 recipefile = get_bb_var('FILE', testrecipe)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001203 recipedir = os.path.dirname(recipefile)
1204 result = runCmd('git status --porcelain .', cwd=recipedir)
1205 if result.output.strip():
1206 self.fail('Recipe directory for %s contains uncommitted changes' % testrecipe)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001207 # Setup srctree for modifying the recipe
1208 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1209 self.track_for_cleanup(tempdir)
1210 self.track_for_cleanup(self.workspacedir)
1211 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1212 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
1213 # Check git repo
1214 self._check_src_repo(tempdir)
1215 # Add oe-local-files to Git
1216 runCmd('rm oe-local-files/.gitignore', cwd=tempdir)
1217 runCmd('git add oe-local-files', cwd=tempdir)
1218 runCmd('git commit -m "Add local sources"', cwd=tempdir)
1219 # Edit / commit local sources
Brad Bishop316dfdd2018-06-25 12:45:53 -04001220 runCmd('echo "# Foobar" >> oe-local-files/file1', cwd=tempdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001221 runCmd('git commit -am "Edit existing file"', cwd=tempdir)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001222 runCmd('git rm oe-local-files/file2', cwd=tempdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001223 runCmd('git commit -m"Remove file"', cwd=tempdir)
1224 runCmd('echo "Foo" > oe-local-files/new-local', cwd=tempdir)
1225 runCmd('git add oe-local-files/new-local', cwd=tempdir)
1226 runCmd('git commit -m "Add new local file"', cwd=tempdir)
1227 runCmd('echo "Gar" > new-file', cwd=tempdir)
1228 runCmd('git add new-file', cwd=tempdir)
1229 runCmd('git commit -m "Add new file"', cwd=tempdir)
1230 self.add_command_to_tearDown('cd %s; git clean -fd .; git checkout .' %
1231 os.path.dirname(recipefile))
1232 # Checkout unmodified file to working copy -> devtool should still pick
1233 # the modified version from HEAD
Brad Bishop316dfdd2018-06-25 12:45:53 -04001234 runCmd('git checkout HEAD^ -- oe-local-files/file1', cwd=tempdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001235 runCmd('devtool update-recipe %s' % testrecipe)
1236 expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)),
Brad Bishop316dfdd2018-06-25 12:45:53 -04001237 (' M', '.*/file1$'),
1238 (' D', '.*/file2$'),
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001239 ('??', '.*/new-local$'),
1240 ('??', '.*/0001-Add-new-file.patch$')]
1241 self._check_repo_status(os.path.dirname(recipefile), expected_status)
1242
Andrew Geissler4ed12e12020-06-05 18:00:41 -05001243 def test_devtool_update_recipe_with_gitignore(self):
1244 # First, modify the recipe
1245 testrecipe = 'devtool-test-ignored'
1246 bb_vars = get_bb_vars(['FILE'], testrecipe)
1247 recipefile = bb_vars['FILE']
1248 patchfile = os.path.join(os.path.dirname(recipefile), testrecipe, testrecipe + '.patch')
1249 newpatchfile = os.path.join(os.path.dirname(recipefile), testrecipe, testrecipe + '.patch.expected')
1250 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1251 self.track_for_cleanup(tempdir)
1252 self.track_for_cleanup(self.workspacedir)
1253 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1254 # (don't bother with cleaning the recipe on teardown, we won't be building it)
1255 result = runCmd('devtool modify %s' % testrecipe)
1256 self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
1257 result = runCmd('devtool finish --force-patch-refresh %s meta-selftest' % testrecipe)
1258 # Check recipe got changed as expected
1259 with open(newpatchfile, 'r') as f:
1260 desiredlines = f.readlines()
1261 with open(patchfile, 'r') as f:
1262 newlines = f.readlines()
1263 # Ignore the initial lines, because oe-selftest creates own meta-selftest repo
1264 # which changes the metadata subject which is added into the patch, but keep
1265 # .patch.expected as it is in case someone runs devtool finish --force-patch-refresh
1266 # devtool-test-ignored manually, then it should generate exactly the same .patch file
1267 self.assertEqual(desiredlines[5:], newlines[5:])
1268
1269 def test_devtool_update_recipe_long_filename(self):
1270 # First, modify the recipe
1271 testrecipe = 'devtool-test-long-filename'
1272 bb_vars = get_bb_vars(['FILE'], testrecipe)
1273 recipefile = bb_vars['FILE']
1274 patchfilename = '0001-I-ll-patch-you-only-if-devtool-lets-me-to-do-it-corr.patch'
1275 patchfile = os.path.join(os.path.dirname(recipefile), testrecipe, patchfilename)
1276 newpatchfile = os.path.join(os.path.dirname(recipefile), testrecipe, patchfilename + '.expected')
1277 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1278 self.track_for_cleanup(tempdir)
1279 self.track_for_cleanup(self.workspacedir)
1280 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1281 # (don't bother with cleaning the recipe on teardown, we won't be building it)
1282 result = runCmd('devtool modify %s' % testrecipe)
1283 self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
1284 result = runCmd('devtool finish --force-patch-refresh %s meta-selftest' % testrecipe)
1285 # Check recipe got changed as expected
1286 with open(newpatchfile, 'r') as f:
1287 desiredlines = f.readlines()
1288 with open(patchfile, 'r') as f:
1289 newlines = f.readlines()
1290 # Ignore the initial lines, because oe-selftest creates own meta-selftest repo
1291 # which changes the metadata subject which is added into the patch, but keep
1292 # .patch.expected as it is in case someone runs devtool finish --force-patch-refresh
1293 # devtool-test-ignored manually, then it should generate exactly the same .patch file
1294 self.assertEqual(desiredlines[5:], newlines[5:])
1295
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001296 def test_devtool_update_recipe_local_files_3(self):
1297 # First, modify the recipe
1298 testrecipe = 'devtool-test-localonly'
1299 bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
1300 recipefile = bb_vars['FILE']
1301 src_uri = bb_vars['SRC_URI']
1302 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1303 self.track_for_cleanup(tempdir)
1304 self.track_for_cleanup(self.workspacedir)
1305 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1306 # (don't bother with cleaning the recipe on teardown, we won't be building it)
1307 result = runCmd('devtool modify %s' % testrecipe)
1308 # Modify one file
1309 runCmd('echo "Another line" >> file2', cwd=os.path.join(self.workspacedir, 'sources', testrecipe, 'oe-local-files'))
1310 self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
1311 result = runCmd('devtool update-recipe %s' % testrecipe)
1312 expected_status = [(' M', '.*/%s/file2$' % testrecipe)]
1313 self._check_repo_status(os.path.dirname(recipefile), expected_status)
1314
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001315 def test_devtool_update_recipe_local_patch_gz(self):
1316 # First, modify the recipe
1317 testrecipe = 'devtool-test-patch-gz'
1318 if get_bb_var('DISTRO') == 'poky-tiny':
1319 self.skipTest("The DISTRO 'poky-tiny' does not provide the dependencies needed by %s" % testrecipe)
1320 bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
1321 recipefile = bb_vars['FILE']
1322 src_uri = bb_vars['SRC_URI']
1323 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1324 self.track_for_cleanup(tempdir)
1325 self.track_for_cleanup(self.workspacedir)
1326 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1327 # (don't bother with cleaning the recipe on teardown, we won't be building it)
1328 result = runCmd('devtool modify %s' % testrecipe)
1329 # Modify one file
1330 srctree = os.path.join(self.workspacedir, 'sources', testrecipe)
1331 runCmd('echo "Another line" >> README', cwd=srctree)
1332 runCmd('git commit -a --amend --no-edit', cwd=srctree)
1333 self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
1334 result = runCmd('devtool update-recipe %s' % testrecipe)
1335 expected_status = [(' M', '.*/%s/readme.patch.gz$' % testrecipe)]
1336 self._check_repo_status(os.path.dirname(recipefile), expected_status)
1337 patch_gz = os.path.join(os.path.dirname(recipefile), testrecipe, 'readme.patch.gz')
1338 result = runCmd('file %s' % patch_gz)
1339 if 'gzip compressed data' not in result.output:
1340 self.fail('New patch file is not gzipped - file reports:\n%s' % result.output)
1341
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001342 def test_devtool_update_recipe_local_files_subdir(self):
1343 # Try devtool update-recipe on a recipe that has a file with subdir= set in
1344 # SRC_URI such that it overwrites a file that was in an archive that
1345 # was also in SRC_URI
1346 # First, modify the recipe
1347 testrecipe = 'devtool-test-subdir'
1348 bb_vars = get_bb_vars(['FILE', 'SRC_URI'], testrecipe)
1349 recipefile = bb_vars['FILE']
1350 src_uri = bb_vars['SRC_URI']
1351 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1352 self.track_for_cleanup(tempdir)
1353 self.track_for_cleanup(self.workspacedir)
1354 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1355 # (don't bother with cleaning the recipe on teardown, we won't be building it)
1356 result = runCmd('devtool modify %s' % testrecipe)
1357 testfile = os.path.join(self.workspacedir, 'sources', testrecipe, 'testfile')
1358 self.assertExists(testfile, 'Extracted source could not be found')
1359 with open(testfile, 'r') as f:
1360 contents = f.read().rstrip()
1361 self.assertEqual(contents, 'Modified version', 'File has apparently not been overwritten as it should have been')
1362 # Test devtool update-recipe without modifying any files
1363 self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
1364 result = runCmd('devtool update-recipe %s' % testrecipe)
1365 expected_status = []
1366 self._check_repo_status(os.path.dirname(recipefile), expected_status)
1367
Andrew Geissler615f2f12022-07-15 14:00:58 -05001368 def test_devtool_finish_modify_git_subdir(self):
1369 # Check preconditions
1370 testrecipe = 'dos2unix'
1371 bb_vars = get_bb_vars(['SRC_URI', 'S', 'WORKDIR', 'FILE'], testrecipe)
1372 self.assertIn('git://', bb_vars['SRC_URI'], 'This test expects the %s recipe to be a git recipe' % testrecipe)
1373 workdir_git = '%s/git/' % bb_vars['WORKDIR']
1374 if not bb_vars['S'].startswith(workdir_git):
1375 self.fail('This test expects the %s recipe to be building from a subdirectory of the git repo' % testrecipe)
1376 subdir = bb_vars['S'].split(workdir_git, 1)[1]
1377 # Clean up anything in the workdir/sysroot/sstate cache
1378 bitbake('%s -c cleansstate' % testrecipe)
1379 # Try modifying a recipe
1380 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1381 self.track_for_cleanup(tempdir)
1382 self.track_for_cleanup(self.workspacedir)
1383 self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
1384 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1385 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
1386 testsrcfile = os.path.join(tempdir, subdir, 'dos2unix.c')
1387 self.assertExists(testsrcfile, 'Extracted source could not be found')
1388 self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created. devtool output: %s' % result.output)
1389 self.assertNotExists(os.path.join(tempdir, subdir, '.git'), 'Subdirectory has been initialised as a git repo')
1390 # Check git repo
1391 self._check_src_repo(tempdir)
1392 # Modify file
1393 runCmd("sed -i '1s:^:/* Add a comment */\\n:' %s" % testsrcfile)
1394 result = runCmd('git commit -a -m "Add a comment"', cwd=tempdir)
1395 # Now try updating original recipe
1396 recipefile = bb_vars['FILE']
1397 recipedir = os.path.dirname(recipefile)
1398 self.add_command_to_tearDown('cd %s; rm -f %s/*.patch; git checkout .' % (recipedir, testrecipe))
1399 result = runCmd('devtool update-recipe %s' % testrecipe)
1400 expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)),
1401 ('??', '.*/%s/%s/$' % (testrecipe, testrecipe))]
1402 self._check_repo_status(os.path.dirname(recipefile), expected_status)
1403 result = runCmd('git diff %s' % os.path.basename(recipefile), cwd=os.path.dirname(recipefile))
1404 removelines = ['SRC_URI = "git://.*"']
1405 addlines = [
1406 'SRC_URI = "git://.* \\\\',
1407 'file://0001-Add-a-comment.patch;patchdir=.. \\\\',
1408 '"'
1409 ]
1410 self._check_diff(result.output, addlines, removelines)
1411 # Put things back so we can run devtool finish on a different layer
1412 runCmd('cd %s; rm -f %s/*.patch; git checkout .' % (recipedir, testrecipe))
1413 # Run devtool finish
1414 res = re.search('recipes-.*', recipedir)
1415 self.assertTrue(res, 'Unable to find recipe subdirectory')
1416 recipesubdir = res[0]
1417 self.add_command_to_tearDown('rm -rf %s' % os.path.join(self.testlayer_path, recipesubdir))
1418 result = runCmd('devtool finish %s meta-selftest' % testrecipe)
1419 # Check bbappend file contents
1420 appendfn = os.path.join(self.testlayer_path, recipesubdir, '%s_%%.bbappend' % testrecipe)
1421 with open(appendfn, 'r') as f:
1422 appendlines = f.readlines()
1423 expected_appendlines = [
1424 'FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
1425 '\n',
1426 'SRC_URI += "file://0001-Add-a-comment.patch;patchdir=.."\n',
1427 '\n'
1428 ]
1429 self.assertEqual(appendlines, expected_appendlines)
1430 self.assertExists(os.path.join(os.path.dirname(appendfn), testrecipe, '0001-Add-a-comment.patch'))
1431 # Try building
1432 bitbake('%s -c patch' % testrecipe)
1433
1434
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001435class DevtoolExtractTests(DevtoolBase):
1436
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001437 def test_devtool_extract(self):
1438 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1439 # Try devtool extract
1440 self.track_for_cleanup(tempdir)
1441 self.track_for_cleanup(self.workspacedir)
1442 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1443 result = runCmd('devtool extract matchbox-terminal %s' % tempdir)
1444 self.assertExists(os.path.join(tempdir, 'Makefile.am'), 'Extracted source could not be found')
1445 self._check_src_repo(tempdir)
1446
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001447 def test_devtool_extract_virtual(self):
1448 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1449 # Try devtool extract
1450 self.track_for_cleanup(tempdir)
1451 self.track_for_cleanup(self.workspacedir)
1452 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1453 result = runCmd('devtool extract virtual/make %s' % tempdir)
1454 self.assertExists(os.path.join(tempdir, 'Makefile.am'), 'Extracted source could not be found')
1455 self._check_src_repo(tempdir)
1456
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001457 def test_devtool_reset_all(self):
1458 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1459 self.track_for_cleanup(tempdir)
1460 self.track_for_cleanup(self.workspacedir)
1461 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1462 testrecipe1 = 'mdadm'
1463 testrecipe2 = 'cronie'
1464 result = runCmd('devtool modify -x %s %s' % (testrecipe1, os.path.join(tempdir, testrecipe1)))
1465 result = runCmd('devtool modify -x %s %s' % (testrecipe2, os.path.join(tempdir, testrecipe2)))
1466 result = runCmd('devtool build %s' % testrecipe1)
1467 result = runCmd('devtool build %s' % testrecipe2)
1468 stampprefix1 = get_bb_var('STAMP', testrecipe1)
1469 self.assertTrue(stampprefix1, 'Unable to get STAMP value for recipe %s' % testrecipe1)
1470 stampprefix2 = get_bb_var('STAMP', testrecipe2)
1471 self.assertTrue(stampprefix2, 'Unable to get STAMP value for recipe %s' % testrecipe2)
1472 result = runCmd('devtool reset -a')
1473 self.assertIn(testrecipe1, result.output)
1474 self.assertIn(testrecipe2, result.output)
1475 result = runCmd('devtool status')
1476 self.assertNotIn(testrecipe1, result.output)
1477 self.assertNotIn(testrecipe2, result.output)
1478 matches1 = glob.glob(stampprefix1 + '*')
1479 self.assertFalse(matches1, 'Stamp files exist for recipe %s that should have been cleaned' % testrecipe1)
1480 matches2 = glob.glob(stampprefix2 + '*')
1481 self.assertFalse(matches2, 'Stamp files exist for recipe %s that should have been cleaned' % testrecipe2)
1482
Patrick Williams45852732022-04-02 08:58:32 -05001483 @OETestTag("runqemu")
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001484 def test_devtool_deploy_target(self):
1485 # NOTE: Whilst this test would seemingly be better placed as a runtime test,
1486 # unfortunately the runtime tests run under bitbake and you can't run
1487 # devtool within bitbake (since devtool needs to run bitbake itself).
1488 # Additionally we are testing build-time functionality as well, so
1489 # really this has to be done as an oe-selftest test.
1490 #
1491 # Check preconditions
1492 machine = get_bb_var('MACHINE')
1493 if not machine.startswith('qemu'):
1494 self.skipTest('This test only works with qemu machines')
1495 if not os.path.exists('/etc/runqemu-nosudo'):
1496 self.skipTest('You must set up tap devices with scripts/runqemu-gen-tapdevs before running this test')
1497 result = runCmd('PATH="$PATH:/sbin:/usr/sbin" ip tuntap show', ignore_status=True)
1498 if result.status != 0:
1499 result = runCmd('PATH="$PATH:/sbin:/usr/sbin" ifconfig -a', ignore_status=True)
1500 if result.status != 0:
1501 self.skipTest('Failed to determine if tap devices exist with ifconfig or ip: %s' % result.output)
1502 for line in result.output.splitlines():
1503 if line.startswith('tap'):
1504 break
1505 else:
1506 self.skipTest('No tap devices found - you must set up tap devices with scripts/runqemu-gen-tapdevs before running this test')
1507 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1508 # Definitions
1509 testrecipe = 'mdadm'
1510 testfile = '/sbin/mdadm'
1511 testimage = 'oe-selftest-image'
1512 testcommand = '/sbin/mdadm --help'
1513 # Build an image to run
1514 bitbake("%s qemu-native qemu-helper-native" % testimage)
1515 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
1516 self.add_command_to_tearDown('bitbake -c clean %s' % testimage)
1517 self.add_command_to_tearDown('rm -f %s/%s*' % (deploy_dir_image, testimage))
1518 # Clean recipe so the first deploy will fail
1519 bitbake("%s -c clean" % testrecipe)
1520 # Try devtool modify
1521 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1522 self.track_for_cleanup(tempdir)
1523 self.track_for_cleanup(self.workspacedir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001524 self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
Brad Bishop00e122a2019-10-05 11:10:57 -04001525 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001526 result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
1527 # Test that deploy-target at this point fails (properly)
1528 result = runCmd('devtool deploy-target -n %s root@localhost' % testrecipe, ignore_status=True)
1529 self.assertNotEqual(result.output, 0, 'devtool deploy-target should have failed, output: %s' % result.output)
1530 self.assertNotIn(result.output, 'Traceback', 'devtool deploy-target should have failed with a proper error not a traceback, output: %s' % result.output)
1531 result = runCmd('devtool build %s' % testrecipe)
1532 # First try a dry-run of deploy-target
1533 result = runCmd('devtool deploy-target -n %s root@localhost' % testrecipe)
1534 self.assertIn(' %s' % testfile, result.output)
1535 # Boot the image
1536 with runqemu(testimage) as qemu:
1537 # Now really test deploy-target
1538 result = runCmd('devtool deploy-target -c %s root@%s' % (testrecipe, qemu.ip))
1539 # Run a test command to see if it was installed properly
1540 sshargs = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
1541 result = runCmd('ssh %s root@%s %s' % (sshargs, qemu.ip, testcommand))
1542 # Check if it deployed all of the files with the right ownership/perms
1543 # First look on the host - need to do this under pseudo to get the correct ownership/perms
1544 bb_vars = get_bb_vars(['D', 'FAKEROOTENV', 'FAKEROOTCMD'], testrecipe)
1545 installdir = bb_vars['D']
1546 fakerootenv = bb_vars['FAKEROOTENV']
1547 fakerootcmd = bb_vars['FAKEROOTCMD']
Brad Bishop19323692019-04-05 15:28:33 -04001548 result = runCmd('%s %s find . -type f -exec ls -l {} \\;' % (fakerootenv, fakerootcmd), cwd=installdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001549 filelist1 = self._process_ls_output(result.output)
1550
1551 # Now look on the target
1552 tempdir2 = tempfile.mkdtemp(prefix='devtoolqa')
1553 self.track_for_cleanup(tempdir2)
1554 tmpfilelist = os.path.join(tempdir2, 'files.txt')
1555 with open(tmpfilelist, 'w') as f:
1556 for line in filelist1:
1557 splitline = line.split()
1558 f.write(splitline[-1] + '\n')
1559 result = runCmd('cat %s | ssh -q %s root@%s \'xargs ls -l\'' % (tmpfilelist, sshargs, qemu.ip))
1560 filelist2 = self._process_ls_output(result.output)
1561 filelist1.sort(key=lambda item: item.split()[-1])
1562 filelist2.sort(key=lambda item: item.split()[-1])
1563 self.assertEqual(filelist1, filelist2)
1564 # Test undeploy-target
1565 result = runCmd('devtool undeploy-target -c %s root@%s' % (testrecipe, qemu.ip))
1566 result = runCmd('ssh %s root@%s %s' % (sshargs, qemu.ip, testcommand), ignore_status=True)
1567 self.assertNotEqual(result, 0, 'undeploy-target did not remove command as it should have')
1568
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001569 def test_devtool_build_image(self):
1570 """Test devtool build-image plugin"""
1571 # Check preconditions
1572 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1573 image = 'core-image-minimal'
1574 self.track_for_cleanup(self.workspacedir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001575 self.add_command_to_tearDown('bitbake -c clean %s' % image)
Brad Bishop00e122a2019-10-05 11:10:57 -04001576 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001577 bitbake('%s -c clean' % image)
1578 # Add target and native recipes to workspace
1579 recipes = ['mdadm', 'parted-native']
1580 for recipe in recipes:
1581 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1582 self.track_for_cleanup(tempdir)
1583 self.add_command_to_tearDown('bitbake -c clean %s' % recipe)
1584 runCmd('devtool modify %s -x %s' % (recipe, tempdir))
1585 # Try to build image
1586 result = runCmd('devtool build-image %s' % image)
1587 self.assertNotEqual(result, 0, 'devtool build-image failed')
1588 # Check if image contains expected packages
1589 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
1590 image_link_name = get_bb_var('IMAGE_LINK_NAME', image)
1591 reqpkgs = [item for item in recipes if not item.endswith('-native')]
1592 with open(os.path.join(deploy_dir_image, image_link_name + '.manifest'), 'r') as f:
1593 for line in f:
1594 splitval = line.split()
1595 if splitval:
1596 pkg = splitval[0]
1597 if pkg in reqpkgs:
1598 reqpkgs.remove(pkg)
1599 if reqpkgs:
1600 self.fail('The following packages were not present in the image as expected: %s' % ', '.join(reqpkgs))
1601
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001602class DevtoolUpgradeTests(DevtoolBase):
1603
Patrick Williams45852732022-04-02 08:58:32 -05001604 def setUp(self):
1605 super().setUp()
1606 try:
1607 runCmd("git config --global user.name")
1608 runCmd("git config --global user.email")
1609 except:
1610 self.skip("Git user.name and user.email must be set")
1611
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001612 def test_devtool_upgrade(self):
1613 # Check preconditions
1614 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1615 self.track_for_cleanup(self.workspacedir)
1616 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1617 # Check parameters
1618 result = runCmd('devtool upgrade -h')
1619 for param in 'recipename srctree --version -V --branch -b --keep-temp --no-patch'.split():
1620 self.assertIn(param, result.output)
1621 # For the moment, we are using a real recipe.
1622 recipe = 'devtool-upgrade-test1'
1623 version = '1.6.0'
1624 oldrecipefile = get_bb_var('FILE', recipe)
1625 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1626 self.track_for_cleanup(tempdir)
1627 # Check that recipe is not already under devtool control
1628 result = runCmd('devtool status')
1629 self.assertNotIn(recipe, result.output)
1630 # Check upgrade. Code does not check if new PV is older or newer that current PV, so, it may be that
1631 # we are downgrading instead of upgrading.
1632 result = runCmd('devtool upgrade %s %s -V %s' % (recipe, tempdir, version))
1633 # Check if srctree at least is populated
1634 self.assertTrue(len(os.listdir(tempdir)) > 0, 'srctree (%s) should be populated with new (%s) source code' % (tempdir, version))
1635 # Check new recipe subdirectory is present
1636 self.assertExists(os.path.join(self.workspacedir, 'recipes', recipe, '%s-%s' % (recipe, version)), 'Recipe folder should exist')
1637 # Check new recipe file is present
1638 newrecipefile = os.path.join(self.workspacedir, 'recipes', recipe, '%s_%s.bb' % (recipe, version))
1639 self.assertExists(newrecipefile, 'Recipe file should exist after upgrade')
1640 # Check devtool status and make sure recipe is present
1641 result = runCmd('devtool status')
1642 self.assertIn(recipe, result.output)
1643 self.assertIn(tempdir, result.output)
1644 # Check recipe got changed as expected
1645 with open(oldrecipefile + '.upgraded', 'r') as f:
1646 desiredlines = f.readlines()
1647 with open(newrecipefile, 'r') as f:
1648 newlines = f.readlines()
1649 self.assertEqual(desiredlines, newlines)
1650 # Check devtool reset recipe
1651 result = runCmd('devtool reset %s -n' % recipe)
1652 result = runCmd('devtool status')
1653 self.assertNotIn(recipe, result.output)
1654 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after resetting')
1655
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001656 def test_devtool_upgrade_git(self):
1657 # Check preconditions
1658 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1659 self.track_for_cleanup(self.workspacedir)
1660 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1661 recipe = 'devtool-upgrade-test2'
1662 commit = '6cc6077a36fe2648a5f993fe7c16c9632f946517'
1663 oldrecipefile = get_bb_var('FILE', recipe)
1664 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1665 self.track_for_cleanup(tempdir)
1666 # Check that recipe is not already under devtool control
1667 result = runCmd('devtool status')
1668 self.assertNotIn(recipe, result.output)
1669 # Check upgrade
1670 result = runCmd('devtool upgrade %s %s -S %s' % (recipe, tempdir, commit))
1671 # Check if srctree at least is populated
1672 self.assertTrue(len(os.listdir(tempdir)) > 0, 'srctree (%s) should be populated with new (%s) source code' % (tempdir, commit))
1673 # Check new recipe file is present
1674 newrecipefile = os.path.join(self.workspacedir, 'recipes', recipe, os.path.basename(oldrecipefile))
1675 self.assertExists(newrecipefile, 'Recipe file should exist after upgrade')
1676 # Check devtool status and make sure recipe is present
1677 result = runCmd('devtool status')
1678 self.assertIn(recipe, result.output)
1679 self.assertIn(tempdir, result.output)
1680 # Check recipe got changed as expected
1681 with open(oldrecipefile + '.upgraded', 'r') as f:
1682 desiredlines = f.readlines()
1683 with open(newrecipefile, 'r') as f:
1684 newlines = f.readlines()
1685 self.assertEqual(desiredlines, newlines)
1686 # Check devtool reset recipe
1687 result = runCmd('devtool reset %s -n' % recipe)
1688 result = runCmd('devtool status')
1689 self.assertNotIn(recipe, result.output)
1690 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after resetting')
1691
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001692 def test_devtool_layer_plugins(self):
1693 """Test that devtool can use plugins from other layers.
1694
1695 This test executes the selftest-reverse command from meta-selftest."""
1696
1697 self.track_for_cleanup(self.workspacedir)
1698 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1699
1700 s = "Microsoft Made No Profit From Anyone's Zunes Yo"
1701 result = runCmd("devtool --quiet selftest-reverse \"%s\"" % s)
1702 self.assertEqual(result.output, s[::-1])
1703
1704 def _copy_file_with_cleanup(self, srcfile, basedstdir, *paths):
1705 dstdir = basedstdir
1706 self.assertExists(dstdir)
1707 for p in paths:
1708 dstdir = os.path.join(dstdir, p)
1709 if not os.path.exists(dstdir):
1710 os.makedirs(dstdir)
Andrew Geissler475cb722020-07-10 16:00:51 -05001711 if p == "lib":
1712 # Can race with other tests
1713 self.add_command_to_tearDown('rmdir --ignore-fail-on-non-empty %s' % dstdir)
1714 else:
1715 self.track_for_cleanup(dstdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001716 dstfile = os.path.join(dstdir, os.path.basename(srcfile))
1717 if srcfile != dstfile:
1718 shutil.copy(srcfile, dstfile)
1719 self.track_for_cleanup(dstfile)
1720
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001721 def test_devtool_load_plugin(self):
1722 """Test that devtool loads only the first found plugin in BBPATH."""
1723
1724 self.track_for_cleanup(self.workspacedir)
1725 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1726
1727 devtool = runCmd("which devtool")
1728 fromname = runCmd("devtool --quiet pluginfile")
1729 srcfile = fromname.output
1730 bbpath = get_bb_var('BBPATH')
1731 searchpath = bbpath.split(':') + [os.path.dirname(devtool.output)]
1732 plugincontent = []
1733 with open(srcfile) as fh:
1734 plugincontent = fh.readlines()
1735 try:
1736 self.assertIn('meta-selftest', srcfile, 'wrong bbpath plugin found')
1737 for path in searchpath:
1738 self._copy_file_with_cleanup(srcfile, path, 'lib', 'devtool')
1739 result = runCmd("devtool --quiet count")
1740 self.assertEqual(result.output, '1')
1741 result = runCmd("devtool --quiet multiloaded")
1742 self.assertEqual(result.output, "no")
1743 for path in searchpath:
1744 result = runCmd("devtool --quiet bbdir")
1745 self.assertEqual(result.output, path)
1746 os.unlink(os.path.join(result.output, 'lib', 'devtool', 'bbpath.py'))
1747 finally:
1748 with open(srcfile, 'w') as fh:
1749 fh.writelines(plugincontent)
1750
1751 def _setup_test_devtool_finish_upgrade(self):
1752 # Check preconditions
1753 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1754 self.track_for_cleanup(self.workspacedir)
1755 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1756 # Use a "real" recipe from meta-selftest
1757 recipe = 'devtool-upgrade-test1'
1758 oldversion = '1.5.3'
1759 newversion = '1.6.0'
1760 oldrecipefile = get_bb_var('FILE', recipe)
1761 recipedir = os.path.dirname(oldrecipefile)
1762 result = runCmd('git status --porcelain .', cwd=recipedir)
1763 if result.output.strip():
1764 self.fail('Recipe directory for %s contains uncommitted changes' % recipe)
1765 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1766 self.track_for_cleanup(tempdir)
1767 # Check that recipe is not already under devtool control
1768 result = runCmd('devtool status')
1769 self.assertNotIn(recipe, result.output)
1770 # Do the upgrade
1771 result = runCmd('devtool upgrade %s %s -V %s' % (recipe, tempdir, newversion))
1772 # Check devtool status and make sure recipe is present
1773 result = runCmd('devtool status')
1774 self.assertIn(recipe, result.output)
1775 self.assertIn(tempdir, result.output)
1776 # Make a change to the source
1777 result = runCmd('sed -i \'/^#include "pv.h"/a \\/* Here is a new comment *\\/\' src/pv/number.c', cwd=tempdir)
1778 result = runCmd('git status --porcelain', cwd=tempdir)
1779 self.assertIn('M src/pv/number.c', result.output)
1780 result = runCmd('git commit src/pv/number.c -m "Add a comment to the code"', cwd=tempdir)
1781 # Check if patch is there
1782 recipedir = os.path.dirname(oldrecipefile)
1783 olddir = os.path.join(recipedir, recipe + '-' + oldversion)
1784 patchfn = '0001-Add-a-note-line-to-the-quick-reference.patch'
Brad Bishop6dbb3162019-11-25 09:41:34 -05001785 backportedpatchfn = 'backported.patch'
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001786 self.assertExists(os.path.join(olddir, patchfn), 'Original patch file does not exist')
Brad Bishop6dbb3162019-11-25 09:41:34 -05001787 self.assertExists(os.path.join(olddir, backportedpatchfn), 'Backported patch file does not exist')
1788 return recipe, oldrecipefile, recipedir, olddir, newversion, patchfn, backportedpatchfn
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001789
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001790 def test_devtool_finish_upgrade_origlayer(self):
Brad Bishop6dbb3162019-11-25 09:41:34 -05001791 recipe, oldrecipefile, recipedir, olddir, newversion, patchfn, backportedpatchfn = self._setup_test_devtool_finish_upgrade()
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001792 # Ensure the recipe is where we think it should be (so that cleanup doesn't trash things)
1793 self.assertIn('/meta-selftest/', recipedir)
1794 # Try finish to the original layer
1795 self.add_command_to_tearDown('rm -rf %s ; cd %s ; git checkout %s' % (recipedir, os.path.dirname(recipedir), recipedir))
1796 result = runCmd('devtool finish %s meta-selftest' % recipe)
1797 result = runCmd('devtool status')
1798 self.assertNotIn(recipe, result.output, 'Recipe should have been reset by finish but wasn\'t')
1799 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish')
1800 self.assertNotExists(oldrecipefile, 'Old recipe file should have been deleted but wasn\'t')
1801 self.assertNotExists(os.path.join(olddir, patchfn), 'Old patch file should have been deleted but wasn\'t')
Brad Bishop6dbb3162019-11-25 09:41:34 -05001802 self.assertNotExists(os.path.join(olddir, backportedpatchfn), 'Old backported patch file should have been deleted but wasn\'t')
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001803 newrecipefile = os.path.join(recipedir, '%s_%s.bb' % (recipe, newversion))
1804 newdir = os.path.join(recipedir, recipe + '-' + newversion)
1805 self.assertExists(newrecipefile, 'New recipe file should have been copied into existing layer but wasn\'t')
1806 self.assertExists(os.path.join(newdir, patchfn), 'Patch file should have been copied into new directory but wasn\'t')
Brad Bishop6dbb3162019-11-25 09:41:34 -05001807 self.assertNotExists(os.path.join(newdir, backportedpatchfn), 'Backported patch file should not have been copied into new directory but was')
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001808 self.assertExists(os.path.join(newdir, '0002-Add-a-comment-to-the-code.patch'), 'New patch file should have been created but wasn\'t')
Brad Bishop6dbb3162019-11-25 09:41:34 -05001809 with open(newrecipefile, 'r') as f:
1810 newcontent = f.read()
1811 self.assertNotIn(backportedpatchfn, newcontent, "Backported patch should have been removed from the recipe but wasn't")
1812 self.assertIn(patchfn, newcontent, "Old patch should have not been removed from the recipe but was")
1813 self.assertIn("0002-Add-a-comment-to-the-code.patch", newcontent, "New patch should have been added to the recipe but wasn't")
1814 self.assertIn("http://www.ivarch.com/programs/sources/pv-${PV}.tar.gz", newcontent, "New recipe no longer has upstream source in SRC_URI")
1815
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001816
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001817 def test_devtool_finish_upgrade_otherlayer(self):
Brad Bishop6dbb3162019-11-25 09:41:34 -05001818 recipe, oldrecipefile, recipedir, olddir, newversion, patchfn, backportedpatchfn = self._setup_test_devtool_finish_upgrade()
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001819 # Ensure the recipe is where we think it should be (so that cleanup doesn't trash things)
1820 self.assertIn('/meta-selftest/', recipedir)
1821 # Try finish to a different layer - should create a bbappend
1822 # This cleanup isn't strictly necessary but do it anyway just in case it goes wrong and writes to here
1823 self.add_command_to_tearDown('rm -rf %s ; cd %s ; git checkout %s' % (recipedir, os.path.dirname(recipedir), recipedir))
1824 oe_core_dir = os.path.join(get_bb_var('COREBASE'), 'meta')
1825 newrecipedir = os.path.join(oe_core_dir, 'recipes-test', 'devtool')
1826 newrecipefile = os.path.join(newrecipedir, '%s_%s.bb' % (recipe, newversion))
1827 self.track_for_cleanup(newrecipedir)
1828 result = runCmd('devtool finish %s oe-core' % recipe)
1829 result = runCmd('devtool status')
1830 self.assertNotIn(recipe, result.output, 'Recipe should have been reset by finish but wasn\'t')
1831 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish')
1832 self.assertExists(oldrecipefile, 'Old recipe file should not have been deleted')
1833 self.assertExists(os.path.join(olddir, patchfn), 'Old patch file should not have been deleted')
Brad Bishop6dbb3162019-11-25 09:41:34 -05001834 self.assertExists(os.path.join(olddir, backportedpatchfn), 'Old backported patch file should not have been deleted')
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001835 newdir = os.path.join(newrecipedir, recipe + '-' + newversion)
1836 self.assertExists(newrecipefile, 'New recipe file should have been copied into existing layer but wasn\'t')
1837 self.assertExists(os.path.join(newdir, patchfn), 'Patch file should have been copied into new directory but wasn\'t')
Brad Bishop6dbb3162019-11-25 09:41:34 -05001838 self.assertNotExists(os.path.join(newdir, backportedpatchfn), 'Backported patch file should not have been copied into new directory but was')
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001839 self.assertExists(os.path.join(newdir, '0002-Add-a-comment-to-the-code.patch'), 'New patch file should have been created but wasn\'t')
Brad Bishop6dbb3162019-11-25 09:41:34 -05001840 with open(newrecipefile, 'r') as f:
1841 newcontent = f.read()
1842 self.assertNotIn(backportedpatchfn, newcontent, "Backported patch should have been removed from the recipe but wasn't")
1843 self.assertIn(patchfn, newcontent, "Old patch should have not been removed from the recipe but was")
1844 self.assertIn("0002-Add-a-comment-to-the-code.patch", newcontent, "New patch should have been added to the recipe but wasn't")
1845 self.assertIn("http://www.ivarch.com/programs/sources/pv-${PV}.tar.gz", newcontent, "New recipe no longer has upstream source in SRC_URI")
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001846
1847 def _setup_test_devtool_finish_modify(self):
1848 # Check preconditions
1849 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1850 # Try modifying a recipe
1851 self.track_for_cleanup(self.workspacedir)
1852 recipe = 'mdadm'
1853 oldrecipefile = get_bb_var('FILE', recipe)
1854 recipedir = os.path.dirname(oldrecipefile)
1855 result = runCmd('git status --porcelain .', cwd=recipedir)
1856 if result.output.strip():
1857 self.fail('Recipe directory for %s contains uncommitted changes' % recipe)
1858 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
1859 self.track_for_cleanup(tempdir)
1860 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1861 result = runCmd('devtool modify %s %s' % (recipe, tempdir))
1862 self.assertExists(os.path.join(tempdir, 'Makefile'), 'Extracted source could not be found')
1863 # Test devtool status
1864 result = runCmd('devtool status')
1865 self.assertIn(recipe, result.output)
1866 self.assertIn(tempdir, result.output)
1867 # Make a change to the source
1868 result = runCmd('sed -i \'/^#include "mdadm.h"/a \\/* Here is a new comment *\\/\' maps.c', cwd=tempdir)
1869 result = runCmd('git status --porcelain', cwd=tempdir)
1870 self.assertIn('M maps.c', result.output)
1871 result = runCmd('git commit maps.c -m "Add a comment to the code"', cwd=tempdir)
1872 for entry in os.listdir(recipedir):
1873 filesdir = os.path.join(recipedir, entry)
1874 if os.path.isdir(filesdir):
1875 break
1876 else:
1877 self.fail('Unable to find recipe files directory for %s' % recipe)
1878 return recipe, oldrecipefile, recipedir, filesdir
1879
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001880 def test_devtool_finish_modify_origlayer(self):
1881 recipe, oldrecipefile, recipedir, filesdir = self._setup_test_devtool_finish_modify()
1882 # Ensure the recipe is where we think it should be (so that cleanup doesn't trash things)
1883 self.assertIn('/meta/', recipedir)
1884 # Try finish to the original layer
1885 self.add_command_to_tearDown('rm -rf %s ; cd %s ; git checkout %s' % (recipedir, os.path.dirname(recipedir), recipedir))
1886 result = runCmd('devtool finish %s meta' % recipe)
1887 result = runCmd('devtool status')
1888 self.assertNotIn(recipe, result.output, 'Recipe should have been reset by finish but wasn\'t')
1889 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish')
1890 expected_status = [(' M', '.*/%s$' % os.path.basename(oldrecipefile)),
1891 ('??', '.*/.*-Add-a-comment-to-the-code.patch$')]
1892 self._check_repo_status(recipedir, expected_status)
1893
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001894 def test_devtool_finish_modify_otherlayer(self):
1895 recipe, oldrecipefile, recipedir, filesdir = self._setup_test_devtool_finish_modify()
1896 # Ensure the recipe is where we think it should be (so that cleanup doesn't trash things)
1897 self.assertIn('/meta/', recipedir)
1898 relpth = os.path.relpath(recipedir, os.path.join(get_bb_var('COREBASE'), 'meta'))
1899 appenddir = os.path.join(get_test_layer(), relpth)
1900 self.track_for_cleanup(appenddir)
1901 # Try finish to the original layer
1902 self.add_command_to_tearDown('rm -rf %s ; cd %s ; git checkout %s' % (recipedir, os.path.dirname(recipedir), recipedir))
1903 result = runCmd('devtool finish %s meta-selftest' % recipe)
1904 result = runCmd('devtool status')
1905 self.assertNotIn(recipe, result.output, 'Recipe should have been reset by finish but wasn\'t')
1906 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish')
1907 result = runCmd('git status --porcelain .', cwd=recipedir)
1908 if result.output.strip():
1909 self.fail('Recipe directory for %s contains the following unexpected changes after finish:\n%s' % (recipe, result.output.strip()))
1910 recipefn = os.path.splitext(os.path.basename(oldrecipefile))[0]
1911 recipefn = recipefn.split('_')[0] + '_%'
1912 appendfile = os.path.join(appenddir, recipefn + '.bbappend')
1913 self.assertExists(appendfile, 'bbappend %s should have been created but wasn\'t' % appendfile)
1914 newdir = os.path.join(appenddir, recipe)
1915 files = os.listdir(newdir)
1916 foundpatch = None
1917 for fn in files:
1918 if fnmatch.fnmatch(fn, '*-Add-a-comment-to-the-code.patch'):
1919 foundpatch = fn
1920 if not foundpatch:
1921 self.fail('No patch file created next to bbappend')
1922 files.remove(foundpatch)
1923 if files:
1924 self.fail('Unexpected file(s) copied next to bbappend: %s' % ', '.join(files))
1925
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001926 def test_devtool_rename(self):
1927 # Check preconditions
1928 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
1929 self.track_for_cleanup(self.workspacedir)
1930 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
1931
1932 # First run devtool add
1933 # We already have this recipe in OE-Core, but that doesn't matter
1934 recipename = 'i2c-tools'
1935 recipever = '3.1.2'
1936 recipefile = os.path.join(self.workspacedir, 'recipes', recipename, '%s_%s.bb' % (recipename, recipever))
1937 url = 'http://downloads.yoctoproject.org/mirror/sources/i2c-tools-%s.tar.bz2' % recipever
1938 def add_recipe():
1939 result = runCmd('devtool add %s' % url)
1940 self.assertExists(recipefile, 'Expected recipe file not created')
1941 self.assertExists(os.path.join(self.workspacedir, 'sources', recipename), 'Source directory not created')
1942 checkvars = {}
1943 checkvars['S'] = None
1944 checkvars['SRC_URI'] = url.replace(recipever, '${PV}')
1945 self._test_recipe_contents(recipefile, checkvars, [])
1946 add_recipe()
1947 # Now rename it - change both name and version
1948 newrecipename = 'mynewrecipe'
1949 newrecipever = '456'
1950 newrecipefile = os.path.join(self.workspacedir, 'recipes', newrecipename, '%s_%s.bb' % (newrecipename, newrecipever))
1951 result = runCmd('devtool rename %s %s -V %s' % (recipename, newrecipename, newrecipever))
1952 self.assertExists(newrecipefile, 'Recipe file not renamed')
1953 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipename), 'Old recipe directory still exists')
1954 newsrctree = os.path.join(self.workspacedir, 'sources', newrecipename)
1955 self.assertExists(newsrctree, 'Source directory not renamed')
1956 checkvars = {}
1957 checkvars['S'] = '${WORKDIR}/%s-%s' % (recipename, recipever)
1958 checkvars['SRC_URI'] = url
1959 self._test_recipe_contents(newrecipefile, checkvars, [])
1960 # Try again - change just name this time
1961 result = runCmd('devtool reset -n %s' % newrecipename)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001962 add_recipe()
1963 newrecipefile = os.path.join(self.workspacedir, 'recipes', newrecipename, '%s_%s.bb' % (newrecipename, recipever))
1964 result = runCmd('devtool rename %s %s' % (recipename, newrecipename))
1965 self.assertExists(newrecipefile, 'Recipe file not renamed')
1966 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipename), 'Old recipe directory still exists')
1967 self.assertExists(os.path.join(self.workspacedir, 'sources', newrecipename), 'Source directory not renamed')
1968 checkvars = {}
1969 checkvars['S'] = '${WORKDIR}/%s-${PV}' % recipename
1970 checkvars['SRC_URI'] = url.replace(recipever, '${PV}')
1971 self._test_recipe_contents(newrecipefile, checkvars, [])
1972 # Try again - change just version this time
1973 result = runCmd('devtool reset -n %s' % newrecipename)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001974 add_recipe()
1975 newrecipefile = os.path.join(self.workspacedir, 'recipes', recipename, '%s_%s.bb' % (recipename, newrecipever))
1976 result = runCmd('devtool rename %s -V %s' % (recipename, newrecipever))
1977 self.assertExists(newrecipefile, 'Recipe file not renamed')
1978 self.assertExists(os.path.join(self.workspacedir, 'sources', recipename), 'Source directory no longer exists')
1979 checkvars = {}
1980 checkvars['S'] = '${WORKDIR}/${BPN}-%s' % recipever
1981 checkvars['SRC_URI'] = url
1982 self._test_recipe_contents(newrecipefile, checkvars, [])
1983
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001984 def test_devtool_virtual_kernel_modify(self):
1985 """
1986 Summary: The purpose of this test case is to verify that
1987 devtool modify works correctly when building
1988 the kernel.
1989 Dependencies: NA
1990 Steps: 1. Build kernel with bitbake.
1991 2. Save the config file generated.
1992 3. Clean the environment.
1993 4. Use `devtool modify virtual/kernel` to validate following:
1994 4.1 The source is checked out correctly.
1995 4.2 The resulting configuration is the same as
1996 what was get on step 2.
1997 4.3 The Kernel can be build correctly.
1998 4.4 Changes made on the source are reflected on the
1999 subsequent builds.
2000 4.5 Changes on the configuration are reflected on the
2001 subsequent builds
2002 Expected: devtool modify is able to checkout the source of the kernel
2003 and modification to the source and configurations are reflected
2004 when building the kernel.
Patrick Williams45852732022-04-02 08:58:32 -05002005 """
2006 kernel_provider = self.td['PREFERRED_PROVIDER_virtual/kernel']
2007
Andrew Geissler82c905d2020-04-13 13:39:40 -05002008 # Clean up the environment
Brad Bishopd7bf8c12018-02-25 22:55:05 -05002009 bitbake('%s -c clean' % kernel_provider)
2010 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
2011 tempdir_cfg = tempfile.mkdtemp(prefix='config_qa')
2012 self.track_for_cleanup(tempdir)
2013 self.track_for_cleanup(tempdir_cfg)
2014 self.track_for_cleanup(self.workspacedir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05002015 self.add_command_to_tearDown('bitbake -c clean %s' % kernel_provider)
Brad Bishop00e122a2019-10-05 11:10:57 -04002016 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
Brad Bishopd7bf8c12018-02-25 22:55:05 -05002017 #Step 1
2018 #Here is just generated the config file instead of all the kernel to optimize the
2019 #time of executing this test case.
2020 bitbake('%s -c configure' % kernel_provider)
2021 bbconfig = os.path.join(get_bb_var('B', kernel_provider),'.config')
2022 #Step 2
2023 runCmd('cp %s %s' % (bbconfig, tempdir_cfg))
2024 self.assertExists(os.path.join(tempdir_cfg, '.config'), 'Could not copy .config file from kernel')
2025
2026 tmpconfig = os.path.join(tempdir_cfg, '.config')
2027 #Step 3
2028 bitbake('%s -c clean' % kernel_provider)
2029 #Step 4.1
2030 runCmd('devtool modify virtual/kernel -x %s' % tempdir)
2031 self.assertExists(os.path.join(tempdir, 'Makefile'), 'Extracted source could not be found')
2032 #Step 4.2
2033 configfile = os.path.join(tempdir,'.config')
Patrick Williams45852732022-04-02 08:58:32 -05002034 runCmd('diff %s %s' % (tmpconfig, configfile))
2035
Brad Bishopd7bf8c12018-02-25 22:55:05 -05002036 #Step 4.3
2037 #NOTE: virtual/kernel is mapped to kernel_provider
Patrick Williams45852732022-04-02 08:58:32 -05002038 runCmd('devtool build %s' % kernel_provider)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05002039 kernelfile = os.path.join(get_bb_var('KBUILD_OUTPUT', kernel_provider), 'vmlinux')
2040 self.assertExists(kernelfile, 'Kernel was not build correctly')
2041
2042 #Modify the kernel source
Patrick Williams45852732022-04-02 08:58:32 -05002043 modfile = os.path.join(tempdir, 'init/version.c')
Andrew Geisslerc5535c92023-01-27 16:10:19 -06002044 # Moved to uts.h in 6.1 onwards
2045 modfile2 = os.path.join(tempdir, 'include/linux/uts.h')
2046 runCmd("sed -i 's/Linux/LiNuX/g' %s %s" % (modfile, modfile2))
Patrick Williams45852732022-04-02 08:58:32 -05002047
Brad Bishopd7bf8c12018-02-25 22:55:05 -05002048 #Modify the configuration
Patrick Williams45852732022-04-02 08:58:32 -05002049 codeconfigfile = os.path.join(tempdir, '.config.new')
Brad Bishopd7bf8c12018-02-25 22:55:05 -05002050 modconfopt = "CONFIG_SG_POOL=n"
Patrick Williams45852732022-04-02 08:58:32 -05002051 runCmd("sed -i 's/CONFIG_SG_POOL=y/%s/' %s" % (modconfopt, codeconfigfile))
2052
Brad Bishopd7bf8c12018-02-25 22:55:05 -05002053 #Build again kernel with devtool
Patrick Williams45852732022-04-02 08:58:32 -05002054 runCmd('devtool build %s' % kernel_provider)
2055
Brad Bishopd7bf8c12018-02-25 22:55:05 -05002056 #Step 4.4
Patrick Williams45852732022-04-02 08:58:32 -05002057 runCmd("grep '%s' %s" % ('LiNuX', kernelfile))
2058
Brad Bishopd7bf8c12018-02-25 22:55:05 -05002059 #Step 4.5
Patrick Williams45852732022-04-02 08:58:32 -05002060 runCmd("grep %s %s" % (modconfopt, codeconfigfile))