diff options
Diffstat (limited to 'poky/meta/lib')
-rw-r--r-- | poky/meta/lib/oe/gpg_sign.py | 27 | ||||
-rw-r--r-- | poky/meta/lib/oe/package.py | 7 | ||||
-rw-r--r-- | poky/meta/lib/oe/patch.py | 68 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/core/loader.py | 3 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/runtime/cases/apt.py | 4 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/runtime/cases/buildcpio.py | 7 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/runtime/cases/ping.py | 3 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/runtime/cases/systemd.py | 2 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/bblogging.py | 18 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/devtool.py | 93 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/efibootpartition.py | 2 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/imagefeatures.py | 8 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/runqemu.py | 28 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/wic.py | 23 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/context.py | 10 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/targetcontrol.py | 12 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/utils/commands.py | 8 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/utils/metadata.py | 6 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/utils/qemurunner.py | 34 |
19 files changed, 263 insertions, 100 deletions
diff --git a/poky/meta/lib/oe/gpg_sign.py b/poky/meta/lib/oe/gpg_sign.py index 613dab8561..ede6186c84 100644 --- a/poky/meta/lib/oe/gpg_sign.py +++ b/poky/meta/lib/oe/gpg_sign.py @@ -5,11 +5,12 @@ # """Helper module for GPG signing""" -import os import bb -import subprocess +import os import shlex +import subprocess +import tempfile class LocalSigner(object): """Class for handling local (on the build host) signing""" @@ -73,8 +74,6 @@ class LocalSigner(object): cmd += ['--homedir', self.gpg_path] if armor: cmd += ['--armor'] - if output_suffix: - cmd += ['-o', input_file + "." + output_suffix] if use_sha256: cmd += ['--digest-algo', "SHA256"] @@ -83,19 +82,27 @@ class LocalSigner(object): if self.gpg_version > (2,1,): cmd += ['--pinentry-mode', 'loopback'] - cmd += [input_file] - try: if passphrase_file: with open(passphrase_file) as fobj: passphrase = fobj.readline(); - job = subprocess.Popen(cmd, stdin=subprocess.PIPE, stderr=subprocess.PIPE) - (_, stderr) = job.communicate(passphrase.encode("utf-8")) + if not output_suffix: + output_suffix = 'asc' if armor else 'sig' + output_file = input_file + "." + output_suffix + with tempfile.TemporaryDirectory(dir=os.path.dirname(output_file)) as tmp_dir: + tmp_file = os.path.join(tmp_dir, os.path.basename(output_file)) + cmd += ['-o', tmp_file] + + cmd += [input_file] + + job = subprocess.Popen(cmd, stdin=subprocess.PIPE, stderr=subprocess.PIPE) + (_, stderr) = job.communicate(passphrase.encode("utf-8")) - if job.returncode: - bb.fatal("GPG exited with code %d: %s" % (job.returncode, stderr.decode("utf-8"))) + if job.returncode: + bb.fatal("GPG exited with code %d: %s" % (job.returncode, stderr.decode("utf-8"))) + os.rename(tmp_file, output_file) except IOError as e: bb.error("IO error (%s): %s" % (e.errno, e.strerror)) raise Exception("Failed to sign '%s'" % input_file) diff --git a/poky/meta/lib/oe/package.py b/poky/meta/lib/oe/package.py index 7a6b31957a..edb70daaf1 100644 --- a/poky/meta/lib/oe/package.py +++ b/poky/meta/lib/oe/package.py @@ -8,7 +8,7 @@ import errno import fnmatch import itertools import os -import pipes +import shlex import re import glob import stat @@ -41,7 +41,7 @@ def runstrip(arg): stripcmd = [strip] skip_strip = False - # kernel module + # kernel module if elftype & 16: if is_kernel_module_signed(file): bb.debug(1, "Skip strip on signed module %s" % file) @@ -1556,7 +1556,7 @@ def process_shlibs(pkgfiles, d): sonames = set() renames = [] ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '') - cmd = d.getVar('OBJDUMP') + " -p " + pipes.quote(file) + " 2>/dev/null" + cmd = d.getVar('OBJDUMP') + " -p " + shlex.quote(file) + " 2>/dev/null" fd = os.popen(cmd) lines = fd.readlines() fd.close() @@ -2012,4 +2012,3 @@ def process_depchains(pkgfiles, d): for dep in bb.utils.explode_deps(d.getVar('RDEPENDS:' + base) or ""): add_dep(rdeps, dep) pkg_addrrecs(pkg, base, suffix, func, rdeps, d) - diff --git a/poky/meta/lib/oe/patch.py b/poky/meta/lib/oe/patch.py index b2dc8d0a90..5990896fdc 100644 --- a/poky/meta/lib/oe/patch.py +++ b/poky/meta/lib/oe/patch.py @@ -4,9 +4,11 @@ # SPDX-License-Identifier: GPL-2.0-only # +import os +import shlex +import subprocess import oe.path import oe.types -import subprocess class NotFoundError(bb.BBHandledException): def __init__(self, path): @@ -27,8 +29,6 @@ class CmdError(bb.BBHandledException): def runcmd(args, dir = None): - import pipes - if dir: olddir = os.path.abspath(os.curdir) if not os.path.exists(dir): @@ -37,7 +37,7 @@ def runcmd(args, dir = None): # print("cwd: %s -> %s" % (olddir, dir)) try: - args = [ pipes.quote(str(arg)) for arg in args ] + args = [ shlex.quote(str(arg)) for arg in args ] cmd = " ".join(args) # print("cmd: %s" % cmd) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) @@ -217,7 +217,7 @@ class PatchTree(PatchSet): with open(self.seriespath, 'w') as f: for p in patches: f.write(p) - + def Import(self, patch, force = None): """""" PatchSet.Import(self, patch, force) @@ -499,6 +499,36 @@ class GitApplyTree(PatchTree): finally: shutil.rmtree(tempdir) + def _need_dirty_check(self): + fetch = bb.fetch2.Fetch([], self.d) + check_dirtyness = False + for url in fetch.urls: + url_data = fetch.ud[url] + parm = url_data.parm + # a git url with subpath param will surely be dirty + # since the git tree from which we clone will be emptied + # from all files that are not in the subpath + if url_data.type == 'git' and parm.get('subpath'): + check_dirtyness = True + return check_dirtyness + + def _commitpatch(self, patch, patchfilevar): + output = "" + # Add all files + shellcmd = ["git", "add", "-f", "-A", "."] + output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir) + # Exclude the patches directory + shellcmd = ["git", "reset", "HEAD", self.patchdir] + output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir) + # Commit the result + (tmpfile, shellcmd) = self.prepareCommit(patch['file'], self.commituser, self.commitemail) + try: + shellcmd.insert(0, patchfilevar) + output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir) + finally: + os.remove(tmpfile) + return output + def _applypatch(self, patch, force = False, reverse = False, run = True): import shutil @@ -534,6 +564,19 @@ class GitApplyTree(PatchTree): shutil.copy2(commithook, applyhook) try: patchfilevar = 'PATCHFILE="%s"' % os.path.basename(patch['file']) + if self._need_dirty_check(): + # Check dirtyness of the tree + try: + output = runcmd(["git", "--work-tree=%s" % reporoot, "status", "--short"]) + except CmdError: + pass + else: + if output: + # The tree is dirty, not need to try to apply patches with git anymore + # since they fail, fallback directly to patch + output = PatchTree._applypatch(self, patch, force, reverse, run) + output += self._commitpatch(patch, patchfilevar) + return output try: shellcmd = [patchfilevar, "git", "--work-tree=%s" % reporoot] self.gitCommandUserOptions(shellcmd, self.commituser, self.commitemail) @@ -560,19 +603,7 @@ class GitApplyTree(PatchTree): except CmdError: # Fall back to patch output = PatchTree._applypatch(self, patch, force, reverse, run) - # Add all files - shellcmd = ["git", "add", "-f", "-A", "."] - output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir) - # Exclude the patches directory - shellcmd = ["git", "reset", "HEAD", self.patchdir] - output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir) - # Commit the result - (tmpfile, shellcmd) = self.prepareCommit(patch['file'], self.commituser, self.commitemail) - try: - shellcmd.insert(0, patchfilevar) - output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir) - finally: - os.remove(tmpfile) + output += self._commitpatch(patch, patchfilevar) return output finally: shutil.rmtree(hooks_dir) @@ -921,4 +952,3 @@ def should_apply(parm, d): return False, "applies to later version" return True, None - diff --git a/poky/meta/lib/oeqa/core/loader.py b/poky/meta/lib/oeqa/core/loader.py index f25b5970e9..d12d5a055c 100644 --- a/poky/meta/lib/oeqa/core/loader.py +++ b/poky/meta/lib/oeqa/core/loader.py @@ -316,6 +316,9 @@ class OETestLoader(unittest.TestLoader): module_name_small in self.modules) \ else False + if any(c.isupper() for c in module.__name__): + raise SystemExit("Module '%s' contains uppercase characters and this isn't supported. Please fix the module name." % module.__name__) + return (load_module, load_underscore) diff --git a/poky/meta/lib/oeqa/runtime/cases/apt.py b/poky/meta/lib/oeqa/runtime/cases/apt.py index 4e09374add..8000645843 100644 --- a/poky/meta/lib/oeqa/runtime/cases/apt.py +++ b/poky/meta/lib/oeqa/runtime/cases/apt.py @@ -39,9 +39,9 @@ class AptRepoTest(AptTest): self.target.run('cd %s; echo deb [ allow-insecure=yes ] %s/all ./ > sources.list' % (apt_get_sourceslist_dir, apt_get_source_server)) def setup_source_config_for_package_install_signed(self): - apt_get_source_server = 'http:\/\/%s:%s' % (self.tc.target.server_ip, self.repo_server.port) + apt_get_source_server = 'http://%s:%s' % (self.tc.target.server_ip, self.repo_server.port) apt_get_sourceslist_dir = '/etc/apt/' - self.target.run("cd %s; cp sources.list sources.list.bak; sed -i 's/\[trusted=yes\] http:\/\/bogus_ip:bogus_port/%s/g' sources.list" % (apt_get_sourceslist_dir, apt_get_source_server)) + self.target.run("cd %s; cp sources.list sources.list.bak; sed -i 's|\[trusted=yes\] http://bogus_ip:bogus_port|%s|g' sources.list" % (apt_get_sourceslist_dir, apt_get_source_server)) def cleanup_source_config_for_package_install(self): apt_get_sourceslist_dir = '/etc/apt/' diff --git a/poky/meta/lib/oeqa/runtime/cases/buildcpio.py b/poky/meta/lib/oeqa/runtime/cases/buildcpio.py index bd3b46d9ef..3728855d24 100644 --- a/poky/meta/lib/oeqa/runtime/cases/buildcpio.py +++ b/poky/meta/lib/oeqa/runtime/cases/buildcpio.py @@ -29,7 +29,10 @@ class BuildCpioTest(OERuntimeTestCase): @OEHasPackage(['autoconf']) def test_cpio(self): self.project.download_archive() - self.project.run_configure('--disable-maintainer-mode', - 'sed -i -e "/char \*program_name/d" src/global.c;') + self.project.run_configure('--disable-maintainer-mode') + # This sed is needed until + # https://git.savannah.gnu.org/cgit/cpio.git/commit/src/global.c?id=641d3f489cf6238bb916368d4ba0d9325a235afb + # is in a release. + self.project._run(r'sed -i -e "/char \*program_name/d" %s/src/global.c' % self.project.targetdir) self.project.run_make() self.project.run_install() diff --git a/poky/meta/lib/oeqa/runtime/cases/ping.py b/poky/meta/lib/oeqa/runtime/cases/ping.py index 967b44175f..f72460e7f3 100644 --- a/poky/meta/lib/oeqa/runtime/cases/ping.py +++ b/poky/meta/lib/oeqa/runtime/cases/ping.py @@ -5,6 +5,7 @@ # from subprocess import Popen, PIPE +from time import sleep from oeqa.runtime.case import OERuntimeTestCase from oeqa.core.decorator.oetimeout import OETimeout @@ -16,6 +17,7 @@ class PingTest(OERuntimeTestCase): def test_ping(self): output = '' count = 0 + self.assertNotEqual(len(self.target.ip), 0, msg="No target IP address set") try: while count < 5: cmd = 'ping -c 1 %s' % self.target.ip @@ -25,6 +27,7 @@ class PingTest(OERuntimeTestCase): count += 1 else: count = 0 + sleep(1) except OEQATimeoutError: self.fail("Ping timeout error for address %s, count %s, output: %s" % (self.target.ip, count, output)) msg = ('Expected 5 consecutive, got %d.\n' diff --git a/poky/meta/lib/oeqa/runtime/cases/systemd.py b/poky/meta/lib/oeqa/runtime/cases/systemd.py index 720b4b517a..37f295492d 100644 --- a/poky/meta/lib/oeqa/runtime/cases/systemd.py +++ b/poky/meta/lib/oeqa/runtime/cases/systemd.py @@ -154,7 +154,7 @@ class SystemdJournalTests(SystemdTest): """ # The expression chain that uniquely identifies the time boot message. - expr_items=['Startup finished', 'kernel', 'userspace','\.$'] + expr_items=['Startup finished', 'kernel', 'userspace', r'\.$'] try: output = self.journalctl(args='-o cat --reverse') except AssertionError: diff --git a/poky/meta/lib/oeqa/selftest/cases/bblogging.py b/poky/meta/lib/oeqa/selftest/cases/bblogging.py index 1534a36a85..040c6db089 100644 --- a/poky/meta/lib/oeqa/selftest/cases/bblogging.py +++ b/poky/meta/lib/oeqa/selftest/cases/bblogging.py @@ -105,16 +105,14 @@ class BitBakeLogging(OESelftestTestCase): self.write_config('BBINCLUDELOGS = ""') result = bitbake("logging-test -c pythontest_exit -f -v", ignore_status = True) self.assertIn("ERROR: Logfile of failure stored in:", result.output) - # python tasks don't log output with -v currently - #self.assertCount(result.output, "This is python stdout", 1) + self.assertCount(result.output, "This is python stdout", 1) def test_python_exit_loggingD(self): # logs, verbose self.write_config('BBINCLUDELOGS = "yes"') result = bitbake("logging-test -c pythontest_exit -f -v", ignore_status = True) self.assertIn("ERROR: Logfile of failure stored in:", result.output) - # python tasks don't log output with -v currently - #self.assertCount(result.output, "This is python stdout", 1) + self.assertCount(result.output, "This is python stdout", 1) def test_python_exec_func_python_loggingA(self): # no logs, no verbose @@ -139,8 +137,7 @@ class BitBakeLogging(OESelftestTestCase): result = bitbake("logging-test -c pythontest_exec_func_python -f -v", ignore_status = True) self.assertIn("ERROR: Logfile of failure stored in:", result.output) - # python tasks don't log output with -v currently - #self.assertCount(result.output, "This is python stdout", 1) + self.assertCount(result.output, "This is python stdout", 1) def test_python_exec_func_python_loggingD(self): # logs, verbose @@ -148,8 +145,7 @@ class BitBakeLogging(OESelftestTestCase): result = bitbake("logging-test -c pythontest_exec_func_python -f -v", ignore_status = True) self.assertIn("ERROR: Logfile of failure stored in:", result.output) - # python tasks don't log output with -v currently - #self.assertCount(result.output, "This is python stdout", 1) + self.assertCount(result.output, "This is python stdout", 1) def test_python_fatal_loggingA(self): # no logs, no verbose @@ -173,8 +169,7 @@ class BitBakeLogging(OESelftestTestCase): self.write_config('BBINCLUDELOGS = ""') result = bitbake("logging-test -c pythontest_fatal -f -v", ignore_status = True) self.assertIn("ERROR: Logfile of failure stored in:", result.output) - # python tasks don't log output with -v currently - #self.assertCount(result.output, "This is python fatal test stdout", 1) + self.assertCount(result.output, "This is python fatal test stdout", 1) self.assertCount(result.output, "This is a fatal error", 1) def test_python_fatal_loggingD(self): @@ -182,7 +177,6 @@ class BitBakeLogging(OESelftestTestCase): self.write_config('BBINCLUDELOGS = "yes"') result = bitbake("logging-test -c pythontest_fatal -f -v", ignore_status = True) self.assertIn("ERROR: Logfile of failure stored in:", result.output) - # python tasks don't log output with -v currently - #self.assertCount(result.output, "This is python fatal test stdout", 1) + self.assertCount(result.output, "This is python fatal test stdout", 1) self.assertCount(result.output, "This is a fatal error", 1) diff --git a/poky/meta/lib/oeqa/selftest/cases/devtool.py b/poky/meta/lib/oeqa/selftest/cases/devtool.py index 81d02017c1..94873fd19f 100644 --- a/poky/meta/lib/oeqa/selftest/cases/devtool.py +++ b/poky/meta/lib/oeqa/selftest/cases/devtool.py @@ -848,6 +848,99 @@ class DevtoolModifyTests(DevtoolBase): # Try building bitbake(testrecipe) + def test_devtool_modify_git_crates_subpath(self): + # This tests two things in devtool context: + # - that we support local git dependencies for cargo based recipe + # - that we support patches in SRC_URI when git url contains subpath parameter + + # Check preconditions: + # recipe inherits cargo + # git:// uri with a subpath as the main package + # some crate:// in SRC_URI + # others git:// in SRC_URI + # cointains a patch + testrecipe = 'zvariant' + bb_vars = get_bb_vars(['SRC_URI', 'FILE', 'WORKDIR', 'CARGO_HOME'], testrecipe) + recipefile = bb_vars['FILE'] + workdir = bb_vars['WORKDIR'] + cargo_home = bb_vars['CARGO_HOME'] + src_uri = bb_vars['SRC_URI'].split() + self.assertTrue(src_uri[0].startswith('git://'), + 'This test expects the %s recipe to have a git repo has its main uri' % testrecipe) + self.assertIn(';subpath=', src_uri[0], + 'This test expects the %s recipe to have a git uri with subpath' % testrecipe) + self.assertTrue(any([uri.startswith('crate://') for uri in src_uri]), + 'This test expects the %s recipe to have some crates in its src uris' % testrecipe) + self.assertGreater(sum(map(lambda x:x.startswith('git://'), src_uri)), 2, + 'This test expects the %s recipe to have several git:// uris' % testrecipe) + self.assertTrue(any([uri.startswith('file://') and '.patch' in uri for uri in src_uri]), + 'This test expects the %s recipe to have a patch in its src uris' % testrecipe) + + self._test_recipe_contents(recipefile, {}, ['cargo']) + + # 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)) + self.assertExists(os.path.join(tempdir, 'Cargo.toml'), 'Extracted source could not be found') + self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created. devtool output: %s' % result.output) + matches = glob.glob(os.path.join(self.workspacedir, 'appends', 'zvariant_*.bbappend')) + self.assertTrue(matches, 'bbappend not created') + # Test devtool status + result = runCmd('devtool status') + self.assertIn(testrecipe, result.output) + self.assertIn(tempdir, result.output) + # Check git repo + self._check_src_repo(tempdir) + # Check that the patch is correctly applied + # last commit message in the tree must contain + # %% original patch: <patchname> + # .. + patchname = None + for uri in src_uri: + if uri.startswith('file://') and '.patch' in uri: + patchname = uri.replace("file://", "").partition('.patch')[0] + '.patch' + self.assertIsNotNone(patchname) + result = runCmd('git -C %s log -1' % tempdir) + self.assertIn("%%%% original patch: %s" % patchname, result.output) + + # Configure the recipe to check that the git dependencies are correctly patched in cargo config + bitbake('-c configure %s' % testrecipe) + + cargo_config_path = os.path.join(cargo_home, 'config') + with open(cargo_config_path, "r") as f: + cargo_config_contents = [line.strip('\n') for line in f.readlines()] + + # Get back git dependencies of the recipe (ignoring the main one) + # and check that they are all correctly patched to be fetched locally + git_deps = [uri for uri in src_uri if uri.startswith("git://")][1:] + for git_dep in git_deps: + raw_url, _, raw_parms = git_dep.partition(";") + parms = {} + for parm in raw_parms.split(";"): + name_parm, _, value_parm = parm.partition('=') + parms[name_parm]=value_parm + self.assertIn('protocol', parms, 'git dependencies uri should contain the "protocol" parameter') + self.assertIn('name', parms, 'git dependencies uri should contain the "name" parameter') + self.assertIn('destsuffix', parms, 'git dependencies uri should contain the "destsuffix" parameter') + self.assertIn('type', parms, 'git dependencies uri should contain the "type" parameter') + self.assertEqual(parms['type'], 'git-dependency', 'git dependencies uri should have "type=git-dependency"') + raw_url = raw_url.replace("git://", '%s://' % parms['protocol']) + patch_line = '[patch."%s"]' % raw_url + path_patched = os.path.join(workdir, parms['destsuffix']) + path_override_line = '%s = { path = "%s" }' % (parms['name'], path_patched) + # Would have been better to use tomllib to read this file :/ + self.assertIn(patch_line, cargo_config_contents) + self.assertIn(path_override_line, cargo_config_contents) + + # Try to package the recipe + bitbake('-c package_qa %s' % testrecipe) + def test_devtool_modify_localfiles(self): # Check preconditions testrecipe = 'lighttpd' diff --git a/poky/meta/lib/oeqa/selftest/cases/efibootpartition.py b/poky/meta/lib/oeqa/selftest/cases/efibootpartition.py index e17da9f9a0..fa74103dec 100644 --- a/poky/meta/lib/oeqa/selftest/cases/efibootpartition.py +++ b/poky/meta/lib/oeqa/selftest/cases/efibootpartition.py @@ -15,7 +15,7 @@ class GenericEFITest(OESelftestTestCase): @skipIfNotMachine("qemux86-64", "test is qemux86-64 specific currently") def test_boot_efi(self): cmd = "runqemu nographic serial wic ovmf" - if oe.types.qemu_use_kvm(self.td['QEMU_USE_KVM'], self.td["TARGET_ARCH"]): + if oe.types.qemu_use_kvm(self.td.get('QEMU_USE_KVM', 0), self.td["TARGET_ARCH"]): cmd += " kvm" image = "core-image-minimal" diff --git a/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py b/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py index d31b43d9cc..0292c882f2 100644 --- a/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py +++ b/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py @@ -229,10 +229,10 @@ UBINIZE_ARGS_mtd_4_256 ?= "-m 4096 -p 256KiB" self.assertTrue(os.path.exists(image_path), "%s image %s doesn't exist" % (itype, image_path)) else: - image_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], "%s.%s" % (bb_vars['IMAGE_LINK_NAME'], itype)) - # check if result image is in deploy directory - self.assertTrue(os.path.exists(image_path), - "%s image %s doesn't exist" % (itype, image_path)) + image_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], "%s.%s" % (bb_vars['IMAGE_LINK_NAME'], itype)) + # check if result image is in deploy directory + self.assertTrue(os.path.exists(image_path), + "%s image %s doesn't exist" % (itype, image_path)) def test_useradd_static(self): config = """ diff --git a/poky/meta/lib/oeqa/selftest/cases/runqemu.py b/poky/meta/lib/oeqa/selftest/cases/runqemu.py index e72ff529c4..f01e1eec66 100644 --- a/poky/meta/lib/oeqa/selftest/cases/runqemu.py +++ b/poky/meta/lib/oeqa/selftest/cases/runqemu.py @@ -4,14 +4,15 @@ # SPDX-License-Identifier: MIT # +import os import re -import tempfile import time import oe.types from oeqa.core.decorator import OETestTag from oeqa.core.decorator.data import skipIfNotArch, skipIfNotMachine from oeqa.selftest.case import OESelftestTestCase -from oeqa.utils.commands import bitbake, runqemu, get_bb_var, runCmd +from oeqa.utils.commands import bitbake, runqemu, get_bb_var + @OETestTag("runqemu") class RunqemuTests(OESelftestTestCase): @@ -23,8 +24,8 @@ class RunqemuTests(OESelftestTestCase): def setUpLocal(self): super(RunqemuTests, self).setUpLocal() self.recipe = 'core-image-minimal' - self.machine = self.td['MACHINE'] - self.image_link_name = get_bb_var('IMAGE_LINK_NAME', self.recipe) + self.machine = self.td['MACHINE'] + self.image_link_name = get_bb_var('IMAGE_LINK_NAME', self.recipe) self.fstypes = "ext4" if self.td["HOST_ARCH"] in ('i586', 'i686', 'x86_64'): @@ -61,7 +62,8 @@ SYSLINUX_TIMEOUT = "10" cmd = "%s %s ext4" % (self.cmd_common, self.machine) with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: with open(qemu.qemurunnerlog) as f: - self.assertIn('rootfs.ext4', f.read(), "Failed: %s" % cmd) + regexp = r'\nROOTFS: .*\.ext4]\n' + self.assertRegex(f.read(), regexp, "Failed to find '%s' in '%s' after running '%s'" % (regexp, qemu.qemurunnerlog, cmd)) @skipIfNotArch(['i586', 'i686', 'x86_64']) def test_boot_machine_iso(self): @@ -69,7 +71,8 @@ SYSLINUX_TIMEOUT = "10" cmd = "%s %s iso" % (self.cmd_common, self.machine) with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: with open(qemu.qemurunnerlog) as f: - self.assertIn('media=cdrom', f.read(), "Failed: %s" % cmd) + text_in = 'media=cdrom' + self.assertIn(text_in, f.read(), "Failed to find '%s' in '%s' after running '%s'" % (text_in, qemu.qemurunnerlog, cmd)) def test_boot_recipe_image(self): """Test runqemu recipe-image""" @@ -85,7 +88,8 @@ SYSLINUX_TIMEOUT = "10" cmd = "%s %s wic.vmdk" % (self.cmd_common, self.recipe) with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: with open(qemu.qemurunnerlog) as f: - self.assertIn('format=vmdk', f.read(), "Failed: %s" % cmd) + text_in = 'format=vmdk' + self.assertIn(text_in, f.read(), "Failed to find '%s' in '%s' after running '%s'" % (text_in, qemu.qemurunnerlog, cmd)) @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently") def test_boot_recipe_image_vdi(self): @@ -93,7 +97,8 @@ SYSLINUX_TIMEOUT = "10" cmd = "%s %s wic.vdi" % (self.cmd_common, self.recipe) with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: with open(qemu.qemurunnerlog) as f: - self.assertIn('format=vdi', f.read(), "Failed: %s" % cmd) + text_in = 'format=vdi' + self.assertIn(text_in, f.read(), "Failed to find '%s' in '%s' after running '%s'" % (text_in, qemu.qemurunnerlog, cmd)) def test_boot_deploy(self): """Test runqemu deploy_dir_image""" @@ -102,7 +107,6 @@ SYSLINUX_TIMEOUT = "10" with open(qemu.qemurunnerlog) as f: self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read())) - @skipIfNotArch(['i586', 'i686', 'x86_64']) def test_boot_deploy_hddimg(self): """Test runqemu deploy_dir_image hddimg""" @@ -166,9 +170,9 @@ class QemuTest(OESelftestTestCase): def setUpClass(cls): super(QemuTest, cls).setUpClass() cls.recipe = 'core-image-minimal' - cls.machine = get_bb_var('MACHINE') - cls.deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') - cls.image_link_name = get_bb_var('IMAGE_LINK_NAME', cls.recipe) + cls.machine = get_bb_var('MACHINE') + cls.deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') + cls.image_link_name = get_bb_var('IMAGE_LINK_NAME', cls.recipe) cls.cmd_common = "runqemu nographic" cls.qemuboot_conf = "%s.qemuboot.conf" % (cls.image_link_name) cls.qemuboot_conf = os.path.join(cls.deploy_dir_image, cls.qemuboot_conf) diff --git a/poky/meta/lib/oeqa/selftest/cases/wic.py b/poky/meta/lib/oeqa/selftest/cases/wic.py index b26b649c3a..0b0ca90c1e 100644 --- a/poky/meta/lib/oeqa/selftest/cases/wic.py +++ b/poky/meta/lib/oeqa/selftest/cases/wic.py @@ -1348,6 +1348,29 @@ class Wic2(WicTestCase): if os.path.exists(image_path + '.bak'): os.rename(image_path + '.bak', image_path) + def test_gpt_partition_name(self): + """Test --part-name argument to set partition name in GPT table""" + config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "test_gpt_partition_name.wks"\n' + self.append_config(config) + bitbake('core-image-minimal') + self.remove_config(config) + deploy_dir = get_bb_var('DEPLOY_DIR_IMAGE') + machine = self.td['MACHINE'] + + image_path = os.path.join(deploy_dir, 'core-image-minimal-%s.wic' % machine) + # Image is created + self.assertTrue(os.path.exists(image_path)) + + # Check the names of the three partitions + # as listed in test_gpt_partition_name.wks + result = runCmd("sfdisk --part-label %s 1" % image_path) + self.assertEqual('boot-A', result.output) + result = runCmd("sfdisk --part-label %s 2" % image_path) + self.assertEqual('root-A', result.output) + # When the --part-name is not defined, the partition name is equal to the --label + result = runCmd("sfdisk --part-label %s 3" % image_path) + self.assertEqual('ext-space', result.output) + class ModifyTests(WicTestCase): def test_wic_ls(self): """Test listing image content using 'wic ls'""" diff --git a/poky/meta/lib/oeqa/selftest/context.py b/poky/meta/lib/oeqa/selftest/context.py index 0a7a9da72a..f2a5ba792f 100644 --- a/poky/meta/lib/oeqa/selftest/context.py +++ b/poky/meta/lib/oeqa/selftest/context.py @@ -16,6 +16,7 @@ from random import choice import oeqa import oe import bb.utils +import bb.tinfoil from oeqa.core.context import OETestContext, OETestContextExecutor from oeqa.core.exception import OEQAPreRun, OEQATestNotFound @@ -79,6 +80,12 @@ class OESelftestTestContext(OETestContext): self.removebuilddir = removebuilddir def setup_builddir(self, suffix, selftestdir, suite): + # Get SSTATE_DIR from the parent build dir + with bb.tinfoil.Tinfoil(tracking=True) as tinfoil: + tinfoil.prepare(quiet=2, config_only=True) + d = tinfoil.config_data + sstatedir = str(d.getVar('SSTATE_DIR')) + builddir = os.environ['BUILDDIR'] if not selftestdir: selftestdir = get_test_layer() @@ -118,6 +125,9 @@ class OESelftestTestContext(OETestContext): if os.environ[e].endswith(builddir): os.environ[e] = os.environ[e].replace(builddir, newbuilddir) + # Set SSTATE_DIR to match the parent SSTATE_DIR + subprocess.check_output("echo 'SSTATE_DIR ?= \"%s\"' >> %s/conf/local.conf" % (sstatedir, newbuilddir), cwd=newbuilddir, shell=True) + os.chdir(newbuilddir) def patch_test(t): diff --git a/poky/meta/lib/oeqa/targetcontrol.py b/poky/meta/lib/oeqa/targetcontrol.py index 1fdff82889..d686fe07ec 100644 --- a/poky/meta/lib/oeqa/targetcontrol.py +++ b/poky/meta/lib/oeqa/targetcontrol.py @@ -7,18 +7,14 @@ # This module is used by testimage.bbclass for setting up and controlling a target machine. import os -import shutil import subprocess import bb -import traceback -import sys import logging from oeqa.utils.sshcontrol import SSHControl from oeqa.utils.qemurunner import QemuRunner from oeqa.utils.qemutinyrunner import QemuTinyRunner from oeqa.utils.dump import TargetDumper from oeqa.utils.dump import MonitorDumper -from oeqa.controllers.testtargetloader import TestTargetLoader from abc import ABCMeta, abstractmethod class BaseTarget(object, metaclass=ABCMeta): @@ -42,7 +38,7 @@ class BaseTarget(object, metaclass=ABCMeta): if os.path.islink(sshloglink): os.unlink(sshloglink) os.symlink(self.sshlog, sshloglink) - self.logger.info("SSH log file: %s" % self.sshlog) + self.logger.info("SSH log file: %s" % self.sshlog) @abstractmethod def start(self, params=None, ssh=True, extra_bootparams=None): @@ -145,7 +141,7 @@ class QemuTarget(BaseTarget): boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT")), use_kvm = use_kvm, dump_dir = dump_dir, - dump_host_cmds = d.getVar("testimage_dump_host"), + dump_host_cmds = dump_host_cmds, logger = logger, tmpfsdir = d.getVar("RUNQEMU_TMPFS_DIR"), serial_ports = len(d.getVar("SERIAL_CONSOLES").split())) @@ -163,7 +159,7 @@ class QemuTarget(BaseTarget): os.unlink(qemuloglink) os.symlink(self.qemulog, qemuloglink) - self.logger.info("rootfs file: %s" % self.rootfs) + self.logger.info("rootfs file: %s" % self.rootfs) self.logger.info("Qemu log file: %s" % self.qemulog) super(QemuTarget, self).deploy() @@ -205,7 +201,7 @@ class QemuTarget(BaseTarget): self.server_ip = self.runner.server_ip self.connection = SSHControl(ip=self.ip, logfile=self.sshlog) else: - raise RuntimError("%s - FAILED to re-start qemu - check the task log and the boot log" % self.pn) + raise RuntimeError("%s - FAILED to re-start qemu - check the task log and the boot log" % self.pn) def run_serial(self, command, timeout=60): return self.runner.run_serial(command, timeout=timeout) diff --git a/poky/meta/lib/oeqa/utils/commands.py b/poky/meta/lib/oeqa/utils/commands.py index f4daea2507..c1f533802e 100644 --- a/poky/meta/lib/oeqa/utils/commands.py +++ b/poky/meta/lib/oeqa/utils/commands.py @@ -8,11 +8,8 @@ # This module is mainly used by scripts/oe-selftest and modules under meta/oeqa/selftest # It provides a class and methods for running commands on the host in a convienent way for tests. - - import os import sys -import signal import subprocess import threading import time @@ -21,6 +18,7 @@ from oeqa.utils import CommandError from oeqa.utils import ftools import re import contextlib +import errno # Export test doesn't require bb try: import bb @@ -85,7 +83,7 @@ class Command(object): except OSError as ex: # It's not an error when the command does not consume all # of our data. subprocess.communicate() also ignores that. - if ex.errno != EPIPE: + if ex.errno != errno.EPIPE: raise # We write in a separate thread because then we can read @@ -117,7 +115,7 @@ class Command(object): else: deadline = time.time() + self.timeout for thread in self.threads: - timeout = deadline - time.time() + timeout = deadline - time.time() if timeout < 0: timeout = 0 thread.join(timeout) diff --git a/poky/meta/lib/oeqa/utils/metadata.py b/poky/meta/lib/oeqa/utils/metadata.py index 8013aa684d..15ec190c4a 100644 --- a/poky/meta/lib/oeqa/utils/metadata.py +++ b/poky/meta/lib/oeqa/utils/metadata.py @@ -27,9 +27,9 @@ def metadata_from_bb(): data_dict = get_bb_vars() # Distro information - info_dict['distro'] = {'id': data_dict['DISTRO'], - 'version_id': data_dict['DISTRO_VERSION'], - 'pretty_name': '%s %s' % (data_dict['DISTRO'], data_dict['DISTRO_VERSION'])} + info_dict['distro'] = {'id': data_dict.get('DISTRO', 'NODISTRO'), + 'version_id': data_dict.get('DISTRO_VERSION', 'NO_DISTRO_VERSION'), + 'pretty_name': '%s %s' % (data_dict.get('DISTRO', 'NODISTRO'), data_dict.get('DISTRO_VERSION', 'NO_DISTRO_VERSION'))} # Host distro information os_release = get_os_release() diff --git a/poky/meta/lib/oeqa/utils/qemurunner.py b/poky/meta/lib/oeqa/utils/qemurunner.py index 05385763ac..6734cee48d 100644 --- a/poky/meta/lib/oeqa/utils/qemurunner.py +++ b/poky/meta/lib/oeqa/utils/qemurunner.py @@ -238,7 +238,7 @@ class QemuRunner: self.origchldhandler = signal.getsignal(signal.SIGCHLD) signal.signal(signal.SIGCHLD, self.handleSIGCHLD) - self.logger.debug('launchcmd=%s'%(launch_cmd)) + self.logger.debug('launchcmd=%s' % (launch_cmd)) # FIXME: We pass in stdin=subprocess.PIPE here to work around stty # blocking at the end of the runqemu script when using this within @@ -275,7 +275,7 @@ class QemuRunner: os._exit(0) self.logger.debug("runqemu started, pid is %s" % self.runqemu.pid) - self.logger.debug("waiting at most %s seconds for qemu pid (%s)" % + self.logger.debug("waiting at most %d seconds for qemu pid (%s)" % (self.runqemutime, time.strftime("%D %H:%M:%S"))) endtime = time.time() + self.runqemutime while not self.is_alive() and time.time() < endtime: @@ -299,7 +299,7 @@ class QemuRunner: self.logger.warning('runqemu exited with code %d' % self.runqemu.returncode) if not self.is_alive(): - self.logger.error("Qemu pid didn't appear in %s seconds (%s)" % + self.logger.error("Qemu pid didn't appear in %d seconds (%s)" % (self.runqemutime, time.strftime("%D %H:%M:%S"))) qemu_pid = None @@ -332,8 +332,8 @@ class QemuRunner: try: os.chdir(os.path.dirname(qmp_port)) try: - from qmp.legacy import QEMUMonitorProtocol - self.qmp = QEMUMonitorProtocol(os.path.basename(qmp_port)) + from qmp.legacy import QEMUMonitorProtocol + self.qmp = QEMUMonitorProtocol(os.path.basename(qmp_port)) except OSError as msg: self.logger.warning("Failed to initialize qemu monitor socket: %s File: %s" % (msg, msg.filename)) return False @@ -343,8 +343,8 @@ class QemuRunner: self.logger.debug("QMP Port does not exist waiting for it to be created") endtime = time.time() + self.runqemutime while not os.path.exists(qmp_port) and self.is_alive() and time.time() < endtime: - self.logger.info("QMP port does not exist yet!") - time.sleep(0.5) + self.logger.info("QMP port does not exist yet!") + time.sleep(0.5) if not os.path.exists(qmp_port) and self.is_alive(): self.logger.warning("QMP Port still does not exist but QEMU is alive") return False @@ -354,7 +354,7 @@ class QemuRunner: self.qmp.settimeout(self.runqemutime) self.qmp.connect() connect_time = time.time() - self.logger.info("QMP connected to QEMU at %s and took %s seconds" % + self.logger.info("QMP connected to QEMU at %s and took %.2f seconds" % (time.strftime("%D %H:%M:%S"), time.time() - launch_time)) except OSError as msg: @@ -388,14 +388,14 @@ class QemuRunner: # Release the qemu process to continue running self.run_monitor('cont') - self.logger.info("QMP released QEMU at %s and took %s seconds from connect" % + self.logger.info("QMP released QEMU at %s and took %.2f seconds from connect" % (time.strftime("%D %H:%M:%S"), time.time() - connect_time)) # We are alive: qemu is running out = self.getOutput(output) netconf = False # network configuration is not required by default - self.logger.debug("qemu started in %s seconds - qemu procces pid is %s (%s)" % + self.logger.debug("qemu started in %.2f seconds - qemu procces pid is %s (%s)" % (time.time() - (endtime - self.runqemutime), self.qemupid, time.strftime("%D %H:%M:%S"))) cmdline = '' @@ -419,7 +419,7 @@ class QemuRunner: except (IndexError, ValueError): # Try to get network configuration from runqemu output match = re.match(r'.*Network configuration: (?:ip=)*([0-9.]+)::([0-9.]+):([0-9.]+).*', - out, re.MULTILINE|re.DOTALL) + out, re.MULTILINE | re.DOTALL) if match: self.ip, self.server_ip, self.netmask = match.groups() # network configuration is required as we couldn't get it @@ -486,9 +486,9 @@ class QemuRunner: self.server_socket = qemusock stopread = True reachedlogin = True - self.logger.debug("Reached login banner in %s seconds (%s, %s)" % + self.logger.debug("Reached login banner in %.2f seconds (%s)" % (time.time() - (endtime - self.boottime), - time.strftime("%D %H:%M:%S"), time.time())) + time.strftime("%D %H:%M:%S"))) else: # no need to check if reachedlogin unless we support multiple connections self.logger.debug("QEMU socket disconnected before login banner reached. (%s)" % @@ -516,7 +516,7 @@ class QemuRunner: (status, output) = self.run_serial(self.boot_patterns['send_login_user'], raw=True, timeout=120) if re.search(self.boot_patterns['search_login_succeeded'], output): self.logged = True - self.logger.debug("Logged as root in serial console") + self.logger.debug("Logged in as %s in serial console" % self.boot_patterns['send_login_user'].replace("\n", "")) if netconf: # configure guest networking cmd = "ifconfig eth0 %s netmask %s up\n" % (self.ip, self.netmask) @@ -527,7 +527,7 @@ class QemuRunner: self.logger.debug("Couldn't configure guest networking") else: self.logger.warning("Couldn't login into serial console" - " as root using blank password") + " as %s using blank password" % self.boot_patterns['send_login_user'].replace("\n", "")) self.logger.warning("The output:\n%s" % output) except: self.logger.warning("Serial console failed while trying to login") @@ -548,12 +548,12 @@ class QemuRunner: if e.errno != errno.ESRCH: raise try: - outs, errs = self.runqemu.communicate(timeout = self.runqemutime) + outs, errs = self.runqemu.communicate(timeout=self.runqemutime) if outs: self.logger.info("Output from runqemu:\n%s", outs.decode("utf-8")) if errs: self.logger.info("Stderr from runqemu:\n%s", errs.decode("utf-8")) - except TimeoutExpired: + except subprocess.TimeoutExpired: self.logger.debug("Sending SIGKILL to runqemu") os.killpg(os.getpgid(self.runqemu.pid), signal.SIGKILL) if not self.runqemu.stdout.closed: |