1# 2# Copyright (c) 2015, Intel Corporation. 3# 4# SPDX-License-Identifier: GPL-2.0-only 5# 6# AUTHORS 7# Ed Bartosh <ed.bartosh@linux.intel.com> 8 9"""Test cases for wic.""" 10 11import os 12import sys 13import unittest 14import hashlib 15 16from glob import glob 17from shutil import rmtree, copy 18from tempfile import NamedTemporaryFile 19 20from oeqa.selftest.case import OESelftestTestCase 21from oeqa.core.decorator import OETestTag 22from oeqa.core.decorator.data import skipIfNotArch 23from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, runqemu 24 25 26def extract_files(debugfs_output): 27 """ 28 extract file names from the output of debugfs -R 'ls -p', 29 which looks like this: 30 31 /2/040755/0/0/.//\n 32 /2/040755/0/0/..//\n 33 /11/040700/0/0/lost+found^M//\n 34 /12/040755/1002/1002/run//\n 35 /13/040755/1002/1002/sys//\n 36 /14/040755/1002/1002/bin//\n 37 /80/040755/1002/1002/var//\n 38 /92/040755/1002/1002/tmp//\n 39 """ 40 # NOTE the occasional ^M in file names 41 return [line.split('/')[5].strip() for line in \ 42 debugfs_output.strip().split('/\n')] 43 44def files_own_by_root(debugfs_output): 45 for line in debugfs_output.strip().split('/\n'): 46 if line.split('/')[3:5] != ['0', '0']: 47 print(debugfs_output) 48 return False 49 return True 50 51class WicTestCase(OESelftestTestCase): 52 """Wic test class.""" 53 54 image_is_ready = False 55 wicenv_cache = {} 56 57 def setUpLocal(self): 58 """This code is executed before each test method.""" 59 self.resultdir = os.path.join(self.builddir, "wic-tmp") 60 super(WicTestCase, self).setUpLocal() 61 62 # Do this here instead of in setUpClass as the base setUp does some 63 # clean up which can result in the native tools built earlier in 64 # setUpClass being unavailable. 65 if not WicTestCase.image_is_ready: 66 if self.td['USE_NLS'] != 'yes': 67 self.skipTest('wic-tools needs USE_NLS=yes') 68 69 bitbake('wic-tools core-image-minimal core-image-minimal-mtdutils') 70 WicTestCase.image_is_ready = True 71 rmtree(self.resultdir, ignore_errors=True) 72 73 def tearDownLocal(self): 74 """Remove resultdir as it may contain images.""" 75 rmtree(self.resultdir, ignore_errors=True) 76 super(WicTestCase, self).tearDownLocal() 77 78 def _get_image_env_path(self, image): 79 """Generate and obtain the path to <image>.env""" 80 if image not in WicTestCase.wicenv_cache: 81 bitbake('%s -c do_rootfs_wicenv' % image) 82 stdir = get_bb_var('STAGING_DIR', image) 83 machine = self.td["MACHINE"] 84 WicTestCase.wicenv_cache[image] = os.path.join(stdir, machine, 'imgdata') 85 return WicTestCase.wicenv_cache[image] 86 87class CLITests(OESelftestTestCase): 88 def test_version(self): 89 """Test wic --version""" 90 runCmd('wic --version') 91 92 def test_help(self): 93 """Test wic --help and wic -h""" 94 runCmd('wic --help') 95 runCmd('wic -h') 96 97 def test_createhelp(self): 98 """Test wic create --help""" 99 runCmd('wic create --help') 100 101 def test_listhelp(self): 102 """Test wic list --help""" 103 runCmd('wic list --help') 104 105 def test_help_create(self): 106 """Test wic help create""" 107 runCmd('wic help create') 108 109 def test_help_list(self): 110 """Test wic help list""" 111 runCmd('wic help list') 112 113 def test_help_overview(self): 114 """Test wic help overview""" 115 runCmd('wic help overview') 116 117 def test_help_plugins(self): 118 """Test wic help plugins""" 119 runCmd('wic help plugins') 120 121 def test_help_kickstart(self): 122 """Test wic help kickstart""" 123 runCmd('wic help kickstart') 124 125 def test_list_images(self): 126 """Test wic list images""" 127 runCmd('wic list images') 128 129 def test_list_source_plugins(self): 130 """Test wic list source-plugins""" 131 runCmd('wic list source-plugins') 132 133 def test_listed_images_help(self): 134 """Test wic listed images help""" 135 output = runCmd('wic list images').output 136 imagelist = [line.split()[0] for line in output.splitlines()] 137 for image in imagelist: 138 runCmd('wic list %s help' % image) 139 140 def test_unsupported_subcommand(self): 141 """Test unsupported subcommand""" 142 self.assertNotEqual(0, runCmd('wic unsupported', ignore_status=True).status) 143 144 def test_no_command(self): 145 """Test wic without command""" 146 self.assertEqual(1, runCmd('wic', ignore_status=True).status) 147 148class Wic(WicTestCase): 149 def test_build_image_name(self): 150 """Test wic create wictestdisk --image-name=core-image-minimal""" 151 cmd = "wic create wictestdisk --image-name=core-image-minimal -o %s" % self.resultdir 152 runCmd(cmd) 153 self.assertEqual(1, len(glob(os.path.join (self.resultdir, "wictestdisk-*.direct")))) 154 155 @skipIfNotArch(['i586', 'i686', 'x86_64']) 156 def test_gpt_image(self): 157 """Test creation of core-image-minimal with gpt table and UUID boot""" 158 cmd = "wic create directdisk-gpt --image-name core-image-minimal -o %s" % self.resultdir 159 runCmd(cmd) 160 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "directdisk-*.direct")))) 161 162 @skipIfNotArch(['i586', 'i686', 'x86_64']) 163 def test_iso_image(self): 164 """Test creation of hybrid iso image with legacy and EFI boot""" 165 config = 'INITRAMFS_IMAGE = "core-image-minimal-initramfs"\n'\ 166 'MACHINE_FEATURES:append = " efi"\n'\ 167 'DEPENDS:pn-core-image-minimal += "syslinux"\n' 168 self.append_config(config) 169 bitbake('core-image-minimal core-image-minimal-initramfs') 170 self.remove_config(config) 171 cmd = "wic create mkhybridiso --image-name core-image-minimal -o %s" % self.resultdir 172 runCmd(cmd) 173 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "HYBRID_ISO_IMG-*.direct")))) 174 self.assertEqual(1, len(glob(os.path.join (self.resultdir, "HYBRID_ISO_IMG-*.iso")))) 175 176 @skipIfNotArch(['i586', 'i686', 'x86_64']) 177 def test_qemux86_directdisk(self): 178 """Test creation of qemux-86-directdisk image""" 179 cmd = "wic create qemux86-directdisk -e core-image-minimal -o %s" % self.resultdir 180 runCmd(cmd) 181 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "qemux86-directdisk-*direct")))) 182 183 @skipIfNotArch(['i586', 'i686', 'x86_64', 'aarch64']) 184 def test_mkefidisk(self): 185 """Test creation of mkefidisk image""" 186 cmd = "wic create mkefidisk -e core-image-minimal -o %s" % self.resultdir 187 runCmd(cmd) 188 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "mkefidisk-*direct")))) 189 190 @skipIfNotArch(['i586', 'i686', 'x86_64']) 191 def test_bootloader_config(self): 192 """Test creation of directdisk-bootloader-config image""" 193 config = 'DEPENDS:pn-core-image-minimal += "syslinux"\n' 194 self.append_config(config) 195 bitbake('core-image-minimal') 196 self.remove_config(config) 197 cmd = "wic create directdisk-bootloader-config -e core-image-minimal -o %s" % self.resultdir 198 runCmd(cmd) 199 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "directdisk-bootloader-config-*direct")))) 200 201 @skipIfNotArch(['i586', 'i686', 'x86_64', 'aarch64']) 202 def test_systemd_bootdisk(self): 203 """Test creation of systemd-bootdisk image""" 204 config = 'MACHINE_FEATURES:append = " efi"\n' 205 self.append_config(config) 206 bitbake('core-image-minimal') 207 self.remove_config(config) 208 cmd = "wic create systemd-bootdisk -e core-image-minimal -o %s" % self.resultdir 209 runCmd(cmd) 210 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "systemd-bootdisk-*direct")))) 211 212 def test_efi_bootpart(self): 213 """Test creation of efi-bootpart image""" 214 cmd = "wic create mkefidisk -e core-image-minimal -o %s" % self.resultdir 215 kimgtype = get_bb_var('KERNEL_IMAGETYPE', 'core-image-minimal') 216 self.append_config('IMAGE_EFI_BOOT_FILES = "%s;kernel"\n' % kimgtype) 217 runCmd(cmd) 218 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 219 images = glob(os.path.join(self.resultdir, "mkefidisk-*.direct")) 220 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot)) 221 self.assertIn("kernel",result.output) 222 223 def test_sdimage_bootpart(self): 224 """Test creation of sdimage-bootpart image""" 225 cmd = "wic create sdimage-bootpart -e core-image-minimal -o %s" % self.resultdir 226 kimgtype = get_bb_var('KERNEL_IMAGETYPE', 'core-image-minimal') 227 self.write_config('IMAGE_BOOT_FILES = "%s"\n' % kimgtype) 228 runCmd(cmd) 229 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "sdimage-bootpart-*direct")))) 230 231 # TODO this doesn't have to be x86-specific 232 @skipIfNotArch(['i586', 'i686', 'x86_64']) 233 def test_default_output_dir(self): 234 """Test default output location""" 235 for fname in glob("directdisk-*.direct"): 236 os.remove(fname) 237 config = 'DEPENDS:pn-core-image-minimal += "syslinux"\n' 238 self.append_config(config) 239 bitbake('core-image-minimal') 240 self.remove_config(config) 241 cmd = "wic create directdisk -e core-image-minimal" 242 runCmd(cmd) 243 self.assertEqual(1, len(glob("directdisk-*.direct"))) 244 245 @skipIfNotArch(['i586', 'i686', 'x86_64']) 246 def test_build_artifacts(self): 247 """Test wic create directdisk providing all artifacts.""" 248 bb_vars = get_bb_vars(['STAGING_DATADIR', 'RECIPE_SYSROOT_NATIVE'], 249 'wic-tools') 250 bb_vars.update(get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_ROOTFS'], 251 'core-image-minimal')) 252 bbvars = {key.lower(): value for key, value in bb_vars.items()} 253 bbvars['resultdir'] = self.resultdir 254 runCmd("wic create directdisk " 255 "-b %(staging_datadir)s " 256 "-k %(deploy_dir_image)s " 257 "-n %(recipe_sysroot_native)s " 258 "-r %(image_rootfs)s " 259 "-o %(resultdir)s" % bbvars) 260 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "directdisk-*.direct")))) 261 262 def test_compress_gzip(self): 263 """Test compressing an image with gzip""" 264 runCmd("wic create wictestdisk " 265 "--image-name core-image-minimal " 266 "-c gzip -o %s" % self.resultdir) 267 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct.gz")))) 268 269 def test_compress_bzip2(self): 270 """Test compressing an image with bzip2""" 271 runCmd("wic create wictestdisk " 272 "--image-name=core-image-minimal " 273 "-c bzip2 -o %s" % self.resultdir) 274 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct.bz2")))) 275 276 def test_compress_xz(self): 277 """Test compressing an image with xz""" 278 runCmd("wic create wictestdisk " 279 "--image-name=core-image-minimal " 280 "--compress-with=xz -o %s" % self.resultdir) 281 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct.xz")))) 282 283 def test_wrong_compressor(self): 284 """Test how wic breaks if wrong compressor is provided""" 285 self.assertEqual(2, runCmd("wic create wictestdisk " 286 "--image-name=core-image-minimal " 287 "-c wrong -o %s" % self.resultdir, 288 ignore_status=True).status) 289 290 def test_debug_short(self): 291 """Test -D option""" 292 runCmd("wic create wictestdisk " 293 "--image-name=core-image-minimal " 294 "-D -o %s" % self.resultdir) 295 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct")))) 296 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "tmp.wic*")))) 297 298 def test_debug_long(self): 299 """Test --debug option""" 300 runCmd("wic create wictestdisk " 301 "--image-name=core-image-minimal " 302 "--debug -o %s" % self.resultdir) 303 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct")))) 304 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "tmp.wic*")))) 305 306 def test_skip_build_check_short(self): 307 """Test -s option""" 308 runCmd("wic create wictestdisk " 309 "--image-name=core-image-minimal " 310 "-s -o %s" % self.resultdir) 311 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct")))) 312 313 def test_skip_build_check_long(self): 314 """Test --skip-build-check option""" 315 runCmd("wic create wictestdisk " 316 "--image-name=core-image-minimal " 317 "--skip-build-check " 318 "--outdir %s" % self.resultdir) 319 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct")))) 320 321 def test_build_rootfs_short(self): 322 """Test -f option""" 323 runCmd("wic create wictestdisk " 324 "--image-name=core-image-minimal " 325 "-f -o %s" % self.resultdir) 326 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct")))) 327 328 def test_build_rootfs_long(self): 329 """Test --build-rootfs option""" 330 runCmd("wic create wictestdisk " 331 "--image-name=core-image-minimal " 332 "--build-rootfs " 333 "--outdir %s" % self.resultdir) 334 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*.direct")))) 335 336 # TODO this doesn't have to be x86-specific 337 @skipIfNotArch(['i586', 'i686', 'x86_64']) 338 def test_rootfs_indirect_recipes(self): 339 """Test usage of rootfs plugin with rootfs recipes""" 340 runCmd("wic create directdisk-multi-rootfs " 341 "--image-name=core-image-minimal " 342 "--rootfs rootfs1=core-image-minimal " 343 "--rootfs rootfs2=core-image-minimal " 344 "--outdir %s" % self.resultdir) 345 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "directdisk-multi-rootfs*.direct")))) 346 347 # TODO this doesn't have to be x86-specific 348 @skipIfNotArch(['i586', 'i686', 'x86_64']) 349 def test_rootfs_artifacts(self): 350 """Test usage of rootfs plugin with rootfs paths""" 351 bb_vars = get_bb_vars(['STAGING_DATADIR', 'RECIPE_SYSROOT_NATIVE'], 352 'wic-tools') 353 bb_vars.update(get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_ROOTFS'], 354 'core-image-minimal')) 355 bbvars = {key.lower(): value for key, value in bb_vars.items()} 356 bbvars['wks'] = "directdisk-multi-rootfs" 357 bbvars['resultdir'] = self.resultdir 358 runCmd("wic create %(wks)s " 359 "--bootimg-dir=%(staging_datadir)s " 360 "--kernel-dir=%(deploy_dir_image)s " 361 "--native-sysroot=%(recipe_sysroot_native)s " 362 "--rootfs-dir rootfs1=%(image_rootfs)s " 363 "--rootfs-dir rootfs2=%(image_rootfs)s " 364 "--outdir %(resultdir)s" % bbvars) 365 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "%(wks)s-*.direct" % bbvars)))) 366 367 def test_exclude_path(self): 368 """Test --exclude-path wks option.""" 369 370 oldpath = os.environ['PATH'] 371 os.environ['PATH'] = get_bb_var("PATH", "wic-tools") 372 373 try: 374 wks_file = 'temp.wks' 375 with open(wks_file, 'w') as wks: 376 rootfs_dir = get_bb_var('IMAGE_ROOTFS', 'core-image-minimal') 377 wks.write(""" 378part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path usr 379part /usr --source rootfs --ondisk mmcblk0 --fstype=ext4 --rootfs-dir %s/usr 380part /etc --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path bin/ --rootfs-dir %s/usr""" 381 % (rootfs_dir, rootfs_dir)) 382 runCmd("wic create %s -e core-image-minimal -o %s" \ 383 % (wks_file, self.resultdir)) 384 385 os.remove(wks_file) 386 wicout = glob(os.path.join(self.resultdir, "%s-*direct" % 'temp')) 387 self.assertEqual(1, len(wicout)) 388 389 wicimg = wicout[0] 390 391 # verify partition size with wic 392 res = runCmd("parted -m %s unit b p 2>/dev/null" % wicimg) 393 394 # parse parted output which looks like this: 395 # BYT;\n 396 # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n 397 # 1:0.00MiB:200MiB:200MiB:ext4::;\n 398 partlns = res.output.splitlines()[2:] 399 400 self.assertEqual(3, len(partlns)) 401 402 for part in [1, 2, 3]: 403 part_file = os.path.join(self.resultdir, "selftest_img.part%d" % part) 404 partln = partlns[part-1].split(":") 405 self.assertEqual(7, len(partln)) 406 start = int(partln[1].rstrip("B")) / 512 407 length = int(partln[3].rstrip("B")) / 512 408 runCmd("dd if=%s of=%s skip=%d count=%d" % 409 (wicimg, part_file, start, length)) 410 411 # Test partition 1, should contain the normal root directories, except 412 # /usr. 413 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \ 414 os.path.join(self.resultdir, "selftest_img.part1")) 415 files = extract_files(res.output) 416 self.assertIn("etc", files) 417 self.assertNotIn("usr", files) 418 419 # Partition 2, should contain common directories for /usr, not root 420 # directories. 421 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \ 422 os.path.join(self.resultdir, "selftest_img.part2")) 423 files = extract_files(res.output) 424 self.assertNotIn("etc", files) 425 self.assertNotIn("usr", files) 426 self.assertIn("share", files) 427 428 # Partition 3, should contain the same as partition 2, including the bin 429 # directory, but not the files inside it. 430 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \ 431 os.path.join(self.resultdir, "selftest_img.part3")) 432 files = extract_files(res.output) 433 self.assertNotIn("etc", files) 434 self.assertNotIn("usr", files) 435 self.assertIn("share", files) 436 self.assertIn("bin", files) 437 res = runCmd("debugfs -R 'ls -p bin' %s 2>/dev/null" % \ 438 os.path.join(self.resultdir, "selftest_img.part3")) 439 files = extract_files(res.output) 440 self.assertIn(".", files) 441 self.assertIn("..", files) 442 self.assertEqual(2, len(files)) 443 444 for part in [1, 2, 3]: 445 part_file = os.path.join(self.resultdir, "selftest_img.part%d" % part) 446 os.remove(part_file) 447 448 finally: 449 os.environ['PATH'] = oldpath 450 451 def test_include_path(self): 452 """Test --include-path wks option.""" 453 454 oldpath = os.environ['PATH'] 455 os.environ['PATH'] = get_bb_var("PATH", "wic-tools") 456 457 try: 458 include_path = os.path.join(self.resultdir, 'test-include') 459 os.makedirs(include_path) 460 with open(os.path.join(include_path, 'test-file'), 'w') as t: 461 t.write("test\n") 462 wks_file = os.path.join(include_path, 'temp.wks') 463 with open(wks_file, 'w') as wks: 464 rootfs_dir = get_bb_var('IMAGE_ROOTFS', 'core-image-minimal') 465 wks.write(""" 466part /part1 --source rootfs --ondisk mmcblk0 --fstype=ext4 467part /part2 --source rootfs --ondisk mmcblk0 --fstype=ext4 --include-path %s""" 468 % (include_path)) 469 runCmd("wic create %s -e core-image-minimal -o %s" \ 470 % (wks_file, self.resultdir)) 471 472 part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0] 473 part2 = glob(os.path.join(self.resultdir, 'temp-*.direct.p2'))[0] 474 475 # Test partition 1, should not contain 'test-file' 476 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1)) 477 files = extract_files(res.output) 478 self.assertNotIn('test-file', files) 479 self.assertEqual(True, files_own_by_root(res.output)) 480 481 # Test partition 2, should contain 'test-file' 482 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part2)) 483 files = extract_files(res.output) 484 self.assertIn('test-file', files) 485 self.assertEqual(True, files_own_by_root(res.output)) 486 487 finally: 488 os.environ['PATH'] = oldpath 489 490 def test_include_path_embeded(self): 491 """Test --include-path wks option.""" 492 493 oldpath = os.environ['PATH'] 494 os.environ['PATH'] = get_bb_var("PATH", "wic-tools") 495 496 try: 497 include_path = os.path.join(self.resultdir, 'test-include') 498 os.makedirs(include_path) 499 with open(os.path.join(include_path, 'test-file'), 'w') as t: 500 t.write("test\n") 501 wks_file = os.path.join(include_path, 'temp.wks') 502 with open(wks_file, 'w') as wks: 503 wks.write(""" 504part / --source rootfs --fstype=ext4 --include-path %s --include-path core-image-minimal-mtdutils export/""" 505 % (include_path)) 506 runCmd("wic create %s -e core-image-minimal -o %s" \ 507 % (wks_file, self.resultdir)) 508 509 part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0] 510 511 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1)) 512 files = extract_files(res.output) 513 self.assertIn('test-file', files) 514 self.assertEqual(True, files_own_by_root(res.output)) 515 516 res = runCmd("debugfs -R 'ls -p /export/etc/' %s 2>/dev/null" % (part1)) 517 files = extract_files(res.output) 518 self.assertIn('passwd', files) 519 self.assertEqual(True, files_own_by_root(res.output)) 520 521 finally: 522 os.environ['PATH'] = oldpath 523 524 def test_include_path_errors(self): 525 """Test --include-path wks option error handling.""" 526 wks_file = 'temp.wks' 527 528 # Absolute argument. 529 with open(wks_file, 'w') as wks: 530 wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils /export") 531 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ 532 % (wks_file, self.resultdir), ignore_status=True).status) 533 os.remove(wks_file) 534 535 # Argument pointing to parent directory. 536 with open(wks_file, 'w') as wks: 537 wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils ././..") 538 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ 539 % (wks_file, self.resultdir), ignore_status=True).status) 540 os.remove(wks_file) 541 542 # 3 Argument pointing to parent directory. 543 with open(wks_file, 'w') as wks: 544 wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils export/ dummy") 545 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ 546 % (wks_file, self.resultdir), ignore_status=True).status) 547 os.remove(wks_file) 548 549 def test_exclude_path_errors(self): 550 """Test --exclude-path wks option error handling.""" 551 wks_file = 'temp.wks' 552 553 # Absolute argument. 554 with open(wks_file, 'w') as wks: 555 wks.write("part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path /usr") 556 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ 557 % (wks_file, self.resultdir), ignore_status=True).status) 558 os.remove(wks_file) 559 560 # Argument pointing to parent directory. 561 with open(wks_file, 'w') as wks: 562 wks.write("part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path ././..") 563 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ 564 % (wks_file, self.resultdir), ignore_status=True).status) 565 os.remove(wks_file) 566 567 def test_permissions(self): 568 """Test permissions are respected""" 569 570 # prepare wicenv and rootfs 571 bitbake('core-image-minimal core-image-minimal-mtdutils -c do_rootfs_wicenv') 572 573 oldpath = os.environ['PATH'] 574 os.environ['PATH'] = get_bb_var("PATH", "wic-tools") 575 576 t_normal = """ 577part / --source rootfs --fstype=ext4 578""" 579 t_exclude = """ 580part / --source rootfs --fstype=ext4 --exclude-path=home 581""" 582 t_multi = """ 583part / --source rootfs --ondisk sda --fstype=ext4 584part /export --source rootfs --rootfs=core-image-minimal-mtdutils --fstype=ext4 585""" 586 t_change = """ 587part / --source rootfs --ondisk sda --fstype=ext4 --exclude-path=etc/ 588part /etc --source rootfs --fstype=ext4 --change-directory=etc 589""" 590 tests = [t_normal, t_exclude, t_multi, t_change] 591 592 try: 593 for test in tests: 594 include_path = os.path.join(self.resultdir, 'test-include') 595 os.makedirs(include_path) 596 wks_file = os.path.join(include_path, 'temp.wks') 597 with open(wks_file, 'w') as wks: 598 wks.write(test) 599 runCmd("wic create %s -e core-image-minimal -o %s" \ 600 % (wks_file, self.resultdir)) 601 602 for part in glob(os.path.join(self.resultdir, 'temp-*.direct.p*')): 603 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part)) 604 self.assertEqual(True, files_own_by_root(res.output)) 605 606 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "%s"\n' % wks_file 607 self.append_config(config) 608 bitbake('core-image-minimal') 609 tmpdir = os.path.join(get_bb_var('WORKDIR', 'core-image-minimal'),'build-wic') 610 611 # check each partition for permission 612 for part in glob(os.path.join(tmpdir, 'temp-*.direct.p*')): 613 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part)) 614 self.assertTrue(files_own_by_root(res.output) 615 ,msg='Files permission incorrect using wks set "%s"' % test) 616 617 # clean config and result directory for next cases 618 self.remove_config(config) 619 rmtree(self.resultdir, ignore_errors=True) 620 621 finally: 622 os.environ['PATH'] = oldpath 623 624 def test_change_directory(self): 625 """Test --change-directory wks option.""" 626 627 oldpath = os.environ['PATH'] 628 os.environ['PATH'] = get_bb_var("PATH", "wic-tools") 629 630 try: 631 include_path = os.path.join(self.resultdir, 'test-include') 632 os.makedirs(include_path) 633 wks_file = os.path.join(include_path, 'temp.wks') 634 with open(wks_file, 'w') as wks: 635 wks.write("part /etc --source rootfs --fstype=ext4 --change-directory=etc") 636 runCmd("wic create %s -e core-image-minimal -o %s" \ 637 % (wks_file, self.resultdir)) 638 639 part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0] 640 641 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1)) 642 files = extract_files(res.output) 643 self.assertIn('passwd', files) 644 645 finally: 646 os.environ['PATH'] = oldpath 647 648 def test_change_directory_errors(self): 649 """Test --change-directory wks option error handling.""" 650 wks_file = 'temp.wks' 651 652 # Absolute argument. 653 with open(wks_file, 'w') as wks: 654 wks.write("part / --source rootfs --fstype=ext4 --change-directory /usr") 655 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ 656 % (wks_file, self.resultdir), ignore_status=True).status) 657 os.remove(wks_file) 658 659 # Argument pointing to parent directory. 660 with open(wks_file, 'w') as wks: 661 wks.write("part / --source rootfs --fstype=ext4 --change-directory ././..") 662 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ 663 % (wks_file, self.resultdir), ignore_status=True).status) 664 os.remove(wks_file) 665 666 def test_no_fstab_update(self): 667 """Test --no-fstab-update wks option.""" 668 669 oldpath = os.environ['PATH'] 670 os.environ['PATH'] = get_bb_var("PATH", "wic-tools") 671 672 # Get stock fstab from base-files recipe 673 bitbake('base-files -c do_install') 674 bf_fstab = os.path.join(get_bb_var('D', 'base-files'), 'etc', 'fstab') 675 self.assertEqual(True, os.path.exists(bf_fstab)) 676 bf_fstab_md5sum = runCmd('md5sum %s 2>/dev/null' % bf_fstab).output.split(" ")[0] 677 678 try: 679 no_fstab_update_path = os.path.join(self.resultdir, 'test-no-fstab-update') 680 os.makedirs(no_fstab_update_path) 681 wks_file = os.path.join(no_fstab_update_path, 'temp.wks') 682 with open(wks_file, 'w') as wks: 683 wks.writelines(['part / --source rootfs --fstype=ext4 --label rootfs\n', 684 'part /mnt/p2 --source rootfs --rootfs-dir=core-image-minimal ', 685 '--fstype=ext4 --label p2 --no-fstab-update\n']) 686 runCmd("wic create %s -e core-image-minimal -o %s" \ 687 % (wks_file, self.resultdir)) 688 689 part_fstab_md5sum = [] 690 for i in range(1, 3): 691 part = glob(os.path.join(self.resultdir, 'temp-*.direct.p') + str(i))[0] 692 part_fstab = runCmd("debugfs -R 'cat etc/fstab' %s 2>/dev/null" % (part)) 693 part_fstab_md5sum.append(hashlib.md5((part_fstab.output + "\n\n").encode('utf-8')).hexdigest()) 694 695 # '/etc/fstab' in partition 2 should contain the same stock fstab file 696 # as the one installed by the base-file recipe. 697 self.assertEqual(bf_fstab_md5sum, part_fstab_md5sum[1]) 698 699 # '/etc/fstab' in partition 1 should contain an updated fstab file. 700 self.assertNotEqual(bf_fstab_md5sum, part_fstab_md5sum[0]) 701 702 finally: 703 os.environ['PATH'] = oldpath 704 705 def test_no_fstab_update_errors(self): 706 """Test --no-fstab-update wks option error handling.""" 707 wks_file = 'temp.wks' 708 709 # Absolute argument. 710 with open(wks_file, 'w') as wks: 711 wks.write("part / --source rootfs --fstype=ext4 --no-fstab-update /etc") 712 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ 713 % (wks_file, self.resultdir), ignore_status=True).status) 714 os.remove(wks_file) 715 716 # Argument pointing to parent directory. 717 with open(wks_file, 'w') as wks: 718 wks.write("part / --source rootfs --fstype=ext4 --no-fstab-update ././..") 719 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ 720 % (wks_file, self.resultdir), ignore_status=True).status) 721 os.remove(wks_file) 722 723 def test_extra_space(self): 724 """Test --extra-space wks option.""" 725 extraspace = 1024**3 726 runCmd("wic create wictestdisk " 727 "--image-name core-image-minimal " 728 "--extra-space %i -o %s" % (extraspace ,self.resultdir)) 729 wicout = glob(os.path.join(self.resultdir, "wictestdisk-*.direct")) 730 self.assertEqual(1, len(wicout)) 731 size = os.path.getsize(wicout[0]) 732 self.assertTrue(size > extraspace) 733 734class Wic2(WicTestCase): 735 736 def test_bmap_short(self): 737 """Test generation of .bmap file -m option""" 738 cmd = "wic create wictestdisk -e core-image-minimal -m -o %s" % self.resultdir 739 runCmd(cmd) 740 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*direct")))) 741 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*direct.bmap")))) 742 743 def test_bmap_long(self): 744 """Test generation of .bmap file --bmap option""" 745 cmd = "wic create wictestdisk -e core-image-minimal --bmap -o %s" % self.resultdir 746 runCmd(cmd) 747 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*direct")))) 748 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*direct.bmap")))) 749 750 def test_image_env(self): 751 """Test generation of <image>.env files.""" 752 image = 'core-image-minimal' 753 imgdatadir = self._get_image_env_path(image) 754 755 bb_vars = get_bb_vars(['IMAGE_BASENAME', 'WICVARS'], image) 756 basename = bb_vars['IMAGE_BASENAME'] 757 self.assertEqual(basename, image) 758 path = os.path.join(imgdatadir, basename) + '.env' 759 self.assertTrue(os.path.isfile(path)) 760 761 wicvars = set(bb_vars['WICVARS'].split()) 762 # filter out optional variables 763 wicvars = wicvars.difference(('DEPLOY_DIR_IMAGE', 'IMAGE_BOOT_FILES', 764 'INITRD', 'INITRD_LIVE', 'ISODIR','INITRAMFS_IMAGE', 765 'INITRAMFS_IMAGE_BUNDLE', 'INITRAMFS_LINK_NAME', 766 'APPEND', 'IMAGE_EFI_BOOT_FILES')) 767 with open(path) as envfile: 768 content = dict(line.split("=", 1) for line in envfile) 769 # test if variables used by wic present in the .env file 770 for var in wicvars: 771 self.assertTrue(var in content, "%s is not in .env file" % var) 772 self.assertTrue(content[var]) 773 774 def test_image_vars_dir_short(self): 775 """Test image vars directory selection -v option""" 776 image = 'core-image-minimal' 777 imgenvdir = self._get_image_env_path(image) 778 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") 779 780 runCmd("wic create wictestdisk " 781 "--image-name=%s -v %s -n %s -o %s" 782 % (image, imgenvdir, native_sysroot, 783 self.resultdir)) 784 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*direct")))) 785 786 def test_image_vars_dir_long(self): 787 """Test image vars directory selection --vars option""" 788 image = 'core-image-minimal' 789 imgenvdir = self._get_image_env_path(image) 790 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") 791 792 runCmd("wic create wictestdisk " 793 "--image-name=%s " 794 "--vars %s " 795 "--native-sysroot %s " 796 "--outdir %s" 797 % (image, imgenvdir, native_sysroot, 798 self.resultdir)) 799 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "wictestdisk-*direct")))) 800 801 # TODO this test could also work on aarch64 802 @skipIfNotArch(['i586', 'i686', 'x86_64']) 803 def test_wic_image_type(self): 804 """Test building wic images by bitbake""" 805 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\ 806 'MACHINE_FEATURES:append = " efi"\n' 807 self.append_config(config) 808 image = 'wic-image-minimal' 809 bitbake(image) 810 self.remove_config(config) 811 812 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_LINK_NAME'], image) 813 prefix = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], '%s.' % bb_vars['IMAGE_LINK_NAME']) 814 815 # check if we have result image and manifests symlinks 816 # pointing to existing files 817 for suffix in ('wic', 'manifest'): 818 path = prefix + suffix 819 self.assertTrue(os.path.islink(path)) 820 self.assertTrue(os.path.isfile(os.path.realpath(path))) 821 822 # TODO this should work on aarch64 823 @skipIfNotArch(['i586', 'i686', 'x86_64']) 824 @OETestTag("runqemu") 825 def test_qemu(self): 826 """Test wic-image-minimal under qemu""" 827 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\ 828 'MACHINE_FEATURES:append = " efi"\n' 829 self.append_config(config) 830 bitbake('wic-image-minimal') 831 self.remove_config(config) 832 833 with runqemu('wic-image-minimal', ssh=False, runqemuparams='nographic') as qemu: 834 cmd = "mount | grep '^/dev/' | cut -f1,3 -d ' ' | egrep -c -e '/dev/sda1 /boot' " \ 835 "-e '/dev/root /|/dev/sda2 /' -e '/dev/sda3 /media' -e '/dev/sda4 /mnt'" 836 status, output = qemu.run_serial(cmd) 837 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 838 self.assertEqual(output, '4') 839 cmd = "grep UUID=2c71ef06-a81d-4735-9d3a-379b69c6bdba /etc/fstab" 840 status, output = qemu.run_serial(cmd) 841 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 842 self.assertEqual(output, 'UUID=2c71ef06-a81d-4735-9d3a-379b69c6bdba\t/media\text4\tdefaults\t0\t0') 843 844 @skipIfNotArch(['i586', 'i686', 'x86_64']) 845 @OETestTag("runqemu") 846 def test_qemu_efi(self): 847 """Test core-image-minimal efi image under qemu""" 848 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "mkefidisk.wks"\n' 849 self.append_config(config) 850 bitbake('core-image-minimal ovmf') 851 self.remove_config(config) 852 853 with runqemu('core-image-minimal', ssh=False, 854 runqemuparams='nographic ovmf', image_fstype='wic') as qemu: 855 cmd = "grep sda. /proc/partitions |wc -l" 856 status, output = qemu.run_serial(cmd) 857 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 858 self.assertEqual(output, '3') 859 860 @staticmethod 861 def _make_fixed_size_wks(size): 862 """ 863 Create a wks of an image with a single partition. Size of the partition is set 864 using --fixed-size flag. Returns a tuple: (path to wks file, wks image name) 865 """ 866 with NamedTemporaryFile("w", suffix=".wks", delete=False) as tempf: 867 wkspath = tempf.name 868 tempf.write("part " \ 869 "--source rootfs --ondisk hda --align 4 --fixed-size %d " 870 "--fstype=ext4\n" % size) 871 872 return wkspath 873 874 def _get_wic_partitions(self, wkspath, native_sysroot=None, ignore_status=False): 875 p = runCmd("wic create %s -e core-image-minimal -o %s" % (wkspath, self.resultdir), 876 ignore_status=ignore_status) 877 878 if p.status: 879 return (p, None) 880 881 wksname = os.path.splitext(os.path.basename(wkspath))[0] 882 883 wicout = glob(os.path.join(self.resultdir, "%s-*direct" % wksname)) 884 885 if not wicout: 886 return (p, None) 887 888 wicimg = wicout[0] 889 890 if not native_sysroot: 891 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") 892 893 # verify partition size with wic 894 res = runCmd("parted -m %s unit kib p 2>/dev/null" % wicimg, 895 native_sysroot=native_sysroot) 896 897 # parse parted output which looks like this: 898 # BYT;\n 899 # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n 900 # 1:0.00MiB:200MiB:200MiB:ext4::;\n 901 return (p, res.output.splitlines()[2:]) 902 903 def test_fixed_size(self): 904 """ 905 Test creation of a simple image with partition size controlled through 906 --fixed-size flag 907 """ 908 wkspath = Wic2._make_fixed_size_wks(200) 909 _, partlns = self._get_wic_partitions(wkspath) 910 os.remove(wkspath) 911 912 self.assertEqual(partlns, [ 913 "1:4.00kiB:204804kiB:204800kiB:ext4::;", 914 ]) 915 916 def test_fixed_size_error(self): 917 """ 918 Test creation of a simple image with partition size controlled through 919 --fixed-size flag. The size of partition is intentionally set to 1MiB 920 in order to trigger an error in wic. 921 """ 922 wkspath = Wic2._make_fixed_size_wks(1) 923 p, _ = self._get_wic_partitions(wkspath, ignore_status=True) 924 os.remove(wkspath) 925 926 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output) 927 928 def test_offset(self): 929 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") 930 931 with NamedTemporaryFile("w", suffix=".wks") as tempf: 932 # Test that partitions are placed at the correct offsets, default KB 933 tempf.write("bootloader --ptable gpt\n" \ 934 "part / --source rootfs --ondisk hda --offset 32 --fixed-size 100M --fstype=ext4\n" \ 935 "part /bar --ondisk hda --offset 102432 --fixed-size 100M --fstype=ext4\n") 936 tempf.flush() 937 938 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) 939 self.assertEqual(partlns, [ 940 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;", 941 "2:102432kiB:204832kiB:102400kiB:ext4:primary:;", 942 ]) 943 944 with NamedTemporaryFile("w", suffix=".wks") as tempf: 945 # Test that partitions are placed at the correct offsets, same with explicit KB 946 tempf.write("bootloader --ptable gpt\n" \ 947 "part / --source rootfs --ondisk hda --offset 32K --fixed-size 100M --fstype=ext4\n" \ 948 "part /bar --ondisk hda --offset 102432K --fixed-size 100M --fstype=ext4\n") 949 tempf.flush() 950 951 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) 952 self.assertEqual(partlns, [ 953 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;", 954 "2:102432kiB:204832kiB:102400kiB:ext4:primary:;", 955 ]) 956 957 with NamedTemporaryFile("w", suffix=".wks") as tempf: 958 # Test that partitions are placed at the correct offsets using MB 959 tempf.write("bootloader --ptable gpt\n" \ 960 "part / --source rootfs --ondisk hda --offset 32K --fixed-size 100M --fstype=ext4\n" \ 961 "part /bar --ondisk hda --offset 101M --fixed-size 100M --fstype=ext4\n") 962 tempf.flush() 963 964 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) 965 self.assertEqual(partlns, [ 966 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;", 967 "2:103424kiB:205824kiB:102400kiB:ext4:primary:;", 968 ]) 969 970 with NamedTemporaryFile("w", suffix=".wks") as tempf: 971 # Test that partitions can be placed on a 512 byte sector boundary 972 tempf.write("bootloader --ptable gpt\n" \ 973 "part / --source rootfs --ondisk hda --offset 65s --fixed-size 99M --fstype=ext4\n" \ 974 "part /bar --ondisk hda --offset 102432 --fixed-size 100M --fstype=ext4\n") 975 tempf.flush() 976 977 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) 978 self.assertEqual(partlns, [ 979 "1:32.5kiB:101408kiB:101376kiB:ext4:primary:;", 980 "2:102432kiB:204832kiB:102400kiB:ext4:primary:;", 981 ]) 982 983 with NamedTemporaryFile("w", suffix=".wks") as tempf: 984 # Test that a partition can be placed immediately after a MSDOS partition table 985 tempf.write("bootloader --ptable msdos\n" \ 986 "part / --source rootfs --ondisk hda --offset 1s --fixed-size 100M --fstype=ext4\n") 987 tempf.flush() 988 989 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) 990 self.assertEqual(partlns, [ 991 "1:0.50kiB:102400kiB:102400kiB:ext4::;", 992 ]) 993 994 with NamedTemporaryFile("w", suffix=".wks") as tempf: 995 # Test that image creation fails if the partitions would overlap 996 tempf.write("bootloader --ptable gpt\n" \ 997 "part / --source rootfs --ondisk hda --offset 32 --fixed-size 100M --fstype=ext4\n" \ 998 "part /bar --ondisk hda --offset 102431 --fixed-size 100M --fstype=ext4\n") 999 tempf.flush() 1000 1001 p, _ = self._get_wic_partitions(tempf.name, ignore_status=True) 1002 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output) 1003 1004 with NamedTemporaryFile("w", suffix=".wks") as tempf: 1005 # Test that partitions are not allowed to overlap with the booloader 1006 tempf.write("bootloader --ptable gpt\n" \ 1007 "part / --source rootfs --ondisk hda --offset 8 --fixed-size 100M --fstype=ext4\n") 1008 tempf.flush() 1009 1010 p, _ = self._get_wic_partitions(tempf.name, ignore_status=True) 1011 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output) 1012 1013 def test_extra_space(self): 1014 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") 1015 1016 with NamedTemporaryFile("w", suffix=".wks") as tempf: 1017 tempf.write("bootloader --ptable gpt\n" \ 1018 "part / --source rootfs --ondisk hda --extra-space 200M --fstype=ext4\n") 1019 tempf.flush() 1020 1021 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) 1022 self.assertEqual(len(partlns), 1) 1023 size = partlns[0].split(':')[3] 1024 self.assertRegex(size, r'^[0-9]+kiB$') 1025 size = int(size[:-3]) 1026 self.assertGreaterEqual(size, 204800) 1027 1028 # TODO this test could also work on aarch64 1029 @skipIfNotArch(['i586', 'i686', 'x86_64']) 1030 @OETestTag("runqemu") 1031 def test_rawcopy_plugin_qemu(self): 1032 """Test rawcopy plugin in qemu""" 1033 # build ext4 and then use it for a wic image 1034 config = 'IMAGE_FSTYPES = "ext4"\n' 1035 self.append_config(config) 1036 bitbake('core-image-minimal') 1037 image_link_name = get_bb_var('IMAGE_LINK_NAME', 'core-image-minimal') 1038 self.remove_config(config) 1039 1040 config = 'IMAGE_FSTYPES = "wic"\n' \ 1041 'IMAGE_LINK_NAME_CORE_IMAGE_MINIMAL = "%s"\n'\ 1042 'WKS_FILE = "test_rawcopy_plugin.wks.in"\n'\ 1043 % image_link_name 1044 self.append_config(config) 1045 bitbake('core-image-minimal-mtdutils') 1046 self.remove_config(config) 1047 1048 with runqemu('core-image-minimal-mtdutils', ssh=False, 1049 runqemuparams='nographic', image_fstype='wic') as qemu: 1050 cmd = "grep sda. /proc/partitions |wc -l" 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 1055 def _rawcopy_plugin(self, fstype): 1056 """Test rawcopy plugin""" 1057 image = 'core-image-minimal' 1058 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_LINK_NAME'], image) 1059 params = ',unpack' if fstype.endswith('.gz') else '' 1060 with NamedTemporaryFile("w", suffix=".wks") as wks: 1061 wks.write('part / --source rawcopy --sourceparams="file=%s.%s%s"\n'\ 1062 % (bb_vars['IMAGE_LINK_NAME'], fstype, params)) 1063 wks.flush() 1064 cmd = "wic create %s -e %s -o %s" % (wks.name, image, self.resultdir) 1065 runCmd(cmd) 1066 wksname = os.path.splitext(os.path.basename(wks.name))[0] 1067 out = glob(os.path.join(self.resultdir, "%s-*direct" % wksname)) 1068 self.assertEqual(1, len(out)) 1069 1070 def test_rawcopy_plugin(self): 1071 self._rawcopy_plugin('ext4') 1072 1073 def test_rawcopy_plugin_unpack(self): 1074 fstype = 'ext4.gz' 1075 config = 'IMAGE_FSTYPES = "%s"\n' % fstype 1076 self.append_config(config) 1077 self.assertEqual(0, bitbake('core-image-minimal').status) 1078 self.remove_config(config) 1079 self._rawcopy_plugin(fstype) 1080 1081 def test_empty_plugin(self): 1082 """Test empty plugin""" 1083 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_empty_plugin.wks"\n' 1084 self.append_config(config) 1085 image = 'core-image-minimal' 1086 bitbake(image) 1087 self.remove_config(config) 1088 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_LINK_NAME'], image) 1089 image_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], '%s.wic' % bb_vars['IMAGE_LINK_NAME']) 1090 self.assertTrue(os.path.exists(image_path)) 1091 1092 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1093 1094 # Fstype column from 'wic ls' should be empty for the second partition 1095 # as listed in test_empty_plugin.wks 1096 result = runCmd("wic ls %s -n %s | awk -F ' ' '{print $1 \" \" $5}' | grep '^2' | wc -w" % (image_path, sysroot)) 1097 self.assertEqual('1', result.output) 1098 1099 @skipIfNotArch(['i586', 'i686', 'x86_64']) 1100 @OETestTag("runqemu") 1101 def test_biosplusefi_plugin_qemu(self): 1102 """Test biosplusefi plugin in qemu""" 1103 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES:append = " efi"\n' 1104 self.append_config(config) 1105 bitbake('core-image-minimal') 1106 self.remove_config(config) 1107 1108 with runqemu('core-image-minimal', ssh=False, 1109 runqemuparams='nographic', image_fstype='wic') as qemu: 1110 # Check that we have ONLY two /dev/sda* partitions (/boot and /) 1111 cmd = "grep sda. /proc/partitions | wc -l" 1112 status, output = qemu.run_serial(cmd) 1113 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1114 self.assertEqual(output, '2') 1115 # Check that /dev/sda1 is /boot and that either /dev/root OR /dev/sda2 is / 1116 cmd = "mount | grep '^/dev/' | cut -f1,3 -d ' ' | egrep -c -e '/dev/sda1 /boot' -e '/dev/root /|/dev/sda2 /'" 1117 status, output = qemu.run_serial(cmd) 1118 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1119 self.assertEqual(output, '2') 1120 # Check that /boot has EFI bootx64.efi (required for EFI) 1121 cmd = "ls /boot/EFI/BOOT/bootx64.efi | wc -l" 1122 status, output = qemu.run_serial(cmd) 1123 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1124 self.assertEqual(output, '1') 1125 # Check that "BOOTABLE" flag is set on boot partition (required for PC-Bios) 1126 # Trailing "cat" seems to be required; otherwise run_serial() sends back echo of the input command 1127 cmd = "fdisk -l /dev/sda | grep /dev/sda1 | awk {print'$2'} | cat" 1128 status, output = qemu.run_serial(cmd) 1129 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1130 self.assertEqual(output, '*') 1131 1132 @skipIfNotArch(['i586', 'i686', 'x86_64']) 1133 def test_biosplusefi_plugin(self): 1134 """Test biosplusefi plugin""" 1135 # Wic generation below may fail depending on the order of the unittests 1136 # This is because bootimg-pcbios (that bootimg-biosplusefi uses) generate its MBR inside STAGING_DATADIR directory 1137 # which may or may not exists depending on what was built already 1138 # If an image hasn't been built yet, directory ${STAGING_DATADIR}/syslinux won't exists and _get_bootimg_dir() 1139 # will raise with "Couldn't find correct bootimg_dir" 1140 # The easiest way to work-around this issue is to make sure we already built an image here, hence the bitbake call 1141 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES:append = " efi"\n' 1142 self.append_config(config) 1143 bitbake('core-image-minimal') 1144 self.remove_config(config) 1145 1146 img = 'core-image-minimal' 1147 with NamedTemporaryFile("w", suffix=".wks") as wks: 1148 wks.writelines(['part /boot --active --source bootimg-biosplusefi --sourceparams="loader=grub-efi"\n', 1149 'part / --source rootfs --fstype=ext4 --align 1024 --use-uuid\n'\ 1150 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n']) 1151 wks.flush() 1152 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir) 1153 runCmd(cmd) 1154 wksname = os.path.splitext(os.path.basename(wks.name))[0] 1155 out = glob(os.path.join(self.resultdir, "%s-*.direct" % wksname)) 1156 self.assertEqual(1, len(out)) 1157 1158 @skipIfNotArch(['i586', 'i686', 'x86_64', 'aarch64']) 1159 def test_uefi_kernel(self): 1160 """ Test uefi-kernel in wic """ 1161 config = 'IMAGE_EFI_BOOT_FILES="/etc/fstab;testfile"\nIMAGE_FSTYPES = "wic"\nWKS_FILE = "test_uefikernel.wks"\nMACHINE_FEATURES:append = " efi"\n' 1162 self.append_config(config) 1163 bitbake('core-image-minimal') 1164 self.remove_config(config) 1165 1166 img = 'core-image-minimal' 1167 with NamedTemporaryFile("w", suffix=".wks") as wks: 1168 wks.writelines(['part /boot --source bootimg-efi --sourceparams="loader=uefi-kernel"\n' 1169 'part / --source rootfs --fstype=ext4 --align 1024 --use-uuid\n'\ 1170 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n']) 1171 wks.flush() 1172 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir) 1173 runCmd(cmd) 1174 wksname = os.path.splitext(os.path.basename(wks.name))[0] 1175 out = glob(os.path.join(self.resultdir, "%s-*.direct" % wksname)) 1176 self.assertEqual(1, len(out)) 1177 1178 # TODO this test could also work on aarch64 1179 @skipIfNotArch(['i586', 'i686', 'x86_64']) 1180 @OETestTag("runqemu") 1181 def test_efi_plugin_unified_kernel_image_qemu(self): 1182 """Test efi plugin's Unified Kernel Image feature in qemu""" 1183 config = 'IMAGE_FSTYPES = "wic"\n'\ 1184 'INITRAMFS_IMAGE = "core-image-minimal-initramfs"\n'\ 1185 'WKS_FILE = "test_efi_plugin.wks"\n'\ 1186 'MACHINE_FEATURES:append = " efi"\n' 1187 self.append_config(config) 1188 bitbake('core-image-minimal core-image-minimal-initramfs ovmf') 1189 self.remove_config(config) 1190 1191 with runqemu('core-image-minimal', ssh=False, 1192 runqemuparams='nographic ovmf', image_fstype='wic') as qemu: 1193 # Check that /boot has EFI bootx64.efi (required for EFI) 1194 cmd = "ls /boot/EFI/BOOT/bootx64.efi | wc -l" 1195 status, output = qemu.run_serial(cmd) 1196 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1197 self.assertEqual(output, '1') 1198 # Check that /boot has EFI/Linux/linux.efi (required for Unified Kernel Images auto detection) 1199 cmd = "ls /boot/EFI/Linux/linux.efi | wc -l" 1200 status, output = qemu.run_serial(cmd) 1201 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1202 self.assertEqual(output, '1') 1203 # Check that /boot doesn't have loader/entries/boot.conf (Unified Kernel Images are auto detected by the bootloader) 1204 cmd = "ls /boot/loader/entries/boot.conf 2&>/dev/null | wc -l" 1205 status, output = qemu.run_serial(cmd) 1206 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1207 self.assertEqual(output, '0') 1208 1209 def test_fs_types(self): 1210 """Test filesystem types for empty and not empty partitions""" 1211 img = 'core-image-minimal' 1212 with NamedTemporaryFile("w", suffix=".wks") as wks: 1213 wks.writelines(['part ext2 --fstype ext2 --source rootfs\n', 1214 'part btrfs --fstype btrfs --source rootfs --size 40M\n', 1215 'part squash --fstype squashfs --source rootfs\n', 1216 'part swap --fstype swap --size 1M\n', 1217 'part emptyvfat --fstype vfat --size 1M\n', 1218 'part emptymsdos --fstype msdos --size 1M\n', 1219 'part emptyext2 --fstype ext2 --size 1M\n', 1220 'part emptybtrfs --fstype btrfs --size 150M\n']) 1221 wks.flush() 1222 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir) 1223 runCmd(cmd) 1224 wksname = os.path.splitext(os.path.basename(wks.name))[0] 1225 out = glob(os.path.join(self.resultdir, "%s-*direct" % wksname)) 1226 self.assertEqual(1, len(out)) 1227 1228 def test_kickstart_parser(self): 1229 """Test wks parser options""" 1230 with NamedTemporaryFile("w", suffix=".wks") as wks: 1231 wks.writelines(['part / --fstype ext3 --source rootfs --system-id 0xFF '\ 1232 '--overhead-factor 1.2 --size 100k\n']) 1233 wks.flush() 1234 cmd = "wic create %s -e core-image-minimal -o %s" % (wks.name, self.resultdir) 1235 runCmd(cmd) 1236 wksname = os.path.splitext(os.path.basename(wks.name))[0] 1237 out = glob(os.path.join(self.resultdir, "%s-*direct" % wksname)) 1238 self.assertEqual(1, len(out)) 1239 1240 def test_image_bootpart_globbed(self): 1241 """Test globbed sources with image-bootpart plugin""" 1242 img = "core-image-minimal" 1243 cmd = "wic create sdimage-bootpart -e %s -o %s" % (img, self.resultdir) 1244 config = 'IMAGE_BOOT_FILES = "%s*"' % get_bb_var('KERNEL_IMAGETYPE', img) 1245 self.append_config(config) 1246 runCmd(cmd) 1247 self.remove_config(config) 1248 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "sdimage-bootpart-*direct")))) 1249 1250 def test_sparse_copy(self): 1251 """Test sparse_copy with FIEMAP and SEEK_HOLE filemap APIs""" 1252 libpath = os.path.join(self.td['COREBASE'], 'scripts', 'lib', 'wic') 1253 sys.path.insert(0, libpath) 1254 from filemap import FilemapFiemap, FilemapSeek, sparse_copy, ErrorNotSupp 1255 with NamedTemporaryFile("w", suffix=".wic-sparse") as sparse: 1256 src_name = sparse.name 1257 src_size = 1024 * 10 1258 sparse.truncate(src_size) 1259 # write one byte to the file 1260 with open(src_name, 'r+b') as sfile: 1261 sfile.seek(1024 * 4) 1262 sfile.write(b'\x00') 1263 dest = sparse.name + '.out' 1264 # copy src file to dest using different filemap APIs 1265 for api in (FilemapFiemap, FilemapSeek, None): 1266 if os.path.exists(dest): 1267 os.unlink(dest) 1268 try: 1269 sparse_copy(sparse.name, dest, api=api) 1270 except ErrorNotSupp: 1271 continue # skip unsupported API 1272 dest_stat = os.stat(dest) 1273 self.assertEqual(dest_stat.st_size, src_size) 1274 # 8 blocks is 4K (physical sector size) 1275 self.assertEqual(dest_stat.st_blocks, 8) 1276 os.unlink(dest) 1277 1278 def test_mkfs_extraopts(self): 1279 """Test wks option --mkfs-extraopts for empty and not empty partitions""" 1280 img = 'core-image-minimal' 1281 with NamedTemporaryFile("w", suffix=".wks") as wks: 1282 wks.writelines( 1283 ['part ext2 --fstype ext2 --source rootfs --mkfs-extraopts "-D -F -i 8192"\n', 1284 "part btrfs --fstype btrfs --source rootfs --size 40M --mkfs-extraopts='--quiet'\n", 1285 'part squash --fstype squashfs --source rootfs --mkfs-extraopts "-no-sparse -b 4096"\n', 1286 'part emptyvfat --fstype vfat --size 1M --mkfs-extraopts "-S 1024 -s 64"\n', 1287 'part emptymsdos --fstype msdos --size 1M --mkfs-extraopts "-S 1024 -s 64"\n', 1288 'part emptyext2 --fstype ext2 --size 1M --mkfs-extraopts "-D -F -i 8192"\n', 1289 'part emptybtrfs --fstype btrfs --size 100M --mkfs-extraopts "--mixed -K"\n']) 1290 wks.flush() 1291 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir) 1292 runCmd(cmd) 1293 wksname = os.path.splitext(os.path.basename(wks.name))[0] 1294 out = glob(os.path.join(self.resultdir, "%s-*direct" % wksname)) 1295 self.assertEqual(1, len(out)) 1296 1297 @skipIfNotArch(['i586', 'i686', 'x86_64']) 1298 @OETestTag("runqemu") 1299 def test_expand_mbr_image(self): 1300 """Test wic write --expand command for mbr image""" 1301 # build an image 1302 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "directdisk.wks"\n' 1303 self.append_config(config) 1304 image = 'core-image-minimal' 1305 bitbake(image) 1306 1307 # get path to the image 1308 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_LINK_NAME'], image) 1309 image_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], '%s.wic' % bb_vars['IMAGE_LINK_NAME']) 1310 1311 self.remove_config(config) 1312 1313 try: 1314 # expand image to 1G 1315 new_image_path = None 1316 with NamedTemporaryFile(mode='wb', suffix='.wic.exp', 1317 dir=bb_vars['DEPLOY_DIR_IMAGE'], delete=False) as sparse: 1318 sparse.truncate(1024 ** 3) 1319 new_image_path = sparse.name 1320 1321 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1322 cmd = "wic write -n %s --expand 1:0 %s %s" % (sysroot, image_path, new_image_path) 1323 runCmd(cmd) 1324 1325 # check if partitions are expanded 1326 orig = runCmd("wic ls %s -n %s" % (image_path, sysroot)) 1327 exp = runCmd("wic ls %s -n %s" % (new_image_path, sysroot)) 1328 orig_sizes = [int(line.split()[3]) for line in orig.output.split('\n')[1:]] 1329 exp_sizes = [int(line.split()[3]) for line in exp.output.split('\n')[1:]] 1330 self.assertEqual(orig_sizes[0], exp_sizes[0]) # first partition is not resized 1331 self.assertTrue(orig_sizes[1] < exp_sizes[1]) 1332 1333 # Check if all free space is partitioned 1334 result = runCmd("%s/usr/sbin/sfdisk -F %s" % (sysroot, new_image_path)) 1335 self.assertTrue("0 B, 0 bytes, 0 sectors" in result.output) 1336 1337 os.rename(image_path, image_path + '.bak') 1338 os.rename(new_image_path, image_path) 1339 1340 # Check if it boots in qemu 1341 with runqemu('core-image-minimal', ssh=False, runqemuparams='nographic') as qemu: 1342 cmd = "ls /etc/" 1343 status, output = qemu.run_serial('true') 1344 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1345 finally: 1346 if os.path.exists(new_image_path): 1347 os.unlink(new_image_path) 1348 if os.path.exists(image_path + '.bak'): 1349 os.rename(image_path + '.bak', image_path) 1350 1351 def test_gpt_partition_name(self): 1352 """Test --part-name argument to set partition name in GPT table""" 1353 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "test_gpt_partition_name.wks"\n' 1354 self.append_config(config) 1355 image = 'core-image-minimal' 1356 bitbake(image) 1357 self.remove_config(config) 1358 deploy_dir = get_bb_var('DEPLOY_DIR_IMAGE') 1359 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_LINK_NAME'], image) 1360 image_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], '%s.wic' % bb_vars['IMAGE_LINK_NAME']) 1361 1362 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1363 1364 # Image is created 1365 self.assertTrue(os.path.exists(image_path), "image file %s doesn't exist" % image_path) 1366 1367 # Check the names of the three partitions 1368 # as listed in test_gpt_partition_name.wks 1369 result = runCmd("%s/usr/sbin/sfdisk --part-label %s 1" % (sysroot, image_path)) 1370 self.assertEqual('boot-A', result.output) 1371 result = runCmd("%s/usr/sbin/sfdisk --part-label %s 2" % (sysroot, image_path)) 1372 self.assertEqual('root-A', result.output) 1373 # When the --part-name is not defined, the partition name is equal to the --label 1374 result = runCmd("%s/usr/sbin/sfdisk --part-label %s 3" % (sysroot, image_path)) 1375 self.assertEqual('ext-space', result.output) 1376 1377class ModifyTests(WicTestCase): 1378 def test_wic_ls(self): 1379 """Test listing image content using 'wic ls'""" 1380 runCmd("wic create wictestdisk " 1381 "--image-name=core-image-minimal " 1382 "-D -o %s" % self.resultdir) 1383 images = glob(os.path.join(self.resultdir, "wictestdisk-*.direct")) 1384 self.assertEqual(1, len(images)) 1385 1386 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1387 1388 # list partitions 1389 result = runCmd("wic ls %s -n %s" % (images[0], sysroot)) 1390 self.assertEqual(3, len(result.output.split('\n'))) 1391 1392 # list directory content of the first partition 1393 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot)) 1394 self.assertEqual(6, len(result.output.split('\n'))) 1395 1396 def test_wic_cp(self): 1397 """Test copy files and directories to the the wic image.""" 1398 runCmd("wic create wictestdisk " 1399 "--image-name=core-image-minimal " 1400 "-D -o %s" % self.resultdir) 1401 images = glob(os.path.join(self.resultdir, "wictestdisk-*.direct")) 1402 self.assertEqual(1, len(images)) 1403 1404 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1405 1406 # list directory content of the first partition 1407 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot)) 1408 self.assertEqual(6, len(result.output.split('\n'))) 1409 1410 with NamedTemporaryFile("w", suffix=".wic-cp") as testfile: 1411 testfile.write("test") 1412 1413 # copy file to the partition 1414 runCmd("wic cp %s %s:1/ -n %s" % (testfile.name, images[0], sysroot)) 1415 1416 # check if file is there 1417 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot)) 1418 self.assertEqual(7, len(result.output.split('\n'))) 1419 self.assertTrue(os.path.basename(testfile.name) in result.output) 1420 1421 # prepare directory 1422 testdir = os.path.join(self.resultdir, 'wic-test-cp-dir') 1423 testsubdir = os.path.join(testdir, 'subdir') 1424 os.makedirs(os.path.join(testsubdir)) 1425 copy(testfile.name, testdir) 1426 1427 # copy directory to the partition 1428 runCmd("wic cp %s %s:1/ -n %s" % (testdir, images[0], sysroot)) 1429 1430 # check if directory is there 1431 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot)) 1432 self.assertEqual(8, len(result.output.split('\n'))) 1433 self.assertTrue(os.path.basename(testdir) in result.output) 1434 1435 # copy the file from the partition and check if it success 1436 dest = '%s-cp' % testfile.name 1437 runCmd("wic cp %s:1/%s %s -n %s" % (images[0], 1438 os.path.basename(testfile.name), dest, sysroot)) 1439 self.assertTrue(os.path.exists(dest)) 1440 1441 1442 def test_wic_rm(self): 1443 """Test removing files and directories from the the wic image.""" 1444 runCmd("wic create mkefidisk " 1445 "--image-name=core-image-minimal " 1446 "-D -o %s" % self.resultdir) 1447 images = glob(os.path.join(self.resultdir, "mkefidisk-*.direct")) 1448 self.assertEqual(1, len(images)) 1449 1450 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1451 # Not bulletproof but hopefully sufficient 1452 kerneltype = get_bb_var('KERNEL_IMAGETYPE', 'virtual/kernel') 1453 1454 # list directory content of the first partition 1455 result = runCmd("wic ls %s:1 -n %s" % (images[0], sysroot)) 1456 self.assertIn('\n%s ' % kerneltype.upper(), result.output) 1457 self.assertIn('\nEFI <DIR> ', result.output) 1458 1459 # remove file. EFI partitions are case-insensitive so exercise that too 1460 runCmd("wic rm %s:1/%s -n %s" % (images[0], kerneltype.lower(), sysroot)) 1461 1462 # remove directory 1463 runCmd("wic rm %s:1/efi -n %s" % (images[0], sysroot)) 1464 1465 # check if they're removed 1466 result = runCmd("wic ls %s:1 -n %s" % (images[0], sysroot)) 1467 self.assertNotIn('\n%s ' % kerneltype.upper(), result.output) 1468 self.assertNotIn('\nEFI <DIR> ', result.output) 1469 1470 def test_wic_ls_ext(self): 1471 """Test listing content of the ext partition using 'wic ls'""" 1472 runCmd("wic create wictestdisk " 1473 "--image-name=core-image-minimal " 1474 "-D -o %s" % self.resultdir) 1475 images = glob(os.path.join(self.resultdir, "wictestdisk-*.direct")) 1476 self.assertEqual(1, len(images)) 1477 1478 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1479 1480 # list directory content of the second ext4 partition 1481 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot)) 1482 self.assertTrue(set(['bin', 'home', 'proc', 'usr', 'var', 'dev', 'lib', 'sbin']).issubset( 1483 set(line.split()[-1] for line in result.output.split('\n') if line))) 1484 1485 def test_wic_cp_ext(self): 1486 """Test copy files and directories to the ext partition.""" 1487 runCmd("wic create wictestdisk " 1488 "--image-name=core-image-minimal " 1489 "-D -o %s" % self.resultdir) 1490 images = glob(os.path.join(self.resultdir, "wictestdisk-*.direct")) 1491 self.assertEqual(1, len(images)) 1492 1493 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1494 1495 # list directory content of the ext4 partition 1496 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot)) 1497 dirs = set(line.split()[-1] for line in result.output.split('\n') if line) 1498 self.assertTrue(set(['bin', 'home', 'proc', 'usr', 'var', 'dev', 'lib', 'sbin']).issubset(dirs)) 1499 1500 with NamedTemporaryFile("w", suffix=".wic-cp") as testfile: 1501 testfile.write("test") 1502 1503 # copy file to the partition 1504 runCmd("wic cp %s %s:2/ -n %s" % (testfile.name, images[0], sysroot)) 1505 1506 # check if file is there 1507 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot)) 1508 newdirs = set(line.split()[-1] for line in result.output.split('\n') if line) 1509 self.assertEqual(newdirs.difference(dirs), set([os.path.basename(testfile.name)])) 1510 1511 # check if the file to copy is in the partition 1512 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot)) 1513 self.assertTrue('fstab' in [line.split()[-1] for line in result.output.split('\n') if line]) 1514 1515 # copy file from the partition, replace the temporary file content with it and 1516 # check for the file size to validate the copy 1517 runCmd("wic cp %s:2/etc/fstab %s -n %s" % (images[0], testfile.name, sysroot)) 1518 self.assertTrue(os.stat(testfile.name).st_size > 0) 1519 1520 1521 def test_wic_rm_ext(self): 1522 """Test removing files from the ext partition.""" 1523 runCmd("wic create mkefidisk " 1524 "--image-name=core-image-minimal " 1525 "-D -o %s" % self.resultdir) 1526 images = glob(os.path.join(self.resultdir, "mkefidisk-*.direct")) 1527 self.assertEqual(1, len(images)) 1528 1529 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1530 1531 # list directory content of the /etc directory on ext4 partition 1532 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot)) 1533 self.assertTrue('fstab' in [line.split()[-1] for line in result.output.split('\n') if line]) 1534 1535 # remove file 1536 runCmd("wic rm %s:2/etc/fstab -n %s" % (images[0], sysroot)) 1537 1538 # check if it's removed 1539 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot)) 1540 self.assertTrue('fstab' not in [line.split()[-1] for line in result.output.split('\n') if line]) 1541 1542 # remove non-empty directory 1543 runCmd("wic rm -r %s:2/etc/ -n %s" % (images[0], sysroot)) 1544 1545 # check if it's removed 1546 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot)) 1547 self.assertTrue('etc' not in [line.split()[-1] for line in result.output.split('\n') if line]) 1548