diff options
Diffstat (limited to 'poky/meta/lib')
-rw-r--r-- | poky/meta/lib/oe/buildhistory_analysis.py | 27 | ||||
-rw-r--r-- | poky/meta/lib/oe/copy_buildsystem.py | 8 | ||||
-rw-r--r-- | poky/meta/lib/oe/package_manager.py | 2 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/runtime/cases/oe_syslog.py | 80 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/runtime/cases/rpm.py | 74 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/bbtests.py | 32 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/buildoptions.py | 7 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/devtool.py | 3 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/recipetool.py | 19 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/runtime_test.py | 4 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/selftest/cases/wic.py | 63 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/utils/logparser.py | 1 | ||||
-rw-r--r-- | poky/meta/lib/oeqa/utils/qemurunner.py | 41 |
13 files changed, 276 insertions, 85 deletions
diff --git a/poky/meta/lib/oe/buildhistory_analysis.py b/poky/meta/lib/oe/buildhistory_analysis.py index 62c7a2e58..708e1b388 100644 --- a/poky/meta/lib/oe/buildhistory_analysis.py +++ b/poky/meta/lib/oe/buildhistory_analysis.py @@ -181,7 +181,7 @@ class ChangeRecord: diff = difflib.unified_diff(alines, blines, self.fieldname, self.fieldname, lineterm='') out += '\n '.join(list(diff)[2:]) out += '\n --' - elif self.fieldname in img_monitor_files or '/image-files/' in self.path: + elif self.fieldname in img_monitor_files or '/image-files/' in self.path or self.fieldname == "sysroot": if self.filechanges or (self.oldvalue and self.newvalue): fieldname = self.fieldname if '/image-files/' in self.path: @@ -282,7 +282,7 @@ def file_list_to_dict(lines): return adict -def compare_file_lists(alines, blines): +def compare_file_lists(alines, blines, compare_ownership=True): adict = file_list_to_dict(alines) bdict = file_list_to_dict(blines) filechanges = [] @@ -294,16 +294,20 @@ def compare_file_lists(alines, blines): newvalue = newsplitv[0][0] if oldvalue != newvalue: filechanges.append(FileChange(path, FileChange.changetype_type, oldvalue, newvalue)) + # Check permissions oldvalue = splitv[0][1:] newvalue = newsplitv[0][1:] if oldvalue != newvalue: filechanges.append(FileChange(path, FileChange.changetype_perms, oldvalue, newvalue)) - # Check owner/group - oldvalue = '%s/%s' % (splitv[1], splitv[2]) - newvalue = '%s/%s' % (newsplitv[1], newsplitv[2]) - if oldvalue != newvalue: - filechanges.append(FileChange(path, FileChange.changetype_ownergroup, oldvalue, newvalue)) + + if compare_ownership: + # Check owner/group + oldvalue = '%s/%s' % (splitv[1], splitv[2]) + newvalue = '%s/%s' % (newsplitv[1], newsplitv[2]) + if oldvalue != newvalue: + filechanges.append(FileChange(path, FileChange.changetype_ownergroup, oldvalue, newvalue)) + # Check symlink target if newsplitv[0][0] == 'l': if len(splitv) > 3: @@ -571,6 +575,15 @@ def process_changes(repopath, revision1, revision2='HEAD', report_all=False, rep elif filename.startswith('latest.'): chg = ChangeRecord(path, filename, d.a_blob.data_stream.read().decode('utf-8'), d.b_blob.data_stream.read().decode('utf-8'), True) changes.append(chg) + elif filename == 'sysroot': + alines = d.a_blob.data_stream.read().decode('utf-8').splitlines() + blines = d.b_blob.data_stream.read().decode('utf-8').splitlines() + filechanges = compare_file_lists(alines,blines, compare_ownership=False) + if filechanges: + chg = ChangeRecord(path, filename, None, None, True) + chg.filechanges = filechanges + changes.append(chg) + elif path.startswith('images/'): filename = os.path.basename(d.a_blob.path) if filename in img_monitor_files: diff --git a/poky/meta/lib/oe/copy_buildsystem.py b/poky/meta/lib/oe/copy_buildsystem.py index 5b96121dd..246ff5825 100644 --- a/poky/meta/lib/oe/copy_buildsystem.py +++ b/poky/meta/lib/oe/copy_buildsystem.py @@ -45,6 +45,9 @@ class BuildSystem(object): corebase = os.path.abspath(self.d.getVar('COREBASE')) layers.append(corebase) + # Get relationship between TOPDIR and COREBASE + # Layers should respect it + corebase_relative = os.path.dirname(os.path.relpath(os.path.abspath(self.d.getVar('TOPDIR')), corebase)) # The bitbake build system uses the meta-skeleton layer as a layout # for common recipies, e.g: the recipetool script to create kernel recipies # Add the meta-skeleton layer to be included as part of the eSDK installation @@ -98,7 +101,10 @@ class BuildSystem(object): if corebase == os.path.dirname(layer): layerdestpath += '/' + os.path.basename(corebase) else: - layer_relative = os.path.basename(corebase) + '/' + os.path.relpath(layer, corebase) + layer_relative = os.path.relpath(layer, corebase) + if os.path.dirname(layer_relative) == corebase_relative: + layer_relative = os.path.dirname(corebase_relative) + '/' + layernewname + layer_relative = os.path.basename(corebase) + '/' + layer_relative if os.path.dirname(layer_relative) != layernewname: layerdestpath += '/' + os.path.dirname(layer_relative) diff --git a/poky/meta/lib/oe/package_manager.py b/poky/meta/lib/oe/package_manager.py index 06feb4def..7c373715a 100644 --- a/poky/meta/lib/oe/package_manager.py +++ b/poky/meta/lib/oe/package_manager.py @@ -1297,6 +1297,8 @@ class OpkgPM(OpkgDpkgPM): rootfs_config = os.path.join('%s/etc/opkg/base-feeds.conf' % self.target_rootfs) + os.makedirs('%s/etc/opkg' % self.target_rootfs, exist_ok=True) + feed_uris = self.construct_uris(feed_uris.split(), feed_base_paths.split()) archs = self.pkg_archs.split() if feed_archs is None else feed_archs.split() diff --git a/poky/meta/lib/oeqa/runtime/cases/oe_syslog.py b/poky/meta/lib/oeqa/runtime/cases/oe_syslog.py index 0f5f9f43c..3a8271a53 100644 --- a/poky/meta/lib/oeqa/runtime/cases/oe_syslog.py +++ b/poky/meta/lib/oeqa/runtime/cases/oe_syslog.py @@ -6,6 +6,7 @@ from oeqa.runtime.case import OERuntimeTestCase from oeqa.core.decorator.depends import OETestDepends from oeqa.core.decorator.data import skipIfDataVar from oeqa.runtime.decorator.package import OEHasPackage +import time class SyslogTest(OERuntimeTestCase): @@ -21,12 +22,72 @@ class SyslogTest(OERuntimeTestCase): class SyslogTestConfig(OERuntimeTestCase): + def verif_not_running(self, pids): + for pid in pids: + status, err_output = self.target.run('kill -0 %s' %pid) + if not status: + self.logger.debug("previous %s is still running" %pid) + return 1 + + def verify_running(self, names): + pids = [] + for name in names: + status, pid = self.target.run('pidof %s' %name) + if status: + self.logger.debug("%s is not running" %name) + return 1, pids + pids.append(pid) + return 0, pids + + + def restart_sanity(self, names, restart_cmd, pidchange=True): + status, original_pids = self.verify_running(names) + if status: + return False + + status, output = self.target.run(restart_cmd) + + msg = ('Could not restart %s service. Status and output: %s and %s' % (names, status, output)) + self.assertEqual(status, 0, msg) + + if not pidchange: + return True + + # Always check for an error, most likely a race between shutting down and starting up + timeout = time.time() + 30 + + restarted = False + status = "" + while time.time() < timeout: + # Verify the previous ones are no longer running + status = self.verif_not_running(original_pids) + if status: + status = "Original syslog processes still running" + continue + + status, pids = self.verify_running(names) + if status: + status = "New syslog processes not running" + continue + + # Everything is fine now, so exit to continue the test + restarted = True + break + + msg = ('%s didn\'t appear to restart: %s' % (names, status)) + self.assertTrue(restarted, msg) + + return True + @OETestDepends(['oe_syslog.SyslogTest.test_syslog_running']) def test_syslog_logger(self): status, output = self.target.run('logger foobar') msg = "Can't log into syslog. Output: %s " % output self.assertEqual(status, 0, msg=msg) + # There is no way to flush the logger to disk in all cases + time.sleep(1) + status, output = self.target.run('grep foobar /var/log/messages') if status != 0: if self.tc.td.get("VIRTUAL-RUNTIME_init_manager") == "systemd": @@ -37,12 +98,17 @@ class SyslogTestConfig(OERuntimeTestCase): ' Output: %s ' % output) self.assertEqual(status, 0, msg=msg) + @OETestDepends(['oe_syslog.SyslogTest.test_syslog_running']) def test_syslog_restart(self): - if "systemd" != self.tc.td.get("VIRTUAL-RUNTIME_init_manager", ""): - (_, _) = self.target.run('/etc/init.d/syslog restart') + if self.restart_sanity(['systemd-journald'], 'systemctl restart syslog.service', pidchange=False): + pass + elif self.restart_sanity(['rsyslogd'], '/etc/init.d/rsyslog restart'): + pass + elif self.restart_sanity(['syslogd', 'klogd'], '/etc/init.d/syslog restart'): + pass else: - (_, _) = self.target.run('systemctl restart syslog.service') + self.logger.info("No syslog found to restart, ignoring") @OETestDepends(['oe_syslog.SyslogTestConfig.test_syslog_logger']) @@ -52,10 +118,8 @@ class SyslogTestConfig(OERuntimeTestCase): def test_syslog_startup_config(self): cmd = 'echo "LOGFILE=/var/log/test" >> /etc/syslog-startup.conf' self.target.run(cmd) - status, output = self.target.run('/etc/init.d/syslog restart') - msg = ('Could not restart syslog service. Status and output:' - ' %s and %s' % (status,output)) - self.assertEqual(status, 0, msg) + + self.test_syslog_restart() cmd = 'logger foobar && grep foobar /var/log/test' status,output = self.target.run(cmd) @@ -64,4 +128,4 @@ class SyslogTestConfig(OERuntimeTestCase): cmd = "sed -i 's#LOGFILE=/var/log/test##' /etc/syslog-startup.conf" self.target.run(cmd) - self.target.run('/etc/init.d/syslog restart') + self.test_syslog_restart() diff --git a/poky/meta/lib/oeqa/runtime/cases/rpm.py b/poky/meta/lib/oeqa/runtime/cases/rpm.py index d8cabd364..8e18b426f 100644 --- a/poky/meta/lib/oeqa/runtime/cases/rpm.py +++ b/poky/meta/lib/oeqa/runtime/cases/rpm.py @@ -4,6 +4,7 @@ import os import fnmatch +import time from oeqa.runtime.case import OERuntimeTestCase from oeqa.core.decorator.depends import OETestDepends @@ -29,35 +30,6 @@ class RpmBasicTest(OERuntimeTestCase): msg = 'status and output: %s and %s' % (status, output) self.assertEqual(status, 0, msg=msg) -class RpmInstallRemoveTest(OERuntimeTestCase): - - @classmethod - def setUpClass(cls): - pkgarch = cls.td['TUNE_PKGARCH'].replace('-', '_') - rpmdir = os.path.join(cls.tc.td['DEPLOY_DIR'], 'rpm', pkgarch) - # Pick base-passwd-doc as a test file to get installed, because it's small - # and it will always be built for standard targets - rpm_doc = 'base-passwd-doc-*.%s.rpm' % pkgarch - if not os.path.exists(rpmdir): - return - for f in fnmatch.filter(os.listdir(rpmdir), rpm_doc): - cls.test_file = os.path.join(rpmdir, f) - cls.dst = '/tmp/base-passwd-doc.rpm' - - @OETestDepends(['rpm.RpmBasicTest.test_rpm_query']) - def test_rpm_install(self): - self.tc.target.copyTo(self.test_file, self.dst) - status, output = self.target.run('rpm -ivh /tmp/base-passwd-doc.rpm') - msg = 'Failed to install base-passwd-doc package: %s' % output - self.assertEqual(status, 0, msg=msg) - self.tc.target.run('rm -f %s' % self.dst) - - @OETestDepends(['rpm.RpmInstallRemoveTest.test_rpm_install']) - def test_rpm_remove(self): - status,output = self.target.run('rpm -e base-passwd-doc') - msg = 'Failed to remove base-passwd-doc package: %s' % output - self.assertEqual(status, 0, msg=msg) - @OETestDepends(['rpm.RpmBasicTest.test_rpm_query']) def test_rpm_query_nonroot(self): @@ -77,7 +49,21 @@ class RpmInstallRemoveTest(OERuntimeTestCase): msg = 'status: %s. Cannot run rpm -qa: %s' % (status, output) self.assertEqual(status, 0, msg=msg) + def check_no_process_for_user(u): + _, output = self.target.run(self.tc.target_cmds['ps']) + if u + ' ' in output: + return False + else: + return True + def unset_up_test_user(u): + # ensure no test1 process in running + timeout = time.time() + 30 + while time.time() < timeout: + if check_no_process_for_user(u): + break + else: + time.sleep(1) status, output = self.target.run('userdel -r %s' % u) msg = 'Failed to erase user: %s' % output self.assertTrue(status == 0, msg=msg) @@ -90,6 +76,36 @@ class RpmInstallRemoveTest(OERuntimeTestCase): finally: unset_up_test_user(tuser) + +class RpmInstallRemoveTest(OERuntimeTestCase): + + @classmethod + def setUpClass(cls): + pkgarch = cls.td['TUNE_PKGARCH'].replace('-', '_') + rpmdir = os.path.join(cls.tc.td['DEPLOY_DIR'], 'rpm', pkgarch) + # Pick base-passwd-doc as a test file to get installed, because it's small + # and it will always be built for standard targets + rpm_doc = 'base-passwd-doc-*.%s.rpm' % pkgarch + if not os.path.exists(rpmdir): + return + for f in fnmatch.filter(os.listdir(rpmdir), rpm_doc): + cls.test_file = os.path.join(rpmdir, f) + cls.dst = '/tmp/base-passwd-doc.rpm' + + @OETestDepends(['rpm.RpmBasicTest.test_rpm_query']) + def test_rpm_install(self): + self.tc.target.copyTo(self.test_file, self.dst) + status, output = self.target.run('rpm -ivh /tmp/base-passwd-doc.rpm') + msg = 'Failed to install base-passwd-doc package: %s' % output + self.assertEqual(status, 0, msg=msg) + self.tc.target.run('rm -f %s' % self.dst) + + @OETestDepends(['rpm.RpmInstallRemoveTest.test_rpm_install']) + def test_rpm_remove(self): + status,output = self.target.run('rpm -e base-passwd-doc') + msg = 'Failed to remove base-passwd-doc package: %s' % output + self.assertEqual(status, 0, msg=msg) + @OETestDepends(['rpm.RpmInstallRemoveTest.test_rpm_remove']) def test_check_rpm_install_removal_log_file_size(self): """ diff --git a/poky/meta/lib/oeqa/selftest/cases/bbtests.py b/poky/meta/lib/oeqa/selftest/cases/bbtests.py index e9ad44b02..17da0fd32 100644 --- a/poky/meta/lib/oeqa/selftest/cases/bbtests.py +++ b/poky/meta/lib/oeqa/selftest/cases/bbtests.py @@ -40,7 +40,7 @@ class BitbakeTests(OESelftestTestCase): def test_event_handler(self): self.write_config("INHERIT += \"test_events\"") result = bitbake('m4-native') - find_build_started = re.search(r"NOTE: Test for bb\.event\.BuildStarted(\n.*)*NOTE: Executing RunQueue Tasks", result.output) + find_build_started = re.search(r"NOTE: Test for bb\.event\.BuildStarted(\n.*)*NOTE: Executing.*Tasks", result.output) find_build_completed = re.search(r"Tasks Summary:.*(\n.*)*NOTE: Test for bb\.event\.BuildCompleted", result.output) self.assertTrue(find_build_started, msg = "Match failed in:\n%s" % result.output) self.assertTrue(find_build_completed, msg = "Match failed in:\n%s" % result.output) @@ -242,6 +242,36 @@ INHERIT_remove = \"report-error\" self.assertIn('_setscene', task, 'A task different from _setscene ran: %s.\n' 'Executed tasks were: %s' % (task, str(tasks))) + def test_skip_setscene(self): + test_recipe = 'ed' + + bitbake(test_recipe) + bitbake('-c clean %s' % test_recipe) + + ret = bitbake('--setscene-only %s' % test_recipe) + tasks = re.findall(r'task\s+(do_\S+):', ret.output) + + for task in tasks: + self.assertIn('_setscene', task, 'A task different from _setscene ran: %s.\n' + 'Executed tasks were: %s' % (task, str(tasks))) + + # Run without setscene. Should do nothing + ret = bitbake('--skip-setscene %s' % test_recipe) + tasks = re.findall(r'task\s+(do_\S+):', ret.output) + + self.assertFalse(tasks, 'Tasks %s ran when they should not have' % (str(tasks))) + + # Clean (leave sstate cache) and run with --skip-setscene. No setscene + # tasks should run + bitbake('-c clean %s' % test_recipe) + + ret = bitbake('--skip-setscene %s' % test_recipe) + tasks = re.findall(r'task\s+(do_\S+):', ret.output) + + for task in tasks: + self.assertNotIn('_setscene', task, 'A _setscene task ran: %s.\n' + 'Executed tasks were: %s' % (task, str(tasks))) + def test_bbappend_order(self): """ Bitbake should bbappend to recipe in a predictable order """ test_recipe = 'ed' diff --git a/poky/meta/lib/oeqa/selftest/cases/buildoptions.py b/poky/meta/lib/oeqa/selftest/cases/buildoptions.py index 3ad65b403..6a5378d3f 100644 --- a/poky/meta/lib/oeqa/selftest/cases/buildoptions.py +++ b/poky/meta/lib/oeqa/selftest/cases/buildoptions.py @@ -162,17 +162,14 @@ class ArchiverTest(OESelftestTestCase): self.assertTrue((g.glob(src_file_glob) and g.glob(tar_file_glob)), "Couldn't find .src.rpm and .tar.gz files under %s/allarch*/xcursor*" % deploy_dir_src) class ToolchainOptions(OESelftestTestCase): - def test_toolchain_fortran(self): """ - Test whether we can enable and build fortran and its supporting libraries + Test that Fortran works by building a Hello, World binary. """ features = 'FORTRAN_forcevariable = ",fortran"\n' - features += 'RUNTIMETARGET_append_pn-gcc-runtime = " libquadmath"\n' self.write_config(features) - - bitbake('gcc-runtime libgfortran') + bitbake('fortran-helloworld') class SourceMirroring(OESelftestTestCase): # Can we download everything from the Yocto Sources Mirror over http only diff --git a/poky/meta/lib/oeqa/selftest/cases/devtool.py b/poky/meta/lib/oeqa/selftest/cases/devtool.py index 904ff6988..6fe145c99 100644 --- a/poky/meta/lib/oeqa/selftest/cases/devtool.py +++ b/poky/meta/lib/oeqa/selftest/cases/devtool.py @@ -240,6 +240,9 @@ class DevtoolTests(DevtoolBase): # Check preconditions result = runCmd('bitbake-layers show-layers') self.assertTrue('\nworkspace' not in result.output, 'This test cannot be run with a workspace layer in bblayers.conf') + # remove conf/devtool.conf to avoid it corrupting tests + devtoolconf = os.path.join(self.builddir, 'conf', 'devtool.conf') + self.track_for_cleanup(devtoolconf) # Try creating a workspace layer with a specific path tempdir = tempfile.mkdtemp(prefix='devtoolqa') self.track_for_cleanup(tempdir) diff --git a/poky/meta/lib/oeqa/selftest/cases/recipetool.py b/poky/meta/lib/oeqa/selftest/cases/recipetool.py index e3f5c7166..1c701a40b 100644 --- a/poky/meta/lib/oeqa/selftest/cases/recipetool.py +++ b/poky/meta/lib/oeqa/selftest/cases/recipetool.py @@ -406,22 +406,19 @@ class RecipetoolTests(RecipetoolBase): self._test_recipe_contents(os.path.join(temprecipe, dirlist[0]), checkvars, inherits) def test_recipetool_create_cmake(self): - bitbake('-c packagedata gtk+') - - # Try adding a recipe temprecipe = os.path.join(self.tempdir, 'recipe') os.makedirs(temprecipe) - recipefile = os.path.join(temprecipe, 'navit_0.5.0.bb') - srcuri = 'http://downloads.yoctoproject.org/mirror/sources/navit-0.5.0.tar.gz' + recipefile = os.path.join(temprecipe, 'taglib_1.11.1.bb') + srcuri = 'http://taglib.github.io/releases/taglib-1.11.1.tar.gz' result = runCmd('recipetool create -o %s %s' % (temprecipe, srcuri)) self.assertTrue(os.path.isfile(recipefile)) checkvars = {} - checkvars['LICENSE'] = set(['Unknown', 'GPLv2', 'LGPLv2']) - checkvars['SRC_URI'] = 'http://downloads.yoctoproject.org/mirror/sources/navit-${PV}.tar.gz' - checkvars['SRC_URI[md5sum]'] = '242f398e979a6b8c0f3c802b63435b68' - checkvars['SRC_URI[sha256sum]'] = '13353481d7fc01a4f64e385dda460b51496366bba0fd2cc85a89a0747910e94d' - checkvars['DEPENDS'] = set(['freetype', 'zlib', 'openssl', 'glib-2.0', 'virtual/libgl', 'virtual/egl', 'gtk+', 'libpng', 'libsdl', 'freeglut', 'dbus-glib', 'fribidi']) - inherits = ['cmake', 'python-dir', 'gettext', 'pkgconfig'] + checkvars['LICENSE'] = set(['LGPLv2.1', 'MPL-1.1']) + checkvars['SRC_URI'] = 'http://taglib.github.io/releases/taglib-${PV}.tar.gz' + checkvars['SRC_URI[md5sum]'] = 'cee7be0ccfc892fa433d6c837df9522a' + checkvars['SRC_URI[sha256sum]'] = 'b6d1a5a610aae6ff39d93de5efd0fdc787aa9e9dc1e7026fa4c961b26563526b' + checkvars['DEPENDS'] = set(['boost', 'zlib']) + inherits = ['cmake'] self._test_recipe_contents(recipefile, checkvars, inherits) def test_recipetool_create_github(self): diff --git a/poky/meta/lib/oeqa/selftest/cases/runtime_test.py b/poky/meta/lib/oeqa/selftest/cases/runtime_test.py index d817b755f..20969d2c4 100644 --- a/poky/meta/lib/oeqa/selftest/cases/runtime_test.py +++ b/poky/meta/lib/oeqa/selftest/cases/runtime_test.py @@ -153,6 +153,7 @@ class TestImage(OESelftestTestCase): # Enable package feed signing 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")) features += 'INHERIT += "sign_package_feed"\n' @@ -165,9 +166,6 @@ class TestImage(OESelftestTestCase): bitbake('core-image-full-cmdline socat') bitbake('-c testimage core-image-full-cmdline') - # remove the oeqa-feed-sign temporal directory - shutil.rmtree(self.gpg_home, ignore_errors=True) - def test_testimage_virgl_gtk(self): """ Summary: Check host-assisted accelerate OpenGL functionality in qemu with gtk frontend diff --git a/poky/meta/lib/oeqa/selftest/cases/wic.py b/poky/meta/lib/oeqa/selftest/cases/wic.py index d16eae588..928c476eb 100644 --- a/poky/meta/lib/oeqa/selftest/cases/wic.py +++ b/poky/meta/lib/oeqa/selftest/cases/wic.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # Copyright (c) 2015, Intel Corporation. # @@ -500,7 +499,8 @@ class Wic2(WicTestCase): wicvars = set(bb_vars['WICVARS'].split()) # filter out optional variables wicvars = wicvars.difference(('DEPLOY_DIR_IMAGE', 'IMAGE_BOOT_FILES', - 'INITRD', 'INITRD_LIVE', 'ISODIR')) + 'INITRD', 'INITRD_LIVE', 'ISODIR','INITRAMFS_IMAGE', + 'INITRAMFS_IMAGE_BUNDLE', 'INITRAMFS_LINK_NAME')) 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 @@ -681,6 +681,65 @@ class Wic2(WicTestCase): out = glob(self.resultdir + "%s-*direct" % wksname) self.assertEqual(1, len(out)) + @only_for_arch(['i586', 'i686', 'x86_64']) + def test_biosplusefi_plugin_qemu(self): + """Test biosplusefi plugin in qemu""" + for fstype in ("ext4", "wic"): + config = 'IMAGE_FSTYPES = "%s"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES_append = " efi"\n' % fstype + self.append_config(config) + self.assertEqual(0, bitbake('core-image-minimal').status) + self.remove_config(config) + + with runqemu('core-image-minimal', ssh=False, image_fstype='wic') as qemu: + # Check that we have ONLY two /dev/sda* partitions (/boot and /) + cmd = "grep sda. /proc/partitions | wc -l" + status, output = qemu.run_serial(cmd) + self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) + self.assertEqual(output, '2') + # Check that /dev/sda1 is /boot and that either /dev/root OR /dev/sda2 is / + cmd = "mount | grep '^/dev/' | cut -f1,3 -d ' ' | egrep -c -e '/dev/sda1 /boot' -e '/dev/root /|/dev/sda2 /'" + status, output = qemu.run_serial(cmd) + self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) + self.assertEqual(output, '2') + # Check that /boot has EFI bootx64.efi (required for EFI) + cmd = "ls /boot/EFI/BOOT/bootx64.efi | wc -l" + status, output = qemu.run_serial(cmd) + self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) + self.assertEqual(output, '1') + # Check that "BOOTABLE" flag is set on boot partition (required for PC-Bios) + # Trailing "cat" seems to be required; otherwise run_serial() sends back echo of the input command + cmd = "fdisk -l /dev/sda | grep /dev/sda1 | awk {print'$2'} | cat" + status, output = qemu.run_serial(cmd) + self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) + self.assertEqual(output, '*') + + @only_for_arch(['i586', 'i686', 'x86_64']) + def test_biosplusefi_plugin(self): + """Test biosplusefi plugin""" + # Wic generation below may fail depending on the order of the unittests + # This is because bootimg-pcbios (that bootimg-biosplusefi uses) generate its MBR inside STAGING_DATADIR directory + # which may or may not exists depending on what was built already + # If an image hasn't been built yet, directory ${STAGING_DATADIR}/syslinux won't exists and _get_bootimg_dir() + # will raise with "Couldn't find correct bootimg_dir" + # The easiest way to work-around this issue is to make sure we already built an image here, hence the bitbake call + for fstype in ("ext4", "wic"): + config = 'IMAGE_FSTYPES = "%s"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES_append = " efi"\n' % fstype + self.append_config(config) + self.assertEqual(0, bitbake('core-image-minimal').status) + self.remove_config(config) + + img = 'core-image-minimal' + with NamedTemporaryFile("w", suffix=".wks") as wks: + wks.writelines(['part /boot --active --source bootimg-biosplusefi --sourceparams="loader=grub-efi"\n', + 'part / --source rootfs --fstype=ext4 --align 1024 --use-uuid\n'\ + 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n']) + wks.flush() + cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir) + runCmd(cmd) + wksname = os.path.splitext(os.path.basename(wks.name))[0] + out = glob(self.resultdir + "%s-*.direct" % wksname) + self.assertEqual(1, len(out)) + def test_fs_types(self): """Test filesystem types for empty and not empty partitions""" img = 'core-image-minimal' diff --git a/poky/meta/lib/oeqa/utils/logparser.py b/poky/meta/lib/oeqa/utils/logparser.py index b31214b1c..7313df8ec 100644 --- a/poky/meta/lib/oeqa/utils/logparser.py +++ b/poky/meta/lib/oeqa/utils/logparser.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # # SPDX-License-Identifier: MIT # diff --git a/poky/meta/lib/oeqa/utils/qemurunner.py b/poky/meta/lib/oeqa/utils/qemurunner.py index c16227fc3..b1999fde8 100644 --- a/poky/meta/lib/oeqa/utils/qemurunner.py +++ b/poky/meta/lib/oeqa/utils/qemurunner.py @@ -98,7 +98,7 @@ class QemuRunner: def handleSIGCHLD(self, signum, frame): if self.runqemu and self.runqemu.poll(): if self.runqemu.returncode: - self.logger.debug('runqemu exited with code %d' % self.runqemu.returncode) + self.logger.warning('runqemu exited with code %d' % self.runqemu.returncode) self.logger.debug("Output from runqemu:\n%s" % self.getOutput(self.runqemu.stdout)) self.stop() self._dump_host() @@ -208,9 +208,9 @@ class QemuRunner: if self.runqemu.poll(): if self.runqemu.returncode: # No point waiting any longer - self.logger.debug('runqemu exited with code %d' % self.runqemu.returncode) + self.logger.warning('runqemu exited with code %d' % self.runqemu.returncode) self._dump_host() - self.logger.debug("Output from runqemu:\n%s" % self.getOutput(output)) + self.logger.warning("Output from runqemu:\n%s" % self.getOutput(output)) self.stop() return False time.sleep(0.5) @@ -329,14 +329,14 @@ class QemuRunner: if not reachedlogin: if time.time() >= endtime: - self.logger.debug("Target didn't reach login banner in %d seconds (%s)" % + self.logger.warning("Target didn't reach login banner in %d seconds (%s)" % (self.boottime, time.strftime("%D %H:%M:%S"))) tail = lambda l: "\n".join(l.splitlines()[-25:]) bootlog = bootlog.decode("utf-8") # in case bootlog is empty, use tail qemu log store at self.msg lines = tail(bootlog if bootlog else self.msg) - self.logger.debug("Last 25 lines of text:\n%s" % lines) - self.logger.debug("Check full boot log: %s" % self.logfile) + self.logger.warning("Last 25 lines of text:\n%s" % lines) + self.logger.warning("Check full boot log: %s" % self.logfile) self._dump_host() self.stop() return False @@ -356,11 +356,11 @@ class QemuRunner: else: self.logger.debug("Couldn't configure guest networking") else: - self.logger.debug("Couldn't login into serial console" + self.logger.warning("Couldn't login into serial console" " as root using blank password") - self.logger.debug("The output:\n%s" % output) + self.logger.warning("The output:\n%s" % output) except: - self.logger.debug("Serial console failed while trying to login") + self.logger.warning("Serial console failed while trying to login") return True def stop(self): @@ -414,7 +414,7 @@ class QemuRunner: self.thread.join() def restart(self, qemuparams = None): - self.logger.debug("Restarting qemu process") + self.logger.warning("Restarting qemu process") if self.runqemu.poll() is None: self.stop() if self.start(qemuparams): @@ -425,13 +425,20 @@ class QemuRunner: if not self.runqemu or self.runqemu.poll() is not None: return False if os.path.isfile(self.qemu_pidfile): - f = open(self.qemu_pidfile, 'r') - qemu_pid = f.read() - f.close() - qemupid = int(qemu_pid) - if os.path.exists("/proc/" + str(qemupid)): - self.qemupid = qemupid - return True + # when handling pidfile, qemu creates the file, stat it, lock it and then write to it + # so it's possible that the file has been created but the content is empty + pidfile_timeout = time.time() + 3 + while time.time() < pidfile_timeout: + with open(self.qemu_pidfile, 'r') as f: + qemu_pid = f.read().strip() + # file created but not yet written contents + if not qemu_pid: + time.sleep(0.5) + continue + else: + if os.path.exists("/proc/" + qemu_pid): + self.qemupid = int(qemu_pid) + return True return False def run_serial(self, command, raw=False, timeout=60): |