summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa
diff options
context:
space:
mode:
authorJoshua Watt <jpewhacker@gmail.com>2024-12-03 15:37:10 -0700
committerRichard Purdie <richard.purdie@linuxfoundation.org>2024-12-05 17:07:10 +0000
commit30638546af257eb6117be3c12b103f54a9b7492a (patch)
tree5d6feec1bca6ab6a90f49704dbc925164d92bcc7 /meta/lib/oeqa
parenteda4a8bc21a3eafa557f85dc625c58959b262508 (diff)
downloadpoky-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.py118
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 @@
7import json 7import json
8import os 8import os
9import textwrap 9import textwrap
10import hashlib
10from pathlib import Path 11from pathlib import Path
11from oeqa.selftest.case import OESelftestTestCase 12from oeqa.selftest.case import OESelftestTestCase
12from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runCmd 13from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runCmd
14import oe.spdx30
13 15
14 16
15class SPDX22Check(OESelftestTestCase): 17class 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")