diff options
Diffstat (limited to 'poky/meta/lib/oeqa/selftest')
20 files changed, 520 insertions, 84 deletions
diff --git a/poky/meta/lib/oeqa/selftest/cases/archiver.py b/poky/meta/lib/oeqa/selftest/cases/archiver.py index 606eaabcb..ddd08ecf8 100644 --- a/poky/meta/lib/oeqa/selftest/cases/archiver.py +++ b/poky/meta/lib/oeqa/selftest/cases/archiver.py @@ -19,8 +19,8 @@ class Archiver(OESelftestTestCase): AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com> """ - include_recipe = 'busybox' - exclude_recipe = 'zlib' + include_recipe = 'selftest-ed' + exclude_recipe = 'initscripts' features = 'INHERIT += "archiver"\n' features += 'ARCHIVER_MODE[src] = "original"\n' @@ -51,8 +51,8 @@ class Archiver(OESelftestTestCase): Author: André Draszik <adraszik@tycoint.com> """ - target_recipe = 'initscripts' - native_recipe = 'zlib-native' + target_recipe = 'selftest-ed' + native_recipe = 'selftest-ed-native' features = 'INHERIT += "archiver"\n' features += 'ARCHIVER_MODE[src] = "original"\n' @@ -86,8 +86,8 @@ class Archiver(OESelftestTestCase): Author: André Draszik <adraszik@tycoint.com> """ - target_recipes = [ 'initscripts', 'zlib' ] - native_recipes = [ 'update-rc.d-native', 'zlib-native' ] + target_recipes = [ 'initscripts', 'selftest-ed' ] + native_recipes = [ 'update-rc.d-native', 'selftest-ed-native' ] features = 'INHERIT += "archiver"\n' features += 'ARCHIVER_MODE[src] = "original"\n' @@ -126,12 +126,13 @@ class Archiver(OESelftestTestCase): features = 'INHERIT += "archiver"\n' features += 'ARCHIVER_MODE[srpm] = "1"\n' + features += 'PACKAGE_CLASSES = "package_rpm"\n' self.write_config(features) - bitbake('-n core-image-sato') + bitbake('-n selftest-nopackages selftest-ed') def _test_archiver_mode(self, mode, target_file_name, extra_config=None): - target = "selftest-ed" + target = 'selftest-ed-native' features = 'INHERIT += "archiver"\n' features += 'ARCHIVER_MODE[src] = "%s"\n' % (mode) @@ -142,8 +143,8 @@ class Archiver(OESelftestTestCase): bitbake('-c clean %s' % (target)) bitbake('-c deploy_archives %s' % (target)) - bb_vars = get_bb_vars(['DEPLOY_DIR_SRC', 'TARGET_SYS']) - glob_str = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['TARGET_SYS'], '%s-*' % (target)) + bb_vars = get_bb_vars(['DEPLOY_DIR_SRC', 'BUILD_SYS']) + glob_str = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['BUILD_SYS'], '%s-*' % (target)) glob_result = glob.glob(glob_str) self.assertTrue(glob_result, 'Missing archiver directory for %s' % (target)) @@ -162,21 +163,21 @@ class Archiver(OESelftestTestCase): Test that the archiver works with `ARCHIVER_MODE[src] = "patched"`. """ - self._test_archiver_mode('patched', 'selftest-ed-1.14.1-r0-patched.tar.gz') + self._test_archiver_mode('patched', 'selftest-ed-native-1.14.1-r0-patched.tar.gz') def test_archiver_mode_configured(self): """ Test that the archiver works with `ARCHIVER_MODE[src] = "configured"`. """ - self._test_archiver_mode('configured', 'selftest-ed-1.14.1-r0-configured.tar.gz') + self._test_archiver_mode('configured', 'selftest-ed-native-1.14.1-r0-configured.tar.gz') def test_archiver_mode_recipe(self): """ Test that the archiver works with `ARCHIVER_MODE[recipe] = "1"`. """ - self._test_archiver_mode('patched', 'selftest-ed-1.14.1-r0-recipe.tar.gz', + self._test_archiver_mode('patched', 'selftest-ed-native-1.14.1-r0-recipe.tar.gz', 'ARCHIVER_MODE[recipe] = "1"\n') def test_archiver_mode_diff(self): @@ -185,7 +186,7 @@ class Archiver(OESelftestTestCase): Exclusions controlled by `ARCHIVER_MODE[diff-exclude]` are not yet tested. """ - self._test_archiver_mode('patched', 'selftest-ed-1.14.1-r0-diff.gz', + self._test_archiver_mode('patched', 'selftest-ed-native-1.14.1-r0-diff.gz', 'ARCHIVER_MODE[diff] = "1"\n') def test_archiver_mode_dumpdata(self): @@ -193,7 +194,7 @@ class Archiver(OESelftestTestCase): Test that the archiver works with `ARCHIVER_MODE[dumpdata] = "1"`. """ - self._test_archiver_mode('patched', 'selftest-ed-1.14.1-r0-showdata.dump', + self._test_archiver_mode('patched', 'selftest-ed-native-1.14.1-r0-showdata.dump', 'ARCHIVER_MODE[dumpdata] = "1"\n') def test_archiver_mode_mirror(self): @@ -254,3 +255,57 @@ class Archiver(OESelftestTestCase): glob_str = os.path.join(bb_vars['DEPLOY_DIR_SRC'], 'mirror', target_file_name) glob_result = glob.glob(glob_str) self.assertTrue(glob_result, 'Missing archive file %s' % (target_file_name)) + + def test_archiver_mode_mirror_gitsm(self): + """ + Test that the archiver correctly handles git submodules with + `ARCHIVER_MODE[src] = "mirror"`. + """ + features = 'INHERIT += "archiver"\n' + features += 'ARCHIVER_MODE[src] = "mirror"\n' + features += 'ARCHIVER_MODE[mirror] = "combined"\n' + features += 'BB_GENERATE_MIRROR_TARBALLS = "1"\n' + features += 'COPYLEFT_LICENSE_INCLUDE = "*"\n' + self.write_config(features) + + bitbake('-c clean git-submodule-test') + bitbake('-c deploy_archives -f git-submodule-test') + + bb_vars = get_bb_vars(['DEPLOY_DIR_SRC']) + for target_file_name in [ + 'git2_git.yoctoproject.org.git-submodule-test.tar.gz', + 'git2_git.yoctoproject.org.bitbake-gitsm-test1.tar.gz', + 'git2_git.yoctoproject.org.bitbake-gitsm-test2.tar.gz', + 'git2_git.openembedded.org.bitbake.tar.gz' + ]: + target_path = os.path.join(bb_vars['DEPLOY_DIR_SRC'], 'mirror', target_file_name) + self.assertTrue(os.path.exists(target_path)) + + def test_archiver_mode_mirror_gitsm_shallow(self): + """ + Test that the archiver correctly handles git submodules with + `ARCHIVER_MODE[src] = "mirror"`. + """ + features = 'INHERIT += "archiver"\n' + features += 'ARCHIVER_MODE[src] = "mirror"\n' + features += 'ARCHIVER_MODE[mirror] = "combined"\n' + features += 'BB_GENERATE_MIRROR_TARBALLS = "1"\n' + features += 'COPYLEFT_LICENSE_INCLUDE = "*"\n' + features += 'BB_GIT_SHALLOW = "1"\n' + features += 'BB_GENERATE_SHALLOW_TARBALLS = "1"\n' + features += 'DL_DIR = "${TOPDIR}/downloads-shallow"\n' + self.write_config(features) + + bitbake('-c clean git-submodule-test') + bitbake('-c deploy_archives -f git-submodule-test') + + bb_vars = get_bb_vars(['DEPLOY_DIR_SRC']) + for target_file_name in [ + 'gitsmshallow_git.yoctoproject.org.git-submodule-test_a2885dd-1_master.tar.gz', + 'gitsmshallow_git.yoctoproject.org.bitbake-gitsm-test1_bare_120f4c7-1.tar.gz', + 'gitsmshallow_git.yoctoproject.org.bitbake-gitsm-test2_bare_f66699e-1.tar.gz', + 'gitsmshallow_git.openembedded.org.bitbake_bare_52a144a-1.tar.gz', + 'gitsmshallow_git.openembedded.org.bitbake_bare_c39b997-1.tar.gz' + ]: + target_path = os.path.join(bb_vars['DEPLOY_DIR_SRC'], 'mirror', target_file_name) + self.assertTrue(os.path.exists(target_path)) diff --git a/poky/meta/lib/oeqa/selftest/cases/containerimage.py b/poky/meta/lib/oeqa/selftest/cases/containerimage.py index c0998e319..4ad7f0e65 100644 --- a/poky/meta/lib/oeqa/selftest/cases/containerimage.py +++ b/poky/meta/lib/oeqa/selftest/cases/containerimage.py @@ -42,6 +42,9 @@ IMAGE_FSTYPES = "container" PACKAGE_CLASSES = "package_ipk" IMAGE_FEATURES = "" IMAGE_BUILDINFO_FILE = "" +INIT_MANAGER = "sysvinit" +IMAGE_INSTALL_remove = "ssh-pregen-hostkeys" + """) bbvars = get_bb_vars(['bindir', 'sysconfdir', 'localstatedir', diff --git a/poky/meta/lib/oeqa/selftest/cases/devtool.py b/poky/meta/lib/oeqa/selftest/cases/devtool.py index 5886862d6..4a791ff40 100644 --- a/poky/meta/lib/oeqa/selftest/cases/devtool.py +++ b/poky/meta/lib/oeqa/selftest/cases/devtool.py @@ -56,7 +56,8 @@ def setUpModule(): if pth.startswith(canonical_layerpath): if relpth.endswith('/'): destdir = os.path.join(corecopydir, relpth) - shutil.copytree(pth, destdir) + # avoid race condition by not copying .pyc files YPBZ#13421,13803 + shutil.copytree(pth, destdir, ignore=ignore_patterns('*.pyc', '__pycache__')) else: destdir = os.path.join(corecopydir, os.path.dirname(relpth)) bb.utils.mkdirhier(destdir) @@ -106,6 +107,13 @@ class DevtoolBase(OESelftestTestCase): 'under the build directory') self.append_config(self.sstate_conf) + def tearDown(self): + # devtools tests are heavy on IO and if bitbake can't write out its caches, we see timeouts. + # call sync around the tests to ensure the IO queue doesn't get too large, taking any IO + # hit here rather than in bitbake shutdown. + super().tearDown() + os.system("sync") + def _check_src_repo(self, repo_dir): """Check srctree git repository""" self.assertTrue(os.path.isdir(os.path.join(repo_dir, '.git')), @@ -676,7 +684,7 @@ class DevtoolModifyTests(DevtoolBase): bbclassextended = False inheritnative = False - testrecipes = 'mtools-native apt-native desktop-file-utils-native'.split() + testrecipes = 'cdrtools-native mtools-native apt-native desktop-file-utils-native'.split() for testrecipe in testrecipes: checkextend = 'native' in (get_bb_var('BBCLASSEXTEND', testrecipe) or '').split() if not bbclassextended: @@ -1108,6 +1116,59 @@ class DevtoolUpdateTests(DevtoolBase): ('??', '.*/0001-Add-new-file.patch$')] self._check_repo_status(os.path.dirname(recipefile), expected_status) + def test_devtool_update_recipe_with_gitignore(self): + # First, modify the recipe + testrecipe = 'devtool-test-ignored' + bb_vars = get_bb_vars(['FILE'], testrecipe) + recipefile = bb_vars['FILE'] + patchfile = os.path.join(os.path.dirname(recipefile), testrecipe, testrecipe + '.patch') + newpatchfile = os.path.join(os.path.dirname(recipefile), testrecipe, testrecipe + '.patch.expected') + tempdir = tempfile.mkdtemp(prefix='devtoolqa') + self.track_for_cleanup(tempdir) + self.track_for_cleanup(self.workspacedir) + self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') + # (don't bother with cleaning the recipe on teardown, we won't be building it) + result = runCmd('devtool modify %s' % testrecipe) + self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile))) + result = runCmd('devtool finish --force-patch-refresh %s meta-selftest' % testrecipe) + # Check recipe got changed as expected + with open(newpatchfile, 'r') as f: + desiredlines = f.readlines() + with open(patchfile, 'r') as f: + newlines = f.readlines() + # Ignore the initial lines, because oe-selftest creates own meta-selftest repo + # which changes the metadata subject which is added into the patch, but keep + # .patch.expected as it is in case someone runs devtool finish --force-patch-refresh + # devtool-test-ignored manually, then it should generate exactly the same .patch file + self.assertEqual(desiredlines[5:], newlines[5:]) + + def test_devtool_update_recipe_long_filename(self): + # First, modify the recipe + testrecipe = 'devtool-test-long-filename' + bb_vars = get_bb_vars(['FILE'], testrecipe) + recipefile = bb_vars['FILE'] + patchfilename = '0001-I-ll-patch-you-only-if-devtool-lets-me-to-do-it-corr.patch' + patchfile = os.path.join(os.path.dirname(recipefile), testrecipe, patchfilename) + newpatchfile = os.path.join(os.path.dirname(recipefile), testrecipe, patchfilename + '.expected') + tempdir = tempfile.mkdtemp(prefix='devtoolqa') + self.track_for_cleanup(tempdir) + self.track_for_cleanup(self.workspacedir) + self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') + # (don't bother with cleaning the recipe on teardown, we won't be building it) + result = runCmd('devtool modify %s' % testrecipe) + self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile))) + result = runCmd('devtool finish --force-patch-refresh %s meta-selftest' % testrecipe) + # Check recipe got changed as expected + with open(newpatchfile, 'r') as f: + desiredlines = f.readlines() + with open(patchfile, 'r') as f: + newlines = f.readlines() + # Ignore the initial lines, because oe-selftest creates own meta-selftest repo + # which changes the metadata subject which is added into the patch, but keep + # .patch.expected as it is in case someone runs devtool finish --force-patch-refresh + # devtool-test-ignored manually, then it should generate exactly the same .patch file + self.assertEqual(desiredlines[5:], newlines[5:]) + def test_devtool_update_recipe_local_files_3(self): # First, modify the recipe testrecipe = 'devtool-test-localonly' @@ -1447,7 +1508,11 @@ class DevtoolUpgradeTests(DevtoolBase): dstdir = os.path.join(dstdir, p) if not os.path.exists(dstdir): os.makedirs(dstdir) - self.track_for_cleanup(dstdir) + if p == "lib": + # Can race with other tests + self.add_command_to_tearDown('rmdir --ignore-fail-on-non-empty %s' % dstdir) + else: + self.track_for_cleanup(dstdir) dstfile = os.path.join(dstdir, os.path.basename(srcfile)) if srcfile != dstfile: shutil.copy(srcfile, dstfile) diff --git a/poky/meta/lib/oeqa/selftest/cases/diffoscope/A/file.txt b/poky/meta/lib/oeqa/selftest/cases/diffoscope/A/file.txt new file mode 100644 index 000000000..f70f10e4d --- /dev/null +++ b/poky/meta/lib/oeqa/selftest/cases/diffoscope/A/file.txt @@ -0,0 +1 @@ +A diff --git a/poky/meta/lib/oeqa/selftest/cases/diffoscope/B/file.txt b/poky/meta/lib/oeqa/selftest/cases/diffoscope/B/file.txt new file mode 100644 index 000000000..223b7836f --- /dev/null +++ b/poky/meta/lib/oeqa/selftest/cases/diffoscope/B/file.txt @@ -0,0 +1 @@ +B diff --git a/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py b/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py index dea519e6d..f7a253374 100644 --- a/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py +++ b/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py @@ -263,6 +263,80 @@ PNBLACKLIST[busybox] = "Don't build this" bitbake("--graphviz core-image-sato") + def test_fit_image(self): + """ + Summary: Check if FIT image and Image Tree Source (its) are built + and the Image Tree Source has the correct fields. + Expected: 1. fitImage and fitImage-its can be built + 2. The type, load address, entrypoint address and + default values of kernel and ramdisk are as expected + in the Image Tree Source. Not all the fields are tested, + only the key fields that wont vary between different + architectures. + Product: oe-core + Author: Usama Arif <usama.arif@arm.com> + """ + config = """ +# Enable creation of fitImage +KERNEL_IMAGETYPE = "Image" +KERNEL_IMAGETYPES += " fitImage " +KERNEL_CLASSES = " kernel-fitimage " + +# RAM disk variables including load address and entrypoint for kernel and RAM disk +IMAGE_FSTYPES += "cpio.gz" +INITRAMFS_IMAGE = "core-image-minimal" +UBOOT_RD_LOADADDRESS = "0x88000000" +UBOOT_RD_ENTRYPOINT = "0x88000000" +UBOOT_LOADADDRESS = "0x80080000" +UBOOT_ENTRYPOINT = "0x80080000" +""" + self.write_config(config) + + # fitImage is created as part of linux recipe + bitbake("virtual/kernel") + + image_type = "core-image-minimal" + deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') + machine = get_bb_var('MACHINE') + fitimage_its_path = os.path.join(deploy_dir_image, + "fitImage-its-%s-%s-%s" % (image_type, machine, machine)) + fitimage_path = os.path.join(deploy_dir_image, + "fitImage-%s-%s-%s" % (image_type, machine, machine)) + + self.assertTrue(os.path.exists(fitimage_its_path), + "%s image tree source doesn't exist" % (fitimage_its_path)) + self.assertTrue(os.path.exists(fitimage_path), + "%s FIT image doesn't exist" % (fitimage_path)) + + # Check that the type, load address, entrypoint address and default + # values for kernel and ramdisk in Image Tree Source are as expected. + # The order of fields in the below array is important. Not all the + # fields are tested, only the key fields that wont vary between + # different architectures. + its_field_check = ['type = "kernel";', + 'load = <0x80080000>;', + 'entry = <0x80080000>;', + 'type = "ramdisk";', + 'load = <0x88000000>;', + 'entry = <0x88000000>;', + 'default = "conf@1";', + 'kernel = "kernel@1";', + 'ramdisk = "ramdisk@1";' + ] + + with open(fitimage_its_path) as its_file: + field_index = 0 + for line in its_file: + if field_index == len(its_field_check): + break + if its_field_check[field_index] in line: + field_index +=1 + + if field_index != len(its_field_check): # if its equal, the test passed + self.assertTrue(field_index == len(its_field_check), + "Fields in Image Tree Source File %s did not match, error in finding %s" + % (fitimage_its_path, its_field_check[field_index])) + def test_image_gen_debugfs(self): """ Summary: Check debugfs generation diff --git a/poky/meta/lib/oeqa/selftest/cases/incompatible_lic.py b/poky/meta/lib/oeqa/selftest/cases/incompatible_lic.py index 3eabd7909..2a6382a1a 100644 --- a/poky/meta/lib/oeqa/selftest/cases/incompatible_lic.py +++ b/poky/meta/lib/oeqa/selftest/cases/incompatible_lic.py @@ -85,7 +85,7 @@ class IncompatibleLicenseTests(OESelftestTestCase): class IncompatibleLicensePerImageTests(OESelftestTestCase): def default_config(self): return """ -IMAGE_INSTALL_append = "bash" +IMAGE_INSTALL_append = " bash" INCOMPATIBLE_LICENSE_pn-core-image-minimal = "GPL-3.0 LGPL-3.0" """ diff --git a/poky/meta/lib/oeqa/selftest/cases/meta_ide.py b/poky/meta/lib/oeqa/selftest/cases/meta_ide.py index 809142559..6f10d30dc 100644 --- a/poky/meta/lib/oeqa/selftest/cases/meta_ide.py +++ b/poky/meta/lib/oeqa/selftest/cases/meta_ide.py @@ -43,7 +43,7 @@ class MetaIDE(OESelftestTestCase): "https://ftp.gnu.org/gnu/cpio/cpio-2.13.tar.gz", self.tmpdir_metaideQA, self.td['DATETIME'], dl_dir=dl_dir) self.project.download_archive() - self.assertEqual(self.project.run_configure(), 0, + self.assertEqual(self.project.run_configure('$CONFIGURE_FLAGS --disable-maintainer-mode','sed -i -e "/char \*program_name/d" src/global.c;'), 0, msg="Running configure failed") self.assertEqual(self.project.run_make(), 0, msg="Running make failed") diff --git a/poky/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py b/poky/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py index d4664bd0d..802a91a48 100644 --- a/poky/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py +++ b/poky/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py @@ -5,6 +5,7 @@ import os from oeqa.selftest.case import OESelftestTestCase import tempfile +import operator from oeqa.utils.commands import get_bb_var class TestBlobParsing(OESelftestTestCase): @@ -97,3 +98,48 @@ class TestBlobParsing(OESelftestTestCase): var_changes[x.fieldname] = (oldvalue, x.newvalue) self.assertEqual(defaultmap, var_changes, "Defaults not set properly") + +class TestFileListCompare(OESelftestTestCase): + + def test_compare_file_lists(self): + # Test that a directory tree that moves location such as /lib/modules/5.4.40-yocto-standard -> /lib/modules/5.4.43-yocto-standard + # is correctly identified as a move + from oe.buildhistory_analysis import compare_file_lists, FileChange + + with open(self.tc.files_dir + "/buildhistory_filelist1.txt", "r") as f: + filelist1 = f.readlines() + with open(self.tc.files_dir + "/buildhistory_filelist2.txt", "r") as f: + filelist2 = f.readlines() + + expectedResult = [ + '/lib/libcap.so.2 changed symlink target from libcap.so.2.33 to libcap.so.2.34', + '/lib/libcap.so.2.33 moved to /lib/libcap.so.2.34', + '/lib/modules/5.4.40-yocto-standard moved to /lib/modules/5.4.43-yocto-standard', + '/lib/modules/5.4.43-yocto-standard/modules.builtin.alias.bin was added', + '/usr/bin/gawk-5.0.1 moved to /usr/bin/gawk-5.1.0', + '/usr/lib/libbtrfsutil.so changed symlink target from libbtrfsutil.so.1.1.1 to libbtrfsutil.so.1.2.0', + '/usr/lib/libbtrfsutil.so.1 changed symlink target from libbtrfsutil.so.1.1.1 to libbtrfsutil.so.1.2.0', + '/usr/lib/libbtrfsutil.so.1.1.1 moved to /usr/lib/libbtrfsutil.so.1.2.0', + '/usr/lib/libkmod.so changed symlink target from libkmod.so.2.3.4 to libkmod.so.2.3.5', + '/usr/lib/libkmod.so.2 changed symlink target from libkmod.so.2.3.4 to libkmod.so.2.3.5', + '/usr/lib/libkmod.so.2.3.4 moved to /usr/lib/libkmod.so.2.3.5', + '/usr/lib/libpixman-1.so.0 changed symlink target from libpixman-1.so.0.38.4 to libpixman-1.so.0.40.0', + '/usr/lib/libpixman-1.so.0.38.4 moved to /usr/lib/libpixman-1.so.0.40.0', + '/usr/lib/opkg/alternatives/rtcwake was added', + '/usr/lib/python3.8/site-packages/PyGObject-3.34.0.egg-info moved to /usr/lib/python3.8/site-packages/PyGObject-3.36.1.egg-info', + '/usr/lib/python3.8/site-packages/btrfsutil-1.1.1-py3.8.egg-info moved to /usr/lib/python3.8/site-packages/btrfsutil-1.2.0-py3.8.egg-info', + '/usr/lib/python3.8/site-packages/pycairo-1.19.0.egg-info moved to /usr/lib/python3.8/site-packages/pycairo-1.19.1.egg-info', + '/usr/sbin/rtcwake changed type from file to symlink', + '/usr/sbin/rtcwake changed permissions from rwxr-xr-x to rwxrwxrwx', + '/usr/sbin/rtcwake changed symlink target from None to /usr/sbin/rtcwake.util-linux', + '/usr/sbin/rtcwake.util-linux was added' + ] + + result = compare_file_lists(filelist1, filelist2) + rendered = [] + for entry in sorted(result, key=operator.attrgetter("path")): + rendered.append(str(entry)) + + self.maxDiff = None + self.assertCountEqual(rendered, expectedResult) + diff --git a/poky/meta/lib/oeqa/selftest/cases/oescripts.py b/poky/meta/lib/oeqa/selftest/cases/oescripts.py index 2f18d8f29..726daff7c 100644 --- a/poky/meta/lib/oeqa/selftest/cases/oescripts.py +++ b/poky/meta/lib/oeqa/selftest/cases/oescripts.py @@ -133,7 +133,7 @@ class OEListPackageconfigTests(OEScriptTests): def check_endlines(self, results, expected_endlines): for line in results.output.splitlines(): for el in expected_endlines: - if line == el: + if line.split() == el.split(): expected_endlines.remove(el) break @@ -177,7 +177,7 @@ class OEListPackageconfigTests(OEScriptTests): self.check_endlines(results, expected_endlines) - def test_packageconfig_flags_optiins_preferred_only(self): + def test_packageconfig_flags_options_preferred_only(self): results = runCmd('%s/contrib/list-packageconfig-flags.py -p' % self.scripts_dir) expected_endlines = [] expected_endlines.append("RECIPE NAME PACKAGECONFIG FLAGS") diff --git a/poky/meta/lib/oeqa/selftest/cases/prservice.py b/poky/meta/lib/oeqa/selftest/cases/prservice.py index fe1f24ea6..578b2b4dd 100644 --- a/poky/meta/lib/oeqa/selftest/cases/prservice.py +++ b/poky/meta/lib/oeqa/selftest/cases/prservice.py @@ -23,7 +23,7 @@ class BitbakePrTests(OESelftestTestCase): package_data_file = os.path.join(self.pkgdata_dir, 'runtime', package_name) package_data = ftools.read_file(package_data_file) find_pr = re.search(r"PKGR: r[0-9]+\.([0-9]+)", package_data) - self.assertTrue(find_pr, "No PKG revision found in %s" % package_data_file) + self.assertTrue(find_pr, "No PKG revision found via regex 'PKGR: r[0-9]+\.([0-9]+)' in %s" % package_data_file) return int(find_pr.group(1)) def get_task_stamp(self, package_name, recipe_task): @@ -40,7 +40,7 @@ class BitbakePrTests(OESelftestTestCase): return str(stamps[0]) def increment_package_pr(self, package_name): - inc_data = "do_package_append() {\n bb.build.exec_func('do_test_prserv', d)\n}\ndo_test_prserv() {\necho \"The current date is: %s\"\n}" % datetime.datetime.now() + inc_data = "do_package_append() {\n bb.build.exec_func('do_test_prserv', d)\n}\ndo_test_prserv() {\necho \"The current date is: %s\" > ${PKGDESTWORK}/${PN}.datestamp\n}" % datetime.datetime.now() self.write_recipeinc(package_name, inc_data) res = bitbake(package_name, ignore_status=True) self.delete_recipeinc(package_name) @@ -63,7 +63,7 @@ class BitbakePrTests(OESelftestTestCase): pr_2 = self.get_pr_version(package_name) stamp_2 = self.get_task_stamp(package_name, track_task) - self.assertTrue(pr_2 - pr_1 == 1, "Step between same pkg. revision is greater than 1") + self.assertTrue(pr_2 - pr_1 == 1, "New PR %s did not increment as expected (from %s), difference should be 1" % (pr_2, pr_1)) self.assertTrue(stamp_1 != stamp_2, "Different pkg rev. but same stamp: %s" % stamp_1) def run_test_pr_export_import(self, package_name, replace_current_db=True): @@ -89,7 +89,7 @@ class BitbakePrTests(OESelftestTestCase): self.increment_package_pr(package_name) pr_2 = self.get_pr_version(package_name) - self.assertTrue(pr_2 - pr_1 == 1, "Step between same pkg. revision is greater than 1") + self.assertTrue(pr_2 - pr_1 == 1, "New PR %s did not increment as expected (from %s), difference should be 1" % (pr_2, pr_1)) def test_import_export_replace_db(self): self.run_test_pr_export_import('m4') diff --git a/poky/meta/lib/oeqa/selftest/cases/recipetool.py b/poky/meta/lib/oeqa/selftest/cases/recipetool.py index 6bfe8f177..6bac53cf3 100644 --- a/poky/meta/lib/oeqa/selftest/cases/recipetool.py +++ b/poky/meta/lib/oeqa/selftest/cases/recipetool.py @@ -226,19 +226,6 @@ class RecipetoolTests(RecipetoolBase): _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-subdir', self.testfile, '', expectedlines, ['testfile']) self.assertNotIn('WARNING: ', output) - def test_recipetool_appendfile_src_glob(self): - # A file that's in SRC_URI as a glob - expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', - '\n', - 'SRC_URI += "file://testfile"\n', - '\n', - 'do_install_append() {\n', - ' install -d ${D}${datadir}\n', - ' install -m 0644 ${WORKDIR}/testfile ${D}${datadir}/selftest-replaceme-src-globfile\n', - '}\n'] - _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-src-globfile', self.testfile, '', expectedlines, ['testfile']) - self.assertNotIn('WARNING: ', output) - def test_recipetool_appendfile_inst_glob(self): # A file that's in do_install as a glob expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -534,7 +521,11 @@ class RecipetoolTests(RecipetoolBase): dstdir = os.path.join(dstdir, p) if not os.path.exists(dstdir): os.makedirs(dstdir) - self.track_for_cleanup(dstdir) + if p == "lib": + # Can race with other tests + self.add_command_to_tearDown('rmdir --ignore-fail-on-non-empty %s' % dstdir) + else: + self.track_for_cleanup(dstdir) dstfile = os.path.join(dstdir, os.path.basename(srcfile)) if srcfile != dstfile: shutil.copy(srcfile, dstfile) diff --git a/poky/meta/lib/oeqa/selftest/cases/reproducible.py b/poky/meta/lib/oeqa/selftest/cases/reproducible.py index 5d3959be7..a7ef33614 100644 --- a/poky/meta/lib/oeqa/selftest/cases/reproducible.py +++ b/poky/meta/lib/oeqa/selftest/cases/reproducible.py @@ -77,6 +77,32 @@ def compare_file(reference, test, diffutils_sysroot): result.status = SAME return result +def run_diffoscope(a_dir, b_dir, html_dir, **kwargs): + return runCmd(['diffoscope', '--no-default-limits', '--exclude-directory-metadata', 'yes', '--html-dir', html_dir, a_dir, b_dir], + **kwargs) + +class DiffoscopeTests(OESelftestTestCase): + diffoscope_test_files = os.path.join(os.path.dirname(os.path.abspath(__file__)), "diffoscope") + + def test_diffoscope(self): + bitbake("diffoscope-native -c addto_recipe_sysroot") + diffoscope_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "diffoscope-native") + + # Check that diffoscope doesn't return an error when the files compare + # the same (a general check that diffoscope is working) + with tempfile.TemporaryDirectory() as tmpdir: + run_diffoscope('A', 'A', tmpdir, + native_sysroot=diffoscope_sysroot, cwd=self.diffoscope_test_files) + + # Check that diffoscope generates an index.html file when the files are + # different + with tempfile.TemporaryDirectory() as tmpdir: + r = run_diffoscope('A', 'B', tmpdir, + native_sysroot=diffoscope_sysroot, ignore_status=True, cwd=self.diffoscope_test_files) + + self.assertNotEqual(r.status, 0, msg="diffoscope was successful when an error was expected") + self.assertTrue(os.path.exists(os.path.join(tmpdir, 'index.html')), "HTML index not found!") + class ReproducibleTests(OESelftestTestCase): package_classes = ['deb', 'ipk'] images = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline'] @@ -232,7 +258,7 @@ class ReproducibleTests(OESelftestTestCase): # Copy jquery to improve the diffoscope output usability self.copy_file(os.path.join(jquery_sysroot, 'usr/share/javascript/jquery/jquery.min.js'), os.path.join(package_html_dir, 'jquery.js')) - runCmd(['diffoscope', '--no-default-limits', '--exclude-directory-metadata', '--html-dir', package_html_dir, 'reproducibleA', 'reproducibleB'], + run_diffoscope('reproducibleA', 'reproducibleB', package_html_dir, native_sysroot=diffoscope_sysroot, ignore_status=True, cwd=package_dir) if fails: diff --git a/poky/meta/lib/oeqa/selftest/cases/runcmd.py b/poky/meta/lib/oeqa/selftest/cases/runcmd.py index 3755764ee..a5ef1ea95 100644 --- a/poky/meta/lib/oeqa/selftest/cases/runcmd.py +++ b/poky/meta/lib/oeqa/selftest/cases/runcmd.py @@ -81,7 +81,7 @@ class RunCmdTests(OESelftestTestCase): self.assertEqual(result.status, -signal.SIGTERM) end = time.time() self.assertLess(end - start, self.TIMEOUT + self.DELTA) - self.assertEqual(numthreads, threading.active_count()) + self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate())) def test_timeout_split(self): numthreads = threading.active_count() @@ -91,13 +91,14 @@ class RunCmdTests(OESelftestTestCase): self.assertEqual(result.status, -signal.SIGTERM) end = time.time() self.assertLess(end - start, self.TIMEOUT + self.DELTA) - self.assertEqual(numthreads, threading.active_count()) + self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate())) def test_stdin(self): numthreads = threading.active_count() result = runCmd("cat", data=b"hello world", timeout=self.TIMEOUT) self.assertEqual("hello world", result.output) - self.assertEqual(numthreads, threading.active_count()) + self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate())) + self.assertEqual(numthreads, 1) def test_stdin_timeout(self): numthreads = threading.active_count() @@ -106,7 +107,7 @@ class RunCmdTests(OESelftestTestCase): self.assertEqual(result.status, -signal.SIGTERM) end = time.time() self.assertLess(end - start, self.TIMEOUT + self.DELTA) - self.assertEqual(numthreads, threading.active_count()) + self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate())) def test_log(self): log = MemLogger() diff --git a/poky/meta/lib/oeqa/selftest/cases/runtime_test.py b/poky/meta/lib/oeqa/selftest/cases/runtime_test.py index 793c98a33..d89731c69 100644 --- a/poky/meta/lib/oeqa/selftest/cases/runtime_test.py +++ b/poky/meta/lib/oeqa/selftest/cases/runtime_test.py @@ -156,7 +156,7 @@ class TestImage(OESelftestTestCase): self.gpg_home = tempfile.mkdtemp(prefix="oeqa-feed-sign-") self.track_for_cleanup(self.gpg_home) signing_key_dir = os.path.join(self.testlayer_path, 'files', 'signing') - runCmd('gpg --batch --homedir %s --import %s' % (self.gpg_home, os.path.join(signing_key_dir, 'key.secret')), native_sysroot=get_bb_var("RECIPE_SYSROOT_NATIVE", "gnupg-native")) + runCmd('gpgconf --list-dirs --homedir %s; gpg -v --batch --homedir %s --import %s' % (self.gpg_home, self.gpg_home, os.path.join(signing_key_dir, 'key.secret')), native_sysroot=get_bb_var("RECIPE_SYSROOT_NATIVE", "gnupg-native"), shell=True) features += 'INHERIT += "sign_package_feed"\n' features += 'PACKAGE_FEED_GPG_NAME = "testuser"\n' features += 'PACKAGE_FEED_GPG_PASSPHRASE_FILE = "%s"\n' % os.path.join(signing_key_dir, 'key.passphrase') diff --git a/poky/meta/lib/oeqa/selftest/cases/signing.py b/poky/meta/lib/oeqa/selftest/cases/signing.py index 202d54994..a28c7eb19 100644 --- a/poky/meta/lib/oeqa/selftest/cases/signing.py +++ b/poky/meta/lib/oeqa/selftest/cases/signing.py @@ -44,7 +44,9 @@ class Signing(OESelftestTestCase): origenv = os.environ.copy() for e in os.environ: - if builddir in os.environ[e]: + if builddir + "/" in os.environ[e]: + os.environ[e] = os.environ[e].replace(builddir + "/", newbuilddir + "/") + if os.environ[e].endswith(builddir): os.environ[e] = os.environ[e].replace(builddir, newbuilddir) os.chdir(newbuilddir) diff --git a/poky/meta/lib/oeqa/selftest/cases/sstatetests.py b/poky/meta/lib/oeqa/selftest/cases/sstatetests.py index 9adb51196..c46e8ba48 100644 --- a/poky/meta/lib/oeqa/selftest/cases/sstatetests.py +++ b/poky/meta/lib/oeqa/selftest/cases/sstatetests.py @@ -19,10 +19,13 @@ class SStateTests(SStateBase): # Test that a git repository which changes is correctly handled by SRCREV = ${AUTOREV} # when PV does not contain SRCPV - tempdir = tempfile.mkdtemp(prefix='oeqa') + tempdir = tempfile.mkdtemp(prefix='sstate_autorev') + tempdldir = tempfile.mkdtemp(prefix='sstate_autorev_dldir') self.track_for_cleanup(tempdir) + self.track_for_cleanup(tempdldir) create_temp_layer(tempdir, 'selftestrecipetool') self.add_command_to_tearDown('bitbake-layers remove-layer %s' % tempdir) + self.append_config("DL_DIR = \"%s\"" % tempdldir) runCmd('bitbake-layers add-layer %s' % tempdir) # Use dbus-wait as a local git repo we can add a commit between two builds in diff --git a/poky/meta/lib/oeqa/selftest/cases/tinfoil.py b/poky/meta/lib/oeqa/selftest/cases/tinfoil.py index d1aa7b9af..206168ed0 100644 --- a/poky/meta/lib/oeqa/selftest/cases/tinfoil.py +++ b/poky/meta/lib/oeqa/selftest/cases/tinfoil.py @@ -100,8 +100,9 @@ class TinfoilTests(OESelftestTestCase): eventreceived = False commandcomplete = False start = time.time() - # Wait for 5s in total so we'd detect spurious heartbeat events for example - while time.time() - start < 5: + # Wait for 10s in total so we'd detect spurious heartbeat events for example + # The test is IO load sensitive too + while time.time() - start < 10: event = tinfoil.wait_event(1) if event: if isinstance(event, bb.command.CommandCompleted): diff --git a/poky/meta/lib/oeqa/selftest/cases/wic.py b/poky/meta/lib/oeqa/selftest/cases/wic.py index c8765e533..714637ec1 100644 --- a/poky/meta/lib/oeqa/selftest/cases/wic.py +++ b/poky/meta/lib/oeqa/selftest/cases/wic.py @@ -235,6 +235,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 @@ -689,7 +700,7 @@ class Wic2(WicTestCase): wicvars = wicvars.difference(('DEPLOY_DIR_IMAGE', 'IMAGE_BOOT_FILES', 'INITRD', 'INITRD_LIVE', 'ISODIR','INITRAMFS_IMAGE', 'INITRAMFS_IMAGE_BUNDLE', 'INITRAMFS_LINK_NAME', - 'APPEND')) + '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 @@ -790,41 +801,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): """ @@ -832,13 +852,111 @@ 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): diff --git a/poky/meta/lib/oeqa/selftest/context.py b/poky/meta/lib/oeqa/selftest/context.py index 48ec5d419..dd3609c1d 100644 --- a/poky/meta/lib/oeqa/selftest/context.py +++ b/poky/meta/lib/oeqa/selftest/context.py @@ -10,6 +10,7 @@ import glob import sys import importlib import subprocess +import unittest from random import choice import oeqa @@ -21,19 +22,54 @@ from oeqa.core.exception import OEQAPreRun, OEQATestNotFound from oeqa.utils.commands import runCmd, get_bb_vars, get_test_layer +class NonConcurrentTestSuite(unittest.TestSuite): + def __init__(self, suite, processes, setupfunc, removefunc): + super().__init__([suite]) + self.processes = processes + self.suite = suite + self.setupfunc = setupfunc + self.removefunc = removefunc + + def run(self, result): + (builddir, newbuilddir) = self.setupfunc("-st", None, self.suite) + ret = super().run(result) + os.chdir(builddir) + if newbuilddir and ret.wasSuccessful(): + self.removefunc(newbuilddir) + +def removebuilddir(d): + delay = 5 + while delay and os.path.exists(d + "/bitbake.lock"): + time.sleep(1) + delay = delay - 1 + # Deleting these directories takes a lot of time, use autobuilder + # clobberdir if its available + clobberdir = os.path.expanduser("~/yocto-autobuilder-helper/janitor/clobberdir") + if os.path.exists(clobberdir): + try: + subprocess.check_call([clobberdir, d]) + return + except subprocess.CalledProcessError: + pass + bb.utils.prunedir(d, ionice=True) + class OESelftestTestContext(OETestContext): - def __init__(self, td=None, logger=None, machines=None, config_paths=None): + def __init__(self, td=None, logger=None, machines=None, config_paths=None, newbuilddir=None): super(OESelftestTestContext, self).__init__(td, logger) self.machines = machines self.custommachine = None self.config_paths = config_paths + self.newbuilddir = newbuilddir def setup_builddir(self, suffix, selftestdir, suite): builddir = os.environ['BUILDDIR'] if not selftestdir: selftestdir = get_test_layer() - newbuilddir = builddir + suffix + if self.newbuilddir: + newbuilddir = os.path.join(self.newbuilddir, 'build' + suffix) + else: + newbuilddir = builddir + suffix newselftestdir = newbuilddir + "/meta-selftest" if os.path.exists(newbuilddir): @@ -46,7 +82,9 @@ class OESelftestTestContext(OETestContext): oe.path.copytree(selftestdir, newselftestdir) for e in os.environ: - if builddir + "/" in os.environ[e] or os.environ[e].endswith(builddir): + if builddir + "/" in os.environ[e]: + os.environ[e] = os.environ[e].replace(builddir + "/", newbuilddir + "/") + if os.environ[e].endswith(builddir): os.environ[e] = os.environ[e].replace(builddir, newbuilddir) subprocess.check_output("git init; git add *; git commit -a -m 'initial'", cwd=newselftestdir, shell=True) @@ -56,9 +94,9 @@ class OESelftestTestContext(OETestContext): os.chdir(newbuilddir) - for t in suite: + def patch_test(t): if not hasattr(t, "tc"): - continue + return cp = t.tc.config_paths for p in cp: if selftestdir in cp[p] and newselftestdir not in cp[p]: @@ -66,16 +104,24 @@ class OESelftestTestContext(OETestContext): if builddir in cp[p] and newbuilddir not in cp[p]: cp[p] = cp[p].replace(builddir, newbuilddir) + def patch_suite(s): + for x in s: + if isinstance(x, unittest.TestSuite): + patch_suite(x) + else: + patch_test(x) + + patch_suite(suite) + return (builddir, newbuilddir) def prepareSuite(self, suites, processes): if processes: from oeqa.core.utils.concurrencytest import ConcurrentTestSuite - return ConcurrentTestSuite(suites, processes, self.setup_builddir) + return ConcurrentTestSuite(suites, processes, self.setup_builddir, removebuilddir) else: - self.setup_builddir("-st", None, suites) - return suites + return NonConcurrentTestSuite(suites, processes, self.setup_builddir, removebuilddir) def runTests(self, processes=None, machine=None, skips=[]): if machine: @@ -133,6 +179,8 @@ class OESelftestTestContextExecutor(OETestContextExecutor): action='append', default=None, help='Exclude all (unhidden) tests that match any of the specified tag(s). (exclude applies before select)') + parser.add_argument('-B', '--newbuilddir', help='New build directory to use for tests.') + parser.add_argument('-v', '--verbose', action='store_true') parser.set_defaults(func=self.run) def _get_available_machines(self): @@ -187,6 +235,7 @@ class OESelftestTestContextExecutor(OETestContextExecutor): self.tc_kwargs['init']['config_paths']['builddir'] = builddir self.tc_kwargs['init']['config_paths']['localconf'] = os.path.join(builddir, "conf/local.conf") self.tc_kwargs['init']['config_paths']['bblayers'] = os.path.join(builddir, "conf/bblayers.conf") + self.tc_kwargs['init']['newbuilddir'] = args.newbuilddir def tag_filter(tags): if args.exclude_tags: |