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 bitbake('wic-image-minimal') 809 self.remove_config(config) 810 811 deploy_dir = get_bb_var('DEPLOY_DIR_IMAGE') 812 machine = self.td['MACHINE'] 813 prefix = os.path.join(deploy_dir, 'wic-image-minimal-%s.' % machine) 814 # check if we have result image and manifests symlinks 815 # pointing to existing files 816 for suffix in ('wic', 'manifest'): 817 path = prefix + suffix 818 self.assertTrue(os.path.islink(path)) 819 self.assertTrue(os.path.isfile(os.path.realpath(path))) 820 821 # TODO this should work on aarch64 822 @skipIfNotArch(['i586', 'i686', 'x86_64']) 823 @OETestTag("runqemu") 824 def test_qemu(self): 825 """Test wic-image-minimal under qemu""" 826 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\ 827 'MACHINE_FEATURES:append = " efi"\n' 828 self.append_config(config) 829 bitbake('wic-image-minimal') 830 self.remove_config(config) 831 832 with runqemu('wic-image-minimal', ssh=False, runqemuparams='nographic') as qemu: 833 cmd = "mount | grep '^/dev/' | cut -f1,3 -d ' ' | egrep -c -e '/dev/sda1 /boot' " \ 834 "-e '/dev/root /|/dev/sda2 /' -e '/dev/sda3 /media' -e '/dev/sda4 /mnt'" 835 status, output = qemu.run_serial(cmd) 836 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 837 self.assertEqual(output, '4') 838 cmd = "grep UUID=2c71ef06-a81d-4735-9d3a-379b69c6bdba /etc/fstab" 839 status, output = qemu.run_serial(cmd) 840 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 841 self.assertEqual(output, 'UUID=2c71ef06-a81d-4735-9d3a-379b69c6bdba\t/media\text4\tdefaults\t0\t0') 842 843 @skipIfNotArch(['i586', 'i686', 'x86_64']) 844 @OETestTag("runqemu") 845 def test_qemu_efi(self): 846 """Test core-image-minimal efi image under qemu""" 847 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "mkefidisk.wks"\n' 848 self.append_config(config) 849 bitbake('core-image-minimal ovmf') 850 self.remove_config(config) 851 852 with runqemu('core-image-minimal', ssh=False, 853 runqemuparams='nographic ovmf', image_fstype='wic') as qemu: 854 cmd = "grep sda. /proc/partitions |wc -l" 855 status, output = qemu.run_serial(cmd) 856 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 857 self.assertEqual(output, '3') 858 859 @staticmethod 860 def _make_fixed_size_wks(size): 861 """ 862 Create a wks of an image with a single partition. Size of the partition is set 863 using --fixed-size flag. Returns a tuple: (path to wks file, wks image name) 864 """ 865 with NamedTemporaryFile("w", suffix=".wks", delete=False) as tempf: 866 wkspath = tempf.name 867 tempf.write("part " \ 868 "--source rootfs --ondisk hda --align 4 --fixed-size %d " 869 "--fstype=ext4\n" % size) 870 871 return wkspath 872 873 def _get_wic_partitions(self, wkspath, native_sysroot=None, ignore_status=False): 874 p = runCmd("wic create %s -e core-image-minimal -o %s" % (wkspath, self.resultdir), 875 ignore_status=ignore_status) 876 877 if p.status: 878 return (p, None) 879 880 wksname = os.path.splitext(os.path.basename(wkspath))[0] 881 882 wicout = glob(os.path.join(self.resultdir, "%s-*direct" % wksname)) 883 884 if not wicout: 885 return (p, None) 886 887 wicimg = wicout[0] 888 889 if not native_sysroot: 890 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") 891 892 # verify partition size with wic 893 res = runCmd("parted -m %s unit kib p 2>/dev/null" % wicimg, 894 native_sysroot=native_sysroot) 895 896 # parse parted output which looks like this: 897 # BYT;\n 898 # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n 899 # 1:0.00MiB:200MiB:200MiB:ext4::;\n 900 return (p, res.output.splitlines()[2:]) 901 902 def test_fixed_size(self): 903 """ 904 Test creation of a simple image with partition size controlled through 905 --fixed-size flag 906 """ 907 wkspath = Wic2._make_fixed_size_wks(200) 908 _, partlns = self._get_wic_partitions(wkspath) 909 os.remove(wkspath) 910 911 self.assertEqual(partlns, [ 912 "1:4.00kiB:204804kiB:204800kiB:ext4::;", 913 ]) 914 915 def test_fixed_size_error(self): 916 """ 917 Test creation of a simple image with partition size controlled through 918 --fixed-size flag. The size of partition is intentionally set to 1MiB 919 in order to trigger an error in wic. 920 """ 921 wkspath = Wic2._make_fixed_size_wks(1) 922 p, _ = self._get_wic_partitions(wkspath, ignore_status=True) 923 os.remove(wkspath) 924 925 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output) 926 927 def test_offset(self): 928 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") 929 930 with NamedTemporaryFile("w", suffix=".wks") as tempf: 931 # Test that partitions are placed at the correct offsets, default KB 932 tempf.write("bootloader --ptable gpt\n" \ 933 "part / --source rootfs --ondisk hda --offset 32 --fixed-size 100M --fstype=ext4\n" \ 934 "part /bar --ondisk hda --offset 102432 --fixed-size 100M --fstype=ext4\n") 935 tempf.flush() 936 937 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) 938 self.assertEqual(partlns, [ 939 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;", 940 "2:102432kiB:204832kiB:102400kiB:ext4:primary:;", 941 ]) 942 943 with NamedTemporaryFile("w", suffix=".wks") as tempf: 944 # Test that partitions are placed at the correct offsets, same with explicit KB 945 tempf.write("bootloader --ptable gpt\n" \ 946 "part / --source rootfs --ondisk hda --offset 32K --fixed-size 100M --fstype=ext4\n" \ 947 "part /bar --ondisk hda --offset 102432K --fixed-size 100M --fstype=ext4\n") 948 tempf.flush() 949 950 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) 951 self.assertEqual(partlns, [ 952 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;", 953 "2:102432kiB:204832kiB:102400kiB:ext4:primary:;", 954 ]) 955 956 with NamedTemporaryFile("w", suffix=".wks") as tempf: 957 # Test that partitions are placed at the correct offsets using MB 958 tempf.write("bootloader --ptable gpt\n" \ 959 "part / --source rootfs --ondisk hda --offset 32K --fixed-size 100M --fstype=ext4\n" \ 960 "part /bar --ondisk hda --offset 101M --fixed-size 100M --fstype=ext4\n") 961 tempf.flush() 962 963 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) 964 self.assertEqual(partlns, [ 965 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;", 966 "2:103424kiB:205824kiB:102400kiB:ext4:primary:;", 967 ]) 968 969 with NamedTemporaryFile("w", suffix=".wks") as tempf: 970 # Test that partitions can be placed on a 512 byte sector boundary 971 tempf.write("bootloader --ptable gpt\n" \ 972 "part / --source rootfs --ondisk hda --offset 65s --fixed-size 99M --fstype=ext4\n" \ 973 "part /bar --ondisk hda --offset 102432 --fixed-size 100M --fstype=ext4\n") 974 tempf.flush() 975 976 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) 977 self.assertEqual(partlns, [ 978 "1:32.5kiB:101408kiB:101376kiB:ext4:primary:;", 979 "2:102432kiB:204832kiB:102400kiB:ext4:primary:;", 980 ]) 981 982 with NamedTemporaryFile("w", suffix=".wks") as tempf: 983 # Test that a partition can be placed immediately after a MSDOS partition table 984 tempf.write("bootloader --ptable msdos\n" \ 985 "part / --source rootfs --ondisk hda --offset 1s --fixed-size 100M --fstype=ext4\n") 986 tempf.flush() 987 988 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) 989 self.assertEqual(partlns, [ 990 "1:0.50kiB:102400kiB:102400kiB:ext4::;", 991 ]) 992 993 with NamedTemporaryFile("w", suffix=".wks") as tempf: 994 # Test that image creation fails if the partitions would overlap 995 tempf.write("bootloader --ptable gpt\n" \ 996 "part / --source rootfs --ondisk hda --offset 32 --fixed-size 100M --fstype=ext4\n" \ 997 "part /bar --ondisk hda --offset 102431 --fixed-size 100M --fstype=ext4\n") 998 tempf.flush() 999 1000 p, _ = self._get_wic_partitions(tempf.name, ignore_status=True) 1001 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output) 1002 1003 with NamedTemporaryFile("w", suffix=".wks") as tempf: 1004 # Test that partitions are not allowed to overlap with the booloader 1005 tempf.write("bootloader --ptable gpt\n" \ 1006 "part / --source rootfs --ondisk hda --offset 8 --fixed-size 100M --fstype=ext4\n") 1007 tempf.flush() 1008 1009 p, _ = self._get_wic_partitions(tempf.name, ignore_status=True) 1010 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output) 1011 1012 def test_extra_space(self): 1013 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") 1014 1015 with NamedTemporaryFile("w", suffix=".wks") as tempf: 1016 tempf.write("bootloader --ptable gpt\n" \ 1017 "part / --source rootfs --ondisk hda --extra-space 200M --fstype=ext4\n") 1018 tempf.flush() 1019 1020 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) 1021 self.assertEqual(len(partlns), 1) 1022 size = partlns[0].split(':')[3] 1023 self.assertRegex(size, r'^[0-9]+kiB$') 1024 size = int(size[:-3]) 1025 self.assertGreaterEqual(size, 204800) 1026 1027 # TODO this test could also work on aarch64 1028 @skipIfNotArch(['i586', 'i686', 'x86_64']) 1029 @OETestTag("runqemu") 1030 def test_rawcopy_plugin_qemu(self): 1031 """Test rawcopy plugin in qemu""" 1032 # build ext4 and then use it for a wic image 1033 config = 'IMAGE_FSTYPES = "ext4"\n' 1034 self.append_config(config) 1035 bitbake('core-image-minimal') 1036 self.remove_config(config) 1037 1038 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_rawcopy_plugin.wks.in"\n' 1039 self.append_config(config) 1040 bitbake('core-image-minimal-mtdutils') 1041 self.remove_config(config) 1042 1043 with runqemu('core-image-minimal-mtdutils', ssh=False, 1044 runqemuparams='nographic', image_fstype='wic') as qemu: 1045 cmd = "grep sda. /proc/partitions |wc -l" 1046 status, output = qemu.run_serial(cmd) 1047 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1048 self.assertEqual(output, '2') 1049 1050 def _rawcopy_plugin(self, fstype): 1051 """Test rawcopy plugin""" 1052 img = 'core-image-minimal' 1053 machine = self.td["MACHINE"] 1054 params = ',unpack' if fstype.endswith('.gz') else '' 1055 with NamedTemporaryFile("w", suffix=".wks") as wks: 1056 wks.write('part / --source rawcopy --sourceparams="file=%s-%s.%s%s"\n'\ 1057 % (img, machine, fstype, params)) 1058 wks.flush() 1059 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir) 1060 runCmd(cmd) 1061 wksname = os.path.splitext(os.path.basename(wks.name))[0] 1062 out = glob(os.path.join(self.resultdir, "%s-*direct" % wksname)) 1063 self.assertEqual(1, len(out)) 1064 1065 def test_rawcopy_plugin(self): 1066 self._rawcopy_plugin('ext4') 1067 1068 def test_rawcopy_plugin_unpack(self): 1069 fstype = 'ext4.gz' 1070 config = 'IMAGE_FSTYPES = "%s"\n' % fstype 1071 self.append_config(config) 1072 self.assertEqual(0, bitbake('core-image-minimal').status) 1073 self.remove_config(config) 1074 self._rawcopy_plugin(fstype) 1075 1076 def test_empty_plugin(self): 1077 """Test empty plugin""" 1078 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_empty_plugin.wks"\n' 1079 self.append_config(config) 1080 bitbake('core-image-minimal') 1081 self.remove_config(config) 1082 deploy_dir = get_bb_var('DEPLOY_DIR_IMAGE') 1083 machine = self.td['MACHINE'] 1084 1085 image_path = os.path.join(deploy_dir, 'core-image-minimal-%s.wic' % machine) 1086 self.assertTrue(os.path.exists(image_path)) 1087 1088 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1089 1090 # Fstype column from 'wic ls' should be empty for the second partition 1091 # as listed in test_empty_plugin.wks 1092 result = runCmd("wic ls %s -n %s | awk -F ' ' '{print $1 \" \" $5}' | grep '^2' | wc -w" % (image_path, sysroot)) 1093 self.assertEqual('1', result.output) 1094 1095 @skipIfNotArch(['i586', 'i686', 'x86_64']) 1096 @OETestTag("runqemu") 1097 def test_biosplusefi_plugin_qemu(self): 1098 """Test biosplusefi plugin in qemu""" 1099 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES:append = " efi"\n' 1100 self.append_config(config) 1101 bitbake('core-image-minimal') 1102 self.remove_config(config) 1103 1104 with runqemu('core-image-minimal', ssh=False, 1105 runqemuparams='nographic', image_fstype='wic') as qemu: 1106 # Check that we have ONLY two /dev/sda* partitions (/boot and /) 1107 cmd = "grep sda. /proc/partitions | wc -l" 1108 status, output = qemu.run_serial(cmd) 1109 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1110 self.assertEqual(output, '2') 1111 # Check that /dev/sda1 is /boot and that either /dev/root OR /dev/sda2 is / 1112 cmd = "mount | grep '^/dev/' | cut -f1,3 -d ' ' | egrep -c -e '/dev/sda1 /boot' -e '/dev/root /|/dev/sda2 /'" 1113 status, output = qemu.run_serial(cmd) 1114 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1115 self.assertEqual(output, '2') 1116 # Check that /boot has EFI bootx64.efi (required for EFI) 1117 cmd = "ls /boot/EFI/BOOT/bootx64.efi | wc -l" 1118 status, output = qemu.run_serial(cmd) 1119 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1120 self.assertEqual(output, '1') 1121 # Check that "BOOTABLE" flag is set on boot partition (required for PC-Bios) 1122 # Trailing "cat" seems to be required; otherwise run_serial() sends back echo of the input command 1123 cmd = "fdisk -l /dev/sda | grep /dev/sda1 | awk {print'$2'} | cat" 1124 status, output = qemu.run_serial(cmd) 1125 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1126 self.assertEqual(output, '*') 1127 1128 @skipIfNotArch(['i586', 'i686', 'x86_64']) 1129 def test_biosplusefi_plugin(self): 1130 """Test biosplusefi plugin""" 1131 # Wic generation below may fail depending on the order of the unittests 1132 # This is because bootimg-pcbios (that bootimg-biosplusefi uses) generate its MBR inside STAGING_DATADIR directory 1133 # which may or may not exists depending on what was built already 1134 # If an image hasn't been built yet, directory ${STAGING_DATADIR}/syslinux won't exists and _get_bootimg_dir() 1135 # will raise with "Couldn't find correct bootimg_dir" 1136 # The easiest way to work-around this issue is to make sure we already built an image here, hence the bitbake call 1137 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES:append = " efi"\n' 1138 self.append_config(config) 1139 bitbake('core-image-minimal') 1140 self.remove_config(config) 1141 1142 img = 'core-image-minimal' 1143 with NamedTemporaryFile("w", suffix=".wks") as wks: 1144 wks.writelines(['part /boot --active --source bootimg-biosplusefi --sourceparams="loader=grub-efi"\n', 1145 'part / --source rootfs --fstype=ext4 --align 1024 --use-uuid\n'\ 1146 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n']) 1147 wks.flush() 1148 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir) 1149 runCmd(cmd) 1150 wksname = os.path.splitext(os.path.basename(wks.name))[0] 1151 out = glob(os.path.join(self.resultdir, "%s-*.direct" % wksname)) 1152 self.assertEqual(1, len(out)) 1153 1154 @skipIfNotArch(['i586', 'i686', 'x86_64', 'aarch64']) 1155 def test_uefi_kernel(self): 1156 """ Test uefi-kernel in wic """ 1157 config = 'IMAGE_EFI_BOOT_FILES="/etc/fstab;testfile"\nIMAGE_FSTYPES = "wic"\nWKS_FILE = "test_uefikernel.wks"\nMACHINE_FEATURES:append = " efi"\n' 1158 self.append_config(config) 1159 bitbake('core-image-minimal') 1160 self.remove_config(config) 1161 1162 img = 'core-image-minimal' 1163 with NamedTemporaryFile("w", suffix=".wks") as wks: 1164 wks.writelines(['part /boot --source bootimg-efi --sourceparams="loader=uefi-kernel"\n' 1165 'part / --source rootfs --fstype=ext4 --align 1024 --use-uuid\n'\ 1166 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n']) 1167 wks.flush() 1168 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir) 1169 runCmd(cmd) 1170 wksname = os.path.splitext(os.path.basename(wks.name))[0] 1171 out = glob(os.path.join(self.resultdir, "%s-*.direct" % wksname)) 1172 self.assertEqual(1, len(out)) 1173 1174 # TODO this test could also work on aarch64 1175 @skipIfNotArch(['i586', 'i686', 'x86_64']) 1176 @OETestTag("runqemu") 1177 def test_efi_plugin_unified_kernel_image_qemu(self): 1178 """Test efi plugin's Unified Kernel Image feature in qemu""" 1179 config = 'IMAGE_FSTYPES = "wic"\n'\ 1180 'INITRAMFS_IMAGE = "core-image-minimal-initramfs"\n'\ 1181 'WKS_FILE = "test_efi_plugin.wks"\n'\ 1182 'MACHINE_FEATURES:append = " efi"\n' 1183 self.append_config(config) 1184 bitbake('core-image-minimal core-image-minimal-initramfs ovmf') 1185 self.remove_config(config) 1186 1187 with runqemu('core-image-minimal', ssh=False, 1188 runqemuparams='nographic ovmf', image_fstype='wic') as qemu: 1189 # Check that /boot has EFI bootx64.efi (required for EFI) 1190 cmd = "ls /boot/EFI/BOOT/bootx64.efi | wc -l" 1191 status, output = qemu.run_serial(cmd) 1192 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1193 self.assertEqual(output, '1') 1194 # Check that /boot has EFI/Linux/linux.efi (required for Unified Kernel Images auto detection) 1195 cmd = "ls /boot/EFI/Linux/linux.efi | wc -l" 1196 status, output = qemu.run_serial(cmd) 1197 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1198 self.assertEqual(output, '1') 1199 # Check that /boot doesn't have loader/entries/boot.conf (Unified Kernel Images are auto detected by the bootloader) 1200 cmd = "ls /boot/loader/entries/boot.conf 2&>/dev/null | wc -l" 1201 status, output = qemu.run_serial(cmd) 1202 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1203 self.assertEqual(output, '0') 1204 1205 def test_fs_types(self): 1206 """Test filesystem types for empty and not empty partitions""" 1207 img = 'core-image-minimal' 1208 with NamedTemporaryFile("w", suffix=".wks") as wks: 1209 wks.writelines(['part ext2 --fstype ext2 --source rootfs\n', 1210 'part btrfs --fstype btrfs --source rootfs --size 40M\n', 1211 'part squash --fstype squashfs --source rootfs\n', 1212 'part swap --fstype swap --size 1M\n', 1213 'part emptyvfat --fstype vfat --size 1M\n', 1214 'part emptymsdos --fstype msdos --size 1M\n', 1215 'part emptyext2 --fstype ext2 --size 1M\n', 1216 'part emptybtrfs --fstype btrfs --size 150M\n']) 1217 wks.flush() 1218 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir) 1219 runCmd(cmd) 1220 wksname = os.path.splitext(os.path.basename(wks.name))[0] 1221 out = glob(os.path.join(self.resultdir, "%s-*direct" % wksname)) 1222 self.assertEqual(1, len(out)) 1223 1224 def test_kickstart_parser(self): 1225 """Test wks parser options""" 1226 with NamedTemporaryFile("w", suffix=".wks") as wks: 1227 wks.writelines(['part / --fstype ext3 --source rootfs --system-id 0xFF '\ 1228 '--overhead-factor 1.2 --size 100k\n']) 1229 wks.flush() 1230 cmd = "wic create %s -e core-image-minimal -o %s" % (wks.name, self.resultdir) 1231 runCmd(cmd) 1232 wksname = os.path.splitext(os.path.basename(wks.name))[0] 1233 out = glob(os.path.join(self.resultdir, "%s-*direct" % wksname)) 1234 self.assertEqual(1, len(out)) 1235 1236 def test_image_bootpart_globbed(self): 1237 """Test globbed sources with image-bootpart plugin""" 1238 img = "core-image-minimal" 1239 cmd = "wic create sdimage-bootpart -e %s -o %s" % (img, self.resultdir) 1240 config = 'IMAGE_BOOT_FILES = "%s*"' % get_bb_var('KERNEL_IMAGETYPE', img) 1241 self.append_config(config) 1242 runCmd(cmd) 1243 self.remove_config(config) 1244 self.assertEqual(1, len(glob(os.path.join(self.resultdir, "sdimage-bootpart-*direct")))) 1245 1246 def test_sparse_copy(self): 1247 """Test sparse_copy with FIEMAP and SEEK_HOLE filemap APIs""" 1248 libpath = os.path.join(self.td['COREBASE'], 'scripts', 'lib', 'wic') 1249 sys.path.insert(0, libpath) 1250 from filemap import FilemapFiemap, FilemapSeek, sparse_copy, ErrorNotSupp 1251 with NamedTemporaryFile("w", suffix=".wic-sparse") as sparse: 1252 src_name = sparse.name 1253 src_size = 1024 * 10 1254 sparse.truncate(src_size) 1255 # write one byte to the file 1256 with open(src_name, 'r+b') as sfile: 1257 sfile.seek(1024 * 4) 1258 sfile.write(b'\x00') 1259 dest = sparse.name + '.out' 1260 # copy src file to dest using different filemap APIs 1261 for api in (FilemapFiemap, FilemapSeek, None): 1262 if os.path.exists(dest): 1263 os.unlink(dest) 1264 try: 1265 sparse_copy(sparse.name, dest, api=api) 1266 except ErrorNotSupp: 1267 continue # skip unsupported API 1268 dest_stat = os.stat(dest) 1269 self.assertEqual(dest_stat.st_size, src_size) 1270 # 8 blocks is 4K (physical sector size) 1271 self.assertEqual(dest_stat.st_blocks, 8) 1272 os.unlink(dest) 1273 1274 def test_mkfs_extraopts(self): 1275 """Test wks option --mkfs-extraopts for empty and not empty partitions""" 1276 img = 'core-image-minimal' 1277 with NamedTemporaryFile("w", suffix=".wks") as wks: 1278 wks.writelines( 1279 ['part ext2 --fstype ext2 --source rootfs --mkfs-extraopts "-D -F -i 8192"\n', 1280 "part btrfs --fstype btrfs --source rootfs --size 40M --mkfs-extraopts='--quiet'\n", 1281 'part squash --fstype squashfs --source rootfs --mkfs-extraopts "-no-sparse -b 4096"\n', 1282 'part emptyvfat --fstype vfat --size 1M --mkfs-extraopts "-S 1024 -s 64"\n', 1283 'part emptymsdos --fstype msdos --size 1M --mkfs-extraopts "-S 1024 -s 64"\n', 1284 'part emptyext2 --fstype ext2 --size 1M --mkfs-extraopts "-D -F -i 8192"\n', 1285 'part emptybtrfs --fstype btrfs --size 100M --mkfs-extraopts "--mixed -K"\n']) 1286 wks.flush() 1287 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir) 1288 runCmd(cmd) 1289 wksname = os.path.splitext(os.path.basename(wks.name))[0] 1290 out = glob(os.path.join(self.resultdir, "%s-*direct" % wksname)) 1291 self.assertEqual(1, len(out)) 1292 1293 @skipIfNotArch(['i586', 'i686', 'x86_64']) 1294 @OETestTag("runqemu") 1295 def test_expand_mbr_image(self): 1296 """Test wic write --expand command for mbr image""" 1297 # build an image 1298 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "directdisk.wks"\n' 1299 self.append_config(config) 1300 bitbake('core-image-minimal') 1301 1302 # get path to the image 1303 deploy_dir = get_bb_var('DEPLOY_DIR_IMAGE') 1304 machine = self.td['MACHINE'] 1305 image_path = os.path.join(deploy_dir, 'core-image-minimal-%s.wic' % machine) 1306 1307 self.remove_config(config) 1308 1309 try: 1310 # expand image to 1G 1311 new_image_path = None 1312 with NamedTemporaryFile(mode='wb', suffix='.wic.exp', 1313 dir=deploy_dir, delete=False) as sparse: 1314 sparse.truncate(1024 ** 3) 1315 new_image_path = sparse.name 1316 1317 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1318 cmd = "wic write -n %s --expand 1:0 %s %s" % (sysroot, image_path, new_image_path) 1319 runCmd(cmd) 1320 1321 # check if partitions are expanded 1322 orig = runCmd("wic ls %s -n %s" % (image_path, sysroot)) 1323 exp = runCmd("wic ls %s -n %s" % (new_image_path, sysroot)) 1324 orig_sizes = [int(line.split()[3]) for line in orig.output.split('\n')[1:]] 1325 exp_sizes = [int(line.split()[3]) for line in exp.output.split('\n')[1:]] 1326 self.assertEqual(orig_sizes[0], exp_sizes[0]) # first partition is not resized 1327 self.assertTrue(orig_sizes[1] < exp_sizes[1]) 1328 1329 # Check if all free space is partitioned 1330 result = runCmd("%s/usr/sbin/sfdisk -F %s" % (sysroot, new_image_path)) 1331 self.assertTrue("0 B, 0 bytes, 0 sectors" in result.output) 1332 1333 os.rename(image_path, image_path + '.bak') 1334 os.rename(new_image_path, image_path) 1335 1336 # Check if it boots in qemu 1337 with runqemu('core-image-minimal', ssh=False, runqemuparams='nographic') as qemu: 1338 cmd = "ls /etc/" 1339 status, output = qemu.run_serial('true') 1340 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 1341 finally: 1342 if os.path.exists(new_image_path): 1343 os.unlink(new_image_path) 1344 if os.path.exists(image_path + '.bak'): 1345 os.rename(image_path + '.bak', image_path) 1346 1347class ModifyTests(WicTestCase): 1348 def test_wic_ls(self): 1349 """Test listing image content using 'wic ls'""" 1350 runCmd("wic create wictestdisk " 1351 "--image-name=core-image-minimal " 1352 "-D -o %s" % self.resultdir) 1353 images = glob(os.path.join(self.resultdir, "wictestdisk-*.direct")) 1354 self.assertEqual(1, len(images)) 1355 1356 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1357 1358 # list partitions 1359 result = runCmd("wic ls %s -n %s" % (images[0], sysroot)) 1360 self.assertEqual(3, len(result.output.split('\n'))) 1361 1362 # list directory content of the first partition 1363 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot)) 1364 self.assertEqual(6, len(result.output.split('\n'))) 1365 1366 def test_wic_cp(self): 1367 """Test copy files and directories to the the wic image.""" 1368 runCmd("wic create wictestdisk " 1369 "--image-name=core-image-minimal " 1370 "-D -o %s" % self.resultdir) 1371 images = glob(os.path.join(self.resultdir, "wictestdisk-*.direct")) 1372 self.assertEqual(1, len(images)) 1373 1374 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1375 1376 # list directory content of the first partition 1377 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot)) 1378 self.assertEqual(6, len(result.output.split('\n'))) 1379 1380 with NamedTemporaryFile("w", suffix=".wic-cp") as testfile: 1381 testfile.write("test") 1382 1383 # copy file to the partition 1384 runCmd("wic cp %s %s:1/ -n %s" % (testfile.name, images[0], sysroot)) 1385 1386 # check if file is there 1387 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot)) 1388 self.assertEqual(7, len(result.output.split('\n'))) 1389 self.assertTrue(os.path.basename(testfile.name) in result.output) 1390 1391 # prepare directory 1392 testdir = os.path.join(self.resultdir, 'wic-test-cp-dir') 1393 testsubdir = os.path.join(testdir, 'subdir') 1394 os.makedirs(os.path.join(testsubdir)) 1395 copy(testfile.name, testdir) 1396 1397 # copy directory to the partition 1398 runCmd("wic cp %s %s:1/ -n %s" % (testdir, images[0], sysroot)) 1399 1400 # check if directory is there 1401 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot)) 1402 self.assertEqual(8, len(result.output.split('\n'))) 1403 self.assertTrue(os.path.basename(testdir) in result.output) 1404 1405 # copy the file from the partition and check if it success 1406 dest = '%s-cp' % testfile.name 1407 runCmd("wic cp %s:1/%s %s -n %s" % (images[0], 1408 os.path.basename(testfile.name), dest, sysroot)) 1409 self.assertTrue(os.path.exists(dest)) 1410 1411 1412 def test_wic_rm(self): 1413 """Test removing files and directories from the the wic image.""" 1414 runCmd("wic create mkefidisk " 1415 "--image-name=core-image-minimal " 1416 "-D -o %s" % self.resultdir) 1417 images = glob(os.path.join(self.resultdir, "mkefidisk-*.direct")) 1418 self.assertEqual(1, len(images)) 1419 1420 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1421 # Not bulletproof but hopefully sufficient 1422 kerneltype = get_bb_var('KERNEL_IMAGETYPE', 'virtual/kernel') 1423 1424 # list directory content of the first partition 1425 result = runCmd("wic ls %s:1 -n %s" % (images[0], sysroot)) 1426 self.assertIn('\n%s ' % kerneltype.upper(), result.output) 1427 self.assertIn('\nEFI <DIR> ', result.output) 1428 1429 # remove file. EFI partitions are case-insensitive so exercise that too 1430 runCmd("wic rm %s:1/%s -n %s" % (images[0], kerneltype.lower(), sysroot)) 1431 1432 # remove directory 1433 runCmd("wic rm %s:1/efi -n %s" % (images[0], sysroot)) 1434 1435 # check if they're removed 1436 result = runCmd("wic ls %s:1 -n %s" % (images[0], sysroot)) 1437 self.assertNotIn('\n%s ' % kerneltype.upper(), result.output) 1438 self.assertNotIn('\nEFI <DIR> ', result.output) 1439 1440 def test_wic_ls_ext(self): 1441 """Test listing content of the ext partition using 'wic ls'""" 1442 runCmd("wic create wictestdisk " 1443 "--image-name=core-image-minimal " 1444 "-D -o %s" % self.resultdir) 1445 images = glob(os.path.join(self.resultdir, "wictestdisk-*.direct")) 1446 self.assertEqual(1, len(images)) 1447 1448 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1449 1450 # list directory content of the second ext4 partition 1451 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot)) 1452 self.assertTrue(set(['bin', 'home', 'proc', 'usr', 'var', 'dev', 'lib', 'sbin']).issubset( 1453 set(line.split()[-1] for line in result.output.split('\n') if line))) 1454 1455 def test_wic_cp_ext(self): 1456 """Test copy files and directories to the ext partition.""" 1457 runCmd("wic create wictestdisk " 1458 "--image-name=core-image-minimal " 1459 "-D -o %s" % self.resultdir) 1460 images = glob(os.path.join(self.resultdir, "wictestdisk-*.direct")) 1461 self.assertEqual(1, len(images)) 1462 1463 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1464 1465 # list directory content of the ext4 partition 1466 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot)) 1467 dirs = set(line.split()[-1] for line in result.output.split('\n') if line) 1468 self.assertTrue(set(['bin', 'home', 'proc', 'usr', 'var', 'dev', 'lib', 'sbin']).issubset(dirs)) 1469 1470 with NamedTemporaryFile("w", suffix=".wic-cp") as testfile: 1471 testfile.write("test") 1472 1473 # copy file to the partition 1474 runCmd("wic cp %s %s:2/ -n %s" % (testfile.name, images[0], sysroot)) 1475 1476 # check if file is there 1477 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot)) 1478 newdirs = set(line.split()[-1] for line in result.output.split('\n') if line) 1479 self.assertEqual(newdirs.difference(dirs), set([os.path.basename(testfile.name)])) 1480 1481 # check if the file to copy is in the partition 1482 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot)) 1483 self.assertTrue('fstab' in [line.split()[-1] for line in result.output.split('\n') if line]) 1484 1485 # copy file from the partition, replace the temporary file content with it and 1486 # check for the file size to validate the copy 1487 runCmd("wic cp %s:2/etc/fstab %s -n %s" % (images[0], testfile.name, sysroot)) 1488 self.assertTrue(os.stat(testfile.name).st_size > 0) 1489 1490 1491 def test_wic_rm_ext(self): 1492 """Test removing files from the ext partition.""" 1493 runCmd("wic create mkefidisk " 1494 "--image-name=core-image-minimal " 1495 "-D -o %s" % self.resultdir) 1496 images = glob(os.path.join(self.resultdir, "mkefidisk-*.direct")) 1497 self.assertEqual(1, len(images)) 1498 1499 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') 1500 1501 # list directory content of the /etc directory on ext4 partition 1502 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot)) 1503 self.assertTrue('fstab' in [line.split()[-1] for line in result.output.split('\n') if line]) 1504 1505 # remove file 1506 runCmd("wic rm %s:2/etc/fstab -n %s" % (images[0], sysroot)) 1507 1508 # check if it's removed 1509 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot)) 1510 self.assertTrue('fstab' not in [line.split()[-1] for line in result.output.split('\n') if line]) 1511 1512 # remove non-empty directory 1513 runCmd("wic rm -r %s:2/etc/ -n %s" % (images[0], sysroot)) 1514 1515 # check if it's removed 1516 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot)) 1517 self.assertTrue('etc' not in [line.split()[-1] for line in result.output.split('\n') if line]) 1518