From 1c7d6584a7811b7785ae5c1e378f14b5ba0971cf Mon Sep 17 00:00:00 2001 From: takeshi_hoshina Date: Mon, 2 Nov 2020 11:07:33 +0900 Subject: basesystem-jj recipes --- external/poky/meta/lib/oeqa/selftest/case.py | 52 ++-- .../lib/oeqa/selftest/cases/_sstatetests_noauto.py | 4 + .../poky/meta/lib/oeqa/selftest/cases/archiver.py | 134 ++++++++++- .../poky/meta/lib/oeqa/selftest/cases/bblayers.py | 20 +- .../poky/meta/lib/oeqa/selftest/cases/bbtests.py | 95 ++++---- .../poky/meta/lib/oeqa/selftest/cases/binutils.py | 50 ++++ .../meta/lib/oeqa/selftest/cases/buildhistory.py | 4 + .../meta/lib/oeqa/selftest/cases/buildoptions.py | 35 ++- .../meta/lib/oeqa/selftest/cases/containerimage.py | 6 +- .../poky/meta/lib/oeqa/selftest/cases/devtool.py | 121 +++++----- .../meta/lib/oeqa/selftest/cases/distrodata.py | 133 ++++++----- external/poky/meta/lib/oeqa/selftest/cases/eSDK.py | 7 +- .../lib/oeqa/selftest/cases/efibootpartition.py | 2 + .../poky/meta/lib/oeqa/selftest/cases/fetch.py | 6 +- external/poky/meta/lib/oeqa/selftest/cases/gcc.py | 152 ++++++++++++ .../poky/meta/lib/oeqa/selftest/cases/glibc.py | 89 +++++++ .../meta/lib/oeqa/selftest/cases/gotoolchain.py | 4 + .../meta/lib/oeqa/selftest/cases/image_typedep.py | 6 +- .../meta/lib/oeqa/selftest/cases/imagefeatures.py | 86 +++++-- .../lib/oeqa/selftest/cases/incompatible_lic.py | 135 +++++++++++ .../lib/oeqa/selftest/cases/kerneldevelopment.py | 67 ++++++ .../meta/lib/oeqa/selftest/cases/layerappend.py | 6 +- .../poky/meta/lib/oeqa/selftest/cases/liboe.py | 8 +- .../meta/lib/oeqa/selftest/cases/lic_checksum.py | 6 +- .../poky/meta/lib/oeqa/selftest/cases/manifest.py | 14 +- .../poky/meta/lib/oeqa/selftest/cases/meta_ide.py | 12 +- .../meta/lib/oeqa/selftest/cases/multiconfig.py | 72 ++++++ .../lib/oeqa/selftest/cases/oelib/buildhistory.py | 10 +- .../poky/meta/lib/oeqa/selftest/cases/oelib/elf.py | 4 + .../meta/lib/oeqa/selftest/cases/oelib/license.py | 4 + .../meta/lib/oeqa/selftest/cases/oelib/path.py | 4 + .../meta/lib/oeqa/selftest/cases/oelib/types.py | 4 + .../meta/lib/oeqa/selftest/cases/oelib/utils.py | 4 + .../poky/meta/lib/oeqa/selftest/cases/oescripts.py | 163 ++++++++++++- .../poky/meta/lib/oeqa/selftest/cases/package.py | 13 +- .../poky/meta/lib/oeqa/selftest/cases/pkgdata.py | 17 +- .../poky/meta/lib/oeqa/selftest/cases/prservice.py | 18 +- .../meta/lib/oeqa/selftest/cases/recipetool.py | 139 ++++++----- .../meta/lib/oeqa/selftest/cases/recipeutils.py | 140 +++++++++++ .../meta/lib/oeqa/selftest/cases/reproducible.py | 240 +++++++++++++++++++ .../lib/oeqa/selftest/cases/resulttooltests.py | 6 +- .../poky/meta/lib/oeqa/selftest/cases/runcmd.py | 34 +-- .../poky/meta/lib/oeqa/selftest/cases/runqemu.py | 17 +- .../meta/lib/oeqa/selftest/cases/runtime_test.py | 264 +++++++++++++++++---- .../poky/meta/lib/oeqa/selftest/cases/selftest.py | 6 +- .../poky/meta/lib/oeqa/selftest/cases/signing.py | 39 +-- .../poky/meta/lib/oeqa/selftest/cases/sstate.py | 8 +- .../meta/lib/oeqa/selftest/cases/sstatetests.py | 100 +++++--- .../poky/meta/lib/oeqa/selftest/cases/sysroot.py | 37 +++ .../poky/meta/lib/oeqa/selftest/cases/tinfoil.py | 28 +-- external/poky/meta/lib/oeqa/selftest/cases/wic.py | 240 +++++++++++-------- external/poky/meta/lib/oeqa/selftest/context.py | 167 +++++++++---- 52 files changed, 2379 insertions(+), 653 deletions(-) create mode 100644 external/poky/meta/lib/oeqa/selftest/cases/binutils.py create mode 100644 external/poky/meta/lib/oeqa/selftest/cases/gcc.py create mode 100644 external/poky/meta/lib/oeqa/selftest/cases/glibc.py create mode 100644 external/poky/meta/lib/oeqa/selftest/cases/incompatible_lic.py create mode 100644 external/poky/meta/lib/oeqa/selftest/cases/kerneldevelopment.py create mode 100644 external/poky/meta/lib/oeqa/selftest/cases/multiconfig.py create mode 100644 external/poky/meta/lib/oeqa/selftest/cases/recipeutils.py create mode 100644 external/poky/meta/lib/oeqa/selftest/cases/reproducible.py create mode 100644 external/poky/meta/lib/oeqa/selftest/cases/sysroot.py (limited to 'external/poky/meta/lib/oeqa/selftest') diff --git a/external/poky/meta/lib/oeqa/selftest/case.py b/external/poky/meta/lib/oeqa/selftest/case.py index 9c08d595..dcad4f76 100644 --- a/external/poky/meta/lib/oeqa/selftest/case.py +++ b/external/poky/meta/lib/oeqa/selftest/case.py @@ -1,9 +1,11 @@ +# # Copyright (C) 2013-2017 Intel Corporation -# Released under the MIT license (see COPYING.MIT) +# +# SPDX-License-Identifier: MIT +# import sys import os -import shutil import glob import errno from unittest.util import safe_repr @@ -27,9 +29,7 @@ class OESelftestTestCase(OETestCase): cls.builddir = cls.tc.config_paths['builddir'] cls.localconf_path = cls.tc.config_paths['localconf'] - cls.localconf_backup = cls.tc.config_paths['localconf_class_backup'] cls.local_bblayers_path = cls.tc.config_paths['bblayers'] - cls.local_bblayers_backup = cls.tc.config_paths['bblayers_class_backup'] cls.testinc_path = os.path.join(cls.tc.config_paths['builddir'], "conf/selftest.inc") @@ -40,8 +40,7 @@ class OESelftestTestCase(OETestCase): cls._track_for_cleanup = [ cls.testinc_path, cls.testinc_bblayers_path, - cls.machineinc_path, cls.localconf_backup, - cls.local_bblayers_backup] + cls.machineinc_path] cls.add_include() @@ -99,30 +98,6 @@ class OESelftestTestCase(OETestCase): def setUp(self): super(OESelftestTestCase, self).setUp() os.chdir(self.builddir) - # Check if local.conf or bblayers.conf files backup exists - # from a previous failed test and restore them - if os.path.isfile(self.localconf_backup) or os.path.isfile( - self.local_bblayers_backup): - self.logger.debug("\ -Found a local.conf and/or bblayers.conf backup from a previously aborted test.\ -Restoring these files now, but tests should be re-executed from a clean environment\ -to ensure accurate results.") - try: - shutil.copyfile(self.localconf_backup, self.localconf_path) - except OSError as e: - if e.errno != errno.ENOENT: - raise - try: - shutil.copyfile(self.local_bblayers_backup, - self.local_bblayers_path) - except OSError as e: - if e.errno != errno.ENOENT: - raise - else: - # backup local.conf and bblayers.conf - shutil.copyfile(self.localconf_path, self.localconf_backup) - shutil.copyfile(self.local_bblayers_path, self.local_bblayers_backup) - self.logger.debug("Creating local.conf and bblayers.conf backups.") # we don't know what the previous test left around in config or inc files # if it failed so we need a fresh start try: @@ -190,13 +165,20 @@ to ensure accurate results.") self.logger.debug("Adding path '%s' to be cleaned up when test is over" % path) self._track_for_cleanup.append(path) - def write_config(self, data): - """Write to /conf/selftest.inc""" + def write_config(self, data, multiconfig=None): + """Write to config file""" + if multiconfig: + multiconfigdir = "%s/conf/multiconfig" % self.builddir + os.makedirs(multiconfigdir, exist_ok=True) + dest_path = '%s/%s.conf' % (multiconfigdir, multiconfig) + self.track_for_cleanup(dest_path) + else: + dest_path = self.testinc_path - self.logger.debug("Writing to: %s\n%s\n" % (self.testinc_path, data)) - ftools.write_file(self.testinc_path, data) + self.logger.debug("Writing to: %s\n%s\n" % (dest_path, data)) + ftools.write_file(dest_path, data) - if self.tc.custommachine and 'MACHINE' in data: + if not multiconfig and self.tc.custommachine and 'MACHINE' in data: machine = get_bb_var('MACHINE') self.logger.warning('MACHINE overridden: %s' % machine) diff --git a/external/poky/meta/lib/oeqa/selftest/cases/_sstatetests_noauto.py b/external/poky/meta/lib/oeqa/selftest/cases/_sstatetests_noauto.py index 0e589623..f7c356ad 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/_sstatetests_noauto.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/_sstatetests_noauto.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + import os import shutil diff --git a/external/poky/meta/lib/oeqa/selftest/cases/archiver.py b/external/poky/meta/lib/oeqa/selftest/cases/archiver.py index 0a6d4e32..bc5447d2 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/archiver.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/archiver.py @@ -1,12 +1,14 @@ +# +# SPDX-License-Identifier: MIT +# + import os import glob from oeqa.utils.commands import bitbake, get_bb_vars from oeqa.selftest.case import OESelftestTestCase -from oeqa.core.decorator.oeid import OETestID class Archiver(OESelftestTestCase): - @OETestID(1345) def test_archiver_allows_to_filter_on_recipe_name(self): """ Summary: The archiver should offer the possibility to filter on the recipe. (#6929) @@ -40,7 +42,6 @@ class Archiver(OESelftestTestCase): excluded_present = len(glob.glob(src_path + '/%s-*' % exclude_recipe)) self.assertFalse(excluded_present, 'Recipe %s was not excluded.' % exclude_recipe) - @OETestID(1900) def test_archiver_filters_by_type(self): """ Summary: The archiver is documented to filter on the recipe type. @@ -73,7 +74,6 @@ class Archiver(OESelftestTestCase): excluded_present = len(glob.glob(src_path_native + '/%s-*' % native_recipe)) self.assertFalse(excluded_present, 'Recipe %s was not excluded.' % native_recipe) - @OETestID(1901) def test_archiver_filters_by_type_and_name(self): """ Summary: Test that the archiver archives by recipe type, taking the @@ -126,6 +126,132 @@ class Archiver(OESelftestTestCase): features = 'INHERIT += "archiver"\n' features += 'ARCHIVER_MODE[srpm] = "1"\n' + features += 'PACKAGE_CLASSES = "package_rpm"\n' self.write_config(features) bitbake('-n core-image-sato') + + def _test_archiver_mode(self, mode, target_file_name, extra_config=None): + target = "selftest-ed" + + features = 'INHERIT += "archiver"\n' + features += 'ARCHIVER_MODE[src] = "%s"\n' % (mode) + if extra_config: + features += extra_config + self.write_config(features) + + bitbake('-c clean %s' % (target)) + bitbake('-c deploy_archives %s' % (target)) + + bb_vars = get_bb_vars(['DEPLOY_DIR_SRC', 'TARGET_SYS']) + glob_str = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['TARGET_SYS'], '%s-*' % (target)) + glob_result = glob.glob(glob_str) + self.assertTrue(glob_result, 'Missing archiver directory for %s' % (target)) + + archive_path = os.path.join(glob_result[0], target_file_name) + self.assertTrue(os.path.exists(archive_path), 'Missing archive file %s' % (target_file_name)) + + def test_archiver_mode_original(self): + """ + Test that the archiver works with `ARCHIVER_MODE[src] = "original"`. + """ + + self._test_archiver_mode('original', 'ed-1.14.1.tar.lz') + + def test_archiver_mode_patched(self): + """ + Test that the archiver works with `ARCHIVER_MODE[src] = "patched"`. + """ + + self._test_archiver_mode('patched', 'selftest-ed-1.14.1-r0-patched.tar.gz') + + def test_archiver_mode_configured(self): + """ + Test that the archiver works with `ARCHIVER_MODE[src] = "configured"`. + """ + + self._test_archiver_mode('configured', 'selftest-ed-1.14.1-r0-configured.tar.gz') + + def test_archiver_mode_recipe(self): + """ + Test that the archiver works with `ARCHIVER_MODE[recipe] = "1"`. + """ + + self._test_archiver_mode('patched', 'selftest-ed-1.14.1-r0-recipe.tar.gz', + 'ARCHIVER_MODE[recipe] = "1"\n') + + def test_archiver_mode_diff(self): + """ + Test that the archiver works with `ARCHIVER_MODE[diff] = "1"`. + Exclusions controlled by `ARCHIVER_MODE[diff-exclude]` are not yet tested. + """ + + self._test_archiver_mode('patched', 'selftest-ed-1.14.1-r0-diff.gz', + 'ARCHIVER_MODE[diff] = "1"\n') + + def test_archiver_mode_dumpdata(self): + """ + Test that the archiver works with `ARCHIVER_MODE[dumpdata] = "1"`. + """ + + self._test_archiver_mode('patched', 'selftest-ed-1.14.1-r0-showdata.dump', + 'ARCHIVER_MODE[dumpdata] = "1"\n') + + def test_archiver_mode_mirror(self): + """ + Test that the archiver works with `ARCHIVER_MODE[src] = "mirror"`. + """ + + self._test_archiver_mode('mirror', 'ed-1.14.1.tar.lz', + 'BB_GENERATE_MIRROR_TARBALLS = "1"\n') + + def test_archiver_mode_mirror_excludes(self): + """ + Test that the archiver works with `ARCHIVER_MODE[src] = "mirror"` and + correctly excludes an archive when its URL matches + `ARCHIVER_MIRROR_EXCLUDE`. + """ + + target='selftest-ed' + target_file_name = 'ed-1.14.1.tar.lz' + + features = 'INHERIT += "archiver"\n' + features += 'ARCHIVER_MODE[src] = "mirror"\n' + features += 'BB_GENERATE_MIRROR_TARBALLS = "1"\n' + features += 'ARCHIVER_MIRROR_EXCLUDE = "${GNU_MIRROR}"\n' + self.write_config(features) + + bitbake('-c clean %s' % (target)) + bitbake('-c deploy_archives %s' % (target)) + + bb_vars = get_bb_vars(['DEPLOY_DIR_SRC', 'TARGET_SYS']) + glob_str = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['TARGET_SYS'], '%s-*' % (target)) + glob_result = glob.glob(glob_str) + self.assertTrue(glob_result, 'Missing archiver directory for %s' % (target)) + + archive_path = os.path.join(glob_result[0], target_file_name) + self.assertFalse(os.path.exists(archive_path), 'Failed to exclude archive file %s' % (target_file_name)) + + def test_archiver_mode_mirror_combined(self): + """ + Test that the archiver works with `ARCHIVER_MODE[src] = "mirror"` + and `ARCHIVER_MODE[mirror] = "combined"`. Archives for multiple recipes + should all end up in the 'mirror' directory. + """ + + features = 'INHERIT += "archiver"\n' + features += 'ARCHIVER_MODE[src] = "mirror"\n' + features += 'ARCHIVER_MODE[mirror] = "combined"\n' + features += 'BB_GENERATE_MIRROR_TARBALLS = "1"\n' + features += 'COPYLEFT_LICENSE_INCLUDE = "*"\n' + self.write_config(features) + + for target in ['selftest-ed', 'selftest-hardlink']: + bitbake('-c clean %s' % (target)) + bitbake('-c deploy_archives %s' % (target)) + + bb_vars = get_bb_vars(['DEPLOY_DIR_SRC']) + for target_file_name in ['ed-1.14.1.tar.lz', 'hello.c']: + glob_str = os.path.join(bb_vars['DEPLOY_DIR_SRC'], 'mirror', target_file_name) + glob_result = glob.glob(glob_str) + self.assertTrue(glob_result, 'Missing archive file %s' % (target_file_name)) diff --git a/external/poky/meta/lib/oeqa/selftest/cases/bblayers.py b/external/poky/meta/lib/oeqa/selftest/cases/bblayers.py index 447c54b7..f131d985 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/bblayers.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/bblayers.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + import os import re @@ -5,33 +9,27 @@ import oeqa.utils.ftools as ftools from oeqa.utils.commands import runCmd, get_bb_var, get_bb_vars from oeqa.selftest.case import OESelftestTestCase -from oeqa.core.decorator.oeid import OETestID class BitbakeLayers(OESelftestTestCase): - @OETestID(756) def test_bitbakelayers_showcrossdepends(self): result = runCmd('bitbake-layers show-cross-depends') - self.assertTrue('aspell' in result.output, msg = "No dependencies were shown. bitbake-layers show-cross-depends output: %s" % result.output) + self.assertIn('aspell', result.output) - @OETestID(83) def test_bitbakelayers_showlayers(self): result = runCmd('bitbake-layers show-layers') - self.assertTrue('meta-selftest' in result.output, msg = "No layers were shown. bitbake-layers show-layers output: %s" % result.output) + self.assertIn('meta-selftest', result.output) - @OETestID(93) def test_bitbakelayers_showappends(self): recipe = "xcursor-transparent-theme" bb_file = self.get_recipe_basename(recipe) result = runCmd('bitbake-layers show-appends') - self.assertTrue(bb_file in result.output, msg="%s file was not recognised. bitbake-layers show-appends output: %s" % (bb_file, result.output)) + self.assertIn(bb_file, result.output) - @OETestID(90) def test_bitbakelayers_showoverlayed(self): result = runCmd('bitbake-layers show-overlayed') - self.assertTrue('aspell' in result.output, msg="aspell overlayed recipe was not recognised bitbake-layers show-overlayed %s" % result.output) + self.assertIn('aspell', result.output) - @OETestID(95) def test_bitbakelayers_flatten(self): recipe = "xcursor-transparent-theme" recipe_path = "recipes-graphics/xcursor-transparent-theme" @@ -46,7 +44,6 @@ class BitbakeLayers(OESelftestTestCase): find_in_contents = re.search("##### bbappended from meta-selftest #####\n(.*\n)*include test_recipe.inc", contents) self.assertTrue(find_in_contents, msg = "Flattening layers did not work. bitbake-layers flatten output: %s" % result.output) - @OETestID(1195) def test_bitbakelayers_add_remove(self): test_layer = os.path.join(get_bb_var('COREBASE'), 'meta-skeleton') result = runCmd('bitbake-layers show-layers') @@ -64,7 +61,6 @@ class BitbakeLayers(OESelftestTestCase): result = runCmd('bitbake-layers show-layers') self.assertNotIn('meta-skeleton', result.output, msg = "meta-skeleton should have been removed at this step. bitbake-layers show-layers output: %s" % result.output) - @OETestID(1384) def test_bitbakelayers_showrecipes(self): result = runCmd('bitbake-layers show-recipes') self.assertIn('aspell:', result.output) diff --git a/external/poky/meta/lib/oeqa/selftest/cases/bbtests.py b/external/poky/meta/lib/oeqa/selftest/cases/bbtests.py index 005fdd09..dc423ec4 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/bbtests.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/bbtests.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + import os import re @@ -5,7 +9,6 @@ import oeqa.utils.ftools as ftools from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars from oeqa.selftest.case import OESelftestTestCase -from oeqa.core.decorator.oeid import OETestID class BitbakeTests(OESelftestTestCase): @@ -14,13 +17,11 @@ class BitbakeTests(OESelftestTestCase): if line in l: return l - @OETestID(789) # Test bitbake can run from the /conf directory def test_run_bitbake_from_dir_1(self): os.chdir(os.path.join(self.builddir, 'conf')) self.assertEqual(bitbake('-e').status, 0, msg = "bitbake couldn't run from \"conf\" dir") - @OETestID(790) # Test bitbake can run from the 's parent directory def test_run_bitbake_from_dir_2(self): my_env = os.environ.copy() @@ -36,17 +37,15 @@ class BitbakeTests(OESelftestTestCase): self.assertEqual(bitbake('-e', env=my_env).status, 0, msg = "bitbake couldn't run from /tmp/") - @OETestID(806) def test_event_handler(self): self.write_config("INHERIT += \"test_events\"") result = bitbake('m4-native') - find_build_started = re.search("NOTE: Test for bb\.event\.BuildStarted(\n.*)*NOTE: Executing RunQueue Tasks", result.output) - find_build_completed = re.search("Tasks Summary:.*(\n.*)*NOTE: Test for bb\.event\.BuildCompleted", 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) - self.assertFalse('Test for bb.event.InvalidEvent' in result.output, msg = "\"Test for bb.event.InvalidEvent\" message found during bitbake process. bitbake output: %s" % result.output) + self.assertNotIn('Test for bb.event.InvalidEvent', result.output) - @OETestID(103) def test_local_sstate(self): bitbake('m4-native') bitbake('m4-native -cclean') @@ -54,17 +53,14 @@ class BitbakeTests(OESelftestTestCase): find_setscene = re.search("m4-native.*do_.*_setscene", result.output) self.assertTrue(find_setscene, msg = "No \"m4-native.*do_.*_setscene\" message found during bitbake m4-native. bitbake output: %s" % result.output ) - @OETestID(105) def test_bitbake_invalid_recipe(self): result = bitbake('-b asdf', ignore_status=True) self.assertTrue("ERROR: Unable to find any recipe file matching 'asdf'" in result.output, msg = "Though asdf recipe doesn't exist, bitbake didn't output any err. message. bitbake output: %s" % result.output) - @OETestID(107) def test_bitbake_invalid_target(self): result = bitbake('asdf', ignore_status=True) - self.assertTrue("ERROR: Nothing PROVIDES 'asdf'" in result.output, msg = "Though no 'asdf' target exists, bitbake didn't output any err. message. bitbake output: %s" % result.output) + self.assertIn("ERROR: Nothing PROVIDES 'asdf'", result.output) - @OETestID(106) def test_warnings_errors(self): result = bitbake('-b asdf', ignore_status=True) find_warnings = re.search("Summary: There w.{2,3}? [1-9][0-9]* WARNING messages* shown", result.output) @@ -72,7 +68,6 @@ class BitbakeTests(OESelftestTestCase): self.assertTrue(find_warnings, msg="Did not find the mumber of warnings at the end of the build:\n" + result.output) self.assertTrue(find_errors, msg="Did not find the mumber of errors at the end of the build:\n" + result.output) - @OETestID(108) def test_invalid_patch(self): # This patch should fail to apply. self.write_recipeinc('man-db', 'FILESEXTRAPATHS_prepend := "${THISDIR}/files:"\nSRC_URI += "file://0001-Test-patch-here.patch"') @@ -80,10 +75,12 @@ class BitbakeTests(OESelftestTestCase): result = bitbake('man-db -c patch', ignore_status=True) self.delete_recipeinc('man-db') bitbake('-cclean man-db') - line = self.getline(result, "Function failed: patch_do_patch") - self.assertTrue(line and line.startswith("ERROR:"), msg = "Incorrectly formed patch application didn't fail. bitbake output: %s" % result.output) + found = False + for l in result.output.split('\n'): + if l.startswith("ERROR:") and "failed" in l and "do_patch" in l: + found = l + self.assertTrue(found and found.startswith("ERROR:"), msg = "Incorrectly formed patch application didn't fail. bitbake output: %s" % result.output) - @OETestID(1354) def test_force_task_1(self): # test 1 from bug 5875 test_recipe = 'zlib' @@ -108,7 +105,6 @@ class BitbakeTests(OESelftestTestCase): ret = bitbake(test_recipe) self.assertIn('task do_package_write_rpm:', ret.output, 'Task do_package_write_rpm did not re-executed.') - @OETestID(163) def test_force_task_2(self): # test 2 from bug 5875 test_recipe = 'zlib' @@ -121,15 +117,14 @@ class BitbakeTests(OESelftestTestCase): for task in look_for_tasks: self.assertIn(task, result.output, msg="Couldn't find %s task.") - @OETestID(167) def test_bitbake_g(self): - result = bitbake('-g core-image-minimal') - for f in ['pn-buildlist', 'recipe-depends.dot', 'task-depends.dot']: + recipe = 'base-files' + result = bitbake('-g %s' % recipe) + for f in ['pn-buildlist', 'task-depends.dot']: self.addCleanup(os.remove, f) self.assertTrue('Task dependencies saved to \'task-depends.dot\'' in result.output, msg = "No task dependency \"task-depends.dot\" file was generated for the given task target. bitbake output: %s" % result.output) - self.assertTrue('busybox' in ftools.read_file(os.path.join(self.builddir, 'task-depends.dot')), msg = "No \"busybox\" dependency found in task-depends.dot file.") + self.assertIn(recipe, ftools.read_file(os.path.join(self.builddir, 'task-depends.dot'))) - @OETestID(899) def test_image_manifest(self): bitbake('core-image-minimal') bb_vars = get_bb_vars(["DEPLOY_DIR_IMAGE", "IMAGE_LINK_NAME"], "core-image-minimal") @@ -138,7 +133,6 @@ class BitbakeTests(OESelftestTestCase): manifest = os.path.join(deploydir, imagename + ".manifest") self.assertTrue(os.path.islink(manifest), msg="No manifest file created for image. It should have been created in %s" % manifest) - @OETestID(168) def test_invalid_recipe_src_uri(self): data = 'SRC_URI = "file://invalid"' self.write_recipeinc('man-db', data) @@ -153,13 +147,11 @@ INHERIT_remove = \"report-error\" bitbake('-ccleanall man-db') self.delete_recipeinc('man-db') self.assertEqual(result.status, 1, msg="Command succeded when it should have failed. bitbake output: %s" % result.output) - self.assertTrue('Fetcher failure: Unable to find file file://invalid anywhere. The paths that were searched were:' in result.output, msg = "\"invalid\" file \ -doesn't exist, yet no error message encountered. bitbake output: %s" % result.output) + self.assertIn('Fetcher failure: Unable to find file file://invalid anywhere. The paths that were searched were:', result.output) line = self.getline(result, 'Fetcher failure for URL: \'file://invalid\'. Unable to fetch URL from any source.') self.assertTrue(line and line.startswith("ERROR:"), msg = "\"invalid\" file \ doesn't exist, yet fetcher didn't report any error. bitbake output: %s" % result.output) - @OETestID(171) def test_rename_downloaded_file(self): # TODO unique dldir instead of using cleanall # TODO: need to set sstatedir? @@ -177,54 +169,46 @@ SSTATE_DIR = \"${TOPDIR}/download-selftest\" self.assertTrue(os.path.isfile(os.path.join(dl_dir, 'test-aspell.tar.gz')), msg = "File rename failed. No corresponding test-aspell.tar.gz file found under %s" % dl_dir) self.assertTrue(os.path.isfile(os.path.join(dl_dir, 'test-aspell.tar.gz.done')), "File rename failed. No corresponding test-aspell.tar.gz.done file found under %s" % dl_dir) - @OETestID(1028) def test_environment(self): self.write_config("TEST_ENV=\"localconf\"") result = runCmd('bitbake -e | grep TEST_ENV=') - self.assertTrue('localconf' in result.output, msg = "bitbake didn't report any value for TEST_ENV variable. To test, run 'bitbake -e | grep TEST_ENV='") + self.assertIn('localconf', result.output) - @OETestID(1029) def test_dry_run(self): result = runCmd('bitbake -n m4-native') self.assertEqual(0, result.status, "bitbake dry run didn't run as expected. %s" % result.output) - @OETestID(1030) def test_just_parse(self): result = runCmd('bitbake -p') self.assertEqual(0, result.status, "errors encountered when parsing recipes. %s" % result.output) - @OETestID(1031) def test_version(self): result = runCmd('bitbake -s | grep wget') - find = re.search("wget *:([0-9a-zA-Z\.\-]+)", result.output) + find = re.search(r"wget *:([0-9a-zA-Z\.\-]+)", result.output) self.assertTrue(find, "No version returned for searched recipe. bitbake output: %s" % result.output) - @OETestID(1032) def test_prefile(self): preconf = os.path.join(self.builddir, 'conf/prefile.conf') self.track_for_cleanup(preconf) ftools.write_file(preconf ,"TEST_PREFILE=\"prefile\"") result = runCmd('bitbake -r conf/prefile.conf -e | grep TEST_PREFILE=') - self.assertTrue('prefile' in result.output, "Preconfigure file \"prefile.conf\"was not taken into consideration. ") + self.assertIn('prefile', result.output) self.write_config("TEST_PREFILE=\"localconf\"") result = runCmd('bitbake -r conf/prefile.conf -e | grep TEST_PREFILE=') - self.assertTrue('localconf' in result.output, "Preconfigure file \"prefile.conf\"was not taken into consideration.") + self.assertIn('localconf', result.output) - @OETestID(1033) def test_postfile(self): postconf = os.path.join(self.builddir, 'conf/postfile.conf') self.track_for_cleanup(postconf) ftools.write_file(postconf , "TEST_POSTFILE=\"postfile\"") self.write_config("TEST_POSTFILE=\"localconf\"") result = runCmd('bitbake -R conf/postfile.conf -e | grep TEST_POSTFILE=') - self.assertTrue('postfile' in result.output, "Postconfigure file \"postfile.conf\"was not taken into consideration.") + self.assertIn('postfile', result.output) - @OETestID(1034) def test_checkuri(self): result = runCmd('bitbake -c checkuri m4') self.assertEqual(0, result.status, msg = "\"checkuri\" task was not executed. bitbake output: %s" % result.output) - @OETestID(1035) def test_continue(self): self.write_config("""DL_DIR = \"${TOPDIR}/download-selftest\" SSTATE_DIR = \"${TOPDIR}/download-selftest\" @@ -239,7 +223,6 @@ INHERIT_remove = \"report-error\" continuepos = result.output.find('NOTE: recipe xcursor-transparent-theme-%s: task do_unpack: Started' % manver.group(1)) self.assertLess(errorpos,continuepos, msg = "bitbake didn't pass do_fail_task. bitbake output: %s" % result.output) - @OETestID(1119) def test_non_gplv3(self): self.write_config('INCOMPATIBLE_LICENSE = "GPLv3"') result = bitbake('selftest-ed', ignore_status=True) @@ -248,7 +231,6 @@ INHERIT_remove = \"report-error\" self.assertFalse(os.path.isfile(os.path.join(lic_dir, 'selftest-ed/generic_GPLv3'))) self.assertTrue(os.path.isfile(os.path.join(lic_dir, 'selftest-ed/generic_GPLv2'))) - @OETestID(1422) def test_setscene_only(self): """ Bitbake option to restore from sstate only within a build (i.e. execute no real tasks, only setscene)""" test_recipe = 'ed' @@ -263,7 +245,36 @@ INHERIT_remove = \"report-error\" self.assertIn('_setscene', task, 'A task different from _setscene ran: %s.\n' 'Executed tasks were: %s' % (task, str(tasks))) - @OETestID(1425) + 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/external/poky/meta/lib/oeqa/selftest/cases/binutils.py b/external/poky/meta/lib/oeqa/selftest/cases/binutils.py new file mode 100644 index 00000000..821f52f5 --- /dev/null +++ b/external/poky/meta/lib/oeqa/selftest/cases/binutils.py @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: MIT +import os +import sys +import re +import logging +from oeqa.core.decorator import OETestTag +from oeqa.core.case import OEPTestResultTestCase +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars + +def parse_values(content): + for i in content: + for v in ["PASS", "FAIL", "XPASS", "XFAIL", "UNRESOLVED", "UNSUPPORTED", "UNTESTED", "ERROR", "WARNING"]: + if i.startswith(v + ": "): + yield i[len(v) + 2:].strip(), v + break + +@OETestTag("toolchain-user", "toolchain-system") +class BinutilsCrossSelfTest(OESelftestTestCase, OEPTestResultTestCase): + def test_binutils(self): + self.run_binutils("binutils") + + def test_gas(self): + self.run_binutils("gas") + + def test_ld(self): + self.run_binutils("ld") + + def run_binutils(self, suite): + features = [] + features.append('CHECK_TARGETS = "{0}"'.format(suite)) + self.write_config("\n".join(features)) + + recipe = "binutils-cross-testsuite" + bb_vars = get_bb_vars(["B", "TARGET_SYS", "T"], recipe) + builddir, target_sys, tdir = bb_vars["B"], bb_vars["TARGET_SYS"], bb_vars["T"] + + bitbake("{0} -c check".format(recipe)) + + sumspath = os.path.join(builddir, suite, "{0}.sum".format(suite)) + if not os.path.exists(sumspath): + sumspath = os.path.join(builddir, suite, "testsuite", "{0}.sum".format(suite)) + logpath = os.path.splitext(sumspath)[0] + ".log" + + ptestsuite = "binutils-{}".format(suite) if suite != "binutils" else suite + self.ptest_section(ptestsuite, logfile = logpath) + with open(sumspath, "r") as f: + for test, result in parse_values(f): + self.ptest_result(ptestsuite, test, result) + diff --git a/external/poky/meta/lib/oeqa/selftest/cases/buildhistory.py b/external/poky/meta/lib/oeqa/selftest/cases/buildhistory.py index 06792d91..d865da62 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/buildhistory.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/buildhistory.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + import os import re import datetime diff --git a/external/poky/meta/lib/oeqa/selftest/cases/buildoptions.py b/external/poky/meta/lib/oeqa/selftest/cases/buildoptions.py index f234bac0..e91f0bd1 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/buildoptions.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/buildoptions.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + import os import re import glob as g @@ -7,11 +11,9 @@ from oeqa.selftest.case import OESelftestTestCase from oeqa.selftest.cases.buildhistory import BuildhistoryBase from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars import oeqa.utils.ftools as ftools -from oeqa.core.decorator.oeid import OETestID class ImageOptionsTests(OESelftestTestCase): - @OETestID(761) def test_incremental_image_generation(self): image_pkgtype = get_bb_var("IMAGE_PKGTYPE") if image_pkgtype != 'rpm': @@ -30,22 +32,20 @@ class ImageOptionsTests(OESelftestTestCase): incremental_removed = re.search(r"Erasing\s*:\s*packagegroup-core-ssh-openssh", log_data_removed) self.assertTrue(incremental_removed, msg = "Match failed in:\n%s" % log_data_removed) - @OETestID(286) def test_ccache_tool(self): bitbake("ccache-native") bb_vars = get_bb_vars(['SYSROOT_DESTDIR', 'bindir'], 'ccache-native') p = bb_vars['SYSROOT_DESTDIR'] + bb_vars['bindir'] + "/" + "ccache" self.assertTrue(os.path.isfile(p), msg = "No ccache found (%s)" % p) self.write_config('INHERIT += "ccache"') - self.add_command_to_tearDown('bitbake -c clean m4') - bitbake("m4 -c clean") - bitbake("m4 -f -c compile") - log_compile = os.path.join(get_bb_var("WORKDIR","m4"), "temp/log.do_compile") + self.add_command_to_tearDown('bitbake -c clean m4-native') + bitbake("m4-native -c clean") + bitbake("m4-native -f -c compile") + log_compile = os.path.join(get_bb_var("WORKDIR","m4-native"), "temp/log.do_compile") with open(log_compile, "r") as f: loglines = "".join(f.readlines()) - self.assertIn("ccache", loglines, msg="No match for ccache in m4 log.do_compile. For further details: %s" % log_compile) + self.assertIn("ccache", loglines, msg="No match for ccache in m4-native log.do_compile. For further details: %s" % log_compile) - @OETestID(1435) def test_read_only_image(self): distro_features = get_bb_var('DISTRO_FEATURES') if not ('x11' in distro_features and 'opengl' in distro_features): @@ -56,7 +56,6 @@ class ImageOptionsTests(OESelftestTestCase): class DiskMonTest(OESelftestTestCase): - @OETestID(277) def test_stoptask_behavior(self): self.write_config('BB_DISKMON_DIRS = "STOPTASKS,${TMPDIR},100000G,100K"') res = bitbake("delay -c delay", ignore_status = True) @@ -76,7 +75,6 @@ class SanityOptionsTest(OESelftestTestCase): if line in l: return l - @OETestID(927) def test_options_warnqa_errorqa_switch(self): self.write_config("INHERIT_remove = \"report-error\"") @@ -98,7 +96,6 @@ class SanityOptionsTest(OESelftestTestCase): line = self.getline(res, "QA Issue: xcursor-transparent-theme-dbg is listed in PACKAGES multiple times, this leads to packaging errors.") self.assertTrue(line and line.startswith("WARNING:"), msg=res.output) - @OETestID(1421) def test_layer_without_git_dir(self): """ Summary: Test that layer git revisions are displayed and do not fail without git repository @@ -140,20 +137,17 @@ class SanityOptionsTest(OESelftestTestCase): class BuildhistoryTests(BuildhistoryBase): - @OETestID(293) def test_buildhistory_basic(self): self.run_buildhistory_operation('xcursor-transparent-theme') self.assertTrue(os.path.isdir(get_bb_var('BUILDHISTORY_DIR')), "buildhistory dir was not created.") - @OETestID(294) def test_buildhistory_buildtime_pr_backwards(self): target = 'xcursor-transparent-theme' - error = "ERROR:.*QA Issue: Package version for package %s went backwards which would break package feeds from (.*-r1.* to .*-r0.*)" % target + error = "ERROR:.*QA Issue: Package version for package %s went backwards which would break package feeds \(from .*-r1.* to .*-r0.*\)" % target self.run_buildhistory_operation(target, target_config="PR = \"r1\"", change_bh_location=True) self.run_buildhistory_operation(target, target_config="PR = \"r0\"", change_bh_location=False, expect_error=True, error_regex=error) class ArchiverTest(OESelftestTestCase): - @OETestID(926) def test_arch_work_dir_and_export_source(self): """ Test for archiving the work directory and exporting the source files. @@ -168,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 @@ -187,6 +178,8 @@ class SourceMirroring(OESelftestTestCase): BB_ALLOWED_NETWORKS = "downloads.yoctoproject.org" MIRRORS = "" DL_DIR = "${TMPDIR}/test_downloads" +STAMPS_DIR = "${TMPDIR}/test_stamps" +SSTATE_DIR = "${TMPDIR}/test_sstate-cache" PREMIRRORS = "\\ bzr://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\ cvs://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\ diff --git a/external/poky/meta/lib/oeqa/selftest/cases/containerimage.py b/external/poky/meta/lib/oeqa/selftest/cases/containerimage.py index 8deaae75..c0998e31 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/containerimage.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/containerimage.py @@ -1,8 +1,11 @@ +# +# SPDX-License-Identifier: MIT +# + import os from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import bitbake, get_bb_vars, runCmd -from oeqa.core.decorator.oeid import OETestID # This test builds an image with using the "container" IMAGE_FSTYPE, and # ensures that then files in the image are only the ones expected. @@ -21,7 +24,6 @@ class ContainerImageTests(OESelftestTestCase): # Verify that when specifying a IMAGE_TYPEDEP_ of the form "foo.bar" that # the conversion type bar gets added as a dep as well - @OETestID(1619) def test_expected_files(self): def get_each_path_part(path): diff --git a/external/poky/meta/lib/oeqa/selftest/cases/devtool.py b/external/poky/meta/lib/oeqa/selftest/cases/devtool.py index 9eb9badf..5003f08c 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/devtool.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/devtool.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + import os import re import shutil @@ -9,7 +13,6 @@ import oeqa.utils.ftools as ftools from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import runCmd, bitbake, get_bb_var, create_temp_layer from oeqa.utils.commands import get_bb_vars, runqemu, get_test_layer -from oeqa.core.decorator.oeid import OETestID oldmetapath = None @@ -134,6 +137,7 @@ class DevtoolBase(OESelftestTestCase): with open(recipefile, 'r') as f: invar = None invalue = None + inherits = set() for line in f: var = None if invar: @@ -155,7 +159,7 @@ class DevtoolBase(OESelftestTestCase): invar = var continue elif line.startswith('inherit '): - inherits = line.split()[1:] + inherits.update(line.split()[1:]) if var and var in checkvars: needvalue = checkvars.pop(var) @@ -233,11 +237,13 @@ class DevtoolBase(OESelftestTestCase): class DevtoolTests(DevtoolBase): - @OETestID(1158) def test_create_workspace(self): # 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) @@ -256,7 +262,6 @@ class DevtoolTests(DevtoolBase): class DevtoolAddTests(DevtoolBase): - @OETestID(1159) def test_devtool_add(self): # Fetch source tempdir = tempfile.mkdtemp(prefix='devtoolqa') @@ -298,7 +303,6 @@ class DevtoolAddTests(DevtoolBase): bindir = bindir[1:] self.assertTrue(os.path.isfile(os.path.join(installdir, bindir, 'pv')), 'pv binary not found in D') - @OETestID(1423) def test_devtool_add_git_local(self): # We need dbus built so that DEPENDS recognition works bitbake('dbus') @@ -340,7 +344,6 @@ class DevtoolAddTests(DevtoolBase): checkvars['DEPENDS'] = set(['dbus']) self._test_recipe_contents(recipefile, checkvars, []) - @OETestID(1162) def test_devtool_add_library(self): # Fetch source tempdir = tempfile.mkdtemp(prefix='devtoolqa') @@ -389,13 +392,12 @@ class DevtoolAddTests(DevtoolBase): self.assertFalse(matches, 'Stamp files exist for recipe libftdi that should have been cleaned') self.assertFalse(os.path.isfile(os.path.join(staging_libdir, 'libftdi1.so.2.1.0')), 'libftdi binary still found in STAGING_LIBDIR after cleaning') - @OETestID(1160) def test_devtool_add_fetch(self): # Fetch source tempdir = tempfile.mkdtemp(prefix='devtoolqa') self.track_for_cleanup(tempdir) testver = '0.23' - url = 'https://pypi.python.org/packages/source/M/MarkupSafe/MarkupSafe-%s.tar.gz' % testver + url = 'https://files.pythonhosted.org/packages/c0/41/bae1254e0396c0cc8cf1751cb7d9afc90a602353695af5952530482c963f/MarkupSafe-%s.tar.gz' % testver testrecipe = 'python-markupsafe' srcdir = os.path.join(tempdir, testrecipe) # Test devtool add @@ -435,7 +437,6 @@ class DevtoolAddTests(DevtoolBase): checkvars['SRC_URI'] = url self._test_recipe_contents(recipefile, checkvars, []) - @OETestID(1161) def test_devtool_add_fetch_git(self): tempdir = tempfile.mkdtemp(prefix='devtoolqa') self.track_for_cleanup(tempdir) @@ -483,7 +484,6 @@ class DevtoolAddTests(DevtoolBase): checkvars['SRCREV'] = checkrev self._test_recipe_contents(recipefile, checkvars, []) - @OETestID(1391) def test_devtool_add_fetch_simple(self): # Fetch source from a remote URL, auto-detecting name tempdir = tempfile.mkdtemp(prefix='devtoolqa') @@ -511,17 +511,36 @@ class DevtoolAddTests(DevtoolBase): checkvars['SRC_URI'] = url.replace(testver, '${PV}') self._test_recipe_contents(recipefile, checkvars, []) + def test_devtool_add_npm(self): + pn = 'savoirfairelinux-node-server-example' + pv = '1.0.0' + url = 'npm://registry.npmjs.org;package=@savoirfairelinux/node-server-example;version=' + pv + # Test devtool add + self.track_for_cleanup(self.workspacedir) + self.add_command_to_tearDown('bitbake -c cleansstate %s' % pn) + self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') + result = runCmd('devtool add \'%s\'' % url) + self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created') + self.assertExists(os.path.join(self.workspacedir, 'recipes', pn, '%s_%s.bb' % (pn, pv)), 'Recipe not created') + self.assertExists(os.path.join(self.workspacedir, 'recipes', pn, pn, 'npm-shrinkwrap.json'), 'Shrinkwrap not created') + # Test devtool status + result = runCmd('devtool status') + self.assertIn(pn, result.output) + # Clean up anything in the workdir/sysroot/sstate cache (have to do this *after* devtool add since the recipe only exists then) + bitbake('%s -c cleansstate' % pn) + # Test devtool build + result = runCmd('devtool build %s' % pn) + class DevtoolModifyTests(DevtoolBase): - @OETestID(1164) def test_devtool_modify(self): import oe.path tempdir = tempfile.mkdtemp(prefix='devtoolqa') self.track_for_cleanup(tempdir) self.track_for_cleanup(self.workspacedir) - self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') self.add_command_to_tearDown('bitbake -c clean mdadm') + self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') result = runCmd('devtool modify mdadm -x %s' % tempdir) self.assertExists(os.path.join(tempdir, 'Makefile'), 'Extracted source could not be found') self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created') @@ -571,7 +590,6 @@ class DevtoolModifyTests(DevtoolBase): result = runCmd('devtool status') self.assertNotIn('mdadm', result.output) - @OETestID(1620) def test_devtool_buildclean(self): def assertFile(path, *paths): f = os.path.join(path, *paths) @@ -590,8 +608,8 @@ class DevtoolModifyTests(DevtoolBase): self.track_for_cleanup(tempdir_m4) self.track_for_cleanup(builddir_m4) self.track_for_cleanup(self.workspacedir) - self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') self.add_command_to_tearDown('bitbake -c clean mdadm m4') + self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') self.write_recipeinc('m4', 'EXTERNALSRC_BUILD = "%s"\ndo_clean() {\n\t:\n}\n' % builddir_m4) try: runCmd('devtool modify mdadm -x %s' % tempdir_mdadm) @@ -607,6 +625,7 @@ class DevtoolModifyTests(DevtoolBase): bitbake('mdadm m4 -c buildclean') assertNoFile(tempdir_mdadm, 'mdadm') assertNoFile(builddir_m4, 'src/m4') + runCmd('echo "#Trigger rebuild" >> %s/Makefile' % tempdir_mdadm) bitbake('mdadm m4 -c compile') assertFile(tempdir_mdadm, 'mdadm') assertFile(builddir_m4, 'src/m4') @@ -618,7 +637,6 @@ class DevtoolModifyTests(DevtoolBase): finally: self.delete_recipeinc('m4') - @OETestID(1166) def test_devtool_modify_invalid(self): # Try modifying some recipes tempdir = tempfile.mkdtemp(prefix='devtoolqa') @@ -647,7 +665,6 @@ class DevtoolModifyTests(DevtoolBase): self.assertNotEqual(result.status, 0, 'devtool modify on %s should have failed. devtool output: %s' % (testrecipe, result.output)) self.assertIn('ERROR: ', result.output, 'devtool modify on %s should have given an ERROR' % testrecipe) - @OETestID(1365) def test_devtool_modify_native(self): # Check preconditions self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory') @@ -677,7 +694,6 @@ class DevtoolModifyTests(DevtoolBase): self.assertTrue(inheritnative, 'None of these recipes do "inherit native" - need to adjust testrecipes list: %s' % ', '.join(testrecipes)) - @OETestID(1165) def test_devtool_modify_git(self): # Check preconditions testrecipe = 'psplash' @@ -689,8 +705,8 @@ class DevtoolModifyTests(DevtoolBase): tempdir = tempfile.mkdtemp(prefix='devtoolqa') self.track_for_cleanup(tempdir) self.track_for_cleanup(self.workspacedir) - self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') 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, 'Makefile.am'), '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) @@ -705,7 +721,6 @@ class DevtoolModifyTests(DevtoolBase): # Try building bitbake(testrecipe) - @OETestID(1167) def test_devtool_modify_localfiles(self): # Check preconditions testrecipe = 'lighttpd' @@ -722,8 +737,8 @@ class DevtoolModifyTests(DevtoolBase): tempdir = tempfile.mkdtemp(prefix='devtoolqa') self.track_for_cleanup(tempdir) self.track_for_cleanup(self.workspacedir) - self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') 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, 'configure.ac'), 'Extracted source could not be found') self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created') @@ -736,7 +751,6 @@ class DevtoolModifyTests(DevtoolBase): # Try building bitbake(testrecipe) - @OETestID(1378) def test_devtool_modify_virtual(self): # Try modifying a virtual recipe virtrecipe = 'virtual/make' @@ -760,7 +774,6 @@ class DevtoolModifyTests(DevtoolBase): class DevtoolUpdateTests(DevtoolBase): - @OETestID(1169) def test_devtool_update_recipe(self): # Check preconditions testrecipe = 'minicom' @@ -793,7 +806,6 @@ class DevtoolUpdateTests(DevtoolBase): ('??', '.*/0002-Add-a-new-file.patch$')] self._check_repo_status(os.path.dirname(recipefile), expected_status) - @OETestID(1172) def test_devtool_update_recipe_git(self): # Check preconditions testrecipe = 'mtd-utils' @@ -863,7 +875,6 @@ class DevtoolUpdateTests(DevtoolBase): ('??', '%s/0002-Add-a-new-file.patch' % relpatchpath)] self._check_repo_status(os.path.dirname(recipefile), expected_status) - @OETestID(1170) def test_devtool_update_recipe_append(self): # Check preconditions testrecipe = 'mdadm' @@ -932,7 +943,6 @@ class DevtoolUpdateTests(DevtoolBase): self.assertEqual(expectedlines, f.readlines()) # Deleting isn't expected to work under these circumstances - @OETestID(1171) def test_devtool_update_recipe_append_git(self): # Check preconditions testrecipe = 'mtd-utils' @@ -1023,7 +1033,6 @@ class DevtoolUpdateTests(DevtoolBase): self.assertEqual(expectedlines, set(f.readlines())) # Deleting isn't expected to work under these circumstances - @OETestID(1370) def test_devtool_update_recipe_local_files(self): """Check that local source files are copied over instead of patched""" testrecipe = 'makedevs' @@ -1055,7 +1064,6 @@ class DevtoolUpdateTests(DevtoolBase): ('??', '.*/makedevs/0001-Add-new-file.patch$')] self._check_repo_status(os.path.dirname(recipefile), expected_status) - @OETestID(1371) def test_devtool_update_recipe_local_files_2(self): """Check local source files support when oe-local-files is in Git""" testrecipe = 'devtool-test-local' @@ -1100,7 +1108,6 @@ class DevtoolUpdateTests(DevtoolBase): ('??', '.*/0001-Add-new-file.patch$')] self._check_repo_status(os.path.dirname(recipefile), expected_status) - @OETestID(1627) def test_devtool_update_recipe_local_files_3(self): # First, modify the recipe testrecipe = 'devtool-test-localonly' @@ -1120,7 +1127,6 @@ class DevtoolUpdateTests(DevtoolBase): expected_status = [(' M', '.*/%s/file2$' % testrecipe)] self._check_repo_status(os.path.dirname(recipefile), expected_status) - @OETestID(1629) def test_devtool_update_recipe_local_patch_gz(self): # First, modify the recipe testrecipe = 'devtool-test-patch-gz' @@ -1148,7 +1154,6 @@ class DevtoolUpdateTests(DevtoolBase): if 'gzip compressed data' not in result.output: self.fail('New patch file is not gzipped - file reports:\n%s' % result.output) - @OETestID(1628) def test_devtool_update_recipe_local_files_subdir(self): # Try devtool update-recipe on a recipe that has a file with subdir= set in # SRC_URI such that it overwrites a file that was in an archive that @@ -1177,7 +1182,6 @@ class DevtoolUpdateTests(DevtoolBase): class DevtoolExtractTests(DevtoolBase): - @OETestID(1163) def test_devtool_extract(self): tempdir = tempfile.mkdtemp(prefix='devtoolqa') # Try devtool extract @@ -1188,7 +1192,6 @@ class DevtoolExtractTests(DevtoolBase): self.assertExists(os.path.join(tempdir, 'Makefile.am'), 'Extracted source could not be found') self._check_src_repo(tempdir) - @OETestID(1379) def test_devtool_extract_virtual(self): tempdir = tempfile.mkdtemp(prefix='devtoolqa') # Try devtool extract @@ -1199,7 +1202,6 @@ class DevtoolExtractTests(DevtoolBase): self.assertExists(os.path.join(tempdir, 'Makefile.am'), 'Extracted source could not be found') self._check_src_repo(tempdir) - @OETestID(1168) def test_devtool_reset_all(self): tempdir = tempfile.mkdtemp(prefix='devtoolqa') self.track_for_cleanup(tempdir) @@ -1226,7 +1228,6 @@ class DevtoolExtractTests(DevtoolBase): matches2 = glob.glob(stampprefix2 + '*') self.assertFalse(matches2, 'Stamp files exist for recipe %s that should have been cleaned' % testrecipe2) - @OETestID(1272) def test_devtool_deploy_target(self): # NOTE: Whilst this test would seemingly be better placed as a runtime test, # unfortunately the runtime tests run under bitbake and you can't run @@ -1267,8 +1268,8 @@ class DevtoolExtractTests(DevtoolBase): tempdir = tempfile.mkdtemp(prefix='devtoolqa') self.track_for_cleanup(tempdir) self.track_for_cleanup(self.workspacedir) - self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') 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)) # Test that deploy-target at this point fails (properly) result = runCmd('devtool deploy-target -n %s root@localhost' % testrecipe, ignore_status=True) @@ -1291,7 +1292,7 @@ class DevtoolExtractTests(DevtoolBase): installdir = bb_vars['D'] fakerootenv = bb_vars['FAKEROOTENV'] fakerootcmd = bb_vars['FAKEROOTCMD'] - result = runCmd('%s %s find . -type f -exec ls -l {} \;' % (fakerootenv, fakerootcmd), cwd=installdir) + result = runCmd('%s %s find . -type f -exec ls -l {} \\;' % (fakerootenv, fakerootcmd), cwd=installdir) filelist1 = self._process_ls_output(result.output) # Now look on the target @@ -1312,15 +1313,14 @@ class DevtoolExtractTests(DevtoolBase): result = runCmd('ssh %s root@%s %s' % (sshargs, qemu.ip, testcommand), ignore_status=True) self.assertNotEqual(result, 0, 'undeploy-target did not remove command as it should have') - @OETestID(1366) def test_devtool_build_image(self): """Test devtool build-image plugin""" # Check preconditions self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory') image = 'core-image-minimal' self.track_for_cleanup(self.workspacedir) - self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') self.add_command_to_tearDown('bitbake -c clean %s' % image) + self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') bitbake('%s -c clean' % image) # Add target and native recipes to workspace recipes = ['mdadm', 'parted-native'] @@ -1348,7 +1348,6 @@ class DevtoolExtractTests(DevtoolBase): class DevtoolUpgradeTests(DevtoolBase): - @OETestID(1367) def test_devtool_upgrade(self): # Check preconditions self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory') @@ -1393,7 +1392,6 @@ class DevtoolUpgradeTests(DevtoolBase): self.assertNotIn(recipe, result.output) self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after resetting') - @OETestID(1433) def test_devtool_upgrade_git(self): # Check preconditions self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory') @@ -1430,7 +1428,6 @@ class DevtoolUpgradeTests(DevtoolBase): self.assertNotIn(recipe, result.output) self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after resetting') - @OETestID(1352) def test_devtool_layer_plugins(self): """Test that devtool can use plugins from other layers. @@ -1450,13 +1447,16 @@ class DevtoolUpgradeTests(DevtoolBase): dstdir = os.path.join(dstdir, p) if not os.path.exists(dstdir): os.makedirs(dstdir) - self.track_for_cleanup(dstdir) + if p == "lib": + # Can race with other tests + self.add_command_to_tearDown('rmdir --ignore-fail-on-non-empty %s' % dstdir) + else: + self.track_for_cleanup(dstdir) dstfile = os.path.join(dstdir, os.path.basename(srcfile)) if srcfile != dstfile: shutil.copy(srcfile, dstfile) self.track_for_cleanup(dstfile) - @OETestID(1625) def test_devtool_load_plugin(self): """Test that devtool loads only the first found plugin in BBPATH.""" @@ -1521,12 +1521,13 @@ class DevtoolUpgradeTests(DevtoolBase): recipedir = os.path.dirname(oldrecipefile) olddir = os.path.join(recipedir, recipe + '-' + oldversion) patchfn = '0001-Add-a-note-line-to-the-quick-reference.patch' + backportedpatchfn = 'backported.patch' self.assertExists(os.path.join(olddir, patchfn), 'Original patch file does not exist') - return recipe, oldrecipefile, recipedir, olddir, newversion, patchfn + self.assertExists(os.path.join(olddir, backportedpatchfn), 'Backported patch file does not exist') + return recipe, oldrecipefile, recipedir, olddir, newversion, patchfn, backportedpatchfn - @OETestID(1623) def test_devtool_finish_upgrade_origlayer(self): - recipe, oldrecipefile, recipedir, olddir, newversion, patchfn = self._setup_test_devtool_finish_upgrade() + recipe, oldrecipefile, recipedir, olddir, newversion, patchfn, backportedpatchfn = self._setup_test_devtool_finish_upgrade() # Ensure the recipe is where we think it should be (so that cleanup doesn't trash things) self.assertIn('/meta-selftest/', recipedir) # Try finish to the original layer @@ -1537,15 +1538,23 @@ class DevtoolUpgradeTests(DevtoolBase): self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish') self.assertNotExists(oldrecipefile, 'Old recipe file should have been deleted but wasn\'t') self.assertNotExists(os.path.join(olddir, patchfn), 'Old patch file should have been deleted but wasn\'t') + self.assertNotExists(os.path.join(olddir, backportedpatchfn), 'Old backported patch file should have been deleted but wasn\'t') newrecipefile = os.path.join(recipedir, '%s_%s.bb' % (recipe, newversion)) newdir = os.path.join(recipedir, recipe + '-' + newversion) self.assertExists(newrecipefile, 'New recipe file should have been copied into existing layer but wasn\'t') self.assertExists(os.path.join(newdir, patchfn), 'Patch file should have been copied into new directory but wasn\'t') + self.assertNotExists(os.path.join(newdir, backportedpatchfn), 'Backported patch file should not have been copied into new directory but was') self.assertExists(os.path.join(newdir, '0002-Add-a-comment-to-the-code.patch'), 'New patch file should have been created but wasn\'t') + with open(newrecipefile, 'r') as f: + newcontent = f.read() + self.assertNotIn(backportedpatchfn, newcontent, "Backported patch should have been removed from the recipe but wasn't") + self.assertIn(patchfn, newcontent, "Old patch should have not been removed from the recipe but was") + self.assertIn("0002-Add-a-comment-to-the-code.patch", newcontent, "New patch should have been added to the recipe but wasn't") + self.assertIn("http://www.ivarch.com/programs/sources/pv-${PV}.tar.gz", newcontent, "New recipe no longer has upstream source in SRC_URI") + - @OETestID(1624) def test_devtool_finish_upgrade_otherlayer(self): - recipe, oldrecipefile, recipedir, olddir, newversion, patchfn = self._setup_test_devtool_finish_upgrade() + recipe, oldrecipefile, recipedir, olddir, newversion, patchfn, backportedpatchfn = self._setup_test_devtool_finish_upgrade() # Ensure the recipe is where we think it should be (so that cleanup doesn't trash things) self.assertIn('/meta-selftest/', recipedir) # Try finish to a different layer - should create a bbappend @@ -1561,10 +1570,18 @@ class DevtoolUpgradeTests(DevtoolBase): self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after finish') self.assertExists(oldrecipefile, 'Old recipe file should not have been deleted') self.assertExists(os.path.join(olddir, patchfn), 'Old patch file should not have been deleted') + self.assertExists(os.path.join(olddir, backportedpatchfn), 'Old backported patch file should not have been deleted') newdir = os.path.join(newrecipedir, recipe + '-' + newversion) self.assertExists(newrecipefile, 'New recipe file should have been copied into existing layer but wasn\'t') self.assertExists(os.path.join(newdir, patchfn), 'Patch file should have been copied into new directory but wasn\'t') + self.assertNotExists(os.path.join(newdir, backportedpatchfn), 'Backported patch file should not have been copied into new directory but was') self.assertExists(os.path.join(newdir, '0002-Add-a-comment-to-the-code.patch'), 'New patch file should have been created but wasn\'t') + with open(newrecipefile, 'r') as f: + newcontent = f.read() + self.assertNotIn(backportedpatchfn, newcontent, "Backported patch should have been removed from the recipe but wasn't") + self.assertIn(patchfn, newcontent, "Old patch should have not been removed from the recipe but was") + self.assertIn("0002-Add-a-comment-to-the-code.patch", newcontent, "New patch should have been added to the recipe but wasn't") + self.assertIn("http://www.ivarch.com/programs/sources/pv-${PV}.tar.gz", newcontent, "New recipe no longer has upstream source in SRC_URI") def _setup_test_devtool_finish_modify(self): # Check preconditions @@ -1599,7 +1616,6 @@ class DevtoolUpgradeTests(DevtoolBase): self.fail('Unable to find recipe files directory for %s' % recipe) return recipe, oldrecipefile, recipedir, filesdir - @OETestID(1621) def test_devtool_finish_modify_origlayer(self): recipe, oldrecipefile, recipedir, filesdir = self._setup_test_devtool_finish_modify() # Ensure the recipe is where we think it should be (so that cleanup doesn't trash things) @@ -1614,7 +1630,6 @@ class DevtoolUpgradeTests(DevtoolBase): ('??', '.*/.*-Add-a-comment-to-the-code.patch$')] self._check_repo_status(recipedir, expected_status) - @OETestID(1622) def test_devtool_finish_modify_otherlayer(self): recipe, oldrecipefile, recipedir, filesdir = self._setup_test_devtool_finish_modify() # Ensure the recipe is where we think it should be (so that cleanup doesn't trash things) @@ -1647,7 +1662,6 @@ class DevtoolUpgradeTests(DevtoolBase): if files: self.fail('Unexpected file(s) copied next to bbappend: %s' % ', '.join(files)) - @OETestID(1626) def test_devtool_rename(self): # Check preconditions self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory') @@ -1708,7 +1722,6 @@ class DevtoolUpgradeTests(DevtoolBase): checkvars['SRC_URI'] = url self._test_recipe_contents(newrecipefile, checkvars, []) - @OETestID(1577) def test_devtool_virtual_kernel_modify(self): """ Summary: The purpose of this test case is to verify that @@ -1732,15 +1745,15 @@ class DevtoolUpgradeTests(DevtoolBase): when building the kernel. """ kernel_provider = get_bb_var('PREFERRED_PROVIDER_virtual/kernel') - # Clean up the enviroment + # Clean up the environment bitbake('%s -c clean' % kernel_provider) tempdir = tempfile.mkdtemp(prefix='devtoolqa') tempdir_cfg = tempfile.mkdtemp(prefix='config_qa') self.track_for_cleanup(tempdir) self.track_for_cleanup(tempdir_cfg) self.track_for_cleanup(self.workspacedir) - self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') self.add_command_to_tearDown('bitbake -c clean %s' % kernel_provider) + self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') #Step 1 #Here is just generated the config file instead of all the kernel to optimize the #time of executing this test case. diff --git a/external/poky/meta/lib/oeqa/selftest/cases/distrodata.py b/external/poky/meta/lib/oeqa/selftest/cases/distrodata.py index e7b5e349..e1cfc3b6 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/distrodata.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/distrodata.py @@ -1,21 +1,16 @@ +# +# SPDX-License-Identifier: MIT +# + from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars from oeqa.utils.decorators import testcase from oeqa.utils.ftools import write_file -from oeqa.core.decorator.oeid import OETestID - -class Distrodata(OESelftestTestCase): - @classmethod - def setUpClass(cls): - super(Distrodata, cls).setUpClass() - feature = 'INHERIT += "distrodata"\n' - feature += 'LICENSE_FLAGS_WHITELIST += " commercial"\n' +import oe.recipeutils - cls.write_config(cls, feature) - bitbake('-c checkpkg world') +class Distrodata(OESelftestTestCase): - @OETestID(1902) def test_checkpkg(self): """ Summary: Test that upstream version checks do not regress @@ -23,9 +18,13 @@ class Distrodata(OESelftestTestCase): Product: oe-core Author: Alexander Kanavin """ - checkpkg_result = open(os.path.join(get_bb_var("LOG_DIR"), "checkpkg.csv")).readlines()[1:] - regressed_failures = [pkg_data[0] for pkg_data in [pkg_line.split('\t') for pkg_line in checkpkg_result] if pkg_data[11] == 'UNKNOWN_BROKEN'] - regressed_successes = [pkg_data[0] for pkg_data in [pkg_line.split('\t') for pkg_line in checkpkg_result] if pkg_data[11] == 'KNOWN_BROKEN'] + feature = 'LICENSE_FLAGS_WHITELIST += " commercial"\n' + self.write_config(feature) + + pkgs = oe.recipeutils.get_recipe_upgrade_status() + + regressed_failures = [pkg[0] for pkg in pkgs if pkg[1] == 'UNKNOWN_BROKEN'] + regressed_successes = [pkg[0] for pkg in pkgs if pkg[1] == 'KNOWN_BROKEN'] msg = "" if len(regressed_failures) > 0: msg = msg + """ @@ -43,8 +42,9 @@ but their recipes claim otherwise by setting UPSTREAM_VERSION_UNKNOWN. Please re def test_maintainers(self): """ - Summary: Test that oe-core recipes have a maintainer + Summary: Test that oe-core recipes have a maintainer and entries in maintainers list have a recipe Expected: All oe-core recipes (except a few special static/testing ones) should have a maintainer listed in maintainers.inc file. + Expected: All entries in maintainers list should have a recipe file that matches them Product: oe-core Author: Alexander Kanavin """ @@ -55,45 +55,64 @@ but their recipes claim otherwise by setting UPSTREAM_VERSION_UNKNOWN. Please re return True return False - def is_in_oe_core(recipe, recipes): - self.assertTrue(recipe in recipes.keys(), "Recipe %s was not in 'bitbake-layers show-recipes' output" %(recipe)) - self.assertTrue(len(recipes[recipe]) > 0, "'bitbake-layers show-recipes' could not determine what layer(s) a recipe %s is in" %(recipe)) - try: - recipes[recipe].index('meta') - return True - except ValueError: - return False - - def get_recipe_layers(): - import re - - recipes = {} - recipe_regex = re.compile('^(?P.*):$') - layer_regex = re.compile('^ (?P\S*) +') - output = runCmd('bitbake-layers show-recipes').output - for line in output.split('\n'): - recipe_name_obj = recipe_regex.search(line) - if recipe_name_obj: - recipe_name = recipe_name_obj.group('name') - recipes[recipe_name] = [] - recipe_layer_obj = layer_regex.search(line) - if recipe_layer_obj: - layer_name = recipe_layer_obj.group('name') - recipes[recipe_name].append(layer_name) - return recipes - - checkpkg_result = open(os.path.join(get_bb_var("LOG_DIR"), "checkpkg.csv")).readlines()[1:] - recipes_layers = get_recipe_layers() - no_maintainer_list = [pkg_data[0] for pkg_data in [pkg_line.split('\t') for pkg_line in checkpkg_result] \ - if pkg_data[14] == '' and is_in_oe_core(pkg_data[0], recipes_layers) and not is_exception(pkg_data[0])] - msg = """ -The following packages do not have a maintainer assigned to them. Please add an entry to meta/conf/distro/include/maintainers.inc file. -""" + "\n".join(no_maintainer_list) - self.assertTrue(len(no_maintainer_list) == 0, msg) - - with_maintainer_list = [pkg_data[0] for pkg_data in [pkg_line.split('\t') for pkg_line in checkpkg_result] \ - if pkg_data[14] != '' and is_in_oe_core(pkg_data[0], recipes_layers) and not is_exception(pkg_data[0])] - msg = """ -The list of oe-core packages with maintainers is empty. This may indicate that the test has regressed and needs fixing. -""" - self.assertTrue(len(with_maintainer_list) > 0, msg) + def is_maintainer_exception(entry): + exceptions = ["musl", "newlib", "linux-yocto", "linux-dummy", "mesa-gl", "libgfortran", + "cve-update-db-native"] + for i in exceptions: + if i in entry: + return True + return False + + feature = 'require conf/distro/include/maintainers.inc\nLICENSE_FLAGS_WHITELIST += " commercial"\nPARSE_ALL_RECIPES = "1"\n' + self.write_config(feature) + + with bb.tinfoil.Tinfoil() as tinfoil: + tinfoil.prepare(config_only=False) + + with_maintainer_list = [] + no_maintainer_list = [] + + missing_recipes = [] + recipes = [] + prefix = "RECIPE_MAINTAINER_pn-" + + # We could have used all_recipes() here, but this method will find + # every recipe if we ever move to setting RECIPE_MAINTAINER in recipe files + # instead of maintainers.inc + for fn in tinfoil.all_recipe_files(variants=False): + if not '/meta/recipes-' in fn: + # We are only interested in OE-Core + continue + rd = tinfoil.parse_recipe_file(fn, appends=False) + pn = rd.getVar('PN') + recipes.append(pn) + if is_exception(pn): + continue + if rd.getVar('RECIPE_MAINTAINER'): + with_maintainer_list.append((pn, fn)) + else: + no_maintainer_list.append((pn, fn)) + + maintainers = tinfoil.config_data.keys() + for key in maintainers: + if key.startswith(prefix): + recipe = tinfoil.config_data.expand(key[len(prefix):]) + if is_maintainer_exception(recipe): + continue + if recipe not in recipes: + missing_recipes.append(recipe) + + if no_maintainer_list: + self.fail(""" +The following recipes do not have a maintainer assigned to them. Please add an entry to meta/conf/distro/include/maintainers.inc file. +""" + "\n".join(['%s (%s)' % i for i in no_maintainer_list])) + + if not with_maintainer_list: + self.fail(""" +The list of oe-core recipes with maintainers is empty. This may indicate that the test has regressed and needs fixing. +""") + + if missing_recipes: + self.fail(""" +Unable to find recipes for the following entries in maintainers.inc: +""" + "\n".join(['%s' % i for i in missing_recipes])) diff --git a/external/poky/meta/lib/oeqa/selftest/cases/eSDK.py b/external/poky/meta/lib/oeqa/selftest/cases/eSDK.py index 8eb6ec66..862849af 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/eSDK.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/eSDK.py @@ -1,9 +1,12 @@ +# +# SPDX-License-Identifier: MIT +# + import tempfile import shutil import os import glob import time -from oeqa.core.decorator.oeid import OETestID from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars @@ -104,14 +107,12 @@ SSTATE_MIRRORS = "file://.* file://%s/PATH" cls.tmpdirobj.cleanup() super().tearDownClass() - @OETestID(1602) def test_install_libraries_headers(self): pn_sstate = 'bc' bitbake(pn_sstate) cmd = "devtool sdk-install %s " % pn_sstate oeSDKExtSelfTest.run_esdk_cmd(self.env_eSDK, self.tmpdir_eSDKQA, cmd) - @OETestID(1603) def test_image_generation_binary_feeds(self): image = 'core-image-minimal' cmd = "devtool build-image %s" % image diff --git a/external/poky/meta/lib/oeqa/selftest/cases/efibootpartition.py b/external/poky/meta/lib/oeqa/selftest/cases/efibootpartition.py index c6f39d5b..a61cf9bc 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/efibootpartition.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/efibootpartition.py @@ -2,6 +2,8 @@ # # Copyright (c) 2017 Wind River Systems, Inc. # +# SPDX-License-Identifier: MIT +# import re diff --git a/external/poky/meta/lib/oeqa/selftest/cases/fetch.py b/external/poky/meta/lib/oeqa/selftest/cases/fetch.py index 4acc8cdc..76cbadf2 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/fetch.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/fetch.py @@ -1,10 +1,12 @@ +# +# SPDX-License-Identifier: MIT +# + import oe.path from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import bitbake -from oeqa.core.decorator.oeid import OETestID class Fetch(OESelftestTestCase): - @OETestID(1058) def test_git_mirrors(self): """ Verify that the git fetcher will fall back to the HTTP mirrors. The diff --git a/external/poky/meta/lib/oeqa/selftest/cases/gcc.py b/external/poky/meta/lib/oeqa/selftest/cases/gcc.py new file mode 100644 index 00000000..3efe1522 --- /dev/null +++ b/external/poky/meta/lib/oeqa/selftest/cases/gcc.py @@ -0,0 +1,152 @@ +# SPDX-License-Identifier: MIT +import os +from oeqa.core.decorator import OETestTag +from oeqa.core.case import OEPTestResultTestCase +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runqemu, Command + +def parse_values(content): + for i in content: + for v in ["PASS", "FAIL", "XPASS", "XFAIL", "UNRESOLVED", "UNSUPPORTED", "UNTESTED", "ERROR", "WARNING"]: + if i.startswith(v + ": "): + yield i[len(v) + 2:].strip(), v + break + +class GccSelfTestBase(OESelftestTestCase, OEPTestResultTestCase): + def check_skip(self, suite): + targets = get_bb_var("RUNTIMETARGET", "gcc-runtime").split() + if suite not in targets: + self.skipTest("Target does not use {0}".format(suite)) + + def run_check(self, *suites, ssh = None): + targets = set() + for s in suites: + if s == "gcc": + targets.add("check-gcc-c") + elif s == "g++": + targets.add("check-gcc-c++") + else: + targets.add("check-target-{}".format(s)) + + # configure ssh target + features = [] + features.append('MAKE_CHECK_TARGETS = "{0}"'.format(" ".join(targets))) + if ssh is not None: + features.append('TOOLCHAIN_TEST_TARGET = "ssh"') + features.append('TOOLCHAIN_TEST_HOST = "{0}"'.format(ssh)) + features.append('TOOLCHAIN_TEST_HOST_USER = "root"') + features.append('TOOLCHAIN_TEST_HOST_PORT = "22"') + self.write_config("\n".join(features)) + + recipe = "gcc-runtime" + bitbake("{} -c check".format(recipe)) + + bb_vars = get_bb_vars(["B", "TARGET_SYS"], recipe) + builddir, target_sys = bb_vars["B"], bb_vars["TARGET_SYS"] + + for suite in suites: + sumspath = os.path.join(builddir, "gcc", "testsuite", suite, "{0}.sum".format(suite)) + if not os.path.exists(sumspath): # check in target dirs + sumspath = os.path.join(builddir, target_sys, suite, "testsuite", "{0}.sum".format(suite)) + if not os.path.exists(sumspath): # handle libstdc++-v3 -> libstdc++ + sumspath = os.path.join(builddir, target_sys, suite, "testsuite", "{0}.sum".format(suite.split("-")[0])) + logpath = os.path.splitext(sumspath)[0] + ".log" + + ptestsuite = "gcc-{}".format(suite) if suite != "gcc" else suite + ptestsuite = ptestsuite + "-user" if ssh is None else ptestsuite + self.ptest_section(ptestsuite, logfile = logpath) + with open(sumspath, "r") as f: + for test, result in parse_values(f): + self.ptest_result(ptestsuite, test, result) + + def run_check_emulated(self, *args, **kwargs): + # build core-image-minimal with required packages + default_installed_packages = ["libgcc", "libstdc++", "libatomic", "libgomp"] + features = [] + features.append('IMAGE_FEATURES += "ssh-server-openssh"') + features.append('CORE_IMAGE_EXTRA_INSTALL += "{0}"'.format(" ".join(default_installed_packages))) + self.write_config("\n".join(features)) + bitbake("core-image-minimal") + + # wrap the execution with a qemu instance + with runqemu("core-image-minimal", runqemuparams = "nographic") as qemu: + # validate that SSH is working + status, _ = qemu.run("uname") + self.assertEqual(status, 0) + + return self.run_check(*args, ssh=qemu.ip, **kwargs) + +@OETestTag("toolchain-user") +class GccCrossSelfTest(GccSelfTestBase): + def test_cross_gcc(self): + self.run_check("gcc") + +@OETestTag("toolchain-user") +class GxxCrossSelfTest(GccSelfTestBase): + def test_cross_gxx(self): + self.run_check("g++") + +@OETestTag("toolchain-user") +class GccLibAtomicSelfTest(GccSelfTestBase): + def test_libatomic(self): + self.run_check("libatomic") + +@OETestTag("toolchain-user") +class GccLibGompSelfTest(GccSelfTestBase): + def test_libgomp(self): + self.run_check("libgomp") + +@OETestTag("toolchain-user") +class GccLibStdCxxSelfTest(GccSelfTestBase): + def test_libstdcxx(self): + self.run_check("libstdc++-v3") + +@OETestTag("toolchain-user") +class GccLibSspSelfTest(GccSelfTestBase): + def test_libssp(self): + self.check_skip("libssp") + self.run_check("libssp") + +@OETestTag("toolchain-user") +class GccLibItmSelfTest(GccSelfTestBase): + def test_libitm(self): + self.check_skip("libitm") + self.run_check("libitm") + +@OETestTag("toolchain-system") +class GccCrossSelfTestSystemEmulated(GccSelfTestBase): + def test_cross_gcc(self): + self.run_check_emulated("gcc") + +@OETestTag("toolchain-system") +class GxxCrossSelfTestSystemEmulated(GccSelfTestBase): + def test_cross_gxx(self): + self.run_check_emulated("g++") + +@OETestTag("toolchain-system") +class GccLibAtomicSelfTestSystemEmulated(GccSelfTestBase): + def test_libatomic(self): + self.run_check_emulated("libatomic") + +@OETestTag("toolchain-system") +class GccLibGompSelfTestSystemEmulated(GccSelfTestBase): + def test_libgomp(self): + self.run_check_emulated("libgomp") + +@OETestTag("toolchain-system") +class GccLibStdCxxSelfTestSystemEmulated(GccSelfTestBase): + def test_libstdcxx(self): + self.run_check_emulated("libstdc++-v3") + +@OETestTag("toolchain-system") +class GccLibSspSelfTestSystemEmulated(GccSelfTestBase): + def test_libssp(self): + self.check_skip("libssp") + self.run_check_emulated("libssp") + +@OETestTag("toolchain-system") +class GccLibItmSelfTestSystemEmulated(GccSelfTestBase): + def test_libitm(self): + self.check_skip("libitm") + self.run_check_emulated("libitm") + diff --git a/external/poky/meta/lib/oeqa/selftest/cases/glibc.py b/external/poky/meta/lib/oeqa/selftest/cases/glibc.py new file mode 100644 index 00000000..c687f6ef --- /dev/null +++ b/external/poky/meta/lib/oeqa/selftest/cases/glibc.py @@ -0,0 +1,89 @@ +# SPDX-License-Identifier: MIT +import os +import contextlib +from oeqa.core.decorator import OETestTag +from oeqa.core.case import OEPTestResultTestCase +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runqemu, Command +from oeqa.utils.nfs import unfs_server + +def parse_values(content): + for i in content: + for v in ["PASS", "FAIL", "XPASS", "XFAIL", "UNRESOLVED", "UNSUPPORTED", "UNTESTED", "ERROR", "WARNING"]: + if i.startswith(v + ": "): + yield i[len(v) + 2:].strip(), v + break + +class GlibcSelfTestBase(OESelftestTestCase, OEPTestResultTestCase): + def run_check(self, ssh = None): + # configure ssh target + features = [] + if ssh is not None: + features.append('TOOLCHAIN_TEST_TARGET = "ssh"') + features.append('TOOLCHAIN_TEST_HOST = "{0}"'.format(ssh)) + features.append('TOOLCHAIN_TEST_HOST_USER = "root"') + features.append('TOOLCHAIN_TEST_HOST_PORT = "22"') + # force single threaded test execution + features.append('EGLIBCPARALLELISM_task-check_pn-glibc-testsuite = "PARALLELMFLAGS="-j1""') + self.write_config("\n".join(features)) + + bitbake("glibc-testsuite -c check") + + builddir = get_bb_var("B", "glibc-testsuite") + + ptestsuite = "glibc-user" if ssh is None else "glibc" + self.ptest_section(ptestsuite) + with open(os.path.join(builddir, "tests.sum"), "r") as f: + for test, result in parse_values(f): + self.ptest_result(ptestsuite, test, result) + + def run_check_emulated(self): + with contextlib.ExitStack() as s: + # use the base work dir, as the nfs mount, since the recipe directory may not exist + tmpdir = get_bb_var("BASE_WORKDIR") + nfsport, mountport = s.enter_context(unfs_server(tmpdir)) + + # build core-image-minimal with required packages + default_installed_packages = [ + "glibc-charmaps", + "libgcc", + "libstdc++", + "libatomic", + "libgomp", + # "python3", + # "python3-pexpect", + "nfs-utils", + ] + features = [] + features.append('IMAGE_FEATURES += "ssh-server-openssh"') + features.append('CORE_IMAGE_EXTRA_INSTALL += "{0}"'.format(" ".join(default_installed_packages))) + self.write_config("\n".join(features)) + bitbake("core-image-minimal") + + # start runqemu + qemu = s.enter_context(runqemu("core-image-minimal", runqemuparams = "nographic")) + + # validate that SSH is working + status, _ = qemu.run("uname") + self.assertEqual(status, 0) + + # setup nfs mount + if qemu.run("mkdir -p \"{0}\"".format(tmpdir))[0] != 0: + raise Exception("Failed to setup NFS mount directory on target") + mountcmd = "mount -o noac,nfsvers=3,port={0},udp,mountport={1} \"{2}:{3}\" \"{3}\"".format(nfsport, mountport, qemu.server_ip, tmpdir) + status, output = qemu.run(mountcmd) + if status != 0: + raise Exception("Failed to setup NFS mount on target ({})".format(repr(output))) + + self.run_check(ssh = qemu.ip) + +@OETestTag("toolchain-user") +class GlibcSelfTest(GlibcSelfTestBase): + def test_glibc(self): + self.run_check() + +@OETestTag("toolchain-system") +class GlibcSelfTestSystemEmulated(GlibcSelfTestBase): + def test_glibc(self): + self.run_check_emulated() + diff --git a/external/poky/meta/lib/oeqa/selftest/cases/gotoolchain.py b/external/poky/meta/lib/oeqa/selftest/cases/gotoolchain.py index 1e23257f..3119520f 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/gotoolchain.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/gotoolchain.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + import glob import os import shutil diff --git a/external/poky/meta/lib/oeqa/selftest/cases/image_typedep.py b/external/poky/meta/lib/oeqa/selftest/cases/image_typedep.py index 932c7f88..52e1080f 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/image_typedep.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/image_typedep.py @@ -1,14 +1,16 @@ +# +# SPDX-License-Identifier: MIT +# + import os from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import bitbake -from oeqa.core.decorator.oeid import OETestID class ImageTypeDepTests(OESelftestTestCase): # Verify that when specifying a IMAGE_TYPEDEP_ of the form "foo.bar" that # the conversion type bar gets added as a dep as well - @OETestID(1633) def test_conversion_typedep_added(self): self.write_recipeinc('emptytest', """ diff --git a/external/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py b/external/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py index 8c95432e..2b9c4998 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py @@ -1,6 +1,9 @@ +# +# SPDX-License-Identifier: MIT +# + from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import runCmd, bitbake, get_bb_var, runqemu -from oeqa.core.decorator.oeid import OETestID from oeqa.utils.sshcontrol import SSHControl import os import json @@ -10,7 +13,6 @@ class ImageFeatures(OESelftestTestCase): test_user = 'tester' root_user = 'root' - @OETestID(1107) def test_non_root_user_can_connect_via_ssh_without_password(self): """ Summary: Check if non root user can connect via ssh without password @@ -36,7 +38,6 @@ class ImageFeatures(OESelftestTestCase): status, output = ssh.run("true") self.assertEqual(status, 0, 'ssh to user %s failed with %s' % (user, output)) - @OETestID(1115) def test_all_users_can_connect_via_ssh_without_password(self): """ Summary: Check if all users can connect via ssh without password @@ -66,7 +67,6 @@ class ImageFeatures(OESelftestTestCase): self.assertEqual(status, 0, 'ssh to user tester failed with %s' % output) - @OETestID(1116) def test_clutter_image_can_be_built(self): """ Summary: Check if clutter image can be built @@ -79,7 +79,6 @@ class ImageFeatures(OESelftestTestCase): # Build a core-image-clutter bitbake('core-image-clutter') - @OETestID(1117) def test_wayland_support_in_image(self): """ Summary: Check Wayland support in image @@ -97,7 +96,6 @@ class ImageFeatures(OESelftestTestCase): # Build a core-image-weston bitbake('core-image-weston') - @OETestID(1497) def test_bmap(self): """ Summary: Check bmap support @@ -126,12 +124,11 @@ class ImageFeatures(OESelftestTestCase): # check if result image is sparse image_stat = os.stat(image_path) - self.assertTrue(image_stat.st_size > image_stat.st_blocks * 512) + self.assertGreater(image_stat.st_size, image_stat.st_blocks * 512) # check if the resulting gzip is valid self.assertTrue(runCmd('gzip -t %s' % gzip_path)) - @OETestID(1903) def test_hypervisor_fmts(self): """ Summary: Check various hypervisor formats @@ -164,9 +161,13 @@ class ImageFeatures(OESelftestTestCase): sysroot = get_bb_var('STAGING_DIR_NATIVE', 'core-image-minimal') result = runCmd('qemu-img info --output json %s' % image_path, native_sysroot=sysroot) - self.assertTrue(json.loads(result.output).get('format') == itype) + try: + data = json.loads(result.output) + self.assertEqual(data.get('format'), itype, + msg="Unexpected format in '%s'" % (result.output)) + except json.decoder.JSONDecodeError: + self.fail("Could not parse '%ss'" % result.output) - @OETestID(1905) def test_long_chain_conversion(self): """ Summary: Check for chaining many CONVERSION_CMDs together @@ -198,7 +199,6 @@ class ImageFeatures(OESelftestTestCase): self.assertTrue(runCmd('cd %s;sha256sum -c %s.%s.sha256sum' % (deploy_dir_image, link_name, conv))) - @OETestID(1904) def test_image_fstypes(self): """ Summary: Check if image of supported image fstypes can be built @@ -208,13 +208,13 @@ class ImageFeatures(OESelftestTestCase): """ image_name = 'core-image-minimal' - img_types = [itype for itype in get_bb_var("IMAGE_TYPES", image_name).split() \ - if itype not in ('container', 'elf', 'f2fs', 'multiubi')] + all_image_types = set(get_bb_var("IMAGE_TYPES", image_name).split()) + blacklist = set(('container', 'elf', 'f2fs', 'multiubi', 'tar.zst')) + img_types = all_image_types - blacklist config = 'IMAGE_FSTYPES += "%s"\n'\ 'MKUBIFS_ARGS ?= "-m 2048 -e 129024 -c 2047"\n'\ 'UBINIZE_ARGS ?= "-m 2048 -p 128KiB -s 512"' % ' '.join(img_types) - self.write_config(config) bitbake(image_name) @@ -236,3 +236,61 @@ USERADD_GID_TABLES += "files/static-group" """ self.write_config(config) bitbake("core-image-base") + + def test_no_busybox_base_utils(self): + config = """ +# Enable x11 +DISTRO_FEATURES_append += "x11" + +# Switch to systemd +DISTRO_FEATURES += "systemd" +VIRTUAL-RUNTIME_init_manager = "systemd" +VIRTUAL-RUNTIME_initscripts = "" +VIRTUAL-RUNTIME_syslog = "" +VIRTUAL-RUNTIME_login_manager = "shadow-base" +DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit" + +# Replace busybox +PREFERRED_PROVIDER_virtual/base-utils = "packagegroup-core-base-utils" +VIRTUAL-RUNTIME_base-utils = "packagegroup-core-base-utils" +VIRTUAL-RUNTIME_base-utils-hwclock = "util-linux-hwclock" +VIRTUAL-RUNTIME_base-utils-syslog = "" + +# Blacklist busybox +PNBLACKLIST[busybox] = "Don't build this" +""" + self.write_config(config) + + bitbake("--graphviz core-image-sato") + + def test_image_gen_debugfs(self): + """ + Summary: Check debugfs generation + Expected: 1. core-image-minimal can be build with IMAGE_GEN_DEBUGFS variable set + 2. debug filesystem is created when variable set + 3. debug symbols available + Product: oe-core + Author: Humberto Ibarra + Yeoh Ee Peng + """ + import glob + image_name = 'core-image-minimal' + features = 'IMAGE_GEN_DEBUGFS = "1"\n' + features += 'IMAGE_FSTYPES_DEBUGFS = "tar.bz2"\n' + features += 'MACHINE = "genericx86-64"\n' + self.write_config(features) + + bitbake(image_name) + deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') + dbg_tar_file = os.path.join(deploy_dir_image, "*-dbg.rootfs.tar.bz2") + debug_files = glob.glob(dbg_tar_file) + self.assertNotEqual(len(debug_files), 0, 'debug filesystem not generated at %s' % dbg_tar_file) + result = runCmd('cd %s; tar xvf %s' % (deploy_dir_image, dbg_tar_file)) + self.assertEqual(result.status, 0, msg='Failed to extract %s: %s' % (dbg_tar_file, result.output)) + result = runCmd('find %s -name %s' % (deploy_dir_image, "udevadm")) + self.assertTrue("udevadm" in result.output, msg='Failed to find udevadm: %s' % result.output) + dbg_symbols_targets = result.output.splitlines() + self.assertTrue(dbg_symbols_targets, msg='Failed to split udevadm: %s' % dbg_symbols_targets) + for t in dbg_symbols_targets: + result = runCmd('objdump --syms %s | grep debug' % t) + self.assertTrue("debug" in result.output, msg='Failed to find debug symbol: %s' % result.output) diff --git a/external/poky/meta/lib/oeqa/selftest/cases/incompatible_lic.py b/external/poky/meta/lib/oeqa/selftest/cases/incompatible_lic.py new file mode 100644 index 00000000..3eabd790 --- /dev/null +++ b/external/poky/meta/lib/oeqa/selftest/cases/incompatible_lic.py @@ -0,0 +1,135 @@ +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import bitbake + +class IncompatibleLicenseTests(OESelftestTestCase): + + def lic_test(self, pn, pn_lic, lic): + error_msg = 'ERROR: Nothing PROVIDES \'%s\'\n%s was skipped: it has incompatible license(s): %s' % (pn, pn, pn_lic) + + self.write_config("INCOMPATIBLE_LICENSE += \"%s\"" % (lic)) + + result = bitbake('%s --dry-run' % (pn), ignore_status=True) + if error_msg not in result.output: + raise AssertionError(result.output) + + # Verify that a package with an SPDX license (from AVAILABLE_LICENSES) + # cannot be built when INCOMPATIBLE_LICENSE contains this SPDX license + def test_incompatible_spdx_license(self): + self.lic_test('incompatible-license', 'GPL-3.0', 'GPL-3.0') + + # Verify that a package with an SPDX license (from AVAILABLE_LICENSES) + # cannot be built when INCOMPATIBLE_LICENSE contains an alias (in + # SPDXLICENSEMAP) of this SPDX license + def test_incompatible_alias_spdx_license(self): + self.lic_test('incompatible-license', 'GPL-3.0', 'GPLv3') + + # Verify that a package with an SPDX license (from AVAILABLE_LICENSES) + # cannot be built when INCOMPATIBLE_LICENSE contains a wildcarded license + # matching this SPDX license + def test_incompatible_spdx_license_wildcard(self): + self.lic_test('incompatible-license', 'GPL-3.0', '*GPL-3.0') + + # Verify that a package with an SPDX license (from AVAILABLE_LICENSES) + # cannot be built when INCOMPATIBLE_LICENSE contains a wildcarded alias + # license matching this SPDX license + def test_incompatible_alias_spdx_license_wildcard(self): + self.lic_test('incompatible-license', 'GPL-3.0', '*GPLv3') + + # Verify that a package with an alias (from SPDXLICENSEMAP) to an SPDX + # license cannot be built when INCOMPATIBLE_LICENSE contains this SPDX + # license + def test_incompatible_spdx_license_alias(self): + self.lic_test('incompatible-license-alias', 'GPL-3.0', 'GPL-3.0') + + # Verify that a package with an alias (from SPDXLICENSEMAP) to an SPDX + # license cannot be built when INCOMPATIBLE_LICENSE contains this alias + def test_incompatible_alias_spdx_license_alias(self): + self.lic_test('incompatible-license-alias', 'GPL-3.0', 'GPLv3') + + # Verify that a package with an alias (from SPDXLICENSEMAP) to an SPDX + # license cannot be built when INCOMPATIBLE_LICENSE contains a wildcarded + # license matching this SPDX license + def test_incompatible_spdx_license_alias_wildcard(self): + self.lic_test('incompatible-license-alias', 'GPL-3.0', '*GPL-3.0') + + # Verify that a package with an alias (from SPDXLICENSEMAP) to an SPDX + # license cannot be built when INCOMPATIBLE_LICENSE contains a wildcarded + # alias license matching the SPDX license + def test_incompatible_alias_spdx_license_alias_wildcard(self): + self.lic_test('incompatible-license-alias', 'GPL-3.0', '*GPLv3') + + # Verify that a package with multiple SPDX licenses (from + # AVAILABLE_LICENSES) cannot be built when INCOMPATIBLE_LICENSE contains + # some of them + def test_incompatible_spdx_licenses(self): + self.lic_test('incompatible-licenses', 'GPL-3.0 LGPL-3.0', 'GPL-3.0 LGPL-3.0') + + # Verify that a package with multiple SPDX licenses (from + # AVAILABLE_LICENSES) cannot be built when INCOMPATIBLE_LICENSE contains a + # wildcard to some of them + def test_incompatible_spdx_licenses_wildcard(self): + self.lic_test('incompatible-licenses', 'GPL-3.0 LGPL-3.0', '*GPL-3.0') + + # Verify that a package with multiple SPDX licenses (from + # AVAILABLE_LICENSES) cannot be built when INCOMPATIBLE_LICENSE contains a + # wildcard matching all licenses + def test_incompatible_all_licenses_wildcard(self): + self.lic_test('incompatible-licenses', 'GPL-2.0 GPL-3.0 LGPL-3.0', '*') + + # Verify that a package with a non-SPDX license (neither in + # AVAILABLE_LICENSES nor in SPDXLICENSEMAP) cannot be built when + # INCOMPATIBLE_LICENSE contains this license + def test_incompatible_nonspdx_license(self): + self.lic_test('incompatible-nonspdx-license', 'FooLicense', 'FooLicense') + +class IncompatibleLicensePerImageTests(OESelftestTestCase): + def default_config(self): + return """ +IMAGE_INSTALL_append = "bash" +INCOMPATIBLE_LICENSE_pn-core-image-minimal = "GPL-3.0 LGPL-3.0" +""" + + def test_bash_default(self): + self.write_config(self.default_config()) + error_msg = "ERROR: core-image-minimal-1.0-r0 do_rootfs: Package bash cannot be installed into the image because it has incompatible license(s): GPL-3.0+" + + result = bitbake('core-image-minimal', ignore_status=True) + if error_msg not in result.output: + raise AssertionError(result.output) + + def test_bash_and_license(self): + self.write_config(self.default_config() + '\nLICENSE_append_pn-bash = " & SomeLicense"') + error_msg = "ERROR: core-image-minimal-1.0-r0 do_rootfs: Package bash cannot be installed into the image because it has incompatible license(s): GPL-3.0+" + + result = bitbake('core-image-minimal', ignore_status=True) + if error_msg not in result.output: + raise AssertionError(result.output) + + def test_bash_or_license(self): + self.write_config(self.default_config() + '\nLICENSE_append_pn-bash = " | SomeLicense"') + + bitbake('core-image-minimal') + + def test_bash_whitelist(self): + self.write_config(self.default_config() + '\nWHITELIST_GPL-3.0_pn-core-image-minimal = "bash"') + + bitbake('core-image-minimal') + +class NoGPL3InImagesTests(OESelftestTestCase): + def test_core_image_minimal(self): + self.write_config(""" +INCOMPATIBLE_LICENSE_pn-core-image-minimal = "GPL-3.0 LGPL-3.0" +""") + bitbake('core-image-minimal') + + def test_core_image_full_cmdline(self): + self.write_config(""" +INHERIT += "testimage"\n +INCOMPATIBLE_LICENSE_pn-core-image-full-cmdline = "GPL-3.0 LGPL-3.0"\n +RDEPENDS_packagegroup-core-full-cmdline-utils_remove = "bash bc coreutils cpio ed findutils gawk grep mc mc-fish mc-helpers mc-helpers-perl sed tar time"\n +RDEPENDS_packagegroup-core-full-cmdline-dev-utils_remove = "diffutils m4 make patch"\n +RDEPENDS_packagegroup-core-full-cmdline-multiuser_remove = "gzip"\n +""") + bitbake('core-image-full-cmdline') + bitbake('-c testimage core-image-full-cmdline') + diff --git a/external/poky/meta/lib/oeqa/selftest/cases/kerneldevelopment.py b/external/poky/meta/lib/oeqa/selftest/cases/kerneldevelopment.py new file mode 100644 index 00000000..a61876ee --- /dev/null +++ b/external/poky/meta/lib/oeqa/selftest/cases/kerneldevelopment.py @@ -0,0 +1,67 @@ +import os +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import runCmd, get_bb_var +from oeqa.utils.git import GitRepo + +class KernelDev(OESelftestTestCase): + + @classmethod + def setUpClass(cls): + super(KernelDev, cls).setUpClass() + # Create the recipe directory structure inside the created layer + cls.layername = 'meta-kerneltest' + runCmd('bitbake-layers create-layer %s' % cls.layername) + runCmd('mkdir -p %s/recipes-kernel/linux/linux-yocto' % cls.layername) + cls.recipes_linuxyocto_dir = os.path.join \ + (cls.builddir, cls.layername, 'recipes-kernel', 'linux', 'linux-yocto') + cls.recipeskernel_dir = os.path.dirname(cls.recipes_linuxyocto_dir) + runCmd('bitbake-layers add-layer %s' % cls.layername) + + @classmethod + def tearDownClass(cls): + runCmd('bitbake-layers remove-layer %s' % cls.layername, ignore_status=True) + runCmd('rm -rf %s' % cls.layername) + super(KernelDev, cls).tearDownClass() + + def setUp(self): + super(KernelDev, self).setUp() + self.set_machine_config('MACHINE = "qemux86-64"\n') + + def test_apply_patches(self): + """ + Summary: Able to apply a single patch to the Linux kernel source + Expected: The README file should exist and the patch changes should be + displayed at the end of the file. + Product: Kernel Development + Author: Yeoh Ee Peng + AutomatedBy: Mazliana Mohamad + """ + runCmd('bitbake virtual/kernel -c patch') + kernel_source = get_bb_var('STAGING_KERNEL_DIR') + readme = os.path.join(kernel_source, 'README') + + # This test step adds modified file 'README' to git and creates a + # patch file '0001-KERNEL_DEV_TEST_CASE.patch' at the same location as file + patch_content = 'This is a test to apply a patch to the kernel' + with open(readme, 'a+') as f: + f.write(patch_content) + repo = GitRepo('%s' % kernel_source, is_topdir=True) + repo.run_cmd('add %s' % readme) + repo.run_cmd(['commit', '-m', 'KERNEL_DEV_TEST_CASE']) + repo.run_cmd(['format-patch', '-1']) + patch_name = '0001-KERNEL_DEV_TEST_CASE.patch' + patchpath = os.path.join(kernel_source, patch_name) + runCmd('mv %s %s' % (patchpath, self.recipes_linuxyocto_dir)) + runCmd('rm %s ' % readme) + self.assertFalse(os.path.exists(readme)) + + recipe_append = os.path.join(self.recipeskernel_dir, 'linux-yocto_%.bbappend') + with open(recipe_append, 'w+') as fh: + fh.write('SRC_URI += "file://%s"\n' % patch_name) + fh.write('FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"') + + runCmd('bitbake virtual/kernel -c clean') + runCmd('bitbake virtual/kernel -c patch') + self.assertTrue(os.path.exists(readme)) + result = runCmd('tail -n 1 %s' % readme) + self.assertEqual(result.output, patch_content) diff --git a/external/poky/meta/lib/oeqa/selftest/cases/layerappend.py b/external/poky/meta/lib/oeqa/selftest/cases/layerappend.py index 2fd5cdb0..05e9426f 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/layerappend.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/layerappend.py @@ -1,9 +1,12 @@ +# +# SPDX-License-Identifier: MIT +# + import os from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import runCmd, bitbake, get_bb_var import oeqa.utils.ftools as ftools -from oeqa.core.decorator.oeid import OETestID class LayerAppendTests(OESelftestTestCase): layerconf = """ @@ -49,7 +52,6 @@ SRC_URI_append = " file://appendtest.txt" ftools.remove_from_file(self.builddir + "/conf/bblayers.conf", self.layerappend) super(LayerAppendTests, self).tearDownLocal() - @OETestID(1196) def test_layer_appends(self): corebase = get_bb_var("COREBASE") diff --git a/external/poky/meta/lib/oeqa/selftest/cases/liboe.py b/external/poky/meta/lib/oeqa/selftest/cases/liboe.py index e8460924..afe8f880 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/liboe.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/liboe.py @@ -1,5 +1,8 @@ +# +# SPDX-License-Identifier: MIT +# + from oeqa.selftest.case import OESelftestTestCase -from oeqa.core.decorator.oeid import OETestID from oeqa.utils.commands import get_bb_var, get_bb_vars, bitbake, runCmd import oe.path import os @@ -11,7 +14,6 @@ class LibOE(OESelftestTestCase): super(LibOE, cls).setUpClass() cls.tmp_dir = get_bb_var('TMPDIR') - @OETestID(1635) def test_copy_tree_special(self): """ Summary: oe.path.copytree() should copy files with special character @@ -37,7 +39,6 @@ class LibOE(OESelftestTestCase): oe.path.remove(testloc) - @OETestID(1636) def test_copy_tree_xattr(self): """ Summary: oe.path.copytree() should preserve xattr on copied files @@ -72,7 +73,6 @@ class LibOE(OESelftestTestCase): oe.path.remove(testloc) - @OETestID(1634) def test_copy_hardlink_tree_count(self): """ Summary: oe.path.copyhardlinktree() shouldn't miss out files diff --git a/external/poky/meta/lib/oeqa/selftest/cases/lic_checksum.py b/external/poky/meta/lib/oeqa/selftest/cases/lic_checksum.py index f992b373..bae935d6 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/lic_checksum.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/lic_checksum.py @@ -1,16 +1,18 @@ +# +# SPDX-License-Identifier: MIT +# + import os import tempfile from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import bitbake from oeqa.utils import CommandError -from oeqa.core.decorator.oeid import OETestID class LicenseTests(OESelftestTestCase): # Verify that changing a license file that has an absolute path causes # the license qa to fail due to a mismatched md5sum. - @OETestID(1197) def test_nonmatching_checksum(self): bitbake_cmd = '-c populate_lic emptytest' error_msg = 'emptytest: The new md5 checksum is 8d777f385d3dfec8815d20f7496026dc' diff --git a/external/poky/meta/lib/oeqa/selftest/cases/manifest.py b/external/poky/meta/lib/oeqa/selftest/cases/manifest.py index 14607193..5d13f354 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/manifest.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/manifest.py @@ -1,8 +1,11 @@ +# +# SPDX-License-Identifier: MIT +# + import os from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import get_bb_var, get_bb_vars, bitbake -from oeqa.core.decorator.oeid import OETestID class ManifestEntry: '''A manifest item of a collection able to list missing packages''' @@ -59,7 +62,6 @@ class VerifyManifest(OESelftestTestCase): self.skipTest("{}: Cannot setup testing scenario"\ .format(self.classname)) - @OETestID(1380) def test_SDK_manifest_entries(self): '''Verifying the SDK manifest entries exist, this may take a build''' @@ -84,11 +86,8 @@ class VerifyManifest(OESelftestTestCase): try: mdir = self.get_dir_from_bb_var('SDK_DEPLOY', self.buildtarget) for k in d_target.keys(): - bb_vars = get_bb_vars(['SDK_NAME', 'SDK_VERSION'], self.buildtarget) - mfilename[k] = "{}-toolchain-{}.{}.manifest".format( - bb_vars['SDK_NAME'], - bb_vars['SDK_VERSION'], - k) + toolchain_outputname = get_bb_var('TOOLCHAIN_OUTPUTNAME', self.buildtarget) + mfilename[k] = "{}.{}.manifest".format(toolchain_outputname, k) mpath[k] = os.path.join(mdir, mfilename[k]) if not os.path.isfile(mpath[k]): self.logger.debug("{}: {} does not exist".format( @@ -126,7 +125,6 @@ class VerifyManifest(OESelftestTestCase): self.logger.info(msg) self.fail(logmsg) - @OETestID(1381) def test_image_manifest_entries(self): '''Verifying the image manifest entries exist''' diff --git a/external/poky/meta/lib/oeqa/selftest/cases/meta_ide.py b/external/poky/meta/lib/oeqa/selftest/cases/meta_ide.py index 5df9d3ed..80914255 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/meta_ide.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/meta_ide.py @@ -1,10 +1,15 @@ +# +# SPDX-License-Identifier: MIT +# + from oeqa.selftest.case import OESelftestTestCase from oeqa.sdk.utils.sdkbuildproject import SDKBuildProject from oeqa.utils.commands import bitbake, get_bb_vars, runCmd -from oeqa.core.decorator.oeid import OETestID +from oeqa.core.decorator import OETestTag import tempfile import shutil +@OETestTag("machine") class MetaIDE(OESelftestTestCase): @classmethod @@ -23,22 +28,19 @@ class MetaIDE(OESelftestTestCase): shutil.rmtree(cls.tmpdir_metaideQA, ignore_errors=True) super(MetaIDE, cls).tearDownClass() - @OETestID(1982) def test_meta_ide_had_installed_meta_ide_support(self): self.assertExists(self.environment_script_path) - @OETestID(1983) def test_meta_ide_can_compile_c_program(self): runCmd('cp %s/test.c %s' % (self.tc.files_dir, self.tmpdir_metaideQA)) runCmd("cd %s; . %s; $CC test.c -lm" % (self.tmpdir_metaideQA, self.environment_script_path)) compiled_file = '%s/a.out' % self.tmpdir_metaideQA self.assertExists(compiled_file) - @OETestID(1984) def test_meta_ide_can_build_cpio_project(self): dl_dir = self.td.get('DL_DIR', None) self.project = SDKBuildProject(self.tmpdir_metaideQA + "/cpio/", self.environment_script_path, - "https://ftp.gnu.org/gnu/cpio/cpio-2.12.tar.gz", + "https://ftp.gnu.org/gnu/cpio/cpio-2.13.tar.gz", self.tmpdir_metaideQA, self.td['DATETIME'], dl_dir=dl_dir) self.project.download_archive() self.assertEqual(self.project.run_configure(), 0, diff --git a/external/poky/meta/lib/oeqa/selftest/cases/multiconfig.py b/external/poky/meta/lib/oeqa/selftest/cases/multiconfig.py new file mode 100644 index 00000000..39b92f24 --- /dev/null +++ b/external/poky/meta/lib/oeqa/selftest/cases/multiconfig.py @@ -0,0 +1,72 @@ +# +# SPDX-License-Identifier: MIT +# + +import os +import textwrap +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import bitbake + +class MultiConfig(OESelftestTestCase): + + def test_multiconfig(self): + """ + Test that a simple multiconfig build works. This uses the mcextend class and the + multiconfig-image-packager test recipe to build a core-image-full-cmdline image which + contains a tiny core-image-minimal and a musl core-image-minimal, installed as packages. + """ + + config = """ +IMAGE_INSTALL_append_pn-core-image-full-cmdline = " multiconfig-image-packager-tiny multiconfig-image-packager-musl" +BBMULTICONFIG = "tiny musl" +""" + self.write_config(config) + + muslconfig = """ +MACHINE = "qemux86-64" +DISTRO = "poky" +TCLIBC = "musl" +TMPDIR = "${TOPDIR}/tmp-mc-musl" +""" + self.write_config(muslconfig, 'musl') + + tinyconfig = """ +MACHINE = "qemux86" +DISTRO = "poky-tiny" +TMPDIR = "${TOPDIR}/tmp-mc-tiny" +""" + self.write_config(tinyconfig, 'tiny') + + # Build a core-image-minimal + bitbake('core-image-full-cmdline') + + def test_multiconfig_reparse(self): + """ + Test that changes to a multiconfig conf file are correctly detected and + cause a reparse/rebuild of a recipe. + """ + config = textwrap.dedent('''\ + MCTESTVAR = "test" + BBMULTICONFIG = "test" + ''') + self.write_config(config) + + testconfig = textwrap.dedent('''\ + MCTESTVAR_append = "1" + ''') + self.write_config(testconfig, 'test') + + # Check that the 1) the task executed and 2) that it output the correct + # value. Note "bitbake -e" is not used because it always reparses the + # recipe and we want to ensure that the automatic reparsing and parse + # caching is detected. + result = bitbake('mc:test:multiconfig-test-parse -c showvar') + self.assertIn('MCTESTVAR=test1', result.output.splitlines()) + + testconfig = textwrap.dedent('''\ + MCTESTVAR_append = "2" + ''') + self.write_config(testconfig, 'test') + + result = bitbake('mc:test:multiconfig-test-parse -c showvar') + self.assertIn('MCTESTVAR=test2', result.output.splitlines()) diff --git a/external/poky/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py b/external/poky/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py index 08675fd8..d4664bd0 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py @@ -1,8 +1,11 @@ +# +# SPDX-License-Identifier: MIT +# + import os from oeqa.selftest.case import OESelftestTestCase import tempfile from oeqa.utils.commands import get_bb_var -from oeqa.core.decorator.oeid import OETestID class TestBlobParsing(OESelftestTestCase): @@ -40,10 +43,9 @@ class TestBlobParsing(OESelftestTestCase): self.repo.git.add("--all") self.repo.git.commit(message=msg) - @OETestID(1859) def test_blob_to_dict(self): """ - Test convertion of git blobs to dictionary + Test conversion of git blobs to dictionary """ from oe.buildhistory_analysis import blob_to_dict valuesmap = { "foo" : "1", "bar" : "2" } @@ -53,7 +55,6 @@ class TestBlobParsing(OESelftestTestCase): self.assertEqual(valuesmap, blob_to_dict(blob), "commit was not translated correctly to dictionary") - @OETestID(1860) def test_compare_dict_blobs(self): """ Test comparisson of dictionaries extracted from git blobs @@ -74,7 +75,6 @@ class TestBlobParsing(OESelftestTestCase): var_changes = { x.fieldname : (x.oldvalue, x.newvalue) for x in change_records} self.assertEqual(changesmap, var_changes, "Changes not reported correctly") - @OETestID(1861) def test_compare_dict_blobs_default(self): """ Test default values for comparisson of git blob dictionaries diff --git a/external/poky/meta/lib/oeqa/selftest/cases/oelib/elf.py b/external/poky/meta/lib/oeqa/selftest/cases/oelib/elf.py index 15c03f46..d0a28090 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/oelib/elf.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/oelib/elf.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + from unittest.case import TestCase import oe.qa diff --git a/external/poky/meta/lib/oeqa/selftest/cases/oelib/license.py b/external/poky/meta/lib/oeqa/selftest/cases/oelib/license.py index d7f91fb2..6ebbee58 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/oelib/license.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/oelib/license.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + from unittest.case import TestCase import oe.license diff --git a/external/poky/meta/lib/oeqa/selftest/cases/oelib/path.py b/external/poky/meta/lib/oeqa/selftest/cases/oelib/path.py index e0eb8134..a1cfa08c 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/oelib/path.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/oelib/path.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + from unittest.case import TestCase import oe, oe.path import tempfile diff --git a/external/poky/meta/lib/oeqa/selftest/cases/oelib/types.py b/external/poky/meta/lib/oeqa/selftest/cases/oelib/types.py index 6b53aa64..7eb49e6f 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/oelib/types.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/oelib/types.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + from unittest.case import TestCase from oe.maketype import create diff --git a/external/poky/meta/lib/oeqa/selftest/cases/oelib/utils.py b/external/poky/meta/lib/oeqa/selftest/cases/oelib/utils.py index 789c6f78..a7214beb 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/oelib/utils.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/oelib/utils.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + import sys from unittest.case import TestCase from contextlib import contextmanager diff --git a/external/poky/meta/lib/oeqa/selftest/cases/oescripts.py b/external/poky/meta/lib/oeqa/selftest/cases/oescripts.py index bcdc2d5a..726daff7 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/oescripts.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/oescripts.py @@ -1,11 +1,18 @@ +# +# SPDX-License-Identifier: MIT +# + +import os +import shutil +import importlib +import unittest from oeqa.selftest.case import OESelftestTestCase from oeqa.selftest.cases.buildhistory import BuildhistoryBase from oeqa.utils.commands import Command, runCmd, bitbake, get_bb_var, get_test_layer -from oeqa.core.decorator.oeid import OETestID +from oeqa.utils import CommandError class BuildhistoryDiffTests(BuildhistoryBase): - @OETestID(295) def test_buildhistory_diff(self): target = 'xcursor-transparent-theme' self.run_buildhistory_operation(target, target_config="PR = \"r1\"", change_bh_location=True) @@ -26,3 +33,155 @@ class BuildhistoryDiffTests(BuildhistoryBase): self.fail('Unexpected line:\n%s\nExpected line endings:\n %s' % (line, '\n '.join(expected_endlines))) if expected_endlines: self.fail('Missing expected line endings:\n %s' % '\n '.join(expected_endlines)) + +@unittest.skipUnless(importlib.util.find_spec("cairo"), "Python cairo module is not present") +class OEScriptTests(OESelftestTestCase): + + @classmethod + def setUpClass(cls): + super(OEScriptTests, cls).setUpClass() + import cairo + bitbake("core-image-minimal -c rootfs -f") + cls.tmpdir = get_bb_var('TMPDIR') + cls.buildstats = cls.tmpdir + "/buildstats/" + sorted(os.listdir(cls.tmpdir + "/buildstats"))[-1] + + scripts_dir = os.path.join(get_bb_var('COREBASE'), 'scripts') + +class OEPybootchartguyTests(OEScriptTests): + + def test_pybootchartguy_help(self): + runCmd('%s/pybootchartgui/pybootchartgui.py --help' % self.scripts_dir) + + def test_pybootchartguy_to_generate_build_png_output(self): + runCmd('%s/pybootchartgui/pybootchartgui.py %s -o %s/charts -f png' % (self.scripts_dir, self.buildstats, self.tmpdir)) + self.assertTrue(os.path.exists(self.tmpdir + "/charts.png")) + + def test_pybootchartguy_to_generate_build_svg_output(self): + runCmd('%s/pybootchartgui/pybootchartgui.py %s -o %s/charts -f svg' % (self.scripts_dir, self.buildstats, self.tmpdir)) + self.assertTrue(os.path.exists(self.tmpdir + "/charts.svg")) + + def test_pybootchartguy_to_generate_build_pdf_output(self): + runCmd('%s/pybootchartgui/pybootchartgui.py %s -o %s/charts -f pdf' % (self.scripts_dir, self.buildstats, self.tmpdir)) + self.assertTrue(os.path.exists(self.tmpdir + "/charts.pdf")) + + +class OEGitproxyTests(OESelftestTestCase): + + scripts_dir = os.path.join(get_bb_var('COREBASE'), 'scripts') + + def test_oegitproxy_help(self): + try: + res = runCmd('%s/oe-git-proxy --help' % self.scripts_dir, assert_error=False) + self.assertTrue(False) + except CommandError as e: + self.assertEqual(2, e.retcode) + + def run_oegitproxy(self, custom_shell=None): + os.environ['SOCAT'] = shutil.which("echo") + os.environ['ALL_PROXY'] = "https://proxy.example.com:3128" + os.environ['NO_PROXY'] = "*.example.com,.no-proxy.org,192.168.42.0/24,127.*.*.*" + + if custom_shell is None: + prefix = '' + else: + prefix = custom_shell + ' ' + + # outside, use the proxy + res = runCmd('%s%s/oe-git-proxy host.outside-example.com 9418' % + (prefix,self.scripts_dir)) + self.assertIn('PROXY:', res.output) + # match with wildcard suffix + res = runCmd('%s%s/oe-git-proxy host.example.com 9418' % + (prefix, self.scripts_dir)) + self.assertIn('TCP:', res.output) + # match just suffix + res = runCmd('%s%s/oe-git-proxy host.no-proxy.org 9418' % + (prefix, self.scripts_dir)) + self.assertIn('TCP:', res.output) + # match IP subnet + res = runCmd('%s%s/oe-git-proxy 192.168.42.42 9418' % + (prefix, self.scripts_dir)) + self.assertIn('TCP:', res.output) + # match IP wildcard + res = runCmd('%s%s/oe-git-proxy 127.1.2.3 9418' % + (prefix, self.scripts_dir)) + self.assertIn('TCP:', res.output) + + # test that * globbering is off + os.environ['NO_PROXY'] = "*" + res = runCmd('%s%s/oe-git-proxy host.example.com 9418' % + (prefix, self.scripts_dir)) + self.assertIn('TCP:', res.output) + + def test_oegitproxy_proxy(self): + self.run_oegitproxy() + + def test_oegitproxy_proxy_dash(self): + dash = shutil.which("dash") + if dash is None: + self.skipTest("No \"dash\" found on test system.") + self.run_oegitproxy(custom_shell=dash) + +class OeRunNativeTest(OESelftestTestCase): + def test_oe_run_native(self): + bitbake("qemu-helper-native -c addto_recipe_sysroot") + result = runCmd("oe-run-native qemu-helper-native tunctl -h") + self.assertIn("Delete: tunctl -d device-name [-f tun-clone-device]", result.output) + +class OEListPackageconfigTests(OEScriptTests): + #oe-core.scripts.List_all_the_PACKAGECONFIG's_flags + def check_endlines(self, results, expected_endlines): + for line in results.output.splitlines(): + for el in expected_endlines: + if line.split() == el.split(): + expected_endlines.remove(el) + break + + if expected_endlines: + self.fail('Missing expected listings:\n %s' % '\n '.join(expected_endlines)) + + + #oe-core.scripts.List_all_the_PACKAGECONFIG's_flags + def test_packageconfig_flags_help(self): + runCmd('%s/contrib/list-packageconfig-flags.py -h' % self.scripts_dir) + + def test_packageconfig_flags_default(self): + results = runCmd('%s/contrib/list-packageconfig-flags.py' % self.scripts_dir) + expected_endlines = [] + expected_endlines.append("RECIPE NAME PACKAGECONFIG FLAGS") + expected_endlines.append("pinentry gtk2 libcap ncurses qt secret") + expected_endlines.append("tar acl") + + self.check_endlines(results, expected_endlines) + + + def test_packageconfig_flags_option_flags(self): + results = runCmd('%s/contrib/list-packageconfig-flags.py -f' % self.scripts_dir) + expected_endlines = [] + expected_endlines.append("PACKAGECONFIG FLAG RECIPE NAMES") + expected_endlines.append("qt nativesdk-pinentry pinentry pinentry-native") + expected_endlines.append("secret nativesdk-pinentry pinentry pinentry-native") + + self.check_endlines(results, expected_endlines) + + def test_packageconfig_flags_option_all(self): + results = runCmd('%s/contrib/list-packageconfig-flags.py -a' % self.scripts_dir) + expected_endlines = [] + expected_endlines.append("pinentry-1.1.0") + expected_endlines.append("PACKAGECONFIG ncurses libcap") + expected_endlines.append("PACKAGECONFIG[qt] --enable-pinentry-qt, --disable-pinentry-qt, qtbase-native qtbase") + expected_endlines.append("PACKAGECONFIG[gtk2] --enable-pinentry-gtk2, --disable-pinentry-gtk2, gtk+ glib-2.0") + expected_endlines.append("PACKAGECONFIG[libcap] --with-libcap, --without-libcap, libcap") + expected_endlines.append("PACKAGECONFIG[ncurses] --enable-ncurses --with-ncurses-include-dir=${STAGING_INCDIR}, --disable-ncurses, ncurses") + expected_endlines.append("PACKAGECONFIG[secret] --enable-libsecret, --disable-libsecret, libsecret") + + self.check_endlines(results, expected_endlines) + + def test_packageconfig_flags_options_preferred_only(self): + results = runCmd('%s/contrib/list-packageconfig-flags.py -p' % self.scripts_dir) + expected_endlines = [] + expected_endlines.append("RECIPE NAME PACKAGECONFIG FLAGS") + expected_endlines.append("pinentry gtk2 libcap ncurses qt secret") + + self.check_endlines(results, expected_endlines) + diff --git a/external/poky/meta/lib/oeqa/selftest/cases/package.py b/external/poky/meta/lib/oeqa/selftest/cases/package.py index 0a88dc25..b87f8dc3 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/package.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/package.py @@ -1,9 +1,13 @@ +# +# SPDX-License-Identifier: MIT +# + from oeqa.selftest.case import OESelftestTestCase -from oeqa.core.decorator.oeid import OETestID from oeqa.utils.commands import bitbake, get_bb_vars, get_bb_var, runqemu import stat import subprocess, os import oe.path +import re class VersionOrdering(OESelftestTestCase): # version1, version2, sort order @@ -36,7 +40,6 @@ class VersionOrdering(OESelftestTestCase): self.bindir = type(self).bindir self.libdir = type(self).libdir - @OETestID(1880) def test_dpkg(self): for ver1, ver2, sort in self.tests: op = { -1: "<<", 0: "=", 1: ">>" }[sort] @@ -53,7 +56,6 @@ class VersionOrdering(OESelftestTestCase): status = subprocess.call((oe.path.join(self.bindir, "dpkg"), "--compare-versions", ver1, op, ver2)) self.assertNotEqual(status, 0, "%s %s %s failed" % (ver1, op, ver2)) - @OETestID(1881) def test_opkg(self): for ver1, ver2, sort in self.tests: op = { -1: "<<", 0: "=", 1: ">>" }[sort] @@ -70,7 +72,6 @@ class VersionOrdering(OESelftestTestCase): status = subprocess.call((oe.path.join(self.bindir, "opkg"), "compare-versions", ver1, op, ver2)) self.assertNotEqual(status, 0, "%s %s %s failed" % (ver1, op, ver2)) - @OETestID(1882) def test_rpm(self): # Need to tell the Python bindings where to find its configuration env = os.environ.copy() @@ -134,10 +135,10 @@ class PackageTests(OESelftestTestCase): return False # Check debugging symbols works correctly - elif "Breakpoint 1, main () at hello.c:4" in l: + elif re.match(r"Breakpoint 1.*hello\.c.*4", l): return True - self.logger.error("GDB result:\n%s: %s" % output) + self.logger.error("GDB result:\n%d: %s", status, output) return False with runqemu('core-image-minimal') as qemu: diff --git a/external/poky/meta/lib/oeqa/selftest/cases/pkgdata.py b/external/poky/meta/lib/oeqa/selftest/cases/pkgdata.py index 99117651..833a1803 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/pkgdata.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/pkgdata.py @@ -1,10 +1,13 @@ +# +# SPDX-License-Identifier: MIT +# + import os import tempfile import fnmatch from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars -from oeqa.core.decorator.oeid import OETestID class OePkgdataUtilTests(OESelftestTestCase): @@ -16,7 +19,6 @@ class OePkgdataUtilTests(OESelftestTestCase): bitbake('target-sdk-provides-dummy -c clean') bitbake('busybox zlib m4') - @OETestID(1203) def test_lookup_pkg(self): # Forward tests result = runCmd('oe-pkgdata-util lookup-pkg "zlib busybox"') @@ -35,7 +37,6 @@ class OePkgdataUtilTests(OESelftestTestCase): self.assertEqual(result.status, 1, "Status different than 1. output: %s" % result.output) self.assertEqual(result.output, 'ERROR: The following packages could not be found: nonexistentpkg') - @OETestID(1205) def test_read_value(self): result = runCmd('oe-pkgdata-util read-value PN libz1') self.assertEqual(result.output, 'zlib') @@ -45,7 +46,6 @@ class OePkgdataUtilTests(OESelftestTestCase): pkgsize = int(result.output.strip()) self.assertGreater(pkgsize, 1, "Size should be greater than 1. %s" % result.output) - @OETestID(1198) def test_find_path(self): result = runCmd('oe-pkgdata-util find-path /lib/libz.so.1') self.assertEqual(result.output, 'zlib: /lib/libz.so.1') @@ -55,7 +55,6 @@ class OePkgdataUtilTests(OESelftestTestCase): self.assertEqual(result.status, 1, "Status different than 1. output: %s" % result.output) self.assertEqual(result.output, 'ERROR: Unable to find any package producing path /not/exist') - @OETestID(1204) def test_lookup_recipe(self): result = runCmd('oe-pkgdata-util lookup-recipe "libz-staticdev busybox"') self.assertEqual(result.output, 'zlib\nbusybox') @@ -65,7 +64,6 @@ class OePkgdataUtilTests(OESelftestTestCase): self.assertEqual(result.status, 1, "Status different than 1. output: %s" % result.output) self.assertEqual(result.output, 'ERROR: The following packages could not be found: nonexistentpkg') - @OETestID(1202) def test_list_pkgs(self): # No arguments result = runCmd('oe-pkgdata-util list-pkgs') @@ -83,7 +81,7 @@ class OePkgdataUtilTests(OESelftestTestCase): pkglist.remove('zlib-ptest') # in case ptest is disabled except ValueError: pass - self.assertEqual(pkglist, ['zlib', 'zlib-dbg', 'zlib-dev', 'zlib-doc', 'zlib-staticdev'], "Packages listed after remove: %s" % result.output) + self.assertEqual(pkglist, ['zlib', 'zlib-dbg', 'zlib-dev', 'zlib-doc', 'zlib-src', 'zlib-staticdev'], "Packages listed after remove: %s" % result.output) # With recipe specified, runtime result = runCmd('oe-pkgdata-util list-pkgs -p zlib -r') pkglist = sorted(result.output.split()) @@ -91,7 +89,7 @@ class OePkgdataUtilTests(OESelftestTestCase): pkglist.remove('libz-ptest') # in case ptest is disabled except ValueError: pass - self.assertEqual(pkglist, ['libz-dbg', 'libz-dev', 'libz-doc', 'libz-staticdev', 'libz1'], "Packages listed after remove: %s" % result.output) + self.assertEqual(pkglist, ['libz-dbg', 'libz-dev', 'libz-doc', 'libz-src', 'libz-staticdev', 'libz1'], "Packages listed after remove: %s" % result.output) # With recipe specified and unpackaged result = runCmd('oe-pkgdata-util list-pkgs -p zlib -u') pkglist = sorted(result.output.split()) @@ -109,7 +107,6 @@ class OePkgdataUtilTests(OESelftestTestCase): pkglist = sorted(result.output.split()) self.assertEqual(pkglist, ['libz-dbg', 'libz-dev', 'libz-doc'], "Packages listed: %s" % result.output) - @OETestID(1201) def test_list_pkg_files(self): def splitoutput(output): files = {} @@ -199,7 +196,6 @@ class OePkgdataUtilTests(OESelftestTestCase): self.assertIn(os.path.join(mandir, 'man3/zlib.3'), files['libz-doc']) self.assertIn(os.path.join(libdir, 'libz.a'), files['libz-staticdev']) - @OETestID(1200) def test_glob(self): tempdir = tempfile.mkdtemp(prefix='pkgdataqa') self.track_for_cleanup(tempdir) @@ -219,7 +215,6 @@ class OePkgdataUtilTests(OESelftestTestCase): self.assertNotIn('libz-dev', resultlist) self.assertNotIn('libz-dbg', resultlist) - @OETestID(1206) def test_specify_pkgdatadir(self): result = runCmd('oe-pkgdata-util -p %s lookup-pkg zlib' % get_bb_var('PKGDATA_DIR')) self.assertEqual(result.output, 'libz1') diff --git a/external/poky/meta/lib/oeqa/selftest/cases/prservice.py b/external/poky/meta/lib/oeqa/selftest/cases/prservice.py index 479e5206..fe1f24ea 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/prservice.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/prservice.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + import os import re import shutil @@ -6,7 +10,6 @@ import datetime import oeqa.utils.ftools as ftools from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import runCmd, bitbake, get_bb_var -from oeqa.core.decorator.oeid import OETestID from oeqa.utils.network import get_free_port class BitbakePrTests(OESelftestTestCase): @@ -19,7 +22,7 @@ class BitbakePrTests(OESelftestTestCase): def get_pr_version(self, package_name): package_data_file = os.path.join(self.pkgdata_dir, 'runtime', package_name) package_data = ftools.read_file(package_data_file) - find_pr = re.search("PKGR: r[0-9]+\.([0-9]+)", package_data) + find_pr = re.search(r"PKGR: r[0-9]+\.([0-9]+)", package_data) self.assertTrue(find_pr, "No PKG revision found in %s" % package_data_file) return int(find_pr.group(1)) @@ -29,7 +32,7 @@ class BitbakePrTests(OESelftestTestCase): package_stamps_path = "/".join(stampdata[:-1]) stamps = [] for stamp in os.listdir(package_stamps_path): - find_stamp = re.match("%s\.%s\.([a-z0-9]{32})" % (re.escape(prefix), recipe_task), stamp) + find_stamp = re.match(r"%s\.%s\.([a-z0-9]{32})" % (re.escape(prefix), recipe_task), stamp) if find_stamp: stamps.append(find_stamp.group(1)) self.assertFalse(len(stamps) == 0, msg="Cound not find stamp for task %s for recipe %s" % (recipe_task, package_name)) @@ -88,39 +91,30 @@ class BitbakePrTests(OESelftestTestCase): self.assertTrue(pr_2 - pr_1 == 1, "Step between same pkg. revision is greater than 1") - @OETestID(930) def test_import_export_replace_db(self): self.run_test_pr_export_import('m4') - @OETestID(931) def test_import_export_override_db(self): self.run_test_pr_export_import('m4', replace_current_db=False) - @OETestID(932) def test_pr_service_rpm_arch_dep(self): self.run_test_pr_service('m4', 'rpm', 'do_package') - @OETestID(934) def test_pr_service_deb_arch_dep(self): self.run_test_pr_service('m4', 'deb', 'do_package') - @OETestID(933) def test_pr_service_ipk_arch_dep(self): self.run_test_pr_service('m4', 'ipk', 'do_package') - @OETestID(935) def test_pr_service_rpm_arch_indep(self): self.run_test_pr_service('xcursor-transparent-theme', 'rpm', 'do_package') - @OETestID(937) def test_pr_service_deb_arch_indep(self): self.run_test_pr_service('xcursor-transparent-theme', 'deb', 'do_package') - @OETestID(936) def test_pr_service_ipk_arch_indep(self): self.run_test_pr_service('xcursor-transparent-theme', 'ipk', 'do_package') - @OETestID(1419) def test_stopping_prservice_message(self): port = get_free_port() diff --git a/external/poky/meta/lib/oeqa/selftest/cases/recipetool.py b/external/poky/meta/lib/oeqa/selftest/cases/recipetool.py index 06f980e1..c2ade254 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/recipetool.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/recipetool.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + import os import shutil import tempfile @@ -5,7 +9,6 @@ import urllib.parse from oeqa.utils.commands import runCmd, bitbake, get_bb_var from oeqa.utils.commands import get_bb_vars, create_temp_layer -from oeqa.core.decorator.oeid import OETestID from oeqa.selftest.cases import devtool templayerdir = None @@ -89,7 +92,6 @@ class RecipetoolTests(RecipetoolBase): for errorstr in checkerror: self.assertIn(errorstr, result.output) - @OETestID(1177) def test_recipetool_appendfile_basic(self): # Basic test expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -97,14 +99,12 @@ class RecipetoolTests(RecipetoolBase): _, output = self._try_recipetool_appendfile('base-files', '/etc/motd', self.testfile, '', expectedlines, ['motd']) self.assertNotIn('WARNING: ', output) - @OETestID(1183) def test_recipetool_appendfile_invalid(self): # Test some commands that should error self._try_recipetool_appendfile_fail('/etc/passwd', self.testfile, ['ERROR: /etc/passwd cannot be handled by this tool', 'useradd', 'extrausers']) self._try_recipetool_appendfile_fail('/etc/timestamp', self.testfile, ['ERROR: /etc/timestamp cannot be handled by this tool']) self._try_recipetool_appendfile_fail('/dev/console', self.testfile, ['ERROR: /dev/console cannot be handled by this tool']) - @OETestID(1176) def test_recipetool_appendfile_alternatives(self): # Now try with a file we know should be an alternative # (this is very much a fake example, but one we know is reliably an alternative) @@ -128,7 +128,6 @@ class RecipetoolTests(RecipetoolBase): result = runCmd('diff -q %s %s' % (testfile2, copiedfile), ignore_status=True) self.assertNotEqual(result.status, 0, 'New file should have been copied but was not %s' % result.output) - @OETestID(1178) def test_recipetool_appendfile_binary(self): # Try appending a binary file # /bin/ls can be a symlink to /usr/bin/ls @@ -137,7 +136,6 @@ class RecipetoolTests(RecipetoolBase): self.assertIn('WARNING: ', result.output) self.assertIn('is a binary', result.output) - @OETestID(1173) def test_recipetool_appendfile_add(self): # Try arbitrary file add to a recipe expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -166,7 +164,6 @@ class RecipetoolTests(RecipetoolBase): '}\n'] self._try_recipetool_appendfile('netbase', '/usr/share/scriptname', testfile2, '-r netbase', expectedlines, ['testfile', testfile2name]) - @OETestID(1174) def test_recipetool_appendfile_add_bindir(self): # Try arbitrary file add to a recipe, this time to a location such that should be installed as executable expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -180,7 +177,6 @@ class RecipetoolTests(RecipetoolBase): _, output = self._try_recipetool_appendfile('netbase', '/usr/bin/selftest-recipetool-testbin', self.testfile, '-r netbase', expectedlines, ['testfile']) self.assertNotIn('WARNING: ', output) - @OETestID(1175) def test_recipetool_appendfile_add_machine(self): # Try arbitrary file add to a recipe, this time to a location such that should be installed as executable expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -196,7 +192,6 @@ class RecipetoolTests(RecipetoolBase): _, output = self._try_recipetool_appendfile('netbase', '/usr/share/something', self.testfile, '-r netbase -m mymachine', expectedlines, ['mymachine/testfile']) self.assertNotIn('WARNING: ', output) - @OETestID(1184) def test_recipetool_appendfile_orig(self): # A file that's in SRC_URI and in do_install with the same name expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -204,7 +199,6 @@ class RecipetoolTests(RecipetoolBase): _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-orig', self.testfile, '', expectedlines, ['selftest-replaceme-orig']) self.assertNotIn('WARNING: ', output) - @OETestID(1191) def test_recipetool_appendfile_todir(self): # A file that's in SRC_URI and in do_install with destination directory rather than file expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -212,7 +206,6 @@ class RecipetoolTests(RecipetoolBase): _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-todir', self.testfile, '', expectedlines, ['selftest-replaceme-todir']) self.assertNotIn('WARNING: ', output) - @OETestID(1187) def test_recipetool_appendfile_renamed(self): # A file that's in SRC_URI with a different name to the destination file expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -220,7 +213,6 @@ class RecipetoolTests(RecipetoolBase): _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-renamed', self.testfile, '', expectedlines, ['file1']) self.assertNotIn('WARNING: ', output) - @OETestID(1190) def test_recipetool_appendfile_subdir(self): # A file that's in SRC_URI in a subdir expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -234,7 +226,6 @@ class RecipetoolTests(RecipetoolBase): _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-subdir', self.testfile, '', expectedlines, ['testfile']) self.assertNotIn('WARNING: ', output) - @OETestID(1189) def test_recipetool_appendfile_src_glob(self): # A file that's in SRC_URI as a glob expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -248,7 +239,6 @@ class RecipetoolTests(RecipetoolBase): _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-src-globfile', self.testfile, '', expectedlines, ['testfile']) self.assertNotIn('WARNING: ', output) - @OETestID(1181) def test_recipetool_appendfile_inst_glob(self): # A file that's in do_install as a glob expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -256,7 +246,6 @@ class RecipetoolTests(RecipetoolBase): _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-inst-globfile', self.testfile, '', expectedlines, ['selftest-replaceme-inst-globfile']) self.assertNotIn('WARNING: ', output) - @OETestID(1182) def test_recipetool_appendfile_inst_todir_glob(self): # A file that's in do_install as a glob with destination as a directory expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -264,7 +253,6 @@ class RecipetoolTests(RecipetoolBase): _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-inst-todir-globfile', self.testfile, '', expectedlines, ['selftest-replaceme-inst-todir-globfile']) self.assertNotIn('WARNING: ', output) - @OETestID(1185) def test_recipetool_appendfile_patch(self): # A file that's added by a patch in SRC_URI expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -283,7 +271,6 @@ class RecipetoolTests(RecipetoolBase): else: self.fail('Patch warning not found in output:\n%s' % output) - @OETestID(1188) def test_recipetool_appendfile_script(self): # Now, a file that's in SRC_URI but installed by a script (so no mention in do_install) expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -297,7 +284,6 @@ class RecipetoolTests(RecipetoolBase): _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-scripted', self.testfile, '', expectedlines, ['testfile']) self.assertNotIn('WARNING: ', output) - @OETestID(1180) def test_recipetool_appendfile_inst_func(self): # A file that's installed from a function called by do_install expectedlines = ['FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"\n', @@ -305,7 +291,6 @@ class RecipetoolTests(RecipetoolBase): _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-inst-func', self.testfile, '', expectedlines, ['selftest-replaceme-inst-func']) self.assertNotIn('WARNING: ', output) - @OETestID(1186) def test_recipetool_appendfile_postinstall(self): # A file that's created by a postinstall script (and explicitly mentioned in it) # First try without specifying recipe @@ -321,7 +306,6 @@ class RecipetoolTests(RecipetoolBase): '}\n'] _, output = self._try_recipetool_appendfile('selftest-recipetool-appendfile', '/usr/share/selftest-replaceme-postinst', self.testfile, '-r selftest-recipetool-appendfile', expectedlines, ['testfile']) - @OETestID(1179) def test_recipetool_appendfile_extlayer(self): # Try creating a bbappend in a layer that's not in bblayers.conf and has a different structure exttemplayerdir = os.path.join(self.tempdir, 'extlayer') @@ -337,7 +321,6 @@ class RecipetoolTests(RecipetoolBase): 'metadata/recipes/recipes-test/selftest-recipetool-appendfile/selftest-recipetool-appendfile/selftest-replaceme-orig'] self.assertEqual(sorted(createdfiles), sorted(expectedfiles)) - @OETestID(1192) def test_recipetool_appendfile_wildcard(self): def try_appendfile_wc(options): @@ -362,7 +345,6 @@ class RecipetoolTests(RecipetoolBase): filename = try_appendfile_wc('-w') self.assertEqual(filename, recipefn.split('_')[0] + '_%.bbappend') - @OETestID(1193) def test_recipetool_create(self): # Try adding a recipe tempsrc = os.path.join(self.tempdir, 'srctree') @@ -379,7 +361,6 @@ class RecipetoolTests(RecipetoolBase): checkvars['SRC_URI[sha256sum]'] = '2e6a401cac9024db2288297e3be1a8ab60e7401ba8e91225218aaf4a27e82a07' self._test_recipe_contents(recipefile, checkvars, []) - @OETestID(1194) def test_recipetool_create_git(self): if 'x11' not in get_bb_var('DISTRO_FEATURES'): self.skipTest('Test requires x11 as distro feature') @@ -402,7 +383,6 @@ class RecipetoolTests(RecipetoolBase): inherits = ['autotools', 'pkgconfig'] self._test_recipe_contents(recipefile, checkvars, inherits) - @OETestID(1392) def test_recipetool_create_simple(self): # Try adding a recipe temprecipe = os.path.join(self.tempdir, 'recipe') @@ -425,27 +405,47 @@ class RecipetoolTests(RecipetoolBase): inherits = ['autotools'] self._test_recipe_contents(os.path.join(temprecipe, dirlist[0]), checkvars, inherits) - @OETestID(1418) 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_npm(self): + temprecipe = os.path.join(self.tempdir, 'recipe') + os.makedirs(temprecipe) + recipefile = os.path.join(temprecipe, 'savoirfairelinux-node-server-example_1.0.0.bb') + shrinkwrap = os.path.join(temprecipe, 'savoirfairelinux-node-server-example', 'npm-shrinkwrap.json') + srcuri = 'npm://registry.npmjs.org;package=@savoirfairelinux/node-server-example;version=1.0.0' + result = runCmd('recipetool create -o %s \'%s\'' % (temprecipe, srcuri)) + self.assertTrue(os.path.isfile(recipefile)) + self.assertTrue(os.path.isfile(shrinkwrap)) + checkvars = {} + checkvars['SUMMARY'] = 'Node Server Example' + checkvars['HOMEPAGE'] = 'https://github.com/savoirfairelinux/node-server-example#readme' + checkvars['LICENSE'] = set(['MIT', 'ISC', 'Unknown']) + urls = [] + urls.append('npm://registry.npmjs.org/;package=@savoirfairelinux/node-server-example;version=${PV}') + urls.append('npmsw://${THISDIR}/${BPN}/npm-shrinkwrap.json') + checkvars['SRC_URI'] = set(urls) + checkvars['S'] = '${WORKDIR}/npm' + checkvars['LICENSE_${PN}'] = 'MIT' + checkvars['LICENSE_${PN}-base64'] = 'Unknown' + checkvars['LICENSE_${PN}-accepts'] = 'MIT' + checkvars['LICENSE_${PN}-inherits'] = 'ISC' + inherits = ['npm'] self._test_recipe_contents(recipefile, checkvars, inherits) - @OETestID(1638) def test_recipetool_create_github(self): # Basic test to see if github URL mangling works temprecipe = os.path.join(self.tempdir, 'recipe') @@ -457,10 +457,47 @@ class RecipetoolTests(RecipetoolBase): checkvars = {} checkvars['LICENSE'] = set(['Apache-2.0']) checkvars['SRC_URI'] = 'git://github.com/mesonbuild/meson;protocol=https' - inherits = ['setuptools'] + inherits = ['setuptools3'] + self._test_recipe_contents(recipefile, checkvars, inherits) + + def test_recipetool_create_python3_setuptools(self): + # Test creating python3 package from tarball (using setuptools3 class) + temprecipe = os.path.join(self.tempdir, 'recipe') + os.makedirs(temprecipe) + pn = 'python-magic' + pv = '0.4.15' + recipefile = os.path.join(temprecipe, '%s_%s.bb' % (pn, pv)) + srcuri = 'https://files.pythonhosted.org/packages/84/30/80932401906eaf787f2e9bd86dc458f1d2e75b064b4c187341f29516945c/python-magic-%s.tar.gz' % pv + result = runCmd('recipetool create -o %s %s' % (temprecipe, srcuri)) + self.assertTrue(os.path.isfile(recipefile)) + checkvars = {} + checkvars['LICENSE'] = set(['MIT']) + checkvars['LIC_FILES_CHKSUM'] = 'file://LICENSE;md5=16a934f165e8c3245f241e77d401bb88' + checkvars['SRC_URI'] = 'https://files.pythonhosted.org/packages/84/30/80932401906eaf787f2e9bd86dc458f1d2e75b064b4c187341f29516945c/python-magic-${PV}.tar.gz' + checkvars['SRC_URI[md5sum]'] = 'e384c95a47218f66c6501cd6dd45ff59' + checkvars['SRC_URI[sha256sum]'] = 'f3765c0f582d2dfc72c15f3b5a82aecfae9498bd29ca840d72f37d7bd38bfcd5' + inherits = ['setuptools3'] + self._test_recipe_contents(recipefile, checkvars, inherits) + + def test_recipetool_create_python3_distutils(self): + # Test creating python3 package from tarball (using distutils3 class) + temprecipe = os.path.join(self.tempdir, 'recipe') + os.makedirs(temprecipe) + pn = 'docutils' + pv = '0.14' + recipefile = os.path.join(temprecipe, '%s_%s.bb' % (pn, pv)) + srcuri = 'https://files.pythonhosted.org/packages/84/f4/5771e41fdf52aabebbadecc9381d11dea0fa34e4759b4071244fa094804c/docutils-%s.tar.gz' % pv + result = runCmd('recipetool create -o %s %s' % (temprecipe, srcuri)) + self.assertTrue(os.path.isfile(recipefile)) + checkvars = {} + checkvars['LICENSE'] = set(['PSF', '&', 'BSD', 'GPL']) + checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING.txt;md5=35a23d42b615470583563132872c97d6' + checkvars['SRC_URI'] = 'https://files.pythonhosted.org/packages/84/f4/5771e41fdf52aabebbadecc9381d11dea0fa34e4759b4071244fa094804c/docutils-${PV}.tar.gz' + checkvars['SRC_URI[md5sum]'] = 'c53768d63db3873b7d452833553469de' + checkvars['SRC_URI[sha256sum]'] = '51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274' + inherits = ['distutils3'] self._test_recipe_contents(recipefile, checkvars, inherits) - @OETestID(1639) def test_recipetool_create_github_tarball(self): # Basic test to ensure github URL mangling doesn't apply to release tarballs temprecipe = os.path.join(self.tempdir, 'recipe') @@ -473,10 +510,9 @@ class RecipetoolTests(RecipetoolBase): checkvars = {} checkvars['LICENSE'] = set(['Apache-2.0']) checkvars['SRC_URI'] = 'https://github.com/mesonbuild/meson/releases/download/${PV}/meson-${PV}.tar.gz' - inherits = ['setuptools'] + inherits = ['setuptools3'] self._test_recipe_contents(recipefile, checkvars, inherits) - @OETestID(1637) def test_recipetool_create_git_http(self): # Basic test to check http git URL mangling works temprecipe = os.path.join(self.tempdir, 'recipe') @@ -498,13 +534,16 @@ class RecipetoolTests(RecipetoolBase): dstdir = os.path.join(dstdir, p) if not os.path.exists(dstdir): os.makedirs(dstdir) - self.track_for_cleanup(dstdir) + if p == "lib": + # Can race with other tests + self.add_command_to_tearDown('rmdir --ignore-fail-on-non-empty %s' % dstdir) + else: + self.track_for_cleanup(dstdir) dstfile = os.path.join(dstdir, os.path.basename(srcfile)) if srcfile != dstfile: shutil.copy(srcfile, dstfile) self.track_for_cleanup(dstfile) - @OETestID(1640) def test_recipetool_load_plugin(self): """Test that recipetool loads only the first found plugin in BBPATH.""" @@ -626,11 +665,9 @@ class RecipetoolAppendsrcBase(RecipetoolBase): class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase): - @OETestID(1273) def test_recipetool_appendsrcfile_basic(self): self._test_appendsrcfile('base-files', 'a-file') - @OETestID(1274) def test_recipetool_appendsrcfile_basic_wildcard(self): testrecipe = 'base-files' self._test_appendsrcfile(testrecipe, 'a-file', options='-w') @@ -638,15 +675,12 @@ class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase): bbappendfile = self._check_bbappend(testrecipe, recipefile, self.templayerdir) self.assertEqual(os.path.basename(bbappendfile), '%s_%%.bbappend' % testrecipe) - @OETestID(1281) def test_recipetool_appendsrcfile_subdir_basic(self): self._test_appendsrcfile('base-files', 'a-file', 'tmp') - @OETestID(1282) def test_recipetool_appendsrcfile_subdir_basic_dirdest(self): self._test_appendsrcfile('base-files', destdir='tmp') - @OETestID(1280) def test_recipetool_appendsrcfile_srcdir_basic(self): testrecipe = 'bash' bb_vars = get_bb_vars(['S', 'WORKDIR'], testrecipe) @@ -655,14 +689,12 @@ class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase): subdir = os.path.relpath(srcdir, workdir) self._test_appendsrcfile(testrecipe, 'a-file', srcdir=subdir) - @OETestID(1275) def test_recipetool_appendsrcfile_existing_in_src_uri(self): testrecipe = 'base-files' filepath = self._get_first_file_uri(testrecipe) self.assertTrue(filepath, 'Unable to test, no file:// uri found in SRC_URI for %s' % testrecipe) self._test_appendsrcfile(testrecipe, filepath, has_src_uri=False) - @OETestID(1276) def test_recipetool_appendsrcfile_existing_in_src_uri_diff_params(self): testrecipe = 'base-files' subdir = 'tmp' @@ -672,7 +704,6 @@ class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase): output = self._test_appendsrcfile(testrecipe, filepath, subdir, has_src_uri=False) self.assertTrue(any('with different parameters' in l for l in output)) - @OETestID(1277) def test_recipetool_appendsrcfile_replace_file_srcdir(self): testrecipe = 'bash' filepath = 'Makefile.in' @@ -683,9 +714,10 @@ class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase): self._test_appendsrcfile(testrecipe, filepath, srcdir=subdir) bitbake('%s:do_unpack' % testrecipe) - self.assertEqual(open(self.testfile, 'r').read(), open(os.path.join(srcdir, filepath), 'r').read()) + with open(self.testfile, 'r') as testfile: + with open(os.path.join(srcdir, filepath), 'r') as makefilein: + self.assertEqual(testfile.read(), makefilein.read()) - @OETestID(1278) def test_recipetool_appendsrcfiles_basic(self, destdir=None): newfiles = [self.testfile] for i in range(1, 5): @@ -695,6 +727,5 @@ class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase): newfiles.append(testfile) self._test_appendsrcfiles('gcc', newfiles, destdir=destdir, options='-W') - @OETestID(1279) def test_recipetool_appendsrcfiles_basic_subdir(self): self.test_recipetool_appendsrcfiles_basic(destdir='testdir') diff --git a/external/poky/meta/lib/oeqa/selftest/cases/recipeutils.py b/external/poky/meta/lib/oeqa/selftest/cases/recipeutils.py new file mode 100644 index 00000000..74787038 --- /dev/null +++ b/external/poky/meta/lib/oeqa/selftest/cases/recipeutils.py @@ -0,0 +1,140 @@ +# +# SPDX-License-Identifier: MIT +# + +import os +import re +import time +import logging +import bb.tinfoil + +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import runCmd, get_test_layer + + +def setUpModule(): + global tinfoil + global metaselftestpath + metaselftestpath = get_test_layer() + tinfoil = bb.tinfoil.Tinfoil(tracking=True) + tinfoil.prepare(config_only=False, quiet=2) + + +def tearDownModule(): + tinfoil.shutdown() + + +class RecipeUtilsTests(OESelftestTestCase): + """ Tests for the recipeutils module functions """ + + def test_patch_recipe_varflag(self): + import oe.recipeutils + rd = tinfoil.parse_recipe('python3-async-test') + vals = {'SRC_URI[md5sum]': 'aaaaaa', 'LICENSE': 'something'} + patches = oe.recipeutils.patch_recipe(rd, rd.getVar('FILE'), vals, patch=True, relpath=metaselftestpath) + + expected_patch = """ +--- a/recipes-devtools/python/python-async-test.inc ++++ b/recipes-devtools/python/python-async-test.inc +@@ -1,14 +1,14 @@ + SUMMARY = "Python framework to process interdependent tasks in a pool of workers" + HOMEPAGE = "http://github.com/gitpython-developers/async" + SECTION = "devel/python" +-LICENSE = "BSD" ++LICENSE = "something" + LIC_FILES_CHKSUM = "file://PKG-INFO;beginline=8;endline=8;md5=88df8e78b9edfd744953862179f2d14e" + + inherit pypi + + PYPI_PACKAGE = "async" + +-SRC_URI[md5sum] = "9b06b5997de2154f3bc0273f80bcef6b" ++SRC_URI[md5sum] = "aaaaaa" + SRC_URI[sha256sum] = "ac6894d876e45878faae493b0cf61d0e28ec417334448ac0a6ea2229d8343051" + + RDEPENDS_${PN} += "${PYTHON_PN}-threading" +""" + patchlines = [] + for f in patches: + for line in f: + patchlines.append(line) + self.maxDiff = None + self.assertEqual(''.join(patchlines).strip(), expected_patch.strip()) + + + def test_patch_recipe_singleappend(self): + import oe.recipeutils + rd = tinfoil.parse_recipe('recipeutils-test') + val = rd.getVar('SRC_URI', False).split() + del val[1] + val = ' '.join(val) + vals = {'SRC_URI': val} + patches = oe.recipeutils.patch_recipe(rd, rd.getVar('FILE'), vals, patch=True, relpath=metaselftestpath) + + expected_patch = """ +--- a/recipes-test/recipeutils/recipeutils-test_1.2.bb ++++ b/recipes-test/recipeutils/recipeutils-test_1.2.bb +@@ -8,6 +8,4 @@ + + BBCLASSEXTEND = "native nativesdk" + +-SRC_URI += "file://somefile" +- + SRC_URI_append = " file://anotherfile" +""" + patchlines = [] + for f in patches: + for line in f: + patchlines.append(line) + self.assertEqual(''.join(patchlines).strip(), expected_patch.strip()) + + + def test_patch_recipe_appends(self): + import oe.recipeutils + rd = tinfoil.parse_recipe('recipeutils-test') + val = rd.getVar('SRC_URI', False).split() + vals = {'SRC_URI': val[0]} + patches = oe.recipeutils.patch_recipe(rd, rd.getVar('FILE'), vals, patch=True, relpath=metaselftestpath) + + expected_patch = """ +--- a/recipes-test/recipeutils/recipeutils-test_1.2.bb ++++ b/recipes-test/recipeutils/recipeutils-test_1.2.bb +@@ -8,6 +8,3 @@ + + BBCLASSEXTEND = "native nativesdk" + +-SRC_URI += "file://somefile" +- +-SRC_URI_append = " file://anotherfile" +""" + patchlines = [] + for f in patches: + for line in f: + patchlines.append(line) + self.assertEqual(''.join(patchlines).strip(), expected_patch.strip()) + + + def test_validate_pn(self): + import oe.recipeutils + expected_results = { + 'test': '', + 'glib-2.0': '', + 'gtk+': '', + 'forcevariable': 'reserved', + 'pn-something': 'reserved', + 'test.bb': 'file', + 'test_one': 'character', + 'test!': 'character', + } + + for pn, expected in expected_results.items(): + result = oe.recipeutils.validate_pn(pn) + if expected: + self.assertIn(expected, result) + else: + self.assertEqual(result, '') + + def test_split_var_value(self): + import oe.recipeutils + res = oe.recipeutils.split_var_value('test.1 test.2 ${@call_function("hi there world", false)} test.4') + self.assertEqual(res, ['test.1', 'test.2', '${@call_function("hi there world", false)}', 'test.4']) diff --git a/external/poky/meta/lib/oeqa/selftest/cases/reproducible.py b/external/poky/meta/lib/oeqa/selftest/cases/reproducible.py new file mode 100644 index 00000000..5d3959be --- /dev/null +++ b/external/poky/meta/lib/oeqa/selftest/cases/reproducible.py @@ -0,0 +1,240 @@ +# +# SPDX-License-Identifier: MIT +# +# Copyright 2019-2020 by Garmin Ltd. or its subsidiaries + +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars +import bb.utils +import functools +import multiprocessing +import textwrap +import json +import unittest +import tempfile +import shutil +import stat +import os +import datetime + +MISSING = 'MISSING' +DIFFERENT = 'DIFFERENT' +SAME = 'SAME' + +@functools.total_ordering +class CompareResult(object): + def __init__(self): + self.reference = None + self.test = None + self.status = 'UNKNOWN' + + def __eq__(self, other): + return (self.status, self.test) == (other.status, other.test) + + def __lt__(self, other): + return (self.status, self.test) < (other.status, other.test) + +class PackageCompareResults(object): + def __init__(self): + self.total = [] + self.missing = [] + self.different = [] + self.same = [] + + 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) + else: + self.same.append(r) + + def sort(self): + self.total.sort() + self.missing.sort() + self.different.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)) + +def compare_file(reference, test, diffutils_sysroot): + result = CompareResult() + result.reference = reference + result.test = test + + if not os.path.exists(reference): + result.status = MISSING + return result + + r = runCmd(['cmp', '--quiet', reference, test], native_sysroot=diffutils_sysroot, ignore_status=True) + + if r.status: + result.status = DIFFERENT + return result + + result.status = SAME + return result + +class ReproducibleTests(OESelftestTestCase): + package_classes = ['deb', 'ipk'] + images = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline'] + save_results = False + if 'OEQA_DEBUGGING_SAVED_OUTPUT' in os.environ: + save_results = os.environ['OEQA_DEBUGGING_SAVED_OUTPUT'] + + # This variable controls if one of the test builds is allowed to pull from + # an sstate cache/mirror. The other build is always done clean as a point of + # comparison. + # If you know that your sstate archives are reproducible, enabling this + # will test that and also make the test run faster. If your sstate is not + # reproducible, disable this in your derived test class + build_from_sstate = True + + def setUpLocal(self): + super().setUpLocal() + needed_vars = ['TOPDIR', 'TARGET_PREFIX', 'BB_NUMBER_THREADS'] + bb_vars = get_bb_vars(needed_vars) + for v in needed_vars: + setattr(self, v.lower(), bb_vars[v]) + + self.extraresults = {} + self.extraresults.setdefault('reproducible.rawlogs', {})['log'] = '' + self.extraresults.setdefault('reproducible', {}).setdefault('files', {}) + + def append_to_log(self, msg): + self.extraresults['reproducible.rawlogs']['log'] += msg + + def compare_packages(self, reference_dir, test_dir, diffutils_sysroot): + result = PackageCompareResults() + + old_cwd = os.getcwd() + try: + file_result = {} + os.chdir(test_dir) + with multiprocessing.Pool(processes=int(self.bb_number_threads or 0)) as p: + for root, dirs, files in os.walk('.'): + async_result = [] + for f in files: + reference_path = os.path.join(reference_dir, root, f) + test_path = os.path.join(test_dir, root, f) + async_result.append(p.apply_async(compare_file, (reference_path, test_path, diffutils_sysroot))) + + for a in async_result: + result.add_result(a.get()) + + finally: + os.chdir(old_cwd) + + result.sort() + return result + + def write_package_list(self, package_class, name, packages): + self.extraresults['reproducible']['files'].setdefault(package_class, {})[name] = [ + {'reference': p.reference, 'test': p.test} for p in packages] + + def copy_file(self, source, dest): + bb.utils.mkdirhier(os.path.dirname(dest)) + shutil.copyfile(source, dest) + + def do_test_build(self, name, use_sstate): + capture_vars = ['DEPLOY_DIR_' + c.upper() for c in self.package_classes] + + tmpdir = os.path.join(self.topdir, name, 'tmp') + if os.path.exists(tmpdir): + bb.utils.remove(tmpdir, recurse=True) + + config = textwrap.dedent('''\ + INHERIT += "reproducible_build" + PACKAGE_CLASSES = "{package_classes}" + INHIBIT_PACKAGE_STRIP = "1" + TMPDIR = "{tmpdir}" + ''').format(package_classes=' '.join('package_%s' % c for c in self.package_classes), + tmpdir=tmpdir) + + if not use_sstate: + # This config fragment will disable using shared and the sstate + # mirror, forcing a complete build from scratch + config += textwrap.dedent('''\ + SSTATE_DIR = "${TMPDIR}/sstate" + SSTATE_MIRROR = "" + ''') + + self.write_config(config) + d = get_bb_vars(capture_vars) + bitbake(' '.join(self.images)) + return d + + def test_reproducible_builds(self): + def strip_topdir(s): + if s.startswith(self.topdir): + return s[len(self.topdir):] + return s + + # Build native utilities + self.write_config('') + bitbake("diffoscope-native diffutils-native jquery-native -c addto_recipe_sysroot") + diffutils_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "diffutils-native") + diffoscope_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "diffoscope-native") + jquery_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "jquery-native") + + if self.save_results: + os.makedirs(self.save_results, exist_ok=True) + datestr = datetime.datetime.now().strftime('%Y%m%d') + save_dir = tempfile.mkdtemp(prefix='oe-reproducible-%s-' % datestr, dir=self.save_results) + os.chmod(save_dir, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) + self.logger.info('Non-reproducible packages will be copied to %s', save_dir) + + vars_A = self.do_test_build('reproducibleA', self.build_from_sstate) + vars_B = self.do_test_build('reproducibleB', False) + + # NOTE: The temp directories from the reproducible build are purposely + # kept after the build so it can be diffed for debugging. + + fails = [] + + for c in self.package_classes: + with self.subTest(package_class=c): + package_class = 'package_' + c + + deploy_A = vars_A['DEPLOY_DIR_' + c.upper()] + deploy_B = vars_B['DEPLOY_DIR_' + c.upper()] + + result = self.compare_packages(deploy_A, deploy_B, diffutils_sysroot) + + self.logger.info('Reproducibility summary for %s: %s' % (c, result)) + + self.append_to_log('\n'.join("%s: %s" % (r.status, r.test) for r in result.total)) + + self.write_package_list(package_class, 'missing', result.missing) + self.write_package_list(package_class, 'different', result.different) + self.write_package_list(package_class, 'same', result.same) + + if self.save_results: + for d in result.different: + 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)])) + + if result.missing or result.different: + fails.append("The following %s packages are missing or different: %s" % + (c, '\n'.join(r.test for r in (result.missing + result.different)))) + + # Clean up empty directories + if self.save_results: + if not os.listdir(save_dir): + os.rmdir(save_dir) + else: + self.logger.info('Running diffoscope') + package_dir = os.path.join(save_dir, 'packages') + package_html_dir = os.path.join(package_dir, 'diff-html') + + # Copy jquery to improve the diffoscope output usability + self.copy_file(os.path.join(jquery_sysroot, 'usr/share/javascript/jquery/jquery.min.js'), os.path.join(package_html_dir, 'jquery.js')) + + runCmd(['diffoscope', '--no-default-limits', '--exclude-directory-metadata', '--html-dir', package_html_dir, 'reproducibleA', 'reproducibleB'], + native_sysroot=diffoscope_sysroot, ignore_status=True, cwd=package_dir) + + if fails: + self.fail('\n'.join(fails)) + diff --git a/external/poky/meta/lib/oeqa/selftest/cases/resulttooltests.py b/external/poky/meta/lib/oeqa/selftest/cases/resulttooltests.py index 0a089c0b..dac5c468 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/resulttooltests.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/resulttooltests.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + import os import sys basepath = os.path.abspath(os.path.dirname(__file__) + '/../../../../../') @@ -52,7 +56,7 @@ class ResultToolTests(OESelftestTestCase): 'test4': {'status': 'ERROR'}, 'test5': {'status': 'SKIPPED'}}} report = ResultsTextReport() - result_report = report.get_aggregated_test_result(None, result_data) + result_report = report.get_aggregated_test_result(None, result_data, 'DummyMachine') self.assertTrue(result_report['passed'] == 2, msg="Passed count not correct:%s" % result_report['passed']) self.assertTrue(result_report['failed'] == 2, msg="Failed count not correct:%s" % result_report['failed']) self.assertTrue(result_report['skipped'] == 1, msg="Skipped count not correct:%s" % result_report['skipped']) diff --git a/external/poky/meta/lib/oeqa/selftest/cases/runcmd.py b/external/poky/meta/lib/oeqa/selftest/cases/runcmd.py index d76d7063..a5ef1ea9 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/runcmd.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/runcmd.py @@ -1,7 +1,10 @@ +# +# SPDX-License-Identifier: MIT +# + from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import runCmd from oeqa.utils import CommandError -from oeqa.core.decorator.oeid import OETestID import subprocess import threading @@ -24,63 +27,52 @@ class RunCmdTests(OESelftestTestCase): # The delta is intentionally smaller than the timeout, to detect cases where # we incorrectly apply the timeout more than once. - TIMEOUT = 2 - DELTA = 1 + TIMEOUT = 5 + DELTA = 3 - @OETestID(1916) def test_result_okay(self): result = runCmd("true") self.assertEqual(result.status, 0) - @OETestID(1915) def test_result_false(self): result = runCmd("false", ignore_status=True) self.assertEqual(result.status, 1) - @OETestID(1917) def test_shell(self): # A shell is used for all string commands. result = runCmd("false; true", ignore_status=True) self.assertEqual(result.status, 0) - @OETestID(1910) def test_no_shell(self): self.assertRaises(FileNotFoundError, runCmd, "false; true", shell=False) - @OETestID(1906) def test_list_not_found(self): self.assertRaises(FileNotFoundError, runCmd, ["false; true"]) - @OETestID(1907) def test_list_okay(self): result = runCmd(["true"]) self.assertEqual(result.status, 0) - @OETestID(1913) def test_result_assertion(self): self.assertRaisesRegexp(AssertionError, "Command 'echo .* false' returned non-zero exit status 1:\nfoobar", runCmd, "echo foobar >&2; false", shell=True) - @OETestID(1914) def test_result_exception(self): self.assertRaisesRegexp(CommandError, "Command 'echo .* false' returned non-zero exit status 1 with output: foobar", runCmd, "echo foobar >&2; false", shell=True, assert_error=False) - @OETestID(1911) def test_output(self): result = runCmd("echo stdout; echo stderr >&2", shell=True) self.assertEqual("stdout\nstderr", result.output) self.assertEqual("", result.error) - @OETestID(1912) def test_output_split(self): result = runCmd("echo stdout; echo stderr >&2", shell=True, stderr=subprocess.PIPE) self.assertEqual("stdout", result.output) self.assertEqual("stderr", result.error) - @OETestID(1920) def test_timeout(self): numthreads = threading.active_count() start = time.time() @@ -89,9 +81,8 @@ class RunCmdTests(OESelftestTestCase): self.assertEqual(result.status, -signal.SIGTERM) end = time.time() self.assertLess(end - start, self.TIMEOUT + self.DELTA) - self.assertEqual(numthreads, threading.active_count()) + self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate())) - @OETestID(1921) def test_timeout_split(self): numthreads = threading.active_count() start = time.time() @@ -100,16 +91,15 @@ class RunCmdTests(OESelftestTestCase): self.assertEqual(result.status, -signal.SIGTERM) end = time.time() self.assertLess(end - start, self.TIMEOUT + self.DELTA) - self.assertEqual(numthreads, threading.active_count()) + self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate())) - @OETestID(1918) def test_stdin(self): numthreads = threading.active_count() result = runCmd("cat", data=b"hello world", timeout=self.TIMEOUT) self.assertEqual("hello world", result.output) - self.assertEqual(numthreads, threading.active_count()) + self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate())) + self.assertEqual(numthreads, 1) - @OETestID(1919) def test_stdin_timeout(self): numthreads = threading.active_count() start = time.time() @@ -117,16 +107,14 @@ class RunCmdTests(OESelftestTestCase): self.assertEqual(result.status, -signal.SIGTERM) end = time.time() self.assertLess(end - start, self.TIMEOUT + self.DELTA) - self.assertEqual(numthreads, threading.active_count()) + self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate())) - @OETestID(1908) def test_log(self): log = MemLogger() result = runCmd("echo stdout; echo stderr >&2", shell=True, output_log=log) self.assertEqual(["Running: echo stdout; echo stderr >&2", "stdout", "stderr"], log.info_msgs) self.assertEqual([], log.error_msgs) - @OETestID(1909) def test_log_split(self): log = MemLogger() result = runCmd("echo stdout; echo stderr >&2", shell=True, output_log=log, stderr=subprocess.PIPE) diff --git a/external/poky/meta/lib/oeqa/selftest/cases/runqemu.py b/external/poky/meta/lib/oeqa/selftest/cases/runqemu.py index f69d4706..7e676bcb 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/runqemu.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/runqemu.py @@ -1,14 +1,16 @@ # # Copyright (c) 2017 Wind River Systems, Inc. # +# SPDX-License-Identifier: MIT +# import re import tempfile import time import oe.types +from oeqa.core.decorator import OETestTag from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import bitbake, runqemu, get_bb_var, runCmd -from oeqa.core.decorator.oeid import OETestID class RunqemuTests(OESelftestTestCase): """Runqemu test class""" @@ -42,7 +44,6 @@ SYSLINUX_TIMEOUT = "10" bitbake(self.recipe) RunqemuTests.image_is_ready = True - @OETestID(2001) def test_boot_machine(self): """Test runqemu machine""" cmd = "%s %s" % (self.cmd_common, self.machine) @@ -50,7 +51,6 @@ SYSLINUX_TIMEOUT = "10" with open(qemu.qemurunnerlog) as f: self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read())) - @OETestID(2002) def test_boot_machine_ext4(self): """Test runqemu machine ext4""" cmd = "%s %s ext4" % (self.cmd_common, self.machine) @@ -58,7 +58,6 @@ SYSLINUX_TIMEOUT = "10" with open(qemu.qemurunnerlog) as f: self.assertIn('rootfs.ext4', f.read(), "Failed: %s" % cmd) - @OETestID(2003) def test_boot_machine_iso(self): """Test runqemu machine iso""" cmd = "%s %s iso" % (self.cmd_common, self.machine) @@ -66,7 +65,6 @@ SYSLINUX_TIMEOUT = "10" with open(qemu.qemurunnerlog) as f: self.assertIn('media=cdrom', f.read(), "Failed: %s" % cmd) - @OETestID(2004) def test_boot_recipe_image(self): """Test runqemu recipe-image""" cmd = "%s %s" % (self.cmd_common, self.recipe) @@ -75,7 +73,6 @@ SYSLINUX_TIMEOUT = "10" self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read())) - @OETestID(2005) def test_boot_recipe_image_vmdk(self): """Test runqemu recipe-image vmdk""" cmd = "%s %s wic.vmdk" % (self.cmd_common, self.recipe) @@ -83,7 +80,6 @@ SYSLINUX_TIMEOUT = "10" with open(qemu.qemurunnerlog) as f: self.assertIn('format=vmdk', f.read(), "Failed: %s" % cmd) - @OETestID(2006) def test_boot_recipe_image_vdi(self): """Test runqemu recipe-image vdi""" cmd = "%s %s wic.vdi" % (self.cmd_common, self.recipe) @@ -91,7 +87,6 @@ SYSLINUX_TIMEOUT = "10" with open(qemu.qemurunnerlog) as f: self.assertIn('format=vdi', f.read(), "Failed: %s" % cmd) - @OETestID(2007) def test_boot_deploy(self): """Test runqemu deploy_dir_image""" cmd = "%s %s" % (self.cmd_common, self.deploy_dir_image) @@ -100,7 +95,6 @@ SYSLINUX_TIMEOUT = "10" self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read())) - @OETestID(2008) def test_boot_deploy_hddimg(self): """Test runqemu deploy_dir_image hddimg""" cmd = "%s %s hddimg" % (self.cmd_common, self.deploy_dir_image) @@ -108,7 +102,6 @@ SYSLINUX_TIMEOUT = "10" with open(qemu.qemurunnerlog) as f: self.assertTrue(re.search('file=.*.hddimg', f.read()), "Failed: %s, %s" % (cmd, f.read())) - @OETestID(2009) def test_boot_machine_slirp(self): """Test runqemu machine slirp""" cmd = "%s slirp %s" % (self.cmd_common, self.machine) @@ -116,7 +109,6 @@ SYSLINUX_TIMEOUT = "10" with open(qemu.qemurunnerlog) as f: self.assertIn(' -netdev user', f.read(), "Failed: %s" % cmd) - @OETestID(2009) def test_boot_machine_slirp_qcow2(self): """Test runqemu machine slirp qcow2""" cmd = "%s slirp wic.qcow2 %s" % (self.cmd_common, self.machine) @@ -124,7 +116,6 @@ SYSLINUX_TIMEOUT = "10" with open(qemu.qemurunnerlog) as f: self.assertIn('format=qcow2', f.read(), "Failed: %s" % cmd) - @OETestID(2010) def test_boot_qemu_boot(self): """Test runqemu /path/to/image.qemuboot.conf""" qemuboot_conf = "%s-%s.qemuboot.conf" % (self.recipe, self.machine) @@ -136,7 +127,6 @@ SYSLINUX_TIMEOUT = "10" with open(qemu.qemurunnerlog) as f: self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read())) - @OETestID(2011) def test_boot_rootfs(self): """Test runqemu /path/to/rootfs.ext4""" rootfs = "%s-%s.ext4" % (self.recipe, self.machine) @@ -158,6 +148,7 @@ SYSLINUX_TIMEOUT = "10" # dedicated for MACHINE=qemux86-64 where it test that qemux86-64 will # bootup various filesystem types, including live image(iso and hddimg) # where live image was not supported on all qemu architecture. +@OETestTag("machine") class QemuTest(OESelftestTestCase): @classmethod diff --git a/external/poky/meta/lib/oeqa/selftest/cases/runtime_test.py b/external/poky/meta/lib/oeqa/selftest/cases/runtime_test.py index 906e460d..60cb2e01 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/runtime_test.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/runtime_test.py @@ -1,11 +1,16 @@ +# +# SPDX-License-Identifier: MIT +# + from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, runqemu from oeqa.utils.sshcontrol import SSHControl -from oeqa.core.decorator.oeid import OETestID import os import re import tempfile import shutil +import oe.lsb +from oeqa.core.decorator.data import skipIfNotQemu class TestExport(OESelftestTestCase): @@ -14,7 +19,6 @@ class TestExport(OESelftestTestCase): runCmd("rm -rf /tmp/sdk") super(TestExport, cls).tearDownClass() - @OETestID(1499) def test_testexport_basic(self): """ Summary: Check basic testexport functionality with only ping test enabled. @@ -54,7 +58,6 @@ class TestExport(OESelftestTestCase): # Verify ping test was succesful self.assertEqual(0, result.status, 'oe-test runtime returned a non 0 status') - @OETestID(1641) def test_testexport_sdk(self): """ Summary: Check sdk functionality for testexport. @@ -109,7 +112,6 @@ class TestExport(OESelftestTestCase): class TestImage(OESelftestTestCase): - @OETestID(1644) def test_testimage_install(self): """ Summary: Check install packages functionality for testimage/testexport. @@ -130,7 +132,6 @@ class TestImage(OESelftestTestCase): bitbake('core-image-full-cmdline socat') bitbake('-c testimage core-image-full-cmdline') - @OETestID(1883) def test_testimage_dnf(self): """ Summary: Check package feeds functionality for dnf @@ -153,6 +154,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,13 +167,124 @@ 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_sdl(self): + """ + Summary: Check host-assisted accelerate OpenGL functionality in qemu with gtk and SDL frontends + Expected: 1. Check that virgl kernel driver is loaded and 3d acceleration is enabled + 2. Check that kmscube demo runs without crashing. + Product: oe-core + Author: Alexander Kanavin + """ + if "DISPLAY" not in os.environ: + self.skipTest("virgl gtk test must be run inside a X session") + distro = oe.lsb.distro_identifier() + if distro and distro == 'debian-8': + self.skipTest('virgl isn\'t working with Debian 8') + if distro and distro == 'centos-7': + self.skipTest('virgl isn\'t working with Centos 7') + if distro and distro == 'opensuseleap-15.0': + self.skipTest('virgl isn\'t working with Opensuse 15.0') + + qemu_packageconfig = get_bb_var('PACKAGECONFIG', 'qemu-system-native') + sdl_packageconfig = get_bb_var('PACKAGECONFIG', 'libsdl2-native') + features = 'INHERIT += "testimage"\n' + if 'gtk+' not in qemu_packageconfig: + features += 'PACKAGECONFIG_append_pn-qemu-system-native = " gtk+"\n' + if 'sdl' not in qemu_packageconfig: + features += 'PACKAGECONFIG_append_pn-qemu-system-native = " sdl"\n' + if 'virglrenderer' not in qemu_packageconfig: + features += 'PACKAGECONFIG_append_pn-qemu-system-native = " virglrenderer"\n' + if 'glx' not in qemu_packageconfig: + features += 'PACKAGECONFIG_append_pn-qemu-system-native = " glx"\n' + if 'opengl' not in sdl_packageconfig: + features += 'PACKAGECONFIG_append_pn-libsdl2-native = " opengl"\n' + features += 'TEST_SUITES = "ping ssh virgl"\n' + features += 'IMAGE_FEATURES_append = " ssh-server-dropbear"\n' + features += 'IMAGE_INSTALL_append = " kmscube"\n' + features_gtk = features + 'TEST_RUNQEMUPARAMS = "gtk gl"\n' + self.write_config(features_gtk) + bitbake('core-image-minimal') + bitbake('-c testimage core-image-minimal') + features_sdl = features + 'TEST_RUNQEMUPARAMS = "sdl gl"\n' + self.write_config(features_sdl) + bitbake('core-image-minimal') + bitbake('-c testimage core-image-minimal') + + def test_testimage_virgl_headless(self): + """ + Summary: Check host-assisted accelerate OpenGL functionality in qemu with egl-headless frontend + Expected: 1. Check that virgl kernel driver is loaded and 3d acceleration is enabled + 2. Check that kmscube demo runs without crashing. + Product: oe-core + Author: Alexander Kanavin + """ + import subprocess, os + try: + content = os.listdir("/dev/dri") + if len([i for i in content if i.startswith('render')]) == 0: + self.skipTest("No render nodes found in /dev/dri: %s" %(content)) + except FileNotFoundError: + self.skipTest("/dev/dri directory does not exist; no render nodes available on this machine.") + try: + dripath = subprocess.check_output("pkg-config --variable=dridriverdir dri", shell=True) + except subprocess.CalledProcessError as e: + self.skipTest("Could not determine the path to dri drivers on the host via pkg-config.\nPlease install Mesa development files (particularly, dri.pc) on the host machine.") + qemu_packageconfig = get_bb_var('PACKAGECONFIG', 'qemu-system-native') + features = 'INHERIT += "testimage"\n' + if 'virglrenderer' not in qemu_packageconfig: + features += 'PACKAGECONFIG_append_pn-qemu-system-native = " virglrenderer"\n' + if 'glx' not in qemu_packageconfig: + features += 'PACKAGECONFIG_append_pn-qemu-system-native = " glx"\n' + features += 'TEST_SUITES = "ping ssh virgl"\n' + features += 'IMAGE_FEATURES_append = " ssh-server-dropbear"\n' + features += 'IMAGE_INSTALL_append = " kmscube"\n' + features += 'TEST_RUNQEMUPARAMS = "egl-headless"\n' + self.write_config(features) + bitbake('core-image-minimal') + bitbake('-c testimage core-image-minimal') class Postinst(OESelftestTestCase): - @OETestID(1540) - @OETestID(1545) - def test_postinst_rootfs_and_boot(self): + + def init_manager_loop(self, init_manager): + import oe.path + + vars = get_bb_vars(("IMAGE_ROOTFS", "sysconfdir"), "core-image-minimal") + rootfs = vars["IMAGE_ROOTFS"] + self.assertIsNotNone(rootfs) + sysconfdir = vars["sysconfdir"] + self.assertIsNotNone(sysconfdir) + # Need to use oe.path here as sysconfdir starts with / + hosttestdir = oe.path.join(rootfs, sysconfdir, "postinst-test") + targettestdir = os.path.join(sysconfdir, "postinst-test") + + for classes in ("package_rpm", "package_deb", "package_ipk"): + with self.subTest(init_manager=init_manager, package_class=classes): + features = 'CORE_IMAGE_EXTRA_INSTALL = "postinst-delayed-b"\n' + features += 'IMAGE_FEATURES += "package-management empty-root-password"\n' + features += 'PACKAGE_CLASSES = "%s"\n' % classes + if init_manager == "systemd": + features += 'DISTRO_FEATURES_append = " systemd"\n' + features += 'VIRTUAL-RUNTIME_init_manager = "systemd"\n' + features += 'DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"\n' + features += 'VIRTUAL-RUNTIME_initscripts = ""\n' + self.write_config(features) + + bitbake('core-image-minimal') + + self.assertTrue(os.path.isfile(os.path.join(hosttestdir, "rootfs")), + "rootfs state file was not created") + + with runqemu('core-image-minimal') as qemu: + # Make the test echo a string and search for that as + # run_serial()'s status code is useless.' + for filename in ("rootfs", "delayed-a", "delayed-b"): + status, output = qemu.run_serial("test -f %s && echo found" % os.path.join(targettestdir, filename)) + self.assertEqual(output, "found", "%s was not present on boot" % filename) + + + + @skipIfNotQemu('qemuall', 'Test only runs in qemu') + def test_postinst_rootfs_and_boot_sysvinit(self): """ Summary: The purpose of this test case is to verify Post-installation scripts are called when rootfs is created and also test @@ -185,46 +298,32 @@ class Postinst(OESelftestTestCase): created by postinst_boot recipe is present on image. Expected: The files are successfully created during rootfs and boot time for 3 different package managers: rpm,ipk,deb and - for initialization managers: sysvinit and systemd. + for initialization managers: sysvinit. """ + self.init_manager_loop("sysvinit") - import oe.path - vars = get_bb_vars(("IMAGE_ROOTFS", "sysconfdir"), "core-image-minimal") - rootfs = vars["IMAGE_ROOTFS"] - self.assertIsNotNone(rootfs) - sysconfdir = vars["sysconfdir"] - self.assertIsNotNone(sysconfdir) - # Need to use oe.path here as sysconfdir starts with / - hosttestdir = oe.path.join(rootfs, sysconfdir, "postinst-test") - targettestdir = os.path.join(sysconfdir, "postinst-test") - - for init_manager in ("sysvinit", "systemd"): - for classes in ("package_rpm", "package_deb", "package_ipk"): - with self.subTest(init_manager=init_manager, package_class=classes): - features = 'CORE_IMAGE_EXTRA_INSTALL = "postinst-delayed-b"\n' - features += 'IMAGE_FEATURES += "package-management empty-root-password"\n' - features += 'PACKAGE_CLASSES = "%s"\n' % classes - if init_manager == "systemd": - features += 'DISTRO_FEATURES_append = " systemd"\n' - features += 'VIRTUAL-RUNTIME_init_manager = "systemd"\n' - features += 'DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"\n' - features += 'VIRTUAL-RUNTIME_initscripts = ""\n' - self.write_config(features) - - bitbake('core-image-minimal') - - self.assertTrue(os.path.isfile(os.path.join(hosttestdir, "rootfs")), - "rootfs state file was not created") + @skipIfNotQemu('qemuall', 'Test only runs in qemu') + def test_postinst_rootfs_and_boot_systemd(self): + """ + Summary: The purpose of this test case is to verify Post-installation + scripts are called when rootfs is created and also test + that script can be delayed to run at first boot. + Dependencies: NA + Steps: 1. Add proper configuration to local.conf file + 2. Build a "core-image-minimal" image + 3. Verify that file created by postinst_rootfs recipe is + present on rootfs dir. + 4. Boot the image created on qemu and verify that the file + created by postinst_boot recipe is present on image. + Expected: The files are successfully created during rootfs and boot + time for 3 different package managers: rpm,ipk,deb and + for initialization managers: systemd. - with runqemu('core-image-minimal') as qemu: - # Make the test echo a string and search for that as - # run_serial()'s status code is useless.' - for filename in ("rootfs", "delayed-a", "delayed-b"): - status, output = qemu.run_serial("test -f %s && echo found" % os.path.join(targettestdir, filename)) - self.assertEqual(output, "found", "%s was not present on boot" % filename) + """ + self.init_manager_loop("systemd") def test_failing_postinst(self): @@ -261,3 +360,80 @@ class Postinst(OESelftestTestCase): self.assertFalse(os.path.isfile(os.path.join(hosttestdir, "rootfs-after-failure")), "rootfs-after-failure file was created") +class SystemTap(OESelftestTestCase): + """ + Summary: The purpose of this test case is to verify native crosstap + works while talking to a target. + Expected: The script should successfully connect to the qemu machine + and run some systemtap examples on a qemu machine. + """ + + @classmethod + def setUpClass(cls): + super(SystemTap, cls).setUpClass() + cls.image = "core-image-minimal" + + def default_config(self): + return """ +# These aren't the actual IP addresses but testexport class needs something defined +TEST_SERVER_IP = "192.168.7.1" +TEST_TARGET_IP = "192.168.7.2" + +EXTRA_IMAGE_FEATURES += "tools-profile dbg-pkgs" +IMAGE_FEATURES_append = " ssh-server-dropbear" + +# enables kernel debug symbols +KERNEL_EXTRA_FEATURES_append = " features/debug/debug-kernel.scc" +KERNEL_EXTRA_FEATURES_append = " features/systemtap/systemtap.scc" + +# add systemtap run-time into target image if it is not there yet +IMAGE_INSTALL_append = " systemtap" +""" + + def test_crosstap_helloworld(self): + self.write_config(self.default_config()) + bitbake('systemtap-native') + systemtap_examples = os.path.join(get_bb_var("WORKDIR","systemtap-native"), "usr/share/systemtap/examples") + bitbake(self.image) + + with runqemu(self.image) as qemu: + cmd = "crosstap -r root@192.168.7.2 -s %s/general/helloworld.stp " % systemtap_examples + result = runCmd(cmd) + self.assertEqual(0, result.status, 'crosstap helloworld returned a non 0 status:%s' % result.output) + + def test_crosstap_pstree(self): + self.write_config(self.default_config()) + + bitbake('systemtap-native') + systemtap_examples = os.path.join(get_bb_var("WORKDIR","systemtap-native"), "usr/share/systemtap/examples") + bitbake(self.image) + + with runqemu(self.image) as qemu: + cmd = "crosstap -r root@192.168.7.2 -s %s/process/pstree.stp" % systemtap_examples + result = runCmd(cmd) + self.assertEqual(0, result.status, 'crosstap pstree returned a non 0 status:%s' % result.output) + + def test_crosstap_syscalls_by_proc(self): + self.write_config(self.default_config()) + + bitbake('systemtap-native') + systemtap_examples = os.path.join(get_bb_var("WORKDIR","systemtap-native"), "usr/share/systemtap/examples") + bitbake(self.image) + + with runqemu(self.image) as qemu: + cmd = "crosstap -r root@192.168.7.2 -s %s/process/ syscalls_by_proc.stp" % systemtap_examples + result = runCmd(cmd) + self.assertEqual(0, result.status, 'crosstap syscalls_by_proc returned a non 0 status:%s' % result.output) + + def test_crosstap_syscalls_by_pid(self): + self.write_config(self.default_config()) + + bitbake('systemtap-native') + systemtap_examples = os.path.join(get_bb_var("WORKDIR","systemtap-native"), "usr/share/systemtap/examples") + bitbake(self.image) + + with runqemu(self.image) as qemu: + cmd = "crosstap -r root@192.168.7.2 -s %s/process/ syscalls_by_pid.stp" % systemtap_examples + result = runCmd(cmd) + self.assertEqual(0, result.status, 'crosstap syscalls_by_pid returned a non 0 status:%s' % result.output) + diff --git a/external/poky/meta/lib/oeqa/selftest/cases/selftest.py b/external/poky/meta/lib/oeqa/selftest/cases/selftest.py index 4b3cb144..af080dcf 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/selftest.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/selftest.py @@ -1,12 +1,14 @@ +# +# SPDX-License-Identifier: MIT +# + import importlib from oeqa.utils.commands import runCmd import oeqa.selftest from oeqa.selftest.case import OESelftestTestCase -from oeqa.core.decorator.oeid import OETestID class ExternalLayer(OESelftestTestCase): - @OETestID(1885) def test_list_imported(self): """ Summary: Checks functionality to import tests from other layers. diff --git a/external/poky/meta/lib/oeqa/selftest/cases/signing.py b/external/poky/meta/lib/oeqa/selftest/cases/signing.py index 4fa99acb..202d5499 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/signing.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/signing.py @@ -1,5 +1,9 @@ +# +# SPDX-License-Identifier: MIT +# + from oeqa.selftest.case import OESelftestTestCase -from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars +from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, create_temp_layer import os import oe import glob @@ -7,7 +11,6 @@ import re import shutil import tempfile from contextlib import contextmanager -from oeqa.core.decorator.oeid import OETestID from oeqa.utils.ftools import write_file @@ -27,7 +30,8 @@ class Signing(OESelftestTestCase): self.secret_key_path = os.path.join(self.testlayer_path, 'files', 'signing', "key.secret") nsysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "gnupg-native") - runCmd('gpg --batch --homedir %s --import %s %s' % (self.gpg_dir, self.pub_key_path, self.secret_key_path), native_sysroot=nsysroot) + + runCmd('gpg --agent-program=`which gpg-agent`\|--auto-expand-secmem --batch --homedir %s --import %s %s' % (self.gpg_dir, self.pub_key_path, self.secret_key_path), native_sysroot=nsysroot) return nsysroot + get_bb_var("bindir_native") @@ -51,7 +55,6 @@ class Signing(OESelftestTestCase): os.environ[e] = origenv[e] os.chdir(builddir) - @OETestID(1362) def test_signing_packages(self): """ Summary: Test that packages can be signed in the package feed @@ -116,7 +119,6 @@ class Signing(OESelftestTestCase): bitbake('core-image-minimal') - @OETestID(1382) def test_signing_sstate_archive(self): """ Summary: Test that sstate archives can be signed @@ -155,8 +157,8 @@ class Signing(OESelftestTestCase): bitbake('-c clean %s' % test_recipe) bitbake('-c populate_lic %s' % test_recipe) - recipe_sig = glob.glob(sstatedir + '/*/*:ed:*_populate_lic.tgz.sig') - recipe_tgz = glob.glob(sstatedir + '/*/*:ed:*_populate_lic.tgz') + recipe_sig = glob.glob(sstatedir + '/*/*/*:ed:*_populate_lic.tgz.sig') + recipe_tgz = glob.glob(sstatedir + '/*/*/*:ed:*_populate_lic.tgz') self.assertEqual(len(recipe_sig), 1, 'Failed to find .sig file.') self.assertEqual(len(recipe_tgz), 1, 'Failed to find .tgz file.') @@ -169,7 +171,6 @@ class Signing(OESelftestTestCase): class LockedSignatures(OESelftestTestCase): - @OETestID(1420) def test_locked_signatures(self): """ Summary: Test locked signature mechanism @@ -179,11 +180,11 @@ class LockedSignatures(OESelftestTestCase): AutomatedBy: Daniel Istrate """ + import uuid + test_recipe = 'ed' locked_sigs_file = 'locked-sigs.inc' - self.add_command_to_tearDown('rm -f %s' % os.path.join(self.builddir, locked_sigs_file)) - bitbake(test_recipe) # Generate locked sigs include file bitbake('-S none %s' % test_recipe) @@ -195,21 +196,29 @@ class LockedSignatures(OESelftestTestCase): # Build a locked recipe bitbake(test_recipe) + templayerdir = tempfile.mkdtemp(prefix='signingqa') + create_temp_layer(templayerdir, 'selftestsigning') + runCmd('bitbake-layers add-layer %s' % templayerdir) + # Make a change that should cause the locked task signature to change + # Use uuid so hash equivalance server isn't triggered recipe_append_file = test_recipe + '_' + get_bb_var('PV', test_recipe) + '.bbappend' - recipe_append_path = os.path.join(self.testlayer_path, 'recipes-test', test_recipe, recipe_append_file) - feature = 'SUMMARY += "test locked signature"\n' + recipe_append_path = os.path.join(templayerdir, 'recipes-test', test_recipe, recipe_append_file) + feature = 'SUMMARY_${PN} = "test locked signature%s"\n' % uuid.uuid4() - os.mkdir(os.path.join(self.testlayer_path, 'recipes-test', test_recipe)) + os.mkdir(os.path.join(templayerdir, 'recipes-test')) + os.mkdir(os.path.join(templayerdir, 'recipes-test', test_recipe)) write_file(recipe_append_path, feature) - self.add_command_to_tearDown('rm -rf %s' % os.path.join(self.testlayer_path, 'recipes-test', test_recipe)) + self.add_command_to_tearDown('bitbake-layers remove-layer %s' % templayerdir) + self.add_command_to_tearDown('rm -f %s' % os.path.join(self.builddir, locked_sigs_file)) + self.add_command_to_tearDown('rm -rf %s' % templayerdir) # Build the recipe again ret = bitbake(test_recipe) # Verify you get the warning and that the real task *isn't* run (i.e. the locked signature has worked) - patt = r'WARNING: The %s:do_package sig is computed to be \S+, but the sig is locked to \S+ in SIGGEN_LOCKEDSIGS\S+' % test_recipe + patt = r'The %s:do_package sig is computed to be \S+, but the sig is locked to \S+ in SIGGEN_LOCKEDSIGS\S+' % test_recipe found_warn = re.search(patt, ret.output) self.assertIsNotNone(found_warn, "Didn't find the expected warning message. Output: %s" % ret.output) diff --git a/external/poky/meta/lib/oeqa/selftest/cases/sstate.py b/external/poky/meta/lib/oeqa/selftest/cases/sstate.py index bc2fdbd8..80ce9e35 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/sstate.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/sstate.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + import datetime import unittest import os @@ -52,11 +56,11 @@ class SStateBase(OESelftestTestCase): def search_sstate(self, filename_regex, distro_specific=True, distro_nonspecific=True): result = [] for root, dirs, files in os.walk(self.sstate_path): - if distro_specific and re.search("%s/[a-z0-9]{2}$" % self.hostdistro, root): + if distro_specific and re.search(r"%s/%s/[a-z0-9]{2}/[a-z0-9]{2}$" % (self.sstate_path, self.hostdistro), root): for f in files: if re.search(filename_regex, f): result.append(f) - if distro_nonspecific and re.search("%s/[a-z0-9]{2}$" % self.sstate_path, root): + if distro_nonspecific and re.search(r"%s/[a-z0-9]{2}/[a-z0-9]{2}$" % self.sstate_path, root): for f in files: if re.search(filename_regex, f): result.append(f) diff --git a/external/poky/meta/lib/oeqa/selftest/cases/sstatetests.py b/external/poky/meta/lib/oeqa/selftest/cases/sstatetests.py index 077d6e53..c46e8ba4 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/sstatetests.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/sstatetests.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + import os import shutil import glob @@ -7,7 +11,6 @@ import tempfile from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_test_layer, create_temp_layer from oeqa.selftest.cases.sstate import SStateBase -from oeqa.core.decorator.oeid import OETestID import bb.siggen @@ -16,10 +19,13 @@ class SStateTests(SStateBase): # Test that a git repository which changes is correctly handled by SRCREV = ${AUTOREV} # when PV does not contain SRCPV - tempdir = tempfile.mkdtemp(prefix='oeqa') + tempdir = tempfile.mkdtemp(prefix='sstate_autorev') + tempdldir = tempfile.mkdtemp(prefix='sstate_autorev_dldir') self.track_for_cleanup(tempdir) + self.track_for_cleanup(tempdldir) create_temp_layer(tempdir, 'selftestrecipetool') self.add_command_to_tearDown('bitbake-layers remove-layer %s' % tempdir) + self.append_config("DL_DIR = \"%s\"" % tempdldir) runCmd('bitbake-layers add-layer %s' % tempdir) # Use dbus-wait as a local git repo we can add a commit between two builds in @@ -73,19 +79,15 @@ class SStateTests(SStateBase): else: self.assertTrue(not file_tracker , msg="Found sstate files in the wrong place for: %s (found %s)" % (', '.join(map(str, targets)), str(file_tracker))) - @OETestID(975) def test_sstate_creation_distro_specific_pass(self): self.run_test_sstate_creation(['binutils-cross-'+ self.tune_arch, 'binutils-native'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True) - @OETestID(1374) def test_sstate_creation_distro_specific_fail(self): self.run_test_sstate_creation(['binutils-cross-'+ self.tune_arch, 'binutils-native'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True, should_pass=False) - @OETestID(976) def test_sstate_creation_distro_nonspecific_pass(self): self.run_test_sstate_creation(['linux-libc-headers'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True) - @OETestID(1375) def test_sstate_creation_distro_nonspecific_fail(self): self.run_test_sstate_creation(['linux-libc-headers'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True, should_pass=False) @@ -96,27 +98,24 @@ class SStateTests(SStateBase): bitbake(['-ccleansstate'] + targets) bitbake(targets) - tgz_created = self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific, distro_nonspecific) + tgz_created = self.search_sstate('|'.join(map(str, [s + r'.*?\.tgz$' for s in targets])), distro_specific, distro_nonspecific) self.assertTrue(tgz_created, msg="Could not find sstate .tgz files for: %s (%s)" % (', '.join(map(str, targets)), str(tgz_created))) - siginfo_created = self.search_sstate('|'.join(map(str, [s + '.*?\.siginfo$' for s in targets])), distro_specific, distro_nonspecific) + siginfo_created = self.search_sstate('|'.join(map(str, [s + r'.*?\.siginfo$' for s in targets])), distro_specific, distro_nonspecific) self.assertTrue(siginfo_created, msg="Could not find sstate .siginfo files for: %s (%s)" % (', '.join(map(str, targets)), str(siginfo_created))) bitbake(['-ccleansstate'] + targets) - tgz_removed = self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific, distro_nonspecific) + tgz_removed = self.search_sstate('|'.join(map(str, [s + r'.*?\.tgz$' for s in targets])), distro_specific, distro_nonspecific) self.assertTrue(not tgz_removed, msg="do_cleansstate didn't remove .tgz sstate files for: %s (%s)" % (', '.join(map(str, targets)), str(tgz_removed))) - @OETestID(977) def test_cleansstate_task_distro_specific_nonspecific(self): targets = ['binutils-cross-'+ self.tune_arch, 'binutils-native'] targets.append('linux-libc-headers') self.run_test_cleansstate_task(targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True) - @OETestID(1376) def test_cleansstate_task_distro_nonspecific(self): self.run_test_cleansstate_task(['linux-libc-headers'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True) - @OETestID(1377) def test_cleansstate_task_distro_specific(self): targets = ['binutils-cross-'+ self.tune_arch, 'binutils-native'] targets.append('linux-libc-headers') @@ -130,14 +129,14 @@ class SStateTests(SStateBase): bitbake(['-ccleansstate'] + targets) bitbake(targets) - results = self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific=False, distro_nonspecific=True) + results = self.search_sstate('|'.join(map(str, [s + r'.*?\.tgz$' for s in targets])), distro_specific=False, distro_nonspecific=True) filtered_results = [] for r in results: if r.endswith(("_populate_lic.tgz", "_populate_lic.tgz.siginfo")): continue filtered_results.append(r) self.assertTrue(filtered_results == [], msg="Found distro non-specific sstate for: %s (%s)" % (', '.join(map(str, targets)), str(filtered_results))) - file_tracker_1 = self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific=True, distro_nonspecific=False) + file_tracker_1 = self.search_sstate('|'.join(map(str, [s + r'.*?\.tgz$' for s in targets])), distro_specific=True, distro_nonspecific=False) self.assertTrue(len(file_tracker_1) >= len(targets), msg = "Not all sstate files ware created for: %s" % ', '.join(map(str, targets))) self.track_for_cleanup(self.distro_specific_sstate + "_old") @@ -146,7 +145,7 @@ class SStateTests(SStateBase): bitbake(['-cclean'] + targets) bitbake(targets) - file_tracker_2 = self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific=True, distro_nonspecific=False) + file_tracker_2 = self.search_sstate('|'.join(map(str, [s + r'.*?\.tgz$' for s in targets])), distro_specific=True, distro_nonspecific=False) self.assertTrue(len(file_tracker_2) >= len(targets), msg = "Not all sstate files ware created for: %s" % ', '.join(map(str, targets))) not_recreated = [x for x in file_tracker_1 if x not in file_tracker_2] @@ -155,15 +154,12 @@ class SStateTests(SStateBase): created_once = [x for x in file_tracker_2 if x not in file_tracker_1] self.assertTrue(created_once == [], msg="The following sstate files ware created only in the second run: %s" % ', '.join(map(str, created_once))) - @OETestID(175) def test_rebuild_distro_specific_sstate_cross_native_targets(self): self.run_test_rebuild_distro_specific_sstate(['binutils-cross-' + self.tune_arch, 'binutils-native'], temp_sstate_location=True) - @OETestID(1372) def test_rebuild_distro_specific_sstate_cross_target(self): self.run_test_rebuild_distro_specific_sstate(['binutils-cross-' + self.tune_arch], temp_sstate_location=True) - @OETestID(1373) def test_rebuild_distro_specific_sstate_native_target(self): self.run_test_rebuild_distro_specific_sstate(['binutils-native'], temp_sstate_location=True) @@ -192,25 +188,24 @@ class SStateTests(SStateBase): if not sstate_arch in sstate_archs_list: sstate_archs_list.append(sstate_arch) if target_config[idx] == target_config[-1]: - target_sstate_before_build = self.search_sstate(target + '.*?\.tgz$') + target_sstate_before_build = self.search_sstate(target + r'.*?\.tgz$') bitbake("-cclean %s" % target) result = bitbake(target, ignore_status=True) if target_config[idx] == target_config[-1]: - target_sstate_after_build = self.search_sstate(target + '.*?\.tgz$') + target_sstate_after_build = self.search_sstate(target + r'.*?\.tgz$') expected_remaining_sstate += [x for x in target_sstate_after_build if x not in target_sstate_before_build if not any(pattern in x for pattern in ignore_patterns)] self.remove_config(global_config[idx]) self.remove_recipeinc(target, target_config[idx]) self.assertEqual(result.status, 0, msg = "build of %s failed with %s" % (target, result.output)) runCmd("sstate-cache-management.sh -y --cache-dir=%s --remove-duplicated --extra-archs=%s" % (self.sstate_path, ','.join(map(str, sstate_archs_list)))) - actual_remaining_sstate = [x for x in self.search_sstate(target + '.*?\.tgz$') if not any(pattern in x for pattern in ignore_patterns)] + actual_remaining_sstate = [x for x in self.search_sstate(target + r'.*?\.tgz$') if not any(pattern in x for pattern in ignore_patterns)] actual_not_expected = [x for x in actual_remaining_sstate if x not in expected_remaining_sstate] self.assertFalse(actual_not_expected, msg="Files should have been removed but ware not: %s" % ', '.join(map(str, actual_not_expected))) expected_not_actual = [x for x in expected_remaining_sstate if x not in actual_remaining_sstate] self.assertFalse(expected_not_actual, msg="Extra files ware removed: %s" ', '.join(map(str, expected_not_actual))) - @OETestID(973) def test_sstate_cache_management_script_using_pr_1(self): global_config = [] target_config = [] @@ -218,7 +213,6 @@ class SStateTests(SStateBase): target_config.append('PR = "0"') self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic']) - @OETestID(978) def test_sstate_cache_management_script_using_pr_2(self): global_config = [] target_config = [] @@ -228,7 +222,6 @@ class SStateTests(SStateBase): target_config.append('PR = "1"') self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic']) - @OETestID(979) def test_sstate_cache_management_script_using_pr_3(self): global_config = [] target_config = [] @@ -240,7 +233,6 @@ class SStateTests(SStateBase): target_config.append('PR = "1"') self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic']) - @OETestID(974) def test_sstate_cache_management_script_using_machine(self): global_config = [] target_config = [] @@ -250,7 +242,6 @@ class SStateTests(SStateBase): target_config.append('') self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic']) - @OETestID(1270) def test_sstate_32_64_same_hash(self): """ The sstate checksums for both native and target should not vary whether @@ -267,6 +258,7 @@ BUILD_ARCH = "x86_64" BUILD_OS = "linux" SDKMACHINE = "x86_64" PACKAGE_CLASSES = "package_rpm package_ipk package_deb" +BB_SIGNATURE_HANDLER = "OEBasicHash" """) self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash") bitbake("core-image-sato -S none") @@ -278,6 +270,7 @@ BUILD_ARCH = "i686" BUILD_OS = "linux" SDKMACHINE = "i686" PACKAGE_CLASSES = "package_rpm package_ipk package_deb" +BB_SIGNATURE_HANDLER = "OEBasicHash" """) self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2") bitbake("core-image-sato -S none") @@ -299,7 +292,6 @@ PACKAGE_CLASSES = "package_rpm package_ipk package_deb" self.assertCountEqual(files1, files2) - @OETestID(1271) def test_sstate_nativelsbstring_same_hash(self): """ The sstate checksums should be independent of whichever NATIVELSBSTRING is @@ -311,6 +303,7 @@ PACKAGE_CLASSES = "package_rpm package_ipk package_deb" TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" TCLIBCAPPEND = \"\" NATIVELSBSTRING = \"DistroA\" +BB_SIGNATURE_HANDLER = "OEBasicHash" """) self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash") bitbake("core-image-sato -S none") @@ -318,6 +311,7 @@ NATIVELSBSTRING = \"DistroA\" TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" TCLIBCAPPEND = \"\" NATIVELSBSTRING = \"DistroB\" +BB_SIGNATURE_HANDLER = "OEBasicHash" """) self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2") bitbake("core-image-sato -S none") @@ -333,7 +327,6 @@ NATIVELSBSTRING = \"DistroB\" self.maxDiff = None self.assertCountEqual(files1, files2) - @OETestID(1368) def test_sstate_allarch_samesigs(self): """ The sstate checksums of allarch packages should be independent of whichever @@ -346,15 +339,16 @@ NATIVELSBSTRING = \"DistroB\" TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" TCLIBCAPPEND = \"\" MACHINE = \"qemux86-64\" +BB_SIGNATURE_HANDLER = "OEBasicHash" """ configB = """ TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" TCLIBCAPPEND = \"\" MACHINE = \"qemuarm\" +BB_SIGNATURE_HANDLER = "OEBasicHash" """ self.sstate_allarch_samesigs(configA, configB) - @OETestID(1645) def test_sstate_nativesdk_samesigs_multilib(self): """ check nativesdk stamps are the same between the two MACHINE values. @@ -367,6 +361,7 @@ MACHINE = \"qemux86-64\" require conf/multilib.conf MULTILIBS = \"multilib:lib32\" DEFAULTTUNE_virtclass-multilib-lib32 = \"x86\" +BB_SIGNATURE_HANDLER = "OEBasicHash" """ configB = """ TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" @@ -374,6 +369,7 @@ TCLIBCAPPEND = \"\" MACHINE = \"qemuarm\" require conf/multilib.conf MULTILIBS = \"\" +BB_SIGNATURE_HANDLER = "OEBasicHash" """ self.sstate_allarch_samesigs(configA, configB) @@ -405,7 +401,6 @@ MULTILIBS = \"\" self.maxDiff = None self.assertEqual(files1, files2) - @OETestID(1369) def test_sstate_sametune_samesigs(self): """ The sstate checksums of two identical machines (using the same tune) should be the @@ -420,6 +415,7 @@ MACHINE = \"qemux86\" require conf/multilib.conf MULTILIBS = "multilib:lib32" DEFAULTTUNE_virtclass-multilib-lib32 = "x86" +BB_SIGNATURE_HANDLER = "OEBasicHash" """) self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash") bitbake("world meta-toolchain -S none") @@ -430,6 +426,7 @@ MACHINE = \"qemux86copy\" require conf/multilib.conf MULTILIBS = "multilib:lib32" DEFAULTTUNE_virtclass-multilib-lib32 = "x86" +BB_SIGNATURE_HANDLER = "OEBasicHash" """) self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2") bitbake("world meta-toolchain -S none") @@ -452,7 +449,46 @@ DEFAULTTUNE_virtclass-multilib-lib32 = "x86" self.assertCountEqual(files1, files2) - @OETestID(1498) + def test_sstate_multilib_or_not_native_samesigs(self): + """The sstate checksums of two native recipes (and their dependencies) + where the target is using multilib in one but not the other + should be the same. We use the qemux86copy machine to test + this. + """ + + self.write_config(""" +TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" +TCLIBCAPPEND = \"\" +MACHINE = \"qemux86\" +require conf/multilib.conf +MULTILIBS = "multilib:lib32" +DEFAULTTUNE_virtclass-multilib-lib32 = "x86" +BB_SIGNATURE_HANDLER = "OEBasicHash" +""") + self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash") + bitbake("binutils-native -S none") + self.write_config(""" +TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" +TCLIBCAPPEND = \"\" +MACHINE = \"qemux86copy\" +BB_SIGNATURE_HANDLER = "OEBasicHash" +""") + self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2") + bitbake("binutils-native -S none") + + def get_files(d): + f = [] + for root, dirs, files in os.walk(d): + for name in files: + f.append(os.path.join(root, name)) + return f + files1 = get_files(self.topdir + "/tmp-sstatesamehash/stamps") + files2 = get_files(self.topdir + "/tmp-sstatesamehash2/stamps") + files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2] + self.maxDiff = None + self.assertCountEqual(files1, files2) + + def test_sstate_noop_samesigs(self): """ The sstate checksums of two builds with these variables changed or @@ -469,6 +505,7 @@ TIME = "111111" DATE = "20161111" INHERIT_remove = "buildstats-summary buildhistory uninative" http_proxy = "" +BB_SIGNATURE_HANDLER = "OEBasicHash" """) self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash") self.track_for_cleanup(self.topdir + "/download1") @@ -485,6 +522,7 @@ DATE = "20161212" INHERIT_remove = "uninative" INHERIT += "buildstats-summary buildhistory" http_proxy = "http://example.com/" +BB_SIGNATURE_HANDLER = "OEBasicHash" """) self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2") self.track_for_cleanup(self.topdir + "/download2") diff --git a/external/poky/meta/lib/oeqa/selftest/cases/sysroot.py b/external/poky/meta/lib/oeqa/selftest/cases/sysroot.py new file mode 100644 index 00000000..6e34927c --- /dev/null +++ b/external/poky/meta/lib/oeqa/selftest/cases/sysroot.py @@ -0,0 +1,37 @@ +# +# SPDX-License-Identifier: MIT +# + +import uuid + +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import bitbake + +class SysrootTests(OESelftestTestCase): + def test_sysroot_cleanup(self): + """ + Build sysroot test which depends on virtual/sysroot-test for one machine, + switch machine, switch provider of virtual/sysroot-test and check that the + sysroot is correctly cleaned up. The files in the two providers overlap + so can cause errors if the sysroot code doesn't function correctly. + Yes, sysroot-test should be machine specific really to avoid this, however + the sysroot cleanup should also work [YOCTO #13702]. + """ + + uuid1 = uuid.uuid4() + uuid2 = uuid.uuid4() + + self.write_config(""" +PREFERRED_PROVIDER_virtual/sysroot-test = "sysroot-test-arch1" +MACHINE = "qemux86" +TESTSTRING_pn-sysroot-test-arch1 = "%s" +TESTSTRING_pn-sysroot-test-arch2 = "%s" +""" % (uuid1, uuid2)) + bitbake("sysroot-test") + self.write_config(""" +PREFERRED_PROVIDER_virtual/sysroot-test = "sysroot-test-arch2" +MACHINE = "qemux86copy" +TESTSTRING_pn-sysroot-test-arch1 = "%s" +TESTSTRING_pn-sysroot-test-arch2 = "%s" +""" % (uuid1, uuid2)) + bitbake("sysroot-test") diff --git a/external/poky/meta/lib/oeqa/selftest/cases/tinfoil.py b/external/poky/meta/lib/oeqa/selftest/cases/tinfoil.py index f889a47b..d1aa7b9a 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/tinfoil.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/tinfoil.py @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: MIT +# + import os import re import time @@ -6,12 +10,10 @@ import bb.tinfoil from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import runCmd -from oeqa.core.decorator.oeid import OETestID class TinfoilTests(OESelftestTestCase): """ Basic tests for the tinfoil API """ - @OETestID(1568) def test_getvar(self): with bb.tinfoil.Tinfoil() as tinfoil: tinfoil.prepare(True) @@ -19,7 +21,6 @@ class TinfoilTests(OESelftestTestCase): if not machine: self.fail('Unable to get MACHINE value - returned %s' % machine) - @OETestID(1569) def test_expand(self): with bb.tinfoil.Tinfoil() as tinfoil: tinfoil.prepare(True) @@ -28,7 +29,6 @@ class TinfoilTests(OESelftestTestCase): if not pid: self.fail('Unable to expand "%s" - returned %s' % (expr, pid)) - @OETestID(1570) def test_getvar_bb_origenv(self): with bb.tinfoil.Tinfoil() as tinfoil: tinfoil.prepare(True) @@ -37,7 +37,6 @@ class TinfoilTests(OESelftestTestCase): self.fail('Unable to get BB_ORIGENV value - returned %s' % origenv) self.assertEqual(origenv.getVar('HOME', False), os.environ['HOME']) - @OETestID(1571) def test_parse_recipe(self): with bb.tinfoil.Tinfoil() as tinfoil: tinfoil.prepare(config_only=False, quiet=2) @@ -48,7 +47,6 @@ class TinfoilTests(OESelftestTestCase): rd = tinfoil.parse_recipe_file(best[3]) self.assertEqual(testrecipe, rd.getVar('PN')) - @OETestID(1572) def test_parse_recipe_copy_expand(self): with bb.tinfoil.Tinfoil() as tinfoil: tinfoil.prepare(config_only=False, quiet=2) @@ -67,21 +65,6 @@ class TinfoilTests(OESelftestTestCase): localdata.setVar('PN', 'hello') self.assertEqual('hello', localdata.getVar('BPN')) - @OETestID(1573) - def test_parse_recipe_initial_datastore(self): - with bb.tinfoil.Tinfoil() as tinfoil: - tinfoil.prepare(config_only=False, quiet=2) - testrecipe = 'mdadm' - best = tinfoil.find_best_provider(testrecipe) - if not best: - self.fail('Unable to find recipe providing %s' % testrecipe) - dcopy = bb.data.createCopy(tinfoil.config_data) - dcopy.setVar('MYVARIABLE', 'somevalue') - rd = tinfoil.parse_recipe_file(best[3], config_data=dcopy) - # Check we can get variable values - self.assertEqual('somevalue', rd.getVar('MYVARIABLE')) - - @OETestID(1574) def test_list_recipes(self): with bb.tinfoil.Tinfoil() as tinfoil: tinfoil.prepare(config_only=False, quiet=2) @@ -100,7 +83,6 @@ class TinfoilTests(OESelftestTestCase): if checkpns: self.fail('Unable to find pkg_fn entries for: %s' % ', '.join(checkpns)) - @OETestID(1575) def test_wait_event(self): with bb.tinfoil.Tinfoil() as tinfoil: tinfoil.prepare(config_only=True) @@ -136,7 +118,6 @@ class TinfoilTests(OESelftestTestCase): self.assertTrue(commandcomplete, 'Timed out waiting for CommandCompleted event from bitbake server') self.assertTrue(eventreceived, 'Did not receive FilesMatchingFound event from bitbake server') - @OETestID(1576) def test_setvariable_clean(self): # First check that setVariable affects the datastore with bb.tinfoil.Tinfoil() as tinfoil: @@ -159,7 +140,6 @@ class TinfoilTests(OESelftestTestCase): value = tinfoil.run_command('getVariable', 'TESTVAR') self.assertEqual(value, 'specialvalue', 'Value set using config_data.setVar() is not reflected in config_data.getVar()') - @OETestID(1884) def test_datastore_operations(self): with bb.tinfoil.Tinfoil() as tinfoil: tinfoil.prepare(config_only=True) diff --git a/external/poky/meta/lib/oeqa/selftest/cases/wic.py b/external/poky/meta/lib/oeqa/selftest/cases/wic.py index 79925f94..626a217e 100644 --- a/external/poky/meta/lib/oeqa/selftest/cases/wic.py +++ b/external/poky/meta/lib/oeqa/selftest/cases/wic.py @@ -1,22 +1,7 @@ -#!/usr/bin/env python -# ex:ts=4:sw=4:sts=4:et -# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- # # Copyright (c) 2015, Intel Corporation. -# All rights reserved. # -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# SPDX-License-Identifier: GPL-2.0-only # # AUTHORS # Ed Bartosh @@ -34,7 +19,6 @@ from tempfile import NamedTemporaryFile from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, runqemu -from oeqa.core.decorator.oeid import OETestID @lru_cache(maxsize=32) @@ -60,6 +44,24 @@ def only_for_arch(archs, image='core-image-minimal'): return wrapped_f return wrapper +def extract_files(debugfs_output): + """ + extract file names from the output of debugfs -R 'ls -p', + which looks like this: + + /2/040755/0/0/.//\n + /2/040755/0/0/..//\n + /11/040700/0/0/lost+found^M//\n + /12/040755/1002/1002/run//\n + /13/040755/1002/1002/sys//\n + /14/040755/1002/1002/bin//\n + /80/040755/1002/1002/var//\n + /92/040755/1002/1002/tmp//\n + """ + # NOTE the occasional ^M in file names + return [line.split('/')[5].strip() for line in \ + debugfs_output.strip().split('/\n')] + class WicTestCase(OESelftestTestCase): """Wic test class.""" @@ -103,63 +105,51 @@ class WicTestCase(OESelftestTestCase): class Wic(WicTestCase): - @OETestID(1552) def test_version(self): """Test wic --version""" runCmd('wic --version') - @OETestID(1208) def test_help(self): """Test wic --help and wic -h""" runCmd('wic --help') runCmd('wic -h') - @OETestID(1209) def test_createhelp(self): """Test wic create --help""" runCmd('wic create --help') - @OETestID(1210) def test_listhelp(self): """Test wic list --help""" runCmd('wic list --help') - @OETestID(1553) def test_help_create(self): """Test wic help create""" runCmd('wic help create') - @OETestID(1554) def test_help_list(self): """Test wic help list""" runCmd('wic help list') - @OETestID(1215) def test_help_overview(self): """Test wic help overview""" runCmd('wic help overview') - @OETestID(1216) def test_help_plugins(self): """Test wic help plugins""" runCmd('wic help plugins') - @OETestID(1217) def test_help_kickstart(self): """Test wic help kickstart""" runCmd('wic help kickstart') - @OETestID(1555) def test_list_images(self): """Test wic list images""" runCmd('wic list images') - @OETestID(1556) def test_list_source_plugins(self): """Test wic list source-plugins""" runCmd('wic list source-plugins') - @OETestID(1557) def test_listed_images_help(self): """Test wic listed images help""" output = runCmd('wic list images').output @@ -167,24 +157,20 @@ class Wic(WicTestCase): for image in imagelist: runCmd('wic list %s help' % image) - @OETestID(1213) def test_unsupported_subcommand(self): """Test unsupported subcommand""" self.assertNotEqual(0, runCmd('wic unsupported', ignore_status=True).status) - @OETestID(1214) def test_no_command(self): """Test wic without command""" self.assertEqual(1, runCmd('wic', ignore_status=True).status) - @OETestID(1211) def test_build_image_name(self): """Test wic create wictestdisk --image-name=core-image-minimal""" cmd = "wic create wictestdisk --image-name=core-image-minimal -o %s" % self.resultdir runCmd(cmd) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct"))) - @OETestID(1157) @only_for_arch(['i586', 'i686', 'x86_64']) def test_gpt_image(self): """Test creation of core-image-minimal with gpt table and UUID boot""" @@ -192,7 +178,6 @@ class Wic(WicTestCase): runCmd(cmd) self.assertEqual(1, len(glob(self.resultdir + "directdisk-*.direct"))) - @OETestID(1346) @only_for_arch(['i586', 'i686', 'x86_64']) def test_iso_image(self): """Test creation of hybrid iso image with legacy and EFI boot""" @@ -207,7 +192,6 @@ class Wic(WicTestCase): self.assertEqual(1, len(glob(self.resultdir + "HYBRID_ISO_IMG-*.direct"))) self.assertEqual(1, len(glob(self.resultdir + "HYBRID_ISO_IMG-*.iso"))) - @OETestID(1348) @only_for_arch(['i586', 'i686', 'x86_64']) def test_qemux86_directdisk(self): """Test creation of qemux-86-directdisk image""" @@ -215,7 +199,6 @@ class Wic(WicTestCase): runCmd(cmd) self.assertEqual(1, len(glob(self.resultdir + "qemux86-directdisk-*direct"))) - @OETestID(1350) @only_for_arch(['i586', 'i686', 'x86_64']) def test_mkefidisk(self): """Test creation of mkefidisk image""" @@ -223,7 +206,6 @@ class Wic(WicTestCase): runCmd(cmd) self.assertEqual(1, len(glob(self.resultdir + "mkefidisk-*direct"))) - @OETestID(1385) @only_for_arch(['i586', 'i686', 'x86_64']) def test_bootloader_config(self): """Test creation of directdisk-bootloader-config image""" @@ -235,7 +217,6 @@ class Wic(WicTestCase): runCmd(cmd) self.assertEqual(1, len(glob(self.resultdir + "directdisk-bootloader-config-*direct"))) - @OETestID(1560) @only_for_arch(['i586', 'i686', 'x86_64']) def test_systemd_bootdisk(self): """Test creation of systemd-bootdisk image""" @@ -247,7 +228,6 @@ class Wic(WicTestCase): runCmd(cmd) self.assertEqual(1, len(glob(self.resultdir + "systemd-bootdisk-*direct"))) - @OETestID(1561) def test_sdimage_bootpart(self): """Test creation of sdimage-bootpart image""" cmd = "wic create sdimage-bootpart -e core-image-minimal -o %s" % self.resultdir @@ -256,7 +236,6 @@ class Wic(WicTestCase): runCmd(cmd) self.assertEqual(1, len(glob(self.resultdir + "sdimage-bootpart-*direct"))) - @OETestID(1562) @only_for_arch(['i586', 'i686', 'x86_64']) def test_default_output_dir(self): """Test default output location""" @@ -270,7 +249,6 @@ class Wic(WicTestCase): runCmd(cmd) self.assertEqual(1, len(glob("directdisk-*.direct"))) - @OETestID(1212) @only_for_arch(['i586', 'i686', 'x86_64']) def test_build_artifacts(self): """Test wic create directdisk providing all artifacts.""" @@ -288,7 +266,6 @@ class Wic(WicTestCase): "-o %(resultdir)s" % bbvars) self.assertEqual(1, len(glob(self.resultdir + "directdisk-*.direct"))) - @OETestID(1264) def test_compress_gzip(self): """Test compressing an image with gzip""" runCmd("wic create wictestdisk " @@ -296,7 +273,6 @@ class Wic(WicTestCase): "-c gzip -o %s" % self.resultdir) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct.gz"))) - @OETestID(1265) def test_compress_bzip2(self): """Test compressing an image with bzip2""" runCmd("wic create wictestdisk " @@ -304,7 +280,6 @@ class Wic(WicTestCase): "-c bzip2 -o %s" % self.resultdir) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct.bz2"))) - @OETestID(1266) def test_compress_xz(self): """Test compressing an image with xz""" runCmd("wic create wictestdisk " @@ -312,7 +287,6 @@ class Wic(WicTestCase): "--compress-with=xz -o %s" % self.resultdir) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct.xz"))) - @OETestID(1267) def test_wrong_compressor(self): """Test how wic breaks if wrong compressor is provided""" self.assertEqual(2, runCmd("wic create wictestdisk " @@ -320,7 +294,6 @@ class Wic(WicTestCase): "-c wrong -o %s" % self.resultdir, ignore_status=True).status) - @OETestID(1558) def test_debug_short(self): """Test -D option""" runCmd("wic create wictestdisk " @@ -328,7 +301,6 @@ class Wic(WicTestCase): "-D -o %s" % self.resultdir) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct"))) - @OETestID(1658) def test_debug_long(self): """Test --debug option""" runCmd("wic create wictestdisk " @@ -336,7 +308,6 @@ class Wic(WicTestCase): "--debug -o %s" % self.resultdir) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct"))) - @OETestID(1563) def test_skip_build_check_short(self): """Test -s option""" runCmd("wic create wictestdisk " @@ -344,7 +315,6 @@ class Wic(WicTestCase): "-s -o %s" % self.resultdir) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct"))) - @OETestID(1671) def test_skip_build_check_long(self): """Test --skip-build-check option""" runCmd("wic create wictestdisk " @@ -353,7 +323,6 @@ class Wic(WicTestCase): "--outdir %s" % self.resultdir) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct"))) - @OETestID(1564) def test_build_rootfs_short(self): """Test -f option""" runCmd("wic create wictestdisk " @@ -361,7 +330,6 @@ class Wic(WicTestCase): "-f -o %s" % self.resultdir) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct"))) - @OETestID(1656) def test_build_rootfs_long(self): """Test --build-rootfs option""" runCmd("wic create wictestdisk " @@ -370,7 +338,6 @@ class Wic(WicTestCase): "--outdir %s" % self.resultdir) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct"))) - @OETestID(1268) @only_for_arch(['i586', 'i686', 'x86_64']) def test_rootfs_indirect_recipes(self): """Test usage of rootfs plugin with rootfs recipes""" @@ -381,7 +348,6 @@ class Wic(WicTestCase): "--outdir %s" % self.resultdir) self.assertEqual(1, len(glob(self.resultdir + "directdisk-multi-rootfs*.direct"))) - @OETestID(1269) @only_for_arch(['i586', 'i686', 'x86_64']) def test_rootfs_artifacts(self): """Test usage of rootfs plugin with rootfs paths""" @@ -401,7 +367,6 @@ class Wic(WicTestCase): "--outdir %(resultdir)s" % bbvars) self.assertEqual(1, len(glob(self.resultdir + "%(wks)s-*.direct" % bbvars))) - @OETestID(1661) def test_exclude_path(self): """Test --exclude-path wks option.""" @@ -446,24 +411,6 @@ part /etc --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path bin/ --r runCmd("dd if=%s of=%s skip=%d count=%d" % (wicimg, part_file, start, length)) - def extract_files(debugfs_output): - """ - extract file names from the output of debugfs -R 'ls -p', - which looks like this: - - /2/040755/0/0/.//\n - /2/040755/0/0/..//\n - /11/040700/0/0/lost+found^M//\n - /12/040755/1002/1002/run//\n - /13/040755/1002/1002/sys//\n - /14/040755/1002/1002/bin//\n - /80/040755/1002/1002/var//\n - /92/040755/1002/1002/tmp//\n - """ - # NOTE the occasional ^M in file names - return [line.split('/')[5].strip() for line in \ - debugfs_output.strip().split('/\n')] - # Test partition 1, should contain the normal root directories, except # /usr. res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \ @@ -504,7 +451,43 @@ part /etc --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path bin/ --r finally: os.environ['PATH'] = oldpath - @OETestID(1662) + def test_include_path(self): + """Test --include-path wks option.""" + + oldpath = os.environ['PATH'] + os.environ['PATH'] = get_bb_var("PATH", "wic-tools") + + try: + include_path = os.path.join(self.resultdir, 'test-include') + os.makedirs(include_path) + with open(os.path.join(include_path, 'test-file'), 'w') as t: + t.write("test\n") + wks_file = os.path.join(include_path, 'temp.wks') + with open(wks_file, 'w') as wks: + rootfs_dir = get_bb_var('IMAGE_ROOTFS', 'core-image-minimal') + wks.write(""" +part /part1 --source rootfs --ondisk mmcblk0 --fstype=ext4 +part /part2 --source rootfs --ondisk mmcblk0 --fstype=ext4 --include-path %s""" + % (include_path)) + runCmd("wic create %s -e core-image-minimal -o %s" \ + % (wks_file, self.resultdir)) + + part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0] + part2 = glob(os.path.join(self.resultdir, 'temp-*.direct.p2'))[0] + + # Test partition 1, should not contain 'test-file' + res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1)) + files = extract_files(res.output) + self.assertNotIn('test-file', files) + + # Test partition 2, should not contain 'test-file' + res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part2)) + files = extract_files(res.output) + self.assertIn('test-file', files) + + finally: + os.environ['PATH'] = oldpath + def test_exclude_path_errors(self): """Test --exclude-path wks option error handling.""" wks_file = 'temp.wks' @@ -525,7 +508,6 @@ part /etc --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path bin/ --r class Wic2(WicTestCase): - @OETestID(1496) def test_bmap_short(self): """Test generation of .bmap file -m option""" cmd = "wic create wictestdisk -e core-image-minimal -m -o %s" % self.resultdir @@ -533,7 +515,6 @@ class Wic2(WicTestCase): self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct"))) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct.bmap"))) - @OETestID(1655) def test_bmap_long(self): """Test generation of .bmap file --bmap option""" cmd = "wic create wictestdisk -e core-image-minimal --bmap -o %s" % self.resultdir @@ -541,7 +522,6 @@ class Wic2(WicTestCase): self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct"))) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct.bmap"))) - @OETestID(1347) def test_image_env(self): """Test generation of .env files.""" image = 'core-image-minimal' @@ -556,7 +536,9 @@ 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', + 'APPEND')) 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 @@ -564,7 +546,6 @@ class Wic2(WicTestCase): self.assertTrue(var in content, "%s is not in .env file" % var) self.assertTrue(content[var]) - @OETestID(1559) def test_image_vars_dir_short(self): """Test image vars directory selection -v option""" image = 'core-image-minimal' @@ -577,7 +558,6 @@ class Wic2(WicTestCase): self.resultdir)) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct"))) - @OETestID(1665) def test_image_vars_dir_long(self): """Test image vars directory selection --vars option""" image = 'core-image-minimal' @@ -593,7 +573,6 @@ class Wic2(WicTestCase): self.resultdir)) self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct"))) - @OETestID(1351) @only_for_arch(['i586', 'i686', 'x86_64']) def test_wic_image_type(self): """Test building wic images by bitbake""" @@ -614,7 +593,6 @@ class Wic2(WicTestCase): self.assertTrue(os.path.islink(path)) self.assertTrue(os.path.isfile(os.path.realpath(path))) - @OETestID(1424) @only_for_arch(['i586', 'i686', 'x86_64']) def test_qemu(self): """Test wic-image-minimal under qemu""" @@ -636,7 +614,6 @@ class Wic2(WicTestCase): self.assertEqual(output, 'UUID=2c71ef06-a81d-4735-9d3a-379b69c6bdba\t/media\text4\tdefaults\t0\t0') @only_for_arch(['i586', 'i686', 'x86_64']) - @OETestID(1852) def test_qemu_efi(self): """Test core-image-minimal efi image under qemu""" config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "mkefidisk.wks"\n' @@ -666,7 +643,6 @@ class Wic2(WicTestCase): return wkspath, wksname - @OETestID(1847) def test_fixed_size(self): """ Test creation of a simple image with partition size controlled through @@ -694,10 +670,11 @@ class Wic2(WicTestCase): # 1:0.00MiB:200MiB:200MiB:ext4::;\n partlns = res.output.splitlines()[2:] - self.assertEqual(1, len(partlns)) - self.assertEqual("1:0.00MiB:200MiB:200MiB:ext4::;", partlns[0]) + self.assertEqual(1, len(partlns), + msg="Partition list '%s'" % res.output) + self.assertEqual("1:0.00MiB:200MiB:200MiB:ext4::;", partlns[0], + msg="Partition list '%s'" % res.output) - @OETestID(1848) def test_fixed_size_error(self): """ Test creation of a simple image with partition size controlled through @@ -713,7 +690,6 @@ class Wic2(WicTestCase): self.assertEqual(0, len(wicout)) @only_for_arch(['i586', 'i686', 'x86_64']) - @OETestID(1854) def test_rawcopy_plugin_qemu(self): """Test rawcopy plugin in qemu""" # build ext4 and wic images @@ -729,7 +705,6 @@ class Wic2(WicTestCase): self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) self.assertEqual(output, '2') - @OETestID(1853) def test_rawcopy_plugin(self): """Test rawcopy plugin""" img = 'core-image-minimal' @@ -746,7 +721,63 @@ class Wic2(WicTestCase): out = glob(self.resultdir + "%s-*direct" % wksname) self.assertEqual(1, len(out)) - @OETestID(1849) + @only_for_arch(['i586', 'i686', 'x86_64']) + def test_biosplusefi_plugin_qemu(self): + """Test biosplusefi plugin in qemu""" + config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES_append = " efi"\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: + # 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 + config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES_append = " efi"\n' + 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' @@ -766,7 +797,6 @@ class Wic2(WicTestCase): out = glob(self.resultdir + "%s-*direct" % wksname) self.assertEqual(1, len(out)) - @OETestID(1851) def test_kickstart_parser(self): """Test wks parser options""" with NamedTemporaryFile("w", suffix=".wks") as wks: @@ -779,7 +809,6 @@ class Wic2(WicTestCase): out = glob(self.resultdir + "%s-*direct" % wksname) self.assertEqual(1, len(out)) - @OETestID(1850) def test_image_bootpart_globbed(self): """Test globbed sources with image-bootpart plugin""" img = "core-image-minimal" @@ -790,7 +819,6 @@ class Wic2(WicTestCase): self.remove_config(config) self.assertEqual(1, len(glob(self.resultdir + "sdimage-bootpart-*direct"))) - @OETestID(1855) def test_sparse_copy(self): """Test sparse_copy with FIEMAP and SEEK_HOLE filemap APIs""" libpath = os.path.join(get_bb_var('COREBASE'), 'scripts', 'lib', 'wic') @@ -819,7 +847,6 @@ class Wic2(WicTestCase): self.assertEqual(dest_stat.st_blocks, 8) os.unlink(dest) - @OETestID(1857) def test_wic_ls(self): """Test listing image content using 'wic ls'""" runCmd("wic create wictestdisk " @@ -838,7 +865,6 @@ class Wic2(WicTestCase): result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot)) self.assertEqual(6, len(result.output.split('\n'))) - @OETestID(1856) def test_wic_cp(self): """Test copy files and directories to the the wic image.""" runCmd("wic create wictestdisk " @@ -878,7 +904,13 @@ class Wic2(WicTestCase): self.assertEqual(8, len(result.output.split('\n'))) self.assertTrue(os.path.basename(testdir) in result.output) - @OETestID(1858) + # copy the file from the partition and check if it success + dest = '%s-cp' % testfile.name + runCmd("wic cp %s:1/%s %s -n %s" % (images[0], + os.path.basename(testfile.name), dest, sysroot)) + self.assertTrue(os.path.exists(dest)) + + def test_wic_rm(self): """Test removing files and directories from the the wic image.""" runCmd("wic create mkefidisk " @@ -905,7 +937,6 @@ class Wic2(WicTestCase): self.assertNotIn('\nBZIMAGE ', result.output) self.assertNotIn('\nEFI ', result.output) - @OETestID(1922) def test_mkfs_extraopts(self): """Test wks option --mkfs-extraopts for empty and not empty partitions""" img = 'core-image-minimal' @@ -1019,6 +1050,16 @@ class Wic2(WicTestCase): newdirs = set(line.split()[-1] for line in result.output.split('\n') if line) self.assertEqual(newdirs.difference(dirs), set([os.path.basename(testfile.name)])) + # check if the file to copy is in the partition + result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot)) + self.assertTrue('fstab' in [line.split()[-1] for line in result.output.split('\n') if line]) + + # copy file from the partition, replace the temporary file content with it and + # check for the file size to validate the copy + runCmd("wic cp %s:2/etc/fstab %s -n %s" % (images[0], testfile.name, sysroot)) + self.assertTrue(os.stat(testfile.name).st_size > 0) + + def test_wic_rm_ext(self): """Test removing files from the ext partition.""" runCmd("wic create mkefidisk " @@ -1039,3 +1080,10 @@ class Wic2(WicTestCase): # check if it's removed result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot)) self.assertTrue('fstab' not in [line.split()[-1] for line in result.output.split('\n') if line]) + + # remove non-empty directory + runCmd("wic rm -r %s:2/etc/ -n %s" % (images[0], sysroot)) + + # check if it's removed + result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot)) + self.assertTrue('etc' not in [line.split()[-1] for line in result.output.split('\n') if line]) diff --git a/external/poky/meta/lib/oeqa/selftest/context.py b/external/poky/meta/lib/oeqa/selftest/context.py index c56e53dc..9baad583 100644 --- a/external/poky/meta/lib/oeqa/selftest/context.py +++ b/external/poky/meta/lib/oeqa/selftest/context.py @@ -1,30 +1,125 @@ +# # Copyright (C) 2017 Intel Corporation -# Released under the MIT license (see COPYING.MIT) +# +# SPDX-License-Identifier: MIT +# import os import time import glob import sys import importlib -import signal -from shutil import copyfile +import subprocess +import unittest from random import choice import oeqa import oe +import bb.utils from oeqa.core.context import OETestContext, OETestContextExecutor from oeqa.core.exception import OEQAPreRun, OEQATestNotFound from oeqa.utils.commands import runCmd, get_bb_vars, get_test_layer +class NonConcurrentTestSuite(unittest.TestSuite): + def __init__(self, suite, processes, setupfunc, removefunc): + super().__init__([suite]) + self.processes = processes + self.suite = suite + self.setupfunc = setupfunc + self.removefunc = removefunc + + def run(self, result): + (builddir, newbuilddir) = self.setupfunc("-st", None, self.suite) + ret = super().run(result) + os.chdir(builddir) + if newbuilddir and ret.wasSuccessful(): + self.removefunc(newbuilddir) + +def removebuilddir(d): + delay = 5 + while delay and os.path.exists(d + "/bitbake.lock"): + time.sleep(1) + delay = delay - 1 + # Deleting these directories takes a lot of time, use autobuilder + # clobberdir if its available + clobberdir = os.path.expanduser("~/yocto-autobuilder-helper/janitor/clobberdir") + if os.path.exists(clobberdir): + try: + subprocess.check_call([clobberdir, d]) + return + except subprocess.CalledProcessError: + pass + bb.utils.prunedir(d, ionice=True) + class OESelftestTestContext(OETestContext): - def __init__(self, td=None, logger=None, machines=None, config_paths=None): + def __init__(self, td=None, logger=None, machines=None, config_paths=None, newbuilddir=None): super(OESelftestTestContext, self).__init__(td, logger) self.machines = machines self.custommachine = None self.config_paths = config_paths + self.newbuilddir = newbuilddir + + def setup_builddir(self, suffix, selftestdir, suite): + builddir = os.environ['BUILDDIR'] + if not selftestdir: + selftestdir = get_test_layer() + if self.newbuilddir: + newbuilddir = os.path.join(self.newbuilddir, 'build' + suffix) + else: + newbuilddir = builddir + suffix + newselftestdir = newbuilddir + "/meta-selftest" + + if os.path.exists(newbuilddir): + self.logger.error("Build directory %s already exists, aborting" % newbuilddir) + sys.exit(1) + + bb.utils.mkdirhier(newbuilddir) + oe.path.copytree(builddir + "/conf", newbuilddir + "/conf") + oe.path.copytree(builddir + "/cache", newbuilddir + "/cache") + oe.path.copytree(selftestdir, newselftestdir) + + for e in os.environ: + if builddir + "/" in os.environ[e] or os.environ[e].endswith(builddir): + os.environ[e] = os.environ[e].replace(builddir, newbuilddir) + + subprocess.check_output("git init; git add *; git commit -a -m 'initial'", cwd=newselftestdir, shell=True) + + # Tried to used bitbake-layers add/remove but it requires recipe parsing and hence is too slow + subprocess.check_output("sed %s/conf/bblayers.conf -i -e 's#%s#%s#g'" % (newbuilddir, selftestdir, newselftestdir), cwd=newbuilddir, shell=True) + + os.chdir(newbuilddir) + + def patch_test(t): + if not hasattr(t, "tc"): + return + cp = t.tc.config_paths + for p in cp: + if selftestdir in cp[p] and newselftestdir not in cp[p]: + cp[p] = cp[p].replace(selftestdir, newselftestdir) + if builddir in cp[p] and newbuilddir not in cp[p]: + cp[p] = cp[p].replace(builddir, newbuilddir) + + def patch_suite(s): + for x in s: + if isinstance(x, unittest.TestSuite): + patch_suite(x) + else: + patch_test(x) + + patch_suite(suite) + + return (builddir, newbuilddir) + + def prepareSuite(self, suites, processes): + if processes: + from oeqa.core.utils.concurrencytest import ConcurrentTestSuite + + return ConcurrentTestSuite(suites, processes, self.setup_builddir, removebuilddir) + else: + return NonConcurrentTestSuite(suites, processes, self.setup_builddir, removebuilddir) def runTests(self, processes=None, machine=None, skips=[]): if machine: @@ -74,7 +169,15 @@ class OESelftestTestContextExecutor(OETestContextExecutor): parser.add_argument('--machine', required=False, choices=['random', 'all'], help='Run tests on different machines (random/all).') - + + parser.add_argument('-t', '--select-tag', dest="select_tags", + action='append', default=None, + help='Filter all (unhidden) tests to any that match any of the specified tag(s).') + parser.add_argument('-T', '--exclude-tag', dest="exclude_tags", + action='append', default=None, + help='Exclude all (unhidden) tests that match any of the specified tag(s). (exclude applies before select)') + + parser.add_argument('-B', '--newbuilddir', help='New build directory to use for tests.') parser.set_defaults(func=self.run) def _get_available_machines(self): @@ -125,26 +228,23 @@ class OESelftestTestContextExecutor(OETestContextExecutor): builddir = os.environ.get("BUILDDIR") self.tc_kwargs['init']['config_paths'] = {} - self.tc_kwargs['init']['config_paths']['testlayer_path'] = \ - get_test_layer() + self.tc_kwargs['init']['config_paths']['testlayer_path'] = get_test_layer() self.tc_kwargs['init']['config_paths']['builddir'] = builddir - self.tc_kwargs['init']['config_paths']['localconf'] = \ - os.path.join(builddir, "conf/local.conf") - self.tc_kwargs['init']['config_paths']['localconf_backup'] = \ - os.path.join(builddir, "conf/local.conf.orig") - self.tc_kwargs['init']['config_paths']['localconf_class_backup'] = \ - os.path.join(builddir, "conf/local.conf.bk") - self.tc_kwargs['init']['config_paths']['bblayers'] = \ - os.path.join(builddir, "conf/bblayers.conf") - self.tc_kwargs['init']['config_paths']['bblayers_backup'] = \ - os.path.join(builddir, "conf/bblayers.conf.orig") - self.tc_kwargs['init']['config_paths']['bblayers_class_backup'] = \ - os.path.join(builddir, "conf/bblayers.conf.bk") - - copyfile(self.tc_kwargs['init']['config_paths']['localconf'], - self.tc_kwargs['init']['config_paths']['localconf_backup']) - copyfile(self.tc_kwargs['init']['config_paths']['bblayers'], - self.tc_kwargs['init']['config_paths']['bblayers_backup']) + self.tc_kwargs['init']['config_paths']['localconf'] = os.path.join(builddir, "conf/local.conf") + self.tc_kwargs['init']['config_paths']['bblayers'] = os.path.join(builddir, "conf/bblayers.conf") + self.tc_kwargs['init']['newbuilddir'] = args.newbuilddir + + def tag_filter(tags): + if args.exclude_tags: + if any(tag in args.exclude_tags for tag in tags): + return True + if args.select_tags: + if not tags or not any(tag in args.select_tags for tag in tags): + return True + return False + + if args.select_tags or args.exclude_tags: + self.tc_kwargs['load']['tags_filter'] = tag_filter self.tc_kwargs['run']['skips'] = args.skips self.tc_kwargs['run']['processes'] = args.processes @@ -257,14 +357,9 @@ class OESelftestTestContextExecutor(OETestContextExecutor): return rc - def _signal_clean_handler(self, signum, frame): - sys.exit(1) - def run(self, logger, args): self._process_args(logger, args) - signal.signal(signal.SIGTERM, self._signal_clean_handler) - rc = None try: if args.machine: @@ -293,20 +388,6 @@ class OESelftestTestContextExecutor(OETestContextExecutor): rc = self._internal_run(logger, args) finally: config_paths = self.tc_kwargs['init']['config_paths'] - if os.path.exists(config_paths['localconf_backup']): - copyfile(config_paths['localconf_backup'], - config_paths['localconf']) - os.remove(config_paths['localconf_backup']) - - if os.path.exists(config_paths['bblayers_backup']): - copyfile(config_paths['bblayers_backup'], - config_paths['bblayers']) - os.remove(config_paths['bblayers_backup']) - - if os.path.exists(config_paths['localconf_class_backup']): - os.remove(config_paths['localconf_class_backup']) - if os.path.exists(config_paths['bblayers_class_backup']): - os.remove(config_paths['bblayers_class_backup']) output_link = os.path.join(os.path.dirname(args.output_log), "%s-results.log" % self.name) -- cgit 1.2.3-korg