summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa/selftest
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib/oeqa/selftest')
-rw-r--r--meta/lib/oeqa/selftest/cases/bbclasses.py106
-rw-r--r--meta/lib/oeqa/selftest/cases/binutils.py2
-rw-r--r--meta/lib/oeqa/selftest/cases/buildoptions.py10
-rw-r--r--meta/lib/oeqa/selftest/cases/cve_check.py51
-rw-r--r--meta/lib/oeqa/selftest/cases/devtool.py65
-rw-r--r--meta/lib/oeqa/selftest/cases/distrodata.py20
-rw-r--r--meta/lib/oeqa/selftest/cases/fitimage.py264
-rw-r--r--meta/lib/oeqa/selftest/cases/gcc.py2
-rw-r--r--meta/lib/oeqa/selftest/cases/imagefeatures.py15
-rw-r--r--meta/lib/oeqa/selftest/cases/incompatible_lic.py6
-rw-r--r--meta/lib/oeqa/selftest/cases/locales.py2
-rw-r--r--meta/lib/oeqa/selftest/cases/meta_ide.py4
-rw-r--r--meta/lib/oeqa/selftest/cases/minidebuginfo.py16
-rw-r--r--meta/lib/oeqa/selftest/cases/oescripts.py2
-rw-r--r--meta/lib/oeqa/selftest/cases/overlayfs.py41
-rw-r--r--meta/lib/oeqa/selftest/cases/package.py26
-rw-r--r--meta/lib/oeqa/selftest/cases/picolibc.py18
-rw-r--r--meta/lib/oeqa/selftest/cases/recipetool.py1
-rw-r--r--meta/lib/oeqa/selftest/cases/reproducible.py11
-rw-r--r--meta/lib/oeqa/selftest/cases/retain.py241
-rw-r--r--meta/lib/oeqa/selftest/cases/runtime_test.py5
-rw-r--r--meta/lib/oeqa/selftest/cases/rust.py118
-rw-r--r--meta/lib/oeqa/selftest/cases/spdx.py134
-rw-r--r--meta/lib/oeqa/selftest/cases/sstatetests.py47
-rw-r--r--meta/lib/oeqa/selftest/context.py5
25 files changed, 904 insertions, 308 deletions
diff --git a/meta/lib/oeqa/selftest/cases/bbclasses.py b/meta/lib/oeqa/selftest/cases/bbclasses.py
new file mode 100644
index 0000000000..10545ebe65
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/bbclasses.py
@@ -0,0 +1,106 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7from oeqa.selftest.case import OESelftestTestCase
8from oeqa.utils.commands import get_bb_vars, bitbake
9
10class Systemd(OESelftestTestCase):
11 """
12 Tests related to the systemd bbclass.
13 """
14
15 def getVars(self, recipe):
16 self.bb_vars = get_bb_vars(
17 [
18 'BPN',
19 'D',
20 'INIT_D_DIR',
21 'prefix',
22 'systemd_system_unitdir',
23 'sysconfdir',
24 ],
25 recipe,
26 )
27
28 def fileExists(self, filename):
29 self.assertExists(filename.format(**self.bb_vars))
30
31 def fileNotExists(self, filename):
32 self.assertNotExists(filename.format(**self.bb_vars))
33
34 def test_systemd_in_distro(self):
35 """
36 Summary: Verify that no sysvinit files are installed when the
37 systemd distro feature is enabled, but sysvinit is not.
38 Expected: Systemd service file exists, but /etc does not.
39 Product: OE-Core
40 Author: Peter Kjellerstedt <peter.kjellerstedt@axis.com>
41 """
42
43 self.write_config("""
44DISTRO_FEATURES:append = " systemd usrmerge"
45DISTRO_FEATURES:remove = "sysvinit"
46VIRTUAL-RUNTIME_init_manager = "systemd"
47""")
48 bitbake("systemd-only systemd-and-sysvinit -c install")
49
50 self.getVars("systemd-only")
51 self.fileExists("{D}{systemd_system_unitdir}/{BPN}.service")
52
53 self.getVars("systemd-and-sysvinit")
54 self.fileExists("{D}{systemd_system_unitdir}/{BPN}.service")
55 self.fileNotExists("{D}{sysconfdir}")
56
57 def test_systemd_and_sysvinit_in_distro(self):
58 """
59 Summary: Verify that both systemd and sysvinit files are installed
60 when both the systemd and sysvinit distro features are
61 enabled.
62 Expected: Systemd service file and sysvinit initscript exist.
63 Product: OE-Core
64 Author: Peter Kjellerstedt <peter.kjellerstedt@axis.com>
65 """
66
67 self.write_config("""
68DISTRO_FEATURES:append = " systemd sysvinit usrmerge"
69VIRTUAL-RUNTIME_init_manager = "systemd"
70""")
71 bitbake("systemd-only systemd-and-sysvinit -c install")
72
73 self.getVars("systemd-only")
74 self.fileExists("{D}{systemd_system_unitdir}/{BPN}.service")
75
76 self.getVars("systemd-and-sysvinit")
77 self.fileExists("{D}{systemd_system_unitdir}/{BPN}.service")
78 self.fileExists("{D}{INIT_D_DIR}/{BPN}")
79
80 def test_sysvinit_in_distro(self):
81 """
82 Summary: Verify that no systemd service files are installed when the
83 sysvinit distro feature is enabled, but systemd is not.
84 Expected: The systemd service file does not exist, nor does /usr.
85 The sysvinit initscript exists.
86 Product: OE-Core
87 Author: Peter Kjellerstedt <peter.kjellerstedt@axis.com>
88 """
89
90 self.write_config("""
91DISTRO_FEATURES:remove = "systemd"
92DISTRO_FEATURES:append = " sysvinit usrmerge"
93VIRTUAL-RUNTIME_init_manager = "sysvinit"
94""")
95 bitbake("systemd-only systemd-and-sysvinit -c install")
96
97 self.getVars("systemd-only")
98 self.fileNotExists("{D}{systemd_system_unitdir}/{BPN}.service")
99 self.fileNotExists("{D}{prefix}")
100 self.fileNotExists("{D}{sysconfdir}")
101 self.fileExists("{D}")
102
103 self.getVars("systemd-and-sysvinit")
104 self.fileNotExists("{D}{systemd_system_unitdir}/{BPN}.service")
105 self.fileNotExists("{D}{prefix}")
106 self.fileExists("{D}{INIT_D_DIR}/{BPN}")
diff --git a/meta/lib/oeqa/selftest/cases/binutils.py b/meta/lib/oeqa/selftest/cases/binutils.py
index 1688eabe4e..5ff263d342 100644
--- a/meta/lib/oeqa/selftest/cases/binutils.py
+++ b/meta/lib/oeqa/selftest/cases/binutils.py
@@ -33,7 +33,7 @@ class BinutilsCrossSelfTest(OESelftestTestCase, OEPTestResultTestCase):
33 features.append('CHECK_TARGETS = "{0}"'.format(suite)) 33 features.append('CHECK_TARGETS = "{0}"'.format(suite))
34 self.write_config("\n".join(features)) 34 self.write_config("\n".join(features))
35 35
36 recipe = "binutils-cross-testsuite" 36 recipe = "binutils-testsuite"
37 bb_vars = get_bb_vars(["B", "TARGET_SYS", "T"], recipe) 37 bb_vars = get_bb_vars(["B", "TARGET_SYS", "T"], recipe)
38 builddir, target_sys, tdir = bb_vars["B"], bb_vars["TARGET_SYS"], bb_vars["T"] 38 builddir, target_sys, tdir = bb_vars["B"], bb_vars["TARGET_SYS"], bb_vars["T"]
39 39
diff --git a/meta/lib/oeqa/selftest/cases/buildoptions.py b/meta/lib/oeqa/selftest/cases/buildoptions.py
index 31dafaa9c5..423c31e189 100644
--- a/meta/lib/oeqa/selftest/cases/buildoptions.py
+++ b/meta/lib/oeqa/selftest/cases/buildoptions.py
@@ -84,7 +84,7 @@ class SanityOptionsTest(OESelftestTestCase):
84 84
85 self.write_config("INHERIT:remove = \"report-error\"") 85 self.write_config("INHERIT:remove = \"report-error\"")
86 if "packages-list" not in get_bb_var("ERROR_QA"): 86 if "packages-list" not in get_bb_var("ERROR_QA"):
87 self.append_config("ERROR_QA:append = \" packages-list\"") 87 self.append_config("ERROR_QA:append:pn-xcursor-transparent-theme = \" packages-list\"")
88 88
89 self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"') 89 self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"')
90 self.add_command_to_tearDown('bitbake -c clean xcursor-transparent-theme') 90 self.add_command_to_tearDown('bitbake -c clean xcursor-transparent-theme')
@@ -94,8 +94,8 @@ class SanityOptionsTest(OESelftestTestCase):
94 self.assertTrue(line and line.startswith("ERROR:"), msg=res.output) 94 self.assertTrue(line and line.startswith("ERROR:"), msg=res.output)
95 self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output)) 95 self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output))
96 self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"') 96 self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"')
97 self.append_config('ERROR_QA:remove = "packages-list"') 97 self.append_config('ERROR_QA:remove:pn-xcursor-transparent-theme = "packages-list"')
98 self.append_config('WARN_QA:append = " packages-list"') 98 self.append_config('WARN_QA:append:pn-xcursor-transparent-theme = " packages-list"')
99 res = bitbake("xcursor-transparent-theme -f -c package") 99 res = bitbake("xcursor-transparent-theme -f -c package")
100 self.delete_recipeinc('xcursor-transparent-theme') 100 self.delete_recipeinc('xcursor-transparent-theme')
101 line = self.getline(res, "QA Issue: xcursor-transparent-theme-dbg is listed in PACKAGES multiple times, this leads to packaging errors.") 101 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):
173 173
174 data = load_bh(os.path.join(history_dir, 'hicolor-icon-theme-dev', 'latest')) 174 data = load_bh(os.path.join(history_dir, 'hicolor-icon-theme-dev', 'latest'))
175 if 'FILELIST' in data: 175 if 'FILELIST' in data:
176 self.assertEqual(data['FILELIST'], '') 176 self.assertEqual(data['FILELIST'], '/usr/share/pkgconfig/default-icon-theme.pc')
177 self.assertEqual(int(data['PKGSIZE']), 0) 177 self.assertGreater(int(data['PKGSIZE']), 0)
178 178
179class ArchiverTest(OESelftestTestCase): 179class ArchiverTest(OESelftestTestCase):
180 def test_arch_work_dir_and_export_source(self): 180 def test_arch_work_dir_and_export_source(self):
diff --git a/meta/lib/oeqa/selftest/cases/cve_check.py b/meta/lib/oeqa/selftest/cases/cve_check.py
index 60cecd1328..3dd3e89d3e 100644
--- a/meta/lib/oeqa/selftest/cases/cve_check.py
+++ b/meta/lib/oeqa/selftest/cases/cve_check.py
@@ -72,6 +72,54 @@ class CVECheck(OESelftestTestCase):
72 self.assertEqual(convert_cve_version("6.2_rc8"), "6.2-rc8") 72 self.assertEqual(convert_cve_version("6.2_rc8"), "6.2-rc8")
73 self.assertEqual(convert_cve_version("6.2_rc31"), "6.2-rc31") 73 self.assertEqual(convert_cve_version("6.2_rc31"), "6.2-rc31")
74 74
75 def test_product_match(self):
76 from oe.cve_check import has_cve_product_match
77
78 status = {}
79 status["detail"] = "ignored"
80 status["vendor"] = "*"
81 status["product"] = "*"
82 status["description"] = ""
83 status["mapping"] = ""
84
85 self.assertEqual(has_cve_product_match(status, "some_vendor:some_product"), True)
86 self.assertEqual(has_cve_product_match(status, "*:*"), True)
87 self.assertEqual(has_cve_product_match(status, "some_product"), True)
88 self.assertEqual(has_cve_product_match(status, "glibc"), True)
89 self.assertEqual(has_cve_product_match(status, "glibca"), True)
90 self.assertEqual(has_cve_product_match(status, "aglibc"), True)
91 self.assertEqual(has_cve_product_match(status, "*"), True)
92 self.assertEqual(has_cve_product_match(status, "aglibc glibc test:test"), True)
93
94 status["product"] = "glibc"
95 self.assertEqual(has_cve_product_match(status, "some_vendor:some_product"), False)
96 # The CPE in the recipe must be defined, no * accepted
97 self.assertEqual(has_cve_product_match(status, "*:*"), False)
98 self.assertEqual(has_cve_product_match(status, "*"), False)
99 self.assertEqual(has_cve_product_match(status, "some_product"), False)
100 self.assertEqual(has_cve_product_match(status, "glibc"), True)
101 self.assertEqual(has_cve_product_match(status, "glibca"), False)
102 self.assertEqual(has_cve_product_match(status, "aglibc"), False)
103 self.assertEqual(has_cve_product_match(status, "some_vendor:glibc"), True)
104 self.assertEqual(has_cve_product_match(status, "some_vendor:glibc test"), True)
105 self.assertEqual(has_cve_product_match(status, "test some_vendor:glibc"), True)
106
107 status["vendor"] = "glibca"
108 status["product"] = "glibc"
109 self.assertEqual(has_cve_product_match(status, "some_vendor:some_product"), False)
110 # The CPE in the recipe must be defined, no * accepted
111 self.assertEqual(has_cve_product_match(status, "*:*"), False)
112 self.assertEqual(has_cve_product_match(status, "*"), False)
113 self.assertEqual(has_cve_product_match(status, "some_product"), False)
114 self.assertEqual(has_cve_product_match(status, "glibc"), False)
115 self.assertEqual(has_cve_product_match(status, "glibca"), False)
116 self.assertEqual(has_cve_product_match(status, "aglibc"), False)
117 self.assertEqual(has_cve_product_match(status, "some_vendor:glibc"), False)
118 self.assertEqual(has_cve_product_match(status, "glibca:glibc"), True)
119 self.assertEqual(has_cve_product_match(status, "test:test glibca:glibc"), True)
120 self.assertEqual(has_cve_product_match(status, "test glibca:glibc"), True)
121 self.assertEqual(has_cve_product_match(status, "glibca:glibc test"), True)
122
75 123
76 def test_recipe_report_json(self): 124 def test_recipe_report_json(self):
77 config = """ 125 config = """
@@ -217,9 +265,10 @@ CVE_CHECK_REPORT_PATCHED = "1"
217 # m4 CVE should not be in logrotate 265 # m4 CVE should not be in logrotate
218 self.assertNotIn("CVE-2008-1687", found_cves) 266 self.assertNotIn("CVE-2008-1687", found_cves)
219 # logrotate has both Patched and Ignored CVEs 267 # logrotate has both Patched and Ignored CVEs
268 detail = "version-not-in-range"
220 self.assertIn("CVE-2011-1098", found_cves) 269 self.assertIn("CVE-2011-1098", found_cves)
221 self.assertEqual(found_cves["CVE-2011-1098"]["status"], "Patched") 270 self.assertEqual(found_cves["CVE-2011-1098"]["status"], "Patched")
222 self.assertEqual(len(found_cves["CVE-2011-1098"]["detail"]), 0) 271 self.assertEqual(found_cves["CVE-2011-1098"]["detail"], detail)
223 self.assertEqual(len(found_cves["CVE-2011-1098"]["description"]), 0) 272 self.assertEqual(len(found_cves["CVE-2011-1098"]["description"]), 0)
224 detail = "not-applicable-platform" 273 detail = "not-applicable-platform"
225 description = "CVE is debian, gentoo or SUSE specific on the way logrotate was installed/used" 274 description = "CVE is debian, gentoo or SUSE specific on the way logrotate was installed/used"
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index c8bf7d9e44..7d61773980 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -753,6 +753,25 @@ class DevtoolModifyTests(DevtoolBase):
753 result = runCmd('devtool status') 753 result = runCmd('devtool status')
754 self.assertNotIn('mdadm', result.output) 754 self.assertNotIn('mdadm', result.output)
755 755
756 def test_devtool_modify_go(self):
757 import oe.path
758 from tempfile import TemporaryDirectory
759 with TemporaryDirectory(prefix='devtoolqa') as tempdir:
760 self.track_for_cleanup(self.workspacedir)
761 self.add_command_to_tearDown('bitbake -c clean go-helloworld')
762 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
763 result = runCmd('devtool modify go-helloworld -x %s' % tempdir)
764 self.assertExists(
765 oe.path.join(tempdir, 'src', 'golang.org', 'x', 'example', 'go.mod'),
766 'Extracted source could not be found'
767 )
768 self.assertExists(
769 oe.path.join(self.workspacedir, 'conf', 'layer.conf'),
770 'Workspace directory not created'
771 )
772 matches = glob.glob(oe.path.join(self.workspacedir, 'appends', 'go-helloworld_*.bbappend'))
773 self.assertTrue(matches, 'bbappend not created %s' % result.output)
774
756 def test_devtool_buildclean(self): 775 def test_devtool_buildclean(self):
757 def assertFile(path, *paths): 776 def assertFile(path, *paths):
758 f = os.path.join(path, *paths) 777 f = os.path.join(path, *paths)
@@ -1998,6 +2017,52 @@ class DevtoolUpgradeTests(DevtoolBase):
1998 newlines = f.readlines() 2017 newlines = f.readlines()
1999 self.assertEqual(desiredlines, newlines) 2018 self.assertEqual(desiredlines, newlines)
2000 2019
2020 def test_devtool_upgrade_recipe_upgrade_extra_tasks(self):
2021 # Check preconditions
2022 self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
2023 self.track_for_cleanup(self.workspacedir)
2024 self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
2025 recipe = 'python3-guessing-game'
2026 version = '0.2.0'
2027 commit = '40cf004c2772ffa20ea803fa3be1528a75be3e98'
2028 oldrecipefile = get_bb_var('FILE', recipe)
2029 oldcratesincfile = os.path.join(os.path.dirname(oldrecipefile), os.path.basename(oldrecipefile).strip('_git.bb') + '-crates.inc')
2030 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
2031 self.track_for_cleanup(tempdir)
2032 # Check that recipe is not already under devtool control
2033 result = runCmd('devtool status')
2034 self.assertNotIn(recipe, result.output)
2035 # Check upgrade
2036 result = runCmd('devtool upgrade %s %s --version %s --srcrev %s' % (recipe, tempdir, version, commit))
2037 # Check if srctree at least is populated
2038 self.assertTrue(len(os.listdir(tempdir)) > 0, 'srctree (%s) should be populated with new (%s) source code' % (tempdir, commit))
2039 # Check new recipe file and new -crates.inc files are present
2040 newrecipefile = os.path.join(self.workspacedir, 'recipes', recipe, os.path.basename(oldrecipefile))
2041 newcratesincfile = os.path.join(self.workspacedir, 'recipes', recipe, os.path.basename(oldcratesincfile))
2042 self.assertExists(newrecipefile, 'Recipe file should exist after upgrade')
2043 self.assertExists(newcratesincfile, 'Recipe crates.inc file should exist after upgrade')
2044 # Check devtool status and make sure recipe is present
2045 result = runCmd('devtool status')
2046 self.assertIn(recipe, result.output)
2047 self.assertIn(tempdir, result.output)
2048 # Check recipe got changed as expected
2049 with open(oldrecipefile + '.upgraded', 'r') as f:
2050 desiredlines = f.readlines()
2051 with open(newrecipefile, 'r') as f:
2052 newlines = f.readlines()
2053 self.assertEqual(desiredlines, newlines)
2054 # Check crates.inc got changed as expected
2055 with open(oldcratesincfile + '.upgraded', 'r') as f:
2056 desiredlines = f.readlines()
2057 with open(newcratesincfile, 'r') as f:
2058 newlines = f.readlines()
2059 self.assertEqual(desiredlines, newlines)
2060 # Check devtool reset recipe
2061 result = runCmd('devtool reset %s -n' % recipe)
2062 result = runCmd('devtool status')
2063 self.assertNotIn(recipe, result.output)
2064 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipe), 'Recipe directory should not exist after resetting')
2065
2001 def test_devtool_layer_plugins(self): 2066 def test_devtool_layer_plugins(self):
2002 """Test that devtool can use plugins from other layers. 2067 """Test that devtool can use plugins from other layers.
2003 2068
diff --git a/meta/lib/oeqa/selftest/cases/distrodata.py b/meta/lib/oeqa/selftest/cases/distrodata.py
index ad952c004b..7771a42e2b 100644
--- a/meta/lib/oeqa/selftest/cases/distrodata.py
+++ b/meta/lib/oeqa/selftest/cases/distrodata.py
@@ -20,10 +20,10 @@ class Distrodata(OESelftestTestCase):
20 feature = 'LICENSE_FLAGS_ACCEPTED += " commercial"\n' 20 feature = 'LICENSE_FLAGS_ACCEPTED += " commercial"\n'
21 self.write_config(feature) 21 self.write_config(feature)
22 22
23 pkgs = oe.recipeutils.get_recipe_upgrade_status() 23 pkggroups = oe.recipeutils.get_recipe_upgrade_status()
24 24
25 regressed_failures = [pkg[0] for pkg in pkgs if pkg[1] == 'UNKNOWN_BROKEN'] 25 regressed_failures = [pkg['pn'] for pkgs in pkggroups for pkg in pkgs if pkg['status'] == 'UNKNOWN_BROKEN']
26 regressed_successes = [pkg[0] for pkg in pkgs if pkg[1] == 'KNOWN_BROKEN'] 26 regressed_successes = [pkg['pn'] for pkgs in pkggroups for pkg in pkgs if pkg['status'] == 'KNOWN_BROKEN']
27 msg = "" 27 msg = ""
28 if len(regressed_failures) > 0: 28 if len(regressed_failures) > 0:
29 msg = msg + """ 29 msg = msg + """
@@ -55,7 +55,7 @@ but their recipes claim otherwise by setting UPSTREAM_VERSION_UNKNOWN. Please re
55 return False 55 return False
56 56
57 def is_maintainer_exception(entry): 57 def is_maintainer_exception(entry):
58 exceptions = ["musl", "newlib", "linux-yocto", "linux-dummy", "mesa-gl", "libgfortran", "libx11-compose-data", 58 exceptions = ["musl", "newlib", "picolibc", "linux-yocto", "linux-dummy", "mesa-gl", "libgfortran", "libx11-compose-data",
59 "cve-update-nvd2-native",] 59 "cve-update-nvd2-native",]
60 for i in exceptions: 60 for i in exceptions:
61 if i in entry: 61 if i in entry:
@@ -115,3 +115,15 @@ The list of oe-core recipes with maintainers is empty. This may indicate that th
115 self.fail(""" 115 self.fail("""
116Unable to find recipes for the following entries in maintainers.inc: 116Unable to find recipes for the following entries in maintainers.inc:
117""" + "\n".join(['%s' % i for i in missing_recipes])) 117""" + "\n".join(['%s' % i for i in missing_recipes]))
118
119 def test_common_include_recipes(self):
120 """
121 Summary: Test that obtaining recipes that share includes between them returns a sane result
122 Expected: At least cmake and qemu entries are present in the output
123 Product: oe-core
124 Author: Alexander Kanavin <alex.kanavin@gmail.com>
125 """
126 recipes = oe.recipeutils.get_common_include_recipes()
127
128 self.assertIn({'qemu-system-native', 'qemu', 'qemu-native'}, recipes)
129 self.assertIn({'cmake-native', 'cmake'}, recipes)
diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py
index 347c065377..0b5f4602fb 100644
--- a/meta/lib/oeqa/selftest/cases/fitimage.py
+++ b/meta/lib/oeqa/selftest/cases/fitimage.py
@@ -11,6 +11,51 @@ import re
11 11
12class FitImageTests(OESelftestTestCase): 12class FitImageTests(OESelftestTestCase):
13 13
14 def _setup_uboot_tools_native(self):
15 """build u-boot-tools-native and return RECIPE_SYSROOT_NATIVE"""
16 bitbake("u-boot-tools-native -c addto_recipe_sysroot")
17 return get_bb_var('RECIPE_SYSROOT_NATIVE', 'u-boot-tools-native')
18
19 def _verify_fit_image_signature(self, uboot_tools_sysroot_native, fitimage_path, dtb_path, conf_name=None):
20 """Verify the signature of a fit contfiguration
21
22 The fit_check_sign utility from u-boot-tools-native is called.
23 uboot-fit_check_sign -f fitImage -k $dtb_name -c conf-$dtb_name
24 """
25 fit_check_sign_path = os.path.join(uboot_tools_sysroot_native, 'usr', 'bin', 'uboot-fit_check_sign')
26 cmd = '%s -f %s -k %s' % (fit_check_sign_path, fitimage_path, dtb_path)
27 if conf_name:
28 cmd += ' -c %s' % conf_name
29 result = runCmd(cmd)
30 self.logger.debug("%s\nreturned: %s\n%s", cmd, str(result.status), result.output)
31 self.assertIn("Signature check OK", result.output)
32
33 @staticmethod
34 def _find_string_in_bin_file(file_path, search_string):
35 """find stings in a binary file
36
37 Shell equivalent: strings "$1" | grep "$2" | wc -l
38 return number of matches
39 """
40 found_positions = 0
41 with open(file_path, 'rb') as file:
42 byte = file.read(1)
43 current_position = 0
44 current_match = 0
45 while byte:
46 char = byte.decode('ascii', errors='ignore')
47 if char == search_string[current_match]:
48 current_match += 1
49 if current_match == len(search_string):
50 found_positions += 1
51 current_match = 0
52 else:
53 current_match = 0
54 current_position += 1
55 byte = file.read(1)
56 return found_positions
57
58
14 def test_fit_image(self): 59 def test_fit_image(self):
15 """ 60 """
16 Summary: Check if FIT image and Image Tree Source (its) are built 61 Summary: Check if FIT image and Image Tree Source (its) are built
@@ -53,10 +98,8 @@ FIT_DESC = "A model description"
53 fitimage_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], 98 fitimage_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'],
54 "fitImage-%s-%s" % (bb_vars['INITRAMFS_IMAGE_NAME'], bb_vars['KERNEL_FIT_LINK_NAME'])) 99 "fitImage-%s-%s" % (bb_vars['INITRAMFS_IMAGE_NAME'], bb_vars['KERNEL_FIT_LINK_NAME']))
55 100
56 self.assertTrue(os.path.exists(fitimage_its_path), 101 self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path))
57 "%s image tree source doesn't exist" % (fitimage_its_path)) 102 self.assertExists(fitimage_path, "%s FIT image doesn't exist" % (fitimage_path))
58 self.assertTrue(os.path.exists(fitimage_path),
59 "%s FIT image doesn't exist" % (fitimage_path))
60 103
61 # Check that the type, load address, entrypoint address and default 104 # Check that the type, load address, entrypoint address and default
62 # values for kernel and ramdisk in Image Tree Source are as expected. 105 # values for kernel and ramdisk in Image Tree Source are as expected.
@@ -108,19 +151,21 @@ FIT_DESC = "A model description"
108 Author: Paul Eggleton <paul.eggleton@microsoft.com> based upon 151 Author: Paul Eggleton <paul.eggleton@microsoft.com> based upon
109 work by Usama Arif <usama.arif@arm.com> 152 work by Usama Arif <usama.arif@arm.com>
110 """ 153 """
154 a_comment = "a smart comment"
111 config = """ 155 config = """
112# Enable creation of fitImage 156# Enable creation of fitImage
113MACHINE = "beaglebone-yocto" 157MACHINE = "beaglebone-yocto"
114KERNEL_IMAGETYPES += " fitImage " 158KERNEL_IMAGETYPES += " fitImage "
115KERNEL_CLASSES = " kernel-fitimage test-mkimage-wrapper " 159KERNEL_CLASSES = " kernel-fitimage "
116UBOOT_SIGN_ENABLE = "1" 160UBOOT_SIGN_ENABLE = "1"
117FIT_GENERATE_KEYS = "1" 161FIT_GENERATE_KEYS = "1"
118UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" 162UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
119UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest" 163UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest"
120UBOOT_SIGN_KEYNAME = "cfg-oe-selftest" 164UBOOT_SIGN_KEYNAME = "cfg-oe-selftest"
121FIT_SIGN_INDIVIDUAL = "1" 165FIT_SIGN_INDIVIDUAL = "1"
122UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" 166UBOOT_MKIMAGE_SIGN_ARGS = "-c '%s'"
123""" 167""" % a_comment
168
124 self.write_config(config) 169 self.write_config(config)
125 170
126 # fitImage is created as part of linux recipe 171 # fitImage is created as part of linux recipe
@@ -133,10 +178,8 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
133 fitimage_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], 178 fitimage_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'],
134 "fitImage-%s.bin" % (bb_vars['KERNEL_FIT_LINK_NAME'])) 179 "fitImage-%s.bin" % (bb_vars['KERNEL_FIT_LINK_NAME']))
135 180
136 self.assertTrue(os.path.exists(fitimage_its_path), 181 self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path))
137 "%s image tree source doesn't exist" % (fitimage_its_path)) 182 self.assertExists(fitimage_path, "%s FIT image doesn't exist" % (fitimage_path))
138 self.assertTrue(os.path.exists(fitimage_path),
139 "%s FIT image doesn't exist" % (fitimage_path))
140 183
141 req_itspaths = [ 184 req_itspaths = [
142 ['/', 'images', 'kernel-1'], 185 ['/', 'images', 'kernel-1'],
@@ -195,10 +238,8 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
195 self.assertEqual(value, reqvalue) 238 self.assertEqual(value, reqvalue)
196 239
197 # Dump the image to see if it really got signed 240 # Dump the image to see if it really got signed
198 bitbake("u-boot-tools-native -c addto_recipe_sysroot") 241 uboot_tools_sysroot_native = self._setup_uboot_tools_native()
199 result = runCmd('bitbake -e u-boot-tools-native | grep ^RECIPE_SYSROOT_NATIVE=') 242 dumpimage_path = os.path.join(uboot_tools_sysroot_native, 'usr', 'bin', 'dumpimage')
200 recipe_sysroot_native = result.output.split('=')[1].strip('"')
201 dumpimage_path = os.path.join(recipe_sysroot_native, 'usr', 'bin', 'dumpimage')
202 result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path)) 243 result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path))
203 in_signed = None 244 in_signed = None
204 signed_sections = {} 245 signed_sections = {}
@@ -224,17 +265,15 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
224 value = values.get('Sign value', None) 265 value = values.get('Sign value', None)
225 self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section) 266 self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section)
226 267
227 # Check for UBOOT_MKIMAGE_SIGN_ARGS 268 # Search for the string passed to mkimage: 1 kernel + 3 DTBs + config per DTB = 7 sections
228 result = runCmd('bitbake -e virtual/kernel | grep ^T=') 269 # Looks like mkimage supports to add a comment but does not support to read it back.
229 tempdir = result.output.split('=', 1)[1].strip().strip('') 270 found_comments = FitImageTests._find_string_in_bin_file(fitimage_path, a_comment)
230 result = runCmd('grep "a smart comment" %s/run.do_assemble_fitimage' % tempdir, ignore_status=True) 271 self.assertEqual(found_comments, 7, "Expected 7 signed and commented section in the fitImage.")
231 self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN_ARGS value did not get used')
232 272
233 # Check for evidence of test-mkimage-wrapper class 273 # Verify the signature for all configurations = DTBs
234 result = runCmd('grep "### uboot-mkimage wrapper message" %s/log.do_assemble_fitimage' % tempdir, ignore_status=True) 274 for dtb in ['am335x-bone.dtb', 'am335x-boneblack.dtb', 'am335x-bonegreen.dtb']:
235 self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE did not work') 275 self._verify_fit_image_signature(uboot_tools_sysroot_native, fitimage_path,
236 result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_assemble_fitimage' % tempdir, ignore_status=True) 276 os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], dtb), 'conf-' + dtb)
237 self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work')
238 277
239 def test_uboot_fit_image(self): 278 def test_uboot_fit_image(self):
240 """ 279 """
@@ -287,10 +326,8 @@ FIT_SIGN_INDIVIDUAL = "1"
287 fitimage_path = os.path.join(deploy_dir_image, 326 fitimage_path = os.path.join(deploy_dir_image,
288 "u-boot-fitImage-%s" % (machine,)) 327 "u-boot-fitImage-%s" % (machine,))
289 328
290 self.assertTrue(os.path.exists(fitimage_its_path), 329 self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path))
291 "%s image tree source doesn't exist" % (fitimage_its_path)) 330 self.assertExists(fitimage_path, "%s FIT image doesn't exist" % (fitimage_path))
292 self.assertTrue(os.path.exists(fitimage_path),
293 "%s FIT image doesn't exist" % (fitimage_path))
294 331
295 # Check that the type, load address, entrypoint address and default 332 # Check that the type, load address, entrypoint address and default
296 # values for kernel and ramdisk in Image Tree Source are as expected. 333 # values for kernel and ramdisk in Image Tree Source are as expected.
@@ -351,7 +388,6 @@ UBOOT_ENTRYPOINT = "0x80080000"
351UBOOT_FIT_DESC = "A model description" 388UBOOT_FIT_DESC = "A model description"
352KERNEL_IMAGETYPES += " fitImage " 389KERNEL_IMAGETYPES += " fitImage "
353KERNEL_CLASSES = " kernel-fitimage " 390KERNEL_CLASSES = " kernel-fitimage "
354INHERIT += "test-mkimage-wrapper"
355UBOOT_SIGN_ENABLE = "1" 391UBOOT_SIGN_ENABLE = "1"
356FIT_GENERATE_KEYS = "1" 392FIT_GENERATE_KEYS = "1"
357UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" 393UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
@@ -372,10 +408,8 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart U-Boot comment'"
372 fitimage_path = os.path.join(deploy_dir_image, 408 fitimage_path = os.path.join(deploy_dir_image,
373 "u-boot-fitImage-%s" % (machine,)) 409 "u-boot-fitImage-%s" % (machine,))
374 410
375 self.assertTrue(os.path.exists(fitimage_its_path), 411 self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path))
376 "%s image tree source doesn't exist" % (fitimage_its_path)) 412 self.assertExists(fitimage_path, "%s FIT image doesn't exist" % (fitimage_path))
377 self.assertTrue(os.path.exists(fitimage_path),
378 "%s FIT image doesn't exist" % (fitimage_path))
379 413
380 # Check that the type, load address, entrypoint address and default 414 # Check that the type, load address, entrypoint address and default
381 # values for kernel and ramdisk in Image Tree Source are as expected. 415 # 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'"
425 work by Paul Eggleton <paul.eggleton@microsoft.com> and 459 work by Paul Eggleton <paul.eggleton@microsoft.com> and
426 Usama Arif <usama.arif@arm.com> 460 Usama Arif <usama.arif@arm.com>
427 """ 461 """
462 a_comment = "a smart U-Boot comment"
428 config = """ 463 config = """
429# There's no U-boot deconfig with CONFIG_FIT_SIGNATURE yet, so we need at 464# There's no U-boot deconfig with CONFIG_FIT_SIGNATURE yet, so we need at
430# least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set 465# least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set
@@ -434,7 +469,6 @@ SPL_BINARY = "MLO"
434# The kernel-fitimage class is a dependency even if we're only 469# The kernel-fitimage class is a dependency even if we're only
435# creating/signing the U-Boot fitImage 470# creating/signing the U-Boot fitImage
436KERNEL_CLASSES = " kernel-fitimage" 471KERNEL_CLASSES = " kernel-fitimage"
437INHERIT += "test-mkimage-wrapper"
438# Enable creation and signing of the U-Boot fitImage 472# Enable creation and signing of the U-Boot fitImage
439UBOOT_FITIMAGE_ENABLE = "1" 473UBOOT_FITIMAGE_ENABLE = "1"
440SPL_SIGN_ENABLE = "1" 474SPL_SIGN_ENABLE = "1"
@@ -446,17 +480,17 @@ UBOOT_LOADADDRESS = "0x80000000"
446UBOOT_DTB_LOADADDRESS = "0x82000000" 480UBOOT_DTB_LOADADDRESS = "0x82000000"
447UBOOT_ARCH = "arm" 481UBOOT_ARCH = "arm"
448SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" 482SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
449SPL_MKIMAGE_SIGN_ARGS = "-c 'a smart U-Boot comment'" 483SPL_MKIMAGE_SIGN_ARGS = "-c '%s'"
450UBOOT_EXTLINUX = "0" 484UBOOT_EXTLINUX = "0"
451UBOOT_FIT_GENERATE_KEYS = "1" 485UBOOT_FIT_GENERATE_KEYS = "1"
452UBOOT_FIT_HASH_ALG = "sha256" 486UBOOT_FIT_HASH_ALG = "sha256"
453""" 487""" % a_comment
488
454 self.write_config(config) 489 self.write_config(config)
455 490
456 # The U-Boot fitImage is created as part of the U-Boot recipe 491 # The U-Boot fitImage is created as part of the U-Boot recipe
457 bitbake("virtual/bootloader") 492 bitbake("virtual/bootloader")
458 493
459 image_type = "core-image-minimal"
460 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 494 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
461 machine = get_bb_var('MACHINE') 495 machine = get_bb_var('MACHINE')
462 fitimage_its_path = os.path.join(deploy_dir_image, 496 fitimage_its_path = os.path.join(deploy_dir_image,
@@ -464,10 +498,8 @@ UBOOT_FIT_HASH_ALG = "sha256"
464 fitimage_path = os.path.join(deploy_dir_image, 498 fitimage_path = os.path.join(deploy_dir_image,
465 "u-boot-fitImage-%s" % (machine,)) 499 "u-boot-fitImage-%s" % (machine,))
466 500
467 self.assertTrue(os.path.exists(fitimage_its_path), 501 self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path))
468 "%s image tree source doesn't exist" % (fitimage_its_path)) 502 self.assertExists(fitimage_path, "%s FIT image doesn't exist" % (fitimage_path))
469 self.assertTrue(os.path.exists(fitimage_path),
470 "%s FIT image doesn't exist" % (fitimage_path))
471 503
472 req_itspaths = [ 504 req_itspaths = [
473 ['/', 'images', 'uboot'], 505 ['/', 'images', 'uboot'],
@@ -516,10 +548,8 @@ UBOOT_FIT_HASH_ALG = "sha256"
516 self.assertEqual(value, reqvalue) 548 self.assertEqual(value, reqvalue)
517 549
518 # Dump the image to see if it really got signed 550 # Dump the image to see if it really got signed
519 bitbake("u-boot-tools-native -c addto_recipe_sysroot") 551 uboot_tools_sysroot_native = self._setup_uboot_tools_native()
520 result = runCmd('bitbake -e u-boot-tools-native | grep ^RECIPE_SYSROOT_NATIVE=') 552 dumpimage_path = os.path.join(uboot_tools_sysroot_native, 'usr', 'bin', 'dumpimage')
521 recipe_sysroot_native = result.output.split('=')[1].strip('"')
522 dumpimage_path = os.path.join(recipe_sysroot_native, 'usr', 'bin', 'dumpimage')
523 result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path)) 553 result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path))
524 in_signed = None 554 in_signed = None
525 signed_sections = {} 555 signed_sections = {}
@@ -542,16 +572,14 @@ UBOOT_FIT_HASH_ALG = "sha256"
542 self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section) 572 self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section)
543 573
544 # Check for SPL_MKIMAGE_SIGN_ARGS 574 # Check for SPL_MKIMAGE_SIGN_ARGS
545 result = runCmd('bitbake -e virtual/bootloader | grep ^T=') 575 # Looks like mkimage supports to add a comment but does not support to read it back.
546 tempdir = result.output.split('=', 1)[1].strip().strip('') 576 found_comments = FitImageTests._find_string_in_bin_file(fitimage_path, a_comment)
547 result = runCmd('grep "a smart U-Boot comment" %s/run.do_uboot_assemble_fitimage' % tempdir, ignore_status=True) 577 self.assertEqual(found_comments, 2, "Expected 2 signed and commented section in the fitImage.")
548 self.assertEqual(result.status, 0, 'SPL_MKIMAGE_SIGN_ARGS value did not get used') 578
579 # Verify the signature
580 self._verify_fit_image_signature(uboot_tools_sysroot_native, fitimage_path,
581 os.path.join(deploy_dir_image, 'u-boot-spl.dtb'))
549 582
550 # Check for evidence of test-mkimage-wrapper class
551 result = runCmd('grep "### uboot-mkimage wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
552 self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE did not work')
553 result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
554 self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work')
555 583
556 def test_sign_cascaded_uboot_fit_image(self): 584 def test_sign_cascaded_uboot_fit_image(self):
557 """ 585 """
@@ -573,6 +601,7 @@ UBOOT_FIT_HASH_ALG = "sha256"
573 work by Paul Eggleton <paul.eggleton@microsoft.com> and 601 work by Paul Eggleton <paul.eggleton@microsoft.com> and
574 Usama Arif <usama.arif@arm.com> 602 Usama Arif <usama.arif@arm.com>
575 """ 603 """
604 a_comment = "a smart cascaded U-Boot comment"
576 config = """ 605 config = """
577# There's no U-boot deconfig with CONFIG_FIT_SIGNATURE yet, so we need at 606# There's no U-boot deconfig with CONFIG_FIT_SIGNATURE yet, so we need at
578# least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set 607# least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set
@@ -588,7 +617,7 @@ UBOOT_DTB_BINARY = "u-boot.dtb"
588UBOOT_ENTRYPOINT = "0x80000000" 617UBOOT_ENTRYPOINT = "0x80000000"
589UBOOT_LOADADDRESS = "0x80000000" 618UBOOT_LOADADDRESS = "0x80000000"
590UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" 619UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
591UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart cascaded Kernel comment'" 620UBOOT_MKIMAGE_SIGN_ARGS = "-c '%s'"
592UBOOT_DTB_LOADADDRESS = "0x82000000" 621UBOOT_DTB_LOADADDRESS = "0x82000000"
593UBOOT_ARCH = "arm" 622UBOOT_ARCH = "arm"
594SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" 623SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
@@ -598,20 +627,18 @@ UBOOT_FIT_GENERATE_KEYS = "1"
598UBOOT_FIT_HASH_ALG = "sha256" 627UBOOT_FIT_HASH_ALG = "sha256"
599KERNEL_IMAGETYPES += " fitImage " 628KERNEL_IMAGETYPES += " fitImage "
600KERNEL_CLASSES = " kernel-fitimage " 629KERNEL_CLASSES = " kernel-fitimage "
601INHERIT += "test-mkimage-wrapper"
602UBOOT_SIGN_ENABLE = "1" 630UBOOT_SIGN_ENABLE = "1"
603FIT_GENERATE_KEYS = "1" 631FIT_GENERATE_KEYS = "1"
604UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" 632UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
605UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest" 633UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest"
606UBOOT_SIGN_KEYNAME = "cfg-oe-selftest" 634UBOOT_SIGN_KEYNAME = "cfg-oe-selftest"
607FIT_SIGN_INDIVIDUAL = "1" 635FIT_SIGN_INDIVIDUAL = "1"
608""" 636""" % a_comment
609 self.write_config(config) 637 self.write_config(config)
610 638
611 # The U-Boot fitImage is created as part of the U-Boot recipe 639 # The U-Boot fitImage is created as part of the U-Boot recipe
612 bitbake("virtual/bootloader") 640 bitbake("virtual/bootloader")
613 641
614 image_type = "core-image-minimal"
615 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 642 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
616 machine = get_bb_var('MACHINE') 643 machine = get_bb_var('MACHINE')
617 fitimage_its_path = os.path.join(deploy_dir_image, 644 fitimage_its_path = os.path.join(deploy_dir_image,
@@ -619,10 +646,8 @@ FIT_SIGN_INDIVIDUAL = "1"
619 fitimage_path = os.path.join(deploy_dir_image, 646 fitimage_path = os.path.join(deploy_dir_image,
620 "u-boot-fitImage-%s" % (machine,)) 647 "u-boot-fitImage-%s" % (machine,))
621 648
622 self.assertTrue(os.path.exists(fitimage_its_path), 649 self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path))
623 "%s image tree source doesn't exist" % (fitimage_its_path)) 650 self.assertExists(fitimage_path, "%s FIT image doesn't exist" % (fitimage_path))
624 self.assertTrue(os.path.exists(fitimage_path),
625 "%s FIT image doesn't exist" % (fitimage_path))
626 651
627 req_itspaths = [ 652 req_itspaths = [
628 ['/', 'images', 'uboot'], 653 ['/', 'images', 'uboot'],
@@ -671,10 +696,8 @@ FIT_SIGN_INDIVIDUAL = "1"
671 self.assertEqual(value, reqvalue) 696 self.assertEqual(value, reqvalue)
672 697
673 # Dump the image to see if it really got signed 698 # Dump the image to see if it really got signed
674 bitbake("u-boot-tools-native -c addto_recipe_sysroot") 699 uboot_tools_sysroot_native = self._setup_uboot_tools_native()
675 result = runCmd('bitbake -e u-boot-tools-native | grep ^RECIPE_SYSROOT_NATIVE=') 700 dumpimage_path = os.path.join(uboot_tools_sysroot_native, 'usr', 'bin', 'dumpimage')
676 recipe_sysroot_native = result.output.split('=')[1].strip('"')
677 dumpimage_path = os.path.join(recipe_sysroot_native, 'usr', 'bin', 'dumpimage')
678 result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path)) 701 result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path))
679 in_signed = None 702 in_signed = None
680 signed_sections = {} 703 signed_sections = {}
@@ -697,17 +720,13 @@ FIT_SIGN_INDIVIDUAL = "1"
697 self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section) 720 self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section)
698 721
699 # Check for SPL_MKIMAGE_SIGN_ARGS 722 # Check for SPL_MKIMAGE_SIGN_ARGS
700 result = runCmd('bitbake -e virtual/bootloader | grep ^T=') 723 # Looks like mkimage supports to add a comment but does not support to read it back.
701 tempdir = result.output.split('=', 1)[1].strip().strip('') 724 found_comments = FitImageTests._find_string_in_bin_file(fitimage_path, a_comment)
702 result = runCmd('grep "a smart cascaded U-Boot comment" %s/run.do_uboot_assemble_fitimage' % tempdir, ignore_status=True) 725 self.assertEqual(found_comments, 2, "Expected 2 signed and commented section in the fitImage.")
703 self.assertEqual(result.status, 0, 'SPL_MKIMAGE_SIGN_ARGS value did not get used')
704
705 # Check for evidence of test-mkimage-wrapper class
706 result = runCmd('grep "### uboot-mkimage wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
707 self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE did not work')
708 result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
709 self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work')
710 726
727 # Verify the signature
728 self._verify_fit_image_signature(uboot_tools_sysroot_native, fitimage_path,
729 os.path.join(deploy_dir_image, 'u-boot-spl.dtb'))
711 730
712 731
713 def test_initramfs_bundle(self): 732 def test_initramfs_bundle(self):
@@ -755,24 +774,24 @@ FIT_HASH_ALG = "sha256"
755 # fitImage is created as part of linux recipe 774 # fitImage is created as part of linux recipe
756 bitbake("virtual/kernel") 775 bitbake("virtual/kernel")
757 776
758 image_type = get_bb_var('INITRAMFS_IMAGE') 777 bb_vars = get_bb_vars([
759 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 778 'DEPLOY_DIR_IMAGE',
760 machine = get_bb_var('MACHINE') 779 'FIT_HASH_ALG',
761 fitimage_its_path = os.path.join(deploy_dir_image, 780 'FIT_KERNEL_COMP_ALG',
762 "fitImage-its-%s-%s-%s" % (image_type, machine, machine)) 781 'INITRAMFS_IMAGE',
763 fitimage_path = os.path.join(deploy_dir_image,"fitImage") 782 'MACHINE',
764 783 'UBOOT_ARCH',
765 self.assertTrue(os.path.exists(fitimage_its_path), 784 'UBOOT_ENTRYPOINT',
766 "%s image tree source doesn't exist" % (fitimage_its_path)) 785 'UBOOT_LOADADDRESS',
767 self.assertTrue(os.path.exists(fitimage_path), 786 'UBOOT_MKIMAGE_KERNEL_TYPE'
768 "%s FIT image doesn't exist" % (fitimage_path)) 787 ],
788 'virtual/kernel')
789 fitimage_its_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'],
790 "fitImage-its-%s-%s-%s" % (bb_vars['INITRAMFS_IMAGE'], bb_vars['MACHINE'], bb_vars['MACHINE']))
791 fitimage_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'],"fitImage")
769 792
770 kernel_load = str(get_bb_var('UBOOT_LOADADDRESS')) 793 self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path))
771 kernel_entry = str(get_bb_var('UBOOT_ENTRYPOINT')) 794 self.assertExists(fitimage_path, "%s FIT image doesn't exist" % (fitimage_path))
772 kernel_type = str(get_bb_var('UBOOT_MKIMAGE_KERNEL_TYPE'))
773 kernel_compression = str(get_bb_var('FIT_KERNEL_COMP_ALG'))
774 uboot_arch = str(get_bb_var('UBOOT_ARCH'))
775 fit_hash_alg = str(get_bb_var('FIT_HASH_ALG'))
776 795
777 its_file = open(fitimage_its_path) 796 its_file = open(fitimage_its_path)
778 797
@@ -782,31 +801,31 @@ FIT_HASH_ALG = "sha256"
782 'kernel-1 {', 801 'kernel-1 {',
783 'description = "Linux kernel";', 802 'description = "Linux kernel";',
784 'data = /incbin/("linux.bin");', 803 'data = /incbin/("linux.bin");',
785 'type = "' + kernel_type + '";', 804 'type = "' + str(bb_vars['UBOOT_MKIMAGE_KERNEL_TYPE']) + '";',
786 'arch = "' + uboot_arch + '";', 805 'arch = "' + str(bb_vars['UBOOT_ARCH']) + '";',
787 'os = "linux";', 806 'os = "linux";',
788 'compression = "' + kernel_compression + '";', 807 'compression = "' + str(bb_vars['FIT_KERNEL_COMP_ALG']) + '";',
789 'load = <' + kernel_load + '>;', 808 'load = <' + str(bb_vars['UBOOT_LOADADDRESS']) + '>;',
790 'entry = <' + kernel_entry + '>;', 809 'entry = <' + str(bb_vars['UBOOT_ENTRYPOINT']) + '>;',
791 'hash-1 {', 810 'hash-1 {',
792 'algo = "' + fit_hash_alg +'";', 811 'algo = "' + str(bb_vars['FIT_HASH_ALG']) +'";',
793 '};', 812 '};',
794 '};' 813 '};'
795 ] 814 ]
796 815
797 node_str = exp_node_lines[0] 816 node_str = exp_node_lines[0]
798 817
799 test_passed = False
800
801 print ("checking kernel node\n") 818 print ("checking kernel node\n")
819 self.assertIn(node_str, its_lines)
802 820
803 if node_str in its_lines: 821 node_start_idx = its_lines.index(node_str)
804 node_start_idx = its_lines.index(node_str) 822 node = its_lines[node_start_idx:(node_start_idx + len(exp_node_lines))]
805 node = its_lines[node_start_idx:(node_start_idx + len(exp_node_lines))] 823
806 if node == exp_node_lines: 824 # Remove the absolute path. This refers to WORKDIR which is not always predictable.
807 print("kernel node verified") 825 re_data = re.compile(r'^data = /incbin/\(.*/linux\.bin"\);$')
808 else: 826 node = [re.sub(re_data, 'data = /incbin/("linux.bin");', cfg_str) for cfg_str in node]
809 self.assertTrue(test_passed == True,"kernel node does not match expectation") 827
828 self.assertEqual(node, exp_node_lines, "kernel node does not match expectation")
810 829
811 rx_configs = re.compile("^conf-.*") 830 rx_configs = re.compile("^conf-.*")
812 its_configs = list(filter(rx_configs.match, its_lines)) 831 its_configs = list(filter(rx_configs.match, its_lines))
@@ -822,25 +841,14 @@ FIT_HASH_ALG = "sha256"
822 841
823 node = its_lines[cfg_start_idx:line_idx] 842 node = its_lines[cfg_start_idx:line_idx]
824 print("checking configuration " + cfg_str.rstrip(" {")) 843 print("checking configuration " + cfg_str.rstrip(" {"))
825 rx_desc_line = re.compile("^description.*1 Linux kernel.*") 844 rx_desc_line = re.compile(r'^description = ".*Linux kernel.*')
826 if len(list(filter(rx_desc_line.match, node))) != 1: 845 self.assertEqual(len(list(filter(rx_desc_line.match, node))), 1, "kernel keyword not found in the description line")
827 self.assertTrue(test_passed == True,"kernel keyword not found in the description line")
828 break
829 else:
830 print("kernel keyword found in the description line")
831 846
832 if 'kernel = "kernel-1";' not in node: 847 self.assertIn('kernel = "kernel-1";', node)
833 self.assertTrue(test_passed == True,"kernel line not found")
834 break
835 else:
836 print("kernel line found")
837 848
838 rx_sign_line = re.compile("^sign-images.*kernel.*") 849 rx_sign_line = re.compile(r'^sign-images = .*kernel.*')
839 if len(list(filter(rx_sign_line.match, node))) != 1: 850 self.assertEqual(len(list(filter(rx_sign_line.match, node))), 1, "kernel hash not signed")
840 self.assertTrue(test_passed == True,"kernel hash not signed")
841 break
842 else:
843 print("kernel hash signed")
844 851
845 test_passed = True 852 # Verify the signature
846 self.assertTrue(test_passed == True,"Initramfs bundle test success") 853 uboot_tools_sysroot_native = self._setup_uboot_tools_native()
854 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/meta/lib/oeqa/selftest/cases/gcc.py b/meta/lib/oeqa/selftest/cases/gcc.py
index 89360178fe..4cc0894d42 100644
--- a/meta/lib/oeqa/selftest/cases/gcc.py
+++ b/meta/lib/oeqa/selftest/cases/gcc.py
@@ -37,7 +37,7 @@ class GccSelfTestBase(OESelftestTestCase, OEPTestResultTestCase):
37 features = [] 37 features = []
38 features.append('MAKE_CHECK_TARGETS = "{0}"'.format(" ".join(targets))) 38 features.append('MAKE_CHECK_TARGETS = "{0}"'.format(" ".join(targets)))
39 if ssh is not None: 39 if ssh is not None:
40 features.append('TOOLCHAIN_TEST_TARGET = "ssh"') 40 features.append('TOOLCHAIN_TEST_TARGET = "linux-ssh"')
41 features.append('TOOLCHAIN_TEST_HOST = "{0}"'.format(ssh)) 41 features.append('TOOLCHAIN_TEST_HOST = "{0}"'.format(ssh))
42 features.append('TOOLCHAIN_TEST_HOST_USER = "root"') 42 features.append('TOOLCHAIN_TEST_HOST_USER = "root"')
43 features.append('TOOLCHAIN_TEST_HOST_PORT = "22"') 43 features.append('TOOLCHAIN_TEST_HOST_PORT = "22"')
diff --git a/meta/lib/oeqa/selftest/cases/imagefeatures.py b/meta/lib/oeqa/selftest/cases/imagefeatures.py
index dc88c222bd..94d01ba116 100644
--- a/meta/lib/oeqa/selftest/cases/imagefeatures.py
+++ b/meta/lib/oeqa/selftest/cases/imagefeatures.py
@@ -250,12 +250,7 @@ USERADD_GID_TABLES += "files/static-group"
250DISTRO_FEATURES:append = " pam opengl wayland" 250DISTRO_FEATURES:append = " pam opengl wayland"
251 251
252# Switch to systemd 252# Switch to systemd
253DISTRO_FEATURES:append = " systemd usrmerge" 253INIT_MANAGER = "systemd"
254VIRTUAL-RUNTIME_init_manager = "systemd"
255VIRTUAL-RUNTIME_initscripts = ""
256VIRTUAL-RUNTIME_syslog = ""
257VIRTUAL-RUNTIME_login_manager = "shadow-base"
258DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
259 254
260# Replace busybox 255# Replace busybox
261PREFERRED_PROVIDER_virtual/base-utils = "packagegroup-core-base-utils" 256PREFERRED_PROVIDER_virtual/base-utils = "packagegroup-core-base-utils"
@@ -319,7 +314,7 @@ SKIP_RECIPE[busybox] = "Don't build this"
319 """ 314 """
320 config = """ 315 config = """
321DISTRO_FEATURES:append = " api-documentation" 316DISTRO_FEATURES:append = " api-documentation"
322CORE_IMAGE_EXTRA_INSTALL = "man-pages kmod-doc" 317CORE_IMAGE_EXTRA_INSTALL = "man-pages"
323""" 318"""
324 self.write_config(config) 319 self.write_config(config)
325 bitbake("core-image-minimal") 320 bitbake("core-image-minimal")
@@ -330,7 +325,7 @@ CORE_IMAGE_EXTRA_INSTALL = "man-pages kmod-doc"
330 self.assertEqual(status, 1, 'Failed to run apropos: %s' % (output)) 325 self.assertEqual(status, 1, 'Failed to run apropos: %s' % (output))
331 self.assertIn("iso_8859_15", output) 326 self.assertIn("iso_8859_15", output)
332 327
333 # This manpage is provided by kmod 328 # This manpage is provided by man-pages
334 status, output = qemu.run_serial("man --pager=cat modprobe") 329 status, output = qemu.run_serial("man --pager=cat intro")
335 self.assertEqual(status, 1, 'Failed to run man: %s' % (output)) 330 self.assertEqual(status, 1, 'Failed to run man: %s' % (output))
336 self.assertIn("force-modversion", output) 331 self.assertIn("introduction to user commands", output)
diff --git a/meta/lib/oeqa/selftest/cases/incompatible_lic.py b/meta/lib/oeqa/selftest/cases/incompatible_lic.py
index f4af67a239..be5484bca4 100644
--- a/meta/lib/oeqa/selftest/cases/incompatible_lic.py
+++ b/meta/lib/oeqa/selftest/cases/incompatible_lic.py
@@ -114,7 +114,7 @@ INCOMPATIBLE_LICENSE:pn-core-image-minimal = "GPL-3.0* LGPL-3.0*"
114 114
115 def test_bash_and_license(self): 115 def test_bash_and_license(self):
116 self.disable_class("create-spdx") 116 self.disable_class("create-spdx")
117 self.write_config(self.default_config() + '\nLICENSE:append:pn-bash = " & SomeLicense"') 117 self.write_config(self.default_config() + '\nLICENSE:append:pn-bash = " & SomeLicense"\nERROR_QA:remove:pn-bash = "license-exists"')
118 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" 118 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"
119 119
120 result = bitbake('core-image-minimal', ignore_status=True) 120 result = bitbake('core-image-minimal', ignore_status=True)
@@ -123,12 +123,12 @@ INCOMPATIBLE_LICENSE:pn-core-image-minimal = "GPL-3.0* LGPL-3.0*"
123 123
124 def test_bash_or_license(self): 124 def test_bash_or_license(self):
125 self.disable_class("create-spdx") 125 self.disable_class("create-spdx")
126 self.write_config(self.default_config() + '\nLICENSE:append:pn-bash = " | SomeLicense"') 126 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"')
127 127
128 bitbake('core-image-minimal') 128 bitbake('core-image-minimal')
129 129
130 def test_bash_license_exceptions(self): 130 def test_bash_license_exceptions(self):
131 self.write_config(self.default_config() + '\nINCOMPATIBLE_LICENSE_EXCEPTIONS:pn-core-image-minimal = "bash:GPL-3.0-or-later"') 131 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"')
132 132
133 bitbake('core-image-minimal') 133 bitbake('core-image-minimal')
134 134
diff --git a/meta/lib/oeqa/selftest/cases/locales.py b/meta/lib/oeqa/selftest/cases/locales.py
index 4ca8ffb7aa..ac4888ef66 100644
--- a/meta/lib/oeqa/selftest/cases/locales.py
+++ b/meta/lib/oeqa/selftest/cases/locales.py
@@ -14,7 +14,7 @@ class LocalesTest(OESelftestTestCase):
14 features = [] 14 features = []
15 features.append('EXTRA_IMAGE_FEATURES = "empty-root-password allow-empty-password allow-root-login"') 15 features.append('EXTRA_IMAGE_FEATURES = "empty-root-password allow-empty-password allow-root-login"')
16 features.append('IMAGE_INSTALL:append = " glibc-utils localedef"') 16 features.append('IMAGE_INSTALL:append = " glibc-utils localedef"')
17 features.append('GLIBC_GENERATE_LOCALES = "en_US.UTF-8 fr_FR.UTF-8"') 17 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"')
18 features.append('IMAGE_LINGUAS:append = " en-us fr-fr"') 18 features.append('IMAGE_LINGUAS:append = " en-us fr-fr"')
19 if binary_enabled: 19 if binary_enabled:
20 features.append('ENABLE_BINARY_LOCALE_GENERATION = "1"') 20 features.append('ENABLE_BINARY_LOCALE_GENERATION = "1"')
diff --git a/meta/lib/oeqa/selftest/cases/meta_ide.py b/meta/lib/oeqa/selftest/cases/meta_ide.py
index ffe0d2604d..5a17ca52ea 100644
--- a/meta/lib/oeqa/selftest/cases/meta_ide.py
+++ b/meta/lib/oeqa/selftest/cases/meta_ide.py
@@ -20,8 +20,8 @@ class MetaIDE(OESelftestTestCase):
20 bitbake('meta-ide-support') 20 bitbake('meta-ide-support')
21 bitbake('build-sysroots -c build_native_sysroot') 21 bitbake('build-sysroots -c build_native_sysroot')
22 bitbake('build-sysroots -c build_target_sysroot') 22 bitbake('build-sysroots -c build_target_sysroot')
23 bb_vars = get_bb_vars(['MULTIMACH_TARGET_SYS', 'DEPLOY_DIR_IMAGE', 'COREBASE']) 23 bb_vars = get_bb_vars(['MACHINE_ARCH', 'TARGET_VENDOR', 'TARGET_OS', 'DEPLOY_DIR_IMAGE', 'COREBASE'])
24 cls.environment_script = 'environment-setup-%s' % bb_vars['MULTIMACH_TARGET_SYS'] 24 cls.environment_script = 'environment-setup-%s%s-%s' % (bb_vars['MACHINE_ARCH'], bb_vars['TARGET_VENDOR'], bb_vars['TARGET_OS'])
25 cls.deploydir = bb_vars['DEPLOY_DIR_IMAGE'] 25 cls.deploydir = bb_vars['DEPLOY_DIR_IMAGE']
26 cls.environment_script_path = '%s/%s' % (cls.deploydir, cls.environment_script) 26 cls.environment_script_path = '%s/%s' % (cls.deploydir, cls.environment_script)
27 cls.corebasedir = bb_vars['COREBASE'] 27 cls.corebasedir = bb_vars['COREBASE']
diff --git a/meta/lib/oeqa/selftest/cases/minidebuginfo.py b/meta/lib/oeqa/selftest/cases/minidebuginfo.py
index 2919f07939..a8923460f9 100644
--- a/meta/lib/oeqa/selftest/cases/minidebuginfo.py
+++ b/meta/lib/oeqa/selftest/cases/minidebuginfo.py
@@ -8,6 +8,7 @@ import subprocess
8import tempfile 8import tempfile
9import shutil 9import shutil
10 10
11from oeqa.core.decorator import OETestTag
11from oeqa.selftest.case import OESelftestTestCase 12from oeqa.selftest.case import OESelftestTestCase
12from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runCmd 13from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runCmd
13 14
@@ -42,3 +43,18 @@ IMAGE_FSTYPES = "tar.bz2"
42 native_sysroot = native_sysroot, target_sys = target_sys) 43 native_sysroot = native_sysroot, target_sys = target_sys)
43 self.assertIn(".gnu_debugdata", r.output) 44 self.assertIn(".gnu_debugdata", r.output)
44 45
46 @OETestTag("runqemu")
47 def test_minidebuginfo_qemu(self):
48 """
49 Test minidebuginfo inside a qemu.
50 This runs test_systemd_coredump_minidebuginfo and other minidebuginfo runtime tests which may be added in the future.
51 """
52
53 self.write_config("""
54DISTRO_FEATURES:append = " minidebuginfo"
55INIT_MANAGER = "systemd"
56IMAGE_CLASSES += "testimage"
57TEST_SUITES = "ping ssh systemd"
58 """)
59 bitbake('core-image-minimal')
60 bitbake('-c testimage core-image-minimal')
diff --git a/meta/lib/oeqa/selftest/cases/oescripts.py b/meta/lib/oeqa/selftest/cases/oescripts.py
index f69efccfee..bfbc33b08d 100644
--- a/meta/lib/oeqa/selftest/cases/oescripts.py
+++ b/meta/lib/oeqa/selftest/cases/oescripts.py
@@ -175,7 +175,7 @@ class OEListPackageconfigTests(OESelftestTestCase):
175 def test_packageconfig_flags_option_all(self): 175 def test_packageconfig_flags_option_all(self):
176 results = runCmd('%s/contrib/list-packageconfig-flags.py -a' % self.scripts_dir) 176 results = runCmd('%s/contrib/list-packageconfig-flags.py -a' % self.scripts_dir)
177 expected_endlines = [] 177 expected_endlines = []
178 expected_endlines.append("pinentry-1.2.1") 178 expected_endlines.append("pinentry-1.3.1")
179 expected_endlines.append("PACKAGECONFIG ncurses") 179 expected_endlines.append("PACKAGECONFIG ncurses")
180 expected_endlines.append("PACKAGECONFIG[qt] --enable-pinentry-qt, --disable-pinentry-qt, qtbase-native qtbase") 180 expected_endlines.append("PACKAGECONFIG[qt] --enable-pinentry-qt, --disable-pinentry-qt, qtbase-native qtbase")
181 expected_endlines.append("PACKAGECONFIG[gtk2] --enable-pinentry-gtk2, --disable-pinentry-gtk2, gtk+ glib-2.0") 181 expected_endlines.append("PACKAGECONFIG[gtk2] --enable-pinentry-gtk2, --disable-pinentry-gtk2, gtk+ glib-2.0")
diff --git a/meta/lib/oeqa/selftest/cases/overlayfs.py b/meta/lib/oeqa/selftest/cases/overlayfs.py
index e31063567b..580fbdcb9c 100644
--- a/meta/lib/oeqa/selftest/cases/overlayfs.py
+++ b/meta/lib/oeqa/selftest/cases/overlayfs.py
@@ -5,7 +5,7 @@
5# 5#
6 6
7from oeqa.selftest.case import OESelftestTestCase 7from oeqa.selftest.case import OESelftestTestCase
8from oeqa.utils.commands import bitbake, runqemu 8from oeqa.utils.commands import bitbake, runqemu, get_bb_vars
9from oeqa.core.decorator import OETestTag 9from oeqa.core.decorator import OETestTag
10from oeqa.core.decorator.data import skipIfNotMachine 10from oeqa.core.decorator.data import skipIfNotMachine
11 11
@@ -466,6 +466,45 @@ IMAGE_INSTALL:append = " overlayfs-user"
466 line = getline_qemu(output, "Read-only file system") 466 line = getline_qemu(output, "Read-only file system")
467 self.assertTrue(line, msg=output) 467 self.assertTrue(line, msg=output)
468 468
469 @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently")
470 def test_postinst_on_target_for_read_only_rootfs(self):
471 """
472 Summary: The purpose of this test case is to verify that post-installation
473 on target scripts are executed even if using read-only rootfs when
474 read-only-rootfs-delayed-postinsts is set
475 Expected: The test files are created on first boot
476 """
477
478 import oe.path
479
480 vars = get_bb_vars(("IMAGE_ROOTFS", "sysconfdir"), "core-image-minimal")
481 sysconfdir = vars["sysconfdir"]
482 self.assertIsNotNone(sysconfdir)
483 # Need to use oe.path here as sysconfdir starts with /
484 targettestdir = os.path.join(sysconfdir, "postinst-test")
485
486 config = self.get_working_config()
487
488 args = {
489 'OVERLAYFS_INIT_OPTION': "",
490 'OVERLAYFS_ETC_USE_ORIG_INIT_NAME': 1,
491 'OVERLAYFS_ROOTFS_TYPE': "ext4",
492 'OVERLAYFS_ETC_CREATE_MOUNT_DIRS': 1
493 }
494
495 # read-only-rootfs is already set in get_working_config()
496 config += 'EXTRA_IMAGE_FEATURES += "read-only-rootfs-delayed-postinsts"\n'
497 config += 'CORE_IMAGE_EXTRA_INSTALL = "postinst-delayed-b"\n'
498
499 self.write_config(config.format(**args))
500
501 res = bitbake('core-image-minimal')
502
503 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
504 for filename in ("rootfs", "delayed-a", "delayed-b"):
505 status, output = qemu.run_serial("test -f %s && echo found" % os.path.join(targettestdir, filename))
506 self.assertIn("found", output, "%s was not present on boot" % filename)
507
469 def get_working_config(self): 508 def get_working_config(self):
470 return """ 509 return """
471# Use systemd as init manager 510# Use systemd as init manager
diff --git a/meta/lib/oeqa/selftest/cases/package.py b/meta/lib/oeqa/selftest/cases/package.py
index 1aa6c03f8a..38ed7173fe 100644
--- a/meta/lib/oeqa/selftest/cases/package.py
+++ b/meta/lib/oeqa/selftest/cases/package.py
@@ -103,11 +103,37 @@ class PackageTests(OESelftestTestCase):
103 103
104 dest = get_bb_var('PKGDEST', 'selftest-hardlink') 104 dest = get_bb_var('PKGDEST', 'selftest-hardlink')
105 bindir = get_bb_var('bindir', 'selftest-hardlink') 105 bindir = get_bb_var('bindir', 'selftest-hardlink')
106 libdir = get_bb_var('libdir', 'selftest-hardlink')
107 libexecdir = get_bb_var('libexecdir', 'selftest-hardlink')
106 108
107 def checkfiles(): 109 def checkfiles():
108 # Recipe creates 4 hardlinked files, there is a copy in package/ and a copy in packages-split/ 110 # Recipe creates 4 hardlinked files, there is a copy in package/ and a copy in packages-split/
109 # so expect 8 in total. 111 # so expect 8 in total.
110 self.assertEqual(os.stat(dest + "/selftest-hardlink" + bindir + "/hello1").st_nlink, 8) 112 self.assertEqual(os.stat(dest + "/selftest-hardlink" + bindir + "/hello1").st_nlink, 8)
113 self.assertEqual(os.stat(dest + "/selftest-hardlink" + libexecdir + "/hello3").st_nlink, 8)
114
115 # Check dbg version
116 # 2 items, a copy in both package/packages-split so 4
117 self.assertEqual(os.stat(dest + "/selftest-hardlink-dbg" + bindir + "/.debug/hello1").st_nlink, 4)
118 self.assertEqual(os.stat(dest + "/selftest-hardlink-dbg" + libexecdir + "/.debug/hello1").st_nlink, 4)
119
120 # Even though the libexecdir name is 'hello3' or 'hello4', that isn't the debug target name
121 self.assertEqual(os.path.exists(dest + "/selftest-hardlink-dbg" + libexecdir + "/.debug/hello3"), False)
122 self.assertEqual(os.path.exists(dest + "/selftest-hardlink-dbg" + libexecdir + "/.debug/hello4"), False)
123
124 # Check the staticdev libraries
125 # 101 items, a copy in both package/packages-split so 202
126 self.assertEqual(os.stat(dest + "/selftest-hardlink-staticdev" + libdir + "/libhello.a").st_nlink, 202)
127 self.assertEqual(os.stat(dest + "/selftest-hardlink-staticdev" + libdir + "/libhello-25.a").st_nlink, 202)
128 self.assertEqual(os.stat(dest + "/selftest-hardlink-staticdev" + libdir + "/libhello-50.a").st_nlink, 202)
129 self.assertEqual(os.stat(dest + "/selftest-hardlink-staticdev" + libdir + "/libhello-75.a").st_nlink, 202)
130
131 # Check static dbg
132 # 101 items, a copy in both package/packages-split so 202
133 self.assertEqual(os.stat(dest + "/selftest-hardlink-dbg" + libdir + "/.debug-static/libhello.a").st_nlink, 202)
134 self.assertEqual(os.stat(dest + "/selftest-hardlink-dbg" + libdir + "/.debug-static/libhello-25.a").st_nlink, 202)
135 self.assertEqual(os.stat(dest + "/selftest-hardlink-dbg" + libdir + "/.debug-static/libhello-50.a").st_nlink, 202)
136 self.assertEqual(os.stat(dest + "/selftest-hardlink-dbg" + libdir + "/.debug-static/libhello-75.a").st_nlink, 202)
111 137
112 # Test a sparse file remains sparse 138 # Test a sparse file remains sparse
113 sparsestat = os.stat(dest + "/selftest-hardlink" + bindir + "/sparsetest") 139 sparsestat = os.stat(dest + "/selftest-hardlink" + bindir + "/sparsetest")
diff --git a/meta/lib/oeqa/selftest/cases/picolibc.py b/meta/lib/oeqa/selftest/cases/picolibc.py
new file mode 100644
index 0000000000..e40b4fc3d3
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/picolibc.py
@@ -0,0 +1,18 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7from oeqa.selftest.case import OESelftestTestCase
8from oeqa.utils.commands import bitbake, get_bb_var
9
10class PicolibcTest(OESelftestTestCase):
11
12 def test_picolibc(self):
13 compatible_machines = ['qemuarm', 'qemuarm64', 'qemuriscv32', 'qemuriscv64']
14 machine = get_bb_var('MACHINE')
15 if machine not in compatible_machines:
16 self.skipTest('This test only works with machines : %s' % ' '.join(compatible_machines))
17 self.write_config('TCLIBC = "picolibc"')
18 bitbake("picolibc-helloworld")
diff --git a/meta/lib/oeqa/selftest/cases/recipetool.py b/meta/lib/oeqa/selftest/cases/recipetool.py
index 42202b7831..f742dd4d64 100644
--- a/meta/lib/oeqa/selftest/cases/recipetool.py
+++ b/meta/lib/oeqa/selftest/cases/recipetool.py
@@ -1068,6 +1068,7 @@ class RecipetoolTests(RecipetoolBase):
1068 1068
1069 d = DataConnectorCopy 1069 d = DataConnectorCopy
1070 d.getVar = Mock(return_value=commonlicdir) 1070 d.getVar = Mock(return_value=commonlicdir)
1071 d.expand = Mock(side_effect=lambda x: x)
1071 1072
1072 srctree = tempfile.mkdtemp(prefix='recipetoolqa') 1073 srctree = tempfile.mkdtemp(prefix='recipetoolqa')
1073 self.track_for_cleanup(srctree) 1074 self.track_for_cleanup(srctree)
diff --git a/meta/lib/oeqa/selftest/cases/reproducible.py b/meta/lib/oeqa/selftest/cases/reproducible.py
index 80e830136f..3d3f30eebc 100644
--- a/meta/lib/oeqa/selftest/cases/reproducible.py
+++ b/meta/lib/oeqa/selftest/cases/reproducible.py
@@ -133,7 +133,8 @@ class ReproducibleTests(OESelftestTestCase):
133 max_report_size = 250 * 1024 * 1024 133 max_report_size = 250 * 1024 * 1024
134 134
135 # targets are the things we want to test the reproducibility of 135 # targets are the things we want to test the reproducibility of
136 targets = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline', 'core-image-weston', 'world'] 136 # Have to add the virtual targets manually for now as builds may or may not include them as they're exclude from world
137 targets = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline', 'core-image-weston', 'world', 'virtual/librpc', 'virtual/libsdl2', 'virtual/crypt']
137 138
138 # sstate targets are things to pull from sstate to potentially cut build/debugging time 139 # sstate targets are things to pull from sstate to potentially cut build/debugging time
139 sstate_targets = [] 140 sstate_targets = []
@@ -273,9 +274,13 @@ class ReproducibleTests(OESelftestTestCase):
273 os.chmod(save_dir, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) 274 os.chmod(save_dir, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
274 self.logger.info('Non-reproducible packages will be copied to %s', save_dir) 275 self.logger.info('Non-reproducible packages will be copied to %s', save_dir)
275 276
277 # The below bug shows that a few reproducible issues are depends on build dir path length.
278 # https://bugzilla.yoctoproject.org/show_bug.cgi?id=15554
279 # So, the reproducibleA & reproducibleB directories are changed to reproducibleA & reproducibleB-extended to have different size.
280
276 vars_A = self.do_test_build('reproducibleA', self.build_from_sstate) 281 vars_A = self.do_test_build('reproducibleA', self.build_from_sstate)
277 282
278 vars_B = self.do_test_build('reproducibleB', False) 283 vars_B = self.do_test_build('reproducibleB-extended', False)
279 284
280 # NOTE: The temp directories from the reproducible build are purposely 285 # NOTE: The temp directories from the reproducible build are purposely
281 # kept after the build so it can be diffed for debugging. 286 # kept after the build so it can be diffed for debugging.
@@ -330,7 +335,7 @@ class ReproducibleTests(OESelftestTestCase):
330 # Copy jquery to improve the diffoscope output usability 335 # Copy jquery to improve the diffoscope output usability
331 self.copy_file(os.path.join(jquery_sysroot, 'usr/share/javascript/jquery/jquery.min.js'), os.path.join(package_html_dir, 'jquery.js')) 336 self.copy_file(os.path.join(jquery_sysroot, 'usr/share/javascript/jquery/jquery.min.js'), os.path.join(package_html_dir, 'jquery.js'))
332 337
333 run_diffoscope('reproducibleA', 'reproducibleB', package_html_dir, max_report_size=self.max_report_size, 338 run_diffoscope('reproducibleA', 'reproducibleB-extended', package_html_dir, max_report_size=self.max_report_size,
334 native_sysroot=diffoscope_sysroot, ignore_status=True, cwd=package_dir) 339 native_sysroot=diffoscope_sysroot, ignore_status=True, cwd=package_dir)
335 340
336 if fails: 341 if fails:
diff --git a/meta/lib/oeqa/selftest/cases/retain.py b/meta/lib/oeqa/selftest/cases/retain.py
new file mode 100644
index 0000000000..892be45857
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/retain.py
@@ -0,0 +1,241 @@
1# Tests for retain.bbclass
2#
3# Copyright OpenEmbedded Contributors
4#
5# SPDX-License-Identifier: MIT
6#
7
8import os
9import glob
10import fnmatch
11import oe.path
12import shutil
13import tarfile
14from oeqa.utils.commands import bitbake, get_bb_vars
15from oeqa.selftest.case import OESelftestTestCase
16
17class Retain(OESelftestTestCase):
18
19 def test_retain_always(self):
20 """
21 Summary: Test retain class with RETAIN_DIRS_ALWAYS
22 Expected: Archive written to RETAIN_OUTDIR when build of test recipe completes
23 Product: oe-core
24 Author: Paul Eggleton <paul.eggleton@microsoft.com>
25 """
26
27 test_recipe = 'quilt-native'
28
29 features = 'INHERIT += "retain"\n'
30 features += 'RETAIN_DIRS_ALWAYS = "${T}"\n'
31 self.write_config(features)
32
33 bitbake('-c clean %s' % test_recipe)
34
35 bb_vars = get_bb_vars(['RETAIN_OUTDIR', 'TMPDIR'])
36 retain_outdir = bb_vars['RETAIN_OUTDIR'] or ''
37 tmpdir = bb_vars['TMPDIR']
38 if len(retain_outdir) < 5:
39 self.fail('RETAIN_OUTDIR value "%s" is invalid' % retain_outdir)
40 if not oe.path.is_path_parent(tmpdir, retain_outdir):
41 self.fail('RETAIN_OUTDIR (%s) is not underneath TMPDIR (%s)' % (retain_outdir, tmpdir))
42 try:
43 shutil.rmtree(retain_outdir)
44 except FileNotFoundError:
45 pass
46
47 bitbake(test_recipe)
48 if not glob.glob(os.path.join(retain_outdir, '%s_temp_*.tar.gz' % test_recipe)):
49 self.fail('No output archive for %s created' % test_recipe)
50
51
52 def test_retain_failure(self):
53 """
54 Summary: Test retain class default behaviour
55 Expected: Archive written to RETAIN_OUTDIR only when build of test
56 recipe fails, and archive contents are as expected
57 Product: oe-core
58 Author: Paul Eggleton <paul.eggleton@microsoft.com>
59 """
60
61 test_recipe_fail = 'error'
62
63 features = 'INHERIT += "retain"\n'
64 self.write_config(features)
65
66 bb_vars = get_bb_vars(['RETAIN_OUTDIR', 'TMPDIR', 'RETAIN_DIRS_ALWAYS', 'RETAIN_DIRS_GLOBAL_ALWAYS'])
67 if bb_vars['RETAIN_DIRS_ALWAYS']:
68 self.fail('RETAIN_DIRS_ALWAYS is set, this interferes with the test')
69 if bb_vars['RETAIN_DIRS_GLOBAL_ALWAYS']:
70 self.fail('RETAIN_DIRS_GLOBAL_ALWAYS is set, this interferes with the test')
71 retain_outdir = bb_vars['RETAIN_OUTDIR'] or ''
72 tmpdir = bb_vars['TMPDIR']
73 if len(retain_outdir) < 5:
74 self.fail('RETAIN_OUTDIR value "%s" is invalid' % retain_outdir)
75 if not oe.path.is_path_parent(tmpdir, retain_outdir):
76 self.fail('RETAIN_OUTDIR (%s) is not underneath TMPDIR (%s)' % (retain_outdir, tmpdir))
77
78 try:
79 shutil.rmtree(retain_outdir)
80 except FileNotFoundError:
81 pass
82
83 bitbake('-c clean %s' % test_recipe_fail)
84
85 if os.path.exists(retain_outdir):
86 retain_dirlist = os.listdir(retain_outdir)
87 if retain_dirlist:
88 self.fail('RETAIN_OUTDIR should be empty without failure, contents:\n%s' % '\n'.join(retain_dirlist))
89
90 result = bitbake('-c compile %s' % test_recipe_fail, ignore_status=True)
91 if result.status == 0:
92 self.fail('Build of %s did not fail as expected' % test_recipe_fail)
93
94 archives = glob.glob(os.path.join(retain_outdir, '%s_*.tar.gz' % test_recipe_fail))
95 if not archives:
96 self.fail('No output archive for %s created' % test_recipe_fail)
97 if len(archives) > 1:
98 self.fail('More than one archive for %s created' % test_recipe_fail)
99 for archive in archives:
100 found = False
101 archive_prefix = os.path.basename(archive).split('.tar')[0]
102 expected_prefix_start = '%s_workdir' % test_recipe_fail
103 if not archive_prefix.startswith(expected_prefix_start):
104 self.fail('Archive %s name does not start with expected prefix "%s"' % (os.path.basename(archive), expected_prefix_start))
105 with tarfile.open(archive) as tf:
106 for ti in tf:
107 if not fnmatch.fnmatch(ti.name, '%s/*' % archive_prefix):
108 self.fail('File without tarball-named subdirectory within tarball %s: %s' % (os.path.basename(archive), ti.name))
109 if ti.name.endswith('/temp/log.do_compile'):
110 found = True
111 if not found:
112 self.fail('Did not find log.do_compile in output archive %s' % os.path.basename(archive))
113
114
115 def test_retain_global(self):
116 """
117 Summary: Test retain class RETAIN_DIRS_GLOBAL_* behaviour
118 Expected: Ensure RETAIN_DIRS_GLOBAL_ALWAYS always causes an
119 archive to be created, and RETAIN_DIRS_GLOBAL_FAILURE
120 only causes an archive to be created on failure.
121 Also test archive naming (with : character) as an
122 added bonus.
123 Product: oe-core
124 Author: Paul Eggleton <paul.eggleton@microsoft.com>
125 """
126
127 test_recipe = 'quilt-native'
128 test_recipe_fail = 'error'
129
130 features = 'INHERIT += "retain"\n'
131 features += 'RETAIN_DIRS_GLOBAL_ALWAYS = "${LOG_DIR};prefix=buildlogs"\n'
132 features += 'RETAIN_DIRS_GLOBAL_FAILURE = "${STAMPS_DIR}"\n'
133 self.write_config(features)
134
135 bitbake('-c clean %s' % test_recipe)
136
137 bb_vars = get_bb_vars(['RETAIN_OUTDIR', 'TMPDIR', 'STAMPS_DIR'])
138 retain_outdir = bb_vars['RETAIN_OUTDIR'] or ''
139 tmpdir = bb_vars['TMPDIR']
140 if len(retain_outdir) < 5:
141 self.fail('RETAIN_OUTDIR value "%s" is invalid' % retain_outdir)
142 if not oe.path.is_path_parent(tmpdir, retain_outdir):
143 self.fail('RETAIN_OUTDIR (%s) is not underneath TMPDIR (%s)' % (retain_outdir, tmpdir))
144 try:
145 shutil.rmtree(retain_outdir)
146 except FileNotFoundError:
147 pass
148
149 # Test success case
150 bitbake(test_recipe)
151 if not glob.glob(os.path.join(retain_outdir, 'buildlogs_*.tar.gz')):
152 self.fail('No output archive for LOG_DIR created')
153 stamps_dir = bb_vars['STAMPS_DIR']
154 if glob.glob(os.path.join(retain_outdir, '%s_*.tar.gz' % os.path.basename(stamps_dir))):
155 self.fail('Output archive for STAMPS_DIR created when it should not have been')
156
157 # Test failure case
158 result = bitbake('-c compile %s' % test_recipe_fail, ignore_status=True)
159 if result.status == 0:
160 self.fail('Build of %s did not fail as expected' % test_recipe_fail)
161 if not glob.glob(os.path.join(retain_outdir, '%s_*.tar.gz' % os.path.basename(stamps_dir))):
162 self.fail('Output archive for STAMPS_DIR not created')
163 if len(glob.glob(os.path.join(retain_outdir, 'buildlogs_*.tar.gz'))) != 2:
164 self.fail('Should be exactly two buildlogs archives in output dir')
165
166
167 def test_retain_misc(self):
168 """
169 Summary: Test retain class with RETAIN_ENABLED and RETAIN_TARBALL_SUFFIX
170 Expected: Archive written to RETAIN_OUTDIR only when RETAIN_ENABLED is set
171 and archive contents are as expected. Also test archive naming
172 (with : character) as an added bonus.
173 Product: oe-core
174 Author: Paul Eggleton <paul.eggleton@microsoft.com>
175 """
176
177 test_recipe_fail = 'error'
178
179 features = 'INHERIT += "retain"\n'
180 features += 'RETAIN_DIRS_ALWAYS = "${T}"\n'
181 features += 'RETAIN_ENABLED = "0"\n'
182 self.write_config(features)
183
184 bb_vars = get_bb_vars(['RETAIN_OUTDIR', 'TMPDIR'])
185 retain_outdir = bb_vars['RETAIN_OUTDIR'] or ''
186 tmpdir = bb_vars['TMPDIR']
187 if len(retain_outdir) < 5:
188 self.fail('RETAIN_OUTDIR value "%s" is invalid' % retain_outdir)
189 if not oe.path.is_path_parent(tmpdir, retain_outdir):
190 self.fail('RETAIN_OUTDIR (%s) is not underneath TMPDIR (%s)' % (retain_outdir, tmpdir))
191
192 try:
193 shutil.rmtree(retain_outdir)
194 except FileNotFoundError:
195 pass
196
197 bitbake('-c clean %s' % test_recipe_fail)
198 result = bitbake('-c compile %s' % test_recipe_fail, ignore_status=True)
199 if result.status == 0:
200 self.fail('Build of %s did not fail as expected' % test_recipe_fail)
201
202 if os.path.exists(retain_outdir) and os.listdir(retain_outdir):
203 self.fail('RETAIN_OUTDIR should be empty with RETAIN_ENABLED = "0"')
204
205 features = 'INHERIT += "retain"\n'
206 features += 'RETAIN_DIRS_ALWAYS = "${T};prefix=recipelogs"\n'
207 features += 'RETAIN_TARBALL_SUFFIX = "${DATETIME}-testsuffix.tar.bz2"\n'
208 features += 'RETAIN_ENABLED = "1"\n'
209 self.write_config(features)
210
211 result = bitbake('-c compile %s' % test_recipe_fail, ignore_status=True)
212 if result.status == 0:
213 self.fail('Build of %s did not fail as expected' % test_recipe_fail)
214
215 archives = glob.glob(os.path.join(retain_outdir, '%s_*-testsuffix.tar.bz2' % test_recipe_fail))
216 if not archives:
217 self.fail('No output archive for %s created' % test_recipe_fail)
218 if len(archives) != 2:
219 self.fail('Two archives for %s expected, but %d exist' % (test_recipe_fail, len(archives)))
220 recipelogs_found = False
221 workdir_found = False
222 for archive in archives:
223 contents_found = False
224 archive_prefix = os.path.basename(archive).split('.tar')[0]
225 if archive_prefix.startswith('%s_recipelogs' % test_recipe_fail):
226 recipelogs_found = True
227 if archive_prefix.startswith('%s_workdir' % test_recipe_fail):
228 workdir_found = True
229 with tarfile.open(archive, 'r:bz2') as tf:
230 for ti in tf:
231 if not fnmatch.fnmatch(ti.name, '%s/*' % (archive_prefix)):
232 self.fail('File without tarball-named subdirectory within tarball %s: %s' % (os.path.basename(archive), ti.name))
233 if ti.name.endswith('/log.do_compile'):
234 contents_found = True
235 if not contents_found:
236 # Both archives should contain this file
237 self.fail('Did not find log.do_compile in output archive %s' % os.path.basename(archive))
238 if not recipelogs_found:
239 self.fail('No archive with expected "recipelogs" prefix found')
240 if not workdir_found:
241 self.fail('No archive with expected "workdir" prefix found')
diff --git a/meta/lib/oeqa/selftest/cases/runtime_test.py b/meta/lib/oeqa/selftest/cases/runtime_test.py
index 13aa5f16c9..27090ae5cd 100644
--- a/meta/lib/oeqa/selftest/cases/runtime_test.py
+++ b/meta/lib/oeqa/selftest/cases/runtime_test.py
@@ -310,10 +310,7 @@ class Postinst(OESelftestTestCase):
310 features += 'IMAGE_FEATURES += "package-management empty-root-password"\n' 310 features += 'IMAGE_FEATURES += "package-management empty-root-password"\n'
311 features += 'PACKAGE_CLASSES = "%s"\n' % classes 311 features += 'PACKAGE_CLASSES = "%s"\n' % classes
312 if init_manager == "systemd": 312 if init_manager == "systemd":
313 features += 'DISTRO_FEATURES:append = " systemd usrmerge"\n' 313 features += 'INIT_MANAGER = "systemd"\n'
314 features += 'VIRTUAL-RUNTIME_init_manager = "systemd"\n'
315 features += 'DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"\n'
316 features += 'VIRTUAL-RUNTIME_initscripts = ""\n'
317 self.write_config(features) 314 self.write_config(features)
318 315
319 bitbake('core-image-minimal') 316 bitbake('core-image-minimal')
diff --git a/meta/lib/oeqa/selftest/cases/rust.py b/meta/lib/oeqa/selftest/cases/rust.py
index ad14189c6d..cbe6366f75 100644
--- a/meta/lib/oeqa/selftest/cases/rust.py
+++ b/meta/lib/oeqa/selftest/cases/rust.py
@@ -66,132 +66,45 @@ class RustSelfTestSystemEmulated(OESelftestTestCase, OEPTestResultTestCase):
66 # bless: First runs rustfmt to format the codebase, 66 # bless: First runs rustfmt to format the codebase,
67 # then runs tidy checks. 67 # then runs tidy checks.
68 exclude_list = [ 68 exclude_list = [
69 'compiler/rustc', 69 'src/bootstrap',
70 'compiler/rustc_interface/src/tests.rs',
71 'library/panic_abort',
72 'library/panic_unwind',
73 'library/test/src/stats/tests.rs',
74 'src/bootstrap/builder/tests.rs',
75 'src/doc/rustc', 70 'src/doc/rustc',
76 'src/doc/rustdoc', 71 'src/doc/rustdoc',
77 'src/doc/unstable-book', 72 'src/doc/unstable-book',
78 'src/librustdoc', 73 'src/librustdoc',
79 'src/rustdoc-json-types', 74 'src/rustdoc-json-types',
80 'src/tools/compiletest/src/common.rs', 75 'src/tools/compiletest/src/common.rs',
76 'src/tools/jsondoclint',
81 'src/tools/lint-docs', 77 'src/tools/lint-docs',
78 'src/tools/replace-version-placeholder',
82 'src/tools/rust-analyzer', 79 'src/tools/rust-analyzer',
83 'src/tools/rustdoc-themes', 80 'src/tools/rustdoc-themes',
84 'src/tools/tidy', 81 'src/tools/rust-installer',
82 'src/tools/suggest-tests',
83 'src/tools/tidy/src/',
85 'tests/assembly/asm/aarch64-outline-atomics.rs', 84 'tests/assembly/asm/aarch64-outline-atomics.rs',
86 'tests/codegen/abi-main-signature-32bit-c-int.rs', 85 'tests/codegen/abi-main-signature-32bit-c-int.rs',
87 'tests/codegen/abi-repr-ext.rs', 86 'tests/codegen/i128-x86-align.rs',
88 'tests/codegen/abi-x86-interrupt.rs', 87 'tests/codegen/issues/issue-122805.rs',
89 'tests/codegen/branch-protection.rs',
90 'tests/codegen/catch-unwind.rs',
91 'tests/codegen/cf-protection.rs',
92 'tests/codegen/enum-bounds-check-derived-idx.rs',
93 'tests/codegen/force-unwind-tables.rs',
94 'tests/codegen/intrinsic-no-unnamed-attr.rs',
95 'tests/codegen/issues/issue-103840.rs',
96 'tests/codegen/issues/issue-47278.rs',
97 'tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs',
98 'tests/codegen/lifetime_start_end.rs',
99 'tests/codegen/local-generics-in-exe-internalized.rs',
100 'tests/codegen/match-unoptimized.rs',
101 'tests/codegen/noalias-rwlockreadguard.rs',
102 'tests/codegen/non-terminate/nonempty-infinite-loop.rs',
103 'tests/codegen/noreturn-uninhabited.rs',
104 'tests/codegen/repr-transparent-aggregates-3.rs',
105 'tests/codegen/riscv-abi/call-llvm-intrinsics.rs',
106 'tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs',
107 'tests/codegen/riscv-abi/riscv64-lp64d-abi.rs',
108 'tests/codegen/sse42-implies-crc32.rs',
109 'tests/codegen/thread-local.rs', 88 'tests/codegen/thread-local.rs',
110 'tests/codegen/uninit-consts.rs', 89 'tests/mir-opt/',
111 'tests/pretty/raw-str-nonexpr.rs',
112 'tests/run-make', 90 'tests/run-make',
113 'tests/run-make-fulldeps', 91 'tests/run-make-fulldeps',
114 'tests/rustdoc', 92 'tests/rustdoc',
115 'tests/rustdoc-json', 93 'tests/rustdoc-json',
116 'tests/rustdoc-js-std', 94 'tests/rustdoc-js-std',
117 'tests/rustdoc-ui/cfg-test.rs',
118 'tests/rustdoc-ui/check-cfg-test.rs',
119 'tests/rustdoc-ui/display-output.rs',
120 'tests/rustdoc-ui/doc-comment-multi-line-attr.rs',
121 'tests/rustdoc-ui/doc-comment-multi-line-cfg-attr.rs',
122 'tests/rustdoc-ui/doc-test-doctest-feature.rs',
123 'tests/rustdoc-ui/doctest-multiline-crate-attribute.rs',
124 'tests/rustdoc-ui/doctest-output.rs',
125 'tests/rustdoc-ui/doc-test-rustdoc-feature.rs',
126 'tests/rustdoc-ui/failed-doctest-compile-fail.rs',
127 'tests/rustdoc-ui/issue-80992.rs',
128 'tests/rustdoc-ui/issue-91134.rs',
129 'tests/rustdoc-ui/nocapture-fail.rs',
130 'tests/rustdoc-ui/nocapture.rs',
131 'tests/rustdoc-ui/no-run-flag.rs',
132 'tests/rustdoc-ui/run-directory.rs',
133 'tests/rustdoc-ui/test-no_std.rs',
134 'tests/rustdoc-ui/test-type.rs',
135 'tests/rustdoc/unit-return.rs',
136 'tests/ui/abi/stack-probes-lto.rs', 95 'tests/ui/abi/stack-probes-lto.rs',
137 'tests/ui/abi/stack-probes.rs', 96 'tests/ui/abi/stack-probes.rs',
138 'tests/ui/array-slice-vec/subslice-patterns-const-eval-match.rs', 97 'tests/ui/codegen/mismatched-data-layouts.rs',
139 'tests/ui/asm/x86_64/sym.rs',
140 'tests/ui/associated-type-bounds/fn-apit.rs',
141 'tests/ui/associated-type-bounds/fn-dyn-apit.rs',
142 'tests/ui/associated-type-bounds/fn-wrap-apit.rs',
143 'tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs', 98 'tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs',
144 'tests/ui/drop/dynamic-drop.rs', 99 'tests/ui-fulldeps/',
145 'tests/ui/empty_global_asm.rs',
146 'tests/ui/functions-closures/fn-help-with-err.rs',
147 'tests/ui/linkage-attr/issue-10755.rs',
148 'tests/ui/macros/restricted-shadowing-legacy.rs',
149 'tests/ui/process/nofile-limit.rs', 100 'tests/ui/process/nofile-limit.rs',
150 'tests/ui/process/process-panic-after-fork.rs',
151 'tests/ui/process/process-sigpipe.rs',
152 'tests/ui/simd/target-feature-mixup.rs',
153 'tests/ui/structs-enums/multiple-reprs.rs', 101 'tests/ui/structs-enums/multiple-reprs.rs',
154 'src/tools/jsondoclint', 102 'tidyselftest'
155 'src/tools/replace-version-placeholder',
156 'tests/codegen/abi-efiapi.rs',
157 'tests/codegen/abi-sysv64.rs',
158 'tests/codegen/align-byval.rs',
159 'tests/codegen/align-fn.rs',
160 'tests/codegen/asm-powerpc-clobbers.rs',
161 'tests/codegen/async-fn-debug-awaitee-field.rs',
162 'tests/codegen/binary-search-index-no-bound-check.rs',
163 'tests/codegen/call-metadata.rs',
164 'tests/codegen/debug-column.rs',
165 'tests/codegen/debug-limited.rs',
166 'tests/codegen/debuginfo-generic-closure-env-names.rs',
167 'tests/codegen/drop.rs',
168 'tests/codegen/dst-vtable-align-nonzero.rs',
169 'tests/codegen/enable-lto-unit-splitting.rs',
170 'tests/codegen/enum/enum-u128.rs',
171 'tests/codegen/fn-impl-trait-self.rs',
172 'tests/codegen/inherit_overflow.rs',
173 'tests/codegen/inline-function-args-debug-info.rs',
174 'tests/codegen/intrinsics/mask.rs',
175 'tests/codegen/intrinsics/transmute-niched.rs',
176 'tests/codegen/issues/issue-73258.rs',
177 'tests/codegen/issues/issue-75546.rs',
178 'tests/codegen/issues/issue-77812.rs',
179 'tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs',
180 'tests/codegen/llvm-ident.rs',
181 'tests/codegen/mainsubprogram.rs',
182 'tests/codegen/move-operands.rs',
183 'tests/codegen/repr/transparent-mips64.rs',
184 'tests/mir-opt/',
185 'tests/rustdoc-json',
186 'tests/rustdoc-ui/doc-test-rustdoc-feature.rs',
187 'tests/rustdoc-ui/no-run-flag.rs',
188 'tests/ui-fulldeps/',
189 'tests/ui/numbers-arithmetic/u128.rs'
190 ] 103 ]
191 104
192 exclude_fail_tests = " ".join([" --exclude " + item for item in exclude_list]) 105 exclude_fail_tests = " ".join([" --exclude " + item for item in exclude_list])
193 # Add exclude_fail_tests with other test arguments 106 # Add exclude_fail_tests with other test arguments
194 testargs = exclude_fail_tests + " --doc --no-fail-fast --bless" 107 testargs = exclude_fail_tests + " --no-fail-fast --bless"
195 108
196 # wrap the execution with a qemu instance. 109 # wrap the execution with a qemu instance.
197 # Tests are run with 512 tasks in parallel to execute all tests very quickly 110 # Tests are run with 512 tasks in parallel to execute all tests very quickly
@@ -210,9 +123,8 @@ class RustSelfTestSystemEmulated(OESelftestTestCase, OEPTestResultTestCase):
210 tmpdir = get_bb_var("TMPDIR", "rust") 123 tmpdir = get_bb_var("TMPDIR", "rust")
211 124
212 # Set path for target-poky-linux-gcc, RUST_TARGET_PATH and hosttools. 125 # Set path for target-poky-linux-gcc, RUST_TARGET_PATH and hosttools.
213 cmd = " export PATH=%s/recipe-sysroot-native/usr/bin:$PATH;" % rustlibpath 126 cmd = "export TARGET_VENDOR=\"-poky\";"
214 cmd = cmd + " export TARGET_VENDOR=\"-poky\";" 127 cmd = cmd + " export PATH=%s/recipe-sysroot-native/usr/bin/python3-native:%s/recipe-sysroot-native/usr/bin:%s/recipe-sysroot-native/usr/bin/%s:%s/hosttools:$PATH;" % (rustlibpath, rustlibpath, rustlibpath, tcpath, tmpdir)
215 cmd = cmd + " export PATH=%s/recipe-sysroot-native/usr/bin/%s:%s/hosttools:$PATH;" % (rustlibpath, tcpath, tmpdir)
216 cmd = cmd + " export RUST_TARGET_PATH=%s/rust-targets;" % rustlibpath 128 cmd = cmd + " export RUST_TARGET_PATH=%s/rust-targets;" % rustlibpath
217 # Trigger testing. 129 # Trigger testing.
218 cmd = cmd + " export TEST_DEVICE_ADDR=\"%s:12345\";" % qemu.ip 130 cmd = cmd + " export TEST_DEVICE_ADDR=\"%s:12345\";" % qemu.ip
diff --git a/meta/lib/oeqa/selftest/cases/spdx.py b/meta/lib/oeqa/selftest/cases/spdx.py
index 05fc4e390b..be595babb3 100644
--- a/meta/lib/oeqa/selftest/cases/spdx.py
+++ b/meta/lib/oeqa/selftest/cases/spdx.py
@@ -6,29 +6,37 @@
6 6
7import json 7import json
8import os 8import os
9import textwrap
10from pathlib import Path
9from oeqa.selftest.case import OESelftestTestCase 11from oeqa.selftest.case import OESelftestTestCase
10from oeqa.utils.commands import bitbake, get_bb_var, runCmd 12from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runCmd
11 13
12class SPDXCheck(OESelftestTestCase):
13 14
15class SPDX22Check(OESelftestTestCase):
14 @classmethod 16 @classmethod
15 def setUpClass(cls): 17 def setUpClass(cls):
16 super(SPDXCheck, cls).setUpClass() 18 super().setUpClass()
17 bitbake("python3-spdx-tools-native") 19 bitbake("python3-spdx-tools-native")
18 bitbake("-c addto_recipe_sysroot python3-spdx-tools-native") 20 bitbake("-c addto_recipe_sysroot python3-spdx-tools-native")
19 21
20 def check_recipe_spdx(self, high_level_dir, spdx_file, target_name): 22 def check_recipe_spdx(self, high_level_dir, spdx_file, target_name):
21 config = """ 23 config = textwrap.dedent(
22INHERIT += "create-spdx" 24 """\
23""" 25 INHERIT:remove = "create-spdx"
26 INHERIT += "create-spdx-2.2"
27 """
28 )
24 self.write_config(config) 29 self.write_config(config)
25 30
26 deploy_dir = get_bb_var("DEPLOY_DIR") 31 deploy_dir = get_bb_var("DEPLOY_DIR")
27 machine_var = get_bb_var("MACHINE") 32 machine_var = get_bb_var("MACHINE")
33 spdx_version = get_bb_var("SPDX_VERSION")
28 # qemux86-64 creates the directory qemux86_64 34 # qemux86-64 creates the directory qemux86_64
29 machine_dir = machine_var.replace("-", "_") 35 machine_dir = machine_var.replace("-", "_")
30 36
31 full_file_path = os.path.join(deploy_dir, "spdx", machine_dir, high_level_dir, spdx_file) 37 full_file_path = os.path.join(
38 deploy_dir, "spdx", spdx_version, machine_dir, high_level_dir, spdx_file
39 )
32 40
33 try: 41 try:
34 os.remove(full_file_path) 42 os.remove(full_file_path)
@@ -43,8 +51,13 @@ INHERIT += "create-spdx"
43 self.assertNotEqual(report, None) 51 self.assertNotEqual(report, None)
44 self.assertNotEqual(report["SPDXID"], None) 52 self.assertNotEqual(report["SPDXID"], None)
45 53
46 python = os.path.join(get_bb_var('STAGING_BINDIR', 'python3-spdx-tools-native'), 'nativepython3') 54 python = os.path.join(
47 validator = os.path.join(get_bb_var('STAGING_BINDIR', 'python3-spdx-tools-native'), 'pyspdxtools') 55 get_bb_var("STAGING_BINDIR", "python3-spdx-tools-native"),
56 "nativepython3",
57 )
58 validator = os.path.join(
59 get_bb_var("STAGING_BINDIR", "python3-spdx-tools-native"), "pyspdxtools"
60 )
48 result = runCmd("{} {} -i {}".format(python, validator, filename)) 61 result = runCmd("{} {} -i {}".format(python, validator, filename))
49 62
50 self.assertExists(full_file_path) 63 self.assertExists(full_file_path)
@@ -52,3 +65,106 @@ INHERIT += "create-spdx"
52 65
53 def test_spdx_base_files(self): 66 def test_spdx_base_files(self):
54 self.check_recipe_spdx("packages", "base-files.spdx.json", "base-files") 67 self.check_recipe_spdx("packages", "base-files.spdx.json", "base-files")
68
69
70class SPDX3CheckBase(object):
71 """
72 Base class for checking SPDX 3 based tests
73 """
74
75 def check_spdx_file(self, filename):
76 import oe.spdx30
77
78 self.assertExists(filename)
79
80 # Read the file
81 objset = oe.spdx30.SHACLObjectSet()
82 with open(filename, "r") as f:
83 d = oe.spdx30.JSONLDDeserializer()
84 d.read(f, objset)
85
86 return objset
87
88 def check_recipe_spdx(self, target_name, spdx_path, *, task=None, extraconf=""):
89 config = textwrap.dedent(
90 f"""\
91 INHERIT:remove = "create-spdx"
92 INHERIT += "{self.SPDX_CLASS}"
93 {extraconf}
94 """
95 )
96 self.write_config(config)
97
98 if task:
99 bitbake(f"-c {task} {target_name}")
100 else:
101 bitbake(target_name)
102
103 filename = spdx_path.format(
104 **get_bb_vars(
105 [
106 "DEPLOY_DIR_IMAGE",
107 "DEPLOY_DIR_SPDX",
108 "MACHINE",
109 "MACHINE_ARCH",
110 "SDKMACHINE",
111 "SDK_DEPLOY",
112 "SPDX_VERSION",
113 "TOOLCHAIN_OUTPUTNAME",
114 ],
115 target_name,
116 )
117 )
118
119 return self.check_spdx_file(filename)
120
121 def check_objset_missing_ids(self, objset):
122 if objset.missing_ids:
123 self.assertTrue(
124 False,
125 "The following SPDXIDs are unresolved:\n "
126 + "\n ".join(objset.missing_ids),
127 )
128
129
130class SPDX30Check(SPDX3CheckBase, OESelftestTestCase):
131 SPDX_CLASS = "create-spdx-3.0"
132
133 def test_base_files(self):
134 self.check_recipe_spdx(
135 "base-files",
136 "{DEPLOY_DIR_SPDX}/{MACHINE_ARCH}/packages/base-files.spdx.json",
137 )
138
139 def test_core_image_minimal(self):
140 objset = self.check_recipe_spdx(
141 "core-image-minimal",
142 "{DEPLOY_DIR_IMAGE}/core-image-minimal-{MACHINE}.rootfs.spdx.json",
143 )
144
145 # Document should be fully linked
146 self.check_objset_missing_ids(objset)
147
148 def test_core_image_minimal_sdk(self):
149 objset = self.check_recipe_spdx(
150 "core-image-minimal",
151 "{SDK_DEPLOY}/{TOOLCHAIN_OUTPUTNAME}.spdx.json",
152 task="populate_sdk",
153 )
154
155 # Document should be fully linked
156 self.check_objset_missing_ids(objset)
157
158 def test_baremetal_helloworld(self):
159 objset = self.check_recipe_spdx(
160 "baremetal-helloworld",
161 "{DEPLOY_DIR_IMAGE}/baremetal-helloworld-image-{MACHINE}.spdx.json",
162 extraconf=textwrap.dedent(
163 """\
164 TCLIBC = "baremetal"
165 """
166 ),
167 )
168
169 # Document should be fully linked
170 self.check_objset_missing_ids(objset)
diff --git a/meta/lib/oeqa/selftest/cases/sstatetests.py b/meta/lib/oeqa/selftest/cases/sstatetests.py
index 86d6cd7464..ae295bef5f 100644
--- a/meta/lib/oeqa/selftest/cases/sstatetests.py
+++ b/meta/lib/oeqa/selftest/cases/sstatetests.py
@@ -378,7 +378,6 @@ class SStateHashSameSigs(SStateBase):
378 self.write_config(""" 378 self.write_config("""
379MACHINE = "qemux86" 379MACHINE = "qemux86"
380TMPDIR = "${TOPDIR}/tmp-sstatesamehash" 380TMPDIR = "${TOPDIR}/tmp-sstatesamehash"
381TCLIBCAPPEND = ""
382BUILD_ARCH = "x86_64" 381BUILD_ARCH = "x86_64"
383BUILD_OS = "linux" 382BUILD_OS = "linux"
384SDKMACHINE = "x86_64" 383SDKMACHINE = "x86_64"
@@ -390,7 +389,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash"
390 self.write_config(""" 389 self.write_config("""
391MACHINE = "qemux86" 390MACHINE = "qemux86"
392TMPDIR = "${TOPDIR}/tmp-sstatesamehash2" 391TMPDIR = "${TOPDIR}/tmp-sstatesamehash2"
393TCLIBCAPPEND = ""
394BUILD_ARCH = "i686" 392BUILD_ARCH = "i686"
395BUILD_OS = "linux" 393BUILD_OS = "linux"
396SDKMACHINE = "i686" 394SDKMACHINE = "i686"
@@ -426,7 +424,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash"
426 424
427 self.write_config(""" 425 self.write_config("""
428TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" 426TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
429TCLIBCAPPEND = \"\"
430NATIVELSBSTRING = \"DistroA\" 427NATIVELSBSTRING = \"DistroA\"
431BB_SIGNATURE_HANDLER = "OEBasicHash" 428BB_SIGNATURE_HANDLER = "OEBasicHash"
432""") 429""")
@@ -434,7 +431,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash"
434 bitbake("core-image-weston -S none") 431 bitbake("core-image-weston -S none")
435 self.write_config(""" 432 self.write_config("""
436TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" 433TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
437TCLIBCAPPEND = \"\"
438NATIVELSBSTRING = \"DistroB\" 434NATIVELSBSTRING = \"DistroB\"
439BB_SIGNATURE_HANDLER = "OEBasicHash" 435BB_SIGNATURE_HANDLER = "OEBasicHash"
440""") 436""")
@@ -463,17 +459,17 @@ class SStateHashSameSigs2(SStateBase):
463 459
464 configA = """ 460 configA = """
465TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" 461TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
466TCLIBCAPPEND = \"\"
467MACHINE = \"qemux86-64\" 462MACHINE = \"qemux86-64\"
468BB_SIGNATURE_HANDLER = "OEBasicHash" 463BB_SIGNATURE_HANDLER = "OEBasicHash"
469""" 464"""
470 #OLDEST_KERNEL is arch specific so set to a different value here for testing 465 #OLDEST_KERNEL is arch specific so set to a different value here for testing
471 configB = """ 466 configB = """
472TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" 467TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
473TCLIBCAPPEND = \"\"
474MACHINE = \"qemuarm\" 468MACHINE = \"qemuarm\"
475OLDEST_KERNEL = \"3.3.0\" 469OLDEST_KERNEL = \"3.3.0\"
476BB_SIGNATURE_HANDLER = "OEBasicHash" 470BB_SIGNATURE_HANDLER = "OEBasicHash"
471ERROR_QA:append = " somenewoption"
472WARN_QA:append = " someotheroption"
477""" 473"""
478 self.sstate_common_samesigs(configA, configB, allarch=True) 474 self.sstate_common_samesigs(configA, configB, allarch=True)
479 475
@@ -484,7 +480,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash"
484 480
485 configA = """ 481 configA = """
486TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" 482TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
487TCLIBCAPPEND = \"\"
488MACHINE = \"qemux86-64\" 483MACHINE = \"qemux86-64\"
489require conf/multilib.conf 484require conf/multilib.conf
490MULTILIBS = \"multilib:lib32\" 485MULTILIBS = \"multilib:lib32\"
@@ -493,7 +488,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash"
493""" 488"""
494 configB = """ 489 configB = """
495TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" 490TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
496TCLIBCAPPEND = \"\"
497MACHINE = \"qemuarm\" 491MACHINE = \"qemuarm\"
498require conf/multilib.conf 492require conf/multilib.conf
499MULTILIBS = \"\" 493MULTILIBS = \"\"
@@ -511,7 +505,6 @@ class SStateHashSameSigs3(SStateBase):
511 505
512 self.write_config(""" 506 self.write_config("""
513TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" 507TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
514TCLIBCAPPEND = \"\"
515MACHINE = \"qemux86\" 508MACHINE = \"qemux86\"
516require conf/multilib.conf 509require conf/multilib.conf
517MULTILIBS = "multilib:lib32" 510MULTILIBS = "multilib:lib32"
@@ -522,7 +515,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash"
522 bitbake("world meta-toolchain -S none") 515 bitbake("world meta-toolchain -S none")
523 self.write_config(""" 516 self.write_config("""
524TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" 517TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
525TCLIBCAPPEND = \"\"
526MACHINE = \"qemux86copy\" 518MACHINE = \"qemux86copy\"
527require conf/multilib.conf 519require conf/multilib.conf
528MULTILIBS = "multilib:lib32" 520MULTILIBS = "multilib:lib32"
@@ -559,7 +551,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash"
559 551
560 self.write_config(""" 552 self.write_config("""
561TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" 553TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
562TCLIBCAPPEND = \"\"
563MACHINE = \"qemux86\" 554MACHINE = \"qemux86\"
564require conf/multilib.conf 555require conf/multilib.conf
565MULTILIBS = "multilib:lib32" 556MULTILIBS = "multilib:lib32"
@@ -570,7 +561,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash"
570 bitbake("binutils-native -S none") 561 bitbake("binutils-native -S none")
571 self.write_config(""" 562 self.write_config("""
572TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" 563TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
573TCLIBCAPPEND = \"\"
574MACHINE = \"qemux86copy\" 564MACHINE = \"qemux86copy\"
575BB_SIGNATURE_HANDLER = "OEBasicHash" 565BB_SIGNATURE_HANDLER = "OEBasicHash"
576""") 566""")
@@ -598,7 +588,6 @@ class SStateHashSameSigs4(SStateBase):
598 588
599 self.write_config(""" 589 self.write_config("""
600TMPDIR = "${TOPDIR}/tmp-sstatesamehash" 590TMPDIR = "${TOPDIR}/tmp-sstatesamehash"
601TCLIBCAPPEND = ""
602BB_NUMBER_THREADS = "${@oe.utils.cpu_count()}" 591BB_NUMBER_THREADS = "${@oe.utils.cpu_count()}"
603PARALLEL_MAKE = "-j 1" 592PARALLEL_MAKE = "-j 1"
604DL_DIR = "${TOPDIR}/download1" 593DL_DIR = "${TOPDIR}/download1"
@@ -613,7 +602,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash"
613 bitbake("world meta-toolchain -S none") 602 bitbake("world meta-toolchain -S none")
614 self.write_config(""" 603 self.write_config("""
615TMPDIR = "${TOPDIR}/tmp-sstatesamehash2" 604TMPDIR = "${TOPDIR}/tmp-sstatesamehash2"
616TCLIBCAPPEND = ""
617BB_NUMBER_THREADS = "${@oe.utils.cpu_count()+1}" 605BB_NUMBER_THREADS = "${@oe.utils.cpu_count()+1}"
618PARALLEL_MAKE = "-j 2" 606PARALLEL_MAKE = "-j 2"
619DL_DIR = "${TOPDIR}/download2" 607DL_DIR = "${TOPDIR}/download2"
@@ -724,7 +712,6 @@ class SStateFindSiginfo(SStateBase):
724 """ 712 """
725 self.write_config(""" 713 self.write_config("""
726TMPDIR = \"${TOPDIR}/tmp-sstates-findsiginfo\" 714TMPDIR = \"${TOPDIR}/tmp-sstates-findsiginfo\"
727TCLIBCAPPEND = \"\"
728MACHINE = \"qemux86-64\" 715MACHINE = \"qemux86-64\"
729require conf/multilib.conf 716require conf/multilib.conf
730MULTILIBS = "multilib:lib32" 717MULTILIBS = "multilib:lib32"
@@ -917,15 +904,24 @@ INHERIT += "base-do-configure-modified"
917""", 904""",
918expected_sametmp_output, expected_difftmp_output) 905expected_sametmp_output, expected_difftmp_output)
919 906
920@OETestTag("yocto-mirrors") 907class SStateCheckObjectPresence(SStateBase):
921class SStateMirrors(SStateBase): 908 def check_bb_output(self, output, targets, exceptions, check_cdn):
922 def check_bb_output(self, output, exceptions, check_cdn):
923 def is_exception(object, exceptions): 909 def is_exception(object, exceptions):
924 for e in exceptions: 910 for e in exceptions:
925 if re.search(e, object): 911 if re.search(e, object):
926 return True 912 return True
927 return False 913 return False
928 914
915 # sstate is checked for existence of these, but they never get written out to begin with
916 exceptions += ["{}.*image_qa".format(t) for t in targets.split()]
917 exceptions += ["{}.*deploy_source_date_epoch".format(t) for t in targets.split()]
918 exceptions += ["{}.*image_complete".format(t) for t in targets.split()]
919 exceptions += ["linux-yocto.*shared_workdir"]
920 # these get influnced by IMAGE_FSTYPES tweaks in yocto-autobuilder-helper's config.json (on x86-64)
921 # additionally, they depend on noexec (thus, absent stamps) package, install, etc. image tasks,
922 # which makes tracing other changes difficult
923 exceptions += ["{}.*create_.*spdx".format(t) for t in targets.split()]
924
929 output_l = output.splitlines() 925 output_l = output.splitlines()
930 for l in output_l: 926 for l in output_l:
931 if l.startswith("Sstate summary"): 927 if l.startswith("Sstate summary"):
@@ -960,18 +956,9 @@ class SStateMirrors(SStateBase):
960 self.assertEqual(len(failed_urls), missing_objects, "Amount of reported missing objects does not match failed URLs: {}\nFailed URLs:\n{}\nFetcher diagnostics:\n{}".format(missing_objects, "\n".join(failed_urls), "\n".join(failed_urls_extrainfo))) 956 self.assertEqual(len(failed_urls), missing_objects, "Amount of reported missing objects does not match failed URLs: {}\nFailed URLs:\n{}\nFetcher diagnostics:\n{}".format(missing_objects, "\n".join(failed_urls), "\n".join(failed_urls_extrainfo)))
961 self.assertEqual(len(failed_urls), 0, "Missing objects in the cache:\n{}\nFetcher diagnostics:\n{}".format("\n".join(failed_urls), "\n".join(failed_urls_extrainfo))) 957 self.assertEqual(len(failed_urls), 0, "Missing objects in the cache:\n{}\nFetcher diagnostics:\n{}".format("\n".join(failed_urls), "\n".join(failed_urls_extrainfo)))
962 958
959@OETestTag("yocto-mirrors")
960class SStateMirrors(SStateCheckObjectPresence):
963 def run_test(self, machine, targets, exceptions, check_cdn = True, ignore_errors = False): 961 def run_test(self, machine, targets, exceptions, check_cdn = True, ignore_errors = False):
964 # sstate is checked for existence of these, but they never get written out to begin with
965 exceptions += ["{}.*image_qa".format(t) for t in targets.split()]
966 exceptions += ["{}.*deploy_source_date_epoch".format(t) for t in targets.split()]
967 exceptions += ["{}.*image_complete".format(t) for t in targets.split()]
968 exceptions += ["linux-yocto.*shared_workdir"]
969 # these get influnced by IMAGE_FSTYPES tweaks in yocto-autobuilder-helper's config.json (on x86-64)
970 # additionally, they depend on noexec (thus, absent stamps) package, install, etc. image tasks,
971 # which makes tracing other changes difficult
972 exceptions += ["{}.*create_spdx".format(t) for t in targets.split()]
973 exceptions += ["{}.*create_runtime_spdx".format(t) for t in targets.split()]
974
975 if check_cdn: 962 if check_cdn:
976 self.config_sstate(True) 963 self.config_sstate(True)
977 self.append_config(""" 964 self.append_config("""
@@ -987,7 +974,7 @@ MACHINE = "{}"
987 bitbake("-S none {}".format(targets)) 974 bitbake("-S none {}".format(targets))
988 if ignore_errors: 975 if ignore_errors:
989 return 976 return
990 self.check_bb_output(result.output, exceptions, check_cdn) 977 self.check_bb_output(result.output, targets, exceptions, check_cdn)
991 978
992 def test_cdn_mirror_qemux86_64(self): 979 def test_cdn_mirror_qemux86_64(self):
993 exceptions = [] 980 exceptions = []
diff --git a/meta/lib/oeqa/selftest/context.py b/meta/lib/oeqa/selftest/context.py
index 99186175e5..acc3b073bd 100644
--- a/meta/lib/oeqa/selftest/context.py
+++ b/meta/lib/oeqa/selftest/context.py
@@ -117,8 +117,11 @@ class OESelftestTestContext(OETestContext):
117 newbblayers += 'BBLAYERS = "%s"\n' % ' '.join(bblayers_abspath) 117 newbblayers += 'BBLAYERS = "%s"\n' % ' '.join(bblayers_abspath)
118 f.write(newbblayers) 118 f.write(newbblayers)
119 119
120 # Rewrite builddir paths seen in environment variables
120 for e in os.environ: 121 for e in os.environ:
121 if builddir + "/" in os.environ[e]: 122 # Rewrite paths that absolutely point inside builddir
123 # (e.g $builddir/conf/ would be rewritten but not $builddir/../bitbake/)
124 if builddir + "/" in os.environ[e] and builddir + "/" in os.path.abspath(os.environ[e]):
122 os.environ[e] = os.environ[e].replace(builddir + "/", newbuilddir + "/") 125 os.environ[e] = os.environ[e].replace(builddir + "/", newbuilddir + "/")
123 if os.environ[e].endswith(builddir): 126 if os.environ[e].endswith(builddir):
124 os.environ[e] = os.environ[e].replace(builddir, newbuilddir) 127 os.environ[e] = os.environ[e].replace(builddir, newbuilddir)