diff options
Diffstat (limited to 'meta/lib/oeqa/selftest')
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 | |||
7 | from oeqa.selftest.case import OESelftestTestCase | ||
8 | from oeqa.utils.commands import get_bb_vars, bitbake | ||
9 | |||
10 | class 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(""" | ||
44 | DISTRO_FEATURES:append = " systemd usrmerge" | ||
45 | DISTRO_FEATURES:remove = "sysvinit" | ||
46 | VIRTUAL-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(""" | ||
68 | DISTRO_FEATURES:append = " systemd sysvinit usrmerge" | ||
69 | VIRTUAL-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(""" | ||
91 | DISTRO_FEATURES:remove = "systemd" | ||
92 | DISTRO_FEATURES:append = " sysvinit usrmerge" | ||
93 | VIRTUAL-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 | ||
179 | class ArchiverTest(OESelftestTestCase): | 179 | class 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(""" |
116 | Unable to find recipes for the following entries in maintainers.inc: | 116 | Unable 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 | ||
12 | class FitImageTests(OESelftestTestCase): | 12 | class 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 |
113 | MACHINE = "beaglebone-yocto" | 157 | MACHINE = "beaglebone-yocto" |
114 | KERNEL_IMAGETYPES += " fitImage " | 158 | KERNEL_IMAGETYPES += " fitImage " |
115 | KERNEL_CLASSES = " kernel-fitimage test-mkimage-wrapper " | 159 | KERNEL_CLASSES = " kernel-fitimage " |
116 | UBOOT_SIGN_ENABLE = "1" | 160 | UBOOT_SIGN_ENABLE = "1" |
117 | FIT_GENERATE_KEYS = "1" | 161 | FIT_GENERATE_KEYS = "1" |
118 | UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" | 162 | UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" |
119 | UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest" | 163 | UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest" |
120 | UBOOT_SIGN_KEYNAME = "cfg-oe-selftest" | 164 | UBOOT_SIGN_KEYNAME = "cfg-oe-selftest" |
121 | FIT_SIGN_INDIVIDUAL = "1" | 165 | FIT_SIGN_INDIVIDUAL = "1" |
122 | UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" | 166 | UBOOT_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" | |||
351 | UBOOT_FIT_DESC = "A model description" | 388 | UBOOT_FIT_DESC = "A model description" |
352 | KERNEL_IMAGETYPES += " fitImage " | 389 | KERNEL_IMAGETYPES += " fitImage " |
353 | KERNEL_CLASSES = " kernel-fitimage " | 390 | KERNEL_CLASSES = " kernel-fitimage " |
354 | INHERIT += "test-mkimage-wrapper" | ||
355 | UBOOT_SIGN_ENABLE = "1" | 391 | UBOOT_SIGN_ENABLE = "1" |
356 | FIT_GENERATE_KEYS = "1" | 392 | FIT_GENERATE_KEYS = "1" |
357 | UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" | 393 | UBOOT_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 |
436 | KERNEL_CLASSES = " kernel-fitimage" | 471 | KERNEL_CLASSES = " kernel-fitimage" |
437 | INHERIT += "test-mkimage-wrapper" | ||
438 | # Enable creation and signing of the U-Boot fitImage | 472 | # Enable creation and signing of the U-Boot fitImage |
439 | UBOOT_FITIMAGE_ENABLE = "1" | 473 | UBOOT_FITIMAGE_ENABLE = "1" |
440 | SPL_SIGN_ENABLE = "1" | 474 | SPL_SIGN_ENABLE = "1" |
@@ -446,17 +480,17 @@ UBOOT_LOADADDRESS = "0x80000000" | |||
446 | UBOOT_DTB_LOADADDRESS = "0x82000000" | 480 | UBOOT_DTB_LOADADDRESS = "0x82000000" |
447 | UBOOT_ARCH = "arm" | 481 | UBOOT_ARCH = "arm" |
448 | SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" | 482 | SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" |
449 | SPL_MKIMAGE_SIGN_ARGS = "-c 'a smart U-Boot comment'" | 483 | SPL_MKIMAGE_SIGN_ARGS = "-c '%s'" |
450 | UBOOT_EXTLINUX = "0" | 484 | UBOOT_EXTLINUX = "0" |
451 | UBOOT_FIT_GENERATE_KEYS = "1" | 485 | UBOOT_FIT_GENERATE_KEYS = "1" |
452 | UBOOT_FIT_HASH_ALG = "sha256" | 486 | UBOOT_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" | |||
588 | UBOOT_ENTRYPOINT = "0x80000000" | 617 | UBOOT_ENTRYPOINT = "0x80000000" |
589 | UBOOT_LOADADDRESS = "0x80000000" | 618 | UBOOT_LOADADDRESS = "0x80000000" |
590 | UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" | 619 | UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" |
591 | UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart cascaded Kernel comment'" | 620 | UBOOT_MKIMAGE_SIGN_ARGS = "-c '%s'" |
592 | UBOOT_DTB_LOADADDRESS = "0x82000000" | 621 | UBOOT_DTB_LOADADDRESS = "0x82000000" |
593 | UBOOT_ARCH = "arm" | 622 | UBOOT_ARCH = "arm" |
594 | SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" | 623 | SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" |
@@ -598,20 +627,18 @@ UBOOT_FIT_GENERATE_KEYS = "1" | |||
598 | UBOOT_FIT_HASH_ALG = "sha256" | 627 | UBOOT_FIT_HASH_ALG = "sha256" |
599 | KERNEL_IMAGETYPES += " fitImage " | 628 | KERNEL_IMAGETYPES += " fitImage " |
600 | KERNEL_CLASSES = " kernel-fitimage " | 629 | KERNEL_CLASSES = " kernel-fitimage " |
601 | INHERIT += "test-mkimage-wrapper" | ||
602 | UBOOT_SIGN_ENABLE = "1" | 630 | UBOOT_SIGN_ENABLE = "1" |
603 | FIT_GENERATE_KEYS = "1" | 631 | FIT_GENERATE_KEYS = "1" |
604 | UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" | 632 | UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" |
605 | UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest" | 633 | UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest" |
606 | UBOOT_SIGN_KEYNAME = "cfg-oe-selftest" | 634 | UBOOT_SIGN_KEYNAME = "cfg-oe-selftest" |
607 | FIT_SIGN_INDIVIDUAL = "1" | 635 | FIT_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" | |||
250 | DISTRO_FEATURES:append = " pam opengl wayland" | 250 | DISTRO_FEATURES:append = " pam opengl wayland" |
251 | 251 | ||
252 | # Switch to systemd | 252 | # Switch to systemd |
253 | DISTRO_FEATURES:append = " systemd usrmerge" | 253 | INIT_MANAGER = "systemd" |
254 | VIRTUAL-RUNTIME_init_manager = "systemd" | ||
255 | VIRTUAL-RUNTIME_initscripts = "" | ||
256 | VIRTUAL-RUNTIME_syslog = "" | ||
257 | VIRTUAL-RUNTIME_login_manager = "shadow-base" | ||
258 | DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit" | ||
259 | 254 | ||
260 | # Replace busybox | 255 | # Replace busybox |
261 | PREFERRED_PROVIDER_virtual/base-utils = "packagegroup-core-base-utils" | 256 | PREFERRED_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 = """ |
321 | DISTRO_FEATURES:append = " api-documentation" | 316 | DISTRO_FEATURES:append = " api-documentation" |
322 | CORE_IMAGE_EXTRA_INSTALL = "man-pages kmod-doc" | 317 | CORE_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 | |||
8 | import tempfile | 8 | import tempfile |
9 | import shutil | 9 | import shutil |
10 | 10 | ||
11 | from oeqa.core.decorator import OETestTag | ||
11 | from oeqa.selftest.case import OESelftestTestCase | 12 | from oeqa.selftest.case import OESelftestTestCase |
12 | from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runCmd | 13 | from 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(""" | ||
54 | DISTRO_FEATURES:append = " minidebuginfo" | ||
55 | INIT_MANAGER = "systemd" | ||
56 | IMAGE_CLASSES += "testimage" | ||
57 | TEST_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 | ||
7 | from oeqa.selftest.case import OESelftestTestCase | 7 | from oeqa.selftest.case import OESelftestTestCase |
8 | from oeqa.utils.commands import bitbake, runqemu | 8 | from oeqa.utils.commands import bitbake, runqemu, get_bb_vars |
9 | from oeqa.core.decorator import OETestTag | 9 | from oeqa.core.decorator import OETestTag |
10 | from oeqa.core.decorator.data import skipIfNotMachine | 10 | from 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 | |||
7 | from oeqa.selftest.case import OESelftestTestCase | ||
8 | from oeqa.utils.commands import bitbake, get_bb_var | ||
9 | |||
10 | class 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 | |||
8 | import os | ||
9 | import glob | ||
10 | import fnmatch | ||
11 | import oe.path | ||
12 | import shutil | ||
13 | import tarfile | ||
14 | from oeqa.utils.commands import bitbake, get_bb_vars | ||
15 | from oeqa.selftest.case import OESelftestTestCase | ||
16 | |||
17 | class 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 | ||
7 | import json | 7 | import json |
8 | import os | 8 | import os |
9 | import textwrap | ||
10 | from pathlib import Path | ||
9 | from oeqa.selftest.case import OESelftestTestCase | 11 | from oeqa.selftest.case import OESelftestTestCase |
10 | from oeqa.utils.commands import bitbake, get_bb_var, runCmd | 12 | from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runCmd |
11 | 13 | ||
12 | class SPDXCheck(OESelftestTestCase): | ||
13 | 14 | ||
15 | class 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( |
22 | INHERIT += "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 | |||
70 | class 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 | |||
130 | class 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(""" |
379 | MACHINE = "qemux86" | 379 | MACHINE = "qemux86" |
380 | TMPDIR = "${TOPDIR}/tmp-sstatesamehash" | 380 | TMPDIR = "${TOPDIR}/tmp-sstatesamehash" |
381 | TCLIBCAPPEND = "" | ||
382 | BUILD_ARCH = "x86_64" | 381 | BUILD_ARCH = "x86_64" |
383 | BUILD_OS = "linux" | 382 | BUILD_OS = "linux" |
384 | SDKMACHINE = "x86_64" | 383 | SDKMACHINE = "x86_64" |
@@ -390,7 +389,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash" | |||
390 | self.write_config(""" | 389 | self.write_config(""" |
391 | MACHINE = "qemux86" | 390 | MACHINE = "qemux86" |
392 | TMPDIR = "${TOPDIR}/tmp-sstatesamehash2" | 391 | TMPDIR = "${TOPDIR}/tmp-sstatesamehash2" |
393 | TCLIBCAPPEND = "" | ||
394 | BUILD_ARCH = "i686" | 392 | BUILD_ARCH = "i686" |
395 | BUILD_OS = "linux" | 393 | BUILD_OS = "linux" |
396 | SDKMACHINE = "i686" | 394 | SDKMACHINE = "i686" |
@@ -426,7 +424,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash" | |||
426 | 424 | ||
427 | self.write_config(""" | 425 | self.write_config(""" |
428 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" | 426 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" |
429 | TCLIBCAPPEND = \"\" | ||
430 | NATIVELSBSTRING = \"DistroA\" | 427 | NATIVELSBSTRING = \"DistroA\" |
431 | BB_SIGNATURE_HANDLER = "OEBasicHash" | 428 | BB_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(""" |
436 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" | 433 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" |
437 | TCLIBCAPPEND = \"\" | ||
438 | NATIVELSBSTRING = \"DistroB\" | 434 | NATIVELSBSTRING = \"DistroB\" |
439 | BB_SIGNATURE_HANDLER = "OEBasicHash" | 435 | BB_SIGNATURE_HANDLER = "OEBasicHash" |
440 | """) | 436 | """) |
@@ -463,17 +459,17 @@ class SStateHashSameSigs2(SStateBase): | |||
463 | 459 | ||
464 | configA = """ | 460 | configA = """ |
465 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" | 461 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" |
466 | TCLIBCAPPEND = \"\" | ||
467 | MACHINE = \"qemux86-64\" | 462 | MACHINE = \"qemux86-64\" |
468 | BB_SIGNATURE_HANDLER = "OEBasicHash" | 463 | BB_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 = """ |
472 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" | 467 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" |
473 | TCLIBCAPPEND = \"\" | ||
474 | MACHINE = \"qemuarm\" | 468 | MACHINE = \"qemuarm\" |
475 | OLDEST_KERNEL = \"3.3.0\" | 469 | OLDEST_KERNEL = \"3.3.0\" |
476 | BB_SIGNATURE_HANDLER = "OEBasicHash" | 470 | BB_SIGNATURE_HANDLER = "OEBasicHash" |
471 | ERROR_QA:append = " somenewoption" | ||
472 | WARN_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 = """ |
486 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" | 482 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" |
487 | TCLIBCAPPEND = \"\" | ||
488 | MACHINE = \"qemux86-64\" | 483 | MACHINE = \"qemux86-64\" |
489 | require conf/multilib.conf | 484 | require conf/multilib.conf |
490 | MULTILIBS = \"multilib:lib32\" | 485 | MULTILIBS = \"multilib:lib32\" |
@@ -493,7 +488,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash" | |||
493 | """ | 488 | """ |
494 | configB = """ | 489 | configB = """ |
495 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" | 490 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" |
496 | TCLIBCAPPEND = \"\" | ||
497 | MACHINE = \"qemuarm\" | 491 | MACHINE = \"qemuarm\" |
498 | require conf/multilib.conf | 492 | require conf/multilib.conf |
499 | MULTILIBS = \"\" | 493 | MULTILIBS = \"\" |
@@ -511,7 +505,6 @@ class SStateHashSameSigs3(SStateBase): | |||
511 | 505 | ||
512 | self.write_config(""" | 506 | self.write_config(""" |
513 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" | 507 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" |
514 | TCLIBCAPPEND = \"\" | ||
515 | MACHINE = \"qemux86\" | 508 | MACHINE = \"qemux86\" |
516 | require conf/multilib.conf | 509 | require conf/multilib.conf |
517 | MULTILIBS = "multilib:lib32" | 510 | MULTILIBS = "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(""" |
524 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" | 517 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" |
525 | TCLIBCAPPEND = \"\" | ||
526 | MACHINE = \"qemux86copy\" | 518 | MACHINE = \"qemux86copy\" |
527 | require conf/multilib.conf | 519 | require conf/multilib.conf |
528 | MULTILIBS = "multilib:lib32" | 520 | MULTILIBS = "multilib:lib32" |
@@ -559,7 +551,6 @@ BB_SIGNATURE_HANDLER = "OEBasicHash" | |||
559 | 551 | ||
560 | self.write_config(""" | 552 | self.write_config(""" |
561 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" | 553 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\" |
562 | TCLIBCAPPEND = \"\" | ||
563 | MACHINE = \"qemux86\" | 554 | MACHINE = \"qemux86\" |
564 | require conf/multilib.conf | 555 | require conf/multilib.conf |
565 | MULTILIBS = "multilib:lib32" | 556 | MULTILIBS = "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(""" |
572 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" | 563 | TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\" |
573 | TCLIBCAPPEND = \"\" | ||
574 | MACHINE = \"qemux86copy\" | 564 | MACHINE = \"qemux86copy\" |
575 | BB_SIGNATURE_HANDLER = "OEBasicHash" | 565 | BB_SIGNATURE_HANDLER = "OEBasicHash" |
576 | """) | 566 | """) |
@@ -598,7 +588,6 @@ class SStateHashSameSigs4(SStateBase): | |||
598 | 588 | ||
599 | self.write_config(""" | 589 | self.write_config(""" |
600 | TMPDIR = "${TOPDIR}/tmp-sstatesamehash" | 590 | TMPDIR = "${TOPDIR}/tmp-sstatesamehash" |
601 | TCLIBCAPPEND = "" | ||
602 | BB_NUMBER_THREADS = "${@oe.utils.cpu_count()}" | 591 | BB_NUMBER_THREADS = "${@oe.utils.cpu_count()}" |
603 | PARALLEL_MAKE = "-j 1" | 592 | PARALLEL_MAKE = "-j 1" |
604 | DL_DIR = "${TOPDIR}/download1" | 593 | DL_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(""" |
615 | TMPDIR = "${TOPDIR}/tmp-sstatesamehash2" | 604 | TMPDIR = "${TOPDIR}/tmp-sstatesamehash2" |
616 | TCLIBCAPPEND = "" | ||
617 | BB_NUMBER_THREADS = "${@oe.utils.cpu_count()+1}" | 605 | BB_NUMBER_THREADS = "${@oe.utils.cpu_count()+1}" |
618 | PARALLEL_MAKE = "-j 2" | 606 | PARALLEL_MAKE = "-j 2" |
619 | DL_DIR = "${TOPDIR}/download2" | 607 | DL_DIR = "${TOPDIR}/download2" |
@@ -724,7 +712,6 @@ class SStateFindSiginfo(SStateBase): | |||
724 | """ | 712 | """ |
725 | self.write_config(""" | 713 | self.write_config(""" |
726 | TMPDIR = \"${TOPDIR}/tmp-sstates-findsiginfo\" | 714 | TMPDIR = \"${TOPDIR}/tmp-sstates-findsiginfo\" |
727 | TCLIBCAPPEND = \"\" | ||
728 | MACHINE = \"qemux86-64\" | 715 | MACHINE = \"qemux86-64\" |
729 | require conf/multilib.conf | 716 | require conf/multilib.conf |
730 | MULTILIBS = "multilib:lib32" | 717 | MULTILIBS = "multilib:lib32" |
@@ -917,15 +904,24 @@ INHERIT += "base-do-configure-modified" | |||
917 | """, | 904 | """, |
918 | expected_sametmp_output, expected_difftmp_output) | 905 | expected_sametmp_output, expected_difftmp_output) |
919 | 906 | ||
920 | @OETestTag("yocto-mirrors") | 907 | class SStateCheckObjectPresence(SStateBase): |
921 | class 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") | ||
960 | class 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) |