mirror of
https://gitlab.com/buildroot.org/buildroot.git
synced 2026-09-30 22:11:59 -09:00
support/testing/utils: add basic tests for utils/generate-cyclonedx
Introduce unit-tests for the generate-cyclonedx script, covering basic
script invocation, patch CVE extraction and virtual packages.
Signed-off-by: Martin Willi <martin@strongswan.org>
Acked-By: Thomas Perale <thomas.perale@mind.be>
[Arnout: fix check-package errors]
Signed-off-by: Arnout Vandecappelle <arnout@rnout.be>
(cherry picked from commit 929e7cb005)
Signed-off-by: Thomas Perale <thomas.perale@mind.be>
This commit is contained in:
committed by
Thomas Perale
parent
14d453e4f6
commit
8745d88263
139
support/testing/tests/utils/test_generate_cyclonedx.py
Normal file
139
support/testing/tests/utils/test_generate_cyclonedx.py
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
"""Unit tests for utils/generate-cyclonedx."""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import infra
|
||||||
|
|
||||||
|
PATCH = "support/testing/tests/utils/test_generate_cyclonedx/0001-cve_upstream.patch"
|
||||||
|
SCHEMA_LICENSES = ["MIT", "Apache-2.0", "GPL-3.0-only"]
|
||||||
|
|
||||||
|
|
||||||
|
class TestGenerateCycloneDX(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
# Provide a fake SPDX schema so the script never hits the network.
|
||||||
|
self.schema_dir = tempfile.TemporaryDirectory()
|
||||||
|
self.addCleanup(self.schema_dir.cleanup)
|
||||||
|
|
||||||
|
cyclonedx_dir = Path(self.schema_dir.name) / "cyclonedx"
|
||||||
|
cyclonedx_dir.mkdir(parents=True)
|
||||||
|
schema_path = cyclonedx_dir / "spdx-1.6.schema.json"
|
||||||
|
schema_path.write_text(json.dumps({"enum": SCHEMA_LICENSES}))
|
||||||
|
|
||||||
|
self.env = os.environ.copy()
|
||||||
|
self.env["BR2_DL_DIR"] = self.schema_dir.name
|
||||||
|
self.script = infra.basepath("utils/generate-cyclonedx")
|
||||||
|
self.cwd = infra.basepath()
|
||||||
|
|
||||||
|
def _make_show_info(self) -> dict:
|
||||||
|
return {
|
||||||
|
"package-foo": {
|
||||||
|
"name": "foo",
|
||||||
|
"version": "1.2",
|
||||||
|
"type": "target",
|
||||||
|
"virtual": False,
|
||||||
|
"licenses": "MIT",
|
||||||
|
"cpe-id": "cpe:2.3:a:example:foo:1.2:*:*:*:*:*:*:*",
|
||||||
|
"patches": [PATCH],
|
||||||
|
"provides": ["package-virtual"],
|
||||||
|
"dependencies": ["skeleton-baz", "package-bar"],
|
||||||
|
"ignore_cves": ["CVE-2025-0001"],
|
||||||
|
"package_dir": "package/package-foo",
|
||||||
|
},
|
||||||
|
"skeleton-baz": {
|
||||||
|
"name": "skeleton-baz",
|
||||||
|
"version": "0.1",
|
||||||
|
"type": "target",
|
||||||
|
"virtual": False,
|
||||||
|
"licenses": "Apache-2.0",
|
||||||
|
"dependencies": [],
|
||||||
|
"package_dir": "package/skeleton-baz",
|
||||||
|
},
|
||||||
|
"package-bar": {
|
||||||
|
"name": "bar",
|
||||||
|
"version": "0.2",
|
||||||
|
"type": "target",
|
||||||
|
"virtual": False,
|
||||||
|
"licenses": "MIT",
|
||||||
|
"ignore_cves": ["CVE-2025-0002"],
|
||||||
|
"dependencies": ["package-virtual"],
|
||||||
|
"package_dir": "package/package-bar",
|
||||||
|
},
|
||||||
|
"host-tool": {
|
||||||
|
"name": "host-tool",
|
||||||
|
"version": "0.3",
|
||||||
|
"type": "host",
|
||||||
|
"virtual": False,
|
||||||
|
"licenses": "GPL-3.0-only",
|
||||||
|
"dependencies": [],
|
||||||
|
"package_dir": "package/host-tool",
|
||||||
|
},
|
||||||
|
"package-virtual": {
|
||||||
|
"name": "virtual-provider",
|
||||||
|
"virtual": True,
|
||||||
|
"type": "target",
|
||||||
|
"dependencies": ["package-foo"],
|
||||||
|
"package_dir": "package/package-virtual",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def _run_script(self, extra_args=(), show_info=None):
|
||||||
|
data = show_info if show_info is not None else self._make_show_info()
|
||||||
|
completed = subprocess.run(
|
||||||
|
[self.script, *extra_args],
|
||||||
|
cwd=self.cwd,
|
||||||
|
env=self.env,
|
||||||
|
input=json.dumps(data),
|
||||||
|
text=True,
|
||||||
|
capture_output=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
return json.loads(completed.stdout)
|
||||||
|
|
||||||
|
def _find_component(self, result: dict, name: str) -> dict:
|
||||||
|
for component in result["components"]:
|
||||||
|
if component["bom-ref"] == name:
|
||||||
|
return component
|
||||||
|
self.fail(f"component {name} missing")
|
||||||
|
|
||||||
|
def test_default(self):
|
||||||
|
result = self._run_script()
|
||||||
|
|
||||||
|
self.assertEqual(len(result["components"]), 4)
|
||||||
|
self.assertIn("vulnerabilities", result)
|
||||||
|
vulnerabilities = {v["id"]: v for v in result["vulnerabilities"]}
|
||||||
|
self.assertEqual(len(vulnerabilities), 2)
|
||||||
|
self.assertEqual(vulnerabilities["CVE-2025-0001"]["analysis"]["state"], "resolved_with_pedigree")
|
||||||
|
self.assertEqual(vulnerabilities["CVE-2025-0002"]["analysis"]["state"], "in_triage")
|
||||||
|
|
||||||
|
foo = self._find_component(result, "package-foo")
|
||||||
|
patch = foo["pedigree"]["patches"][0]
|
||||||
|
self.assertIn("text", patch["diff"])
|
||||||
|
self.assertIn("content", patch["diff"]["text"])
|
||||||
|
|
||||||
|
host = self._find_component(result, "host-tool")
|
||||||
|
self.assertEqual(host["properties"][0]["value"], "host")
|
||||||
|
|
||||||
|
names = {c["bom-ref"] for c in result["components"]}
|
||||||
|
self.assertIn("skeleton-baz", names)
|
||||||
|
self.assertIn("package-bar", names)
|
||||||
|
self.assertNotIn("package-virtual", names)
|
||||||
|
|
||||||
|
foo_deps = next(d for d in result["dependencies"] if d["ref"] == "package-foo")
|
||||||
|
self.assertEqual(foo_deps["dependsOn"], ["package-bar", "skeleton-baz"])
|
||||||
|
|
||||||
|
bar_deps = next(d for d in result["dependencies"] if d["ref"] == "package-bar")
|
||||||
|
self.assertEqual(bar_deps["dependsOn"], ["package-foo"])
|
||||||
|
|
||||||
|
def test_virtual(self):
|
||||||
|
result = self._run_script(["--virtual"])
|
||||||
|
|
||||||
|
names = {c["bom-ref"] for c in result["components"]}
|
||||||
|
self.assertEqual(names, {"package-foo", "skeleton-baz", "host-tool", "package-virtual", "package-bar"})
|
||||||
|
|
||||||
|
foo_deps = next(d for d in result["dependencies"] if d["ref"] == "package-foo")
|
||||||
|
self.assertEqual(foo_deps["dependsOn"], ["package-bar", "skeleton-baz"])
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
|
||||||
|
CVE: CVE-2025-0001
|
||||||
|
Upstream: https://patches.example/foo.patch
|
||||||
|
|
||||||
|
Signed-off-by: the contributor
|
||||||
|
|
||||||
|
diff --git a/foo.txt b/foo.txt
|
||||||
|
index 0000001..0000002 100644
|
||||||
|
--- a/foo.txt
|
||||||
|
+++ b/foo.txt
|
||||||
|
@@
|
||||||
|
-foo
|
||||||
|
+bar
|
||||||
Reference in New Issue
Block a user