summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa/selftest/recipetool.py
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2015-05-18 16:15:07 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-05-20 21:41:04 +0100
commitfbfc06a969200e582a059c9943e6fd17aca70e30 (patch)
tree1862fb721f550d42f10e8867224712754a865d34 /meta/lib/oeqa/selftest/recipetool.py
parentc63adf5c5b4b5984c315e914a7d3cb4b51040602 (diff)
downloadpoky-fbfc06a969200e582a059c9943e6fd17aca70e30.tar.gz
recipetool: add appendfile subcommand
Locating which recipe provides a file in an image that you want to modify and then figuring out how to bbappend the recipe in order to replace it can be a tedious process. Thus, add a new appendfile subcommand to recipetool, providing the ability to create a bbappend file to add/replace any file in the target system. Without the -r option, it will search for the recipe packaging the specified file (using pkgdata from previously built recipes). The bbappend will be created at the appropriate path within the specified layer directory (which may or may not be in your bblayers.conf) or if one already exists it will be updated appropriately. Fairly extensive oe-selftest tests are also provided. Implements [YOCTO #6447]. (From OE-Core rev: dd2aa93b3c13d2c6464ef0fda59620c7dba450bb) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib/oeqa/selftest/recipetool.py')
-rw-r--r--meta/lib/oeqa/selftest/recipetool.py313
1 files changed, 311 insertions, 2 deletions
diff --git a/meta/lib/oeqa/selftest/recipetool.py b/meta/lib/oeqa/selftest/recipetool.py
index 832fb7b16a..f3ad493457 100644
--- a/meta/lib/oeqa/selftest/recipetool.py
+++ b/meta/lib/oeqa/selftest/recipetool.py
@@ -6,16 +6,326 @@ import tempfile
6 6
7import oeqa.utils.ftools as ftools 7import oeqa.utils.ftools as ftools
8from oeqa.selftest.base import oeSelfTest 8from oeqa.selftest.base import oeSelfTest
9from oeqa.utils.commands import runCmd, bitbake, get_bb_var 9from oeqa.utils.commands import runCmd, bitbake, get_bb_var, create_temp_layer
10from oeqa.utils.decorators import testcase 10from oeqa.utils.decorators import testcase
11from oeqa.selftest.devtool import DevtoolBase 11from oeqa.selftest.devtool import DevtoolBase
12 12
13 13
14templayerdir = ''
15
16def setUpModule():
17 global templayerdir
18 templayerdir = tempfile.mkdtemp(prefix='recipetoolqa')
19 create_temp_layer(templayerdir, 'selftestrecipetool')
20 result = runCmd('bitbake-layers add-layer %s' % templayerdir)
21 # Ensure we have the right data in shlibs/pkgdata
22 logger = logging.getLogger("selftest")
23 logger.info('Running bitbake to generate pkgdata')
24 bitbake('base-files coreutils busybox selftest-recipetool-appendfile')
25
26def tearDownModule():
27 runCmd('bitbake-layers remove-layer %s' % templayerdir, ignore_status=True)
28 runCmd('rm -rf %s' % templayerdir)
29 # Shouldn't leave any traces of this artificial recipe behind
30 bitbake('-c cleansstate selftest-recipetool-appendfile')
31
32
14class RecipetoolTests(DevtoolBase): 33class RecipetoolTests(DevtoolBase):
15 34
16 def setUpLocal(self): 35 def setUpLocal(self):
17 self.tempdir = tempfile.mkdtemp(prefix='recipetoolqa') 36 self.tempdir = tempfile.mkdtemp(prefix='recipetoolqa')
18 self.track_for_cleanup(self.tempdir) 37 self.track_for_cleanup(self.tempdir)
38 self.testfile = os.path.join(self.tempdir, 'testfile')
39 with open(self.testfile, 'w') as f:
40 f.write('Test file\n')
41
42 def tearDownLocal(self):
43 runCmd('rm -rf %s/recipes-*' % templayerdir)
44
45 def _try_recipetool_appendfile(self, testrecipe, destfile, newfile, options, expectedlines, expectedfiles):
46 result = runCmd('recipetool appendfile %s %s %s %s' % (templayerdir, destfile, newfile, options))
47 self.assertNotIn('Traceback', result.output)
48 # Check the bbappend was created and applies properly
49 recipefile = get_bb_var('FILE', testrecipe)
50 bbappendfile = self._check_bbappend(testrecipe, recipefile, templayerdir)
51 # Check the bbappend contents
52 with open(bbappendfile, 'r') as f:
53 self.assertEqual(expectedlines, f.readlines())
54 # Check file was copied
55 filesdir = os.path.join(os.path.dirname(bbappendfile), testrecipe)
56 for expectedfile in expectedfiles:
57 self.assertTrue(os.path.isfile(os.path.join(filesdir, expectedfile)), 'Expected file %s to be copied next to bbappend, but it wasn\'t' % expectedfile)
58 # Check no other files created
59 createdfiles = []
60 for root, _, files in os.walk(filesdir):
61 for f in files:
62 createdfiles.append(os.path.relpath(os.path.join(root, f), filesdir))
63 self.assertTrue(sorted(createdfiles), sorted(expectedfiles))
64 return bbappendfile, result.output
65
66 def _try_recipetool_appendfile_fail(self, destfile, newfile, checkerror):
67 cmd = 'recipetool appendfile %s %s %s' % (templayerdir, destfile, newfile)
68 result = runCmd(cmd, ignore_status=True)
69 self.assertNotEqual(result.status, 0, 'Command "%s" should have failed but didn\'t' % cmd)
70 self.assertNotIn('Traceback', result.output)
71 for errorstr in checkerror:
72 self.assertIn(errorstr, result.output)
73
74
75 def test_recipetool_appendfile_basic(self):
76 # Basic test
77 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
78 '\n']
79 _, output = self._try_recipetool_appendfile('base-files', '/etc/motd', self.testfile, '', expectedlines, ['motd'])
80 self.assertNotIn('WARNING: ', output)
81
82 def test_recipetool_appendfile_invalid(self):
83 # Test some commands that should error
84 self._try_recipetool_appendfile_fail('/etc/passwd', self.testfile, ['ERROR: /etc/passwd cannot be handled by this tool', 'useradd', 'extrausers'])
85 self._try_recipetool_appendfile_fail('/etc/timestamp', self.testfile, ['ERROR: /etc/timestamp cannot be handled by this tool'])
86 self._try_recipetool_appendfile_fail('/dev/console', self.testfile, ['ERROR: /dev/console cannot be handled by this tool'])
87
88 def test_recipetool_appendfile_alternatives(self):
89 # Now try with a file we know should be an alternative
90 # (this is very much a fake example, but one we know is reliably an alternative)
91 self._try_recipetool_appendfile_fail('/bin/ls', self.testfile, ['ERROR: File /bin/ls is an alternative possibly provided by the following recipes:', 'coreutils', 'busybox'])
92 corebase = get_bb_var('COREBASE')
93 # Need a test file - should be executable
94 testfile2 = os.path.join(corebase, 'oe-init-build-env')
95 testfile2name = os.path.basename(testfile2)
96 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
97 '\n',
98 'SRC_URI += "file://%s"\n' % testfile2name,
99 '\n',
100 'do_install_append() {\n',
101 ' install -d ${D}${base_bindir}\n',
102 ' install -m 0755 ${WORKDIR}/%s ${D}${base_bindir}/ls\n' % testfile2name,
103 '}\n']
104 self._try_recipetool_appendfile('coreutils', '/bin/ls', testfile2, '-r coreutils', expectedlines, [testfile2name])
105 # Now try bbappending the same file again, contents should not change
106 bbappendfile, _ = self._try_recipetool_appendfile('coreutils', '/bin/ls', self.testfile, '-r coreutils', expectedlines, [testfile2name])
107 # But file should have
108 copiedfile = os.path.join(os.path.dirname(bbappendfile), 'coreutils', testfile2name)
109 result = runCmd('diff -q %s %s' % (testfile2, copiedfile), ignore_status=True)
110 self.assertNotEqual(result.status, 0, 'New file should have been copied but was not')
111
112 def test_recipetool_appendfile_binary(self):
113 # Try appending a binary file
114 result = runCmd('recipetool appendfile %s /bin/ls /bin/ls -r coreutils' % templayerdir)
115 self.assertIn('WARNING: ', result.output)
116 self.assertIn('is a binary', result.output)
117
118 def test_recipetool_appendfile_add(self):
119 corebase = get_bb_var('COREBASE')
120 # Try arbitrary file add to a recipe
121 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
122 '\n',
123 'SRC_URI += "file://testfile"\n',
124 '\n',
125 'do_install_append() {\n',
126 ' install -d ${D}${datadir}\n',
127 ' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/something\n',
128 '}\n']
129 self._try_recipetool_appendfile('netbase', '/usr/share/something', self.testfile, '-r netbase', expectedlines, ['testfile'])
130 # Try adding another file, this time where the source file is executable
131 # (so we're testing that, plus modifying an existing bbappend)
132 testfile2 = os.path.join(corebase, 'oe-init-build-env')
133 testfile2name = os.path.basename(testfile2)
134 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
135 '\n',
136 'SRC_URI += "file://testfile \\\n',
137 ' file://%s \\\n' % testfile2name,
138 ' "\n',
139 '\n',
140 'do_install_append() {\n',
141 ' install -d ${D}${datadir}\n',
142 ' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/something\n',
143 ' install -m 0755 ${WORKDIR}/%s ${D}${datadir}/scriptname\n' % testfile2name,
144 '}\n']
145 self._try_recipetool_appendfile('netbase', '/usr/share/scriptname', testfile2, '-r netbase', expectedlines, ['testfile', testfile2name])
146
147 def test_recipetool_appendfile_add_bindir(self):
148 # Try arbitrary file add to a recipe, this time to a location such that should be installed as executable
149 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
150 '\n',
151 'SRC_URI += "file://testfile"\n',
152 '\n',
153 'do_install_append() {\n',
154 ' install -d ${D}${bindir}\n',
155 ' install -m 0755 ${WORKDIR}/testfile ${D}${bindir}/selftest-recipetool-testbin\n',
156 '}\n']
157 _, output = self._try_recipetool_appendfile('netbase', '/usr/bin/selftest-recipetool-testbin', self.testfile, '-r netbase', expectedlines, ['testfile'])
158 self.assertNotIn('WARNING: ', output)
159
160 def test_recipetool_appendfile_add_machine(self):
161 # Try arbitrary file add to a recipe, this time to a location such that should be installed as executable
162 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
163 '\n',
164 'PACKAGE_ARCH = "${MACHINE_ARCH}"\n',
165 '\n',
166 'SRC_URI_append_mymachine = " file://testfile"\n',
167 '\n',
168 'do_install_append_mymachine() {\n',
169 ' install -d ${D}${datadir}\n',
170 ' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/something\n',
171 '}\n']
172 _, output = self._try_recipetool_appendfile('netbase', '/usr/share/something', self.testfile, '-r netbase -m mymachine', expectedlines, ['mymachine/testfile'])
173 self.assertNotIn('WARNING: ', output)
174
175 def test_recipetool_appendfile_orig(self):
176 # A file that's in SRC_URI and in do_install with the same name
177 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
178 '\n']
179 _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-orig', self.testfile, '', expectedlines, ['selftest-replaceme-orig'])
180 self.assertNotIn('WARNING: ', output)
181
182 def test_recipetool_appendfile_todir(self):
183 # A file that's in SRC_URI and in do_install with destination directory rather than file
184 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
185 '\n']
186 _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-todir', self.testfile, '', expectedlines, ['selftest-replaceme-todir'])
187 self.assertNotIn('WARNING: ', output)
188
189 def test_recipetool_appendfile_renamed(self):
190 # A file that's in SRC_URI with a different name to the destination file
191 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
192 '\n']
193 _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-renamed', self.testfile, '', expectedlines, ['file1'])
194 self.assertNotIn('WARNING: ', output)
195
196 def test_recipetool_appendfile_subdir(self):
197 # A file that's in SRC_URI in a subdir
198 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
199 '\n',
200 'SRC_URI += "file://testfile"\n',
201 '\n',
202 'do_install_append() {\n',
203 ' install -d ${D}${datadir}\n',
204 ' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/selftest-replaceme-subdir\n',
205 '}\n']
206 _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-subdir', self.testfile, '', expectedlines, ['testfile'])
207 self.assertNotIn('WARNING: ', output)
208
209 def test_recipetool_appendfile_src_glob(self):
210 # A file that's in SRC_URI as a glob
211 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
212 '\n',
213 'SRC_URI += "file://testfile"\n',
214 '\n',
215 'do_install_append() {\n',
216 ' install -d ${D}${datadir}\n',
217 ' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/selftest-replaceme-src-globfile\n',
218 '}\n']
219 _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-src-globfile', self.testfile, '', expectedlines, ['testfile'])
220 self.assertNotIn('WARNING: ', output)
221
222 def test_recipetool_appendfile_inst_glob(self):
223 # A file that's in do_install as a glob
224 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
225 '\n']
226 _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-inst-globfile', self.testfile, '', expectedlines, ['selftest-replaceme-inst-globfile'])
227 self.assertNotIn('WARNING: ', output)
228
229 def test_recipetool_appendfile_inst_todir_glob(self):
230 # A file that's in do_install as a glob with destination as a directory
231 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
232 '\n']
233 _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-inst-todir-globfile', self.testfile, '', expectedlines, ['selftest-replaceme-inst-todir-globfile'])
234 self.assertNotIn('WARNING: ', output)
235
236 def test_recipetool_appendfile_patch(self):
237 # A file that's added by a patch in SRC_URI
238 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
239 '\n',
240 'SRC_URI += "file://testfile"\n',
241 '\n',
242 'do_install_append() {\n',
243 ' install -d ${D}${sysconfdir}\n',
244 ' install -m 0644 ${WORKDIR}/testfile ${D}${sysconfdir}/selftest-replaceme-patched\n',
245 '}\n']
246 _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/etc/selftest-replaceme-patched', self.testfile, '', expectedlines, ['testfile'])
247 for line in output.splitlines():
248 if line.startswith('WARNING: '):
249 self.assertIn('add-file.patch', line, 'Unexpected warning found in output:\n%s' % line)
250 break
251 else:
252 self.assertTrue(False, 'Patch warning not found in output:\n%s' % output)
253
254 def test_recipetool_appendfile_script(self):
255 # Now, a file that's in SRC_URI but installed by a script (so no mention in do_install)
256 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
257 '\n',
258 'SRC_URI += "file://testfile"\n',
259 '\n',
260 'do_install_append() {\n',
261 ' install -d ${D}${datadir}\n',
262 ' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/selftest-replaceme-scripted\n',
263 '}\n']
264 _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-scripted', self.testfile, '', expectedlines, ['testfile'])
265 self.assertNotIn('WARNING: ', output)
266
267 def test_recipetool_appendfile_inst_func(self):
268 # A file that's installed from a function called by do_install
269 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
270 '\n']
271 _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-inst-func', self.testfile, '', expectedlines, ['selftest-replaceme-inst-func'])
272 self.assertNotIn('WARNING: ', output)
273
274 def test_recipetool_appendfile_postinstall(self):
275 # A file that's created by a postinstall script (and explicitly mentioned in it)
276 # First try without specifying recipe
277 self._try_recipetool_appendfile_fail('/usr/share/selftest-replaceme-postinst', self.testfile, ['File /usr/share/selftest-replaceme-postinst may be written out in a pre/postinstall script of the following recipes:', 'selftest-recipetool-appendfile'])
278 # Now specify recipe
279 expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n',
280 '\n',
281 'SRC_URI += "file://testfile"\n',
282 '\n',
283 'do_install_append() {\n',
284 ' install -d ${D}${datadir}\n',
285 ' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/selftest-replaceme-postinst\n',
286 '}\n']
287 _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-postinst', self.testfile, '-r selftest-recipetool-appendfile', expectedlines, ['testfile'])
288
289 def test_recipetool_appendfile_extlayer(self):
290 # Try creating a bbappend in a layer that's not in bblayers.conf and has a different structure
291 exttemplayerdir = os.path.join(self.tempdir, 'extlayer')
292 self._create_temp_layer(exttemplayerdir, False, 'oeselftestextlayer', recipepathspec='metadata/recipes/recipes-*/*')
293 result = runCmd('recipetool appendfile %s /usr/share/selftest-replaceme-orig %s' % (exttemplayerdir, self.testfile))
294 self.assertNotIn('Traceback', result.output)
295 createdfiles = []
296 for root, _, files in os.walk(exttemplayerdir):
297 for f in files:
298 createdfiles.append(os.path.relpath(os.path.join(root, f), exttemplayerdir))
299 createdfiles.remove('conf/layer.conf')
300 expectedfiles = ['metadata/recipes/recipes-test/selftest-recipetool-appendfile/selftest-recipetool-appendfile.bbappend',
301 'metadata/recipes/recipes-test/selftest-recipetool-appendfile/selftest-recipetool-appendfile/selftest-replaceme-orig']
302 self.assertEqual(sorted(createdfiles), sorted(expectedfiles))
303
304 def test_recipetool_appendfile_wildcard(self):
305
306 def try_appendfile_wc(options):
307 result = runCmd('recipetool appendfile %s /etc/profile %s %s' % (templayerdir, self.testfile, options))
308 self.assertNotIn('Traceback', result.output)
309 bbappendfile = None
310 for root, _, files in os.walk(templayerdir):
311 for f in files:
312 if f.endswith('.bbappend'):
313 bbappendfile = f
314 break
315 if not bbappendfile:
316 self.assertTrue(False, 'No bbappend file created')
317 runCmd('rm -rf %s/recipes-*' % templayerdir)
318 return bbappendfile
319
320 # Check without wildcard option
321 recipefn = os.path.basename(get_bb_var('FILE', 'base-files'))
322 filename = try_appendfile_wc('')
323 self.assertEqual(filename, recipefn.replace('.bb', '.bbappend'))
324 # Now check with wildcard option
325 filename = try_appendfile_wc('-w')
326 self.assertEqual(filename, recipefn.split('_')[0] + '_%.bbappend')
327
328
19 329
20 def test_recipetool_create(self): 330 def test_recipetool_create(self):
21 # Try adding a recipe 331 # Try adding a recipe
@@ -52,4 +362,3 @@ class RecipetoolTests(DevtoolBase):
52 checkvars['DEPENDS'] = 'libpng pango libx11 libxext jpeg' 362 checkvars['DEPENDS'] = 'libpng pango libx11 libxext jpeg'
53 inherits = ['autotools', 'pkgconfig'] 363 inherits = ['autotools', 'pkgconfig']
54 self._test_recipe_contents(recipefile, checkvars, inherits) 364 self._test_recipe_contents(recipefile, checkvars, inherits)
55