diff options
Diffstat (limited to 'poky/meta/lib')
22 files changed, 202 insertions, 43 deletions
diff --git a/poky/meta/lib/bblayers/create.py b/poky/meta/lib/bblayers/create.py index 542f31fc81..f49b48d1b4 100644 --- a/poky/meta/lib/bblayers/create.py +++ b/poky/meta/lib/bblayers/create.py @@ -71,7 +71,7 @@ class CreatePlugin(LayerPlugin): def register_commands(self, sp): parser_create_layer = self.add_command(sp, 'create-layer', self.do_create_layer, parserecipes=False) parser_create_layer.add_argument('layerdir', help='Layer directory to create') - parser_create_layer.add_argument('--priority', '-p', default=6, help='Layer directory to create') + parser_create_layer.add_argument('--priority', '-p', default=6, help='Priority of recipes in layer') parser_create_layer.add_argument('--example-recipe-name', '-e', dest='examplerecipe', default='example', help='Filename of the example recipe') parser_create_layer.add_argument('--example-recipe-version', '-v', dest='version', default='0.1', help='Version number for the example recipe') diff --git a/poky/meta/lib/oe/copy_buildsystem.py b/poky/meta/lib/oe/copy_buildsystem.py index 31a84f5b06..d97bf9d1b9 100644 --- a/poky/meta/lib/oe/copy_buildsystem.py +++ b/poky/meta/lib/oe/copy_buildsystem.py @@ -20,7 +20,7 @@ def _smart_copy(src, dest): mode = os.stat(src).st_mode if stat.S_ISDIR(mode): bb.utils.mkdirhier(dest) - cmd = "tar --exclude='.git' --xattrs --xattrs-include='*' -chf - -C %s -p . \ + cmd = "tar --exclude='.git' --exclude='__pycache__' --xattrs --xattrs-include='*' -chf - -C %s -p . \ | tar --xattrs --xattrs-include='*' -xf - -C %s" % (src, dest) subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) else: @@ -259,7 +259,7 @@ def create_locked_sstate_cache(lockedsigs, input_sstate_cache, output_sstate_cac bb.note('Generating sstate-cache...') nativelsbstring = d.getVar('NATIVELSBSTRING') - bb.process.run("gen-lockedsig-cache %s %s %s %s %s" % (lockedsigs, input_sstate_cache, output_sstate_cache, nativelsbstring, filterfile or '')) + bb.process.run("PYTHONDONTWRITEBYTECODE=1 gen-lockedsig-cache %s %s %s %s %s" % (lockedsigs, input_sstate_cache, output_sstate_cache, nativelsbstring, filterfile or '')) if fixedlsbstring and nativelsbstring != fixedlsbstring: nativedir = output_sstate_cache + '/' + nativelsbstring if os.path.isdir(nativedir): @@ -286,7 +286,7 @@ def check_sstate_task_list(d, targets, filteroutfile, cmdprefix='', cwd=None, lo logparam = '-l %s' % logfile else: logparam = '' - cmd = "%sBB_SETSCENE_ENFORCE=1 PSEUDO_DISABLED=1 oe-check-sstate %s -s -o %s %s" % (cmdprefix, targets, filteroutfile, logparam) + cmd = "%sPYTHONDONTWRITEBYTECODE=1 BB_SETSCENE_ENFORCE=1 PSEUDO_DISABLED=1 oe-check-sstate %s -s -o %s %s" % (cmdprefix, targets, filteroutfile, logparam) env = dict(d.getVar('BB_ORIGENV', False)) env.pop('BUILDDIR', '') env.pop('BBPATH', '') diff --git a/poky/meta/lib/oe/cve_check.py b/poky/meta/lib/oe/cve_check.py index ce755f940a..a1d7c292af 100644 --- a/poky/meta/lib/oe/cve_check.py +++ b/poky/meta/lib/oe/cve_check.py @@ -11,8 +11,13 @@ _Version = collections.namedtuple( class Version(): def __init__(self, version, suffix=None): + + suffixes = ["alphabetical", "patch"] + 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]+)?)?)(.*)?""" + elif str(suffix) == "patch": + version_pattern = r"""r?v?(?:(?P<release>[0-9]+(?:[-\.][0-9]+)*)(?P<patch>[-_\.]?(p|patch)(?P<patch_l>[0-9]+))?(?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) @@ -23,7 +28,7 @@ class 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 "", + patch_l=match.group("patch_l") if str(suffix) in suffixes and match.group("patch_l") else "", pre_l=match.group("pre_l"), pre_v=match.group("pre_v") ) diff --git a/poky/meta/lib/oe/package_manager.py b/poky/meta/lib/oe/package_manager.py index b0660411ea..db988d9247 100644 --- a/poky/meta/lib/oe/package_manager.py +++ b/poky/meta/lib/oe/package_manager.py @@ -403,7 +403,7 @@ class PackageManager(object, metaclass=ABCMeta): bb.utils.remove(self.intercepts_dir, True) bb.utils.mkdirhier(self.intercepts_dir) for intercept in postinst_intercepts: - bb.utils.copyfile(intercept, os.path.join(self.intercepts_dir, os.path.basename(intercept))) + shutil.copy(intercept, os.path.join(self.intercepts_dir, os.path.basename(intercept))) @abstractmethod def _handle_intercept_failure(self, failed_script): diff --git a/poky/meta/lib/oe/rootfs.py b/poky/meta/lib/oe/rootfs.py index cd65e62030..9e9f7f1f08 100644 --- a/poky/meta/lib/oe/rootfs.py +++ b/poky/meta/lib/oe/rootfs.py @@ -167,7 +167,7 @@ class Rootfs(object, metaclass=ABCMeta): pass os.rename(self.image_rootfs, self.image_rootfs + '-dbg') - bb.note(" Restoreing original rootfs...") + bb.note(" Restoring original rootfs...") os.rename(self.image_rootfs + '-orig', self.image_rootfs) def _exec_shell_cmd(self, cmd): @@ -304,7 +304,7 @@ class Rootfs(object, metaclass=ABCMeta): def _check_for_kernel_modules(self, modules_dir): for root, dirs, files in os.walk(modules_dir, topdown=True): for name in files: - found_ko = name.endswith(".ko") + found_ko = name.endswith((".ko", ".ko.gz", ".ko.xz")) if found_ko: return found_ko return False diff --git a/poky/meta/lib/oe/sstatesig.py b/poky/meta/lib/oe/sstatesig.py index 51e1d492c3..aeceb100d7 100644 --- a/poky/meta/lib/oe/sstatesig.py +++ b/poky/meta/lib/oe/sstatesig.py @@ -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.error("Manifest %s not found in %s (variant '%s')?" % (manifest, d2.expand(" ".join(pkgarchs)), variant)) + bb.warn("Manifest %s not found in %s (variant '%s')?" % (manifest, d2.expand(" ".join(pkgarchs)), variant)) return None, d2 def OEOuthashBasic(path, sigfile, task, d): diff --git a/poky/meta/lib/oe/terminal.py b/poky/meta/lib/oe/terminal.py index eb10a6e33e..2ac39df9e1 100644 --- a/poky/meta/lib/oe/terminal.py +++ b/poky/meta/lib/oe/terminal.py @@ -163,7 +163,12 @@ class Tmux(Terminal): # devshells, if it's already there, add a new window to it. window_name = 'devshell-%i' % os.getpid() - self.command = 'tmux new -c "{{cwd}}" -d -s {0} -n {0} "{{command}}"'.format(window_name) + self.command = 'tmux new -c "{{cwd}}" -d -s {0} -n {0} "{{command}}"' + if not check_tmux_version('1.9'): + # `tmux new-session -c` was added in 1.9; + # older versions fail with that flag + self.command = 'tmux new -d -s {0} -n {0} "{{command}}"' + self.command = self.command.format(window_name) Terminal.__init__(self, sh_cmd, title, env, d) attach_cmd = 'tmux att -t {0}'.format(window_name) @@ -253,13 +258,18 @@ def spawn(name, sh_cmd, title=None, env=None, d=None): except OSError: return +def check_tmux_version(desired): + vernum = check_terminal_version("tmux") + if vernum and LooseVersion(vernum) < desired: + return False + return vernum + def check_tmux_pane_size(tmux): import subprocess as sub # On older tmux versions (<1.9), return false. The reason # is that there is no easy way to get the height of the active panel # on current window without nested formats (available from version 1.9) - vernum = check_terminal_version("tmux") - if vernum and LooseVersion(vernum) < '1.9': + if not check_tmux_version('1.9'): return False try: p = sub.Popen('%s list-panes -F "#{?pane_active,#{pane_height},}"' % tmux, diff --git a/poky/meta/lib/oeqa/core/case.py b/poky/meta/lib/oeqa/core/case.py index aae451fef2..bc4446a938 100644 --- a/poky/meta/lib/oeqa/core/case.py +++ b/poky/meta/lib/oeqa/core/case.py @@ -43,8 +43,13 @@ class OETestCase(unittest.TestCase): clss.tearDownClassMethod() def _oeSetUp(self): - for d in self.decorators: - d.setUpDecorator() + try: + for d in self.decorators: + d.setUpDecorator() + except: + for d in self.decorators: + d.tearDownDecorator() + raise self.setUpMethod() def _oeTearDown(self): diff --git a/poky/meta/lib/oeqa/core/decorator/oetimeout.py b/poky/meta/lib/oeqa/core/decorator/oetimeout.py index df90d1c798..5e6873ad48 100644 --- a/poky/meta/lib/oeqa/core/decorator/oetimeout.py +++ b/poky/meta/lib/oeqa/core/decorator/oetimeout.py @@ -24,5 +24,6 @@ class OETimeout(OETestDecorator): def tearDownDecorator(self): signal.alarm(0) - signal.signal(signal.SIGALRM, self.alarmSignal) - self.logger.debug("Removed SIGALRM handler") + if hasattr(self, 'alarmSignal'): + signal.signal(signal.SIGALRM, self.alarmSignal) + self.logger.debug("Removed SIGALRM handler") diff --git a/poky/meta/lib/oeqa/core/tests/cases/timeout.py b/poky/meta/lib/oeqa/core/tests/cases/timeout.py index 5dfecc7b7c..69cf969a67 100644 --- a/poky/meta/lib/oeqa/core/tests/cases/timeout.py +++ b/poky/meta/lib/oeqa/core/tests/cases/timeout.py @@ -8,6 +8,7 @@ from time import sleep from oeqa.core.case import OETestCase from oeqa.core.decorator.oetimeout import OETimeout +from oeqa.core.decorator.depends import OETestDepends class TimeoutTest(OETestCase): @@ -19,3 +20,15 @@ class TimeoutTest(OETestCase): def testTimeoutFail(self): sleep(2) self.assertTrue(True, msg='How is this possible?') + + + def testTimeoutSkip(self): + self.skipTest("This test needs to be skipped, so that testTimeoutDepends()'s OETestDepends kicks in") + + @OETestDepends(["timeout.TimeoutTest.testTimeoutSkip"]) + @OETimeout(3) + def testTimeoutDepends(self): + self.assertTrue(False, msg='How is this possible?') + + def testTimeoutUnrelated(self): + sleep(6) diff --git a/poky/meta/lib/oeqa/core/tests/test_decorators.py b/poky/meta/lib/oeqa/core/tests/test_decorators.py index b798bf7d33..5095f39948 100755 --- a/poky/meta/lib/oeqa/core/tests/test_decorators.py +++ b/poky/meta/lib/oeqa/core/tests/test_decorators.py @@ -133,5 +133,11 @@ class TestTimeoutDecorator(TestBase): msg = "OETestTimeout didn't restore SIGALRM" self.assertIs(alarm_signal, signal.getsignal(signal.SIGALRM), msg=msg) + def test_timeout_cancel(self): + tests = ['timeout.TimeoutTest.testTimeoutSkip', 'timeout.TimeoutTest.testTimeoutDepends', 'timeout.TimeoutTest.testTimeoutUnrelated'] + msg = 'Unrelated test failed to complete' + tc = self._testLoader(modules=self.modules, tests=tests) + self.assertTrue(tc.runTests().wasSuccessful(), msg=msg) + if __name__ == '__main__': unittest.main() diff --git a/poky/meta/lib/oeqa/runtime/cases/pam.py b/poky/meta/lib/oeqa/runtime/cases/pam.py index 271a1943e3..a482ded945 100644 --- a/poky/meta/lib/oeqa/runtime/cases/pam.py +++ b/poky/meta/lib/oeqa/runtime/cases/pam.py @@ -8,11 +8,14 @@ from oeqa.runtime.case import OERuntimeTestCase from oeqa.core.decorator.depends import OETestDepends from oeqa.core.decorator.data import skipIfNotFeature +from oeqa.runtime.decorator.package import OEHasPackage class PamBasicTest(OERuntimeTestCase): @skipIfNotFeature('pam', 'Test requires pam to be in DISTRO_FEATURES') @OETestDepends(['ssh.SSHTest.test_ssh']) + @OEHasPackage(['shadow']) + @OEHasPackage(['shadow-base']) def test_pam(self): status, output = self.target.run('login --help') msg = ('login command does not work as expected. ' diff --git a/poky/meta/lib/oeqa/runtime/cases/parselogs.py b/poky/meta/lib/oeqa/runtime/cases/parselogs.py index a1791b5cca..f703927660 100644 --- a/poky/meta/lib/oeqa/runtime/cases/parselogs.py +++ b/poky/meta/lib/oeqa/runtime/cases/parselogs.py @@ -88,6 +88,8 @@ qemux86_common = [ 'tsc: HPET/PMTIMER calibration failed', "modeset(0): Failed to initialize the DRI2 extension", "glamor initialization failed", + "blk_update_request: I/O error, dev fd0, sector 0 op 0x0:(READ)", + "floppy: error", ] + common_errors ignore_errors = { diff --git a/poky/meta/lib/oeqa/selftest/cases/bblayers.py b/poky/meta/lib/oeqa/selftest/cases/bblayers.py index f131d9856c..7d74833f61 100644 --- a/poky/meta/lib/oeqa/selftest/cases/bblayers.py +++ b/poky/meta/lib/oeqa/selftest/cases/bblayers.py @@ -12,6 +12,11 @@ from oeqa.selftest.case import OESelftestTestCase class BitbakeLayers(OESelftestTestCase): + def test_bitbakelayers_layerindexshowdepends(self): + result = runCmd('bitbake-layers layerindex-show-depends meta-poky') + find_in_contents = re.search("openembedded-core", result.output) + self.assertTrue(find_in_contents, msg = "openembedded-core should have been listed at this step. bitbake-layers layerindex-show-depends meta-poky output: %s" % result.output) + def test_bitbakelayers_showcrossdepends(self): result = runCmd('bitbake-layers show-cross-depends') self.assertIn('aspell', result.output) diff --git a/poky/meta/lib/oeqa/selftest/cases/buildoptions.py b/poky/meta/lib/oeqa/selftest/cases/buildoptions.py index e91f0bd18f..b1b9ea7e55 100644 --- a/poky/meta/lib/oeqa/selftest/cases/buildoptions.py +++ b/poky/meta/lib/oeqa/selftest/cases/buildoptions.py @@ -57,15 +57,15 @@ class ImageOptionsTests(OESelftestTestCase): class DiskMonTest(OESelftestTestCase): def test_stoptask_behavior(self): - self.write_config('BB_DISKMON_DIRS = "STOPTASKS,${TMPDIR},100000G,100K"') + self.write_config('BB_DISKMON_DIRS = "STOPTASKS,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"') res = bitbake("delay -c delay", ignore_status = True) self.assertTrue('ERROR: No new tasks can be executed since the disk space monitor action is "STOPTASKS"!' in res.output, msg = "Tasks should have stopped. Disk monitor is set to STOPTASK: %s" % res.output) self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output)) - self.write_config('BB_DISKMON_DIRS = "ABORT,${TMPDIR},100000G,100K"') + self.write_config('BB_DISKMON_DIRS = "ABORT,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"') res = bitbake("delay -c delay", ignore_status = True) self.assertTrue('ERROR: Immediately abort since the disk space monitor action is "ABORT"!' in res.output, "Tasks should have been aborted immediatelly. Disk monitor is set to ABORT: %s" % res.output) self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output)) - self.write_config('BB_DISKMON_DIRS = "WARN,${TMPDIR},100000G,100K"') + self.write_config('BB_DISKMON_DIRS = "WARN,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"') res = bitbake("delay -c delay") self.assertTrue('WARNING: The free space' in res.output, msg = "A warning should have been displayed for disk monitor is set to WARN: %s" %res.output) diff --git a/poky/meta/lib/oeqa/selftest/cases/cve_check.py b/poky/meta/lib/oeqa/selftest/cases/cve_check.py index 3f343a2841..d1947baffc 100644 --- a/poky/meta/lib/oeqa/selftest/cases/cve_check.py +++ b/poky/meta/lib/oeqa/selftest/cases/cve_check.py @@ -34,3 +34,11 @@ class CVECheck(OESelftestTestCase): 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'") + + # consider the trailing "p" and "patch" as patched released when comparing + result = Version("1.0","patch") < Version("1.0p1","patch") + self.assertTrue( result ,msg="Failed to compare version with suffix '1.0' < '1.0p1'") + result = Version("1.0p2","patch") > Version("1.0p1","patch") + self.assertTrue( result ,msg="Failed to compare version with suffix '1.0p2' > '1.0p1'") + result = Version("1.0_patch2","patch") < Version("1.0_patch3","patch") + self.assertTrue( result ,msg="Failed to compare version with suffix '1.0_patch2' < '1.0_patch3'") diff --git a/poky/meta/lib/oeqa/selftest/cases/distrodata.py b/poky/meta/lib/oeqa/selftest/cases/distrodata.py index e1cfc3b621..8e5e24db3d 100644 --- a/poky/meta/lib/oeqa/selftest/cases/distrodata.py +++ b/poky/meta/lib/oeqa/selftest/cases/distrodata.py @@ -63,7 +63,7 @@ but their recipes claim otherwise by setting UPSTREAM_VERSION_UNKNOWN. Please re return True return False - feature = 'require conf/distro/include/maintainers.inc\nLICENSE_FLAGS_WHITELIST += " commercial"\nPARSE_ALL_RECIPES = "1"\n' + feature = 'require conf/distro/include/maintainers.inc\nLICENSE_FLAGS_WHITELIST += " commercial"\nPARSE_ALL_RECIPES = "1"\nPACKAGE_CLASSES = "package_ipk package_deb package_rpm"\n' self.write_config(feature) with bb.tinfoil.Tinfoil() as tinfoil: diff --git a/poky/meta/lib/oeqa/selftest/cases/reproducible.py b/poky/meta/lib/oeqa/selftest/cases/reproducible.py index 7f74cec28f..0e44ce4dbf 100644 --- a/poky/meta/lib/oeqa/selftest/cases/reproducible.py +++ b/poky/meta/lib/oeqa/selftest/cases/reproducible.py @@ -17,6 +17,62 @@ import stat import os import datetime +# For sample packages, see: +# https://autobuilder.yocto.io/pub/repro-fail/oe-reproducible-20201127-0t7wr_oo/ +# https://autobuilder.yocto.io/pub/repro-fail/oe-reproducible-20201127-4s9ejwyp/ +# https://autobuilder.yocto.io/pub/repro-fail/oe-reproducible-20201127-haiwdlbr/ +# https://autobuilder.yocto.io/pub/repro-fail/oe-reproducible-20201127-hwds3mcl/ +# https://autobuilder.yocto.io/pub/repro-fail/oe-reproducible-20201203-sua0pzvc/ +# (both packages/ and packages-excluded/) +exclude_packages = [ + 'acpica-src', + 'babeltrace2-ptest', + 'bind', + 'bootchart2-doc', + 'epiphany', + 'gcr', + 'git', + 'glide', + 'go-dep', + 'go-helloworld', + 'go-runtime', + 'go_', + 'gstreamer1.0-python', + 'hwlatdetect', + 'kernel-devsrc', + 'libaprutil', + 'libcap-ng', + 'libjson', + 'libproxy', + 'lsb-release', + 'lttng-tools-dbg', + 'lttng-tools-ptest', + 'ltp', + 'ovmf-shell-efi', + 'parted-ptest', + 'perf', + 'piglit', + 'pybootchartgui', + 'qemu', + 'quilt-ptest', + "rpm", + 'rsync', + 'ruby', + 'stress-ng', + 'systemd-bootchart', + 'systemtap', + 'valgrind-ptest', + 'vim', + 'webkitgtk', + ] + +def is_excluded(package): + package_name = os.path.basename(package) + for i in exclude_packages: + if package_name.startswith(i): + return i + return None + MISSING = 'MISSING' DIFFERENT = 'DIFFERENT' SAME = 'SAME' @@ -39,14 +95,21 @@ class PackageCompareResults(object): self.total = [] self.missing = [] self.different = [] + self.different_excluded = [] self.same = [] + self.active_exclusions = set() def add_result(self, r): self.total.append(r) if r.status == MISSING: self.missing.append(r) elif r.status == DIFFERENT: - self.different.append(r) + exclusion = is_excluded(r.reference) + if exclusion: + self.different_excluded.append(r) + self.active_exclusions.add(exclusion) + else: + self.different.append(r) else: self.same.append(r) @@ -54,10 +117,14 @@ class PackageCompareResults(object): self.total.sort() self.missing.sort() self.different.sort() + self.different_excluded.sort() self.same.sort() def __str__(self): - return 'same=%i different=%i missing=%i total=%i' % (len(self.same), len(self.different), len(self.missing), len(self.total)) + return 'same=%i different=%i different_excluded=%i missing=%i total=%i\nunused_exclusions=%s' % (len(self.same), len(self.different), len(self.different_excluded), len(self.missing), len(self.total), self.unused_exclusions()) + + def unused_exclusions(self): + return sorted(set(exclude_packages) - self.active_exclusions) def compare_file(reference, test, diffutils_sysroot): result = CompareResult() @@ -78,8 +145,14 @@ def compare_file(reference, test, diffutils_sysroot): return result class ReproducibleTests(OESelftestTestCase): + # Test the reproducibility of whatever is built between sstate_targets and targets + package_classes = ['deb', 'ipk'] - images = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline'] + + # targets are the things we want to test the reproducibility of + targets = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline', 'world'] + # sstate targets are things to pull from sstate to potentially cut build/debugging time + sstate_targets = [] save_results = False if 'OEQA_DEBUGGING_SAVED_OUTPUT' in os.environ: save_results = os.environ['OEQA_DEBUGGING_SAVED_OUTPUT'] @@ -150,10 +223,17 @@ class ReproducibleTests(OESelftestTestCase): PACKAGE_CLASSES = "{package_classes}" INHIBIT_PACKAGE_STRIP = "1" TMPDIR = "{tmpdir}" + LICENSE_FLAGS_WHITELIST = "commercial" + DISTRO_FEATURES_append = ' systemd pam' ''').format(package_classes=' '.join('package_%s' % c for c in self.package_classes), tmpdir=tmpdir) if not use_sstate: + if self.sstate_targets: + self.logger.info("Building prebuild for %s (sstate allowed)..." % (name)) + self.write_config(config) + bitbake(' '.join(self.sstate_targets)) + # This config fragment will disable using shared and the sstate # mirror, forcing a complete build from scratch config += textwrap.dedent('''\ @@ -164,7 +244,8 @@ class ReproducibleTests(OESelftestTestCase): 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)) + # targets used to be called images + bitbake(' '.join(getattr(self, 'images', self.targets))) return d def test_reproducible_builds(self): @@ -212,6 +293,7 @@ class ReproducibleTests(OESelftestTestCase): self.write_package_list(package_class, 'missing', result.missing) self.write_package_list(package_class, 'different', result.different) + self.write_package_list(package_class, 'different_excluded', result.different_excluded) self.write_package_list(package_class, 'same', result.same) if self.save_results: @@ -219,8 +301,12 @@ class ReproducibleTests(OESelftestTestCase): self.copy_file(d.reference, '/'.join([save_dir, 'packages', strip_topdir(d.reference)])) self.copy_file(d.test, '/'.join([save_dir, 'packages', strip_topdir(d.test)])) + for d in result.different_excluded: + self.copy_file(d.reference, '/'.join([save_dir, 'packages-excluded', strip_topdir(d.reference)])) + self.copy_file(d.test, '/'.join([save_dir, 'packages-excluded', strip_topdir(d.test)])) + if result.missing or result.different: - fails.append("The following %s packages are missing or different: %s" % + fails.append("The following %s packages are missing or different and not in exclusion list: %s" % (c, '\n'.join(r.test for r in (result.missing + result.different)))) # Clean up empty directories diff --git a/poky/meta/lib/oeqa/selftest/cases/runqemu.py b/poky/meta/lib/oeqa/selftest/cases/runqemu.py index 7e676bcb41..da22f77b27 100644 --- a/poky/meta/lib/oeqa/selftest/cases/runqemu.py +++ b/poky/meta/lib/oeqa/selftest/cases/runqemu.py @@ -163,12 +163,11 @@ class QemuTest(OESelftestTestCase): bitbake(cls.recipe) def _start_qemu_shutdown_check_if_shutdown_succeeded(self, qemu, timeout): + # Allow the runner's LoggingThread instance to exit without errors + # (such as the exception "Console connection closed unexpectedly") + # as qemu will disappear when we shut it down + qemu.runner.allowexit() qemu.run_serial("shutdown -h now") - # Stop thread will stop the LoggingThread instance used for logging - # qemu through serial console, stop thread will prevent this code - # from facing exception (Console connection closed unexpectedly) - # when qemu was shutdown by the above shutdown command - qemu.runner.stop_thread() time_track = 0 try: while True: diff --git a/poky/meta/lib/oeqa/selftest/cases/wic.py b/poky/meta/lib/oeqa/selftest/cases/wic.py index 0435aa29c9..f7abdba015 100644 --- a/poky/meta/lib/oeqa/selftest/cases/wic.py +++ b/poky/meta/lib/oeqa/selftest/cases/wic.py @@ -905,14 +905,18 @@ class Wic2(WicTestCase): @only_for_arch(['i586', 'i686', 'x86_64']) def test_rawcopy_plugin_qemu(self): """Test rawcopy plugin in qemu""" - # build ext4 and wic images - for fstype in ("ext4", "wic"): - config = 'IMAGE_FSTYPES = "%s"\nWKS_FILE = "test_rawcopy_plugin.wks.in"\n' % fstype - self.append_config(config) - self.assertEqual(0, bitbake('core-image-minimal').status) - self.remove_config(config) + # build ext4 and then use it for a wic image + config = 'IMAGE_FSTYPES = "ext4"\n' + self.append_config(config) + self.assertEqual(0, bitbake('core-image-minimal').status) + self.remove_config(config) - with runqemu('core-image-minimal', ssh=False, image_fstype='wic') as qemu: + config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_rawcopy_plugin.wks.in"\n' + self.append_config(config) + self.assertEqual(0, bitbake('core-image-minimal-mtdutils').status) + self.remove_config(config) + + with runqemu('core-image-minimal-mtdutils', ssh=False, image_fstype='wic') as qemu: cmd = "grep sda. /proc/partitions |wc -l" status, output = qemu.run_serial(cmd) self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) diff --git a/poky/meta/lib/oeqa/utils/commands.py b/poky/meta/lib/oeqa/utils/commands.py index a71c16ab14..024261410e 100644 --- a/poky/meta/lib/oeqa/utils/commands.py +++ b/poky/meta/lib/oeqa/utils/commands.py @@ -174,11 +174,8 @@ def runCmd(command, ignore_status=False, timeout=None, assert_error=True, sync=T if native_sysroot: extra_paths = "%s/sbin:%s/usr/sbin:%s/usr/bin" % \ (native_sysroot, native_sysroot, native_sysroot) - extra_libpaths = "%s/lib:%s/usr/lib" % \ - (native_sysroot, native_sysroot) nenv = dict(options.get('env', os.environ)) nenv['PATH'] = extra_paths + ':' + nenv.get('PATH', '') - nenv['LD_LIBRARY_PATH'] = extra_libpaths + ':' + nenv.get('LD_LIBRARY_PATH', '') options['env'] = nenv cmd = Command(command, timeout=timeout, output_log=output_log, **options) diff --git a/poky/meta/lib/oeqa/utils/qemurunner.py b/poky/meta/lib/oeqa/utils/qemurunner.py index 77ec939ad7..79db2cc247 100644 --- a/poky/meta/lib/oeqa/utils/qemurunner.py +++ b/poky/meta/lib/oeqa/utils/qemurunner.py @@ -70,6 +70,8 @@ class QemuRunner: self.monitorpipe = None self.logger = logger + # Whether we're expecting an exit and should show related errors + self.canexit = False # Enable testing other OS's # Set commands for target communication, and default to Linux ALWAYS @@ -467,6 +469,11 @@ class QemuRunner: self.thread.stop() self.thread.join() + def allowexit(self): + self.canexit = True + if self.thread: + self.thread.allowexit() + def restart(self, qemuparams = None): self.logger.warning("Restarting qemu process") if self.runqemu.poll() is None: @@ -522,7 +529,9 @@ class QemuRunner: if re.search(self.boot_patterns['search_cmd_finished'], data): break else: - raise Exception("No data on serial console socket") + if self.canexit: + return (1, "") + raise Exception("No data on serial console socket, connection closed?") if data: if raw: @@ -560,6 +569,7 @@ class LoggingThread(threading.Thread): self.logger = logger self.readsock = None self.running = False + self.canexit = False self.errorevents = select.POLLERR | select.POLLHUP | select.POLLNVAL self.readevents = select.POLLIN | select.POLLPRI @@ -593,6 +603,9 @@ class LoggingThread(threading.Thread): self.close_ignore_error(self.writepipe) self.running = False + def allowexit(self): + self.canexit = True + def eventloop(self): poll = select.poll() event_read_mask = self.errorevents | self.readevents @@ -638,7 +651,7 @@ class LoggingThread(threading.Thread): data = self.readsock.recv(count) except socket.error as e: if e.errno == errno.EAGAIN or e.errno == errno.EWOULDBLOCK: - return '' + return b'' else: raise @@ -649,7 +662,9 @@ class LoggingThread(threading.Thread): # happened. But for this code it counts as an # error since the connection shouldn't go away # until qemu exits. - raise Exception("Console connection closed unexpectedly") + if not self.canexit: + raise Exception("Console connection closed unexpectedly") + return b'' return data |