diff options
Diffstat (limited to 'meta/lib/oeqa/selftest/cases/wic.py')
-rw-r--r-- | meta/lib/oeqa/selftest/cases/wic.py | 568 |
1 files changed, 505 insertions, 63 deletions
diff --git a/meta/lib/oeqa/selftest/cases/wic.py b/meta/lib/oeqa/selftest/cases/wic.py index ea75300406..dc7b9e637e 100644 --- a/meta/lib/oeqa/selftest/cases/wic.py +++ b/meta/lib/oeqa/selftest/cases/wic.py @@ -11,6 +11,7 @@ import os import sys import unittest +import hashlib from glob import glob from shutil import rmtree, copy @@ -44,6 +45,30 @@ def only_for_arch(archs, image='core-image-minimal'): return wrapped_f return wrapper +def extract_files(debugfs_output): + """ + extract file names from the output of debugfs -R 'ls -p', + which looks like this: + + /2/040755/0/0/.//\n + /2/040755/0/0/..//\n + /11/040700/0/0/lost+found^M//\n + /12/040755/1002/1002/run//\n + /13/040755/1002/1002/sys//\n + /14/040755/1002/1002/bin//\n + /80/040755/1002/1002/var//\n + /92/040755/1002/1002/tmp//\n + """ + # NOTE the occasional ^M in file names + return [line.split('/')[5].strip() for line in \ + debugfs_output.strip().split('/\n')] + +def files_own_by_root(debugfs_output): + for line in debugfs_output.strip().split('/\n'): + if line.split('/')[3:5] != ['0', '0']: + print(debugfs_output) + return False + return True class WicTestCase(OESelftestTestCase): """Wic test class.""" @@ -66,6 +91,7 @@ class WicTestCase(OESelftestTestCase): self.skipTest('wic-tools cannot be built due its (intltool|gettext)-native dependency and NLS disable') bitbake('core-image-minimal') + bitbake('core-image-minimal-mtdutils') WicTestCase.image_is_ready = True rmtree(self.resultdir, ignore_errors=True) @@ -164,8 +190,8 @@ class Wic(WicTestCase): def test_iso_image(self): """Test creation of hybrid iso image with legacy and EFI boot""" config = 'INITRAMFS_IMAGE = "core-image-minimal-initramfs"\n'\ - 'MACHINE_FEATURES_append = " efi"\n'\ - 'DEPENDS_pn-core-image-minimal += "syslinux"\n' + 'MACHINE_FEATURES:append = " efi"\n'\ + 'DEPENDS:pn-core-image-minimal += "syslinux"\n' self.append_config(config) bitbake('core-image-minimal core-image-minimal-initramfs') self.remove_config(config) @@ -191,7 +217,7 @@ class Wic(WicTestCase): @only_for_arch(['i586', 'i686', 'x86_64']) def test_bootloader_config(self): """Test creation of directdisk-bootloader-config image""" - config = 'DEPENDS_pn-core-image-minimal += "syslinux"\n' + config = 'DEPENDS:pn-core-image-minimal += "syslinux"\n' self.append_config(config) bitbake('core-image-minimal') self.remove_config(config) @@ -202,7 +228,7 @@ class Wic(WicTestCase): @only_for_arch(['i586', 'i686', 'x86_64']) def test_systemd_bootdisk(self): """Test creation of systemd-bootdisk image""" - config = 'MACHINE_FEATURES_append = " efi"\n' + config = 'MACHINE_FEATURES:append = " efi"\n' self.append_config(config) bitbake('core-image-minimal') self.remove_config(config) @@ -210,6 +236,17 @@ class Wic(WicTestCase): runCmd(cmd) self.assertEqual(1, len(glob(self.resultdir + "systemd-bootdisk-*direct"))) + def test_efi_bootpart(self): + """Test creation of efi-bootpart image""" + cmd = "wic create mkefidisk -e core-image-minimal -o %s" % self.resultdir + kimgtype = get_bb_var('KERNEL_IMAGETYPE', 'core-image-minimal') + self.append_config('IMAGE_EFI_BOOT_FILES = "%s;kernel"\n' % kimgtype) + runCmd(cmd) + sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') + images = glob(self.resultdir + "mkefidisk-*.direct") + result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot)) + self.assertIn("kernel",result.output) + def test_sdimage_bootpart(self): """Test creation of sdimage-bootpart image""" cmd = "wic create sdimage-bootpart -e core-image-minimal -o %s" % self.resultdir @@ -223,7 +260,7 @@ class Wic(WicTestCase): """Test default output location""" for fname in glob("directdisk-*.direct"): os.remove(fname) - config = 'DEPENDS_pn-core-image-minimal += "syslinux"\n' + config = 'DEPENDS:pn-core-image-minimal += "syslinux"\n' self.append_config(config) bitbake('core-image-minimal') self.remove_config(config) @@ -282,6 +319,7 @@ class Wic(WicTestCase): "--image-name=core-image-minimal " "-D -o %s" % self.resultdir) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct"))) + self.assertEqual(1, len(glob(self.resultdir + "tmp.wic*"))) def test_debug_long(self): """Test --debug option""" @@ -289,6 +327,7 @@ class Wic(WicTestCase): "--image-name=core-image-minimal " "--debug -o %s" % self.resultdir) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct"))) + self.assertEqual(1, len(glob(self.resultdir + "tmp.wic*"))) def test_skip_build_check_short(self): """Test -s option""" @@ -393,24 +432,6 @@ part /etc --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path bin/ --r runCmd("dd if=%s of=%s skip=%d count=%d" % (wicimg, part_file, start, length)) - def extract_files(debugfs_output): - """ - extract file names from the output of debugfs -R 'ls -p', - which looks like this: - - /2/040755/0/0/.//\n - /2/040755/0/0/..//\n - /11/040700/0/0/lost+found^M//\n - /12/040755/1002/1002/run//\n - /13/040755/1002/1002/sys//\n - /14/040755/1002/1002/bin//\n - /80/040755/1002/1002/var//\n - /92/040755/1002/1002/tmp//\n - """ - # NOTE the occasional ^M in file names - return [line.split('/')[5].strip() for line in \ - debugfs_output.strip().split('/\n')] - # Test partition 1, should contain the normal root directories, except # /usr. res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \ @@ -451,6 +472,104 @@ part /etc --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path bin/ --r finally: os.environ['PATH'] = oldpath + def test_include_path(self): + """Test --include-path wks option.""" + + oldpath = os.environ['PATH'] + os.environ['PATH'] = get_bb_var("PATH", "wic-tools") + + try: + include_path = os.path.join(self.resultdir, 'test-include') + os.makedirs(include_path) + with open(os.path.join(include_path, 'test-file'), 'w') as t: + t.write("test\n") + wks_file = os.path.join(include_path, 'temp.wks') + with open(wks_file, 'w') as wks: + rootfs_dir = get_bb_var('IMAGE_ROOTFS', 'core-image-minimal') + wks.write(""" +part /part1 --source rootfs --ondisk mmcblk0 --fstype=ext4 +part /part2 --source rootfs --ondisk mmcblk0 --fstype=ext4 --include-path %s""" + % (include_path)) + runCmd("wic create %s -e core-image-minimal -o %s" \ + % (wks_file, self.resultdir)) + + part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0] + part2 = glob(os.path.join(self.resultdir, 'temp-*.direct.p2'))[0] + + # Test partition 1, should not contain 'test-file' + res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1)) + files = extract_files(res.output) + self.assertNotIn('test-file', files) + self.assertEqual(True, files_own_by_root(res.output)) + + # Test partition 2, should contain 'test-file' + res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part2)) + files = extract_files(res.output) + self.assertIn('test-file', files) + self.assertEqual(True, files_own_by_root(res.output)) + + finally: + os.environ['PATH'] = oldpath + + def test_include_path_embeded(self): + """Test --include-path wks option.""" + + oldpath = os.environ['PATH'] + os.environ['PATH'] = get_bb_var("PATH", "wic-tools") + + try: + include_path = os.path.join(self.resultdir, 'test-include') + os.makedirs(include_path) + with open(os.path.join(include_path, 'test-file'), 'w') as t: + t.write("test\n") + wks_file = os.path.join(include_path, 'temp.wks') + with open(wks_file, 'w') as wks: + wks.write(""" +part / --source rootfs --fstype=ext4 --include-path %s --include-path core-image-minimal-mtdutils export/""" + % (include_path)) + runCmd("wic create %s -e core-image-minimal -o %s" \ + % (wks_file, self.resultdir)) + + part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0] + + res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1)) + files = extract_files(res.output) + self.assertIn('test-file', files) + self.assertEqual(True, files_own_by_root(res.output)) + + res = runCmd("debugfs -R 'ls -p /export/etc/' %s 2>/dev/null" % (part1)) + files = extract_files(res.output) + self.assertIn('passwd', files) + self.assertEqual(True, files_own_by_root(res.output)) + + finally: + os.environ['PATH'] = oldpath + + def test_include_path_errors(self): + """Test --include-path wks option error handling.""" + wks_file = 'temp.wks' + + # Absolute argument. + with open(wks_file, 'w') as wks: + wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils /export") + self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ + % (wks_file, self.resultdir), ignore_status=True).status) + os.remove(wks_file) + + # Argument pointing to parent directory. + with open(wks_file, 'w') as wks: + wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils ././..") + self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ + % (wks_file, self.resultdir), ignore_status=True).status) + os.remove(wks_file) + + # 3 Argument pointing to parent directory. + with open(wks_file, 'w') as wks: + wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils export/ dummy") + self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ + % (wks_file, self.resultdir), ignore_status=True).status) + os.remove(wks_file) + def test_exclude_path_errors(self): """Test --exclude-path wks option error handling.""" wks_file = 'temp.wks' @@ -469,6 +588,173 @@ part /etc --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path bin/ --r % (wks_file, self.resultdir), ignore_status=True).status) os.remove(wks_file) + def test_permissions(self): + """Test permissions are respected""" + + # prepare wicenv and rootfs + bitbake('core-image-minimal core-image-minimal-mtdutils -c do_rootfs_wicenv') + + oldpath = os.environ['PATH'] + os.environ['PATH'] = get_bb_var("PATH", "wic-tools") + + t_normal = """ +part / --source rootfs --fstype=ext4 +""" + t_exclude = """ +part / --source rootfs --fstype=ext4 --exclude-path=home +""" + t_multi = """ +part / --source rootfs --ondisk sda --fstype=ext4 +part /export --source rootfs --rootfs=core-image-minimal-mtdutils --fstype=ext4 +""" + t_change = """ +part / --source rootfs --ondisk sda --fstype=ext4 --exclude-path=etc/ +part /etc --source rootfs --fstype=ext4 --change-directory=etc +""" + tests = [t_normal, t_exclude, t_multi, t_change] + + try: + for test in tests: + include_path = os.path.join(self.resultdir, 'test-include') + os.makedirs(include_path) + wks_file = os.path.join(include_path, 'temp.wks') + with open(wks_file, 'w') as wks: + wks.write(test) + runCmd("wic create %s -e core-image-minimal -o %s" \ + % (wks_file, self.resultdir)) + + for part in glob(os.path.join(self.resultdir, 'temp-*.direct.p*')): + res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part)) + self.assertEqual(True, files_own_by_root(res.output)) + + config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "%s"\n' % wks_file + self.append_config(config) + bitbake('core-image-minimal') + tmpdir = os.path.join(get_bb_var('WORKDIR', 'core-image-minimal'),'build-wic') + + # check each partition for permission + for part in glob(os.path.join(tmpdir, 'temp-*.direct.p*')): + res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part)) + self.assertTrue(files_own_by_root(res.output) + ,msg='Files permission incorrect using wks set "%s"' % test) + + # clean config and result directory for next cases + self.remove_config(config) + rmtree(self.resultdir, ignore_errors=True) + + finally: + os.environ['PATH'] = oldpath + + def test_change_directory(self): + """Test --change-directory wks option.""" + + oldpath = os.environ['PATH'] + os.environ['PATH'] = get_bb_var("PATH", "wic-tools") + + try: + include_path = os.path.join(self.resultdir, 'test-include') + os.makedirs(include_path) + wks_file = os.path.join(include_path, 'temp.wks') + with open(wks_file, 'w') as wks: + wks.write("part /etc --source rootfs --fstype=ext4 --change-directory=etc") + runCmd("wic create %s -e core-image-minimal -o %s" \ + % (wks_file, self.resultdir)) + + part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0] + + res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1)) + files = extract_files(res.output) + self.assertIn('passwd', files) + + finally: + os.environ['PATH'] = oldpath + + def test_change_directory_errors(self): + """Test --change-directory wks option error handling.""" + wks_file = 'temp.wks' + + # Absolute argument. + with open(wks_file, 'w') as wks: + wks.write("part / --source rootfs --fstype=ext4 --change-directory /usr") + self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ + % (wks_file, self.resultdir), ignore_status=True).status) + os.remove(wks_file) + + # Argument pointing to parent directory. + with open(wks_file, 'w') as wks: + wks.write("part / --source rootfs --fstype=ext4 --change-directory ././..") + self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ + % (wks_file, self.resultdir), ignore_status=True).status) + os.remove(wks_file) + + def test_no_fstab_update(self): + """Test --no-fstab-update wks option.""" + + oldpath = os.environ['PATH'] + os.environ['PATH'] = get_bb_var("PATH", "wic-tools") + + # Get stock fstab from base-files recipe + self.assertEqual(0, bitbake('base-files -c do_install').status) + bf_fstab = os.path.join(get_bb_var('D', 'base-files'), 'etc/fstab') + self.assertEqual(True, os.path.exists(bf_fstab)) + bf_fstab_md5sum = runCmd('md5sum %s 2>/dev/null' % bf_fstab).output.split(" ")[0] + + try: + no_fstab_update_path = os.path.join(self.resultdir, 'test-no-fstab-update') + os.makedirs(no_fstab_update_path) + wks_file = os.path.join(no_fstab_update_path, 'temp.wks') + with open(wks_file, 'w') as wks: + wks.writelines(['part / --source rootfs --fstype=ext4 --label rootfs\n', + 'part /mnt/p2 --source rootfs --rootfs-dir=core-image-minimal ', + '--fstype=ext4 --label p2 --no-fstab-update\n']) + runCmd("wic create %s -e core-image-minimal -o %s" \ + % (wks_file, self.resultdir)) + + part_fstab_md5sum = [] + for i in range(1, 3): + part = glob(os.path.join(self.resultdir, 'temp-*.direct.p') + str(i))[0] + part_fstab = runCmd("debugfs -R 'cat etc/fstab' %s 2>/dev/null" % (part)) + part_fstab_md5sum.append(hashlib.md5((part_fstab.output + "\n\n").encode('utf-8')).hexdigest()) + + # '/etc/fstab' in partition 2 should contain the same stock fstab file + # as the one installed by the base-file recipe. + self.assertEqual(bf_fstab_md5sum, part_fstab_md5sum[1]) + + # '/etc/fstab' in partition 1 should contain an updated fstab file. + self.assertNotEqual(bf_fstab_md5sum, part_fstab_md5sum[0]) + + finally: + os.environ['PATH'] = oldpath + + def test_no_fstab_update_errors(self): + """Test --no-fstab-update wks option error handling.""" + wks_file = 'temp.wks' + + # Absolute argument. + with open(wks_file, 'w') as wks: + wks.write("part / --source rootfs --fstype=ext4 --no-fstab-update /etc") + self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ + % (wks_file, self.resultdir), ignore_status=True).status) + os.remove(wks_file) + + # Argument pointing to parent directory. + with open(wks_file, 'w') as wks: + wks.write("part / --source rootfs --fstype=ext4 --no-fstab-update ././..") + self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \ + % (wks_file, self.resultdir), ignore_status=True).status) + os.remove(wks_file) + + def test_extra_space(self): + """Test --extra-space wks option.""" + extraspace = 1024**3 + runCmd("wic create wictestdisk " + "--image-name core-image-minimal " + "--extra-space %i -o %s" % (extraspace ,self.resultdir)) + wicout = glob(self.resultdir + "wictestdisk-*.direct") + self.assertEqual(1, len(wicout)) + size = os.path.getsize(wicout[0]) + self.assertTrue(size > extraspace) + class Wic2(WicTestCase): def test_bmap_short(self): @@ -500,7 +786,8 @@ class Wic2(WicTestCase): # filter out optional variables wicvars = wicvars.difference(('DEPLOY_DIR_IMAGE', 'IMAGE_BOOT_FILES', 'INITRD', 'INITRD_LIVE', 'ISODIR','INITRAMFS_IMAGE', - 'INITRAMFS_IMAGE_BUNDLE', 'INITRAMFS_LINK_NAME')) + 'INITRAMFS_IMAGE_BUNDLE', 'INITRAMFS_LINK_NAME', + 'APPEND', 'IMAGE_EFI_BOOT_FILES')) with open(path) as envfile: content = dict(line.split("=", 1) for line in envfile) # test if variables used by wic present in the .env file @@ -539,7 +826,7 @@ class Wic2(WicTestCase): def test_wic_image_type(self): """Test building wic images by bitbake""" config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\ - 'MACHINE_FEATURES_append = " efi"\n' + 'MACHINE_FEATURES:append = " efi"\n' self.append_config(config) self.assertEqual(0, bitbake('wic-image-minimal').status) self.remove_config(config) @@ -559,7 +846,7 @@ class Wic2(WicTestCase): def test_qemu(self): """Test wic-image-minimal under qemu""" config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\ - 'MACHINE_FEATURES_append = " efi"\n' + 'MACHINE_FEATURES:append = " efi"\n' self.append_config(config) self.assertEqual(0, bitbake('wic-image-minimal').status) self.remove_config(config) @@ -601,41 +888,50 @@ class Wic2(WicTestCase): tempf.write("part " \ "--source rootfs --ondisk hda --align 4 --fixed-size %d " "--fstype=ext4\n" % size) - wksname = os.path.splitext(os.path.basename(wkspath))[0] - return wkspath, wksname + return wkspath - def test_fixed_size(self): - """ - Test creation of a simple image with partition size controlled through - --fixed-size flag - """ - wkspath, wksname = Wic2._make_fixed_size_wks(200) + def _get_wic_partitions(self, wkspath, native_sysroot=None, ignore_status=False): + p = runCmd("wic create %s -e core-image-minimal -o %s" % (wkspath, self.resultdir), + ignore_status=ignore_status) + + if p.status: + return (p, None) + + wksname = os.path.splitext(os.path.basename(wkspath))[0] - runCmd("wic create %s -e core-image-minimal -o %s" \ - % (wkspath, self.resultdir)) - os.remove(wkspath) wicout = glob(self.resultdir + "%s-*direct" % wksname) - self.assertEqual(1, len(wicout)) + + if not wicout: + return (p, None) wicimg = wicout[0] - native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") + if not native_sysroot: + native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") # verify partition size with wic - res = runCmd("parted -m %s unit mib p 2>/dev/null" % wicimg, + res = runCmd("parted -m %s unit kib p 2>/dev/null" % wicimg, native_sysroot=native_sysroot) # parse parted output which looks like this: # BYT;\n # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n # 1:0.00MiB:200MiB:200MiB:ext4::;\n - partlns = res.output.splitlines()[2:] + return (p, res.output.splitlines()[2:]) + + def test_fixed_size(self): + """ + Test creation of a simple image with partition size controlled through + --fixed-size flag + """ + wkspath = Wic2._make_fixed_size_wks(200) + _, partlns = self._get_wic_partitions(wkspath) + os.remove(wkspath) - self.assertEqual(1, len(partlns), - msg="Partition list '%s'" % res.output) - self.assertEqual("1:0.00MiB:200MiB:200MiB:ext4::;", partlns[0], - msg="Partition list '%s'" % res.output) + self.assertEqual(partlns, [ + "1:4.00kiB:204804kiB:204800kiB:ext4::;", + ]) def test_fixed_size_error(self): """ @@ -643,25 +939,127 @@ class Wic2(WicTestCase): --fixed-size flag. The size of partition is intentionally set to 1MiB in order to trigger an error in wic. """ - wkspath, wksname = Wic2._make_fixed_size_wks(1) - - self.assertEqual(1, runCmd("wic create %s -e core-image-minimal -o %s" \ - % (wkspath, self.resultdir), ignore_status=True).status) + wkspath = Wic2._make_fixed_size_wks(1) + p, _ = self._get_wic_partitions(wkspath, ignore_status=True) os.remove(wkspath) - wicout = glob(self.resultdir + "%s-*direct" % wksname) - self.assertEqual(0, len(wicout)) + + self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output) + + def test_offset(self): + native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") + + with NamedTemporaryFile("w", suffix=".wks") as tempf: + # Test that partitions are placed at the correct offsets, default KB + tempf.write("bootloader --ptable gpt\n" \ + "part / --source rootfs --ondisk hda --offset 32 --fixed-size 100M --fstype=ext4\n" \ + "part /bar --ondisk hda --offset 102432 --fixed-size 100M --fstype=ext4\n") + tempf.flush() + + _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) + self.assertEqual(partlns, [ + "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;", + "2:102432kiB:204832kiB:102400kiB:ext4:primary:;", + ]) + + with NamedTemporaryFile("w", suffix=".wks") as tempf: + # Test that partitions are placed at the correct offsets, same with explicit KB + tempf.write("bootloader --ptable gpt\n" \ + "part / --source rootfs --ondisk hda --offset 32K --fixed-size 100M --fstype=ext4\n" \ + "part /bar --ondisk hda --offset 102432K --fixed-size 100M --fstype=ext4\n") + tempf.flush() + + _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) + self.assertEqual(partlns, [ + "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;", + "2:102432kiB:204832kiB:102400kiB:ext4:primary:;", + ]) + + with NamedTemporaryFile("w", suffix=".wks") as tempf: + # Test that partitions are placed at the correct offsets using MB + tempf.write("bootloader --ptable gpt\n" \ + "part / --source rootfs --ondisk hda --offset 32K --fixed-size 100M --fstype=ext4\n" \ + "part /bar --ondisk hda --offset 101M --fixed-size 100M --fstype=ext4\n") + tempf.flush() + + _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) + self.assertEqual(partlns, [ + "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;", + "2:103424kiB:205824kiB:102400kiB:ext4:primary:;", + ]) + + with NamedTemporaryFile("w", suffix=".wks") as tempf: + # Test that partitions can be placed on a 512 byte sector boundary + tempf.write("bootloader --ptable gpt\n" \ + "part / --source rootfs --ondisk hda --offset 65s --fixed-size 99M --fstype=ext4\n" \ + "part /bar --ondisk hda --offset 102432 --fixed-size 100M --fstype=ext4\n") + tempf.flush() + + _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) + self.assertEqual(partlns, [ + "1:32.5kiB:101408kiB:101376kiB:ext4:primary:;", + "2:102432kiB:204832kiB:102400kiB:ext4:primary:;", + ]) + + with NamedTemporaryFile("w", suffix=".wks") as tempf: + # Test that a partition can be placed immediately after a MSDOS partition table + tempf.write("bootloader --ptable msdos\n" \ + "part / --source rootfs --ondisk hda --offset 1s --fixed-size 100M --fstype=ext4\n") + tempf.flush() + + _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) + self.assertEqual(partlns, [ + "1:0.50kiB:102400kiB:102400kiB:ext4::;", + ]) + + with NamedTemporaryFile("w", suffix=".wks") as tempf: + # Test that image creation fails if the partitions would overlap + tempf.write("bootloader --ptable gpt\n" \ + "part / --source rootfs --ondisk hda --offset 32 --fixed-size 100M --fstype=ext4\n" \ + "part /bar --ondisk hda --offset 102431 --fixed-size 100M --fstype=ext4\n") + tempf.flush() + + p, _ = self._get_wic_partitions(tempf.name, ignore_status=True) + self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output) + + with NamedTemporaryFile("w", suffix=".wks") as tempf: + # Test that partitions are not allowed to overlap with the booloader + tempf.write("bootloader --ptable gpt\n" \ + "part / --source rootfs --ondisk hda --offset 8 --fixed-size 100M --fstype=ext4\n") + tempf.flush() + + p, _ = self._get_wic_partitions(tempf.name, ignore_status=True) + self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output) + + def test_extra_space(self): + native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools") + + with NamedTemporaryFile("w", suffix=".wks") as tempf: + tempf.write("bootloader --ptable gpt\n" \ + "part / --source rootfs --ondisk hda --extra-space 200M --fstype=ext4\n") + tempf.flush() + + _, partlns = self._get_wic_partitions(tempf.name, native_sysroot) + self.assertEqual(len(partlns), 1) + size = partlns[0].split(':')[3] + self.assertRegex(size, r'^[0-9]+kiB$') + size = int(size[:-3]) + self.assertGreaterEqual(size, 204800) @only_for_arch(['i586', 'i686', 'x86_64']) def test_rawcopy_plugin_qemu(self): """Test rawcopy plugin in qemu""" - # build ext4 and wic images - for fstype in ("ext4", "wic"): - config = 'IMAGE_FSTYPES = "%s"\nWKS_FILE = "test_rawcopy_plugin.wks.in"\n' % fstype - self.append_config(config) - self.assertEqual(0, bitbake('core-image-minimal').status) - self.remove_config(config) + # build ext4 and then use it for a wic image + config = 'IMAGE_FSTYPES = "ext4"\n' + self.append_config(config) + self.assertEqual(0, bitbake('core-image-minimal').status) + self.remove_config(config) - with runqemu('core-image-minimal', ssh=False, image_fstype='wic') as qemu: + config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_rawcopy_plugin.wks.in"\n' + self.append_config(config) + self.assertEqual(0, bitbake('core-image-minimal-mtdutils').status) + self.remove_config(config) + + with runqemu('core-image-minimal-mtdutils', ssh=False, image_fstype='wic') as qemu: cmd = "grep sda. /proc/partitions |wc -l" status, output = qemu.run_serial(cmd) self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) @@ -683,10 +1081,30 @@ class Wic2(WicTestCase): out = glob(self.resultdir + "%s-*direct" % wksname) self.assertEqual(1, len(out)) + def test_empty_plugin(self): + """Test empty plugin""" + config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_empty_plugin.wks"\n' + self.append_config(config) + self.assertEqual(0, bitbake('core-image-minimal').status) + self.remove_config(config) + + bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'MACHINE']) + deploy_dir = bb_vars['DEPLOY_DIR_IMAGE'] + machine = bb_vars['MACHINE'] + image_path = os.path.join(deploy_dir, 'core-image-minimal-%s.wic' % machine) + self.assertEqual(True, os.path.exists(image_path)) + + sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools') + + # Fstype column from 'wic ls' should be empty for the second partition + # as listed in test_empty_plugin.wks + result = runCmd("wic ls %s -n %s | awk -F ' ' '{print $1 \" \" $5}' | grep '^2' | wc -w" % (image_path, sysroot)) + self.assertEqual('1', result.output) + @only_for_arch(['i586', 'i686', 'x86_64']) def test_biosplusefi_plugin_qemu(self): """Test biosplusefi plugin in qemu""" - config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES_append = " efi"\n' + config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES:append = " efi"\n' self.append_config(config) self.assertEqual(0, bitbake('core-image-minimal').status) self.remove_config(config) @@ -723,7 +1141,7 @@ class Wic2(WicTestCase): # If an image hasn't been built yet, directory ${STAGING_DATADIR}/syslinux won't exists and _get_bootimg_dir() # will raise with "Couldn't find correct bootimg_dir" # The easiest way to work-around this issue is to make sure we already built an image here, hence the bitbake call - config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES_append = " efi"\n' + config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES:append = " efi"\n' self.append_config(config) self.assertEqual(0, bitbake('core-image-minimal').status) self.remove_config(config) @@ -866,6 +1284,13 @@ class Wic2(WicTestCase): self.assertEqual(8, len(result.output.split('\n'))) self.assertTrue(os.path.basename(testdir) in result.output) + # copy the file from the partition and check if it success + dest = '%s-cp' % testfile.name + runCmd("wic cp %s:1/%s %s -n %s" % (images[0], + os.path.basename(testfile.name), dest, sysroot)) + self.assertTrue(os.path.exists(dest)) + + def test_wic_rm(self): """Test removing files and directories from the the wic image.""" runCmd("wic create mkefidisk " @@ -950,8 +1375,8 @@ class Wic2(WicTestCase): result = runCmd("%s/usr/sbin/sfdisk -F %s" % (sysroot, new_image_path)) self.assertTrue("0 B, 0 bytes, 0 sectors" in result.output) - os.rename(image_path, image_path + '.bak') - os.rename(new_image_path, image_path) + bb.utils.rename(image_path, image_path + '.bak') + bb.utils.rename(new_image_path, image_path) # Check if it boots in qemu with runqemu('core-image-minimal', ssh=False) as qemu: @@ -962,7 +1387,7 @@ class Wic2(WicTestCase): if os.path.exists(new_image_path): os.unlink(new_image_path) if os.path.exists(image_path + '.bak'): - os.rename(image_path + '.bak', image_path) + bb.utils.rename(image_path + '.bak', image_path) def test_wic_ls_ext(self): """Test listing content of the ext partition using 'wic ls'""" @@ -1005,6 +1430,16 @@ class Wic2(WicTestCase): newdirs = set(line.split()[-1] for line in result.output.split('\n') if line) self.assertEqual(newdirs.difference(dirs), set([os.path.basename(testfile.name)])) + # check if the file to copy is in the partition + result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot)) + self.assertTrue('fstab' in [line.split()[-1] for line in result.output.split('\n') if line]) + + # copy file from the partition, replace the temporary file content with it and + # check for the file size to validate the copy + runCmd("wic cp %s:2/etc/fstab %s -n %s" % (images[0], testfile.name, sysroot)) + self.assertTrue(os.stat(testfile.name).st_size > 0) + + def test_wic_rm_ext(self): """Test removing files from the ext partition.""" runCmd("wic create mkefidisk " @@ -1025,3 +1460,10 @@ class Wic2(WicTestCase): # check if it's removed result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot)) self.assertTrue('fstab' not in [line.split()[-1] for line in result.output.split('\n') if line]) + + # remove non-empty directory + runCmd("wic rm -r %s:2/etc/ -n %s" % (images[0], sysroot)) + + # check if it's removed + result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot)) + self.assertTrue('etc' not in [line.split()[-1] for line in result.output.split('\n') if line]) |