diff options
Diffstat (limited to 'poky/meta/lib')
-rw-r--r-- | poky/meta/lib/oe/cve_check.py | 60 | ||||
-rw-r--r-- | poky/meta/lib/oe/patch.py | 2 | ||||
-rw-r--r-- | poky/meta/lib/oe/path.py | 21 | ||||
-rw-r--r-- | poky/meta/lib/oe/prservice.py | 4 | ||||
-rw-r--r-- | poky/meta/lib/oe/recipeutils.py | 2 | ||||
-rw-r--r-- | poky/meta/lib/oe/reproducible.py | 8 | ||||
-rw-r--r-- | poky/meta/lib/oe/sstatesig.py | 12 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/runtime/cases/df.py | 2 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/runtime/cases/ptest.py | 1 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/runtime/cases/runlevel.py | 22 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/cve_check.py | 36 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/devtool.py | 37 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/prservice.py | 8 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/pseudo.py | 27 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/reproducible.py | 7 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/runtime_test.py | 1 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/tinfoil.py | 6 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/wic.py | 106 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/utils/commands.py | 4 |
19 files changed, 344 insertions, 22 deletions
diff --git a/poky/meta/lib/oe/cve_check.py b/poky/meta/lib/oe/cve_check.py new file mode 100644 index 0000000000..ce755f940a --- /dev/null +++ b/poky/meta/lib/oe/cve_check.py @@ -0,0 +1,60 @@ +import collections +import re +import itertools +import functools + +_Version = collections.namedtuple( + "_Version", ["release", "patch_l", "pre_l", "pre_v"] +) + +@functools.total_ordering +class Version(): + + def __init__(self, version, suffix=None): + if str(suffix) == "alphabetical": + version_pattern = r"""r?v?(?:(?P<release>[0-9]+(?:[-\.][0-9]+)*)(?P<patch>[-_\.]?(?P<patch_l>[a-z]))?(?P<pre>[-_\.]?(?P<pre_l>(rc|alpha|beta|pre|preview|dev))[-_\.]?(?P<pre_v>[0-9]+)?)?)(.*)?""" + else: + version_pattern = r"""r?v?(?:(?P<release>[0-9]+(?:[-\.][0-9]+)*)(?P<pre>[-_\.]?(?P<pre_l>(rc|alpha|beta|pre|preview|dev))[-_\.]?(?P<pre_v>[0-9]+)?)?)(.*)?""" + regex = re.compile(r"^\s*" + version_pattern + r"\s*$", re.VERBOSE | re.IGNORECASE) + + match = regex.search(version) + if not match: + raise Exception("Invalid version: '{0}'".format(version)) + + self._version = _Version( + release=tuple(int(i) for i in match.group("release").replace("-",".").split(".")), + patch_l=match.group("patch_l") if str(suffix) == "alphabetical" and match.group("patch_l") else "", + pre_l=match.group("pre_l"), + pre_v=match.group("pre_v") + ) + + self._key = _cmpkey( + self._version.release, + self._version.patch_l, + self._version.pre_l, + self._version.pre_v + ) + + def __eq__(self, other): + if not isinstance(other, Version): + return NotImplemented + return self._key == other._key + + def __gt__(self, other): + if not isinstance(other, Version): + return NotImplemented + return self._key > other._key + +def _cmpkey(release, patch_l, pre_l, pre_v): + # remove leading 0 + _release = tuple( + reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release)))) + ) + + _patch = patch_l.upper() + + if pre_l is None and pre_v is None: + _pre = float('inf') + else: + _pre = float(pre_v) if pre_v else float('-inf') + return _release, _patch, _pre diff --git a/poky/meta/lib/oe/patch.py b/poky/meta/lib/oe/patch.py index 7ca2e28b1f..7cd8436da5 100644 --- a/poky/meta/lib/oe/patch.py +++ b/poky/meta/lib/oe/patch.py @@ -512,7 +512,7 @@ class GitApplyTree(PatchTree): try: shellcmd = [patchfilevar, "git", "--work-tree=%s" % reporoot] self.gitCommandUserOptions(shellcmd, self.commituser, self.commitemail) - shellcmd += ["am", "-3", "--keep-cr", "-p%s" % patch['strippath']] + shellcmd += ["am", "-3", "--keep-cr", "--no-scissors", "-p%s" % patch['strippath']] return _applypatchhelper(shellcmd, patch, force, reverse, run) except CmdError: # Need to abort the git am, or we'll still be within it at the end diff --git a/poky/meta/lib/oe/path.py b/poky/meta/lib/oe/path.py index 082972457b..c8d8ad05b9 100644 --- a/poky/meta/lib/oe/path.py +++ b/poky/meta/lib/oe/path.py @@ -320,3 +320,24 @@ def which_wild(pathname, path=None, mode=os.F_OK, *, reverse=False, candidates=F return files +def canonicalize(paths, sep=','): + """Given a string with paths (separated by commas by default), expand + each path using os.path.realpath() and return the resulting paths as a + string (separated using the same separator a the original string). + """ + # Ignore paths containing "$" as they are assumed to be unexpanded bitbake + # variables. Normally they would be ignored, e.g., when passing the paths + # through the shell they would expand to empty strings. However, when they + # are passed through os.path.realpath(), it will cause them to be prefixed + # with the absolute path to the current directory and thus not be empty + # anymore. + # + # Also maintain trailing slashes, as the paths may actually be used as + # prefixes in sting compares later on, where the slashes then are important. + canonical_paths = [] + for path in (paths or '').split(sep): + if '$' not in path: + trailing_slash = path.endswith('/') and '/' or '' + canonical_paths.append(os.path.realpath(path) + trailing_slash) + + return sep.join(canonical_paths) diff --git a/poky/meta/lib/oe/prservice.py b/poky/meta/lib/oe/prservice.py index 2d3c9c7e50..fcdbe66c19 100644 --- a/poky/meta/lib/oe/prservice.py +++ b/poky/meta/lib/oe/prservice.py @@ -3,10 +3,6 @@ # def prserv_make_conn(d, check = False): - # Otherwise this fails when called from recipes which e.g. inherit python3native (which sets _PYTHON_SYSCONFIGDATA_NAME) with: - # No module named '_sysconfigdata' - if '_PYTHON_SYSCONFIGDATA_NAME' in os.environ: - del os.environ['_PYTHON_SYSCONFIGDATA_NAME'] import prserv.serv host_params = list([_f for _f in (d.getVar("PRSERV_HOST") or '').split(':') if _f]) try: diff --git a/poky/meta/lib/oe/recipeutils.py b/poky/meta/lib/oe/recipeutils.py index fde1ad3ddd..f36a2fb0ac 100644 --- a/poky/meta/lib/oe/recipeutils.py +++ b/poky/meta/lib/oe/recipeutils.py @@ -409,7 +409,7 @@ def copy_recipe_files(d, tgt_dir, whole_dir=False, download=True, all_variants=F fetch.download() for pth in fetch.localpaths(): if pth not in localpaths: - localpaths.append(pth) + localpaths.append(os.path.abspath(pth)) uri_values.append(srcuri) fetch_urls(d) diff --git a/poky/meta/lib/oe/reproducible.py b/poky/meta/lib/oe/reproducible.py index 0fb02ccdb0..204b9bd734 100644 --- a/poky/meta/lib/oe/reproducible.py +++ b/poky/meta/lib/oe/reproducible.py @@ -90,8 +90,12 @@ def get_source_date_epoch_from_youngest_file(d, sourcedir): bb.debug(1, "Newest file found: %s" % newest_file) return source_date_epoch -def fixed_source_date_epoch(): +def fixed_source_date_epoch(d): bb.debug(1, "No tarball or git repo found to determine SOURCE_DATE_EPOCH") + source_date_epoch = d.getVar('SOURCE_DATE_EPOCH_FALLBACK') + if source_date_epoch: + bb.debug(1, "Using SOURCE_DATE_EPOCH_FALLBACK") + return int(source_date_epoch) return 0 def get_source_date_epoch(d, sourcedir): @@ -99,6 +103,6 @@ def get_source_date_epoch(d, sourcedir): get_source_date_epoch_from_git(d, sourcedir) or get_source_date_epoch_from_known_files(d, sourcedir) or get_source_date_epoch_from_youngest_file(d, sourcedir) or - fixed_source_date_epoch() # Last resort + fixed_source_date_epoch(d) # Last resort ) diff --git a/poky/meta/lib/oe/sstatesig.py b/poky/meta/lib/oe/sstatesig.py index d5a6200562..51e1d492c3 100644 --- a/poky/meta/lib/oe/sstatesig.py +++ b/poky/meta/lib/oe/sstatesig.py @@ -434,7 +434,7 @@ def find_sstate_manifest(taskdata, taskdata2, taskname, d, multilibcache): d2 = multilibcache[variant] if taskdata.endswith("-native"): - pkgarchs = ["${BUILD_ARCH}"] + pkgarchs = ["${BUILD_ARCH}", "${BUILD_ARCH}_${ORIGNATIVELSBSTRING}"] elif taskdata.startswith("nativesdk-"): pkgarchs = ["${SDK_ARCH}_${SDK_OS}", "allarch"] elif "-cross-canadian" in taskdata: @@ -453,7 +453,7 @@ def find_sstate_manifest(taskdata, taskdata2, taskname, d, multilibcache): manifest = d2.expand("${SSTATE_MANIFESTS}/manifest-%s-%s.%s" % (pkgarch, taskdata, taskname)) if os.path.exists(manifest): return manifest, d2 - bb.warn("Manifest %s not found in %s (variant '%s')?" % (manifest, d2.expand(" ".join(pkgarchs)), variant)) + bb.error("Manifest %s not found in %s (variant '%s')?" % (manifest, d2.expand(" ".join(pkgarchs)), variant)) return None, d2 def OEOuthashBasic(path, sigfile, task, d): @@ -477,6 +477,8 @@ def OEOuthashBasic(path, sigfile, task, d): h = hashlib.sha256() prev_dir = os.getcwd() include_owners = os.environ.get('PSEUDO_DISABLED') == '0' + if "package_write_" in task or task == "package_qa": + include_owners = False include_timestamps = False if task == "package": include_timestamps = d.getVar('BUILD_REPRODUCIBLE_BINARIES') == '1' @@ -550,9 +552,11 @@ def OEOuthashBasic(path, sigfile, task, d): try: update_hash(" %10s" % pwd.getpwuid(s.st_uid).pw_name) update_hash(" %10s" % grp.getgrgid(s.st_gid).gr_name) - except KeyError: + except KeyError as e: bb.warn("KeyError in %s" % path) - raise + msg = ("KeyError: %s\nPath %s is owned by uid %d, gid %d, which doesn't match " + "any user/group on target. This may be due to host contamination." % (e, path, s.st_uid, s.st_gid)) + raise Exception(msg).with_traceback(e.__traceback__) if include_timestamps: update_hash(" %10d" % s.st_mtime) diff --git a/poky/meta/lib/oeqa/runtime/cases/df.py b/poky/meta/lib/oeqa/runtime/cases/df.py index 89fd0fb901..bb155c9cf9 100644 --- a/poky/meta/lib/oeqa/runtime/cases/df.py +++ b/poky/meta/lib/oeqa/runtime/cases/df.py @@ -4,12 +4,14 @@ from oeqa.runtime.case import OERuntimeTestCase from oeqa.core.decorator.depends import OETestDepends +from oeqa.core.decorator.data import skipIfDataVar, skipIfInDataVar from oeqa.runtime.decorator.package import OEHasPackage class DfTest(OERuntimeTestCase): @OETestDepends(['ssh.SSHTest.test_ssh']) @OEHasPackage(['coreutils', 'busybox']) + @skipIfInDataVar('IMAGE_FEATURES', 'read-only-rootfs', 'Test case df requires a writable rootfs') def test_df(self): cmd = "df -P / | sed -n '2p' | awk '{print $4}'" (status,output) = self.target.run(cmd) diff --git a/poky/meta/lib/oeqa/runtime/cases/ptest.py b/poky/meta/lib/oeqa/runtime/cases/ptest.py index ef0470da7e..2066d009c3 100644 --- a/poky/meta/lib/oeqa/runtime/cases/ptest.py +++ b/poky/meta/lib/oeqa/runtime/cases/ptest.py @@ -104,4 +104,5 @@ class PtestRunnerTest(OERuntimeTestCase): failmsg = failmsg + "Failed ptests:\n%s" % pprint.pformat(failed_tests) if failmsg: + self.logger.warning("There were failing ptests.") self.fail(failmsg) diff --git a/poky/meta/lib/oeqa/runtime/cases/runlevel.py b/poky/meta/lib/oeqa/runtime/cases/runlevel.py new file mode 100644 index 0000000000..3a4df8ace1 --- /dev/null +++ b/poky/meta/lib/oeqa/runtime/cases/runlevel.py @@ -0,0 +1,22 @@ +from oeqa.runtime.case import OERuntimeTestCase +from oeqa.core.decorator.depends import OETestDepends + +import time + +class RunLevel_Test(OERuntimeTestCase): + + @OETestDepends(['ssh.SSHTest.test_ssh']) + def test_runlevel_3(self): + (status, output) = self.target.run("init 3 && sleep 5 && runlevel") + runlevel= '5 3' + self.assertEqual(output, runlevel, msg='Failed to set current runlevel to runlevel 3, current runlevel : %s' % output[-1]) + (status, output) = self.target.run("uname -a") + self.assertEqual(status, 0, msg='Failed to run uname command, output: %s' % output) + + @OETestDepends(['runlevel.RunLevel_Test.test_runlevel_3']) + def test_runlevel_5(self): + (status, output) = self.target.run("init 5 && sleep 5 && runlevel") + runlevel = '3 5' + self.assertEqual(output, runlevel, msg='Failed to set current runlevel to runlevel 5, current runlevel : %s' % output[-1]) + (status, output) = self.target.run('export DISPLAY=:0 && x11perf -aa10text') + self.assertEqual(status, 0, msg='Failed to run 2D graphic test, output: %s' % output) diff --git a/poky/meta/lib/oeqa/selftest/cases/cve_check.py b/poky/meta/lib/oeqa/selftest/cases/cve_check.py new file mode 100644 index 0000000000..3f343a2841 --- /dev/null +++ b/poky/meta/lib/oeqa/selftest/cases/cve_check.py @@ -0,0 +1,36 @@ +from oe.cve_check import Version +from oeqa.selftest.case import OESelftestTestCase + +class CVECheck(OESelftestTestCase): + + def test_version_compare(self): + result = Version("100") > Version("99") + self.assertTrue( result, msg="Failed to compare version '100' > '99'") + result = Version("2.3.1") > Version("2.2.3") + self.assertTrue( result, msg="Failed to compare version '2.3.1' > '2.2.3'") + result = Version("2021-01-21") > Version("2020-12-25") + self.assertTrue( result, msg="Failed to compare version '2021-01-21' > '2020-12-25'") + result = Version("1.2-20200910") < Version("1.2-20200920") + self.assertTrue( result, msg="Failed to compare version '1.2-20200910' < '1.2-20200920'") + + result = Version("1.0") >= Version("1.0beta") + self.assertTrue( result, msg="Failed to compare version '1.0' >= '1.0beta'") + result = Version("1.0-rc2") > Version("1.0-rc1") + self.assertTrue( result, msg="Failed to compare version '1.0-rc2' > '1.0-rc1'") + result = Version("1.0.alpha1") < Version("1.0") + self.assertTrue( result, msg="Failed to compare version '1.0.alpha1' < '1.0'") + result = Version("1.0_dev") <= Version("1.0") + self.assertTrue( result, msg="Failed to compare version '1.0_dev' <= '1.0'") + + # ignore "p1" and "p2", so these should be equal + result = Version("1.0p2") == Version("1.0p1") + self.assertTrue( result ,msg="Failed to compare version '1.0p2' to '1.0p1'") + # ignore the "b" and "r" + result = Version("1.0b") == Version("1.0r") + self.assertTrue( result ,msg="Failed to compare version '1.0b' to '1.0r'") + + # consider the trailing alphabet as patched level when comparing + result = Version("1.0b","alphabetical") < Version("1.0r","alphabetical") + self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' < '1.0r'") + result = Version("1.0b","alphabetical") > Version("1.0","alphabetical") + self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' > '1.0'") diff --git a/poky/meta/lib/oeqa/selftest/cases/devtool.py b/poky/meta/lib/oeqa/selftest/cases/devtool.py index ddf46547de..0985434238 100644 --- a/poky/meta/lib/oeqa/selftest/cases/devtool.py +++ b/poky/meta/lib/oeqa/selftest/cases/devtool.py @@ -693,7 +693,44 @@ class DevtoolModifyTests(DevtoolBase): self.assertTrue(bbclassextended, 'None of these recipes are BBCLASSEXTENDed to native - need to adjust testrecipes list: %s' % ', '.join(testrecipes)) self.assertTrue(inheritnative, 'None of these recipes do "inherit native" - need to adjust testrecipes list: %s' % ', '.join(testrecipes)) + def test_devtool_modify_localfiles_only(self): + # Check preconditions + testrecipe = 'base-files' + src_uri = (get_bb_var('SRC_URI', testrecipe) or '').split() + foundlocalonly = False + correct_symlink = False + for item in src_uri: + if item.startswith('file://'): + if '.patch' not in item: + foundlocalonly = True + else: + foundlocalonly = False + break + self.assertTrue(foundlocalonly, 'This test expects the %s recipe to fetch local files only and it seems that it no longer does' % testrecipe) + # Clean up anything in the workdir/sysroot/sstate cache + bitbake('%s -c cleansstate' % testrecipe) + # Try modifying a recipe + tempdir = tempfile.mkdtemp(prefix='devtoolqa') + self.track_for_cleanup(tempdir) + self.track_for_cleanup(self.workspacedir) + self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe) + self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') + result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir)) + srcfile = os.path.join(tempdir, 'oe-local-files/share/dot.bashrc') + srclink = os.path.join(tempdir, 'share/dot.bashrc') + self.assertExists(srcfile, 'Extracted source could not be found') + if os.path.islink(srclink) and os.path.exists(srclink) and os.path.samefile(srcfile, srclink): + correct_symlink = True + self.assertTrue(correct_symlink, 'Source symlink to oe-local-files is broken') + matches = glob.glob(os.path.join(self.workspacedir, 'appends', '%s_*.bbappend' % testrecipe)) + self.assertTrue(matches, 'bbappend not created') + # Test devtool status + result = runCmd('devtool status') + self.assertIn(testrecipe, result.output) + self.assertIn(tempdir, result.output) + # Try building + bitbake(testrecipe) def test_devtool_modify_git(self): # Check preconditions diff --git a/poky/meta/lib/oeqa/selftest/cases/prservice.py b/poky/meta/lib/oeqa/selftest/cases/prservice.py index 85b534963d..578b2b4dd9 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 pkg revisions is not 1 (was %s - %s)" % (pr_2, pr_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 pkg revisions is not 1 (was %s - %s)" % (pr_2, pr_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/pseudo.py b/poky/meta/lib/oeqa/selftest/cases/pseudo.py new file mode 100644 index 0000000000..33593d5ce9 --- /dev/null +++ b/poky/meta/lib/oeqa/selftest/cases/pseudo.py @@ -0,0 +1,27 @@ +# +# SPDX-License-Identifier: MIT +# + +import glob +import os +import shutil +from oeqa.utils.commands import bitbake, get_test_layer +from oeqa.selftest.case import OESelftestTestCase + +class Pseudo(OESelftestTestCase): + + def test_pseudo_pyc_creation(self): + self.write_config("") + + metaselftestpath = get_test_layer() + pycache_path = os.path.join(metaselftestpath, 'lib/__pycache__') + if os.path.exists(pycache_path): + shutil.rmtree(pycache_path) + + bitbake('pseudo-pyc-test -c install') + + test1_pyc_present = len(glob.glob(os.path.join(pycache_path, 'pseudo_pyc_test1.*.pyc'))) + self.assertTrue(test1_pyc_present, 'test1 pyc file missing, should be created outside of pseudo context.') + + test2_pyc_present = len(glob.glob(os.path.join(pycache_path, 'pseudo_pyc_test2.*.pyc'))) + self.assertFalse(test2_pyc_present, 'test2 pyc file present, should not be created in pseudo context.') diff --git a/poky/meta/lib/oeqa/selftest/cases/reproducible.py b/poky/meta/lib/oeqa/selftest/cases/reproducible.py index 5d3959be77..7f74cec28f 100644 --- a/poky/meta/lib/oeqa/selftest/cases/reproducible.py +++ b/poky/meta/lib/oeqa/selftest/cases/reproducible.py @@ -68,7 +68,7 @@ def compare_file(reference, test, diffutils_sysroot): result.status = MISSING return result - r = runCmd(['cmp', '--quiet', reference, test], native_sysroot=diffutils_sysroot, ignore_status=True) + r = runCmd(['cmp', '--quiet', reference, test], native_sysroot=diffutils_sysroot, ignore_status=True, sync=False) if r.status: result.status = DIFFERENT @@ -158,9 +158,10 @@ class ReproducibleTests(OESelftestTestCase): # mirror, forcing a complete build from scratch config += textwrap.dedent('''\ SSTATE_DIR = "${TMPDIR}/sstate" - SSTATE_MIRROR = "" + SSTATE_MIRRORS = "" ''') + self.logger.info("Building %s (sstate%s allowed)..." % (name, '' if use_sstate else ' NOT')) self.write_config(config) d = get_bb_vars(capture_vars) bitbake(' '.join(self.images)) @@ -187,6 +188,7 @@ class ReproducibleTests(OESelftestTestCase): self.logger.info('Non-reproducible packages will be copied to %s', save_dir) vars_A = self.do_test_build('reproducibleA', self.build_from_sstate) + vars_B = self.do_test_build('reproducibleB', False) # NOTE: The temp directories from the reproducible build are purposely @@ -201,6 +203,7 @@ class ReproducibleTests(OESelftestTestCase): deploy_A = vars_A['DEPLOY_DIR_' + c.upper()] deploy_B = vars_B['DEPLOY_DIR_' + c.upper()] + self.logger.info('Checking %s packages for differences...' % c) result = self.compare_packages(deploy_A, deploy_B, diffutils_sysroot) self.logger.info('Reproducibility summary for %s: %s' % (c, result)) diff --git a/poky/meta/lib/oeqa/selftest/cases/runtime_test.py b/poky/meta/lib/oeqa/selftest/cases/runtime_test.py index cd03069340..976b513727 100644 --- a/poky/meta/lib/oeqa/selftest/cases/runtime_test.py +++ b/poky/meta/lib/oeqa/selftest/cases/runtime_test.py @@ -161,6 +161,7 @@ class TestImage(OESelftestTestCase): features += 'PACKAGE_FEED_GPG_NAME = "testuser"\n' features += 'PACKAGE_FEED_GPG_PASSPHRASE_FILE = "%s"\n' % os.path.join(signing_key_dir, 'key.passphrase') features += 'GPG_PATH = "%s"\n' % self.gpg_home + features += 'PSEUDO_IGNORE_PATHS .= ",%s"\n' % self.gpg_home self.write_config(features) # Build core-image-sato and testimage diff --git a/poky/meta/lib/oeqa/selftest/cases/tinfoil.py b/poky/meta/lib/oeqa/selftest/cases/tinfoil.py index 206168ed00..a51c6048d3 100644 --- a/poky/meta/lib/oeqa/selftest/cases/tinfoil.py +++ b/poky/meta/lib/oeqa/selftest/cases/tinfoil.py @@ -100,9 +100,11 @@ class TinfoilTests(OESelftestTestCase): eventreceived = False commandcomplete = False start = time.time() - # Wait for 10s in total so we'd detect spurious heartbeat events for example + # Wait for maximum 60s in total so we'd detect spurious heartbeat events for example # The test is IO load sensitive too - while time.time() - start < 10: + while (not (eventreceived == True and commandcomplete == True) + and (time.time() - start < 60)): + # if we received both events (on let's say a good day), we are done 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 13b6a0cc72..0435aa29c9 100644 --- a/poky/meta/lib/oeqa/selftest/cases/wic.py +++ b/poky/meta/lib/oeqa/selftest/cases/wic.py @@ -62,6 +62,12 @@ def extract_files(debugfs_output): 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.""" @@ -84,6 +90,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) @@ -506,6 +513,105 @@ part /part2 --source rootfs --ondisk mmcblk0 --fstype=ext4 --include-path %s""" % (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) + class Wic2(WicTestCase): def test_bmap_short(self): diff --git a/poky/meta/lib/oeqa/utils/commands.py b/poky/meta/lib/oeqa/utils/commands.py index 8b3e12038d..a71c16ab14 100644 --- a/poky/meta/lib/oeqa/utils/commands.py +++ b/poky/meta/lib/oeqa/utils/commands.py @@ -125,11 +125,11 @@ class Command(object): def stop(self): for thread in self.threads: - if thread.isAlive(): + if thread.is_alive(): self.process.terminate() # let's give it more time to terminate gracefully before killing it thread.join(5) - if thread.isAlive(): + if thread.is_alive(): self.process.kill() thread.join() |