Skip to content

Commit d9c3ded

Browse files
fix: no warning for missing dependencies if no component exists (#720)
--------- Signed-off-by: weichslgartner <[email protected]>
1 parent 5ec73d0 commit d9c3ded

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

cyclonedx/model/bom.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -694,8 +694,9 @@ def validate(self) -> bool:
694694
'One or more Components have Dependency references to Components/Services that are not known in this '
695695
f'BOM. They are: {dependency_diff}')
696696

697-
# 2. if root component is set: dependencies should exist for the Component this BOM is describing
698-
if self.metadata.component and not any(map(
697+
# 2. if root component is set and there are other components: dependencies should exist for the Component
698+
# this BOM is describing
699+
if self.metadata.component and len(self.components) > 0 and not any(map(
699700
lambda d: d.ref == self.metadata.component.bom_ref and len(d.dependencies) > 0, # type: ignore[union-attr]
700701
self.dependencies
701702
)):

tests/test_model_bom.py

+17-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
#
1515
# SPDX-License-Identifier: Apache-2.0
1616
# Copyright (c) OWASP Foundation. All Rights Reserved.
17-
18-
17+
import warnings
1918
from typing import Callable, Tuple
2019
from unittest import TestCase
2120
from uuid import uuid4
@@ -31,6 +30,7 @@
3130
from cyclonedx.model.license import DisjunctiveLicense
3231
from cyclonedx.model.lifecycle import LifecyclePhase, NamedLifecycle, PredefinedLifecycle
3332
from cyclonedx.model.tool import Tool
33+
from cyclonedx.output.json import JsonV1Dot6
3434
from tests._data.models import (
3535
get_bom_component_licenses_invalid,
3636
get_bom_component_nested_licenses_invalid,
@@ -139,6 +139,21 @@ def test_empty_bom(self) -> None:
139139
self.assertFalse(bom.services)
140140
self.assertFalse(bom.external_references)
141141

142+
def test_root_component_only_bom(self) -> None:
143+
with warnings.catch_warnings(record=True) as w:
144+
warnings.simplefilter('always')
145+
bom = Bom(metadata=BomMetaData(component=Component(name='test', version='1.2')))
146+
_ = JsonV1Dot6(bom).output_as_string()
147+
self.assertEqual(len(w), 0)
148+
149+
def test_warning_missing_dependency(self) -> None:
150+
with self.assertWarns(expected_warning=UserWarning) as w:
151+
bom = Bom(metadata=BomMetaData(component=Component(name='root_component', version='1.2')))
152+
bom.components.add(Component(name='test2', version='4.2'))
153+
_ = JsonV1Dot6(bom).output_as_string()
154+
self.assertEqual(len(w.warnings), 1)
155+
self.assertIn('has no defined dependencies ', str(w.warnings[0]))
156+
142157
def test_empty_bom_defined_serial(self) -> None:
143158
serial_number = uuid4()
144159
bom = Bom(serial_number=serial_number)

0 commit comments

Comments
 (0)