blob: a11e2d07810ba36fc000bb7e43dcef0478e8e0df [file] [log] [blame]
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001#
2# Copyright (c) 2015, Intel Corporation.
Brad Bishopd7bf8c12018-02-25 22:55:05 -05003#
Brad Bishopc342db32019-05-15 21:57:59 -04004# SPDX-License-Identifier: GPL-2.0-only
Brad Bishopd7bf8c12018-02-25 22:55:05 -05005#
6# AUTHORS
7# Ed Bartosh <ed.bartosh@linux.intel.com>
8
9"""Test cases for wic."""
10
11import os
12import sys
13import unittest
14
15from glob import glob
16from shutil import rmtree, copy
17from functools import wraps, lru_cache
18from tempfile import NamedTemporaryFile
19
20from oeqa.selftest.case import OESelftestTestCase
21from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, runqemu
Brad Bishopd7bf8c12018-02-25 22:55:05 -050022
23
24@lru_cache(maxsize=32)
25def get_host_arch(recipe):
26 """A cached call to get_bb_var('HOST_ARCH', <recipe>)"""
27 return get_bb_var('HOST_ARCH', recipe)
28
29
30def only_for_arch(archs, image='core-image-minimal'):
31 """Decorator for wrapping test cases that can be run only for specific target
32 architectures. A list of compatible architectures is passed in `archs`.
33 Current architecture will be determined by parsing bitbake output for
34 `image` recipe.
35 """
36 def wrapper(func):
37 @wraps(func)
38 def wrapped_f(*args, **kwargs):
39 arch = get_host_arch(image)
40 if archs and arch not in archs:
41 raise unittest.SkipTest("Testcase arch dependency not met: %s" % arch)
42 return func(*args, **kwargs)
43 wrapped_f.__name__ = func.__name__
44 return wrapped_f
45 return wrapper
46
Andrew Geissler82c905d2020-04-13 13:39:40 -050047def extract_files(debugfs_output):
48 """
49 extract file names from the output of debugfs -R 'ls -p',
50 which looks like this:
51
52 /2/040755/0/0/.//\n
53 /2/040755/0/0/..//\n
54 /11/040700/0/0/lost+found^M//\n
55 /12/040755/1002/1002/run//\n
56 /13/040755/1002/1002/sys//\n
57 /14/040755/1002/1002/bin//\n
58 /80/040755/1002/1002/var//\n
59 /92/040755/1002/1002/tmp//\n
60 """
61 # NOTE the occasional ^M in file names
62 return [line.split('/')[5].strip() for line in \
63 debugfs_output.strip().split('/\n')]
64
65def files_own_by_root(debugfs_output):
66 for line in debugfs_output.strip().split('/\n'):
67 if line.split('/')[3:5] != ['0', '0']:
68 print(debugfs_output)
69 return False
70 return True
Brad Bishopd7bf8c12018-02-25 22:55:05 -050071
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080072class WicTestCase(OESelftestTestCase):
Brad Bishopd7bf8c12018-02-25 22:55:05 -050073 """Wic test class."""
74
Brad Bishopd7bf8c12018-02-25 22:55:05 -050075 image_is_ready = False
Brad Bishopd7bf8c12018-02-25 22:55:05 -050076 wicenv_cache = {}
77
78 def setUpLocal(self):
79 """This code is executed before each test method."""
Brad Bishopc4ea0752018-11-15 14:30:15 -080080 self.resultdir = self.builddir + "/wic-tmp/"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080081 super(WicTestCase, self).setUpLocal()
Brad Bishopd7bf8c12018-02-25 22:55:05 -050082
83 # Do this here instead of in setUpClass as the base setUp does some
84 # clean up which can result in the native tools built earlier in
85 # setUpClass being unavailable.
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080086 if not WicTestCase.image_is_ready:
Brad Bishopd7bf8c12018-02-25 22:55:05 -050087 if get_bb_var('USE_NLS') == 'yes':
88 bitbake('wic-tools')
89 else:
90 self.skipTest('wic-tools cannot be built due its (intltool|gettext)-native dependency and NLS disable')
91
92 bitbake('core-image-minimal')
Andrew Geissler82c905d2020-04-13 13:39:40 -050093 bitbake('core-image-minimal-mtdutils')
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080094 WicTestCase.image_is_ready = True
Brad Bishopd7bf8c12018-02-25 22:55:05 -050095
96 rmtree(self.resultdir, ignore_errors=True)
97
98 def tearDownLocal(self):
99 """Remove resultdir as it may contain images."""
100 rmtree(self.resultdir, ignore_errors=True)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800101 super(WicTestCase, self).tearDownLocal()
102
103 def _get_image_env_path(self, image):
104 """Generate and obtain the path to <image>.env"""
105 if image not in WicTestCase.wicenv_cache:
106 self.assertEqual(0, bitbake('%s -c do_rootfs_wicenv' % image).status)
107 bb_vars = get_bb_vars(['STAGING_DIR', 'MACHINE'], image)
108 stdir = bb_vars['STAGING_DIR']
109 machine = bb_vars['MACHINE']
110 WicTestCase.wicenv_cache[image] = os.path.join(stdir, machine, 'imgdata')
111 return WicTestCase.wicenv_cache[image]
112
113class Wic(WicTestCase):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500114
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500115 def test_version(self):
116 """Test wic --version"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800117 runCmd('wic --version')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500118
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500119 def test_help(self):
120 """Test wic --help and wic -h"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800121 runCmd('wic --help')
122 runCmd('wic -h')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500123
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500124 def test_createhelp(self):
125 """Test wic create --help"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800126 runCmd('wic create --help')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500127
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500128 def test_listhelp(self):
129 """Test wic list --help"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800130 runCmd('wic list --help')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500131
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500132 def test_help_create(self):
133 """Test wic help create"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800134 runCmd('wic help create')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500135
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500136 def test_help_list(self):
137 """Test wic help list"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800138 runCmd('wic help list')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500139
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500140 def test_help_overview(self):
141 """Test wic help overview"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800142 runCmd('wic help overview')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500143
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500144 def test_help_plugins(self):
145 """Test wic help plugins"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800146 runCmd('wic help plugins')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500147
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500148 def test_help_kickstart(self):
149 """Test wic help kickstart"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800150 runCmd('wic help kickstart')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500151
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500152 def test_list_images(self):
153 """Test wic list images"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800154 runCmd('wic list images')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500155
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500156 def test_list_source_plugins(self):
157 """Test wic list source-plugins"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800158 runCmd('wic list source-plugins')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500159
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500160 def test_listed_images_help(self):
161 """Test wic listed images help"""
162 output = runCmd('wic list images').output
163 imagelist = [line.split()[0] for line in output.splitlines()]
164 for image in imagelist:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800165 runCmd('wic list %s help' % image)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500166
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500167 def test_unsupported_subcommand(self):
168 """Test unsupported subcommand"""
169 self.assertNotEqual(0, runCmd('wic unsupported', ignore_status=True).status)
170
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500171 def test_no_command(self):
172 """Test wic without command"""
173 self.assertEqual(1, runCmd('wic', ignore_status=True).status)
174
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500175 def test_build_image_name(self):
176 """Test wic create wictestdisk --image-name=core-image-minimal"""
177 cmd = "wic create wictestdisk --image-name=core-image-minimal -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800178 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500179 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
180
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500181 @only_for_arch(['i586', 'i686', 'x86_64'])
182 def test_gpt_image(self):
183 """Test creation of core-image-minimal with gpt table and UUID boot"""
184 cmd = "wic create directdisk-gpt --image-name core-image-minimal -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800185 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500186 self.assertEqual(1, len(glob(self.resultdir + "directdisk-*.direct")))
187
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500188 @only_for_arch(['i586', 'i686', 'x86_64'])
189 def test_iso_image(self):
190 """Test creation of hybrid iso image with legacy and EFI boot"""
191 config = 'INITRAMFS_IMAGE = "core-image-minimal-initramfs"\n'\
192 'MACHINE_FEATURES_append = " efi"\n'\
193 'DEPENDS_pn-core-image-minimal += "syslinux"\n'
194 self.append_config(config)
Brad Bishopc4ea0752018-11-15 14:30:15 -0800195 bitbake('core-image-minimal core-image-minimal-initramfs')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500196 self.remove_config(config)
197 cmd = "wic create mkhybridiso --image-name core-image-minimal -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800198 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500199 self.assertEqual(1, len(glob(self.resultdir + "HYBRID_ISO_IMG-*.direct")))
200 self.assertEqual(1, len(glob(self.resultdir + "HYBRID_ISO_IMG-*.iso")))
201
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500202 @only_for_arch(['i586', 'i686', 'x86_64'])
203 def test_qemux86_directdisk(self):
204 """Test creation of qemux-86-directdisk image"""
205 cmd = "wic create qemux86-directdisk -e core-image-minimal -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800206 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500207 self.assertEqual(1, len(glob(self.resultdir + "qemux86-directdisk-*direct")))
208
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500209 @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
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800213 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500214 self.assertEqual(1, len(glob(self.resultdir + "mkefidisk-*direct")))
215
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500216 @only_for_arch(['i586', 'i686', 'x86_64'])
217 def test_bootloader_config(self):
218 """Test creation of directdisk-bootloader-config image"""
219 config = 'DEPENDS_pn-core-image-minimal += "syslinux"\n'
220 self.append_config(config)
221 bitbake('core-image-minimal')
222 self.remove_config(config)
223 cmd = "wic create directdisk-bootloader-config -e core-image-minimal -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800224 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500225 self.assertEqual(1, len(glob(self.resultdir + "directdisk-bootloader-config-*direct")))
226
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500227 @only_for_arch(['i586', 'i686', 'x86_64'])
228 def test_systemd_bootdisk(self):
229 """Test creation of systemd-bootdisk image"""
230 config = 'MACHINE_FEATURES_append = " efi"\n'
231 self.append_config(config)
232 bitbake('core-image-minimal')
233 self.remove_config(config)
234 cmd = "wic create systemd-bootdisk -e core-image-minimal -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800235 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500236 self.assertEqual(1, len(glob(self.resultdir + "systemd-bootdisk-*direct")))
237
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500238 def test_efi_bootpart(self):
239 """Test creation of efi-bootpart image"""
240 cmd = "wic create mkefidisk -e core-image-minimal -o %s" % self.resultdir
241 kimgtype = get_bb_var('KERNEL_IMAGETYPE', 'core-image-minimal')
242 self.append_config('IMAGE_EFI_BOOT_FILES = "%s;kernel"\n' % kimgtype)
243 runCmd(cmd)
244 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
245 images = glob(self.resultdir + "mkefidisk-*.direct")
246 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
247 self.assertIn("kernel",result.output)
248
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500249 def test_sdimage_bootpart(self):
250 """Test creation of sdimage-bootpart image"""
251 cmd = "wic create sdimage-bootpart -e core-image-minimal -o %s" % self.resultdir
252 kimgtype = get_bb_var('KERNEL_IMAGETYPE', 'core-image-minimal')
253 self.write_config('IMAGE_BOOT_FILES = "%s"\n' % kimgtype)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800254 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500255 self.assertEqual(1, len(glob(self.resultdir + "sdimage-bootpart-*direct")))
256
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500257 @only_for_arch(['i586', 'i686', 'x86_64'])
258 def test_default_output_dir(self):
259 """Test default output location"""
260 for fname in glob("directdisk-*.direct"):
261 os.remove(fname)
262 config = 'DEPENDS_pn-core-image-minimal += "syslinux"\n'
263 self.append_config(config)
264 bitbake('core-image-minimal')
265 self.remove_config(config)
266 cmd = "wic create directdisk -e core-image-minimal"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800267 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500268 self.assertEqual(1, len(glob("directdisk-*.direct")))
269
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500270 @only_for_arch(['i586', 'i686', 'x86_64'])
271 def test_build_artifacts(self):
272 """Test wic create directdisk providing all artifacts."""
273 bb_vars = get_bb_vars(['STAGING_DATADIR', 'RECIPE_SYSROOT_NATIVE'],
274 'wic-tools')
275 bb_vars.update(get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_ROOTFS'],
276 'core-image-minimal'))
277 bbvars = {key.lower(): value for key, value in bb_vars.items()}
278 bbvars['resultdir'] = self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800279 runCmd("wic create directdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500280 "-b %(staging_datadir)s "
281 "-k %(deploy_dir_image)s "
282 "-n %(recipe_sysroot_native)s "
283 "-r %(image_rootfs)s "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800284 "-o %(resultdir)s" % bbvars)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500285 self.assertEqual(1, len(glob(self.resultdir + "directdisk-*.direct")))
286
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500287 def test_compress_gzip(self):
288 """Test compressing an image with gzip"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800289 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500290 "--image-name core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800291 "-c gzip -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500292 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct.gz")))
293
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500294 def test_compress_bzip2(self):
295 """Test compressing an image with bzip2"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800296 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500297 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800298 "-c bzip2 -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500299 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct.bz2")))
300
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500301 def test_compress_xz(self):
302 """Test compressing an image with xz"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800303 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500304 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800305 "--compress-with=xz -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500306 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct.xz")))
307
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500308 def test_wrong_compressor(self):
309 """Test how wic breaks if wrong compressor is provided"""
310 self.assertEqual(2, runCmd("wic create wictestdisk "
311 "--image-name=core-image-minimal "
312 "-c wrong -o %s" % self.resultdir,
313 ignore_status=True).status)
314
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500315 def test_debug_short(self):
316 """Test -D option"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800317 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500318 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800319 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500320 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600321 self.assertEqual(1, len(glob(self.resultdir + "tmp.wic*")))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500322
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500323 def test_debug_long(self):
324 """Test --debug option"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800325 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500326 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800327 "--debug -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500328 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600329 self.assertEqual(1, len(glob(self.resultdir + "tmp.wic*")))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500330
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500331 def test_skip_build_check_short(self):
332 """Test -s option"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800333 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500334 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800335 "-s -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500336 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
337
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500338 def test_skip_build_check_long(self):
339 """Test --skip-build-check option"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800340 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500341 "--image-name=core-image-minimal "
342 "--skip-build-check "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800343 "--outdir %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500344 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
345
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500346 def test_build_rootfs_short(self):
347 """Test -f option"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800348 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500349 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800350 "-f -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500351 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
352
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500353 def test_build_rootfs_long(self):
354 """Test --build-rootfs option"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800355 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500356 "--image-name=core-image-minimal "
357 "--build-rootfs "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800358 "--outdir %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500359 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
360
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500361 @only_for_arch(['i586', 'i686', 'x86_64'])
362 def test_rootfs_indirect_recipes(self):
363 """Test usage of rootfs plugin with rootfs recipes"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800364 runCmd("wic create directdisk-multi-rootfs "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500365 "--image-name=core-image-minimal "
366 "--rootfs rootfs1=core-image-minimal "
367 "--rootfs rootfs2=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800368 "--outdir %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500369 self.assertEqual(1, len(glob(self.resultdir + "directdisk-multi-rootfs*.direct")))
370
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500371 @only_for_arch(['i586', 'i686', 'x86_64'])
372 def test_rootfs_artifacts(self):
373 """Test usage of rootfs plugin with rootfs paths"""
374 bb_vars = get_bb_vars(['STAGING_DATADIR', 'RECIPE_SYSROOT_NATIVE'],
375 'wic-tools')
376 bb_vars.update(get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_ROOTFS'],
377 'core-image-minimal'))
378 bbvars = {key.lower(): value for key, value in bb_vars.items()}
379 bbvars['wks'] = "directdisk-multi-rootfs"
380 bbvars['resultdir'] = self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800381 runCmd("wic create %(wks)s "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500382 "--bootimg-dir=%(staging_datadir)s "
383 "--kernel-dir=%(deploy_dir_image)s "
384 "--native-sysroot=%(recipe_sysroot_native)s "
385 "--rootfs-dir rootfs1=%(image_rootfs)s "
386 "--rootfs-dir rootfs2=%(image_rootfs)s "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800387 "--outdir %(resultdir)s" % bbvars)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500388 self.assertEqual(1, len(glob(self.resultdir + "%(wks)s-*.direct" % bbvars)))
389
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500390 def test_exclude_path(self):
391 """Test --exclude-path wks option."""
392
393 oldpath = os.environ['PATH']
394 os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
395
396 try:
397 wks_file = 'temp.wks'
398 with open(wks_file, 'w') as wks:
399 rootfs_dir = get_bb_var('IMAGE_ROOTFS', 'core-image-minimal')
400 wks.write("""
401part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path usr
402part /usr --source rootfs --ondisk mmcblk0 --fstype=ext4 --rootfs-dir %s/usr
403part /etc --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path bin/ --rootfs-dir %s/usr"""
404 % (rootfs_dir, rootfs_dir))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800405 runCmd("wic create %s -e core-image-minimal -o %s" \
406 % (wks_file, self.resultdir))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500407
408 os.remove(wks_file)
409 wicout = glob(self.resultdir + "%s-*direct" % 'temp')
410 self.assertEqual(1, len(wicout))
411
412 wicimg = wicout[0]
413
414 # verify partition size with wic
415 res = runCmd("parted -m %s unit b p 2>/dev/null" % wicimg)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500416
417 # parse parted output which looks like this:
418 # BYT;\n
419 # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n
420 # 1:0.00MiB:200MiB:200MiB:ext4::;\n
421 partlns = res.output.splitlines()[2:]
422
423 self.assertEqual(3, len(partlns))
424
425 for part in [1, 2, 3]:
426 part_file = os.path.join(self.resultdir, "selftest_img.part%d" % part)
427 partln = partlns[part-1].split(":")
428 self.assertEqual(7, len(partln))
429 start = int(partln[1].rstrip("B")) / 512
430 length = int(partln[3].rstrip("B")) / 512
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800431 runCmd("dd if=%s of=%s skip=%d count=%d" %
432 (wicimg, part_file, start, length))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500433
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500434 # Test partition 1, should contain the normal root directories, except
435 # /usr.
436 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \
437 os.path.join(self.resultdir, "selftest_img.part1"))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500438 files = extract_files(res.output)
439 self.assertIn("etc", files)
440 self.assertNotIn("usr", files)
441
442 # Partition 2, should contain common directories for /usr, not root
443 # directories.
444 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \
445 os.path.join(self.resultdir, "selftest_img.part2"))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500446 files = extract_files(res.output)
447 self.assertNotIn("etc", files)
448 self.assertNotIn("usr", files)
449 self.assertIn("share", files)
450
451 # Partition 3, should contain the same as partition 2, including the bin
452 # directory, but not the files inside it.
453 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \
454 os.path.join(self.resultdir, "selftest_img.part3"))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500455 files = extract_files(res.output)
456 self.assertNotIn("etc", files)
457 self.assertNotIn("usr", files)
458 self.assertIn("share", files)
459 self.assertIn("bin", files)
460 res = runCmd("debugfs -R 'ls -p bin' %s 2>/dev/null" % \
461 os.path.join(self.resultdir, "selftest_img.part3"))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500462 files = extract_files(res.output)
463 self.assertIn(".", files)
464 self.assertIn("..", files)
465 self.assertEqual(2, len(files))
466
467 for part in [1, 2, 3]:
468 part_file = os.path.join(self.resultdir, "selftest_img.part%d" % part)
469 os.remove(part_file)
470
471 finally:
472 os.environ['PATH'] = oldpath
473
Andrew Geissler82c905d2020-04-13 13:39:40 -0500474 def test_include_path(self):
475 """Test --include-path wks option."""
476
477 oldpath = os.environ['PATH']
478 os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
479
480 try:
481 include_path = os.path.join(self.resultdir, 'test-include')
482 os.makedirs(include_path)
483 with open(os.path.join(include_path, 'test-file'), 'w') as t:
484 t.write("test\n")
485 wks_file = os.path.join(include_path, 'temp.wks')
486 with open(wks_file, 'w') as wks:
487 rootfs_dir = get_bb_var('IMAGE_ROOTFS', 'core-image-minimal')
488 wks.write("""
489part /part1 --source rootfs --ondisk mmcblk0 --fstype=ext4
490part /part2 --source rootfs --ondisk mmcblk0 --fstype=ext4 --include-path %s"""
491 % (include_path))
492 runCmd("wic create %s -e core-image-minimal -o %s" \
493 % (wks_file, self.resultdir))
494
495 part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0]
496 part2 = glob(os.path.join(self.resultdir, 'temp-*.direct.p2'))[0]
497
498 # Test partition 1, should not contain 'test-file'
499 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1))
500 files = extract_files(res.output)
501 self.assertNotIn('test-file', files)
502 self.assertEqual(True, files_own_by_root(res.output))
503
504 # Test partition 2, should contain 'test-file'
505 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part2))
506 files = extract_files(res.output)
507 self.assertIn('test-file', files)
508 self.assertEqual(True, files_own_by_root(res.output))
509
510 finally:
511 os.environ['PATH'] = oldpath
512
513 def test_include_path_embeded(self):
514 """Test --include-path wks option."""
515
516 oldpath = os.environ['PATH']
517 os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
518
519 try:
520 include_path = os.path.join(self.resultdir, 'test-include')
521 os.makedirs(include_path)
522 with open(os.path.join(include_path, 'test-file'), 'w') as t:
523 t.write("test\n")
524 wks_file = os.path.join(include_path, 'temp.wks')
525 with open(wks_file, 'w') as wks:
526 wks.write("""
527part / --source rootfs --fstype=ext4 --include-path %s --include-path core-image-minimal-mtdutils export/"""
528 % (include_path))
529 runCmd("wic create %s -e core-image-minimal -o %s" \
530 % (wks_file, self.resultdir))
531
532 part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0]
533
534 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1))
535 files = extract_files(res.output)
536 self.assertIn('test-file', files)
537 self.assertEqual(True, files_own_by_root(res.output))
538
539 res = runCmd("debugfs -R 'ls -p /export/etc/' %s 2>/dev/null" % (part1))
540 files = extract_files(res.output)
541 self.assertIn('passwd', files)
542 self.assertEqual(True, files_own_by_root(res.output))
543
544 finally:
545 os.environ['PATH'] = oldpath
546
547 def test_include_path_errors(self):
548 """Test --include-path wks option error handling."""
549 wks_file = 'temp.wks'
550
551 # Absolute argument.
552 with open(wks_file, 'w') as wks:
553 wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils /export")
554 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
555 % (wks_file, self.resultdir), ignore_status=True).status)
556 os.remove(wks_file)
557
558 # Argument pointing to parent directory.
559 with open(wks_file, 'w') as wks:
560 wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils ././..")
561 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
562 % (wks_file, self.resultdir), ignore_status=True).status)
563 os.remove(wks_file)
564
565 # 3 Argument pointing to parent directory.
566 with open(wks_file, 'w') as wks:
567 wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils export/ dummy")
568 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
569 % (wks_file, self.resultdir), ignore_status=True).status)
570 os.remove(wks_file)
571
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500572 def test_exclude_path_errors(self):
573 """Test --exclude-path wks option error handling."""
574 wks_file = 'temp.wks'
575
576 # Absolute argument.
577 with open(wks_file, 'w') as wks:
578 wks.write("part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path /usr")
579 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
580 % (wks_file, self.resultdir), ignore_status=True).status)
581 os.remove(wks_file)
582
583 # Argument pointing to parent directory.
584 with open(wks_file, 'w') as wks:
585 wks.write("part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path ././..")
586 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
587 % (wks_file, self.resultdir), ignore_status=True).status)
588 os.remove(wks_file)
589
Andrew Geissler82c905d2020-04-13 13:39:40 -0500590 def test_permissions(self):
591 """Test permissions are respected"""
592
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600593 # prepare wicenv and rootfs
594 bitbake('core-image-minimal core-image-minimal-mtdutils -c do_rootfs_wicenv')
595
Andrew Geissler82c905d2020-04-13 13:39:40 -0500596 oldpath = os.environ['PATH']
597 os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
598
599 t_normal = """
600part / --source rootfs --fstype=ext4
601"""
602 t_exclude = """
603part / --source rootfs --fstype=ext4 --exclude-path=home
604"""
605 t_multi = """
606part / --source rootfs --ondisk sda --fstype=ext4
607part /export --source rootfs --rootfs=core-image-minimal-mtdutils --fstype=ext4
608"""
609 t_change = """
610part / --source rootfs --ondisk sda --fstype=ext4 --exclude-path=etc/   
611part /etc --source rootfs --fstype=ext4 --change-directory=etc
612"""
613 tests = [t_normal, t_exclude, t_multi, t_change]
614
615 try:
616 for test in tests:
617 include_path = os.path.join(self.resultdir, 'test-include')
618 os.makedirs(include_path)
619 wks_file = os.path.join(include_path, 'temp.wks')
620 with open(wks_file, 'w') as wks:
621 wks.write(test)
622 runCmd("wic create %s -e core-image-minimal -o %s" \
623 % (wks_file, self.resultdir))
624
625 for part in glob(os.path.join(self.resultdir, 'temp-*.direct.p*')):
626 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part))
627 self.assertEqual(True, files_own_by_root(res.output))
628
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600629 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "%s"\n' % wks_file
630 self.append_config(config)
631 bitbake('core-image-minimal')
632 tmpdir = os.path.join(get_bb_var('WORKDIR', 'core-image-minimal'),'build-wic')
633
634 # check each partition for permission
635 for part in glob(os.path.join(tmpdir, 'temp-*.direct.p*')):
636 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part))
637 self.assertTrue(files_own_by_root(res.output)
638 ,msg='Files permission incorrect using wks set "%s"' % test)
639
640 # clean config and result directory for next cases
641 self.remove_config(config)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500642 rmtree(self.resultdir, ignore_errors=True)
643
644 finally:
645 os.environ['PATH'] = oldpath
646
647 def test_change_directory(self):
648 """Test --change-directory wks option."""
649
650 oldpath = os.environ['PATH']
651 os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
652
653 try:
654 include_path = os.path.join(self.resultdir, 'test-include')
655 os.makedirs(include_path)
656 wks_file = os.path.join(include_path, 'temp.wks')
657 with open(wks_file, 'w') as wks:
658 wks.write("part /etc --source rootfs --fstype=ext4 --change-directory=etc")
659 runCmd("wic create %s -e core-image-minimal -o %s" \
660 % (wks_file, self.resultdir))
661
662 part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0]
663
664 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1))
665 files = extract_files(res.output)
666 self.assertIn('passwd', files)
667
668 finally:
669 os.environ['PATH'] = oldpath
670
671 def test_change_directory_errors(self):
672 """Test --change-directory wks option error handling."""
673 wks_file = 'temp.wks'
674
675 # Absolute argument.
676 with open(wks_file, 'w') as wks:
677 wks.write("part / --source rootfs --fstype=ext4 --change-directory /usr")
678 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
679 % (wks_file, self.resultdir), ignore_status=True).status)
680 os.remove(wks_file)
681
682 # Argument pointing to parent directory.
683 with open(wks_file, 'w') as wks:
684 wks.write("part / --source rootfs --fstype=ext4 --change-directory ././..")
685 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
686 % (wks_file, self.resultdir), ignore_status=True).status)
687 os.remove(wks_file)
688
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800689class Wic2(WicTestCase):
690
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500691 def test_bmap_short(self):
692 """Test generation of .bmap file -m option"""
693 cmd = "wic create wictestdisk -e core-image-minimal -m -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800694 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500695 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct")))
696 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct.bmap")))
697
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500698 def test_bmap_long(self):
699 """Test generation of .bmap file --bmap option"""
700 cmd = "wic create wictestdisk -e core-image-minimal --bmap -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800701 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500702 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct")))
703 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct.bmap")))
704
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500705 def test_image_env(self):
706 """Test generation of <image>.env files."""
707 image = 'core-image-minimal'
708 imgdatadir = self._get_image_env_path(image)
709
710 bb_vars = get_bb_vars(['IMAGE_BASENAME', 'WICVARS'], image)
711 basename = bb_vars['IMAGE_BASENAME']
712 self.assertEqual(basename, image)
713 path = os.path.join(imgdatadir, basename) + '.env'
714 self.assertTrue(os.path.isfile(path))
715
716 wicvars = set(bb_vars['WICVARS'].split())
717 # filter out optional variables
718 wicvars = wicvars.difference(('DEPLOY_DIR_IMAGE', 'IMAGE_BOOT_FILES',
Brad Bishop96ff1982019-08-19 13:50:42 -0400719 'INITRD', 'INITRD_LIVE', 'ISODIR','INITRAMFS_IMAGE',
Andrew Geissler82c905d2020-04-13 13:39:40 -0500720 'INITRAMFS_IMAGE_BUNDLE', 'INITRAMFS_LINK_NAME',
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500721 'APPEND', 'IMAGE_EFI_BOOT_FILES'))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500722 with open(path) as envfile:
723 content = dict(line.split("=", 1) for line in envfile)
724 # test if variables used by wic present in the .env file
725 for var in wicvars:
726 self.assertTrue(var in content, "%s is not in .env file" % var)
727 self.assertTrue(content[var])
728
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500729 def test_image_vars_dir_short(self):
730 """Test image vars directory selection -v option"""
731 image = 'core-image-minimal'
732 imgenvdir = self._get_image_env_path(image)
733 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
734
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800735 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500736 "--image-name=%s -v %s -n %s -o %s"
737 % (image, imgenvdir, native_sysroot,
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800738 self.resultdir))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500739 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct")))
740
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500741 def test_image_vars_dir_long(self):
742 """Test image vars directory selection --vars option"""
743 image = 'core-image-minimal'
744 imgenvdir = self._get_image_env_path(image)
745 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
746
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800747 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500748 "--image-name=%s "
749 "--vars %s "
750 "--native-sysroot %s "
751 "--outdir %s"
752 % (image, imgenvdir, native_sysroot,
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800753 self.resultdir))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500754 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct")))
755
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500756 @only_for_arch(['i586', 'i686', 'x86_64'])
757 def test_wic_image_type(self):
758 """Test building wic images by bitbake"""
759 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\
760 'MACHINE_FEATURES_append = " efi"\n'
761 self.append_config(config)
762 self.assertEqual(0, bitbake('wic-image-minimal').status)
763 self.remove_config(config)
764
765 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'MACHINE'])
766 deploy_dir = bb_vars['DEPLOY_DIR_IMAGE']
767 machine = bb_vars['MACHINE']
768 prefix = os.path.join(deploy_dir, 'wic-image-minimal-%s.' % machine)
769 # check if we have result image and manifests symlinks
770 # pointing to existing files
771 for suffix in ('wic', 'manifest'):
772 path = prefix + suffix
773 self.assertTrue(os.path.islink(path))
774 self.assertTrue(os.path.isfile(os.path.realpath(path)))
775
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500776 @only_for_arch(['i586', 'i686', 'x86_64'])
777 def test_qemu(self):
778 """Test wic-image-minimal under qemu"""
779 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\
780 'MACHINE_FEATURES_append = " efi"\n'
781 self.append_config(config)
782 self.assertEqual(0, bitbake('wic-image-minimal').status)
783 self.remove_config(config)
784
785 with runqemu('wic-image-minimal', ssh=False) as qemu:
Andrew Geissler99467da2019-02-25 18:54:23 -0600786 cmd = "mount | grep '^/dev/' | cut -f1,3 -d ' ' | egrep -c -e '/dev/sda1 /boot' " \
787 "-e '/dev/root /|/dev/sda2 /' -e '/dev/sda3 /media' -e '/dev/sda4 /mnt'"
Brad Bishop316dfdd2018-06-25 12:45:53 -0400788 status, output = qemu.run_serial(cmd)
Andrew Geissler99467da2019-02-25 18:54:23 -0600789 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
790 self.assertEqual(output, '4')
Brad Bishop316dfdd2018-06-25 12:45:53 -0400791 cmd = "grep UUID= /etc/fstab"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500792 status, output = qemu.run_serial(cmd)
793 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
Brad Bishop316dfdd2018-06-25 12:45:53 -0400794 self.assertEqual(output, 'UUID=2c71ef06-a81d-4735-9d3a-379b69c6bdba\t/media\text4\tdefaults\t0\t0')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500795
796 @only_for_arch(['i586', 'i686', 'x86_64'])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500797 def test_qemu_efi(self):
798 """Test core-image-minimal efi image under qemu"""
799 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "mkefidisk.wks"\n'
800 self.append_config(config)
801 self.assertEqual(0, bitbake('core-image-minimal ovmf').status)
802 self.remove_config(config)
803
804 with runqemu('core-image-minimal', ssh=False,
805 runqemuparams='ovmf', image_fstype='wic') as qemu:
806 cmd = "grep sda. /proc/partitions |wc -l"
807 status, output = qemu.run_serial(cmd)
808 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
809 self.assertEqual(output, '3')
810
811 @staticmethod
812 def _make_fixed_size_wks(size):
813 """
814 Create a wks of an image with a single partition. Size of the partition is set
815 using --fixed-size flag. Returns a tuple: (path to wks file, wks image name)
816 """
817 with NamedTemporaryFile("w", suffix=".wks", delete=False) as tempf:
818 wkspath = tempf.name
819 tempf.write("part " \
820 "--source rootfs --ondisk hda --align 4 --fixed-size %d "
821 "--fstype=ext4\n" % size)
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500822
823 return wkspath
824
825 def _get_wic_partitions(self, wkspath, native_sysroot=None, ignore_status=False):
826 p = runCmd("wic create %s -e core-image-minimal -o %s" % (wkspath, self.resultdir),
827 ignore_status=ignore_status)
828
829 if p.status:
830 return (p, None)
831
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500832 wksname = os.path.splitext(os.path.basename(wkspath))[0]
833
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500834 wicout = glob(self.resultdir + "%s-*direct" % wksname)
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500835
836 if not wicout:
837 return (p, None)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500838
839 wicimg = wicout[0]
840
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500841 if not native_sysroot:
842 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800843
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500844 # verify partition size with wic
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500845 res = runCmd("parted -m %s unit kib p 2>/dev/null" % wicimg,
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800846 native_sysroot=native_sysroot)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500847
848 # parse parted output which looks like this:
849 # BYT;\n
850 # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n
851 # 1:0.00MiB:200MiB:200MiB:ext4::;\n
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500852 return (p, res.output.splitlines()[2:])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500853
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500854 def test_fixed_size(self):
855 """
856 Test creation of a simple image with partition size controlled through
857 --fixed-size flag
858 """
859 wkspath = Wic2._make_fixed_size_wks(200)
860 _, partlns = self._get_wic_partitions(wkspath)
861 os.remove(wkspath)
862
863 self.assertEqual(partlns, [
864 "1:4.00kiB:204804kiB:204800kiB:ext4::;",
865 ])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500866
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500867 def test_fixed_size_error(self):
868 """
869 Test creation of a simple image with partition size controlled through
870 --fixed-size flag. The size of partition is intentionally set to 1MiB
871 in order to trigger an error in wic.
872 """
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500873 wkspath = Wic2._make_fixed_size_wks(1)
874 p, _ = self._get_wic_partitions(wkspath, ignore_status=True)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500875 os.remove(wkspath)
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500876
877 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output)
878
879 def test_offset(self):
880 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
881
882 with NamedTemporaryFile("w", suffix=".wks") as tempf:
883 # Test that partitions are placed at the correct offsets, default KB
884 tempf.write("bootloader --ptable gpt\n" \
885 "part / --source rootfs --ondisk hda --offset 32 --fixed-size 100M --fstype=ext4\n" \
886 "part /bar --ondisk hda --offset 102432 --fixed-size 100M --fstype=ext4\n")
887 tempf.flush()
888
889 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
890 self.assertEqual(partlns, [
891 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;",
892 "2:102432kiB:204832kiB:102400kiB:ext4:primary:;",
893 ])
894
895 with NamedTemporaryFile("w", suffix=".wks") as tempf:
896 # Test that partitions are placed at the correct offsets, same with explicit KB
897 tempf.write("bootloader --ptable gpt\n" \
898 "part / --source rootfs --ondisk hda --offset 32K --fixed-size 100M --fstype=ext4\n" \
899 "part /bar --ondisk hda --offset 102432K --fixed-size 100M --fstype=ext4\n")
900 tempf.flush()
901
902 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
903 self.assertEqual(partlns, [
904 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;",
905 "2:102432kiB:204832kiB:102400kiB:ext4:primary:;",
906 ])
907
908 with NamedTemporaryFile("w", suffix=".wks") as tempf:
909 # Test that partitions are placed at the correct offsets using MB
910 tempf.write("bootloader --ptable gpt\n" \
911 "part / --source rootfs --ondisk hda --offset 32K --fixed-size 100M --fstype=ext4\n" \
912 "part /bar --ondisk hda --offset 101M --fixed-size 100M --fstype=ext4\n")
913 tempf.flush()
914
915 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
916 self.assertEqual(partlns, [
917 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;",
918 "2:103424kiB:205824kiB:102400kiB:ext4:primary:;",
919 ])
920
921 with NamedTemporaryFile("w", suffix=".wks") as tempf:
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500922 # Test that partitions can be placed on a 512 byte sector boundary
923 tempf.write("bootloader --ptable gpt\n" \
924 "part / --source rootfs --ondisk hda --offset 65s --fixed-size 99M --fstype=ext4\n" \
925 "part /bar --ondisk hda --offset 102432 --fixed-size 100M --fstype=ext4\n")
926 tempf.flush()
927
928 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
929 self.assertEqual(partlns, [
930 "1:32.5kiB:101408kiB:101376kiB:ext4:primary:;",
931 "2:102432kiB:204832kiB:102400kiB:ext4:primary:;",
932 ])
933
934 with NamedTemporaryFile("w", suffix=".wks") as tempf:
935 # Test that a partition can be placed immediately after a MSDOS partition table
936 tempf.write("bootloader --ptable msdos\n" \
937 "part / --source rootfs --ondisk hda --offset 1s --fixed-size 100M --fstype=ext4\n")
938 tempf.flush()
939
940 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
941 self.assertEqual(partlns, [
942 "1:0.50kiB:102400kiB:102400kiB:ext4::;",
943 ])
944
945 with NamedTemporaryFile("w", suffix=".wks") as tempf:
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500946 # Test that image creation fails if the partitions would overlap
947 tempf.write("bootloader --ptable gpt\n" \
948 "part / --source rootfs --ondisk hda --offset 32 --fixed-size 100M --fstype=ext4\n" \
949 "part /bar --ondisk hda --offset 102431 --fixed-size 100M --fstype=ext4\n")
950 tempf.flush()
951
952 p, _ = self._get_wic_partitions(tempf.name, ignore_status=True)
953 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output)
954
955 with NamedTemporaryFile("w", suffix=".wks") as tempf:
956 # Test that partitions are not allowed to overlap with the booloader
957 tempf.write("bootloader --ptable gpt\n" \
958 "part / --source rootfs --ondisk hda --offset 8 --fixed-size 100M --fstype=ext4\n")
959 tempf.flush()
960
961 p, _ = self._get_wic_partitions(tempf.name, ignore_status=True)
962 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500963
Andrew Geissler5a43b432020-06-13 10:46:56 -0500964 def test_extra_space(self):
965 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
966
967 with NamedTemporaryFile("w", suffix=".wks") as tempf:
968 tempf.write("bootloader --ptable gpt\n" \
969 "part / --source rootfs --ondisk hda --extra-space 200M --fstype=ext4\n")
970 tempf.flush()
971
972 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
973 self.assertEqual(len(partlns), 1)
974 size = partlns[0].split(':')[3]
975 self.assertRegex(size, r'^[0-9]+kiB$')
976 size = int(size[:-3])
977 self.assertGreaterEqual(size, 204800)
978
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500979 @only_for_arch(['i586', 'i686', 'x86_64'])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500980 def test_rawcopy_plugin_qemu(self):
981 """Test rawcopy plugin in qemu"""
Andrew Geissler95ac1b82021-03-31 14:34:31 -0500982 # build ext4 and then use it for a wic image
983 config = 'IMAGE_FSTYPES = "ext4"\n'
984 self.append_config(config)
985 self.assertEqual(0, bitbake('core-image-minimal').status)
986 self.remove_config(config)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500987
Andrew Geissler95ac1b82021-03-31 14:34:31 -0500988 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_rawcopy_plugin.wks.in"\n'
989 self.append_config(config)
990 self.assertEqual(0, bitbake('core-image-minimal-mtdutils').status)
991 self.remove_config(config)
992
993 with runqemu('core-image-minimal-mtdutils', ssh=False, image_fstype='wic') as qemu:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500994 cmd = "grep sda. /proc/partitions |wc -l"
995 status, output = qemu.run_serial(cmd)
996 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
997 self.assertEqual(output, '2')
998
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500999 def test_rawcopy_plugin(self):
1000 """Test rawcopy plugin"""
1001 img = 'core-image-minimal'
1002 machine = get_bb_var('MACHINE', img)
1003 with NamedTemporaryFile("w", suffix=".wks") as wks:
1004 wks.writelines(['part /boot --active --source bootimg-pcbios\n',
1005 'part / --source rawcopy --sourceparams="file=%s-%s.ext4" --use-uuid\n'\
1006 % (img, machine),
1007 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n'])
1008 wks.flush()
1009 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001010 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001011 wksname = os.path.splitext(os.path.basename(wks.name))[0]
1012 out = glob(self.resultdir + "%s-*direct" % wksname)
1013 self.assertEqual(1, len(out))
1014
Andrew Geisslerd1e89492021-02-12 15:35:20 -06001015 def test_empty_plugin(self):
1016 """Test empty plugin"""
1017 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_empty_plugin.wks"\n'
1018 self.append_config(config)
1019 self.assertEqual(0, bitbake('core-image-minimal').status)
1020 self.remove_config(config)
1021
1022 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'MACHINE'])
1023 deploy_dir = bb_vars['DEPLOY_DIR_IMAGE']
1024 machine = bb_vars['MACHINE']
1025 image_path = os.path.join(deploy_dir, 'core-image-minimal-%s.wic' % machine)
1026 self.assertEqual(True, os.path.exists(image_path))
1027
1028 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1029
1030 # Fstype column from 'wic ls' should be empty for the second partition
1031 # as listed in test_empty_plugin.wks
1032 result = runCmd("wic ls %s -n %s | awk -F ' ' '{print $1 \" \" $5}' | grep '^2' | wc -w" % (image_path, sysroot))
1033 self.assertEqual('1', result.output)
1034
Brad Bishop96ff1982019-08-19 13:50:42 -04001035 @only_for_arch(['i586', 'i686', 'x86_64'])
1036 def test_biosplusefi_plugin_qemu(self):
1037 """Test biosplusefi plugin in qemu"""
Brad Bishop08902b02019-08-20 09:16:51 -04001038 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES_append = " efi"\n'
1039 self.append_config(config)
1040 self.assertEqual(0, bitbake('core-image-minimal').status)
1041 self.remove_config(config)
Brad Bishop96ff1982019-08-19 13:50:42 -04001042
1043 with runqemu('core-image-minimal', ssh=False, image_fstype='wic') as qemu:
1044 # Check that we have ONLY two /dev/sda* partitions (/boot and /)
1045 cmd = "grep sda. /proc/partitions | wc -l"
1046 status, output = qemu.run_serial(cmd)
1047 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1048 self.assertEqual(output, '2')
1049 # Check that /dev/sda1 is /boot and that either /dev/root OR /dev/sda2 is /
1050 cmd = "mount | grep '^/dev/' | cut -f1,3 -d ' ' | egrep -c -e '/dev/sda1 /boot' -e '/dev/root /|/dev/sda2 /'"
1051 status, output = qemu.run_serial(cmd)
1052 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1053 self.assertEqual(output, '2')
1054 # Check that /boot has EFI bootx64.efi (required for EFI)
1055 cmd = "ls /boot/EFI/BOOT/bootx64.efi | wc -l"
1056 status, output = qemu.run_serial(cmd)
1057 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1058 self.assertEqual(output, '1')
1059 # Check that "BOOTABLE" flag is set on boot partition (required for PC-Bios)
1060 # Trailing "cat" seems to be required; otherwise run_serial() sends back echo of the input command
1061 cmd = "fdisk -l /dev/sda | grep /dev/sda1 | awk {print'$2'} | cat"
1062 status, output = qemu.run_serial(cmd)
1063 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1064 self.assertEqual(output, '*')
1065
1066 @only_for_arch(['i586', 'i686', 'x86_64'])
1067 def test_biosplusefi_plugin(self):
1068 """Test biosplusefi plugin"""
1069 # Wic generation below may fail depending on the order of the unittests
1070 # This is because bootimg-pcbios (that bootimg-biosplusefi uses) generate its MBR inside STAGING_DATADIR directory
1071 # which may or may not exists depending on what was built already
1072 # If an image hasn't been built yet, directory ${STAGING_DATADIR}/syslinux won't exists and _get_bootimg_dir()
1073 # will raise with "Couldn't find correct bootimg_dir"
1074 # The easiest way to work-around this issue is to make sure we already built an image here, hence the bitbake call
Brad Bishop08902b02019-08-20 09:16:51 -04001075 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES_append = " efi"\n'
1076 self.append_config(config)
1077 self.assertEqual(0, bitbake('core-image-minimal').status)
1078 self.remove_config(config)
Brad Bishop96ff1982019-08-19 13:50:42 -04001079
1080 img = 'core-image-minimal'
1081 with NamedTemporaryFile("w", suffix=".wks") as wks:
1082 wks.writelines(['part /boot --active --source bootimg-biosplusefi --sourceparams="loader=grub-efi"\n',
1083 'part / --source rootfs --fstype=ext4 --align 1024 --use-uuid\n'\
1084 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n'])
1085 wks.flush()
1086 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
1087 runCmd(cmd)
1088 wksname = os.path.splitext(os.path.basename(wks.name))[0]
1089 out = glob(self.resultdir + "%s-*.direct" % wksname)
1090 self.assertEqual(1, len(out))
1091
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001092 def test_fs_types(self):
1093 """Test filesystem types for empty and not empty partitions"""
1094 img = 'core-image-minimal'
1095 with NamedTemporaryFile("w", suffix=".wks") as wks:
1096 wks.writelines(['part ext2 --fstype ext2 --source rootfs\n',
1097 'part btrfs --fstype btrfs --source rootfs --size 40M\n',
1098 'part squash --fstype squashfs --source rootfs\n',
1099 'part swap --fstype swap --size 1M\n',
1100 'part emptyvfat --fstype vfat --size 1M\n',
1101 'part emptymsdos --fstype msdos --size 1M\n',
1102 'part emptyext2 --fstype ext2 --size 1M\n',
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001103 'part emptybtrfs --fstype btrfs --size 150M\n'])
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001104 wks.flush()
1105 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001106 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001107 wksname = os.path.splitext(os.path.basename(wks.name))[0]
1108 out = glob(self.resultdir + "%s-*direct" % wksname)
1109 self.assertEqual(1, len(out))
1110
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001111 def test_kickstart_parser(self):
1112 """Test wks parser options"""
1113 with NamedTemporaryFile("w", suffix=".wks") as wks:
1114 wks.writelines(['part / --fstype ext3 --source rootfs --system-id 0xFF '\
1115 '--overhead-factor 1.2 --size 100k\n'])
1116 wks.flush()
1117 cmd = "wic create %s -e core-image-minimal -o %s" % (wks.name, self.resultdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001118 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001119 wksname = os.path.splitext(os.path.basename(wks.name))[0]
1120 out = glob(self.resultdir + "%s-*direct" % wksname)
1121 self.assertEqual(1, len(out))
1122
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001123 def test_image_bootpart_globbed(self):
1124 """Test globbed sources with image-bootpart plugin"""
1125 img = "core-image-minimal"
1126 cmd = "wic create sdimage-bootpart -e %s -o %s" % (img, self.resultdir)
1127 config = 'IMAGE_BOOT_FILES = "%s*"' % get_bb_var('KERNEL_IMAGETYPE', img)
1128 self.append_config(config)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001129 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001130 self.remove_config(config)
1131 self.assertEqual(1, len(glob(self.resultdir + "sdimage-bootpart-*direct")))
1132
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001133 def test_sparse_copy(self):
1134 """Test sparse_copy with FIEMAP and SEEK_HOLE filemap APIs"""
1135 libpath = os.path.join(get_bb_var('COREBASE'), 'scripts', 'lib', 'wic')
1136 sys.path.insert(0, libpath)
1137 from filemap import FilemapFiemap, FilemapSeek, sparse_copy, ErrorNotSupp
1138 with NamedTemporaryFile("w", suffix=".wic-sparse") as sparse:
1139 src_name = sparse.name
1140 src_size = 1024 * 10
1141 sparse.truncate(src_size)
1142 # write one byte to the file
1143 with open(src_name, 'r+b') as sfile:
1144 sfile.seek(1024 * 4)
1145 sfile.write(b'\x00')
1146 dest = sparse.name + '.out'
1147 # copy src file to dest using different filemap APIs
1148 for api in (FilemapFiemap, FilemapSeek, None):
1149 if os.path.exists(dest):
1150 os.unlink(dest)
1151 try:
1152 sparse_copy(sparse.name, dest, api=api)
1153 except ErrorNotSupp:
1154 continue # skip unsupported API
1155 dest_stat = os.stat(dest)
1156 self.assertEqual(dest_stat.st_size, src_size)
1157 # 8 blocks is 4K (physical sector size)
1158 self.assertEqual(dest_stat.st_blocks, 8)
1159 os.unlink(dest)
1160
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001161 def test_wic_ls(self):
1162 """Test listing image content using 'wic ls'"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001163 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001164 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001165 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001166 images = glob(self.resultdir + "wictestdisk-*.direct")
1167 self.assertEqual(1, len(images))
1168
1169 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1170
1171 # list partitions
1172 result = runCmd("wic ls %s -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001173 self.assertEqual(3, len(result.output.split('\n')))
1174
1175 # list directory content of the first partition
1176 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001177 self.assertEqual(6, len(result.output.split('\n')))
1178
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001179 def test_wic_cp(self):
1180 """Test copy files and directories to the the wic image."""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001181 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001182 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001183 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001184 images = glob(self.resultdir + "wictestdisk-*.direct")
1185 self.assertEqual(1, len(images))
1186
1187 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1188
1189 # list directory content of the first partition
1190 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001191 self.assertEqual(6, len(result.output.split('\n')))
1192
1193 with NamedTemporaryFile("w", suffix=".wic-cp") as testfile:
1194 testfile.write("test")
1195
1196 # copy file to the partition
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001197 runCmd("wic cp %s %s:1/ -n %s" % (testfile.name, images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001198
1199 # check if file is there
1200 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001201 self.assertEqual(7, len(result.output.split('\n')))
1202 self.assertTrue(os.path.basename(testfile.name) in result.output)
1203
1204 # prepare directory
1205 testdir = os.path.join(self.resultdir, 'wic-test-cp-dir')
1206 testsubdir = os.path.join(testdir, 'subdir')
1207 os.makedirs(os.path.join(testsubdir))
1208 copy(testfile.name, testdir)
1209
1210 # copy directory to the partition
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001211 runCmd("wic cp %s %s:1/ -n %s" % (testdir, images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001212
1213 # check if directory is there
1214 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001215 self.assertEqual(8, len(result.output.split('\n')))
1216 self.assertTrue(os.path.basename(testdir) in result.output)
1217
Andrew Geissler82c905d2020-04-13 13:39:40 -05001218 # copy the file from the partition and check if it success
1219 dest = '%s-cp' % testfile.name
1220 runCmd("wic cp %s:1/%s %s -n %s" % (images[0],
1221 os.path.basename(testfile.name), dest, sysroot))
1222 self.assertTrue(os.path.exists(dest))
1223
1224
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001225 def test_wic_rm(self):
1226 """Test removing files and directories from the the wic image."""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001227 runCmd("wic create mkefidisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001228 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001229 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001230 images = glob(self.resultdir + "mkefidisk-*.direct")
1231 self.assertEqual(1, len(images))
1232
1233 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1234
1235 # list directory content of the first partition
1236 result = runCmd("wic ls %s:1 -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001237 self.assertIn('\nBZIMAGE ', result.output)
1238 self.assertIn('\nEFI <DIR> ', result.output)
1239
1240 # remove file
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001241 runCmd("wic rm %s:1/bzimage -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001242
1243 # remove directory
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001244 runCmd("wic rm %s:1/efi -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001245
1246 # check if they're removed
1247 result = runCmd("wic ls %s:1 -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001248 self.assertNotIn('\nBZIMAGE ', result.output)
1249 self.assertNotIn('\nEFI <DIR> ', result.output)
1250
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001251 def test_mkfs_extraopts(self):
1252 """Test wks option --mkfs-extraopts for empty and not empty partitions"""
1253 img = 'core-image-minimal'
1254 with NamedTemporaryFile("w", suffix=".wks") as wks:
1255 wks.writelines(
1256 ['part ext2 --fstype ext2 --source rootfs --mkfs-extraopts "-D -F -i 8192"\n',
1257 "part btrfs --fstype btrfs --source rootfs --size 40M --mkfs-extraopts='--quiet'\n",
1258 'part squash --fstype squashfs --source rootfs --mkfs-extraopts "-no-sparse -b 4096"\n',
1259 'part emptyvfat --fstype vfat --size 1M --mkfs-extraopts "-S 1024 -s 64"\n',
1260 'part emptymsdos --fstype msdos --size 1M --mkfs-extraopts "-S 1024 -s 64"\n',
1261 'part emptyext2 --fstype ext2 --size 1M --mkfs-extraopts "-D -F -i 8192"\n',
1262 'part emptybtrfs --fstype btrfs --size 100M --mkfs-extraopts "--mixed -K"\n'])
1263 wks.flush()
1264 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001265 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001266 wksname = os.path.splitext(os.path.basename(wks.name))[0]
1267 out = glob(self.resultdir + "%s-*direct" % wksname)
1268 self.assertEqual(1, len(out))
1269
1270 def test_expand_mbr_image(self):
1271 """Test wic write --expand command for mbr image"""
1272 # build an image
1273 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "directdisk.wks"\n'
1274 self.append_config(config)
1275 self.assertEqual(0, bitbake('core-image-minimal').status)
1276
1277 # get path to the image
1278 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'MACHINE'])
1279 deploy_dir = bb_vars['DEPLOY_DIR_IMAGE']
1280 machine = bb_vars['MACHINE']
1281 image_path = os.path.join(deploy_dir, 'core-image-minimal-%s.wic' % machine)
1282
1283 self.remove_config(config)
1284
1285 try:
1286 # expand image to 1G
1287 new_image_path = None
1288 with NamedTemporaryFile(mode='wb', suffix='.wic.exp',
1289 dir=deploy_dir, delete=False) as sparse:
1290 sparse.truncate(1024 ** 3)
1291 new_image_path = sparse.name
1292
1293 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1294 cmd = "wic write -n %s --expand 1:0 %s %s" % (sysroot, image_path, new_image_path)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001295 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001296
1297 # check if partitions are expanded
1298 orig = runCmd("wic ls %s -n %s" % (image_path, sysroot))
1299 exp = runCmd("wic ls %s -n %s" % (new_image_path, sysroot))
1300 orig_sizes = [int(line.split()[3]) for line in orig.output.split('\n')[1:]]
1301 exp_sizes = [int(line.split()[3]) for line in exp.output.split('\n')[1:]]
1302 self.assertEqual(orig_sizes[0], exp_sizes[0]) # first partition is not resized
1303 self.assertTrue(orig_sizes[1] < exp_sizes[1])
1304
1305 # Check if all free space is partitioned
1306 result = runCmd("%s/usr/sbin/sfdisk -F %s" % (sysroot, new_image_path))
1307 self.assertTrue("0 B, 0 bytes, 0 sectors" in result.output)
1308
Andrew Geisslerc926e172021-05-07 16:11:35 -05001309 bb.utils.rename(image_path, image_path + '.bak')
1310 bb.utils.rename(new_image_path, image_path)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001311
1312 # Check if it boots in qemu
1313 with runqemu('core-image-minimal', ssh=False) as qemu:
1314 cmd = "ls /etc/"
1315 status, output = qemu.run_serial('true')
1316 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1317 finally:
1318 if os.path.exists(new_image_path):
1319 os.unlink(new_image_path)
1320 if os.path.exists(image_path + '.bak'):
Andrew Geisslerc926e172021-05-07 16:11:35 -05001321 bb.utils.rename(image_path + '.bak', image_path)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001322
1323 def test_wic_ls_ext(self):
1324 """Test listing content of the ext partition using 'wic ls'"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001325 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001326 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001327 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001328 images = glob(self.resultdir + "wictestdisk-*.direct")
1329 self.assertEqual(1, len(images))
1330
1331 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1332
1333 # list directory content of the second ext4 partition
1334 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001335 self.assertTrue(set(['bin', 'home', 'proc', 'usr', 'var', 'dev', 'lib', 'sbin']).issubset(
1336 set(line.split()[-1] for line in result.output.split('\n') if line)))
1337
1338 def test_wic_cp_ext(self):
1339 """Test copy files and directories to the ext partition."""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001340 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001341 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001342 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001343 images = glob(self.resultdir + "wictestdisk-*.direct")
1344 self.assertEqual(1, len(images))
1345
1346 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1347
1348 # list directory content of the ext4 partition
1349 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001350 dirs = set(line.split()[-1] for line in result.output.split('\n') if line)
1351 self.assertTrue(set(['bin', 'home', 'proc', 'usr', 'var', 'dev', 'lib', 'sbin']).issubset(dirs))
1352
1353 with NamedTemporaryFile("w", suffix=".wic-cp") as testfile:
1354 testfile.write("test")
1355
1356 # copy file to the partition
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001357 runCmd("wic cp %s %s:2/ -n %s" % (testfile.name, images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001358
1359 # check if file is there
1360 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001361 newdirs = set(line.split()[-1] for line in result.output.split('\n') if line)
1362 self.assertEqual(newdirs.difference(dirs), set([os.path.basename(testfile.name)]))
1363
Andrew Geissler82c905d2020-04-13 13:39:40 -05001364 # check if the file to copy is in the partition
1365 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot))
1366 self.assertTrue('fstab' in [line.split()[-1] for line in result.output.split('\n') if line])
1367
1368 # copy file from the partition, replace the temporary file content with it and
1369 # check for the file size to validate the copy
1370 runCmd("wic cp %s:2/etc/fstab %s -n %s" % (images[0], testfile.name, sysroot))
1371 self.assertTrue(os.stat(testfile.name).st_size > 0)
1372
1373
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001374 def test_wic_rm_ext(self):
1375 """Test removing files from the ext partition."""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001376 runCmd("wic create mkefidisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001377 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001378 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001379 images = glob(self.resultdir + "mkefidisk-*.direct")
1380 self.assertEqual(1, len(images))
1381
1382 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1383
1384 # list directory content of the /etc directory on ext4 partition
1385 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001386 self.assertTrue('fstab' in [line.split()[-1] for line in result.output.split('\n') if line])
1387
1388 # remove file
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001389 runCmd("wic rm %s:2/etc/fstab -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001390
1391 # check if it's removed
1392 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001393 self.assertTrue('fstab' not in [line.split()[-1] for line in result.output.split('\n') if line])
Brad Bishop6dbb3162019-11-25 09:41:34 -05001394
1395 # remove non-empty directory
1396 runCmd("wic rm -r %s:2/etc/ -n %s" % (images[0], sysroot))
1397
1398 # check if it's removed
1399 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
1400 self.assertTrue('etc' not in [line.split()[-1] for line in result.output.split('\n') if line])