diff --git a/cyclonedx/model/component.py b/cyclonedx/model/component.py index 89ea379c..74c4ecca 100644 --- a/cyclonedx/model/component.py +++ b/cyclonedx/model/component.py @@ -1774,6 +1774,7 @@ def get_pypi_url(self) -> str: def __comparable_tuple(self) -> _ComparableTuple: return _ComparableTuple(( self.type, self.group, self.name, self.version, + self.bom_ref.value, None if self.purl is None else _ComparablePackageURL(self.purl), self.swid, self.cpe, _ComparableTuple(self.swhids), self.supplier, self.author, self.publisher, diff --git a/cyclonedx/model/contact.py b/cyclonedx/model/contact.py index 2385528d..3266bd92 100644 --- a/cyclonedx/model/contact.py +++ b/cyclonedx/model/contact.py @@ -163,10 +163,10 @@ def street_address(self, street_address: Optional[str]) -> None: def __comparable_tuple(self) -> _ComparableTuple: return _ComparableTuple(( - self.bom_ref, self.country, self.region, self.locality, self.postal_code, self.post_office_box_number, - self.street_address + self.street_address, + None if self.bom_ref is None else self.bom_ref.value, )) def __eq__(self, other: object) -> bool: diff --git a/cyclonedx/model/definition.py b/cyclonedx/model/definition.py index d10072fa..675e5476 100644 --- a/cyclonedx/model/definition.py +++ b/cyclonedx/model/definition.py @@ -256,7 +256,7 @@ def external_references(self, external_references: Iterable[ExternalReference]) def __comparable_tuple(self) -> _ComparableTuple: # all properties are optional - so need to compare all, in hope that one is unique return _ComparableTuple(( - self.bom_ref, self.identifier, + self.identifier, self.bom_ref.value, self.title, self.text, _ComparableTuple(self.descriptions), _ComparableTuple(self.open_cre), self.parent, _ComparableTuple(self.properties), @@ -373,7 +373,9 @@ def requirements(self, requirements: Iterable[Union[str, BomRef]]) -> None: def __comparable_tuple(self) -> _ComparableTuple: # all properties are optional - so need to compare all, in hope that one is unique return _ComparableTuple(( - self.bom_ref, self.identifier, self.title, self.description, _ComparableTuple(self.requirements) + self.identifier, self.bom_ref.value, + self.title, self.description, + _ComparableTuple(self.requirements) )) def __lt__(self, other: Any) -> bool: @@ -545,8 +547,9 @@ def external_references(self, external_references: Iterable[ExternalReference]) def __comparable_tuple(self) -> _ComparableTuple: # all properties are optional - so need to apply all, in hope that one is unique return _ComparableTuple(( - self.bom_ref, - self.name, self.version, self.description, self.owner, + self.name, self.version, + self.bom_ref.value, + self.description, self.owner, _ComparableTuple(self.requirements), _ComparableTuple(self.levels), _ComparableTuple(self.external_references) )) diff --git a/cyclonedx/model/service.py b/cyclonedx/model/service.py index 640f1765..91541f6b 100644 --- a/cyclonedx/model/service.py +++ b/cyclonedx/model/service.py @@ -355,6 +355,7 @@ def release_notes(self, release_notes: Optional[ReleaseNotes]) -> None: def __comparable_tuple(self) -> _ComparableTuple: return _ComparableTuple(( self.group, self.name, self.version, + self.bom_ref.value, self.provider, self.description, self.authenticated, _ComparableTuple(self.data), _ComparableTuple(self.endpoints), _ComparableTuple(self.external_references), _ComparableTuple(self.licenses), diff --git a/cyclonedx/model/vulnerability.py b/cyclonedx/model/vulnerability.py index bec10c7e..fc6d1ce1 100644 --- a/cyclonedx/model/vulnerability.py +++ b/cyclonedx/model/vulnerability.py @@ -1334,7 +1334,7 @@ def properties(self, properties: Iterable[Property]) -> None: def __comparable_tuple(self) -> _ComparableTuple: return _ComparableTuple(( - self.id, + self.id, self.bom_ref.value, self.source, _ComparableTuple(self.references), _ComparableTuple(self.ratings), _ComparableTuple(self.cwes), self.description, self.detail, self.recommendation, self.workaround, _ComparableTuple(self.advisories), diff --git a/tests/_data/models.py b/tests/_data/models.py index 6bba3499..1b083a4d 100644 --- a/tests/_data/models.py +++ b/tests/_data/models.py @@ -1401,6 +1401,37 @@ def get_bom_with_definitions_and_detailed_standards() -> Bom: ])) +def get_bom_for_issue540_duplicate_components() -> Bom: + # tests https://github.com/CycloneDX/cyclonedx-python-lib/issues/540 + bom = _make_bom() + bom.metadata.component = root_component = Component( + name='myApp', + type=ComponentType.APPLICATION, + bom_ref='myApp' + ) + component1 = Component( + type=ComponentType.LIBRARY, + name='some-component', + bom_ref='some-component' + ) + bom.components.add(component1) + bom.register_dependency(root_component, [component1]) + component2 = Component( + type=ComponentType.LIBRARY, + name='some-library', + bom_ref='some-library1' + ) + bom.components.add(component2) + bom.register_dependency(component1, [component2]) + component3 = Component( + type=ComponentType.LIBRARY, + name='some-library', + bom_ref='some-library2' + ) + bom.components.add(component3) + bom.register_dependency(component1, [component3]) + return bom + # --- diff --git a/tests/_data/own/json/1.5/issue677.json b/tests/_data/own/json/1.5/issue677.json new file mode 100644 index 00000000..090d97f8 --- /dev/null +++ b/tests/_data/own/json/1.5/issue677.json @@ -0,0 +1,49 @@ +{ + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "serialNumber": "urn:uuid:66fa5692-2e9d-45c5-830a-ec8ccaf7dcc9", + "version": 1, + "metadata": { + "component": { + "description": "see issue #677 - https://github.com/CycloneDX/cyclonedx-python-lib/issues/677", + "type": "application", + "name": "test" + } + }, + "components": [ + { + "type": "operating-system", + "bom-ref": "test12", + "name": "alpine" + }, + { + "type": "container", + "bom-ref": "test11", + "name": "alpine" + }, + { + "type": "operating-system", + "bom-ref": "test22", + "name": "alpine" + }, + { + "type": "container", + "bom-ref": "test21", + "name": "alpine" + } + ], + "dependencies": [ + { + "ref": "test11", + "dependsOn": [ + "test12" + ] + }, + { + "ref": "test21", + "dependsOn": [ + "test22" + ] + } + ] +} diff --git a/tests/_data/own/json/1.5/issue753.json b/tests/_data/own/json/1.5/issue753.json new file mode 100644 index 00000000..15123220 --- /dev/null +++ b/tests/_data/own/json/1.5/issue753.json @@ -0,0 +1,37 @@ +{ + "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "version": 1, + "metadata": { + "component": { + "type": "application", + "name": "example", + "version": "1.2.3", + "bom-ref": "topref" + } + }, + "components": [ + { + "type": "library", + "name": "styled-engine", + "version": "5.16.6", + "bom-ref": "@mui/styled-engine@npm:5.16.6 [296f2]" + }, + { + "type": "library", + "name": "styled-engine", + "version": "5.16.6", + "bom-ref": "@mui/styled-engine@npm:5.16.6 [3135b]" + } + ], + "dependencies": [ + { + "ref": "topref", + "dependsOn": [ + "@mui/styled-engine@npm:5.16.6 [296f2]", + "@mui/styled-engine@npm:5.16.6 [3135b]" + ] + } + ] +} diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.0.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.0.xml.bin new file mode 100644 index 00000000..dd1947eb --- /dev/null +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.0.xml.bin @@ -0,0 +1,20 @@ + + + + + some-component + + false + + + some-library + + false + + + some-library + + false + + + diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.1.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.1.xml.bin new file mode 100644 index 00000000..6d4d9bdb --- /dev/null +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.1.xml.bin @@ -0,0 +1,17 @@ + + + + + some-component + + + + some-library + + + + some-library + + + + diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.json.bin new file mode 100644 index 00000000..fd8f32b5 --- /dev/null +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.json.bin @@ -0,0 +1,57 @@ +{ + "components": [ + { + "bom-ref": "some-component", + "name": "some-component", + "type": "library", + "version": "" + }, + { + "bom-ref": "some-library1", + "name": "some-library", + "type": "library", + "version": "" + }, + { + "bom-ref": "some-library2", + "name": "some-library", + "type": "library", + "version": "" + } + ], + "dependencies": [ + { + "dependsOn": [ + "some-component" + ], + "ref": "myApp" + }, + { + "dependsOn": [ + "some-library1", + "some-library2" + ], + "ref": "some-component" + }, + { + "ref": "some-library1" + }, + { + "ref": "some-library2" + } + ], + "metadata": { + "component": { + "bom-ref": "myApp", + "name": "myApp", + "type": "application", + "version": "" + }, + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.2" +} \ No newline at end of file diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.xml.bin new file mode 100644 index 00000000..625bc1dc --- /dev/null +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.xml.bin @@ -0,0 +1,35 @@ + + + + 2023-01-07T13:44:32.312678+00:00 + + myApp + + + + + + some-component + + + + some-library + + + + some-library + + + + + + + + + + + + + + + diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.json.bin new file mode 100644 index 00000000..601c5974 --- /dev/null +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.json.bin @@ -0,0 +1,57 @@ +{ + "components": [ + { + "bom-ref": "some-component", + "name": "some-component", + "type": "library", + "version": "" + }, + { + "bom-ref": "some-library1", + "name": "some-library", + "type": "library", + "version": "" + }, + { + "bom-ref": "some-library2", + "name": "some-library", + "type": "library", + "version": "" + } + ], + "dependencies": [ + { + "dependsOn": [ + "some-component" + ], + "ref": "myApp" + }, + { + "dependsOn": [ + "some-library1", + "some-library2" + ], + "ref": "some-component" + }, + { + "ref": "some-library1" + }, + { + "ref": "some-library2" + } + ], + "metadata": { + "component": { + "bom-ref": "myApp", + "name": "myApp", + "type": "application", + "version": "" + }, + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.3" +} \ No newline at end of file diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.xml.bin new file mode 100644 index 00000000..9ca84692 --- /dev/null +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.xml.bin @@ -0,0 +1,35 @@ + + + + 2023-01-07T13:44:32.312678+00:00 + + myApp + + + + + + some-component + + + + some-library + + + + some-library + + + + + + + + + + + + + + + diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.json.bin new file mode 100644 index 00000000..1da35538 --- /dev/null +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.json.bin @@ -0,0 +1,53 @@ +{ + "components": [ + { + "bom-ref": "some-component", + "name": "some-component", + "type": "library" + }, + { + "bom-ref": "some-library1", + "name": "some-library", + "type": "library" + }, + { + "bom-ref": "some-library2", + "name": "some-library", + "type": "library" + } + ], + "dependencies": [ + { + "dependsOn": [ + "some-component" + ], + "ref": "myApp" + }, + { + "dependsOn": [ + "some-library1", + "some-library2" + ], + "ref": "some-component" + }, + { + "ref": "some-library1" + }, + { + "ref": "some-library2" + } + ], + "metadata": { + "component": { + "bom-ref": "myApp", + "name": "myApp", + "type": "application" + }, + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.4" +} \ No newline at end of file diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.xml.bin new file mode 100644 index 00000000..22db0779 --- /dev/null +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.xml.bin @@ -0,0 +1,31 @@ + + + + 2023-01-07T13:44:32.312678+00:00 + + myApp + + + + + some-component + + + some-library + + + some-library + + + + + + + + + + + + + + diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.json.bin new file mode 100644 index 00000000..64c0371b --- /dev/null +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.json.bin @@ -0,0 +1,63 @@ +{ + "components": [ + { + "bom-ref": "some-component", + "name": "some-component", + "type": "library" + }, + { + "bom-ref": "some-library1", + "name": "some-library", + "type": "library" + }, + { + "bom-ref": "some-library2", + "name": "some-library", + "type": "library" + } + ], + "dependencies": [ + { + "dependsOn": [ + "some-component" + ], + "ref": "myApp" + }, + { + "dependsOn": [ + "some-library1", + "some-library2" + ], + "ref": "some-component" + }, + { + "ref": "some-library1" + }, + { + "ref": "some-library2" + } + ], + "metadata": { + "component": { + "bom-ref": "myApp", + "name": "myApp", + "type": "application" + }, + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" + } + ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.5" +} \ No newline at end of file diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.xml.bin new file mode 100644 index 00000000..9146c15a --- /dev/null +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.xml.bin @@ -0,0 +1,35 @@ + + + + 2023-01-07T13:44:32.312678+00:00 + + myApp + + + + + some-component + + + some-library + + + some-library + + + + + + + + + + + + + + + val1 + val2 + + diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.json.bin new file mode 100644 index 00000000..0ce6b2c9 --- /dev/null +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.json.bin @@ -0,0 +1,63 @@ +{ + "components": [ + { + "bom-ref": "some-component", + "name": "some-component", + "type": "library" + }, + { + "bom-ref": "some-library1", + "name": "some-library", + "type": "library" + }, + { + "bom-ref": "some-library2", + "name": "some-library", + "type": "library" + } + ], + "dependencies": [ + { + "dependsOn": [ + "some-component" + ], + "ref": "myApp" + }, + { + "dependsOn": [ + "some-library1", + "some-library2" + ], + "ref": "some-component" + }, + { + "ref": "some-library1" + }, + { + "ref": "some-library2" + } + ], + "metadata": { + "component": { + "bom-ref": "myApp", + "name": "myApp", + "type": "application" + }, + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" + } + ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.6" +} \ No newline at end of file diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.xml.bin new file mode 100644 index 00000000..c64cf536 --- /dev/null +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.xml.bin @@ -0,0 +1,35 @@ + + + + 2023-01-07T13:44:32.312678+00:00 + + myApp + + + + + some-component + + + some-library + + + some-library + + + + + + + + + + + + + + + val1 + val2 + + diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.0.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.0.xml.bin index e70bbd27..5262d1d2 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.0.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.0.xml.bin @@ -4,13 +4,13 @@ dummy 2.3.5 - pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 + pkg:pypi/pathlib2@2.3.5 false dummy 2.3.5 - pkg:pypi/pathlib2@2.3.5 + pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 false diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.1.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.1.xml.bin index baf7bca9..7e9f29bb 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.1.xml.bin @@ -1,15 +1,15 @@ - + dummy 2.3.5 - pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 + pkg:pypi/pathlib2@2.3.5 - + dummy 2.3.5 - pkg:pypi/pathlib2@2.3.5 + pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.json.bin index 651e8e36..cba8ccc0 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.json.bin @@ -1,16 +1,16 @@ { "components": [ { - "bom-ref": "dummy-b", + "bom-ref": "dummy-a", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", + "purl": "pkg:pypi/pathlib2@2.3.5", "type": "library", "version": "2.3.5" }, { - "bom-ref": "dummy-a", + "bom-ref": "dummy-b", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", "type": "library", "version": "2.3.5" } diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.xml.bin index cf695a4d..8e52087f 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.xml.bin @@ -4,15 +4,15 @@ 2023-01-07T13:44:32.312678+00:00 - + dummy 2.3.5 - pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 + pkg:pypi/pathlib2@2.3.5 - + dummy 2.3.5 - pkg:pypi/pathlib2@2.3.5 + pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.json.bin index 6ebec9dd..4f4e5528 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.json.bin @@ -1,16 +1,16 @@ { "components": [ { - "bom-ref": "dummy-b", + "bom-ref": "dummy-a", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", + "purl": "pkg:pypi/pathlib2@2.3.5", "type": "library", "version": "2.3.5" }, { - "bom-ref": "dummy-a", + "bom-ref": "dummy-b", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", "type": "library", "version": "2.3.5" } diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.xml.bin index 9b5b5f7a..56808073 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.xml.bin @@ -4,15 +4,15 @@ 2023-01-07T13:44:32.312678+00:00 - + dummy 2.3.5 - pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 + pkg:pypi/pathlib2@2.3.5 - + dummy 2.3.5 - pkg:pypi/pathlib2@2.3.5 + pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.json.bin index f1eeb9dc..5745f1cf 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.json.bin @@ -1,16 +1,16 @@ { "components": [ { - "bom-ref": "dummy-b", + "bom-ref": "dummy-a", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", + "purl": "pkg:pypi/pathlib2@2.3.5", "type": "library", "version": "2.3.5" }, { - "bom-ref": "dummy-a", + "bom-ref": "dummy-b", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", "type": "library", "version": "2.3.5" } diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.xml.bin index cb9ea370..81a3cb22 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.xml.bin @@ -4,15 +4,15 @@ 2023-01-07T13:44:32.312678+00:00 - + dummy 2.3.5 - pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 + pkg:pypi/pathlib2@2.3.5 - + dummy 2.3.5 - pkg:pypi/pathlib2@2.3.5 + pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.json.bin index 206aaec4..a88cf7ae 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.json.bin @@ -1,16 +1,16 @@ { "components": [ { - "bom-ref": "dummy-b", + "bom-ref": "dummy-a", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", + "purl": "pkg:pypi/pathlib2@2.3.5", "type": "library", "version": "2.3.5" }, { - "bom-ref": "dummy-a", + "bom-ref": "dummy-b", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", "type": "library", "version": "2.3.5" } diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.xml.bin index 2944adfc..36630746 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.xml.bin @@ -4,15 +4,15 @@ 2023-01-07T13:44:32.312678+00:00 - + dummy 2.3.5 - pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 + pkg:pypi/pathlib2@2.3.5 - + dummy 2.3.5 - pkg:pypi/pathlib2@2.3.5 + pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.json.bin index 77097c87..1251020b 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.json.bin @@ -1,16 +1,16 @@ { "components": [ { - "bom-ref": "dummy-b", + "bom-ref": "dummy-a", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", + "purl": "pkg:pypi/pathlib2@2.3.5", "type": "library", "version": "2.3.5" }, { - "bom-ref": "dummy-a", + "bom-ref": "dummy-b", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", "type": "library", "version": "2.3.5" } diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.xml.bin index 92263f13..18390367 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.xml.bin @@ -4,15 +4,15 @@ 2023-01-07T13:44:32.312678+00:00 - + dummy 2.3.5 - pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 + pkg:pypi/pathlib2@2.3.5 - + dummy 2.3.5 - pkg:pypi/pathlib2@2.3.5 + pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 diff --git a/tests/test_model_component.py b/tests/test_model_component.py index 8212cf53..19c97561 100644 --- a/tests/test_model_component.py +++ b/tests/test_model_component.py @@ -144,17 +144,17 @@ def test_multiple_basic_components(self) -> None: self.assertNotEqual(c1, c2) def test_external_references(self) -> None: - c = Component(name='test-component') - c.external_references.add(ExternalReference( + c1 = Component(name='test-component') + c1.external_references.add(ExternalReference( type=ExternalReferenceType.OTHER, url=XsUri('https://cyclonedx.org'), comment='No comment' )) - self.assertEqual(c.name, 'test-component') - self.assertIsNone(c.version) - self.assertEqual(c.type, ComponentType.LIBRARY) - self.assertEqual(len(c.external_references), 1) - self.assertEqual(len(c.hashes), 0) + self.assertEqual(c1.name, 'test-component') + self.assertIsNone(c1.version) + self.assertEqual(c1.type, ComponentType.LIBRARY) + self.assertEqual(len(c1.external_references), 1) + self.assertEqual(len(c1.hashes), 0) c2 = Component(name='test2-component') self.assertEqual(c2.name, 'test2-component') @@ -172,39 +172,35 @@ def test_empty_component_with_version(self) -> None: self.assertEqual(len(c.hashes), 0) def test_component_equal_1(self) -> None: - c = Component(name='test-component') - c.external_references.add(ExternalReference( + c1 = Component(name='test-component') + c1.external_references.add(ExternalReference( type=ExternalReferenceType.OTHER, url=XsUri('https://cyclonedx.org'), comment='No comment' )) - c2 = Component(name='test-component') c2.external_references.add(ExternalReference( type=ExternalReferenceType.OTHER, url=XsUri('https://cyclonedx.org'), comment='No comment' )) - - self.assertEqual(c, c2) + self.assertEqual(c1, c2) def test_component_equal_2(self) -> None: - props: List[Property] = [ + props: List[Property] = ( Property(name='prop1', value='val1'), - Property(name='prop2', value='val2') - ] - - c = Component( + Property(name='prop2', value='val2'), + ) + c1 = Component( name='test-component', version='1.2.3', properties=props ) c2 = Component( name='test-component', version='1.2.3', properties=props ) - - self.assertEqual(c, c2) + self.assertEqual(c1, c2) def test_component_equal_3(self) -> None: - c = Component( + c1 = Component( name='test-component', version='1.2.3', properties=[ Property(name='prop1', value='val1'), Property(name='prop2', value='val2') @@ -216,8 +212,16 @@ def test_component_equal_3(self) -> None: Property(name='prop4', value='val4') ] ) + self.assertNotEqual(c1, c2) - self.assertNotEqual(c, c2) + def test_component_equal_4(self) -> None: + c1 = Component( + name='test-component', version='1.2.3', bom_ref='ref1' + ) + c2 = Component( + name='test-component', version='1.2.3', bom_ref='ref2' + ) + self.assertNotEqual(c1, c2) def test_same_1(self) -> None: c1 = get_component_setuptools_simple() diff --git a/tests/test_model_vulnerability.py b/tests/test_model_vulnerability.py index d4a556ac..7f818043 100644 --- a/tests/test_model_vulnerability.py +++ b/tests/test_model_vulnerability.py @@ -188,7 +188,7 @@ def test_sort(self) -> None: datetime2 = datetime1 + timedelta(seconds=5) # expected sort order: (id, description, detail, source, created, published) - expected_order = [0, 6, 1, 7, 2, 9, 10, 8, 3, 4, 5, 11] + expected_order = [0, 1, 10, 2, 3, 4, 5, 6, 7, 8, 9, 11] vulnerabilities = [ Vulnerability(bom_ref='0', id='a', description='a', detail='a', source=source1, created=datetime1, published=datetime1), diff --git a/tests/test_real_world_examples.py b/tests/test_real_world_examples.py index 1df29fca..0fe3e480 100644 --- a/tests/test_real_world_examples.py +++ b/tests/test_real_world_examples.py @@ -17,6 +17,7 @@ import unittest from datetime import datetime +from json import loads as json_loads from os.path import join from typing import Any from unittest.mock import patch @@ -36,3 +37,19 @@ def test_webgoat_6_1(self, *_: Any, **__: Any) -> None: def test_regression_issue_630(self, *_: Any, **__: Any) -> None: with open(join(OWN_DATA_DIRECTORY, 'xml', '1.6', 'regression_issue630.xml')) as input_xml: Bom.from_xml(input_xml) + + def test_regression_issue677(self, *_: Any, **__: Any) -> None: + # tests https://github.com/CycloneDX/cyclonedx-python-lib/issues/677 + with open(join(OWN_DATA_DIRECTORY, 'json', '1.5', 'issue677.json')) as input_json: + json = json_loads(input_json.read()) + bom = Bom.from_json(json) + self.assertEqual(4, len(bom.components)) + bom.validate() + + def test_regression_issue753(self, *_: Any, **__: Any) -> None: + # tests https://github.com/CycloneDX/cyclonedx-python-lib/issues/753 + with open(join(OWN_DATA_DIRECTORY, 'json', '1.5', 'issue753.json')) as input_json: + json = json_loads(input_json.read()) + bom = Bom.from_json(json) + self.assertEqual(2, len(bom.components)) + bom.validate()