diff --git a/src/spdx/validation/spdx_id_validators.py b/src/spdx/validation/spdx_id_validators.py index dfe25f416..cdf8f0c3a 100644 --- a/src/spdx/validation/spdx_id_validators.py +++ b/src/spdx/validation/spdx_id_validators.py @@ -53,8 +53,7 @@ def validate_spdx_id(spdx_id: str, document: Document, check_document: bool = Fa str]: """ Test that the given spdx_id (and a potential DocumentRef to an external document) is valid and, if it is a reference, actually exists in the document. Optionally checks files or the whole document - for the existence of the spdx_id (i.e. if it is used as a reference). Returns a list of validation messages, - and the external document ref part and id part of the provided spdx_id. """ + for the existence of the spdx_id (i.e. if it is used as a reference). Returns a list of validation messages. """ validation_messages: List[str] = [] split_id: List[str] = spdx_id.split(":") @@ -74,7 +73,7 @@ def validate_spdx_id(spdx_id: str, document: Document, check_document: bool = Fa f'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: {split_id[1]}') if not is_external_doc_ref_present_in_document(split_id[0], document): validation_messages.append( - f"did not find the external document reference {split_id[0]} in the SPDX document") + f'did not find the external document reference "{split_id[0]}" in the SPDX document') return validation_messages @@ -85,10 +84,10 @@ def validate_spdx_id(spdx_id: str, document: Document, check_document: bool = Fa if check_document: if not is_spdx_id_present_in_document(spdx_id, document): - validation_messages.append(f"did not find the referenced spdx_id {spdx_id} in the SPDX document") + validation_messages.append(f'did not find the referenced spdx_id "{spdx_id}" in the SPDX document') if check_files: if not is_spdx_id_present_in_files(spdx_id, document.files): - validation_messages.append(f"did not find the referenced spdx_id {spdx_id} in the SPDX document's files") + validation_messages.append(f'did not find the referenced spdx_id "{spdx_id}" in the SPDX document\'s files') return validation_messages diff --git a/tests/spdx/validation/test_annotation_validator.py b/tests/spdx/validation/test_annotation_validator.py index b37a6860d..608de5bb8 100644 --- a/tests/spdx/validation/test_annotation_validator.py +++ b/tests/spdx/validation/test_annotation_validator.py @@ -28,7 +28,7 @@ def test_valid_annotation(): @pytest.mark.parametrize("annotation_id, file_id, expected_message", [("SPDXRef-File", "SPDXRef-hiddenFile", - "did not find the referenced spdx_id SPDXRef-File in the SPDX document") + 'did not find the referenced spdx_id "SPDXRef-File" in the SPDX document') ]) def test_invalid_annotation(annotation_id, file_id, expected_message): annotation: Annotation = annotation_fixture(spdx_id=annotation_id) diff --git a/tests/spdx/validation/test_relationship_validator.py b/tests/spdx/validation/test_relationship_validator.py index c93c2e24c..89ea0883d 100644 --- a/tests/spdx/validation/test_relationship_validator.py +++ b/tests/spdx/validation/test_relationship_validator.py @@ -33,9 +33,9 @@ def test_valid_relationship(related_spdx_element): @pytest.mark.parametrize("spdx_element_id, related_spdx_element_id, expected_message", [("SPDXRef-unknownFile", "SPDXRef-File", - 'did not find the referenced spdx_id SPDXRef-unknownFile in the SPDX document'), + 'did not find the referenced spdx_id "SPDXRef-unknownFile" in the SPDX document'), ("SPDXRef-File", "SPDXRef-unknownFile", - 'did not find the referenced spdx_id SPDXRef-unknownFile in the SPDX document'), + 'did not find the referenced spdx_id "SPDXRef-unknownFile" in the SPDX document'), ]) def test_unknown_spdx_id(spdx_element_id, related_spdx_element_id, expected_message): relationship: Relationship = relationship_fixture(spdx_element_id=spdx_element_id, diff --git a/tests/spdx/validation/test_spdx_id_validators.py b/tests/spdx/validation/test_spdx_id_validators.py index 4c001697f..ee8536cba 100644 --- a/tests/spdx/validation/test_spdx_id_validators.py +++ b/tests/spdx/validation/test_spdx_id_validators.py @@ -8,5 +8,115 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from unittest import TestCase + +import pytest + +from spdx.validation.spdx_id_validators import is_valid_internal_spdx_id, is_valid_external_doc_ref_id, \ + get_list_of_all_spdx_ids, is_spdx_id_present_in_document, is_external_doc_ref_present_in_document, validate_spdx_id +from tests.spdx.fixtures import document_fixture, file_fixture, package_fixture, snippet_fixture, creation_info_fixture, \ + external_document_ref_fixture + +DOCUMENT = document_fixture(files=[file_fixture(spdx_id="SPDXRef-File1"), + file_fixture(spdx_id="SPDXRef-File2")], + packages=[package_fixture(spdx_id="SPDXRef-Package1"), + package_fixture(spdx_id="SPDXRef-Package2")], + snippets=[snippet_fixture(spdx_id="SPDXRef-Snippet1"), + snippet_fixture(spdx_id="SPDXRef-Snippet2")], + creation_info=creation_info_fixture( + external_document_refs=[external_document_ref_fixture(document_ref_id="DocumentRef-external"), + external_document_ref_fixture(document_ref_id="DocumentRef-1.2-ext")])) + + +@pytest.mark.parametrize("spdx_id", ["SPDXRef-DOCUMENT", "SPDXRef-File1", "SPDXRef-1.3-3.7"]) +def test_valid_internal_spdx_ids(spdx_id): + assert is_valid_internal_spdx_id(spdx_id) + + +@pytest.mark.parametrize("spdx_id", + ["spdxId", "spdxRef-DOCUMENT", "SPDXRef.File", "SPDXRef#Snippet", "SPDXRef-1.3_3.7"]) +def test_invalid_internal_spdx_ids(spdx_id): + assert not is_valid_internal_spdx_id(spdx_id) + + +@pytest.mark.parametrize("doc_ref_id", ["DocumentRef-external", "DocumentRef-...+", "DocumentRef-v0.4.2-alpha"]) +def test_valid_external_doc_ref_ids(doc_ref_id): + assert is_valid_external_doc_ref_id(doc_ref_id) + + +@pytest.mark.parametrize("doc_ref_id", + ["external-ref", "Documentref-external", "DocumentRef-...#", "DocumentRef-v0_4_2-alpha"]) +def test_invalid_external_doc_ref_ids(doc_ref_id): + assert not is_valid_external_doc_ref_id(doc_ref_id) + + +def test_is_spdx_id_present_in_document(): + assert is_spdx_id_present_in_document("SPDXRef-File1", DOCUMENT) + assert is_spdx_id_present_in_document("SPDXRef-Package2", DOCUMENT) + assert is_spdx_id_present_in_document("SPDXRef-Snippet1", DOCUMENT) + assert is_spdx_id_present_in_document("SPDXRef-DOCUMENT", DOCUMENT) + assert not is_spdx_id_present_in_document("SPDXRef-file2", DOCUMENT) + + +def test_is_external_doc_ref_present_in_document(): + assert is_external_doc_ref_present_in_document("DocumentRef-1.2-ext", DOCUMENT) + assert not is_external_doc_ref_present_in_document("DocumentRef-External1", DOCUMENT) + +def test_list_of_all_spdx_ids(): + TestCase().assertCountEqual(get_list_of_all_spdx_ids(DOCUMENT), + ["SPDXRef-DOCUMENT", "SPDXRef-File1", "SPDXRef-File2", "SPDXRef-Package1", + "SPDXRef-Package2", "SPDXRef-Snippet1", "SPDXRef-Snippet2"]) + + +@pytest.mark.parametrize("spdx_id", + ["DocumentRef-external:SPDXRef-File", "SPDXRef-Package"]) +def test_valid_spdx_id(spdx_id): + validation_messages = validate_spdx_id(spdx_id, DOCUMENT) + + assert validation_messages == [] + + +@pytest.mark.parametrize("spdx_id, expected_messages", + [("DocumentRef-external:extern:SPDXRef-File", + [f"spdx_id must not contain more than one colon in order to separate the external document reference id from the internal SPDX id, but is: DocumentRef-external:extern:SPDXRef-File"]), + ("DocumentRef external:SPDXRef-File", + ['the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" and must begin with "DocumentRef-", but is: DocumentRef external', + 'did not find the external document reference "DocumentRef external" in the SPDX document']), + ("DocRef-ext:SPDXRef-File_2", + ['the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" and must begin with "DocumentRef-", but is: DocRef-ext', + 'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: SPDXRef-File_2', + 'did not find the external document reference "DocRef-ext" in the SPDX document']), + ("DocumentRef-external:SPDXRef-File_2", + ['the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: SPDXRef-File_2']), + ("SPDXRef-42+", + ['spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: SPDXRef-42+']) + ]) +def test_invalid_spdx_id(spdx_id, expected_messages): + validation_messages = validate_spdx_id(spdx_id, DOCUMENT) + + TestCase().assertCountEqual(validation_messages, expected_messages) + + +@pytest.mark.parametrize("spdx_id", + ["DocumentRef-external:SPDXRef-File", "SPDXRef-DOCUMENT", "SPDXRef-File1", "SPDXRef-Package1", "SPDXRef-Snippet1"]) +def test_valid_spdx_id_with_check_document(spdx_id): + validation_messages = validate_spdx_id(spdx_id, DOCUMENT, check_document=True) + assert validation_messages == [] + + +def test_invalid_spdx_id_with_check_document(): + validation_messages = validate_spdx_id("SPDXRef-Filet", DOCUMENT, check_document=True) + assert validation_messages == ['did not find the referenced spdx_id "SPDXRef-Filet" in the SPDX document'] + + +@pytest.mark.parametrize("spdx_id", + ["DocumentRef-external:SPDXRef-File", "SPDXRef-File1"]) +def test_valid_spdx_id_with_check_files(spdx_id): + validation_messages = validate_spdx_id(spdx_id, DOCUMENT, check_files=True) + assert validation_messages == [] + + +def test_invalid_spdx_id_with_check_files(): + validation_messages = validate_spdx_id("SPDXRef-Package1", DOCUMENT, check_files=True) + assert validation_messages == ['did not find the referenced spdx_id "SPDXRef-Package1" in the SPDX document\'s files'] -# TODO: https://github.com/spdx/tools-python/issues/376