public inbox for buildroot@busybox.net
 help / color / mirror / Atom feed
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

  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