mirror of
https://git.yoctoproject.org/poky
synced 2026-01-29 21:08:42 +01:00
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: 72ee311d4f74499674a29223fb02d4e774097a54) 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> (cherry picked from commit 14f534f15f7fe6362723d7f064d39783c5bd758f) Signed-off-by: Kamel Bouhara (Schneider Electric) <kamel.bouhara@bootlin.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
This commit is contained in:
committed by
Steve Sakoman
parent
568c1afab4
commit
1919d76f68
@@ -7,9 +7,11 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import textwrap
|
import textwrap
|
||||||
|
import hashlib
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from oeqa.selftest.case import OESelftestTestCase
|
from oeqa.selftest.case import OESelftestTestCase
|
||||||
from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runCmd
|
from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runCmd
|
||||||
|
import oe.spdx30
|
||||||
|
|
||||||
|
|
||||||
class SPDX22Check(OESelftestTestCase):
|
class SPDX22Check(OESelftestTestCase):
|
||||||
@@ -73,8 +75,6 @@ class SPDX3CheckBase(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def check_spdx_file(self, filename):
|
def check_spdx_file(self, filename):
|
||||||
import oe.spdx30
|
|
||||||
|
|
||||||
self.assertExists(filename)
|
self.assertExists(filename)
|
||||||
|
|
||||||
# Read the file
|
# Read the file
|
||||||
@@ -86,13 +86,16 @@ class SPDX3CheckBase(object):
|
|||||||
return objset
|
return objset
|
||||||
|
|
||||||
def check_recipe_spdx(self, target_name, spdx_path, *, task=None, extraconf=""):
|
def check_recipe_spdx(self, target_name, spdx_path, *, task=None, extraconf=""):
|
||||||
config = textwrap.dedent(
|
config = (
|
||||||
f"""\
|
textwrap.dedent(
|
||||||
INHERIT:remove = "create-spdx"
|
f"""\
|
||||||
INHERIT += "{self.SPDX_CLASS}"
|
INHERIT:remove = "create-spdx"
|
||||||
{extraconf}
|
INHERIT += "{self.SPDX_CLASS}"
|
||||||
"""
|
"""
|
||||||
|
)
|
||||||
|
+ textwrap.dedent(extraconf)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.write_config(config)
|
self.write_config(config)
|
||||||
|
|
||||||
if task:
|
if task:
|
||||||
@@ -120,11 +123,17 @@ class SPDX3CheckBase(object):
|
|||||||
return self.check_spdx_file(filename)
|
return self.check_spdx_file(filename)
|
||||||
|
|
||||||
def check_objset_missing_ids(self, objset):
|
def check_objset_missing_ids(self, objset):
|
||||||
if objset.missing_ids:
|
for o in objset.foreach_type(oe.spdx30.SpdxDocument):
|
||||||
|
doc = o
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.assertTrue(False, "Unable to find SpdxDocument")
|
||||||
|
|
||||||
|
missing_ids = objset.missing_ids - set(i.externalSpdxId for i in doc.import_)
|
||||||
|
if missing_ids:
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
False,
|
False,
|
||||||
"The following SPDXIDs are unresolved:\n "
|
"The following SPDXIDs are unresolved:\n " + "\n ".join(missing_ids),
|
||||||
+ "\n ".join(objset.missing_ids),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -188,12 +197,93 @@ class SPDX30Check(SPDX3CheckBase, OESelftestTestCase):
|
|||||||
objset = self.check_recipe_spdx(
|
objset = self.check_recipe_spdx(
|
||||||
"baremetal-helloworld",
|
"baremetal-helloworld",
|
||||||
"{DEPLOY_DIR_IMAGE}/baremetal-helloworld-image-{MACHINE}.spdx.json",
|
"{DEPLOY_DIR_IMAGE}/baremetal-helloworld-image-{MACHINE}.spdx.json",
|
||||||
extraconf=textwrap.dedent(
|
extraconf="""\
|
||||||
"""\
|
|
||||||
TCLIBC = "baremetal"
|
TCLIBC = "baremetal"
|
||||||
"""
|
""",
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Document should be fully linked
|
# Document should be fully linked
|
||||||
self.check_objset_missing_ids(objset)
|
self.check_objset_missing_ids(objset)
|
||||||
|
|
||||||
|
def test_extra_opts(self):
|
||||||
|
HOST_SPDXID = "http://foo.bar/spdx/bar2"
|
||||||
|
|
||||||
|
EXTRACONF = textwrap.dedent(
|
||||||
|
f"""\
|
||||||
|
SPDX_INVOKED_BY_name = "CI Tool"
|
||||||
|
SPDX_INVOKED_BY_type = "software"
|
||||||
|
|
||||||
|
SPDX_ON_BEHALF_OF_name = "John Doe"
|
||||||
|
SPDX_ON_BEHALF_OF_type = "person"
|
||||||
|
SPDX_ON_BEHALF_OF_id_email = "John.Doe@noreply.com"
|
||||||
|
|
||||||
|
SPDX_PACKAGE_SUPPLIER_name = "ACME Embedded Widgets"
|
||||||
|
SPDX_PACKAGE_SUPPLIER_type = "organization"
|
||||||
|
|
||||||
|
SPDX_AUTHORS += "authorA"
|
||||||
|
SPDX_AUTHORS_authorA_ref = "SPDX_ON_BEHALF_OF"
|
||||||
|
|
||||||
|
SPDX_BUILD_HOST = "host"
|
||||||
|
|
||||||
|
SPDX_IMPORTS += "host"
|
||||||
|
SPDX_IMPORTS_host_spdxid = "{HOST_SPDXID}"
|
||||||
|
|
||||||
|
SPDX_INCLUDE_BUILD_VARIABLES = "1"
|
||||||
|
SPDX_INCLUDE_BITBAKE_PARENT_BUILD = "1"
|
||||||
|
SPDX_INCLUDE_TIMESTAMPS = "1"
|
||||||
|
|
||||||
|
SPDX_PRETTY = "1"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
extraconf_hash = hashlib.sha1(EXTRACONF.encode("utf-8")).hexdigest()
|
||||||
|
|
||||||
|
objset = self.check_recipe_spdx(
|
||||||
|
"core-image-minimal",
|
||||||
|
"{DEPLOY_DIR_IMAGE}/core-image-minimal-{MACHINE}.rootfs.spdx.json",
|
||||||
|
# Many SPDX variables do not trigger a rebuild, since they are
|
||||||
|
# intended to record information at the time of the build. As such,
|
||||||
|
# the extra configuration alone may not trigger a rebuild, and even
|
||||||
|
# if it does, the task hash won't necessarily be unique. In order
|
||||||
|
# to make sure rebuilds happen, but still allow these test objects
|
||||||
|
# to be pulled from sstate (e.g. remain reproducible), change the
|
||||||
|
# namespace prefix to include the hash of the extra configuration
|
||||||
|
extraconf=textwrap.dedent(
|
||||||
|
f"""\
|
||||||
|
SPDX_NAMESPACE_PREFIX = "http://spdx.org/spdxdocs/{extraconf_hash}"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
+ EXTRACONF,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Document should be fully linked
|
||||||
|
self.check_objset_missing_ids(objset)
|
||||||
|
|
||||||
|
for o in objset.foreach_type(oe.spdx30.SoftwareAgent):
|
||||||
|
if o.name == "CI Tool":
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.assertTrue(False, "Unable to find software tool")
|
||||||
|
|
||||||
|
for o in objset.foreach_type(oe.spdx30.Person):
|
||||||
|
if o.name == "John Doe":
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.assertTrue(False, "Unable to find person")
|
||||||
|
|
||||||
|
for o in objset.foreach_type(oe.spdx30.Organization):
|
||||||
|
if o.name == "ACME Embedded Widgets":
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.assertTrue(False, "Unable to find organization")
|
||||||
|
|
||||||
|
for o in objset.foreach_type(oe.spdx30.SpdxDocument):
|
||||||
|
doc = o
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.assertTrue(False, "Unable to find SpdxDocument")
|
||||||
|
|
||||||
|
for i in doc.import_:
|
||||||
|
if i.externalSpdxId == HOST_SPDXID:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.assertTrue(False, "Unable to find imported Host SpdxID")
|
||||||
|
|||||||
Reference in New Issue
Block a user