diff options
| author | Joshua Watt <jpewhacker@gmail.com> | 2024-12-03 15:37:10 -0700 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2024-12-05 17:07:10 +0000 |
| commit | 30638546af257eb6117be3c12b103f54a9b7492a (patch) | |
| tree | 5d6feec1bca6ab6a90f49704dbc925164d92bcc7 /meta/lib/oeqa | |
| parent | eda4a8bc21a3eafa557f85dc625c58959b262508 (diff) | |
| download | poky-30638546af257eb6117be3c12b103f54a9b7492a.tar.gz | |
lib: oeqa: spdx: Add tests for extra options
Adds a test for several of the extra options provided by the SPDX
classes. In particular, these are the options that can produce
non-reproducible results, so are not enabled by default in OE core. This
test takes care to configure the build so that the tests do run in a
reproducible manner so that pre-built test objects can be pulled from
sstate
(From OE-Core rev: 14f534f15f7fe6362723d7f064d39783c5bd758f)
Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib/oeqa')
| -rw-r--r-- | meta/lib/oeqa/selftest/cases/spdx.py | 118 |
1 files changed, 104 insertions, 14 deletions
diff --git a/meta/lib/oeqa/selftest/cases/spdx.py b/meta/lib/oeqa/selftest/cases/spdx.py index 8384070219..9b35793d13 100644 --- a/meta/lib/oeqa/selftest/cases/spdx.py +++ b/meta/lib/oeqa/selftest/cases/spdx.py | |||
| @@ -7,9 +7,11 @@ | |||
| 7 | import json | 7 | import json |
| 8 | import os | 8 | import os |
| 9 | import textwrap | 9 | import textwrap |
| 10 | import hashlib | ||
| 10 | from pathlib import Path | 11 | from pathlib import Path |
| 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 |
| 14 | import oe.spdx30 | ||
| 13 | 15 | ||
| 14 | 16 | ||
| 15 | class SPDX22Check(OESelftestTestCase): | 17 | class SPDX22Check(OESelftestTestCase): |
| @@ -73,8 +75,6 @@ class SPDX3CheckBase(object): | |||
| 73 | """ | 75 | """ |
| 74 | 76 | ||
| 75 | def check_spdx_file(self, filename): | 77 | def check_spdx_file(self, filename): |
| 76 | import oe.spdx30 | ||
| 77 | |||
| 78 | self.assertExists(filename) | 78 | self.assertExists(filename) |
| 79 | 79 | ||
| 80 | # Read the file | 80 | # Read the file |
| @@ -86,13 +86,16 @@ class SPDX3CheckBase(object): | |||
| 86 | return objset | 86 | return objset |
| 87 | 87 | ||
| 88 | def check_recipe_spdx(self, target_name, spdx_path, *, task=None, extraconf=""): | 88 | def check_recipe_spdx(self, target_name, spdx_path, *, task=None, extraconf=""): |
| 89 | config = textwrap.dedent( | 89 | config = ( |
| 90 | f"""\ | 90 | textwrap.dedent( |
| 91 | INHERIT:remove = "create-spdx" | 91 | f"""\ |
| 92 | INHERIT += "{self.SPDX_CLASS}" | 92 | INHERIT:remove = "create-spdx" |
| 93 | {extraconf} | 93 | INHERIT += "{self.SPDX_CLASS}" |
| 94 | """ | 94 | """ |
| 95 | ) | ||
| 96 | + textwrap.dedent(extraconf) | ||
| 95 | ) | 97 | ) |
| 98 | |||
| 96 | self.write_config(config) | 99 | self.write_config(config) |
| 97 | 100 | ||
| 98 | if task: | 101 | if task: |
| @@ -120,11 +123,17 @@ class SPDX3CheckBase(object): | |||
| 120 | return self.check_spdx_file(filename) | 123 | return self.check_spdx_file(filename) |
| 121 | 124 | ||
| 122 | def check_objset_missing_ids(self, objset): | 125 | def check_objset_missing_ids(self, objset): |
| 123 | if objset.missing_ids: | 126 | for o in objset.foreach_type(oe.spdx30.SpdxDocument): |
| 127 | doc = o | ||
| 128 | break | ||
| 129 | else: | ||
| 130 | self.assertTrue(False, "Unable to find SpdxDocument") | ||
| 131 | |||
| 132 | missing_ids = objset.missing_ids - set(i.externalSpdxId for i in doc.import_) | ||
| 133 | if missing_ids: | ||
| 124 | self.assertTrue( | 134 | self.assertTrue( |
| 125 | False, | 135 | False, |
| 126 | "The following SPDXIDs are unresolved:\n " | 136 | "The following SPDXIDs are unresolved:\n " + "\n ".join(missing_ids), |
| 127 | + "\n ".join(objset.missing_ids), | ||
| 128 | ) | 137 | ) |
| 129 | 138 | ||
| 130 | 139 | ||
| @@ -188,12 +197,93 @@ class SPDX30Check(SPDX3CheckBase, OESelftestTestCase): | |||
| 188 | objset = self.check_recipe_spdx( | 197 | objset = self.check_recipe_spdx( |
| 189 | "baremetal-helloworld", | 198 | "baremetal-helloworld", |
| 190 | "{DEPLOY_DIR_IMAGE}/baremetal-helloworld-image-{MACHINE}.spdx.json", | 199 | "{DEPLOY_DIR_IMAGE}/baremetal-helloworld-image-{MACHINE}.spdx.json", |
| 191 | extraconf=textwrap.dedent( | 200 | extraconf="""\ |
| 192 | """\ | ||
| 193 | TCLIBC = "baremetal" | 201 | TCLIBC = "baremetal" |
| 202 | """, | ||
| 203 | ) | ||
| 204 | |||
| 205 | # Document should be fully linked | ||
| 206 | self.check_objset_missing_ids(objset) | ||
| 207 | |||
| 208 | def test_extra_opts(self): | ||
| 209 | HOST_SPDXID = "http://foo.bar/spdx/bar2" | ||
| 210 | |||
| 211 | EXTRACONF = textwrap.dedent( | ||
| 212 | f"""\ | ||
| 213 | SPDX_INVOKED_BY_name = "CI Tool" | ||
| 214 | SPDX_INVOKED_BY_type = "software" | ||
| 215 | |||
| 216 | SPDX_ON_BEHALF_OF_name = "John Doe" | ||
| 217 | SPDX_ON_BEHALF_OF_type = "person" | ||
| 218 | SPDX_ON_BEHALF_OF_id_email = "John.Doe@noreply.com" | ||
| 219 | |||
| 220 | SPDX_PACKAGE_SUPPLIER_name = "ACME Embedded Widgets" | ||
| 221 | SPDX_PACKAGE_SUPPLIER_type = "organization" | ||
| 222 | |||
| 223 | SPDX_AUTHORS += "authorA" | ||
| 224 | SPDX_AUTHORS_authorA_ref = "SPDX_ON_BEHALF_OF" | ||
| 225 | |||
| 226 | SPDX_BUILD_HOST = "host" | ||
| 227 | |||
| 228 | SPDX_IMPORTS += "host" | ||
| 229 | SPDX_IMPORTS_host_spdxid = "{HOST_SPDXID}" | ||
| 230 | |||
| 231 | SPDX_INCLUDE_BUILD_VARIABLES = "1" | ||
| 232 | SPDX_INCLUDE_BITBAKE_PARENT_BUILD = "1" | ||
| 233 | SPDX_INCLUDE_TIMESTAMPS = "1" | ||
| 234 | |||
| 235 | SPDX_PRETTY = "1" | ||
| 236 | """ | ||
| 237 | ) | ||
| 238 | extraconf_hash = hashlib.sha1(EXTRACONF.encode("utf-8")).hexdigest() | ||
| 239 | |||
| 240 | objset = self.check_recipe_spdx( | ||
| 241 | "core-image-minimal", | ||
| 242 | "{DEPLOY_DIR_IMAGE}/core-image-minimal-{MACHINE}.rootfs.spdx.json", | ||
| 243 | # Many SPDX variables do not trigger a rebuild, since they are | ||
| 244 | # intended to record information at the time of the build. As such, | ||
| 245 | # the extra configuration alone may not trigger a rebuild, and even | ||
| 246 | # if it does, the task hash won't necessarily be unique. In order | ||
| 247 | # to make sure rebuilds happen, but still allow these test objects | ||
| 248 | # to be pulled from sstate (e.g. remain reproducible), change the | ||
| 249 | # namespace prefix to include the hash of the extra configuration | ||
| 250 | extraconf=textwrap.dedent( | ||
| 251 | f"""\ | ||
| 252 | SPDX_NAMESPACE_PREFIX = "http://spdx.org/spdxdocs/{extraconf_hash}" | ||
| 194 | """ | 253 | """ |
| 195 | ), | 254 | ) |
| 255 | + EXTRACONF, | ||
| 196 | ) | 256 | ) |
| 197 | 257 | ||
| 198 | # Document should be fully linked | 258 | # Document should be fully linked |
| 199 | self.check_objset_missing_ids(objset) | 259 | self.check_objset_missing_ids(objset) |
| 260 | |||
| 261 | for o in objset.foreach_type(oe.spdx30.SoftwareAgent): | ||
| 262 | if o.name == "CI Tool": | ||
| 263 | break | ||
| 264 | else: | ||
| 265 | self.assertTrue(False, "Unable to find software tool") | ||
| 266 | |||
| 267 | for o in objset.foreach_type(oe.spdx30.Person): | ||
| 268 | if o.name == "John Doe": | ||
| 269 | break | ||
| 270 | else: | ||
| 271 | self.assertTrue(False, "Unable to find person") | ||
| 272 | |||
| 273 | for o in objset.foreach_type(oe.spdx30.Organization): | ||
| 274 | if o.name == "ACME Embedded Widgets": | ||
| 275 | break | ||
| 276 | else: | ||
| 277 | self.assertTrue(False, "Unable to find organization") | ||
| 278 | |||
| 279 | for o in objset.foreach_type(oe.spdx30.SpdxDocument): | ||
| 280 | doc = o | ||
| 281 | break | ||
| 282 | else: | ||
| 283 | self.assertTrue(False, "Unable to find SpdxDocument") | ||
| 284 | |||
| 285 | for i in doc.import_: | ||
| 286 | if i.externalSpdxId == HOST_SPDXID: | ||
| 287 | break | ||
| 288 | else: | ||
| 289 | self.assertTrue(False, "Unable to find imported Host SpdxID") | ||
