From be95494066b876abf0e2900da33a5c0ea0300905 Mon Sep 17 00:00:00 2001 From: weichslgartner Date: Tue, 22 Oct 2024 22:19:27 +0200 Subject: [PATCH] fix dependency warning for root component only #617 Signed-off-by: weichslgartner --- cyclonedx/model/bom.py | 5 +++-- tests/test_model_bom.py | 13 +++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/cyclonedx/model/bom.py b/cyclonedx/model/bom.py index a36a5e10..ca04e781 100644 --- a/cyclonedx/model/bom.py +++ b/cyclonedx/model/bom.py @@ -667,8 +667,9 @@ def validate(self) -> bool: 'One or more Components have Dependency references to Components/Services that are not known in this ' f'BOM. They are: {dependency_diff}') - # 2. if root component is set: dependencies should exist for the Component this BOM is describing - if self.metadata.component and not any(map( + # 2. if root component is set and there are other components: dependencies should exist for the Component + # this BOM is describing + if self.metadata.component and len(self.components) > 0 and not any(map( lambda d: d.ref == self.metadata.component.bom_ref and len(d.dependencies) > 0, # type: ignore[union-attr] self.dependencies )): diff --git a/tests/test_model_bom.py b/tests/test_model_bom.py index 925846c7..d17af63a 100644 --- a/tests/test_model_bom.py +++ b/tests/test_model_bom.py @@ -14,8 +14,7 @@ # # SPDX-License-Identifier: Apache-2.0 # Copyright (c) OWASP Foundation. All Rights Reserved. - - +import warnings from typing import Callable, Tuple from unittest import TestCase from uuid import uuid4 @@ -29,6 +28,7 @@ from cyclonedx.model.component import Component, ComponentType from cyclonedx.model.contact import OrganizationalContact, OrganizationalEntity from cyclonedx.model.license import DisjunctiveLicense +from cyclonedx.output.json import JsonV1Dot6 from tests._data.models import ( get_bom_component_licenses_invalid, get_bom_component_nested_licenses_invalid, @@ -133,6 +133,15 @@ def test_empty_bom(self) -> None: self.assertFalse(bom.services) self.assertFalse(bom.external_references) + def test_root_component_only_bom(self) -> None: + with warnings.catch_warnings(): + warnings.simplefilter('error', UserWarning) # Turn UserWarnings into errors + try: + bom = Bom(metadata=BomMetaData(component=Component(name='test', version='1.2'))) + _ = JsonV1Dot6(bom).output_as_string() + except UserWarning as e: + self.fail(f"A warning with 'warn' was issued: {e}") + def test_empty_bom_defined_serial(self) -> None: serial_number = uuid4() bom = Bom(serial_number=serial_number)