Skip to content

Commit e4ad3bc

Browse files
authored
tests: test builder this (#675)
QA for #649 --------- Signed-off-by: Jan Kowalleck <[email protected]>
1 parent 9940cf9 commit e4ad3bc

File tree

4 files changed

+115
-18
lines changed

4 files changed

+115
-18
lines changed

cyclonedx/builder/this.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,23 @@ def this_component() -> Component:
3737
licenses=(DisjunctiveLicense(id='Apache-2.0',
3838
acknowledgement=LicenseAcknowledgement.DECLARED),),
3939
external_references=(
40+
# let's assume this is not a fork
4041
ExternalReference(
41-
type=ExternalReferenceType.BUILD_SYSTEM,
42-
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/actions')
43-
),
44-
ExternalReference(
45-
type=ExternalReferenceType.DISTRIBUTION,
46-
url=XsUri('https://pypi.org/project/cyclonedx-python-lib/')
42+
type=ExternalReferenceType.WEBSITE,
43+
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/#readme')
4744
),
4845
ExternalReference(
4946
type=ExternalReferenceType.DOCUMENTATION,
5047
url=XsUri('https://cyclonedx-python-library.readthedocs.io/')
5148
),
49+
ExternalReference(
50+
type=ExternalReferenceType.VCS,
51+
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib')
52+
),
53+
ExternalReference(
54+
type=ExternalReferenceType.BUILD_SYSTEM,
55+
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/actions')
56+
),
5257
ExternalReference(
5358
type=ExternalReferenceType.ISSUE_TRACKER,
5459
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/issues')
@@ -61,13 +66,10 @@ def this_component() -> Component:
6166
type=ExternalReferenceType.RELEASE_NOTES,
6267
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md')
6368
),
69+
# we cannot assert where the lib was fetched from, but we can give a hint
6470
ExternalReference(
65-
type=ExternalReferenceType.VCS,
66-
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib')
67-
),
68-
ExternalReference(
69-
type=ExternalReferenceType.WEBSITE,
70-
url=XsUri('https://github.com/CycloneDX/cyclonedx-python-lib/#readme')
71+
type=ExternalReferenceType.DISTRIBUTION,
72+
url=XsUri('https://pypi.org/project/cyclonedx-python-lib/')
7173
),
7274
),
7375
# to be extended...

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ requires = ["poetry-core>=1.0.0"]
33
build-backend = "poetry.core.masonry.api"
44

55
[tool.poetry]
6-
# keep in sync with `cyclonedx/builder/this.py`
76
name = "cyclonedx-python-lib"
87
# !! version is managed by semantic_release
98
version = "7.6.0"
@@ -64,7 +63,6 @@ keywords = [
6463
]
6564

6665
[tool.poetry.urls]
67-
# keep in sync with `cyclonedx/builder/this.py`
6866
"Bug Tracker" = "https://github.com/CycloneDX/cyclonedx-python-lib/issues"
6967
"Funding" = "https://owasp.org/donate/?reponame=www-project-cyclonedx&title=OWASP+CycloneDX"
7068

@@ -95,6 +93,7 @@ pep8-naming = "0.14.1"
9593
isort = "5.13.2"
9694
autopep8 = "2.3.1"
9795
mypy = "1.11.2"
96+
toml = { version="0.10.2", python="<3.11"}
9897
tox = "4.18.0"
9998
xmldiff = "2.7.0"
10099
bandit = "1.7.9"

tests/__init__.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@
1414
#
1515
# SPDX-License-Identifier: Apache-2.0
1616
# Copyright (c) OWASP Foundation. All Rights Reserved.
17+
1718
import re
19+
import sys
1820
from os import getenv, path
19-
from os.path import basename, join, splitext
20-
from typing import TYPE_CHECKING, Any, Generator, Iterable, List, Optional, Tuple, TypeVar, Union
21+
from typing import TYPE_CHECKING, Any, Dict, Generator, Iterable, List, Optional, Tuple, TypeVar, Union
2122
from unittest import TestCase
2223
from uuid import UUID
2324

@@ -47,7 +48,7 @@ class SnapshotMixin:
4748

4849
@staticmethod
4950
def getSnapshotFile(snapshot_name: str) -> str: # noqa: N802
50-
return join(SNAPSHOTS_DIRECTORY, f'{snapshot_name}.bin')
51+
return path.join(SNAPSHOTS_DIRECTORY, f'{snapshot_name}.bin')
5152

5253
@classmethod
5354
def writeSnapshot(cls, snapshot_name: str, data: str) -> None: # noqa: N802
@@ -189,4 +190,15 @@ class DpTuple(Tuple[SchemaVersion, str]):
189190
@property
190191
def __name__(self) -> str:
191192
schema_version, test_data_file = self
192-
return f'{schema_version.to_version()}-{splitext(basename(test_data_file))[0]}'
193+
return f'{schema_version.to_version()}-{path.splitext(path.basename(test_data_file))[0]}'
194+
195+
196+
def load_pyproject() -> Dict[str, Any]:
197+
if sys.version_info >= (3, 11):
198+
from tomllib import load as toml_load
199+
with open(path.join(path.dirname(__file__), '..', 'pyproject.toml'), 'rb') as f:
200+
return toml_load(f)
201+
else:
202+
from toml import load as toml_load
203+
with open(path.join(path.dirname(__file__), '..', 'pyproject.toml'), 'rt') as f:
204+
return toml_load(f)

tests/test_builder_this.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# This file is part of CycloneDX Python Lib
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
# SPDX-License-Identifier: Apache-2.0
16+
# Copyright (c) OWASP Foundation. All Rights Reserved.
17+
18+
from typing import Any, Dict, Iterable, Tuple, Union
19+
from unittest import TestCase
20+
21+
from cyclonedx.builder.this import this_component, this_tool
22+
from cyclonedx.model import ExternalReference, ExternalReferenceType
23+
from cyclonedx.model.component import ComponentType
24+
from cyclonedx.model.license import License, LicenseAcknowledgement
25+
from tests import load_pyproject
26+
27+
28+
class ExtRefsTestMixin:
29+
30+
@staticmethod
31+
def __first_ers_uri(t: ExternalReferenceType, ers: Iterable[ExternalReference]) -> str:
32+
return next(filter(lambda r: r.type is t, ers)).url.uri
33+
34+
def assertExtRefs( # noqa:N802
35+
self: Union[TestCase, 'ExtRefsTestMixin'],
36+
p: Dict[str, Any], ers: Iterable[ExternalReference]
37+
) -> None:
38+
self.assertEqual(p['tool']['poetry']['homepage'], self.__first_ers_uri(
39+
ExternalReferenceType.WEBSITE, ers))
40+
self.assertEqual(p['tool']['poetry']['repository'], self.__first_ers_uri(
41+
ExternalReferenceType.VCS, ers))
42+
self.assertEqual(p['tool']['poetry']['documentation'], self.__first_ers_uri(
43+
ExternalReferenceType.DOCUMENTATION, ers))
44+
self.assertEqual(p['tool']['poetry']['urls']['Bug Tracker'], self.__first_ers_uri(
45+
ExternalReferenceType.ISSUE_TRACKER, ers))
46+
47+
48+
class TestThisComponent(TestCase, ExtRefsTestMixin):
49+
def test_basics(self) -> None:
50+
p = load_pyproject()
51+
c = this_component()
52+
self.assertIs(ComponentType.LIBRARY, c.type)
53+
self.assertEqual('CycloneDX', c.group)
54+
self.assertEqual(p['tool']['poetry']['name'], c.name)
55+
self.assertEqual(p['tool']['poetry']['version'], c.version)
56+
self.assertEqual(p['tool']['poetry']['description'], c.description)
57+
58+
def test_license(self) -> None:
59+
p = load_pyproject()
60+
ls: Tuple[License, ...] = tuple(this_component().licenses)
61+
self.assertEqual(1, len(ls))
62+
l = ls[0] # noqa:E741
63+
self.assertIs(LicenseAcknowledgement.DECLARED, l.acknowledgement)
64+
# this uses the fact that poetry expect license declarations as valid SPDX-license-id
65+
self.assertEqual(p['tool']['poetry']['license'], l.id)
66+
67+
def test_extrefs(self) -> None:
68+
p = load_pyproject()
69+
ers: Tuple[ExternalReference, ...] = tuple(this_component().external_references)
70+
self.assertExtRefs(p, ers)
71+
72+
73+
class TestThisTool(TestCase, ExtRefsTestMixin):
74+
def test_basics(self) -> None:
75+
p = load_pyproject()
76+
t = this_tool()
77+
self.assertEqual('CycloneDX', t.vendor)
78+
self.assertEqual(p['tool']['poetry']['name'], t.name)
79+
self.assertEqual(p['tool']['poetry']['version'], t.version)
80+
81+
def test_extrefs(self) -> None:
82+
p = load_pyproject()
83+
ers: Tuple[ExternalReference, ...] = tuple(this_tool().external_references)
84+
self.assertExtRefs(p, ers)

0 commit comments

Comments
 (0)