From: Thomas Perale via buildroot <buildroot@buildroot.org>
To: Martin Willi <martin@strongswan.org>
Cc: Thomas Perale <thomas.perale@mind.be>, buildroot@buildroot.org
Subject: Re: [Buildroot] [PATCH v4 1/6] support/testing/utils: add basic tests for utils/generate-cyclonedx
Date: Thu, 9 Apr 2026 10:34:31 +0200 [thread overview]
Message-ID: <20260409083431.24030-1-thomas.perale@mind.be> (raw)
In-Reply-To: <20260409081401.2060709-2-martin@strongswan.org>
Thanks Martin !
Acked-By: Thomas Perale <thomas.perale@mind.be>
In reply of:
> 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>
> ---
> .../tests/utils/test_generate_cyclonedx.py | 139 ++++++++++++++++++
> .../cve_upstream.patch | 11 ++
> 2 files changed, 150 insertions(+)
> create mode 100644 support/testing/tests/utils/test_generate_cyclonedx.py
> create mode 100644 support/testing/tests/utils/test_generate_cyclonedx/cve_upstream.patch
>
> diff --git a/support/testing/tests/utils/test_generate_cyclonedx.py b/support/testing/tests/utils/test_generate_cyclonedx.py
> new file mode 100644
> index 000000000000..bfe5eaf054cf
> --- /dev/null
> +++ b/support/testing/tests/utils/test_generate_cyclonedx.py
> @@ -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/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"])
> diff --git a/support/testing/tests/utils/test_generate_cyclonedx/cve_upstream.patch b/support/testing/tests/utils/test_generate_cyclonedx/cve_upstream.patch
> new file mode 100644
> index 000000000000..f18e51ebb9ec
> --- /dev/null
> +++ b/support/testing/tests/utils/test_generate_cyclonedx/cve_upstream.patch
> @@ -0,0 +1,11 @@
> +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
> +CVE: CVE-2025-0001
> +Upstream: https://patches.example/foo.patch
> +
> +diff --git a/foo.txt b/foo.txt
> +index 0000001..0000002 100644
> +--- a/foo.txt
> ++++ b/foo.txt
> +@@
> +-foo
> ++bar
> --
> 2.43.0
>
> _______________________________________________
> buildroot mailing list
> buildroot@buildroot.org
> https://lists.buildroot.org/mailman/listinfo/buildroot
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot
next prev parent reply other threads:[~2026-04-09 8:34 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-09 8:13 [Buildroot] [PATCH v4 0/6] Extend CycloneDX metadata Martin Willi
2026-04-09 8:13 ` [Buildroot] [PATCH v4 1/6] support/testing/utils: add basic tests for utils/generate-cyclonedx Martin Willi
2026-04-09 8:34 ` Thomas Perale via buildroot [this message]
2026-04-09 8:13 ` [Buildroot] [PATCH v4 2/6] utils/generate-cyclonedx: remove indirect dependencies from root component Martin Willi
2026-04-09 8:13 ` [Buildroot] [PATCH v4 3/6] utils/generate-cyclonedx: generate externalReferences with source-distribution Martin Willi
2026-04-09 8:43 ` Thomas Perale via buildroot
2026-04-09 8:13 ` [Buildroot] [PATCH v4 4/6] package/pkg-utils: add 'hashes' to show-info Martin Willi
2026-04-09 8:14 ` [Buildroot] [PATCH v4 5/6] utils/generate-cyclonedx: add hashes from .hash files to externalReferences Martin Willi
2026-04-09 8:14 ` [Buildroot] [PATCH v4 6/6] utils/generate-cyclonedx: generate vcs externalReferences for source repos Martin Willi
2026-04-09 8:49 ` Thomas Perale via buildroot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260409083431.24030-1-thomas.perale@mind.be \
--to=buildroot@buildroot.org \
--cc=martin@strongswan.org \
--cc=thomas.perale@mind.be \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox