summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa/selftest/cases/wic.py
diff options
context:
space:
mode:
authorLeonardo Sandoval <leonardo.sandoval.gonzalez@linux.intel.com>2017-05-12 14:40:21 -0700
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-06-06 19:02:43 +0100
commit157c3be2ca93f076033f725ec1ee912df91f7488 (patch)
tree8ef896ff7adf78d63b34059cd5b017a4f0a3419a /meta/lib/oeqa/selftest/cases/wic.py
parent10c512b60d1167122b5fe778b93838dca3def717 (diff)
downloadpoky-157c3be2ca93f076033f725ec1ee912df91f7488.tar.gz
oeqa/selftest/cases: Migrate test cases into the new oe-qa framework
New framework has different classes/decorators so adapt current test cases to support these. Changes include changes on base classes and decorators. Also include paths in selftest/__init__.py isn't needed because the loader is the standard unittest one. (From OE-Core rev: ddbbefdd124604d10bd47dd0266b55a764fcc0ab) Signed-off-by: Leonardo Sandoval <leonardo.sandoval.gonzalez@linux.intel.com> Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib/oeqa/selftest/cases/wic.py')
-rw-r--r--meta/lib/oeqa/selftest/cases/wic.py793
1 files changed, 793 insertions, 0 deletions
diff --git a/meta/lib/oeqa/selftest/cases/wic.py b/meta/lib/oeqa/selftest/cases/wic.py
new file mode 100644
index 0000000000..4040cf7246
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/wic.py
@@ -0,0 +1,793 @@
1#!/usr/bin/env python
2# ex:ts=4:sw=4:sts=4:et
3# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4#
5# Copyright (c) 2015, Intel Corporation.
6# All rights reserved.
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License version 2 as
10# published by the Free Software Foundation.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program; if not, write to the Free Software Foundation, Inc.,
19# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20#
21# AUTHORS
22# Ed Bartosh <ed.bartosh@linux.intel.com>
23
24"""Test cases for wic."""
25
26import os
27import sys
28import unittest
29
30from glob import glob
31from shutil import rmtree
32from functools import wraps, lru_cache
33from tempfile import NamedTemporaryFile
34
35from oeqa.selftest.case import OESelftestTestCase
36from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, runqemu
37from oeqa.core.decorator.oeid import OETestID
38
39
40@lru_cache(maxsize=32)
41def get_host_arch(recipe):
42 """A cached call to get_bb_var('HOST_ARCH', <recipe>)"""
43 return get_bb_var('HOST_ARCH', recipe)
44
45
46def only_for_arch(archs, image='core-image-minimal'):
47 """Decorator for wrapping test cases that can be run only for specific target
48 architectures. A list of compatible architectures is passed in `archs`.
49 Current architecture will be determined by parsing bitbake output for
50 `image` recipe.
51 """
52 def wrapper(func):
53 @wraps(func)
54 def wrapped_f(*args, **kwargs):
55 arch = get_host_arch(image)
56 if archs and arch not in archs:
57 raise unittest.SkipTest("Testcase arch dependency not met: %s" % arch)
58 return func(*args, **kwargs)
59 wrapped_f.__name__ = func.__name__
60 return wrapped_f
61 return wrapper
62
63
64class Wic(OESelftestTestCase):
65 """Wic test class."""
66
67 resultdir = "/var/tmp/wic.oe-selftest/"
68 image_is_ready = False
69 native_sysroot = None
70 wicenv_cache = {}
71
72 def setUpLocal(self):
73 """This code is executed before each test method."""
74 super(Wic, self).setUpLocal()
75 if not self.native_sysroot:
76 Wic.native_sysroot = get_bb_var('STAGING_DIR_NATIVE', 'wic-tools')
77
78 # Do this here instead of in setUpClass as the base setUp does some
79 # clean up which can result in the native tools built earlier in
80 # setUpClass being unavailable.
81 if not Wic.image_is_ready:
82 if get_bb_var('USE_NLS') == 'yes':
83 bitbake('wic-tools')
84 else:
85 self.skipTest('wic-tools cannot be built due its (intltool|gettext)-native dependency and NLS disable')
86
87 bitbake('core-image-minimal')
88 Wic.image_is_ready = True
89
90 rmtree(self.resultdir, ignore_errors=True)
91
92 def tearDownLocal(self):
93 """Remove resultdir as it may contain images."""
94 rmtree(self.resultdir, ignore_errors=True)
95 super(Wic, self).tearDownLocal()
96
97 @OETestID(1552)
98 def test_version(self):
99 """Test wic --version"""
100 self.assertEqual(0, runCmd('wic --version').status)
101
102 @OETestID(1208)
103 def test_help(self):
104 """Test wic --help and wic -h"""
105 self.assertEqual(0, runCmd('wic --help').status)
106 self.assertEqual(0, runCmd('wic -h').status)
107
108 @OETestID(1209)
109 def test_createhelp(self):
110 """Test wic create --help"""
111 self.assertEqual(0, runCmd('wic create --help').status)
112
113 @OETestID(1210)
114 def test_listhelp(self):
115 """Test wic list --help"""
116 self.assertEqual(0, runCmd('wic list --help').status)
117
118 @OETestID(1553)
119 def test_help_create(self):
120 """Test wic help create"""
121 self.assertEqual(0, runCmd('wic help create').status)
122
123 @OETestID(1554)
124 def test_help_list(self):
125 """Test wic help list"""
126 self.assertEqual(0, runCmd('wic help list').status)
127
128 @OETestID(1215)
129 def test_help_overview(self):
130 """Test wic help overview"""
131 self.assertEqual(0, runCmd('wic help overview').status)
132
133 @OETestID(1216)
134 def test_help_plugins(self):
135 """Test wic help plugins"""
136 self.assertEqual(0, runCmd('wic help plugins').status)
137
138 @OETestID(1217)
139 def test_help_kickstart(self):
140 """Test wic help kickstart"""
141 self.assertEqual(0, runCmd('wic help kickstart').status)
142
143 @OETestID(1555)
144 def test_list_images(self):
145 """Test wic list images"""
146 self.assertEqual(0, runCmd('wic list images').status)
147
148 @OETestID(1556)
149 def test_list_source_plugins(self):
150 """Test wic list source-plugins"""
151 self.assertEqual(0, runCmd('wic list source-plugins').status)
152
153 @OETestID(1557)
154 def test_listed_images_help(self):
155 """Test wic listed images help"""
156 output = runCmd('wic list images').output
157 imagelist = [line.split()[0] for line in output.splitlines()]
158 for image in imagelist:
159 self.assertEqual(0, runCmd('wic list %s help' % image).status)
160
161 @OETestID(1213)
162 def test_unsupported_subcommand(self):
163 """Test unsupported subcommand"""
164 self.assertNotEqual(0, runCmd('wic unsupported', ignore_status=True).status)
165
166 @OETestID(1214)
167 def test_no_command(self):
168 """Test wic without command"""
169 self.assertEqual(1, runCmd('wic', ignore_status=True).status)
170
171 @OETestID(1211)
172 def test_build_image_name(self):
173 """Test wic create wictestdisk --image-name=core-image-minimal"""
174 cmd = "wic create wictestdisk --image-name=core-image-minimal -o %s" % self.resultdir
175 self.assertEqual(0, runCmd(cmd).status)
176 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
177
178 @OETestID(1157)
179 @only_for_arch(['i586', 'i686', 'x86_64'])
180 def test_gpt_image(self):
181 """Test creation of core-image-minimal with gpt table and UUID boot"""
182 cmd = "wic create directdisk-gpt --image-name core-image-minimal -o %s" % self.resultdir
183 self.assertEqual(0, runCmd(cmd).status)
184 self.assertEqual(1, len(glob(self.resultdir + "directdisk-*.direct")))
185
186 @OETestID(1346)
187 @only_for_arch(['i586', 'i686', 'x86_64'])
188 def test_iso_image(self):
189 """Test creation of hybrid iso image with legacy and EFI boot"""
190 config = 'INITRAMFS_IMAGE = "core-image-minimal-initramfs"\n'\
191 'MACHINE_FEATURES_append = " efi"\n'
192 self.append_config(config)
193 bitbake('core-image-minimal')
194 self.remove_config(config)
195 cmd = "wic create mkhybridiso --image-name core-image-minimal -o %s" % self.resultdir
196 self.assertEqual(0, runCmd(cmd).status)
197 self.assertEqual(1, len(glob(self.resultdir + "HYBRID_ISO_IMG-*.direct")))
198 self.assertEqual(1, len(glob(self.resultdir + "HYBRID_ISO_IMG-*.iso")))
199
200 @OETestID(1348)
201 @only_for_arch(['i586', 'i686', 'x86_64'])
202 def test_qemux86_directdisk(self):
203 """Test creation of qemux-86-directdisk image"""
204 cmd = "wic create qemux86-directdisk -e core-image-minimal -o %s" % self.resultdir
205 self.assertEqual(0, runCmd(cmd).status)
206 self.assertEqual(1, len(glob(self.resultdir + "qemux86-directdisk-*direct")))
207
208 @OETestID(1350)
209 @only_for_arch(['i586', 'i686', 'x86_64'])
210 def test_mkefidisk(self):
211 """Test creation of mkefidisk image"""
212 cmd = "wic create mkefidisk -e core-image-minimal -o %s" % self.resultdir
213 self.assertEqual(0, runCmd(cmd).status)
214 self.assertEqual(1, len(glob(self.resultdir + "mkefidisk-*direct")))
215
216 @OETestID(1385)
217 @only_for_arch(['i586', 'i686', 'x86_64'])
218 def test_bootloader_config(self):
219 """Test creation of directdisk-bootloader-config image"""
220 cmd = "wic create directdisk-bootloader-config -e core-image-minimal -o %s" % self.resultdir
221 self.assertEqual(0, runCmd(cmd).status)
222 self.assertEqual(1, len(glob(self.resultdir + "directdisk-bootloader-config-*direct")))
223
224 @OETestID(1560)
225 @only_for_arch(['i586', 'i686', 'x86_64'])
226 def test_systemd_bootdisk(self):
227 """Test creation of systemd-bootdisk image"""
228 config = 'MACHINE_FEATURES_append = " efi"\n'
229 self.append_config(config)
230 bitbake('core-image-minimal')
231 self.remove_config(config)
232 cmd = "wic create systemd-bootdisk -e core-image-minimal -o %s" % self.resultdir
233 self.assertEqual(0, runCmd(cmd).status)
234 self.assertEqual(1, len(glob(self.resultdir + "systemd-bootdisk-*direct")))
235
236 @OETestID(1561)
237 def test_sdimage_bootpart(self):
238 """Test creation of sdimage-bootpart image"""
239 cmd = "wic create sdimage-bootpart -e core-image-minimal -o %s" % self.resultdir
240 kimgtype = get_bb_var('KERNEL_IMAGETYPE', 'core-image-minimal')
241 self.write_config('IMAGE_BOOT_FILES = "%s"\n' % kimgtype)
242 self.assertEqual(0, runCmd(cmd).status)
243 self.assertEqual(1, len(glob(self.resultdir + "sdimage-bootpart-*direct")))
244
245 @OETestID(1562)
246 @only_for_arch(['i586', 'i686', 'x86_64'])
247 def test_default_output_dir(self):
248 """Test default output location"""
249 for fname in glob("directdisk-*.direct"):
250 os.remove(fname)
251 cmd = "wic create directdisk -e core-image-minimal"
252 self.assertEqual(0, runCmd(cmd).status)
253 self.assertEqual(1, len(glob("directdisk-*.direct")))
254
255 @OETestID(1212)
256 @only_for_arch(['i586', 'i686', 'x86_64'])
257 def test_build_artifacts(self):
258 """Test wic create directdisk providing all artifacts."""
259 bb_vars = get_bb_vars(['STAGING_DATADIR', 'RECIPE_SYSROOT_NATIVE'],
260 'wic-tools')
261 bb_vars.update(get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_ROOTFS'],
262 'core-image-minimal'))
263 bbvars = {key.lower(): value for key, value in bb_vars.items()}
264 bbvars['resultdir'] = self.resultdir
265 status = runCmd("wic create directdisk "
266 "-b %(staging_datadir)s "
267 "-k %(deploy_dir_image)s "
268 "-n %(recipe_sysroot_native)s "
269 "-r %(image_rootfs)s "
270 "-o %(resultdir)s" % bbvars).status
271 self.assertEqual(0, status)
272 self.assertEqual(1, len(glob(self.resultdir + "directdisk-*.direct")))
273
274 @OETestID(1264)
275 def test_compress_gzip(self):
276 """Test compressing an image with gzip"""
277 self.assertEqual(0, runCmd("wic create wictestdisk "
278 "--image-name core-image-minimal "
279 "-c gzip -o %s" % self.resultdir).status)
280 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct.gz")))
281
282 @OETestID(1265)
283 def test_compress_bzip2(self):
284 """Test compressing an image with bzip2"""
285 self.assertEqual(0, runCmd("wic create wictestdisk "
286 "--image-name=core-image-minimal "
287 "-c bzip2 -o %s" % self.resultdir).status)
288 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct.bz2")))
289
290 @OETestID(1266)
291 def test_compress_xz(self):
292 """Test compressing an image with xz"""
293 self.assertEqual(0, runCmd("wic create wictestdisk "
294 "--image-name=core-image-minimal "
295 "--compress-with=xz -o %s" % self.resultdir).status)
296 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct.xz")))
297
298 @OETestID(1267)
299 def test_wrong_compressor(self):
300 """Test how wic breaks if wrong compressor is provided"""
301 self.assertEqual(2, runCmd("wic create wictestdisk "
302 "--image-name=core-image-minimal "
303 "-c wrong -o %s" % self.resultdir,
304 ignore_status=True).status)
305
306 @OETestID(1558)
307 def test_debug_short(self):
308 """Test -D option"""
309 self.assertEqual(0, runCmd("wic create wictestdisk "
310 "--image-name=core-image-minimal "
311 "-D -o %s" % self.resultdir).status)
312 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
313
314 def test_debug_long(self):
315 """Test --debug option"""
316 self.assertEqual(0, runCmd("wic create wictestdisk "
317 "--image-name=core-image-minimal "
318 "--debug -o %s" % self.resultdir).status)
319 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
320
321 @OETestID(1563)
322 def test_skip_build_check_short(self):
323 """Test -s option"""
324 self.assertEqual(0, runCmd("wic create wictestdisk "
325 "--image-name=core-image-minimal "
326 "-s -o %s" % self.resultdir).status)
327 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
328
329 def test_skip_build_check_long(self):
330 """Test --skip-build-check option"""
331 self.assertEqual(0, runCmd("wic create wictestdisk "
332 "--image-name=core-image-minimal "
333 "--skip-build-check "
334 "--outdir %s" % self.resultdir).status)
335 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
336
337 @OETestID(1564)
338 def test_build_rootfs_short(self):
339 """Test -f option"""
340 self.assertEqual(0, runCmd("wic create wictestdisk "
341 "--image-name=core-image-minimal "
342 "-f -o %s" % self.resultdir).status)
343 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
344
345 def test_build_rootfs_long(self):
346 """Test --build-rootfs option"""
347 self.assertEqual(0, runCmd("wic create wictestdisk "
348 "--image-name=core-image-minimal "
349 "--build-rootfs "
350 "--outdir %s" % self.resultdir).status)
351 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
352
353 @OETestID(1268)
354 @only_for_arch(['i586', 'i686', 'x86_64'])
355 def test_rootfs_indirect_recipes(self):
356 """Test usage of rootfs plugin with rootfs recipes"""
357 status = runCmd("wic create directdisk-multi-rootfs "
358 "--image-name=core-image-minimal "
359 "--rootfs rootfs1=core-image-minimal "
360 "--rootfs rootfs2=core-image-minimal "
361 "--outdir %s" % self.resultdir).status
362 self.assertEqual(0, status)
363 self.assertEqual(1, len(glob(self.resultdir + "directdisk-multi-rootfs*.direct")))
364
365 @OETestID(1269)
366 @only_for_arch(['i586', 'i686', 'x86_64'])
367 def test_rootfs_artifacts(self):
368 """Test usage of rootfs plugin with rootfs paths"""
369 bb_vars = get_bb_vars(['STAGING_DATADIR', 'RECIPE_SYSROOT_NATIVE'],
370 'wic-tools')
371 bb_vars.update(get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_ROOTFS'],
372 'core-image-minimal'))
373 bbvars = {key.lower(): value for key, value in bb_vars.items()}
374 bbvars['wks'] = "directdisk-multi-rootfs"
375 bbvars['resultdir'] = self.resultdir
376 status = runCmd("wic create %(wks)s "
377 "--bootimg-dir=%(staging_datadir)s "
378 "--kernel-dir=%(deploy_dir_image)s "
379 "--native-sysroot=%(recipe_sysroot_native)s "
380 "--rootfs-dir rootfs1=%(image_rootfs)s "
381 "--rootfs-dir rootfs2=%(image_rootfs)s "
382 "--outdir %(resultdir)s" % bbvars).status
383 self.assertEqual(0, status)
384 self.assertEqual(1, len(glob(self.resultdir + "%(wks)s-*.direct" % bbvars)))
385
386 def test_exclude_path(self):
387 """Test --exclude-path wks option."""
388
389 oldpath = os.environ['PATH']
390 os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
391
392 try:
393 wks_file = 'temp.wks'
394 with open(wks_file, 'w') as wks:
395 rootfs_dir = get_bb_var('IMAGE_ROOTFS', 'core-image-minimal')
396 wks.write("""
397part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path usr
398part /usr --source rootfs --ondisk mmcblk0 --fstype=ext4 --rootfs-dir %s/usr
399part /etc --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path bin/ --rootfs-dir %s/usr"""
400 % (rootfs_dir, rootfs_dir))
401 self.assertEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
402 % (wks_file, self.resultdir)).status)
403
404 os.remove(wks_file)
405 wicout = glob(self.resultdir + "%s-*direct" % 'temp')
406 self.assertEqual(1, len(wicout))
407
408 wicimg = wicout[0]
409
410 # verify partition size with wic
411 res = runCmd("parted -m %s unit b p 2>/dev/null" % wicimg)
412 self.assertEqual(0, res.status)
413
414 # parse parted output which looks like this:
415 # BYT;\n
416 # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n
417 # 1:0.00MiB:200MiB:200MiB:ext4::;\n
418 partlns = res.output.splitlines()[2:]
419
420 self.assertEqual(3, len(partlns))
421
422 for part in [1, 2, 3]:
423 part_file = os.path.join(self.resultdir, "selftest_img.part%d" % part)
424 partln = partlns[part-1].split(":")
425 self.assertEqual(7, len(partln))
426 start = int(partln[1].rstrip("B")) / 512
427 length = int(partln[3].rstrip("B")) / 512
428 self.assertEqual(0, runCmd("dd if=%s of=%s skip=%d count=%d" %
429 (wicimg, part_file, start, length)).status)
430
431 def extract_files(debugfs_output):
432 """
433 extract file names from the output of debugfs -R 'ls -p',
434 which looks like this:
435
436 /2/040755/0/0/.//\n
437 /2/040755/0/0/..//\n
438 /11/040700/0/0/lost+found^M//\n
439 /12/040755/1002/1002/run//\n
440 /13/040755/1002/1002/sys//\n
441 /14/040755/1002/1002/bin//\n
442 /80/040755/1002/1002/var//\n
443 /92/040755/1002/1002/tmp//\n
444 """
445 # NOTE the occasional ^M in file names
446 return [line.split('/')[5].strip() for line in \
447 debugfs_output.strip().split('/\n')]
448
449 # Test partition 1, should contain the normal root directories, except
450 # /usr.
451 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \
452 os.path.join(self.resultdir, "selftest_img.part1"))
453 self.assertEqual(0, res.status)
454 files = extract_files(res.output)
455 self.assertIn("etc", files)
456 self.assertNotIn("usr", files)
457
458 # Partition 2, should contain common directories for /usr, not root
459 # directories.
460 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \
461 os.path.join(self.resultdir, "selftest_img.part2"))
462 self.assertEqual(0, res.status)
463 files = extract_files(res.output)
464 self.assertNotIn("etc", files)
465 self.assertNotIn("usr", files)
466 self.assertIn("share", files)
467
468 # Partition 3, should contain the same as partition 2, including the bin
469 # directory, but not the files inside it.
470 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \
471 os.path.join(self.resultdir, "selftest_img.part3"))
472 self.assertEqual(0, res.status)
473 files = extract_files(res.output)
474 self.assertNotIn("etc", files)
475 self.assertNotIn("usr", files)
476 self.assertIn("share", files)
477 self.assertIn("bin", files)
478 res = runCmd("debugfs -R 'ls -p bin' %s 2>/dev/null" % \
479 os.path.join(self.resultdir, "selftest_img.part3"))
480 self.assertEqual(0, res.status)
481 files = extract_files(res.output)
482 self.assertIn(".", files)
483 self.assertIn("..", files)
484 self.assertEqual(2, len(files))
485
486 for part in [1, 2, 3]:
487 part_file = os.path.join(self.resultdir, "selftest_img.part%d" % part)
488 os.remove(part_file)
489
490 finally:
491 os.environ['PATH'] = oldpath
492
493 def test_exclude_path_errors(self):
494 """Test --exclude-path wks option error handling."""
495 wks_file = 'temp.wks'
496
497 # Absolute argument.
498 with open(wks_file, 'w') as wks:
499 wks.write("part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path /usr")
500 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
501 % (wks_file, self.resultdir), ignore_status=True).status)
502 os.remove(wks_file)
503
504 # Argument pointing to parent directory.
505 with open(wks_file, 'w') as wks:
506 wks.write("part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path ././..")
507 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
508 % (wks_file, self.resultdir), ignore_status=True).status)
509 os.remove(wks_file)
510
511 @OETestID(1496)
512 def test_bmap_short(self):
513 """Test generation of .bmap file -m option"""
514 cmd = "wic create wictestdisk -e core-image-minimal -m -o %s" % self.resultdir
515 status = runCmd(cmd).status
516 self.assertEqual(0, status)
517 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct")))
518 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct.bmap")))
519
520 def test_bmap_long(self):
521 """Test generation of .bmap file --bmap option"""
522 cmd = "wic create wictestdisk -e core-image-minimal --bmap -o %s" % self.resultdir
523 status = runCmd(cmd).status
524 self.assertEqual(0, status)
525 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct")))
526 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct.bmap")))
527
528 def _get_image_env_path(self, image):
529 """Generate and obtain the path to <image>.env"""
530 if image not in self.wicenv_cache:
531 self.assertEqual(0, bitbake('%s -c do_rootfs_wicenv' % image).status)
532 bb_vars = get_bb_vars(['STAGING_DIR', 'MACHINE'], image)
533 stdir = bb_vars['STAGING_DIR']
534 machine = bb_vars['MACHINE']
535 self.wicenv_cache[image] = os.path.join(stdir, machine, 'imgdata')
536 return self.wicenv_cache[image]
537
538 @OETestID(1347)
539 def test_image_env(self):
540 """Test generation of <image>.env files."""
541 image = 'core-image-minimal'
542 imgdatadir = self._get_image_env_path(image)
543
544 bb_vars = get_bb_vars(['IMAGE_BASENAME', 'WICVARS'], image)
545 basename = bb_vars['IMAGE_BASENAME']
546 self.assertEqual(basename, image)
547 path = os.path.join(imgdatadir, basename) + '.env'
548 self.assertTrue(os.path.isfile(path))
549
550 wicvars = set(bb_vars['WICVARS'].split())
551 # filter out optional variables
552 wicvars = wicvars.difference(('DEPLOY_DIR_IMAGE', 'IMAGE_BOOT_FILES',
553 'INITRD', 'INITRD_LIVE', 'ISODIR'))
554 with open(path) as envfile:
555 content = dict(line.split("=", 1) for line in envfile)
556 # test if variables used by wic present in the .env file
557 for var in wicvars:
558 self.assertTrue(var in content, "%s is not in .env file" % var)
559 self.assertTrue(content[var])
560
561 @OETestID(1559)
562 def test_image_vars_dir_short(self):
563 """Test image vars directory selection -v option"""
564 image = 'core-image-minimal'
565 imgenvdir = self._get_image_env_path(image)
566
567 self.assertEqual(0, runCmd("wic create wictestdisk "
568 "--image-name=%s -v %s -o %s"
569 % (image, imgenvdir, self.resultdir)).status)
570 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct")))
571
572 def test_image_vars_dir_long(self):
573 """Test image vars directory selection --vars option"""
574 image = 'core-image-minimal'
575 imgenvdir = self._get_image_env_path(image)
576 self.assertEqual(0, runCmd("wic create wictestdisk "
577 "--image-name=%s "
578 "--vars %s "
579 "--outdir %s"
580 % (image, imgenvdir, self.resultdir)).status)
581 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct")))
582
583 @OETestID(1351)
584 @only_for_arch(['i586', 'i686', 'x86_64'])
585 def test_wic_image_type(self):
586 """Test building wic images by bitbake"""
587 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\
588 'MACHINE_FEATURES_append = " efi"\n'
589 self.append_config(config)
590 self.assertEqual(0, bitbake('wic-image-minimal').status)
591 self.remove_config(config)
592
593 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'MACHINE'])
594 deploy_dir = bb_vars['DEPLOY_DIR_IMAGE']
595 machine = bb_vars['MACHINE']
596 prefix = os.path.join(deploy_dir, 'wic-image-minimal-%s.' % machine)
597 # check if we have result image and manifests symlinks
598 # pointing to existing files
599 for suffix in ('wic', 'manifest'):
600 path = prefix + suffix
601 self.assertTrue(os.path.islink(path))
602 self.assertTrue(os.path.isfile(os.path.realpath(path)))
603
604 @OETestID(1422)
605 @only_for_arch(['i586', 'i686', 'x86_64'])
606 def test_qemu(self):
607 """Test wic-image-minimal under qemu"""
608 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\
609 'MACHINE_FEATURES_append = " efi"\n'
610 self.append_config(config)
611 self.assertEqual(0, bitbake('wic-image-minimal').status)
612 self.remove_config(config)
613
614 with runqemu('wic-image-minimal', ssh=False) as qemu:
615 cmd = "mount |grep '^/dev/' | cut -f1,3 -d ' '"
616 status, output = qemu.run_serial(cmd)
617 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
618 self.assertEqual(output, '/dev/root /\r\n/dev/sda3 /mnt')
619
620 @only_for_arch(['i586', 'i686', 'x86_64'])
621 def test_qemu_efi(self):
622 """Test core-image-minimal efi image under qemu"""
623 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "mkefidisk.wks"\n'
624 self.append_config(config)
625 self.assertEqual(0, bitbake('core-image-minimal ovmf').status)
626 self.remove_config(config)
627
628 with runqemu('core-image-minimal', ssh=False,
629 runqemuparams='ovmf', image_fstype='wic') as qemu:
630 cmd = "grep sda. /proc/partitions |wc -l"
631 status, output = qemu.run_serial(cmd)
632 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
633 self.assertEqual(output, '3')
634
635 @staticmethod
636 def _make_fixed_size_wks(size):
637 """
638 Create a wks of an image with a single partition. Size of the partition is set
639 using --fixed-size flag. Returns a tuple: (path to wks file, wks image name)
640 """
641 with NamedTemporaryFile("w", suffix=".wks", delete=False) as tempf:
642 wkspath = tempf.name
643 tempf.write("part " \
644 "--source rootfs --ondisk hda --align 4 --fixed-size %d "
645 "--fstype=ext4\n" % size)
646 wksname = os.path.splitext(os.path.basename(wkspath))[0]
647
648 return wkspath, wksname
649
650 def test_fixed_size(self):
651 """
652 Test creation of a simple image with partition size controlled through
653 --fixed-size flag
654 """
655 wkspath, wksname = Wic._make_fixed_size_wks(200)
656
657 self.assertEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
658 % (wkspath, self.resultdir)).status)
659 os.remove(wkspath)
660 wicout = glob(self.resultdir + "%s-*direct" % wksname)
661 self.assertEqual(1, len(wicout))
662
663 wicimg = wicout[0]
664
665 # verify partition size with wic
666 res = runCmd("parted -m %s unit mib p 2>/dev/null" % wicimg,
667 ignore_status=True,
668 native_sysroot=self.native_sysroot)
669 self.assertEqual(0, res.status)
670
671 # parse parted output which looks like this:
672 # BYT;\n
673 # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n
674 # 1:0.00MiB:200MiB:200MiB:ext4::;\n
675 partlns = res.output.splitlines()[2:]
676
677 self.assertEqual(1, len(partlns))
678 self.assertEqual("1:0.00MiB:200MiB:200MiB:ext4::;", partlns[0])
679
680 def test_fixed_size_error(self):
681 """
682 Test creation of a simple image with partition size controlled through
683 --fixed-size flag. The size of partition is intentionally set to 1MiB
684 in order to trigger an error in wic.
685 """
686 wkspath, wksname = Wic._make_fixed_size_wks(1)
687
688 self.assertEqual(1, runCmd("wic create %s -e core-image-minimal -o %s" \
689 % (wkspath, self.resultdir), ignore_status=True).status)
690 os.remove(wkspath)
691 wicout = glob(self.resultdir + "%s-*direct" % wksname)
692 self.assertEqual(0, len(wicout))
693
694 @only_for_arch(['i586', 'i686', 'x86_64'])
695 def test_rawcopy_plugin_qemu(self):
696 """Test rawcopy plugin in qemu"""
697 # build ext4 and wic images
698 for fstype in ("ext4", "wic"):
699 config = 'IMAGE_FSTYPES = "%s"\nWKS_FILE = "test_rawcopy_plugin.wks.in"\n' % fstype
700 self.append_config(config)
701 self.assertEqual(0, bitbake('core-image-minimal').status)
702 self.remove_config(config)
703
704 with runqemu('core-image-minimal', ssh=False, image_fstype='wic') as qemu:
705 cmd = "grep sda. /proc/partitions |wc -l"
706 status, output = qemu.run_serial(cmd)
707 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
708 self.assertEqual(output, '2')
709
710 def test_rawcopy_plugin(self):
711 """Test rawcopy plugin"""
712 img = 'core-image-minimal'
713 machine = get_bb_var('MACHINE', img)
714 with NamedTemporaryFile("w", suffix=".wks") as wks:
715 wks.writelines(['part /boot --active --source bootimg-pcbios\n',
716 'part / --source rawcopy --sourceparams="file=%s-%s.ext4" --use-uuid\n'\
717 % (img, machine),
718 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n'])
719 wks.flush()
720 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
721 self.assertEqual(0, runCmd(cmd).status)
722 wksname = os.path.splitext(os.path.basename(wks.name))[0]
723 out = glob(self.resultdir + "%s-*direct" % wksname)
724 self.assertEqual(1, len(out))
725
726 def test_fs_types(self):
727 """Test filesystem types for empty and not empty partitions"""
728 img = 'core-image-minimal'
729 with NamedTemporaryFile("w", suffix=".wks") as wks:
730 wks.writelines(['part ext2 --fstype ext2 --source rootfs\n',
731 'part btrfs --fstype btrfs --source rootfs --size 40M\n',
732 'part squash --fstype squashfs --source rootfs\n',
733 'part swap --fstype swap --size 1M\n',
734 'part emptyvfat --fstype vfat --size 1M\n',
735 'part emptymsdos --fstype msdos --size 1M\n',
736 'part emptyext2 --fstype ext2 --size 1M\n',
737 'part emptybtrfs --fstype btrfs --size 100M\n'])
738 wks.flush()
739 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
740 self.assertEqual(0, runCmd(cmd).status)
741 wksname = os.path.splitext(os.path.basename(wks.name))[0]
742 out = glob(self.resultdir + "%s-*direct" % wksname)
743 self.assertEqual(1, len(out))
744
745 def test_kickstart_parser(self):
746 """Test wks parser options"""
747 with NamedTemporaryFile("w", suffix=".wks") as wks:
748 wks.writelines(['part / --fstype ext3 --source rootfs --system-id 0xFF '\
749 '--overhead-factor 1.2 --size 100k\n'])
750 wks.flush()
751 cmd = "wic create %s -e core-image-minimal -o %s" % (wks.name, self.resultdir)
752 self.assertEqual(0, runCmd(cmd).status)
753 wksname = os.path.splitext(os.path.basename(wks.name))[0]
754 out = glob(self.resultdir + "%s-*direct" % wksname)
755 self.assertEqual(1, len(out))
756
757 def test_image_bootpart_globbed(self):
758 """Test globbed sources with image-bootpart plugin"""
759 img = "core-image-minimal"
760 cmd = "wic create sdimage-bootpart -e %s -o %s" % (img, self.resultdir)
761 config = 'IMAGE_BOOT_FILES = "%s*"' % get_bb_var('KERNEL_IMAGETYPE', img)
762 self.append_config(config)
763 self.assertEqual(0, runCmd(cmd).status)
764 self.remove_config(config)
765 self.assertEqual(1, len(glob(self.resultdir + "sdimage-bootpart-*direct")))
766
767 def test_sparse_copy(self):
768 """Test sparse_copy with FIEMAP and SEEK_HOLE filemap APIs"""
769 libpath = os.path.join(get_bb_var('COREBASE'), 'scripts', 'lib', 'wic')
770 sys.path.insert(0, libpath)
771 from filemap import FilemapFiemap, FilemapSeek, sparse_copy, ErrorNotSupp
772 with NamedTemporaryFile("w", suffix=".wic-sparse") as sparse:
773 src_name = sparse.name
774 src_size = 1024 * 10
775 sparse.truncate(src_size)
776 # write one byte to the file
777 with open(src_name, 'r+b') as sfile:
778 sfile.seek(1024 * 4)
779 sfile.write(b'\x00')
780 dest = sparse.name + '.out'
781 # copy src file to dest using different filemap APIs
782 for api in (FilemapFiemap, FilemapSeek, None):
783 if os.path.exists(dest):
784 os.unlink(dest)
785 try:
786 sparse_copy(sparse.name, dest, api=api)
787 except ErrorNotSupp:
788 continue # skip unsupported API
789 dest_stat = os.stat(dest)
790 self.assertEqual(dest_stat.st_size, src_size)
791 # 8 blocks is 4K (physical sector size)
792 self.assertEqual(dest_stat.st_blocks, 8)
793 os.unlink(dest)