diff options
Diffstat (limited to 'poky/meta/lib/oeqa/selftest')
24 files changed, 812 insertions, 306 deletions
diff --git a/poky/meta/lib/oeqa/selftest/cases/bbclasses.py b/poky/meta/lib/oeqa/selftest/cases/bbclasses.py new file mode 100644 index 0000000000..10545ebe65 --- /dev/null +++ b/poky/meta/lib/oeqa/selftest/cases/bbclasses.py @@ -0,0 +1,106 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import get_bb_vars, bitbake + +class Systemd(OESelftestTestCase): + """ + Tests related to the systemd bbclass. + """ + + def getVars(self, recipe): + self.bb_vars = get_bb_vars( + [ + 'BPN', + 'D', + 'INIT_D_DIR', + 'prefix', + 'systemd_system_unitdir', + 'sysconfdir', + ], + recipe, + ) + + def fileExists(self, filename): + self.assertExists(filename.format(**self.bb_vars)) + + def fileNotExists(self, filename): + self.assertNotExists(filename.format(**self.bb_vars)) + + def test_systemd_in_distro(self): + """ + Summary: Verify that no sysvinit files are installed when the + systemd distro feature is enabled, but sysvinit is not. + Expected: Systemd service file exists, but /etc does not. + Product: OE-Core + Author: Peter Kjellerstedt <peter.kjellerstedt@axis.com> + """ + + self.write_config(""" +DISTRO_FEATURES:append = " systemd usrmerge" +DISTRO_FEATURES:remove = "sysvinit" +VIRTUAL-RUNTIME_init_manager = "systemd" +""") + bitbake("systemd-only systemd-and-sysvinit -c install") + + self.getVars("systemd-only") + self.fileExists("{D}{systemd_system_unitdir}/{BPN}.service") + + self.getVars("systemd-and-sysvinit") + self.fileExists("{D}{systemd_system_unitdir}/{BPN}.service") + self.fileNotExists("{D}{sysconfdir}") + + def test_systemd_and_sysvinit_in_distro(self): + """ + Summary: Verify that both systemd and sysvinit files are installed + when both the systemd and sysvinit distro features are + enabled. + Expected: Systemd service file and sysvinit initscript exist. + Product: OE-Core + Author: Peter Kjellerstedt <peter.kjellerstedt@axis.com> + """ + + self.write_config(""" +DISTRO_FEATURES:append = " systemd sysvinit usrmerge" +VIRTUAL-RUNTIME_init_manager = "systemd" +""") + bitbake("systemd-only systemd-and-sysvinit -c install") + + self.getVars("systemd-only") + self.fileExists("{D}{systemd_system_unitdir}/{BPN}.service") + + self.getVars("systemd-and-sysvinit") + self.fileExists("{D}{systemd_system_unitdir}/{BPN}.service") + self.fileExists("{D}{INIT_D_DIR}/{BPN}") + + def test_sysvinit_in_distro(self): + """ + Summary: Verify that no systemd service files are installed when the + sysvinit distro feature is enabled, but systemd is not. + Expected: The systemd service file does not exist, nor does /usr. + The sysvinit initscript exists. + Product: OE-Core + Author: Peter Kjellerstedt <peter.kjellerstedt@axis.com> + """ + + self.write_config(""" +DISTRO_FEATURES:remove = "systemd" +DISTRO_FEATURES:append = " sysvinit usrmerge" +VIRTUAL-RUNTIME_init_manager = "sysvinit" +""") + bitbake("systemd-only systemd-and-sysvinit -c install") + + self.getVars("systemd-only") + self.fileNotExists("{D}{systemd_system_unitdir}/{BPN}.service") + self.fileNotExists("{D}{prefix}") + self.fileNotExists("{D}{sysconfdir}") + self.fileExists("{D}") + + self.getVars("systemd-and-sysvinit") + self.fileNotExists("{D}{systemd_system_unitdir}/{BPN}.service") + self.fileNotExists("{D}{prefix}") + self.fileExists("{D}{INIT_D_DIR}/{BPN}") diff --git a/poky/meta/lib/oeqa/selftest/cases/binutils.py b/poky/meta/lib/oeqa/selftest/cases/binutils.py index 1688eabe4e..5ff263d342 100644 --- a/poky/meta/lib/oeqa/selftest/cases/binutils.py +++ b/poky/meta/lib/oeqa/selftest/cases/binutils.py @@ -33,7 +33,7 @@ class BinutilsCrossSelfTest(OESelftestTestCase, OEPTestResultTestCase): features.append('CHECK_TARGETS = "{0}"'.format(suite)) self.write_config("\n".join(features)) - recipe = "binutils-cross-testsuite" + recipe = "binutils-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"] diff --git a/poky/meta/lib/oeqa/selftest/cases/buildoptions.py b/poky/meta/lib/oeqa/selftest/cases/buildoptions.py index 31dafaa9c5..423c31e189 100644 --- a/poky/meta/lib/oeqa/selftest/cases/buildoptions.py +++ b/poky/meta/lib/oeqa/selftest/cases/buildoptions.py @@ -84,7 +84,7 @@ class SanityOptionsTest(OESelftestTestCase): self.write_config("INHERIT:remove = \"report-error\"") if "packages-list" not in get_bb_var("ERROR_QA"): - self.append_config("ERROR_QA:append = \" packages-list\"") + self.append_config("ERROR_QA:append:pn-xcursor-transparent-theme = \" packages-list\"") self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"') self.add_command_to_tearDown('bitbake -c clean xcursor-transparent-theme') @@ -94,8 +94,8 @@ class SanityOptionsTest(OESelftestTestCase): self.assertTrue(line and line.startswith("ERROR:"), msg=res.output) self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output)) self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"') - self.append_config('ERROR_QA:remove = "packages-list"') - self.append_config('WARN_QA:append = " packages-list"') + self.append_config('ERROR_QA:remove:pn-xcursor-transparent-theme = "packages-list"') + self.append_config('WARN_QA:append:pn-xcursor-transparent-theme = " packages-list"') res = bitbake("xcursor-transparent-theme -f -c package") self.delete_recipeinc('xcursor-transparent-theme') line = self.getline(res, "QA Issue: xcursor-transparent-theme-dbg is listed in PACKAGES multiple times, this leads to packaging errors.") @@ -173,8 +173,8 @@ class BuildhistoryTests(BuildhistoryBase): data = load_bh(os.path.join(history_dir, 'hicolor-icon-theme-dev', 'latest')) if 'FILELIST' in data: - self.assertEqual(data['FILELIST'], '') - self.assertEqual(int(data['PKGSIZE']), 0) + self.assertEqual(data['FILELIST'], '/usr/share/pkgconfig/default-icon-theme.pc') + self.assertGreater(int(data['PKGSIZE']), 0) class ArchiverTest(OESelftestTestCase): def test_arch_work_dir_and_export_source(self): diff --git a/poky/meta/lib/oeqa/selftest/cases/cve_check.py b/poky/meta/lib/oeqa/selftest/cases/cve_check.py index 60cecd1328..3dd3e89d3e 100644 --- a/poky/meta/lib/oeqa/selftest/cases/cve_check.py +++ b/poky/meta/lib/oeqa/selftest/cases/cve_check.py @@ -72,6 +72,54 @@ class CVECheck(OESelftestTestCase): self.assertEqual(convert_cve_version("6.2_rc8"), "6.2-rc8") self.assertEqual(convert_cve_version("6.2_rc31"), "6.2-rc31") + def test_product_match(self): + from oe.cve_check import has_cve_product_match + + status = {} + status["detail"] = "ignored" + status["vendor"] = "*" + status["product"] = "*" + status["description"] = "" + status["mapping"] = "" + + self.assertEqual(has_cve_product_match(status, "some_vendor:some_product"), True) + self.assertEqual(has_cve_product_match(status, "*:*"), True) + self.assertEqual(has_cve_product_match(status, "some_product"), True) + self.assertEqual(has_cve_product_match(status, "glibc"), True) + self.assertEqual(has_cve_product_match(status, "glibca"), True) + self.assertEqual(has_cve_product_match(status, "aglibc"), True) + self.assertEqual(has_cve_product_match(status, "*"), True) + self.assertEqual(has_cve_product_match(status, "aglibc glibc test:test"), True) + + status["product"] = "glibc" + self.assertEqual(has_cve_product_match(status, "some_vendor:some_product"), False) + # The CPE in the recipe must be defined, no * accepted + self.assertEqual(has_cve_product_match(status, "*:*"), False) + self.assertEqual(has_cve_product_match(status, "*"), False) + self.assertEqual(has_cve_product_match(status, "some_product"), False) + self.assertEqual(has_cve_product_match(status, "glibc"), True) + self.assertEqual(has_cve_product_match(status, "glibca"), False) + self.assertEqual(has_cve_product_match(status, "aglibc"), False) + self.assertEqual(has_cve_product_match(status, "some_vendor:glibc"), True) + self.assertEqual(has_cve_product_match(status, "some_vendor:glibc test"), True) + self.assertEqual(has_cve_product_match(status, "test some_vendor:glibc"), True) + + status["vendor"] = "glibca" + status["product"] = "glibc" + self.assertEqual(has_cve_product_match(status, "some_vendor:some_product"), False) + # The CPE in the recipe must be defined, no * accepted + self.assertEqual(has_cve_product_match(status, "*:*"), False) + self.assertEqual(has_cve_product_match(status, "*"), False) + self.assertEqual(has_cve_product_match(status, "some_product"), False) + self.assertEqual(has_cve_product_match(status, "glibc"), False) + self.assertEqual(has_cve_product_match(status, "glibca"), False) + self.assertEqual(has_cve_product_match(status, "aglibc"), False) + self.assertEqual(has_cve_product_match(status, "some_vendor:glibc"), False) + self.assertEqual(has_cve_product_match(status, "glibca:glibc"), True) + self.assertEqual(has_cve_product_match(status, "test:test glibca:glibc"), True) + self.assertEqual(has_cve_product_match(status, "test glibca:glibc"), True) + self.assertEqual(has_cve_product_match(status, "glibca:glibc test"), True) + def test_recipe_report_json(self): config = """ @@ -217,9 +265,10 @@ CVE_CHECK_REPORT_PATCHED = "1" # m4 CVE should not be in logrotate self.assertNotIn("CVE-2008-1687", found_cves) # logrotate has both Patched and Ignored CVEs + detail = "version-not-in-range" self.assertIn("CVE-2011-1098", found_cves) self.assertEqual(found_cves["CVE-2011-1098"]["status"], "Patched") - self.assertEqual(len(found_cves["CVE-2011-1098"]["detail"]), 0) + self.assertEqual(found_cves["CVE-2011-1098"]["detail"], detail) self.assertEqual(len(found_cves["CVE-2011-1098"]["description"]), 0) detail = "not-applicable-platform" description = "CVE is debian, gentoo or SUSE specific on the way logrotate was installed/used" diff --git a/poky/meta/lib/oeqa/selftest/cases/devtool.py b/poky/meta/lib/oeqa/selftest/cases/devtool.py index 432d9c9a67..8e709944a8 100644 --- a/poky/meta/lib/oeqa/selftest/cases/devtool.py +++ b/poky/meta/lib/oeqa/selftest/cases/devtool.py @@ -317,7 +317,7 @@ class DevtoolBase(DevtoolTestCase): cls.sstate_conf = 'SSTATE_DIR = "%s"\n' % cls.devtool_sstate cls.sstate_conf += ('SSTATE_MIRRORS += "file://.* file:///%s/PATH"\n' % cls.original_sstate) - cls.sstate_conf += ('BB_HASHSERVE_UPSTREAM = "hashserv.yocto.io:8687"\n') + cls.sstate_conf += ('BB_HASHSERVE_UPSTREAM = "hashserv.yoctoproject.org:8686"\n') @classmethod def tearDownClass(cls): @@ -2017,7 +2017,7 @@ class DevtoolUpgradeTests(DevtoolBase): newlines = f.readlines() self.assertEqual(desiredlines, newlines) - def test_devtool_upgrade_recipe_update_extra_tasks(self): + def test_devtool_upgrade_recipe_upgrade_extra_tasks(self): # Check preconditions self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory') self.track_for_cleanup(self.workspacedir) diff --git a/poky/meta/lib/oeqa/selftest/cases/distrodata.py b/poky/meta/lib/oeqa/selftest/cases/distrodata.py index ad952c004b..7771a42e2b 100644 --- a/poky/meta/lib/oeqa/selftest/cases/distrodata.py +++ b/poky/meta/lib/oeqa/selftest/cases/distrodata.py @@ -20,10 +20,10 @@ class Distrodata(OESelftestTestCase): feature = 'LICENSE_FLAGS_ACCEPTED += " commercial"\n' self.write_config(feature) - pkgs = oe.recipeutils.get_recipe_upgrade_status() + pkggroups = 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'] + regressed_failures = [pkg['pn'] for pkgs in pkggroups for pkg in pkgs if pkg['status'] == 'UNKNOWN_BROKEN'] + regressed_successes = [pkg['pn'] for pkgs in pkggroups for pkg in pkgs if pkg['status'] == 'KNOWN_BROKEN'] msg = "" if len(regressed_failures) > 0: msg = msg + """ @@ -55,7 +55,7 @@ but their recipes claim otherwise by setting UPSTREAM_VERSION_UNKNOWN. Please re return False def is_maintainer_exception(entry): - exceptions = ["musl", "newlib", "linux-yocto", "linux-dummy", "mesa-gl", "libgfortran", "libx11-compose-data", + exceptions = ["musl", "newlib", "picolibc", "linux-yocto", "linux-dummy", "mesa-gl", "libgfortran", "libx11-compose-data", "cve-update-nvd2-native",] for i in exceptions: if i in entry: @@ -115,3 +115,15 @@ The list of oe-core recipes with maintainers is empty. This may indicate that th self.fail(""" Unable to find recipes for the following entries in maintainers.inc: """ + "\n".join(['%s' % i for i in missing_recipes])) + + def test_common_include_recipes(self): + """ + Summary: Test that obtaining recipes that share includes between them returns a sane result + Expected: At least cmake and qemu entries are present in the output + Product: oe-core + Author: Alexander Kanavin <alex.kanavin@gmail.com> + """ + recipes = oe.recipeutils.get_common_include_recipes() + + self.assertIn({'qemu-system-native', 'qemu', 'qemu-native'}, recipes) + self.assertIn({'cmake-native', 'cmake'}, recipes) diff --git a/poky/meta/lib/oeqa/selftest/cases/fitimage.py b/poky/meta/lib/oeqa/selftest/cases/fitimage.py index 347c065377..0b5f4602fb 100644 --- a/poky/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/poky/meta/lib/oeqa/selftest/cases/fitimage.py @@ -11,6 +11,51 @@ import re class FitImageTests(OESelftestTestCase): + def _setup_uboot_tools_native(self): + """build u-boot-tools-native and return RECIPE_SYSROOT_NATIVE""" + bitbake("u-boot-tools-native -c addto_recipe_sysroot") + return get_bb_var('RECIPE_SYSROOT_NATIVE', 'u-boot-tools-native') + + def _verify_fit_image_signature(self, uboot_tools_sysroot_native, fitimage_path, dtb_path, conf_name=None): + """Verify the signature of a fit contfiguration + + The fit_check_sign utility from u-boot-tools-native is called. + uboot-fit_check_sign -f fitImage -k $dtb_name -c conf-$dtb_name + """ + fit_check_sign_path = os.path.join(uboot_tools_sysroot_native, 'usr', 'bin', 'uboot-fit_check_sign') + cmd = '%s -f %s -k %s' % (fit_check_sign_path, fitimage_path, dtb_path) + if conf_name: + cmd += ' -c %s' % conf_name + result = runCmd(cmd) + self.logger.debug("%s\nreturned: %s\n%s", cmd, str(result.status), result.output) + self.assertIn("Signature check OK", result.output) + + @staticmethod + def _find_string_in_bin_file(file_path, search_string): + """find stings in a binary file + + Shell equivalent: strings "$1" | grep "$2" | wc -l + return number of matches + """ + found_positions = 0 + with open(file_path, 'rb') as file: + byte = file.read(1) + current_position = 0 + current_match = 0 + while byte: + char = byte.decode('ascii', errors='ignore') + if char == search_string[current_match]: + current_match += 1 + if current_match == len(search_string): + found_positions += 1 + current_match = 0 + else: + current_match = 0 + current_position += 1 + byte = file.read(1) + return found_positions + + def test_fit_image(self): """ Summary: Check if FIT image and Image Tree Source (its) are built @@ -53,10 +98,8 @@ FIT_DESC = "A model description" fitimage_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], "fitImage-%s-%s" % (bb_vars['INITRAMFS_IMAGE_NAME'], bb_vars['KERNEL_FIT_LINK_NAME'])) - self.assertTrue(os.path.exists(fitimage_its_path), - "%s image tree source doesn't exist" % (fitimage_its_path)) - self.assertTrue(os.path.exists(fitimage_path), - "%s FIT image doesn't exist" % (fitimage_path)) + self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path)) + self.assertExists(fitimage_path, "%s FIT image doesn't exist" % (fitimage_path)) # Check that the type, load address, entrypoint address and default # values for kernel and ramdisk in Image Tree Source are as expected. @@ -108,19 +151,21 @@ FIT_DESC = "A model description" Author: Paul Eggleton <paul.eggleton@microsoft.com> based upon work by Usama Arif <usama.arif@arm.com> """ + a_comment = "a smart comment" config = """ # Enable creation of fitImage MACHINE = "beaglebone-yocto" KERNEL_IMAGETYPES += " fitImage " -KERNEL_CLASSES = " kernel-fitimage test-mkimage-wrapper " +KERNEL_CLASSES = " kernel-fitimage " UBOOT_SIGN_ENABLE = "1" FIT_GENERATE_KEYS = "1" UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest" UBOOT_SIGN_KEYNAME = "cfg-oe-selftest" FIT_SIGN_INDIVIDUAL = "1" -UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" -""" +UBOOT_MKIMAGE_SIGN_ARGS = "-c '%s'" +""" % a_comment + self.write_config(config) # fitImage is created as part of linux recipe @@ -133,10 +178,8 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" fitimage_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], "fitImage-%s.bin" % (bb_vars['KERNEL_FIT_LINK_NAME'])) - self.assertTrue(os.path.exists(fitimage_its_path), - "%s image tree source doesn't exist" % (fitimage_its_path)) - self.assertTrue(os.path.exists(fitimage_path), - "%s FIT image doesn't exist" % (fitimage_path)) + self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path)) + self.assertExists(fitimage_path, "%s FIT image doesn't exist" % (fitimage_path)) req_itspaths = [ ['/', 'images', 'kernel-1'], @@ -195,10 +238,8 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" self.assertEqual(value, reqvalue) # Dump the image to see if it really got signed - bitbake("u-boot-tools-native -c addto_recipe_sysroot") - result = runCmd('bitbake -e u-boot-tools-native | grep ^RECIPE_SYSROOT_NATIVE=') - recipe_sysroot_native = result.output.split('=')[1].strip('"') - dumpimage_path = os.path.join(recipe_sysroot_native, 'usr', 'bin', 'dumpimage') + uboot_tools_sysroot_native = self._setup_uboot_tools_native() + dumpimage_path = os.path.join(uboot_tools_sysroot_native, 'usr', 'bin', 'dumpimage') result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path)) in_signed = None signed_sections = {} @@ -224,17 +265,15 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" value = values.get('Sign value', None) self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section) - # Check for UBOOT_MKIMAGE_SIGN_ARGS - result = runCmd('bitbake -e virtual/kernel | grep ^T=') - tempdir = result.output.split('=', 1)[1].strip().strip('') - result = runCmd('grep "a smart comment" %s/run.do_assemble_fitimage' % tempdir, ignore_status=True) - self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN_ARGS value did not get used') + # Search for the string passed to mkimage: 1 kernel + 3 DTBs + config per DTB = 7 sections + # Looks like mkimage supports to add a comment but does not support to read it back. + found_comments = FitImageTests._find_string_in_bin_file(fitimage_path, a_comment) + self.assertEqual(found_comments, 7, "Expected 7 signed and commented section in the fitImage.") - # Check for evidence of test-mkimage-wrapper class - result = runCmd('grep "### uboot-mkimage wrapper message" %s/log.do_assemble_fitimage' % tempdir, ignore_status=True) - self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE did not work') - result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_assemble_fitimage' % tempdir, ignore_status=True) - self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work') + # Verify the signature for all configurations = DTBs + for dtb in ['am335x-bone.dtb', 'am335x-boneblack.dtb', 'am335x-bonegreen.dtb']: + self._verify_fit_image_signature(uboot_tools_sysroot_native, fitimage_path, + os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], dtb), 'conf-' + dtb) def test_uboot_fit_image(self): """ @@ -287,10 +326,8 @@ FIT_SIGN_INDIVIDUAL = "1" fitimage_path = os.path.join(deploy_dir_image, "u-boot-fitImage-%s" % (machine,)) - self.assertTrue(os.path.exists(fitimage_its_path), - "%s image tree source doesn't exist" % (fitimage_its_path)) - self.assertTrue(os.path.exists(fitimage_path), - "%s FIT image doesn't exist" % (fitimage_path)) + self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path)) + self.assertExists(fitimage_path, "%s FIT image doesn't exist" % (fitimage_path)) # Check that the type, load address, entrypoint address and default # values for kernel and ramdisk in Image Tree Source are as expected. @@ -351,7 +388,6 @@ UBOOT_ENTRYPOINT = "0x80080000" UBOOT_FIT_DESC = "A model description" KERNEL_IMAGETYPES += " fitImage " KERNEL_CLASSES = " kernel-fitimage " -INHERIT += "test-mkimage-wrapper" UBOOT_SIGN_ENABLE = "1" FIT_GENERATE_KEYS = "1" UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" @@ -372,10 +408,8 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart U-Boot comment'" fitimage_path = os.path.join(deploy_dir_image, "u-boot-fitImage-%s" % (machine,)) - self.assertTrue(os.path.exists(fitimage_its_path), - "%s image tree source doesn't exist" % (fitimage_its_path)) - self.assertTrue(os.path.exists(fitimage_path), - "%s FIT image doesn't exist" % (fitimage_path)) + self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path)) + self.assertExists(fitimage_path, "%s FIT image doesn't exist" % (fitimage_path)) # Check that the type, load address, entrypoint address and default # values for kernel and ramdisk in Image Tree Source are as expected. @@ -425,6 +459,7 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart U-Boot comment'" work by Paul Eggleton <paul.eggleton@microsoft.com> and Usama Arif <usama.arif@arm.com> """ + a_comment = "a smart U-Boot comment" config = """ # There's no U-boot deconfig with CONFIG_FIT_SIGNATURE yet, so we need at # least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set @@ -434,7 +469,6 @@ SPL_BINARY = "MLO" # The kernel-fitimage class is a dependency even if we're only # creating/signing the U-Boot fitImage KERNEL_CLASSES = " kernel-fitimage" -INHERIT += "test-mkimage-wrapper" # Enable creation and signing of the U-Boot fitImage UBOOT_FITIMAGE_ENABLE = "1" SPL_SIGN_ENABLE = "1" @@ -446,17 +480,17 @@ UBOOT_LOADADDRESS = "0x80000000" UBOOT_DTB_LOADADDRESS = "0x82000000" UBOOT_ARCH = "arm" SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" -SPL_MKIMAGE_SIGN_ARGS = "-c 'a smart U-Boot comment'" +SPL_MKIMAGE_SIGN_ARGS = "-c '%s'" UBOOT_EXTLINUX = "0" UBOOT_FIT_GENERATE_KEYS = "1" UBOOT_FIT_HASH_ALG = "sha256" -""" +""" % a_comment + self.write_config(config) # The U-Boot fitImage is created as part of the U-Boot recipe bitbake("virtual/bootloader") - image_type = "core-image-minimal" deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') machine = get_bb_var('MACHINE') fitimage_its_path = os.path.join(deploy_dir_image, @@ -464,10 +498,8 @@ UBOOT_FIT_HASH_ALG = "sha256" fitimage_path = os.path.join(deploy_dir_image, "u-boot-fitImage-%s" % (machine,)) - self.assertTrue(os.path.exists(fitimage_its_path), - "%s image tree source doesn't exist" % (fitimage_its_path)) - self.assertTrue(os.path.exists(fitimage_path), - "%s FIT image doesn't exist" % (fitimage_path)) + self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path)) + self.assertExists(fitimage_path, "%s FIT image doesn't exist" % (fitimage_path)) req_itspaths = [ ['/', 'images', 'uboot'], @@ -516,10 +548,8 @@ UBOOT_FIT_HASH_ALG = "sha256" self.assertEqual(value, reqvalue) # Dump the image to see if it really got signed - bitbake("u-boot-tools-native -c addto_recipe_sysroot") - result = runCmd('bitbake -e u-boot-tools-native | grep ^RECIPE_SYSROOT_NATIVE=') - recipe_sysroot_native = result.output.split('=')[1].strip('"') - dumpimage_path = os.path.join(recipe_sysroot_native, 'usr', 'bin', 'dumpimage') + uboot_tools_sysroot_native = self._setup_uboot_tools_native() + dumpimage_path = os.path.join(uboot_tools_sysroot_native, 'usr', 'bin', 'dumpimage') result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path)) in_signed = None signed_sections = {} @@ -542,16 +572,14 @@ UBOOT_FIT_HASH_ALG = "sha256" self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section) # Check for SPL_MKIMAGE_SIGN_ARGS - result = runCmd('bitbake -e virtual/bootloader | grep ^T=') - tempdir = result.output.split('=', 1)[1].strip().strip('') - result = runCmd('grep "a smart U-Boot comment" %s/run.do_uboot_assemble_fitimage' % tempdir, ignore_status=True) - self.assertEqual(result.status, 0, 'SPL_MKIMAGE_SIGN_ARGS value did not get used') + # Looks like mkimage supports to add a comment but does not support to read it back. + found_comments = FitImageTests._find_string_in_bin_file(fitimage_path, a_comment) + self.assertEqual(found_comments, 2, "Expected 2 signed and commented section in the fitImage.") + + # Verify the signature + self._verify_fit_image_signature(uboot_tools_sysroot_native, fitimage_path, + os.path.join(deploy_dir_image, 'u-boot-spl.dtb')) - # Check for evidence of test-mkimage-wrapper class - result = runCmd('grep "### uboot-mkimage wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True) - self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE did not work') - result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True) - self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work') def test_sign_cascaded_uboot_fit_image(self): """ @@ -573,6 +601,7 @@ UBOOT_FIT_HASH_ALG = "sha256" work by Paul Eggleton <paul.eggleton@microsoft.com> and Usama Arif <usama.arif@arm.com> """ + a_comment = "a smart cascaded U-Boot comment" config = """ # There's no U-boot deconfig with CONFIG_FIT_SIGNATURE yet, so we need at # least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set @@ -588,7 +617,7 @@ UBOOT_DTB_BINARY = "u-boot.dtb" UBOOT_ENTRYPOINT = "0x80000000" UBOOT_LOADADDRESS = "0x80000000" UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" -UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart cascaded Kernel comment'" +UBOOT_MKIMAGE_SIGN_ARGS = "-c '%s'" UBOOT_DTB_LOADADDRESS = "0x82000000" UBOOT_ARCH = "arm" SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" @@ -598,20 +627,18 @@ UBOOT_FIT_GENERATE_KEYS = "1" UBOOT_FIT_HASH_ALG = "sha256" KERNEL_IMAGETYPES += " fitImage " KERNEL_CLASSES = " kernel-fitimage " -INHERIT += "test-mkimage-wrapper" UBOOT_SIGN_ENABLE = "1" FIT_GENERATE_KEYS = "1" UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest" UBOOT_SIGN_KEYNAME = "cfg-oe-selftest" FIT_SIGN_INDIVIDUAL = "1" -""" +""" % a_comment self.write_config(config) # The U-Boot fitImage is created as part of the U-Boot recipe bitbake("virtual/bootloader") - image_type = "core-image-minimal" deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') machine = get_bb_var('MACHINE') fitimage_its_path = os.path.join(deploy_dir_image, @@ -619,10 +646,8 @@ FIT_SIGN_INDIVIDUAL = "1" fitimage_path = os.path.join(deploy_dir_image, "u-boot-fitImage-%s" % (machine,)) - self.assertTrue(os.path.exists(fitimage_its_path), - "%s image tree source doesn't exist" % (fitimage_its_path)) - self.assertTrue(os.path.exists(fitimage_path), - "%s FIT image doesn't exist" % (fitimage_path)) + self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path)) + self.assertExists(fitimage_path, "%s FIT image doesn't exist" % (fitimage_path)) req_itspaths = [ ['/', 'images', 'uboot'], @@ -671,10 +696,8 @@ FIT_SIGN_INDIVIDUAL = "1" self.assertEqual(value, reqvalue) # Dump the image to see if it really got signed - bitbake("u-boot-tools-native -c addto_recipe_sysroot") - result = runCmd('bitbake -e u-boot-tools-native | grep ^RECIPE_SYSROOT_NATIVE=') - recipe_sysroot_native = result.output.split('=')[1].strip('"') - dumpimage_path = os.path.join(recipe_sysroot_native, 'usr', 'bin', 'dumpimage') + uboot_tools_sysroot_native = self._setup_uboot_tools_native() + dumpimage_path = os.path.join(uboot_tools_sysroot_native, 'usr', 'bin', 'dumpimage') result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path)) in_signed = None signed_sections = {} @@ -697,17 +720,13 @@ FIT_SIGN_INDIVIDUAL = "1" self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section) # Check for SPL_MKIMAGE_SIGN_ARGS - result = runCmd('bitbake -e virtual/bootloader | grep ^T=') - tempdir = result.output.split('=', 1)[1].strip().strip('') - result = runCmd('grep "a smart cascaded U-Boot comment" %s/run.do_uboot_assemble_fitimage' % tempdir, ignore_status=True) - self.assertEqual(result.status, 0, 'SPL_MKIMAGE_SIGN_ARGS value did not get used') - - # Check for evidence of test-mkimage-wrapper class - result = runCmd('grep "### uboot-mkimage wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True) - self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE did not work') - result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True) - self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work') + # Looks like mkimage supports to add a comment but does not support to read it back. + found_comments = FitImageTests._find_string_in_bin_file(fitimage_path, a_comment) + self.assertEqual(found_comments, 2, "Expected 2 signed and commented section in the fitImage.") + # Verify the signature + self._verify_fit_image_signature(uboot_tools_sysroot_native, fitimage_path, + os.path.join(deploy_dir_image, 'u-boot-spl.dtb')) def test_initramfs_bundle(self): @@ -755,24 +774,24 @@ FIT_HASH_ALG = "sha256" # fitImage is created as part of linux recipe bitbake("virtual/kernel") - image_type = get_bb_var('INITRAMFS_IMAGE') - deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') - machine = get_bb_var('MACHINE') - fitimage_its_path = os.path.join(deploy_dir_image, - "fitImage-its-%s-%s-%s" % (image_type, machine, machine)) - fitimage_path = os.path.join(deploy_dir_image,"fitImage") - - self.assertTrue(os.path.exists(fitimage_its_path), - "%s image tree source doesn't exist" % (fitimage_its_path)) - self.assertTrue(os.path.exists(fitimage_path), - "%s FIT image doesn't exist" % (fitimage_path)) + bb_vars = get_bb_vars([ + 'DEPLOY_DIR_IMAGE', + 'FIT_HASH_ALG', + 'FIT_KERNEL_COMP_ALG', + 'INITRAMFS_IMAGE', + 'MACHINE', + 'UBOOT_ARCH', + 'UBOOT_ENTRYPOINT', + 'UBOOT_LOADADDRESS', + 'UBOOT_MKIMAGE_KERNEL_TYPE' + ], + 'virtual/kernel') + fitimage_its_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], + "fitImage-its-%s-%s-%s" % (bb_vars['INITRAMFS_IMAGE'], bb_vars['MACHINE'], bb_vars['MACHINE'])) + fitimage_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'],"fitImage") - kernel_load = str(get_bb_var('UBOOT_LOADADDRESS')) - kernel_entry = str(get_bb_var('UBOOT_ENTRYPOINT')) - kernel_type = str(get_bb_var('UBOOT_MKIMAGE_KERNEL_TYPE')) - kernel_compression = str(get_bb_var('FIT_KERNEL_COMP_ALG')) - uboot_arch = str(get_bb_var('UBOOT_ARCH')) - fit_hash_alg = str(get_bb_var('FIT_HASH_ALG')) + self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path)) + self.assertExists(fitimage_path, "%s FIT image doesn't exist" % (fitimage_path)) its_file = open(fitimage_its_path) @@ -782,31 +801,31 @@ FIT_HASH_ALG = "sha256" 'kernel-1 {', 'description = "Linux kernel";', 'data = /incbin/("linux.bin");', - 'type = "' + kernel_type + '";', - 'arch = "' + uboot_arch + '";', + 'type = "' + str(bb_vars['UBOOT_MKIMAGE_KERNEL_TYPE']) + '";', + 'arch = "' + str(bb_vars['UBOOT_ARCH']) + '";', 'os = "linux";', - 'compression = "' + kernel_compression + '";', - 'load = <' + kernel_load + '>;', - 'entry = <' + kernel_entry + '>;', + 'compression = "' + str(bb_vars['FIT_KERNEL_COMP_ALG']) + '";', + 'load = <' + str(bb_vars['UBOOT_LOADADDRESS']) + '>;', + 'entry = <' + str(bb_vars['UBOOT_ENTRYPOINT']) + '>;', 'hash-1 {', - 'algo = "' + fit_hash_alg +'";', + 'algo = "' + str(bb_vars['FIT_HASH_ALG']) +'";', '};', '};' ] node_str = exp_node_lines[0] - test_passed = False - print ("checking kernel node\n") + self.assertIn(node_str, its_lines) - if node_str in its_lines: - node_start_idx = its_lines.index(node_str) - node = its_lines[node_start_idx:(node_start_idx + len(exp_node_lines))] - if node == exp_node_lines: - print("kernel node verified") - else: - self.assertTrue(test_passed == True,"kernel node does not match expectation") + node_start_idx = its_lines.index(node_str) + node = its_lines[node_start_idx:(node_start_idx + len(exp_node_lines))] + + # Remove the absolute path. This refers to WORKDIR which is not always predictable. + re_data = re.compile(r'^data = /incbin/\(.*/linux\.bin"\);$') + node = [re.sub(re_data, 'data = /incbin/("linux.bin");', cfg_str) for cfg_str in node] + + self.assertEqual(node, exp_node_lines, "kernel node does not match expectation") rx_configs = re.compile("^conf-.*") its_configs = list(filter(rx_configs.match, its_lines)) @@ -822,25 +841,14 @@ FIT_HASH_ALG = "sha256" node = its_lines[cfg_start_idx:line_idx] print("checking configuration " + cfg_str.rstrip(" {")) - rx_desc_line = re.compile("^description.*1 Linux kernel.*") - if len(list(filter(rx_desc_line.match, node))) != 1: - self.assertTrue(test_passed == True,"kernel keyword not found in the description line") - break - else: - print("kernel keyword found in the description line") + rx_desc_line = re.compile(r'^description = ".*Linux kernel.*') + self.assertEqual(len(list(filter(rx_desc_line.match, node))), 1, "kernel keyword not found in the description line") - if 'kernel = "kernel-1";' not in node: - self.assertTrue(test_passed == True,"kernel line not found") - break - else: - print("kernel line found") + self.assertIn('kernel = "kernel-1";', node) - rx_sign_line = re.compile("^sign-images.*kernel.*") - if len(list(filter(rx_sign_line.match, node))) != 1: - self.assertTrue(test_passed == True,"kernel hash not signed") - break - else: - print("kernel hash signed") + rx_sign_line = re.compile(r'^sign-images = .*kernel.*') + self.assertEqual(len(list(filter(rx_sign_line.match, node))), 1, "kernel hash not signed") - test_passed = True - self.assertTrue(test_passed == True,"Initramfs bundle test success") + # Verify the signature + uboot_tools_sysroot_native = self._setup_uboot_tools_native() + self._verify_fit_image_signature(uboot_tools_sysroot_native, fitimage_path, os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], 'am335x-bone.dtb')) diff --git a/poky/meta/lib/oeqa/selftest/cases/gcc.py b/poky/meta/lib/oeqa/selftest/cases/gcc.py index 89360178fe..1bda29a72b 100644 --- a/poky/meta/lib/oeqa/selftest/cases/gcc.py +++ b/poky/meta/lib/oeqa/selftest/cases/gcc.py @@ -37,7 +37,7 @@ class GccSelfTestBase(OESelftestTestCase, OEPTestResultTestCase): 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_TARGET = "linux-ssh"') features.append('TOOLCHAIN_TEST_HOST = "{0}"'.format(ssh)) features.append('TOOLCHAIN_TEST_HOST_USER = "root"') features.append('TOOLCHAIN_TEST_HOST_PORT = "22"') @@ -83,6 +83,8 @@ class GccSelfTestBase(OESelftestTestCase, OEPTestResultTestCase): # validate that SSH is working status, _ = qemu.run("uname") self.assertEqual(status, 0) + qemu.run('echo "MaxStartups 75:30:100" >> /etc/ssh/sshd_config') + qemu.run('service sshd restart') return self.run_check(*args, ssh=qemu.ip, **kwargs) diff --git a/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py b/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py index dc88c222bd..94d01ba116 100644 --- a/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py +++ b/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py @@ -250,12 +250,7 @@ USERADD_GID_TABLES += "files/static-group" DISTRO_FEATURES:append = " pam opengl wayland" # Switch to systemd -DISTRO_FEATURES:append = " systemd usrmerge" -VIRTUAL-RUNTIME_init_manager = "systemd" -VIRTUAL-RUNTIME_initscripts = "" -VIRTUAL-RUNTIME_syslog = "" -VIRTUAL-RUNTIME_login_manager = "shadow-base" -DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit" +INIT_MANAGER = "systemd" # Replace busybox PREFERRED_PROVIDER_virtual/base-utils = "packagegroup-core-base-utils" @@ -319,7 +314,7 @@ SKIP_RECIPE[busybox] = "Don't build this" """ config = """ DISTRO_FEATURES:append = " api-documentation" -CORE_IMAGE_EXTRA_INSTALL = "man-pages kmod-doc" +CORE_IMAGE_EXTRA_INSTALL = "man-pages" """ self.write_config(config) bitbake("core-image-minimal") @@ -330,7 +325,7 @@ CORE_IMAGE_EXTRA_INSTALL = "man-pages kmod-doc" self.assertEqual(status, 1, 'Failed to run apropos: %s' % (output)) self.assertIn("iso_8859_15", output) - # This manpage is provided by kmod - status, output = qemu.run_serial("man --pager=cat modprobe") + # This manpage is provided by man-pages + status, output = qemu.run_serial("man --pager=cat intro") self.assertEqual(status, 1, 'Failed to run man: %s' % (output)) - self.assertIn("force-modversion", output) + self.assertIn("introduction to user commands", output) diff --git a/poky/meta/lib/oeqa/selftest/cases/incompatible_lic.py b/poky/meta/lib/oeqa/selftest/cases/incompatible_lic.py index f4af67a239..be5484bca4 100644 --- a/poky/meta/lib/oeqa/selftest/cases/incompatible_lic.py +++ b/poky/meta/lib/oeqa/selftest/cases/incompatible_lic.py @@ -114,7 +114,7 @@ INCOMPATIBLE_LICENSE:pn-core-image-minimal = "GPL-3.0* LGPL-3.0*" def test_bash_and_license(self): self.disable_class("create-spdx") - self.write_config(self.default_config() + '\nLICENSE:append:pn-bash = " & SomeLicense"') + self.write_config(self.default_config() + '\nLICENSE:append:pn-bash = " & SomeLicense"\nERROR_QA:remove:pn-bash = "license-exists"') 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-or-later" result = bitbake('core-image-minimal', ignore_status=True) @@ -123,12 +123,12 @@ INCOMPATIBLE_LICENSE:pn-core-image-minimal = "GPL-3.0* LGPL-3.0*" def test_bash_or_license(self): self.disable_class("create-spdx") - self.write_config(self.default_config() + '\nLICENSE:append:pn-bash = " | SomeLicense"') + self.write_config(self.default_config() + '\nLICENSE:append:pn-bash = " | SomeLicense"\nERROR_QA:remove:pn-bash = "license-exists"\nERROR_QA:remove:pn-core-image-minimal = "license-file-missing"') bitbake('core-image-minimal') def test_bash_license_exceptions(self): - self.write_config(self.default_config() + '\nINCOMPATIBLE_LICENSE_EXCEPTIONS:pn-core-image-minimal = "bash:GPL-3.0-or-later"') + self.write_config(self.default_config() + '\nINCOMPATIBLE_LICENSE_EXCEPTIONS:pn-core-image-minimal = "bash:GPL-3.0-or-later"\nERROR_QA:remove:pn-core-image-minimal = "license-exception"') bitbake('core-image-minimal') diff --git a/poky/meta/lib/oeqa/selftest/cases/locales.py b/poky/meta/lib/oeqa/selftest/cases/locales.py index 4ca8ffb7aa..ac4888ef66 100644 --- a/poky/meta/lib/oeqa/selftest/cases/locales.py +++ b/poky/meta/lib/oeqa/selftest/cases/locales.py @@ -14,7 +14,7 @@ class LocalesTest(OESelftestTestCase): features = [] features.append('EXTRA_IMAGE_FEATURES = "empty-root-password allow-empty-password allow-root-login"') features.append('IMAGE_INSTALL:append = " glibc-utils localedef"') - features.append('GLIBC_GENERATE_LOCALES = "en_US.UTF-8 fr_FR.UTF-8"') + features.append('GLIBC_GENERATE_LOCALES = "en_US.UTF-8 fr_FR.UTF-8 en_US.ISO-8859-1 de_DE.UTF-8 fr_FR.ISO-8859-1 zh_HK.BIG5-HKSCS tr_TR.UTF-8"') features.append('IMAGE_LINGUAS:append = " en-us fr-fr"') if binary_enabled: features.append('ENABLE_BINARY_LOCALE_GENERATION = "1"') diff --git a/poky/meta/lib/oeqa/selftest/cases/meta_ide.py b/poky/meta/lib/oeqa/selftest/cases/meta_ide.py index ffe0d2604d..5a17ca52ea 100644 --- a/poky/meta/lib/oeqa/selftest/cases/meta_ide.py +++ b/poky/meta/lib/oeqa/selftest/cases/meta_ide.py @@ -20,8 +20,8 @@ class MetaIDE(OESelftestTestCase): bitbake('meta-ide-support') bitbake('build-sysroots -c build_native_sysroot') bitbake('build-sysroots -c build_target_sysroot') - bb_vars = get_bb_vars(['MULTIMACH_TARGET_SYS', 'DEPLOY_DIR_IMAGE', 'COREBASE']) - cls.environment_script = 'environment-setup-%s' % bb_vars['MULTIMACH_TARGET_SYS'] + bb_vars = get_bb_vars(['MACHINE_ARCH', 'TARGET_VENDOR', 'TARGET_OS', 'DEPLOY_DIR_IMAGE', 'COREBASE']) + cls.environment_script = 'environment-setup-%s%s-%s' % (bb_vars['MACHINE_ARCH'], bb_vars['TARGET_VENDOR'], bb_vars['TARGET_OS']) cls.deploydir = bb_vars['DEPLOY_DIR_IMAGE'] cls.environment_script_path = '%s/%s' % (cls.deploydir, cls.environment_script) cls.corebasedir = bb_vars['COREBASE'] diff --git a/poky/meta/lib/oeqa/selftest/cases/oescripts.py b/poky/meta/lib/oeqa/selftest/cases/oescripts.py index fcfe54af74..bfbc33b08d 100644 --- a/poky/meta/lib/oeqa/selftest/cases/oescripts.py +++ b/poky/meta/lib/oeqa/selftest/cases/oescripts.py @@ -175,7 +175,7 @@ class OEListPackageconfigTests(OESelftestTestCase): 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.3.0") + expected_endlines.append("pinentry-1.3.1") expected_endlines.append("PACKAGECONFIG ncurses") 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") diff --git a/poky/meta/lib/oeqa/selftest/cases/overlayfs.py b/poky/meta/lib/oeqa/selftest/cases/overlayfs.py index e31063567b..580fbdcb9c 100644 --- a/poky/meta/lib/oeqa/selftest/cases/overlayfs.py +++ b/poky/meta/lib/oeqa/selftest/cases/overlayfs.py @@ -5,7 +5,7 @@ # from oeqa.selftest.case import OESelftestTestCase -from oeqa.utils.commands import bitbake, runqemu +from oeqa.utils.commands import bitbake, runqemu, get_bb_vars from oeqa.core.decorator import OETestTag from oeqa.core.decorator.data import skipIfNotMachine @@ -466,6 +466,45 @@ IMAGE_INSTALL:append = " overlayfs-user" line = getline_qemu(output, "Read-only file system") self.assertTrue(line, msg=output) + @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently") + def test_postinst_on_target_for_read_only_rootfs(self): + """ + Summary: The purpose of this test case is to verify that post-installation + on target scripts are executed even if using read-only rootfs when + read-only-rootfs-delayed-postinsts is set + Expected: The test files are created on first boot + """ + + import oe.path + + vars = get_bb_vars(("IMAGE_ROOTFS", "sysconfdir"), "core-image-minimal") + sysconfdir = vars["sysconfdir"] + self.assertIsNotNone(sysconfdir) + # Need to use oe.path here as sysconfdir starts with / + targettestdir = os.path.join(sysconfdir, "postinst-test") + + config = self.get_working_config() + + args = { + 'OVERLAYFS_INIT_OPTION': "", + 'OVERLAYFS_ETC_USE_ORIG_INIT_NAME': 1, + 'OVERLAYFS_ROOTFS_TYPE': "ext4", + 'OVERLAYFS_ETC_CREATE_MOUNT_DIRS': 1 + } + + # read-only-rootfs is already set in get_working_config() + config += 'EXTRA_IMAGE_FEATURES += "read-only-rootfs-delayed-postinsts"\n' + config += 'CORE_IMAGE_EXTRA_INSTALL = "postinst-delayed-b"\n' + + self.write_config(config.format(**args)) + + res = bitbake('core-image-minimal') + + with runqemu('core-image-minimal', image_fstype='wic') as qemu: + for filename in ("rootfs", "delayed-a", "delayed-b"): + status, output = qemu.run_serial("test -f %s && echo found" % os.path.join(targettestdir, filename)) + self.assertIn("found", output, "%s was not present on boot" % filename) + def get_working_config(self): return """ # Use systemd as init manager diff --git a/poky/meta/lib/oeqa/selftest/cases/package.py b/poky/meta/lib/oeqa/selftest/cases/package.py index 1aa6c03f8a..38ed7173fe 100644 --- a/poky/meta/lib/oeqa/selftest/cases/package.py +++ b/poky/meta/lib/oeqa/selftest/cases/package.py @@ -103,11 +103,37 @@ class PackageTests(OESelftestTestCase): dest = get_bb_var('PKGDEST', 'selftest-hardlink') bindir = get_bb_var('bindir', 'selftest-hardlink') + libdir = get_bb_var('libdir', 'selftest-hardlink') + libexecdir = get_bb_var('libexecdir', 'selftest-hardlink') def checkfiles(): # Recipe creates 4 hardlinked files, there is a copy in package/ and a copy in packages-split/ # so expect 8 in total. self.assertEqual(os.stat(dest + "/selftest-hardlink" + bindir + "/hello1").st_nlink, 8) + self.assertEqual(os.stat(dest + "/selftest-hardlink" + libexecdir + "/hello3").st_nlink, 8) + + # Check dbg version + # 2 items, a copy in both package/packages-split so 4 + self.assertEqual(os.stat(dest + "/selftest-hardlink-dbg" + bindir + "/.debug/hello1").st_nlink, 4) + self.assertEqual(os.stat(dest + "/selftest-hardlink-dbg" + libexecdir + "/.debug/hello1").st_nlink, 4) + + # Even though the libexecdir name is 'hello3' or 'hello4', that isn't the debug target name + self.assertEqual(os.path.exists(dest + "/selftest-hardlink-dbg" + libexecdir + "/.debug/hello3"), False) + self.assertEqual(os.path.exists(dest + "/selftest-hardlink-dbg" + libexecdir + "/.debug/hello4"), False) + + # Check the staticdev libraries + # 101 items, a copy in both package/packages-split so 202 + self.assertEqual(os.stat(dest + "/selftest-hardlink-staticdev" + libdir + "/libhello.a").st_nlink, 202) + self.assertEqual(os.stat(dest + "/selftest-hardlink-staticdev" + libdir + "/libhello-25.a").st_nlink, 202) + self.assertEqual(os.stat(dest + "/selftest-hardlink-staticdev" + libdir + "/libhello-50.a").st_nlink, 202) + self.assertEqual(os.stat(dest + "/selftest-hardlink-staticdev" + libdir + "/libhello-75.a").st_nlink, 202) + + # Check static dbg + # 101 items, a copy in both package/packages-split so 202 + self.assertEqual(os.stat(dest + "/selftest-hardlink-dbg" + libdir + "/.debug-static/libhello.a").st_nlink, 202) + self.assertEqual(os.stat(dest + "/selftest-hardlink-dbg" + libdir + "/.debug-static/libhello-25.a").st_nlink, 202) + self.assertEqual(os.stat(dest + "/selftest-hardlink-dbg" + libdir + "/.debug-static/libhello-50.a").st_nlink, 202) + self.assertEqual(os.stat(dest + "/selftest-hardlink-dbg" + libdir + "/.debug-static/libhello-75.a").st_nlink, 202) # Test a sparse file remains sparse sparsestat = os.stat(dest + "/selftest-hardlink" + bindir + "/sparsetest") diff --git a/poky/meta/lib/oeqa/selftest/cases/picolibc.py b/poky/meta/lib/oeqa/selftest/cases/picolibc.py new file mode 100644 index 0000000000..e40b4fc3d3 --- /dev/null +++ b/poky/meta/lib/oeqa/selftest/cases/picolibc.py @@ -0,0 +1,18 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import bitbake, get_bb_var + +class PicolibcTest(OESelftestTestCase): + + def test_picolibc(self): + compatible_machines = ['qemuarm', 'qemuarm64', 'qemuriscv32', 'qemuriscv64'] + machine = get_bb_var('MACHINE') + if machine not in compatible_machines: + self.skipTest('This test only works with machines : %s' % ' '.join(compatible_machines)) + self.write_config('TCLIBC = "picolibc"') + bitbake("picolibc-helloworld") diff --git a/poky/meta/lib/oeqa/selftest/cases/recipetool.py b/poky/meta/lib/oeqa/selftest/cases/recipetool.py index 42202b7831..f742dd4d64 100644 --- a/poky/meta/lib/oeqa/selftest/cases/recipetool.py +++ b/poky/meta/lib/oeqa/selftest/cases/recipetool.py @@ -1068,6 +1068,7 @@ class RecipetoolTests(RecipetoolBase): d = DataConnectorCopy d.getVar = Mock(return_value=commonlicdir) + d.expand = Mock(side_effect=lambda x: x) srctree = tempfile.mkdtemp(prefix='recipetoolqa') self.track_for_cleanup(srctree) diff --git a/poky/meta/lib/oeqa/selftest/cases/reproducible.py b/poky/meta/lib/oeqa/selftest/cases/reproducible.py index 97a9c3da90..92266ab66a 100644 --- a/poky/meta/lib/oeqa/selftest/cases/reproducible.py +++ b/poky/meta/lib/oeqa/selftest/cases/reproducible.py @@ -16,8 +16,6 @@ import os import datetime exclude_packages = [ - 'rust-rustdoc', - 'rust-dbg' ] def is_excluded(package): @@ -135,7 +133,8 @@ class ReproducibleTests(OESelftestTestCase): max_report_size = 250 * 1024 * 1024 # targets are the things we want to test the reproducibility of - targets = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline', 'core-image-weston', 'world'] + # Have to add the virtual targets manually for now as builds may or may not include them as they're exclude from world + targets = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline', 'core-image-weston', 'world', 'virtual/librpc', 'virtual/libsdl2', 'virtual/crypt'] # sstate targets are things to pull from sstate to potentially cut build/debugging time sstate_targets = [] @@ -178,12 +177,8 @@ class ReproducibleTests(OESelftestTestCase): self.sstate_targets = bb_vars['OEQA_REPRODUCIBLE_TEST_SSTATE_TARGETS'].split() 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(self.oeqa_reproducible_excluded_packages) @@ -210,7 +205,7 @@ class ReproducibleTests(OESelftestTestCase): 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] + p.reference.split("/./")[1] for p in packages] def copy_file(self, source, dest): bb.utils.mkdirhier(os.path.dirname(dest)) @@ -275,9 +270,13 @@ class ReproducibleTests(OESelftestTestCase): 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) + # The below bug shows that a few reproducible issues are depends on build dir path length. + # https://bugzilla.yoctoproject.org/show_bug.cgi?id=15554 + # So, the reproducibleA & reproducibleB directories are changed to reproducibleA & reproducibleB-extended to have different size. + vars_A = self.do_test_build('reproducibleA', self.build_from_sstate) - vars_B = self.do_test_build('reproducibleB', False) + vars_B = self.do_test_build('reproducibleB-extended', False) # NOTE: The temp directories from the reproducible build are purposely # kept after the build so it can be diffed for debugging. @@ -296,8 +295,6 @@ class ReproducibleTests(OESelftestTestCase): 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, 'different_excluded', result.different_excluded) @@ -332,7 +329,7 @@ class ReproducibleTests(OESelftestTestCase): # 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')) - run_diffoscope('reproducibleA', 'reproducibleB', package_html_dir, max_report_size=self.max_report_size, + run_diffoscope('reproducibleA', 'reproducibleB-extended', package_html_dir, max_report_size=self.max_report_size, native_sysroot=diffoscope_sysroot, ignore_status=True, cwd=package_dir) if fails: diff --git a/poky/meta/lib/oeqa/selftest/cases/retain.py b/poky/meta/lib/oeqa/selftest/cases/retain.py new file mode 100644 index 0000000000..892be45857 --- /dev/null +++ b/poky/meta/lib/oeqa/selftest/cases/retain.py @@ -0,0 +1,241 @@ +# Tests for retain.bbclass +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +import os +import glob +import fnmatch +import oe.path +import shutil +import tarfile +from oeqa.utils.commands import bitbake, get_bb_vars +from oeqa.selftest.case import OESelftestTestCase + +class Retain(OESelftestTestCase): + + def test_retain_always(self): + """ + Summary: Test retain class with RETAIN_DIRS_ALWAYS + Expected: Archive written to RETAIN_OUTDIR when build of test recipe completes + Product: oe-core + Author: Paul Eggleton <paul.eggleton@microsoft.com> + """ + + test_recipe = 'quilt-native' + + features = 'INHERIT += "retain"\n' + features += 'RETAIN_DIRS_ALWAYS = "${T}"\n' + self.write_config(features) + + bitbake('-c clean %s' % test_recipe) + + bb_vars = get_bb_vars(['RETAIN_OUTDIR', 'TMPDIR']) + retain_outdir = bb_vars['RETAIN_OUTDIR'] or '' + tmpdir = bb_vars['TMPDIR'] + if len(retain_outdir) < 5: + self.fail('RETAIN_OUTDIR value "%s" is invalid' % retain_outdir) + if not oe.path.is_path_parent(tmpdir, retain_outdir): + self.fail('RETAIN_OUTDIR (%s) is not underneath TMPDIR (%s)' % (retain_outdir, tmpdir)) + try: + shutil.rmtree(retain_outdir) + except FileNotFoundError: + pass + + bitbake(test_recipe) + if not glob.glob(os.path.join(retain_outdir, '%s_temp_*.tar.gz' % test_recipe)): + self.fail('No output archive for %s created' % test_recipe) + + + def test_retain_failure(self): + """ + Summary: Test retain class default behaviour + Expected: Archive written to RETAIN_OUTDIR only when build of test + recipe fails, and archive contents are as expected + Product: oe-core + Author: Paul Eggleton <paul.eggleton@microsoft.com> + """ + + test_recipe_fail = 'error' + + features = 'INHERIT += "retain"\n' + self.write_config(features) + + bb_vars = get_bb_vars(['RETAIN_OUTDIR', 'TMPDIR', 'RETAIN_DIRS_ALWAYS', 'RETAIN_DIRS_GLOBAL_ALWAYS']) + if bb_vars['RETAIN_DIRS_ALWAYS']: + self.fail('RETAIN_DIRS_ALWAYS is set, this interferes with the test') + if bb_vars['RETAIN_DIRS_GLOBAL_ALWAYS']: + self.fail('RETAIN_DIRS_GLOBAL_ALWAYS is set, this interferes with the test') + retain_outdir = bb_vars['RETAIN_OUTDIR'] or '' + tmpdir = bb_vars['TMPDIR'] + if len(retain_outdir) < 5: + self.fail('RETAIN_OUTDIR value "%s" is invalid' % retain_outdir) + if not oe.path.is_path_parent(tmpdir, retain_outdir): + self.fail('RETAIN_OUTDIR (%s) is not underneath TMPDIR (%s)' % (retain_outdir, tmpdir)) + + try: + shutil.rmtree(retain_outdir) + except FileNotFoundError: + pass + + bitbake('-c clean %s' % test_recipe_fail) + + if os.path.exists(retain_outdir): + retain_dirlist = os.listdir(retain_outdir) + if retain_dirlist: + self.fail('RETAIN_OUTDIR should be empty without failure, contents:\n%s' % '\n'.join(retain_dirlist)) + + result = bitbake('-c compile %s' % test_recipe_fail, ignore_status=True) + if result.status == 0: + self.fail('Build of %s did not fail as expected' % test_recipe_fail) + + archives = glob.glob(os.path.join(retain_outdir, '%s_*.tar.gz' % test_recipe_fail)) + if not archives: + self.fail('No output archive for %s created' % test_recipe_fail) + if len(archives) > 1: + self.fail('More than one archive for %s created' % test_recipe_fail) + for archive in archives: + found = False + archive_prefix = os.path.basename(archive).split('.tar')[0] + expected_prefix_start = '%s_workdir' % test_recipe_fail + if not archive_prefix.startswith(expected_prefix_start): + self.fail('Archive %s name does not start with expected prefix "%s"' % (os.path.basename(archive), expected_prefix_start)) + with tarfile.open(archive) as tf: + for ti in tf: + if not fnmatch.fnmatch(ti.name, '%s/*' % archive_prefix): + self.fail('File without tarball-named subdirectory within tarball %s: %s' % (os.path.basename(archive), ti.name)) + if ti.name.endswith('/temp/log.do_compile'): + found = True + if not found: + self.fail('Did not find log.do_compile in output archive %s' % os.path.basename(archive)) + + + def test_retain_global(self): + """ + Summary: Test retain class RETAIN_DIRS_GLOBAL_* behaviour + Expected: Ensure RETAIN_DIRS_GLOBAL_ALWAYS always causes an + archive to be created, and RETAIN_DIRS_GLOBAL_FAILURE + only causes an archive to be created on failure. + Also test archive naming (with : character) as an + added bonus. + Product: oe-core + Author: Paul Eggleton <paul.eggleton@microsoft.com> + """ + + test_recipe = 'quilt-native' + test_recipe_fail = 'error' + + features = 'INHERIT += "retain"\n' + features += 'RETAIN_DIRS_GLOBAL_ALWAYS = "${LOG_DIR};prefix=buildlogs"\n' + features += 'RETAIN_DIRS_GLOBAL_FAILURE = "${STAMPS_DIR}"\n' + self.write_config(features) + + bitbake('-c clean %s' % test_recipe) + + bb_vars = get_bb_vars(['RETAIN_OUTDIR', 'TMPDIR', 'STAMPS_DIR']) + retain_outdir = bb_vars['RETAIN_OUTDIR'] or '' + tmpdir = bb_vars['TMPDIR'] + if len(retain_outdir) < 5: + self.fail('RETAIN_OUTDIR value "%s" is invalid' % retain_outdir) + if not oe.path.is_path_parent(tmpdir, retain_outdir): + self.fail('RETAIN_OUTDIR (%s) is not underneath TMPDIR (%s)' % (retain_outdir, tmpdir)) + try: + shutil.rmtree(retain_outdir) + except FileNotFoundError: + pass + + # Test success case + bitbake(test_recipe) + if not glob.glob(os.path.join(retain_outdir, 'buildlogs_*.tar.gz')): + self.fail('No output archive for LOG_DIR created') + stamps_dir = bb_vars['STAMPS_DIR'] + if glob.glob(os.path.join(retain_outdir, '%s_*.tar.gz' % os.path.basename(stamps_dir))): + self.fail('Output archive for STAMPS_DIR created when it should not have been') + + # Test failure case + result = bitbake('-c compile %s' % test_recipe_fail, ignore_status=True) + if result.status == 0: + self.fail('Build of %s did not fail as expected' % test_recipe_fail) + if not glob.glob(os.path.join(retain_outdir, '%s_*.tar.gz' % os.path.basename(stamps_dir))): + self.fail('Output archive for STAMPS_DIR not created') + if len(glob.glob(os.path.join(retain_outdir, 'buildlogs_*.tar.gz'))) != 2: + self.fail('Should be exactly two buildlogs archives in output dir') + + + def test_retain_misc(self): + """ + Summary: Test retain class with RETAIN_ENABLED and RETAIN_TARBALL_SUFFIX + Expected: Archive written to RETAIN_OUTDIR only when RETAIN_ENABLED is set + and archive contents are as expected. Also test archive naming + (with : character) as an added bonus. + Product: oe-core + Author: Paul Eggleton <paul.eggleton@microsoft.com> + """ + + test_recipe_fail = 'error' + + features = 'INHERIT += "retain"\n' + features += 'RETAIN_DIRS_ALWAYS = "${T}"\n' + features += 'RETAIN_ENABLED = "0"\n' + self.write_config(features) + + bb_vars = get_bb_vars(['RETAIN_OUTDIR', 'TMPDIR']) + retain_outdir = bb_vars['RETAIN_OUTDIR'] or '' + tmpdir = bb_vars['TMPDIR'] + if len(retain_outdir) < 5: + self.fail('RETAIN_OUTDIR value "%s" is invalid' % retain_outdir) + if not oe.path.is_path_parent(tmpdir, retain_outdir): + self.fail('RETAIN_OUTDIR (%s) is not underneath TMPDIR (%s)' % (retain_outdir, tmpdir)) + + try: + shutil.rmtree(retain_outdir) + except FileNotFoundError: + pass + + bitbake('-c clean %s' % test_recipe_fail) + result = bitbake('-c compile %s' % test_recipe_fail, ignore_status=True) + if result.status == 0: + self.fail('Build of %s did not fail as expected' % test_recipe_fail) + + if os.path.exists(retain_outdir) and os.listdir(retain_outdir): + self.fail('RETAIN_OUTDIR should be empty with RETAIN_ENABLED = "0"') + + features = 'INHERIT += "retain"\n' + features += 'RETAIN_DIRS_ALWAYS = "${T};prefix=recipelogs"\n' + features += 'RETAIN_TARBALL_SUFFIX = "${DATETIME}-testsuffix.tar.bz2"\n' + features += 'RETAIN_ENABLED = "1"\n' + self.write_config(features) + + result = bitbake('-c compile %s' % test_recipe_fail, ignore_status=True) + if result.status == 0: + self.fail('Build of %s did not fail as expected' % test_recipe_fail) + + archives = glob.glob(os.path.join(retain_outdir, '%s_*-testsuffix.tar.bz2' % test_recipe_fail)) + if not archives: + self.fail('No output archive for %s created' % test_recipe_fail) + if len(archives) != 2: + self.fail('Two archives for %s expected, but %d exist' % (test_recipe_fail, len(archives))) + recipelogs_found = False + workdir_found = False + for archive in archives: + contents_found = False + archive_prefix = os.path.basename(archive).split('.tar')[0] + if archive_prefix.startswith('%s_recipelogs' % test_recipe_fail): + recipelogs_found = True + if archive_prefix.startswith('%s_workdir' % test_recipe_fail): + workdir_found = True + with tarfile.open(archive, 'r:bz2') as tf: + for ti in tf: + if not fnmatch.fnmatch(ti.name, '%s/*' % (archive_prefix)): + self.fail('File without tarball-named subdirectory within tarball %s: %s' % (os.path.basename(archive), ti.name)) + if ti.name.endswith('/log.do_compile'): + contents_found = True + if not contents_found: + # Both archives should contain this file + self.fail('Did not find log.do_compile in output archive %s' % os.path.basename(archive)) + if not recipelogs_found: + self.fail('No archive with expected "recipelogs" prefix found') + if not workdir_found: + self.fail('No archive with expected "workdir" prefix found') diff --git a/poky/meta/lib/oeqa/selftest/cases/runtime_test.py b/poky/meta/lib/oeqa/selftest/cases/runtime_test.py index 13aa5f16c9..27090ae5cd 100644 --- a/poky/meta/lib/oeqa/selftest/cases/runtime_test.py +++ b/poky/meta/lib/oeqa/selftest/cases/runtime_test.py @@ -310,10 +310,7 @@ class Postinst(OESelftestTestCase): features += 'IMAGE_FEATURES += "package-management empty-root-password"\n' features += 'PACKAGE_CLASSES = "%s"\n' % classes if init_manager == "systemd": - features += 'DISTRO_FEATURES:append = " systemd usrmerge"\n' - features += 'VIRTUAL-RUNTIME_init_manager = "systemd"\n' - features += 'DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"\n' - features += 'VIRTUAL-RUNTIME_initscripts = ""\n' + features += 'INIT_MANAGER = "systemd"\n' self.write_config(features) bitbake('core-image-minimal') diff --git a/poky/meta/lib/oeqa/selftest/cases/rust.py b/poky/meta/lib/oeqa/selftest/cases/rust.py index 4ccbe9867b..cbe6366f75 100644 --- a/poky/meta/lib/oeqa/selftest/cases/rust.py +++ b/poky/meta/lib/oeqa/selftest/cases/rust.py @@ -66,132 +66,45 @@ class RustSelfTestSystemEmulated(OESelftestTestCase, OEPTestResultTestCase): # bless: First runs rustfmt to format the codebase, # then runs tidy checks. exclude_list = [ - 'compiler/rustc', - 'compiler/rustc_interface/src/tests.rs', - 'library/panic_abort', - 'library/panic_unwind', - 'library/test/src/stats/tests.rs', - 'src/bootstrap/builder/tests.rs', + 'src/bootstrap', 'src/doc/rustc', 'src/doc/rustdoc', 'src/doc/unstable-book', 'src/librustdoc', 'src/rustdoc-json-types', 'src/tools/compiletest/src/common.rs', + 'src/tools/jsondoclint', 'src/tools/lint-docs', + 'src/tools/replace-version-placeholder', 'src/tools/rust-analyzer', 'src/tools/rustdoc-themes', - 'src/tools/tidy', + 'src/tools/rust-installer', + 'src/tools/suggest-tests', + 'src/tools/tidy/src/', 'tests/assembly/asm/aarch64-outline-atomics.rs', 'tests/codegen/abi-main-signature-32bit-c-int.rs', - 'tests/codegen/abi-repr-ext.rs', - 'tests/codegen/abi-x86-interrupt.rs', - 'tests/codegen/branch-protection.rs', - 'tests/codegen/catch-unwind.rs', - 'tests/codegen/cf-protection.rs', - 'tests/codegen/enum-bounds-check-derived-idx.rs', - 'tests/codegen/force-unwind-tables.rs', - 'tests/codegen/intrinsic-no-unnamed-attr.rs', - 'tests/codegen/issues/issue-103840.rs', - 'tests/codegen/issues/issue-47278.rs', - 'tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs', - 'tests/codegen/lifetime_start_end.rs', - 'tests/codegen/local-generics-in-exe-internalized.rs', - 'tests/codegen/match-unoptimized.rs', - 'tests/codegen/noalias-rwlockreadguard.rs', - 'tests/codegen/non-terminate/nonempty-infinite-loop.rs', - 'tests/codegen/noreturn-uninhabited.rs', - 'tests/codegen/repr-transparent-aggregates-3.rs', - 'tests/codegen/riscv-abi/call-llvm-intrinsics.rs', - 'tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs', - 'tests/codegen/riscv-abi/riscv64-lp64d-abi.rs', - 'tests/codegen/sse42-implies-crc32.rs', + 'tests/codegen/i128-x86-align.rs', + 'tests/codegen/issues/issue-122805.rs', 'tests/codegen/thread-local.rs', - 'tests/codegen/uninit-consts.rs', - 'tests/pretty/raw-str-nonexpr.rs', + 'tests/mir-opt/', 'tests/run-make', 'tests/run-make-fulldeps', 'tests/rustdoc', 'tests/rustdoc-json', 'tests/rustdoc-js-std', - 'tests/rustdoc-ui/cfg-test.rs', - 'tests/rustdoc-ui/check-cfg-test.rs', - 'tests/rustdoc-ui/display-output.rs', - 'tests/rustdoc-ui/doc-comment-multi-line-attr.rs', - 'tests/rustdoc-ui/doc-comment-multi-line-cfg-attr.rs', - 'tests/rustdoc-ui/doc-test-doctest-feature.rs', - 'tests/rustdoc-ui/doctest-multiline-crate-attribute.rs', - 'tests/rustdoc-ui/doctest-output.rs', - 'tests/rustdoc-ui/doc-test-rustdoc-feature.rs', - 'tests/rustdoc-ui/failed-doctest-compile-fail.rs', - 'tests/rustdoc-ui/issue-80992.rs', - 'tests/rustdoc-ui/issue-91134.rs', - 'tests/rustdoc-ui/nocapture-fail.rs', - 'tests/rustdoc-ui/nocapture.rs', - 'tests/rustdoc-ui/no-run-flag.rs', - 'tests/rustdoc-ui/run-directory.rs', - 'tests/rustdoc-ui/test-no_std.rs', - 'tests/rustdoc-ui/test-type.rs', - 'tests/rustdoc/unit-return.rs', 'tests/ui/abi/stack-probes-lto.rs', 'tests/ui/abi/stack-probes.rs', - 'tests/ui/array-slice-vec/subslice-patterns-const-eval-match.rs', - 'tests/ui/asm/x86_64/sym.rs', - 'tests/ui/associated-type-bounds/fn-apit.rs', - 'tests/ui/associated-type-bounds/fn-dyn-apit.rs', - 'tests/ui/associated-type-bounds/fn-wrap-apit.rs', + 'tests/ui/codegen/mismatched-data-layouts.rs', 'tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs', - 'tests/ui/drop/dynamic-drop.rs', - 'tests/ui/empty_global_asm.rs', - 'tests/ui/functions-closures/fn-help-with-err.rs', - 'tests/ui/linkage-attr/issue-10755.rs', - 'tests/ui/macros/restricted-shadowing-legacy.rs', + 'tests/ui-fulldeps/', 'tests/ui/process/nofile-limit.rs', - 'tests/ui/process/process-panic-after-fork.rs', - 'tests/ui/process/process-sigpipe.rs', - 'tests/ui/simd/target-feature-mixup.rs', 'tests/ui/structs-enums/multiple-reprs.rs', - 'src/tools/jsondoclint', - 'src/tools/replace-version-placeholder', - 'tests/codegen/abi-efiapi.rs', - 'tests/codegen/abi-sysv64.rs', - 'tests/codegen/align-byval.rs', - 'tests/codegen/align-fn.rs', - 'tests/codegen/asm-powerpc-clobbers.rs', - 'tests/codegen/async-fn-debug-awaitee-field.rs', - 'tests/codegen/binary-search-index-no-bound-check.rs', - 'tests/codegen/call-metadata.rs', - 'tests/codegen/debug-column.rs', - 'tests/codegen/debug-limited.rs', - 'tests/codegen/debuginfo-generic-closure-env-names.rs', - 'tests/codegen/drop.rs', - 'tests/codegen/dst-vtable-align-nonzero.rs', - 'tests/codegen/enable-lto-unit-splitting.rs', - 'tests/codegen/enum/enum-u128.rs', - 'tests/codegen/fn-impl-trait-self.rs', - 'tests/codegen/inherit_overflow.rs', - 'tests/codegen/inline-function-args-debug-info.rs', - 'tests/codegen/intrinsics/mask.rs', - 'tests/codegen/intrinsics/transmute-niched.rs', - 'tests/codegen/issues/issue-73258.rs', - 'tests/codegen/issues/issue-75546.rs', - 'tests/codegen/issues/issue-77812.rs', - 'tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs', - 'tests/codegen/llvm-ident.rs', - 'tests/codegen/mainsubprogram.rs', - 'tests/codegen/move-operands.rs', - 'tests/codegen/repr/transparent-mips64.rs', - 'tests/mir-opt/', - 'tests/rustdoc-json', - 'tests/rustdoc-ui/doc-test-rustdoc-feature.rs', - 'tests/rustdoc-ui/no-run-flag.rs', - 'tests/ui-fulldeps/', - 'tests/ui/numbers-arithmetic/u128.rs' + 'tidyselftest' ] exclude_fail_tests = " ".join([" --exclude " + item for item in exclude_list]) # Add exclude_fail_tests with other test arguments - testargs = exclude_fail_tests + " --doc --no-fail-fast --bless" + testargs = exclude_fail_tests + " --no-fail-fast --bless" # wrap the execution with a qemu instance. # Tests are run with 512 tasks in parallel to execute all tests very quickly diff --git a/poky/meta/lib/oeqa/selftest/cases/spdx.py b/poky/meta/lib/oeqa/selftest/cases/spdx.py index 7685a81e7f..be595babb3 100644 --- a/poky/meta/lib/oeqa/selftest/cases/spdx.py +++ b/poky/meta/lib/oeqa/selftest/cases/spdx.py @@ -6,21 +6,26 @@ import json import os +import textwrap +from pathlib import Path from oeqa.selftest.case import OESelftestTestCase -from oeqa.utils.commands import bitbake, get_bb_var, runCmd +from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runCmd -class SPDXCheck(OESelftestTestCase): +class SPDX22Check(OESelftestTestCase): @classmethod def setUpClass(cls): - super(SPDXCheck, cls).setUpClass() + super().setUpClass() bitbake("python3-spdx-tools-native") bitbake("-c addto_recipe_sysroot python3-spdx-tools-native") def check_recipe_spdx(self, high_level_dir, spdx_file, target_name): - config = """ -INHERIT += "create-spdx" -""" + config = textwrap.dedent( + """\ + INHERIT:remove = "create-spdx" + INHERIT += "create-spdx-2.2" + """ + ) self.write_config(config) deploy_dir = get_bb_var("DEPLOY_DIR") @@ -29,7 +34,9 @@ INHERIT += "create-spdx" # qemux86-64 creates the directory qemux86_64 machine_dir = machine_var.replace("-", "_") - full_file_path = os.path.join(deploy_dir, "spdx", spdx_version, machine_dir, high_level_dir, spdx_file) + full_file_path = os.path.join( + deploy_dir, "spdx", spdx_version, machine_dir, high_level_dir, spdx_file + ) try: os.remove(full_file_path) @@ -44,8 +51,13 @@ INHERIT += "create-spdx" self.assertNotEqual(report, None) self.assertNotEqual(report["SPDXID"], None) - python = os.path.join(get_bb_var('STAGING_BINDIR', 'python3-spdx-tools-native'), 'nativepython3') - validator = os.path.join(get_bb_var('STAGING_BINDIR', 'python3-spdx-tools-native'), 'pyspdxtools') + python = os.path.join( + get_bb_var("STAGING_BINDIR", "python3-spdx-tools-native"), + "nativepython3", + ) + validator = os.path.join( + get_bb_var("STAGING_BINDIR", "python3-spdx-tools-native"), "pyspdxtools" + ) result = runCmd("{} {} -i {}".format(python, validator, filename)) self.assertExists(full_file_path) @@ -53,3 +65,106 @@ INHERIT += "create-spdx" def test_spdx_base_files(self): self.check_recipe_spdx("packages", "base-files.spdx.json", "base-files") + + +class SPDX3CheckBase(object): + """ + Base class for checking SPDX 3 based tests + """ + + def check_spdx_file(self, filename): + import oe.spdx30 + + self.assertExists(filename) + + # Read the file + objset = oe.spdx30.SHACLObjectSet() + with open(filename, "r") as f: + d = oe.spdx30.JSONLDDeserializer() + d.read(f, objset) + + return objset + + def check_recipe_spdx(self, target_name, spdx_path, *, task=None, extraconf=""): + config = textwrap.dedent( + f"""\ + INHERIT:remove = "create-spdx" + INHERIT += "{self.SPDX_CLASS}" + {extraconf} + """ + ) + self.write_config(config) + + if task: + bitbake(f"-c {task} {target_name}") + else: + bitbake(target_name) + + filename = spdx_path.format( + **get_bb_vars( + [ + "DEPLOY_DIR_IMAGE", + "DEPLOY_DIR_SPDX", + "MACHINE", + "MACHINE_ARCH", + "SDKMACHINE", + "SDK_DEPLOY", + "SPDX_VERSION", + "TOOLCHAIN_OUTPUTNAME", + ], + target_name, + ) + ) + + return self.check_spdx_file(filename) + + def check_objset_missing_ids(self, objset): + if objset.missing_ids: + self.assertTrue( + False, + "The following SPDXIDs are unresolved:\n " + + "\n ".join(objset.missing_ids), + ) + + +class SPDX30Check(SPDX3CheckBase, OESelftestTestCase): + SPDX_CLASS = "create-spdx-3.0" + + def test_base_files(self): + self.check_recipe_spdx( + "base-files", + "{DEPLOY_DIR_SPDX}/{MACHINE_ARCH}/packages/base-files.spdx.json", + ) + + def test_core_image_minimal(self): + objset = self.check_recipe_spdx( + "core-image-minimal", + "{DEPLOY_DIR_IMAGE}/core-image-minimal-{MACHINE}.rootfs.spdx.json", + ) + + # Document should be fully linked + self.check_objset_missing_ids(objset) + + def test_core_image_minimal_sdk(self): + objset = self.check_recipe_spdx( + "core-image-minimal", + "{SDK_DEPLOY}/{TOOLCHAIN_OUTPUTNAME}.spdx.json", + task="populate_sdk", + ) + + # Document should be fully linked + self.check_objset_missing_ids(objset) + + def test_baremetal_helloworld(self): + objset = self.check_recipe_spdx( + "baremetal-helloworld", + "{DEPLOY_DIR_IMAGE}/baremetal-helloworld-image-{MACHINE}.spdx.json", + extraconf=textwrap.dedent( + """\ + TCLIBC = "baremetal" + """ + ), + ) + + # Document should be fully linked + self.check_objset_missing_ids(objset) diff --git a/poky/meta/lib/oeqa/selftest/cases/sstatetests.py b/poky/meta/lib/oeqa/selftest/cases/sstatetests.py index 94ad6e38b6..fa0172dd6d 100644 --- a/poky/meta/lib/oeqa/selftest/cases/sstatetests.py +++ b/poky/meta/lib/oeqa/selftest/cases/sstatetests.py @@ -378,7 +378,6 @@ class SStateHashSameSigs(SStateBase): self.write_config(""" MACHINE = "qemux86" TMPDIR = "${TOPDIR}/tmp-sstatesamehash" -TCLIBCAPPEND = "" BUILD_ARCH = "x86_64" BUILD_OS = "linux" SDKMACHINE = "x86_64" @@ -390,7 +389,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash" self.write_config(""" MACHINE = "qemux86" TMPDIR = "${TOPDIR}/tmp-sstatesamehash2" -TCLIBCAPPEND = "" BUILD_ARCH = "i686" BUILD_OS = "linux" SDKMACHINE = "i686" @@ -426,7 +424,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash" self.write_config(""" TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" -TCLIBCAPPEND = \"\" NATIVELSBSTRING = \"DistroA\" BB_SIGNATURE_HANDLER = "OEBasicHash" """) @@ -434,7 +431,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash" bitbake("core-image-weston -S none") self.write_config(""" TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" -TCLIBCAPPEND = \"\" NATIVELSBSTRING = \"DistroB\" BB_SIGNATURE_HANDLER = "OEBasicHash" """) @@ -463,17 +459,17 @@ class SStateHashSameSigs2(SStateBase): configA = """ TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" -TCLIBCAPPEND = \"\" MACHINE = \"qemux86-64\" BB_SIGNATURE_HANDLER = "OEBasicHash" """ #OLDEST_KERNEL is arch specific so set to a different value here for testing configB = """ TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" -TCLIBCAPPEND = \"\" MACHINE = \"qemuarm\" OLDEST_KERNEL = \"3.3.0\" BB_SIGNATURE_HANDLER = "OEBasicHash" +ERROR_QA:append = " somenewoption" +WARN_QA:append = " someotheroption" """ self.sstate_common_samesigs(configA, configB, allarch=True) @@ -484,7 +480,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash" configA = """ TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" -TCLIBCAPPEND = \"\" MACHINE = \"qemux86-64\" require conf/multilib.conf MULTILIBS = \"multilib:lib32\" @@ -493,7 +488,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash" """ configB = """ TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" -TCLIBCAPPEND = \"\" MACHINE = \"qemuarm\" require conf/multilib.conf MULTILIBS = \"\" @@ -511,7 +505,6 @@ class SStateHashSameSigs3(SStateBase): self.write_config(""" TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" -TCLIBCAPPEND = \"\" MACHINE = \"qemux86\" require conf/multilib.conf MULTILIBS = "multilib:lib32" @@ -522,7 +515,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash" bitbake("world meta-toolchain -S none") self.write_config(""" TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" -TCLIBCAPPEND = \"\" MACHINE = \"qemux86copy\" require conf/multilib.conf MULTILIBS = "multilib:lib32" @@ -559,7 +551,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash" self.write_config(""" TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" -TCLIBCAPPEND = \"\" MACHINE = \"qemux86\" require conf/multilib.conf MULTILIBS = "multilib:lib32" @@ -570,7 +561,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash" bitbake("binutils-native -S none") self.write_config(""" TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" -TCLIBCAPPEND = \"\" MACHINE = \"qemux86copy\" BB_SIGNATURE_HANDLER = "OEBasicHash" """) @@ -598,7 +588,6 @@ class SStateHashSameSigs4(SStateBase): self.write_config(""" TMPDIR = "${TOPDIR}/tmp-sstatesamehash" -TCLIBCAPPEND = "" BB_NUMBER_THREADS = "${@oe.utils.cpu_count()}" PARALLEL_MAKE = "-j 1" DL_DIR = "${TOPDIR}/download1" @@ -613,7 +602,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash" bitbake("world meta-toolchain -S none") self.write_config(""" TMPDIR = "${TOPDIR}/tmp-sstatesamehash2" -TCLIBCAPPEND = "" BB_NUMBER_THREADS = "${@oe.utils.cpu_count()+1}" PARALLEL_MAKE = "-j 2" DL_DIR = "${TOPDIR}/download2" @@ -724,7 +712,6 @@ class SStateFindSiginfo(SStateBase): """ self.write_config(""" TMPDIR = \"${TOPDIR}/tmp-sstates-findsiginfo\" -TCLIBCAPPEND = \"\" MACHINE = \"qemux86-64\" require conf/multilib.conf MULTILIBS = "multilib:lib32" @@ -933,8 +920,7 @@ class SStateCheckObjectPresence(SStateBase): # these get influnced by IMAGE_FSTYPES tweaks in yocto-autobuilder-helper's config.json (on x86-64) # additionally, they depend on noexec (thus, absent stamps) package, install, etc. image tasks, # which makes tracing other changes difficult - exceptions += ["{}.*create_spdx".format(t) for t in targets.split()] - exceptions += ["{}.*create_runtime_spdx".format(t) for t in targets.split()] + exceptions += ["{}.*create_.*spdx".format(t) for t in targets.split()] output_l = output.splitlines() for l in output_l: @@ -977,7 +963,7 @@ class SStateMirrors(SStateCheckObjectPresence): self.config_sstate(True) self.append_config(""" MACHINE = "{}" -BB_HASHSERVE_UPSTREAM = "hashserv.yocto.io:8687" +BB_HASHSERVE_UPSTREAM = "hashserv.yoctoproject.org:8686" SSTATE_MIRRORS ?= "file://.* http://cdn.jsdelivr.net/yocto/sstate/all/PATH;downloadfilename=PATH" """.format(machine)) else: @@ -992,12 +978,10 @@ MACHINE = "{}" def test_cdn_mirror_qemux86_64(self): exceptions = [] - self.run_test("qemux86-64", "core-image-minimal core-image-full-cmdline core-image-sato-sdk", exceptions, ignore_errors = True) self.run_test("qemux86-64", "core-image-minimal core-image-full-cmdline core-image-sato-sdk", exceptions) def test_cdn_mirror_qemuarm64(self): exceptions = [] - self.run_test("qemuarm64", "core-image-minimal core-image-full-cmdline core-image-sato-sdk", exceptions, ignore_errors = True) self.run_test("qemuarm64", "core-image-minimal core-image-full-cmdline core-image-sato-sdk", exceptions) def test_local_cache_qemux86_64(self): diff --git a/poky/meta/lib/oeqa/selftest/context.py b/poky/meta/lib/oeqa/selftest/context.py index 99186175e5..acc3b073bd 100644 --- a/poky/meta/lib/oeqa/selftest/context.py +++ b/poky/meta/lib/oeqa/selftest/context.py @@ -117,8 +117,11 @@ class OESelftestTestContext(OETestContext): newbblayers += 'BBLAYERS = "%s"\n' % ' '.join(bblayers_abspath) f.write(newbblayers) + # Rewrite builddir paths seen in environment variables for e in os.environ: - if builddir + "/" in os.environ[e]: + # Rewrite paths that absolutely point inside builddir + # (e.g $builddir/conf/ would be rewritten but not $builddir/../bitbake/) + if builddir + "/" in os.environ[e] and builddir + "/" in os.path.abspath(os.environ[e]): os.environ[e] = os.environ[e].replace(builddir + "/", newbuilddir + "/") if os.environ[e].endswith(builddir): os.environ[e] = os.environ[e].replace(builddir, newbuilddir) |