Skip to content

Commit

Permalink
[issue-744] implement validation of external license references
Browse files Browse the repository at this point in the history
Signed-off-by: Armin Tänzer <armin.taenzer@tngtech.com>
  • Loading branch information
armintaenzertng committed Aug 24, 2023
1 parent ca72624 commit 85b480a
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 2 deletions.
32 changes: 31 additions & 1 deletion src/spdx_tools/spdx/validation/license_expression_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from spdx_tools.common.spdx_licensing import spdx_licensing
from spdx_tools.spdx.model import Document, SpdxNoAssertion, SpdxNone
from spdx_tools.spdx.validation.spdx_id_validators import is_external_doc_ref_present_in_document
from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage


Expand Down Expand Up @@ -42,7 +43,36 @@ def validate_license_expression(
license_ref_ids: List[str] = [license_ref.license_id for license_ref in document.extracted_licensing_info]

for non_spdx_token in spdx_licensing.validate(license_expression).invalid_symbols:
if non_spdx_token not in license_ref_ids:
if ":" in non_spdx_token:
split_token: List[str] = non_spdx_token.split(":")
if len(split_token) != 2:
validation_messages.append(
ValidationMessage(
f"Too many colons in license reference: {non_spdx_token}. "
"A license reference must only contain a single colon to "
"separate an external document reference from the license reference.",
context,
)
)
else:
if not split_token[1].startswith("LicenseRef-"):
validation_messages.append(
ValidationMessage(
f'A license reference must start with "LicenseRef-", but is: {split_token[1]} '
f"in external license reference {non_spdx_token}.",
context,
)
)
if not is_external_doc_ref_present_in_document(split_token[0], document):
validation_messages.append(
ValidationMessage(
f'Did not find the external document reference "{split_token[0]}" in the SPDX document. '
f"From the external license reference {non_spdx_token}.",
context,
)
)

elif non_spdx_token not in license_ref_ids:
validation_messages.append(
ValidationMessage(
f"Unrecognized license reference: {non_spdx_token}. license_expression must only use IDs from the "
Expand Down
39 changes: 38 additions & 1 deletion tests/spdx/validation/test_license_expression_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
validate_license_expressions,
)
from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage
from tests.spdx.fixtures import document_fixture, extracted_licensing_info_fixture
from tests.spdx.fixtures import document_fixture, external_document_ref_fixture, extracted_licensing_info_fixture

FIXTURE_LICENSE_ID = extracted_licensing_info_fixture().license_id
EXTERNAL_DOCUMENT_ID = external_document_ref_fixture().document_ref_id


@pytest.mark.parametrize(
Expand All @@ -26,6 +27,7 @@
"MIT",
FIXTURE_LICENSE_ID,
f"GPL-2.0-only with GPL-CC-1.0 and {FIXTURE_LICENSE_ID} with 389-exception or Beerware",
f"{EXTERNAL_DOCUMENT_ID}:LicenseRef-007",
],
)
def test_valid_license_expression(expression_string):
Expand Down Expand Up @@ -136,3 +138,38 @@ def test_invalid_license_expression_with_invalid_exceptions(expression_string, e
expected_messages = [ValidationMessage(expected_message, context)]

assert validation_messages == expected_messages


@pytest.mark.parametrize(
"expression_string, expected_message",
[
(
f"{EXTERNAL_DOCUMENT_ID}:LicenseRef-007:4",
f"Too many colons in license reference: {EXTERNAL_DOCUMENT_ID}:LicenseRef-007:4. "
"A license reference must only contain a single colon to "
"separate an external document reference from the license reference.",
),
(
f"{EXTERNAL_DOCUMENT_ID}:unknown_license",
'A license reference must start with "LicenseRef-", but is: unknown_license '
f"in external license reference {EXTERNAL_DOCUMENT_ID}:unknown_license.",
),
(
"DocumentRef-unknown:LicenseRef-1",
'Did not find the external document reference "DocumentRef-unknown" in the SPDX document. '
"From the external license reference DocumentRef-unknown:LicenseRef-1.",
),
],
)
def test_invalid_license_expression_with_external_reference(expression_string, expected_message):
document: Document = document_fixture()
license_expression: LicenseExpression = spdx_licensing.parse(expression_string)
parent_id = "SPDXRef-File"
context = ValidationContext(
parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, full_element=license_expression
)

validation_messages: List[ValidationMessage] = validate_license_expression(license_expression, document, parent_id)
expected_messages = [ValidationMessage(expected_message, context)]

assert validation_messages == expected_messages

0 comments on commit 85b480a

Please sign in to comment.