[OE-core][PATCH v5 6/8] selftest: spdx: Add SPDX 3.0 test cases

Joshua Watt
2024-07-03T14:01:26Z

Adds test cases for SPDX 3.0. Reworks the SPDX 2.2 test setup so it can
also be run even if the default is SPDX 3.0

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
meta/lib/oeqa/selftest/cases/spdx.py | 118 +++++++++++++++++++++++++--
1 file changed, 109 insertions(+), 9 deletions(-)

diff --git a/meta/lib/oeqa/selftest/cases/spdx.py b/meta/lib/oeqa/selftest/cases/spdx.py
index 7685a81e7fb..4a507633cfe 100644
--- a/meta/lib/oeqa/selftest/cases/spdx.py
+++ b/meta/lib/oeqa/selftest/cases/spdx.py
@@ -6,21 +6,26 @@

import json
import os
+import textwrap
+from pathlib import Path
from oeqa.selftest.case import OESelftestTestCase
-from oeqa.utils.commands import bitbake, get_bb_var, runCmd
+from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runCmd

-class SPDXCheck(OESelftestTestCase):

+class SPDX22Check(OESelftestTestCase):
@classmethod
def setUpClass(cls):
- super(SPDXCheck, cls).setUpClass()
+ super().setUpClass()
bitbake("python3-spdx-tools-native")
bitbake("-c addto_recipe_sysroot python3-spdx-tools-native")

def check_recipe_spdx(self, high_level_dir, spdx_file, target_name):
- config = """
-INHERIT += "create-spdx"
-"""
+ config = textwrap.dedent(
+ """\
+ INHERIT:remove = "create-spdx"
+ INHERIT += "create-spdx-2.2"
+ """
+ )
self.write_config(config)

deploy_dir = get_bb_var("DEPLOY_DIR")
@@ -29,7 +34,9 @@ INHERIT += "create-spdx"
# qemux86-64 creates the directory qemux86_64
machine_dir = machine_var.replace("-", "_")

- full_file_path = os.path.join(deploy_dir, "spdx", spdx_version, machine_dir, high_level_dir, spdx_file)
+ full_file_path = os.path.join(
+ deploy_dir, "spdx", spdx_version, machine_dir, high_level_dir, spdx_file
+ )

try:
os.remove(full_file_path)
@@ -44,8 +51,13 @@ INHERIT += "create-spdx"
self.assertNotEqual(report, None)
self.assertNotEqual(report["SPDXID"], None)

- python = os.path.join(get_bb_var('STAGING_BINDIR', 'python3-spdx-tools-native'), 'nativepython3')
- validator = os.path.join(get_bb_var('STAGING_BINDIR', 'python3-spdx-tools-native'), 'pyspdxtools')
+ python = os.path.join(
+ get_bb_var("STAGING_BINDIR", "python3-spdx-tools-native"),
+ "nativepython3",
+ )
+ validator = os.path.join(
+ get_bb_var("STAGING_BINDIR", "python3-spdx-tools-native"), "pyspdxtools"
+ )
result = runCmd("{} {} -i {}".format(python, validator, filename))

self.assertExists(full_file_path)
@@ -53,3 +65,91 @@ INHERIT += "create-spdx"

def test_spdx_base_files(self):
self.check_recipe_spdx("packages", "base-files.spdx.json", "base-files")
+
+
+class SPDX3CheckBase(object):
+ """
+ Base class for checking SPDX 3 based tests
+ """
+
+ def check_spdx_file(self, filename):
+ import oe.spdx30
+
+ self.assertExists(filename)
+
+ # Read the file
+ objset = oe.spdx30.SHACLObjectSet()
+ with open(filename, "r") as f:
+ d = oe.spdx30.JSONLDDeserializer()
+ d.read(f, objset)
+
+ return objset
+
+ def check_recipe_spdx(self, target_name, spdx_path, *, task=None):
+ config = textwrap.dedent(
+ f"""\
+ INHERIT:remove = "create-spdx"
+ INHERIT += "{self.SPDX_CLASS}"
+ """
+ )
+ self.write_config(config)
+
+ if task:
+ bitbake(f"-c {task} {target_name}")
+ else:
+ bitbake(target_name)
+
+ filename = spdx_path.format(
+ **get_bb_vars(
+ [
+ "DEPLOY_DIR_IMAGE",
+ "DEPLOY_DIR_SPDX",
+ "MACHINE",
+ "MACHINE_ARCH",
+ "SDKMACHINE",
+ "SDK_DEPLOY",
+ "SPDX_VERSION",
+ "TOOLCHAIN_OUTPUTNAME",
+ ],
+ target_name,
+ )
+ )
+
+ return self.check_spdx_file(filename)
+
+ def check_objset_missing_ids(self, objset):
+ if objset.missing_ids:
+ self.assertTrue(
+ False,
+ "The following SPDXIDs are unresolved:\n "
+ + "\n ".join(objset.missing_ids),
+ )
+
+
+class SPDX30Check(SPDX3CheckBase, OESelftestTestCase):
+ SPDX_CLASS = "create-spdx-3.0"
+
+ def test_base_files(self):
+ self.check_recipe_spdx(
+ "base-files",
+ "{DEPLOY_DIR_SPDX}/{MACHINE_ARCH}/packages/base-files.spdx.json",
+ )
+
+ def test_core_image_minimal(self):
+ objset = self.check_recipe_spdx(
+ "core-image-minimal",
+ "{DEPLOY_DIR_IMAGE}/core-image-minimal-{MACHINE}.rootfs.spdx.json",
+ )
+
+ # Document should be fully linked
+ self.check_objset_missing_ids(objset)
+
+ def test_core_image_minimal_sdk(self):
+ objset = self.check_recipe_spdx(
+ "core-image-minimal",
+ "{SDK_DEPLOY}/{TOOLCHAIN_OUTPUTNAME}.spdx.json",
+ task="populate_sdk",
+ )
+
+ # Document should be fully linked
+ self.check_objset_missing_ids(objset)
--
2.45.2