[{"id":3675172,"web_url":"http://patchwork.ozlabs.org/comment/3675172/","msgid":"<20260409083431.24030-1-thomas.perale@mind.be>","list_archive_url":null,"date":"2026-04-09T08:34:31","subject":"Re: [Buildroot] [PATCH v4 1/6] support/testing/utils: add basic\n tests for utils/generate-cyclonedx","submitter":{"id":87308,"url":"http://patchwork.ozlabs.org/api/people/87308/","name":"Thomas Perale","email":"thomas.perale@mind.be"},"content":"Thanks Martin !\n\nAcked-By: Thomas Perale <thomas.perale@mind.be>\n\nIn reply of:\n> Introduce unit-tests for the generate-cyclonedx script, covering basic\n> script invocation, patch CVE extraction and virtual packages.\n> \n> Signed-off-by: Martin Willi <martin@strongswan.org>\n\n> ---\n>  .../tests/utils/test_generate_cyclonedx.py    | 139 ++++++++++++++++++\n>  .../cve_upstream.patch                        |  11 ++\n>  2 files changed, 150 insertions(+)\n>  create mode 100644 support/testing/tests/utils/test_generate_cyclonedx.py\n>  create mode 100644 support/testing/tests/utils/test_generate_cyclonedx/cve_upstream.patch\n> \n> diff --git a/support/testing/tests/utils/test_generate_cyclonedx.py b/support/testing/tests/utils/test_generate_cyclonedx.py\n> new file mode 100644\n> index 000000000000..bfe5eaf054cf\n> --- /dev/null\n> +++ b/support/testing/tests/utils/test_generate_cyclonedx.py\n> @@ -0,0 +1,139 @@\n> +\"\"\"Unit tests for utils/generate-cyclonedx.\"\"\"\n> +\n> +import json\n> +import os\n> +import subprocess\n> +import tempfile\n> +import unittest\n> +from pathlib import Path\n> +\n> +import infra\n> +\n> +PATCH = \"support/testing/tests/utils/test_generate_cyclonedx/cve_upstream.patch\"\n> +SCHEMA_LICENSES = [\"MIT\", \"Apache-2.0\", \"GPL-3.0-only\"]\n> +\n> +\n> +class TestGenerateCycloneDX(unittest.TestCase):\n> +    def setUp(self):\n> +        # Provide a fake SPDX schema so the script never hits the network.\n> +        self.schema_dir = tempfile.TemporaryDirectory()\n> +        self.addCleanup(self.schema_dir.cleanup)\n> +\n> +        cyclonedx_dir = Path(self.schema_dir.name) / \"cyclonedx\"\n> +        cyclonedx_dir.mkdir(parents=True)\n> +        schema_path = cyclonedx_dir / \"spdx-1.6.schema.json\"\n> +        schema_path.write_text(json.dumps({\"enum\": SCHEMA_LICENSES}))\n> +\n> +        self.env = os.environ.copy()\n> +        self.env[\"BR2_DL_DIR\"] = self.schema_dir.name\n> +        self.script = infra.basepath(\"utils/generate-cyclonedx\")\n> +        self.cwd = infra.basepath()\n> +\n> +    def _make_show_info(self) -> dict:\n> +        return {\n> +            \"package-foo\": {\n> +                \"name\": \"foo\",\n> +                \"version\": \"1.2\",\n> +                \"type\": \"target\",\n> +                \"virtual\": False,\n> +                \"licenses\": \"MIT\",\n> +                \"cpe-id\": \"cpe:2.3:a:example:foo:1.2:*:*:*:*:*:*:*\",\n> +                \"patches\": [PATCH],\n> +                \"provides\": [\"package-virtual\"],\n> +                \"dependencies\": [\"skeleton-baz\", \"package-bar\"],\n> +                \"ignore_cves\": [\"CVE-2025-0001\"],\n> +                \"package_dir\": \"package/package-foo\",\n> +            },\n> +            \"skeleton-baz\": {\n> +                \"name\": \"skeleton-baz\",\n> +                \"version\": \"0.1\",\n> +                \"type\": \"target\",\n> +                \"virtual\": False,\n> +                \"licenses\": \"Apache-2.0\",\n> +                \"dependencies\": [],\n> +                \"package_dir\": \"package/skeleton-baz\",\n> +            },\n> +            \"package-bar\": {\n> +                \"name\": \"bar\",\n> +                \"version\": \"0.2\",\n> +                \"type\": \"target\",\n> +                \"virtual\": False,\n> +                \"licenses\": \"MIT\",\n> +                \"ignore_cves\": [\"CVE-2025-0002\"],\n> +                \"dependencies\": [\"package-virtual\"],\n> +                \"package_dir\": \"package/package-bar\",\n> +            },\n> +            \"host-tool\": {\n> +                \"name\": \"host-tool\",\n> +                \"version\": \"0.3\",\n> +                \"type\": \"host\",\n> +                \"virtual\": False,\n> +                \"licenses\": \"GPL-3.0-only\",\n> +                \"dependencies\": [],\n> +                \"package_dir\": \"package/host-tool\",\n> +            },\n> +            \"package-virtual\": {\n> +                \"name\": \"virtual-provider\",\n> +                \"virtual\": True,\n> +                \"type\": \"target\",\n> +                \"dependencies\": [\"package-foo\"],\n> +                \"package_dir\": \"package/package-virtual\",\n> +            },\n> +        }\n> +\n> +    def _run_script(self, extra_args=(), show_info=None):\n> +        data = show_info if show_info is not None else self._make_show_info()\n> +        completed = subprocess.run(\n> +            [self.script, *extra_args],\n> +            cwd=self.cwd,\n> +            env=self.env,\n> +            input=json.dumps(data),\n> +            text=True,\n> +            capture_output=True,\n> +            check=True,\n> +        )\n> +        return json.loads(completed.stdout)\n> +\n> +    def _find_component(self, result: dict, name: str) -> dict:\n> +        for component in result[\"components\"]:\n> +            if component[\"bom-ref\"] == name:\n> +                return component\n> +        self.fail(f\"component {name} missing\")\n> +\n> +    def test_default(self):\n> +        result = self._run_script()\n> +\n> +        self.assertEqual(len(result[\"components\"]), 4)\n> +        self.assertIn(\"vulnerabilities\", result)\n> +        vulnerabilities = {v[\"id\"]: v for v in result[\"vulnerabilities\"]}\n> +        self.assertEqual(len(vulnerabilities), 2)\n> +        self.assertEqual(vulnerabilities[\"CVE-2025-0001\"][\"analysis\"][\"state\"], \"resolved_with_pedigree\")\n> +        self.assertEqual(vulnerabilities[\"CVE-2025-0002\"][\"analysis\"][\"state\"], \"in_triage\")\n> +\n> +        foo = self._find_component(result, \"package-foo\")\n> +        patch = foo[\"pedigree\"][\"patches\"][0]\n> +        self.assertIn(\"text\", patch[\"diff\"])\n> +        self.assertIn(\"content\", patch[\"diff\"][\"text\"])\n> +\n> +        host = self._find_component(result, \"host-tool\")\n> +        self.assertEqual(host[\"properties\"][0][\"value\"], \"host\")\n> +\n> +        names = {c[\"bom-ref\"] for c in result[\"components\"]}\n> +        self.assertIn(\"skeleton-baz\", names)\n> +        self.assertIn(\"package-bar\", names)\n> +        self.assertNotIn(\"package-virtual\", names)\n> +\n> +        foo_deps = next(d for d in result[\"dependencies\"] if d[\"ref\"] == \"package-foo\")\n> +        self.assertEqual(foo_deps[\"dependsOn\"], [\"package-bar\", \"skeleton-baz\"])\n> +\n> +        bar_deps = next(d for d in result[\"dependencies\"] if d[\"ref\"] == \"package-bar\")\n> +        self.assertEqual(bar_deps[\"dependsOn\"], [\"package-foo\"])\n> +\n> +    def test_virtual(self):\n> +        result = self._run_script([\"--virtual\"])\n> +\n> +        names = {c[\"bom-ref\"] for c in result[\"components\"]}\n> +        self.assertEqual(names, {\"package-foo\", \"skeleton-baz\", \"host-tool\", \"package-virtual\", \"package-bar\"})\n> +\n> +        foo_deps = next(d for d in result[\"dependencies\"] if d[\"ref\"] == \"package-foo\")\n> +        self.assertEqual(foo_deps[\"dependsOn\"], [\"package-bar\", \"skeleton-baz\"])\n> diff --git a/support/testing/tests/utils/test_generate_cyclonedx/cve_upstream.patch b/support/testing/tests/utils/test_generate_cyclonedx/cve_upstream.patch\n> new file mode 100644\n> index 000000000000..f18e51ebb9ec\n> --- /dev/null\n> +++ b/support/testing/tests/utils/test_generate_cyclonedx/cve_upstream.patch\n> @@ -0,0 +1,11 @@\n> +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001\n> +CVE: CVE-2025-0001\n> +Upstream: https://patches.example/foo.patch\n> +\n> +diff --git a/foo.txt b/foo.txt\n> +index 0000001..0000002 100644\n> +--- a/foo.txt\n> ++++ b/foo.txt\n> +@@\n> +-foo\n> ++bar\n> -- \n> 2.43.0\n> \n> _______________________________________________\n> buildroot mailing list\n> buildroot@buildroot.org\n> https://lists.buildroot.org/mailman/listinfo/buildroot","headers":{"Return-Path":"<buildroot-bounces@buildroot.org>","X-Original-To":["incoming-buildroot@patchwork.ozlabs.org","buildroot@buildroot.org"],"Delivered-To":["patchwork-incoming-buildroot@legolas.ozlabs.org","buildroot@buildroot.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=buildroot.org header.i=@buildroot.org\n header.a=rsa-sha256 header.s=default header.b=ePZPDUo9;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=buildroot.org\n (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org;\n envelope-from=buildroot-bounces@buildroot.org; receiver=patchwork.ozlabs.org)"],"Received":["from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4frtXM5HPGz1xtJ\n\tfor <incoming-buildroot@patchwork.ozlabs.org>;\n Thu, 09 Apr 2026 18:34:42 +1000 (AEST)","from localhost (localhost [127.0.0.1])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id 9220040E7C;\n\tThu,  9 Apr 2026 08:34:39 +0000 (UTC)","from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id Ie1ZUKQAtJeW; Thu,  9 Apr 2026 08:34:38 +0000 (UTC)","from lists1.osuosl.org (lists1.osuosl.org [140.211.166.142])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id 7FFF940F1A;\n\tThu,  9 Apr 2026 08:34:38 +0000 (UTC)","from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136])\n by lists1.osuosl.org (Postfix) with ESMTP id 9C5B51F6\n for <buildroot@buildroot.org>; Thu,  9 Apr 2026 08:34:37 +0000 (UTC)","from localhost (localhost [127.0.0.1])\n by smtp3.osuosl.org (Postfix) with ESMTP id 8DC00607E8\n for <buildroot@buildroot.org>; Thu,  9 Apr 2026 08:34:37 +0000 (UTC)","from smtp3.osuosl.org ([127.0.0.1])\n by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id TFtyEdFWA5sn for <buildroot@buildroot.org>;\n Thu,  9 Apr 2026 08:34:36 +0000 (UTC)","from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com\n [IPv6:2a00:1450:4864:20::32d])\n by smtp3.osuosl.org (Postfix) with ESMTPS id 8BA2560796\n for <buildroot@buildroot.org>; Thu,  9 Apr 2026 08:34:34 +0000 (UTC)","by mail-wm1-x32d.google.com with SMTP id\n 5b1f17b1804b1-488ba6366a7so7189505e9.0\n for <buildroot@buildroot.org>; Thu, 09 Apr 2026 01:34:34 -0700 (PDT)","from arch ([79.132.232.220]) by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-488cd1999c6sm28552345e9.4.2026.04.09.01.34.32\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Thu, 09 Apr 2026 01:34:32 -0700 (PDT)"],"X-Virus-Scanned":["amavis at osuosl.org","amavis at osuosl.org"],"X-Comment":"SPF check N/A for local connections - client-ip=140.211.166.142;\n helo=lists1.osuosl.org; envelope-from=buildroot-bounces@buildroot.org;\n receiver=<UNKNOWN> ","DKIM-Filter":["OpenDKIM Filter v2.11.0 smtp4.osuosl.org 7FFF940F1A","OpenDKIM Filter v2.11.0 smtp3.osuosl.org 8BA2560796"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=buildroot.org;\n\ts=default; t=1775723678;\n\tbh=WnVBmHfWC9FQtkBTeGHhCRKC3MrXL14ycU2Z5FGzbeE=;\n\th=To:Cc:Date:In-Reply-To:References:Subject:List-Id:\n\t List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe:\n\t From:Reply-To:From;\n\tb=ePZPDUo9X4SH7dHddDMYtgOioV2IpLH0SQmA7XwCrWnixNHnGhpPQI4YXCbqMSyhN\n\t bNGsNUHcMOLayWOawjgek5RYR3Bn1/hifi2aORclHjnfOcNc5ostV12iQJt57pfoqD\n\t ck1rA1Fk8tk/sLJt5Mp3BBfnrYuAQFJasU9/0Kh1/yQR0tYVoi+lgnByggRVKB2XM2\n\t zT6J/vDkRfq8CATPI1UUSkFnM5TM1Uvy1W8aJLEp+IiPAxWL1TABUXy+iCHMlkeuKz\n\t 1goarB5b8x1PYW50j0OUkGP0ZuPPcVF0mEs6IifN5XipUrmay1IXglyqgBdCZ070tT\n\t tg1A6d+YZgKSQ==","Received-SPF":"Pass (mailfrom) identity=mailfrom;\n client-ip=2a00:1450:4864:20::32d; helo=mail-wm1-x32d.google.com;\n envelope-from=thomas.perale@essensium.com; receiver=<UNKNOWN>","DMARC-Filter":"OpenDMARC Filter v1.4.2 smtp3.osuosl.org 8BA2560796","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775723673; x=1776328473;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=B6JYLJtuHU5rDfQJ0NRXWMpBl/BN8+ZA2IVgL2geCc0=;\n b=sRQXJ7CEk+h9/lD/m53AkFDfCex2wRQHdKcbOweJTL5X0HrO2iNqbaPJcnBuHgyBIX\n r/cDtSFAODsYU0KdvV+6QD1KoNEi6yYt34HaMFt0tonOde0N1zvt8tEb7JxDI785/41h\n uY3h/yMNS1ERjUhsxIymKvxdmHqZ0gCg1/U1QsC2XcM16lTR0MzIKvyCwUykKVErfhfT\n gfgo5InH/OnGCWYSUAP/XGJaq4CoW+OZ2yHe7YWkjRN5nD5Tdc+8AOdJUqCs5MGG+Z4m\n vVS7xYTYZZ3VKlVRjq4/cjtbhsYXOos7W29rx4WQG5m4cIfmf7KuLEXFAIGuHtdxeW8p\n +/fQ==","X-Forwarded-Encrypted":"i=1;\n AJvYcCW1MwI2ci/iO3MNB7sRAz2BFJ3SSttSnvi5610UG7xKiKcj4IzoSCqAmuitNgFDvCzRjY7549KmsBE=@buildroot.org","X-Gm-Message-State":"AOJu0YzGSjxyRWeVBEwJM8mWaKx8BBHhSSXruVQxE0SPCPkh5rYaE5Os\n 4f8/3vzsIK0cfr7zSvQUsK+1Nhp9u4Yz3s/LExfLIbAvVWTAbaOS1rha0TnRLefh/7c=","X-Gm-Gg":"AeBDiesdNE2E/dT5vLxY8yHEixu4lqUeQxdztW8hI0UxpwTe+JX9sp9CRiUuKcsRQGv\n lXOIGLJVG7nBgCpUAlddYci3d3QSRO8qC7MEvAao5+03OlvLgvubFngoM8WGOa28cGyTIUNIe2u\n 0AOvXwhH9pHpMjN3F9+8qzV9l+xMzdM4qiab5h48fmwK4C1JeQjn/Uy2aCEVazcWKQzgpK0Swyi\n u8mfEaXihrPHroAxvc5++2w9rCu/HQ+Yl3fvqNTueF2j+aTqHfVk0zUHb0zyESf/0ayTbxnjhYz\n huNJF2zB4qjRYCYyxlpwz0pVHG6s/hFSS/BT9KtiI6QJmBpmVZlV8mWT5zWNsub0acJ2c8/0Rnv\n nniWF946qzlTIDGzgwxqTR5+0yDVQSaLlxOYJda8oRrDuoOWfceZ/fjNcdLK6MneNPV1FtSD0wW\n tL+Jvq8bu1MA1GKDwE","X-Received":"by 2002:a05:600c:5292:b0:488:8c89:cfaa with SMTP id\n 5b1f17b1804b1-488996b021fmr372601665e9.3.1775723672678;\n Thu, 09 Apr 2026 01:34:32 -0700 (PDT)","To":"Martin Willi <martin@strongswan.org>","Cc":"Thomas Perale <thomas.perale@mind.be>,\n\tbuildroot@buildroot.org","Date":"Thu,  9 Apr 2026 10:34:31 +0200","Message-ID":"<20260409083431.24030-1-thomas.perale@mind.be>","X-Mailer":"git-send-email 2.53.0","In-Reply-To":"<20260409081401.2060709-2-martin@strongswan.org>","References":"<20260409081401.2060709-2-martin@strongswan.org>","MIME-Version":"1.0","X-Mailman-Original-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=mind.be; s=google; t=1775723673; x=1776328473; darn=buildroot.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=B6JYLJtuHU5rDfQJ0NRXWMpBl/BN8+ZA2IVgL2geCc0=;\n b=a+bF9b3b9AGq2ot0Y/CmCW9Hn97JDCu6yp7STnxqwVjZ3P0sJhB66EZ81Nae8/+0G9\n CWpMrqjD5mkI8VVag1DrgCwv8odrQxO3l4Fb7GtdYbcAaUSZzVSNyKjH4Ntlrg4Ja4Dx\n Urn6W1M+vOhrQGbzTPPwAxy/7MTC2TRcQFCcjJw01U1b9Z59xGO2Vx4Ykaa7R6IRSCte\n HWqlDNe5VcWpMf4Df+KRnoNIfjanESwJSwsoF//zlPYhPdTaASpgtcSvFwf5/ysm/Nkn\n k+3/T0F30ZvqwC1L2ZOHil3uCNWFHaqX93Y4f0AjeJxBKm+K9hJQ3bE1MIy9p1Ek/0W0\n f+Pw==","X-Mailman-Original-Authentication-Results":["smtp3.osuosl.org;\n dmarc=pass (p=quarantine dis=none)\n header.from=mind.be","smtp3.osuosl.org;\n dkim=pass (2048-bit key,\n unprotected) header.d=mind.be header.i=@mind.be header.a=rsa-sha256\n header.s=google header.b=a+bF9b3b"],"Subject":"Re: [Buildroot] [PATCH v4 1/6] support/testing/utils: add basic\n tests for utils/generate-cyclonedx","X-BeenThere":"buildroot@buildroot.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Discussion and development of buildroot <buildroot.buildroot.org>","List-Unsubscribe":"<https://lists.buildroot.org/mailman/options/buildroot>,\n <mailto:buildroot-request@buildroot.org?subject=unsubscribe>","List-Archive":"<http://lists.buildroot.org/pipermail/buildroot/>","List-Post":"<mailto:buildroot@buildroot.org>","List-Help":"<mailto:buildroot-request@buildroot.org?subject=help>","List-Subscribe":"<https://lists.buildroot.org/mailman/listinfo/buildroot>,\n <mailto:buildroot-request@buildroot.org?subject=subscribe>","From":"Thomas Perale via buildroot <buildroot@buildroot.org>","Reply-To":"Thomas Perale <thomas.perale@mind.be>","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"buildroot-bounces@buildroot.org","Sender":"\"buildroot\" <buildroot-bounces@buildroot.org>"}}]