blob: 2bf5cb9a8610d2aca16edf734caeaf90825b5d81 [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"""
982 # build ext4 and wic images
983 for fstype in ("ext4", "wic"):
984 config = 'IMAGE_FSTYPES = "%s"\nWKS_FILE = "test_rawcopy_plugin.wks.in"\n' % fstype
985 self.append_config(config)
986 self.assertEqual(0, bitbake('core-image-minimal').status)
987 self.remove_config(config)
988
989 with runqemu('core-image-minimal', ssh=False, image_fstype='wic') as qemu:
990 cmd = "grep sda. /proc/partitions |wc -l"
991 status, output = qemu.run_serial(cmd)
992 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
993 self.assertEqual(output, '2')
994
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500995 def test_rawcopy_plugin(self):
996 """Test rawcopy plugin"""
997 img = 'core-image-minimal'
998 machine = get_bb_var('MACHINE', img)
999 with NamedTemporaryFile("w", suffix=".wks") as wks:
1000 wks.writelines(['part /boot --active --source bootimg-pcbios\n',
1001 'part / --source rawcopy --sourceparams="file=%s-%s.ext4" --use-uuid\n'\
1002 % (img, machine),
1003 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n'])
1004 wks.flush()
1005 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001006 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001007 wksname = os.path.splitext(os.path.basename(wks.name))[0]
1008 out = glob(self.resultdir + "%s-*direct" % wksname)
1009 self.assertEqual(1, len(out))
1010
Andrew Geisslerd1e89492021-02-12 15:35:20 -06001011 def test_empty_plugin(self):
1012 """Test empty plugin"""
1013 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_empty_plugin.wks"\n'
1014 self.append_config(config)
1015 self.assertEqual(0, bitbake('core-image-minimal').status)
1016 self.remove_config(config)
1017
1018 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'MACHINE'])
1019 deploy_dir = bb_vars['DEPLOY_DIR_IMAGE']
1020 machine = bb_vars['MACHINE']
1021 image_path = os.path.join(deploy_dir, 'core-image-minimal-%s.wic' % machine)
1022 self.assertEqual(True, os.path.exists(image_path))
1023
1024 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1025
1026 # Fstype column from 'wic ls' should be empty for the second partition
1027 # as listed in test_empty_plugin.wks
1028 result = runCmd("wic ls %s -n %s | awk -F ' ' '{print $1 \" \" $5}' | grep '^2' | wc -w" % (image_path, sysroot))
1029 self.assertEqual('1', result.output)
1030
Brad Bishop96ff1982019-08-19 13:50:42 -04001031 @only_for_arch(['i586', 'i686', 'x86_64'])
1032 def test_biosplusefi_plugin_qemu(self):
1033 """Test biosplusefi plugin in qemu"""
Brad Bishop08902b02019-08-20 09:16:51 -04001034 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES_append = " efi"\n'
1035 self.append_config(config)
1036 self.assertEqual(0, bitbake('core-image-minimal').status)
1037 self.remove_config(config)
Brad Bishop96ff1982019-08-19 13:50:42 -04001038
1039 with runqemu('core-image-minimal', ssh=False, image_fstype='wic') as qemu:
1040 # Check that we have ONLY two /dev/sda* partitions (/boot and /)
1041 cmd = "grep sda. /proc/partitions | wc -l"
1042 status, output = qemu.run_serial(cmd)
1043 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1044 self.assertEqual(output, '2')
1045 # Check that /dev/sda1 is /boot and that either /dev/root OR /dev/sda2 is /
1046 cmd = "mount | grep '^/dev/' | cut -f1,3 -d ' ' | egrep -c -e '/dev/sda1 /boot' -e '/dev/root /|/dev/sda2 /'"
1047 status, output = qemu.run_serial(cmd)
1048 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1049 self.assertEqual(output, '2')
1050 # Check that /boot has EFI bootx64.efi (required for EFI)
1051 cmd = "ls /boot/EFI/BOOT/bootx64.efi | wc -l"
1052 status, output = qemu.run_serial(cmd)
1053 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1054 self.assertEqual(output, '1')
1055 # Check that "BOOTABLE" flag is set on boot partition (required for PC-Bios)
1056 # Trailing "cat" seems to be required; otherwise run_serial() sends back echo of the input command
1057 cmd = "fdisk -l /dev/sda | grep /dev/sda1 | awk {print'$2'} | cat"
1058 status, output = qemu.run_serial(cmd)
1059 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1060 self.assertEqual(output, '*')
1061
1062 @only_for_arch(['i586', 'i686', 'x86_64'])
1063 def test_biosplusefi_plugin(self):
1064 """Test biosplusefi plugin"""
1065 # Wic generation below may fail depending on the order of the unittests
1066 # This is because bootimg-pcbios (that bootimg-biosplusefi uses) generate its MBR inside STAGING_DATADIR directory
1067 # which may or may not exists depending on what was built already
1068 # If an image hasn't been built yet, directory ${STAGING_DATADIR}/syslinux won't exists and _get_bootimg_dir()
1069 # will raise with "Couldn't find correct bootimg_dir"
1070 # 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 -04001071 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES_append = " efi"\n'
1072 self.append_config(config)
1073 self.assertEqual(0, bitbake('core-image-minimal').status)
1074 self.remove_config(config)
Brad Bishop96ff1982019-08-19 13:50:42 -04001075
1076 img = 'core-image-minimal'
1077 with NamedTemporaryFile("w", suffix=".wks") as wks:
1078 wks.writelines(['part /boot --active --source bootimg-biosplusefi --sourceparams="loader=grub-efi"\n',
1079 'part / --source rootfs --fstype=ext4 --align 1024 --use-uuid\n'\
1080 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n'])
1081 wks.flush()
1082 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
1083 runCmd(cmd)
1084 wksname = os.path.splitext(os.path.basename(wks.name))[0]
1085 out = glob(self.resultdir + "%s-*.direct" % wksname)
1086 self.assertEqual(1, len(out))
1087
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001088 def test_fs_types(self):
1089 """Test filesystem types for empty and not empty partitions"""
1090 img = 'core-image-minimal'
1091 with NamedTemporaryFile("w", suffix=".wks") as wks:
1092 wks.writelines(['part ext2 --fstype ext2 --source rootfs\n',
1093 'part btrfs --fstype btrfs --source rootfs --size 40M\n',
1094 'part squash --fstype squashfs --source rootfs\n',
1095 'part swap --fstype swap --size 1M\n',
1096 'part emptyvfat --fstype vfat --size 1M\n',
1097 'part emptymsdos --fstype msdos --size 1M\n',
1098 'part emptyext2 --fstype ext2 --size 1M\n',
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001099 'part emptybtrfs --fstype btrfs --size 150M\n'])
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001100 wks.flush()
1101 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001102 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001103 wksname = os.path.splitext(os.path.basename(wks.name))[0]
1104 out = glob(self.resultdir + "%s-*direct" % wksname)
1105 self.assertEqual(1, len(out))
1106
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001107 def test_kickstart_parser(self):
1108 """Test wks parser options"""
1109 with NamedTemporaryFile("w", suffix=".wks") as wks:
1110 wks.writelines(['part / --fstype ext3 --source rootfs --system-id 0xFF '\
1111 '--overhead-factor 1.2 --size 100k\n'])
1112 wks.flush()
1113 cmd = "wic create %s -e core-image-minimal -o %s" % (wks.name, self.resultdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001114 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001115 wksname = os.path.splitext(os.path.basename(wks.name))[0]
1116 out = glob(self.resultdir + "%s-*direct" % wksname)
1117 self.assertEqual(1, len(out))
1118
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001119 def test_image_bootpart_globbed(self):
1120 """Test globbed sources with image-bootpart plugin"""
1121 img = "core-image-minimal"
1122 cmd = "wic create sdimage-bootpart -e %s -o %s" % (img, self.resultdir)
1123 config = 'IMAGE_BOOT_FILES = "%s*"' % get_bb_var('KERNEL_IMAGETYPE', img)
1124 self.append_config(config)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001125 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001126 self.remove_config(config)
1127 self.assertEqual(1, len(glob(self.resultdir + "sdimage-bootpart-*direct")))
1128
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001129 def test_sparse_copy(self):
1130 """Test sparse_copy with FIEMAP and SEEK_HOLE filemap APIs"""
1131 libpath = os.path.join(get_bb_var('COREBASE'), 'scripts', 'lib', 'wic')
1132 sys.path.insert(0, libpath)
1133 from filemap import FilemapFiemap, FilemapSeek, sparse_copy, ErrorNotSupp
1134 with NamedTemporaryFile("w", suffix=".wic-sparse") as sparse:
1135 src_name = sparse.name
1136 src_size = 1024 * 10
1137 sparse.truncate(src_size)
1138 # write one byte to the file
1139 with open(src_name, 'r+b') as sfile:
1140 sfile.seek(1024 * 4)
1141 sfile.write(b'\x00')
1142 dest = sparse.name + '.out'
1143 # copy src file to dest using different filemap APIs
1144 for api in (FilemapFiemap, FilemapSeek, None):
1145 if os.path.exists(dest):
1146 os.unlink(dest)
1147 try:
1148 sparse_copy(sparse.name, dest, api=api)
1149 except ErrorNotSupp:
1150 continue # skip unsupported API
1151 dest_stat = os.stat(dest)
1152 self.assertEqual(dest_stat.st_size, src_size)
1153 # 8 blocks is 4K (physical sector size)
1154 self.assertEqual(dest_stat.st_blocks, 8)
1155 os.unlink(dest)
1156
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001157 def test_wic_ls(self):
1158 """Test listing image content using 'wic ls'"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001159 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001160 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001161 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001162 images = glob(self.resultdir + "wictestdisk-*.direct")
1163 self.assertEqual(1, len(images))
1164
1165 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1166
1167 # list partitions
1168 result = runCmd("wic ls %s -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001169 self.assertEqual(3, len(result.output.split('\n')))
1170
1171 # list directory content of the first partition
1172 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001173 self.assertEqual(6, len(result.output.split('\n')))
1174
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001175 def test_wic_cp(self):
1176 """Test copy files and directories to the the wic image."""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001177 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001178 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001179 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001180 images = glob(self.resultdir + "wictestdisk-*.direct")
1181 self.assertEqual(1, len(images))
1182
1183 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1184
1185 # list directory content of the first partition
1186 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001187 self.assertEqual(6, len(result.output.split('\n')))
1188
1189 with NamedTemporaryFile("w", suffix=".wic-cp") as testfile:
1190 testfile.write("test")
1191
1192 # copy file to the partition
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001193 runCmd("wic cp %s %s:1/ -n %s" % (testfile.name, images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001194
1195 # check if file is there
1196 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001197 self.assertEqual(7, len(result.output.split('\n')))
1198 self.assertTrue(os.path.basename(testfile.name) in result.output)
1199
1200 # prepare directory
1201 testdir = os.path.join(self.resultdir, 'wic-test-cp-dir')
1202 testsubdir = os.path.join(testdir, 'subdir')
1203 os.makedirs(os.path.join(testsubdir))
1204 copy(testfile.name, testdir)
1205
1206 # copy directory to the partition
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001207 runCmd("wic cp %s %s:1/ -n %s" % (testdir, images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001208
1209 # check if directory is there
1210 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001211 self.assertEqual(8, len(result.output.split('\n')))
1212 self.assertTrue(os.path.basename(testdir) in result.output)
1213
Andrew Geissler82c905d2020-04-13 13:39:40 -05001214 # copy the file from the partition and check if it success
1215 dest = '%s-cp' % testfile.name
1216 runCmd("wic cp %s:1/%s %s -n %s" % (images[0],
1217 os.path.basename(testfile.name), dest, sysroot))
1218 self.assertTrue(os.path.exists(dest))
1219
1220
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001221 def test_wic_rm(self):
1222 """Test removing files and directories from the the wic image."""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001223 runCmd("wic create mkefidisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001224 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001225 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001226 images = glob(self.resultdir + "mkefidisk-*.direct")
1227 self.assertEqual(1, len(images))
1228
1229 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1230
1231 # list directory content of the first partition
1232 result = runCmd("wic ls %s:1 -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001233 self.assertIn('\nBZIMAGE ', result.output)
1234 self.assertIn('\nEFI <DIR> ', result.output)
1235
1236 # remove file
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001237 runCmd("wic rm %s:1/bzimage -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001238
1239 # remove directory
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001240 runCmd("wic rm %s:1/efi -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001241
1242 # check if they're removed
1243 result = runCmd("wic ls %s:1 -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001244 self.assertNotIn('\nBZIMAGE ', result.output)
1245 self.assertNotIn('\nEFI <DIR> ', result.output)
1246
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001247 def test_mkfs_extraopts(self):
1248 """Test wks option --mkfs-extraopts for empty and not empty partitions"""
1249 img = 'core-image-minimal'
1250 with NamedTemporaryFile("w", suffix=".wks") as wks:
1251 wks.writelines(
1252 ['part ext2 --fstype ext2 --source rootfs --mkfs-extraopts "-D -F -i 8192"\n',
1253 "part btrfs --fstype btrfs --source rootfs --size 40M --mkfs-extraopts='--quiet'\n",
1254 'part squash --fstype squashfs --source rootfs --mkfs-extraopts "-no-sparse -b 4096"\n',
1255 'part emptyvfat --fstype vfat --size 1M --mkfs-extraopts "-S 1024 -s 64"\n',
1256 'part emptymsdos --fstype msdos --size 1M --mkfs-extraopts "-S 1024 -s 64"\n',
1257 'part emptyext2 --fstype ext2 --size 1M --mkfs-extraopts "-D -F -i 8192"\n',
1258 'part emptybtrfs --fstype btrfs --size 100M --mkfs-extraopts "--mixed -K"\n'])
1259 wks.flush()
1260 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001261 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001262 wksname = os.path.splitext(os.path.basename(wks.name))[0]
1263 out = glob(self.resultdir + "%s-*direct" % wksname)
1264 self.assertEqual(1, len(out))
1265
1266 def test_expand_mbr_image(self):
1267 """Test wic write --expand command for mbr image"""
1268 # build an image
1269 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "directdisk.wks"\n'
1270 self.append_config(config)
1271 self.assertEqual(0, bitbake('core-image-minimal').status)
1272
1273 # get path to the image
1274 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'MACHINE'])
1275 deploy_dir = bb_vars['DEPLOY_DIR_IMAGE']
1276 machine = bb_vars['MACHINE']
1277 image_path = os.path.join(deploy_dir, 'core-image-minimal-%s.wic' % machine)
1278
1279 self.remove_config(config)
1280
1281 try:
1282 # expand image to 1G
1283 new_image_path = None
1284 with NamedTemporaryFile(mode='wb', suffix='.wic.exp',
1285 dir=deploy_dir, delete=False) as sparse:
1286 sparse.truncate(1024 ** 3)
1287 new_image_path = sparse.name
1288
1289 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1290 cmd = "wic write -n %s --expand 1:0 %s %s" % (sysroot, image_path, new_image_path)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001291 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001292
1293 # check if partitions are expanded
1294 orig = runCmd("wic ls %s -n %s" % (image_path, sysroot))
1295 exp = runCmd("wic ls %s -n %s" % (new_image_path, sysroot))
1296 orig_sizes = [int(line.split()[3]) for line in orig.output.split('\n')[1:]]
1297 exp_sizes = [int(line.split()[3]) for line in exp.output.split('\n')[1:]]
1298 self.assertEqual(orig_sizes[0], exp_sizes[0]) # first partition is not resized
1299 self.assertTrue(orig_sizes[1] < exp_sizes[1])
1300
1301 # Check if all free space is partitioned
1302 result = runCmd("%s/usr/sbin/sfdisk -F %s" % (sysroot, new_image_path))
1303 self.assertTrue("0 B, 0 bytes, 0 sectors" in result.output)
1304
1305 os.rename(image_path, image_path + '.bak')
1306 os.rename(new_image_path, image_path)
1307
1308 # Check if it boots in qemu
1309 with runqemu('core-image-minimal', ssh=False) as qemu:
1310 cmd = "ls /etc/"
1311 status, output = qemu.run_serial('true')
1312 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1313 finally:
1314 if os.path.exists(new_image_path):
1315 os.unlink(new_image_path)
1316 if os.path.exists(image_path + '.bak'):
1317 os.rename(image_path + '.bak', image_path)
1318
1319 def test_wic_ls_ext(self):
1320 """Test listing content of the ext partition using 'wic ls'"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001321 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001322 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001323 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001324 images = glob(self.resultdir + "wictestdisk-*.direct")
1325 self.assertEqual(1, len(images))
1326
1327 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1328
1329 # list directory content of the second ext4 partition
1330 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001331 self.assertTrue(set(['bin', 'home', 'proc', 'usr', 'var', 'dev', 'lib', 'sbin']).issubset(
1332 set(line.split()[-1] for line in result.output.split('\n') if line)))
1333
1334 def test_wic_cp_ext(self):
1335 """Test copy files and directories to the ext partition."""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001336 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001337 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001338 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001339 images = glob(self.resultdir + "wictestdisk-*.direct")
1340 self.assertEqual(1, len(images))
1341
1342 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1343
1344 # list directory content of the ext4 partition
1345 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001346 dirs = set(line.split()[-1] for line in result.output.split('\n') if line)
1347 self.assertTrue(set(['bin', 'home', 'proc', 'usr', 'var', 'dev', 'lib', 'sbin']).issubset(dirs))
1348
1349 with NamedTemporaryFile("w", suffix=".wic-cp") as testfile:
1350 testfile.write("test")
1351
1352 # copy file to the partition
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001353 runCmd("wic cp %s %s:2/ -n %s" % (testfile.name, images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001354
1355 # check if file is there
1356 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001357 newdirs = set(line.split()[-1] for line in result.output.split('\n') if line)
1358 self.assertEqual(newdirs.difference(dirs), set([os.path.basename(testfile.name)]))
1359
Andrew Geissler82c905d2020-04-13 13:39:40 -05001360 # check if the file to copy is in the partition
1361 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot))
1362 self.assertTrue('fstab' in [line.split()[-1] for line in result.output.split('\n') if line])
1363
1364 # copy file from the partition, replace the temporary file content with it and
1365 # check for the file size to validate the copy
1366 runCmd("wic cp %s:2/etc/fstab %s -n %s" % (images[0], testfile.name, sysroot))
1367 self.assertTrue(os.stat(testfile.name).st_size > 0)
1368
1369
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001370 def test_wic_rm_ext(self):
1371 """Test removing files from the ext partition."""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001372 runCmd("wic create mkefidisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001373 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001374 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001375 images = glob(self.resultdir + "mkefidisk-*.direct")
1376 self.assertEqual(1, len(images))
1377
1378 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1379
1380 # list directory content of the /etc directory on ext4 partition
1381 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001382 self.assertTrue('fstab' in [line.split()[-1] for line in result.output.split('\n') if line])
1383
1384 # remove file
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001385 runCmd("wic rm %s:2/etc/fstab -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001386
1387 # check if it's removed
1388 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001389 self.assertTrue('fstab' not in [line.split()[-1] for line in result.output.split('\n') if line])
Brad Bishop6dbb3162019-11-25 09:41:34 -05001390
1391 # remove non-empty directory
1392 runCmd("wic rm -r %s:2/etc/ -n %s" % (images[0], sysroot))
1393
1394 # check if it's removed
1395 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
1396 self.assertTrue('etc' not in [line.split()[-1] for line in result.output.split('\n') if line])