debian-forge/test/mod/test_util_sbom_spdx.py
Tomáš Hozza dbb7aa0051 test/sbom/spdx: move importorskip to relevant test case
Move the call to `pytest.importorskip()` function into a specific test
case that relies on imported modules. This will make test cases in the
same file to be run, even if importing the modules fail.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
2025-02-27 13:31:19 +01:00

131 lines
6.2 KiB
Python

import os
import pytest
import osbuild
from osbuild.util.sbom.spdx import (
SpdxLicenseExpressionCreator,
create_spdx2_document,
sbom_pkgset_to_spdx2_doc,
spdx2_checksum_algorithm,
)
from osbuild.util.sbom.spdx2.model import (
CreatorType,
ExternalPackageRefCategory,
ExtractedLicensingInfo,
RelationshipType,
)
from ..test import patch_license_expression
@pytest.mark.parametrize("licensing_available", (True, False))
def test_spdxlicenseexpressionfactory_license_expression_availability(licensing_available):
with patch_license_expression(licensing_available) as mocked_licensing:
lf = SpdxLicenseExpressionCreator()
license_expression = lf.ensure_license_expression("MIT")
if licensing_available:
assert mocked_licensing is not None
# The license string should be a SPDX license expression string.
assert license_expression == "MIT"
assert len(lf.extracted_license_infos()) == 0
else:
assert mocked_licensing is None
# The license string should be wrapped in an ExtractedLicensingInfo,
# because the license-expression package is not available.
assert isinstance(license_expression, ExtractedLicensingInfo)
assert str(license_expression).startswith("LicenseRef-")
assert license_expression.extracted_text == "MIT"
assert len(lf.extracted_license_infos()) == 1
def test_create_spdx2_document():
doc1 = create_spdx2_document()
assert doc1.creation_info.spdx_version == "SPDX-2.3"
assert doc1.creation_info.spdx_id == "SPDXRef-DOCUMENT"
assert doc1.creation_info.name == f"sbom-by-osbuild-{osbuild.__version__}"
assert doc1.creation_info.data_license == "CC0-1.0"
assert doc1.creation_info.document_namespace.startswith("https://osbuild.org/spdxdocs/sbom-by-osbuild-")
assert len(doc1.creation_info.creators) == 1
assert doc1.creation_info.creators[0].creator_type == CreatorType.TOOL
assert doc1.creation_info.creators[0].name == f"osbuild-{osbuild.__version__}"
assert doc1.creation_info.created
doc2 = create_spdx2_document()
assert doc1.creation_info.document_namespace != doc2.creation_info.document_namespace
assert doc1.creation_info.created != doc2.creation_info.created
doc1_dict = doc1.to_dict()
doc2_dict = doc2.to_dict()
del doc1_dict["creationInfo"]["created"]
del doc2_dict["creationInfo"]["created"]
del doc1_dict["documentNamespace"]
del doc2_dict["documentNamespace"]
assert doc1_dict == doc2_dict
@pytest.mark.parametrize("licensing_available", (True, False))
def test_sbom_pkgset_to_spdx2_doc(licensing_available):
testutil_dnf4 = pytest.importorskip("osbuild.testutil.dnf4")
bom_dnf = pytest.importorskip("osbuild.util.sbom.dnf")
dnf_pkgset = testutil_dnf4.depsolve_pkgset([os.path.abspath("./test/data/testrepos/baseos")], ["bash"])
bom_pkgset = bom_dnf.dnf_pkgset_to_sbom_pkgset(dnf_pkgset)
with patch_license_expression(licensing_available) as _:
extracted_licensing_infos = set()
doc = sbom_pkgset_to_spdx2_doc(bom_pkgset)
assert len(doc.packages) == len(bom_pkgset)
for spdx_pkg, bom_pkg in zip(doc.packages, bom_pkgset):
assert spdx_pkg.spdx_id == f"SPDXRef-{bom_pkg.uuid()}"
assert spdx_pkg.name == bom_pkg.name
assert spdx_pkg.version == bom_pkg.version
assert not spdx_pkg.files_analyzed
assert spdx_pkg.download_location == bom_pkg.download_url
assert spdx_pkg.homepage == bom_pkg.homepage
assert spdx_pkg.summary == bom_pkg.summary
assert spdx_pkg.description == bom_pkg.description
assert spdx_pkg.source_info == bom_pkg.source_info()
assert spdx_pkg.built_date == bom_pkg.build_date
# If the license-expression package is available, only the "MIT" license is converted
# as a valid SPDX license expression for our testing package set.
if licensing_available and bom_pkg.license_declared == "MIT":
assert isinstance(spdx_pkg.license_declared, str)
assert spdx_pkg.license_declared == "MIT"
# If the license-expression package is not available, all licenses are converted
# to SPDX license references.
# The same applies to all licenses that are not "MIT" if the package is available,
# because the testing package set contains only "MIT" as a valid SPDX license expression.
else:
assert isinstance(spdx_pkg.license_declared, ExtractedLicensingInfo)
assert str(spdx_pkg.license_declared).startswith("LicenseRef-")
assert spdx_pkg.license_declared.extracted_text == bom_pkg.license_declared
extracted_licensing_infos.add(spdx_pkg.license_declared)
assert len(spdx_pkg.checksums) == 1
assert spdx_pkg.checksums[0].algorithm == spdx2_checksum_algorithm(list(bom_pkg.checksums.keys())[0])
assert spdx_pkg.checksums[0].value == list(bom_pkg.checksums.values())[0]
assert len(spdx_pkg.external_references) == 1
assert spdx_pkg.external_references[0].category == ExternalPackageRefCategory.PACKAGE_MANAGER
assert spdx_pkg.external_references[0].reference_type == "purl"
assert spdx_pkg.external_references[0].locator == bom_pkg.purl()
assert len([rel for rel in doc.relationships if rel.relationship_type ==
RelationshipType.DESCRIBES]) == len(bom_pkgset)
deps_count = sum(len(bom_pkg.depends_on) for bom_pkg in bom_pkgset)
assert len([rel for rel in doc.relationships if rel.relationship_type ==
RelationshipType.DEPENDS_ON]) == deps_count
optional_deps_count = sum(len(bom_pkg.optional_depends_on) for bom_pkg in bom_pkgset)
assert len([rel for rel in doc.relationships if rel.relationship_type ==
RelationshipType.OPTIONAL_DEPENDENCY_OF]) == optional_deps_count
assert len(extracted_licensing_infos) > 0
assert sorted(extracted_licensing_infos, key=lambda x: x.license_ref_id) == \
sorted(doc.extracted_licensing_infos, key=lambda x: x.license_ref_id)