From a6628534740398006f6f844731808a7af62c2ed6 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 6 Apr 2023 14:36:24 +0200 Subject: [PATCH] [issue-394] add tests for tag_value writer Signed-off-by: Meret Behrens --- .../writer/tagvalue/test_annotation_writer.py | 28 +++++ .../writer/tagvalue/test_checksum_writer.py | 26 +++++ .../test_extracted_licensing_info_writer.py | 28 +++++ .../spdx/writer/tagvalue/test_file_writer.py | 38 +++++++ .../writer/tagvalue/test_package_writer.py | 51 +++++---- .../tagvalue/test_relationship_writer.py | 46 ++++++++ .../writer/tagvalue/test_snippet_writer.py | 37 +++++++ .../writer/tagvalue/test_tagvalue_writer.py | 103 +++++++++++++++++- .../test_tagvalue_writer_helper_functions.py | 33 +++++- 9 files changed, 362 insertions(+), 28 deletions(-) create mode 100644 tests/spdx/writer/tagvalue/test_annotation_writer.py create mode 100644 tests/spdx/writer/tagvalue/test_checksum_writer.py create mode 100644 tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py create mode 100644 tests/spdx/writer/tagvalue/test_file_writer.py create mode 100644 tests/spdx/writer/tagvalue/test_relationship_writer.py create mode 100644 tests/spdx/writer/tagvalue/test_snippet_writer.py diff --git a/tests/spdx/writer/tagvalue/test_annotation_writer.py b/tests/spdx/writer/tagvalue/test_annotation_writer.py new file mode 100644 index 000000000..1af76c342 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_annotation_writer.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +from spdx.writer.tagvalue.annotation_writer import write_annotation +from tests.spdx.fixtures import annotation_fixture + + +def test_annotation_writer(): + annotation = annotation_fixture() + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_annotation(annotation, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call(f"Annotator: Person: {annotation.annotator.name} ({annotation.annotator.email})\n"), + call("AnnotationDate: 2022-12-01T00:00:00Z\n"), + call(f"AnnotationType: {annotation.annotation_type.name}\n"), + call(f"SPDXREF: {annotation.spdx_id}\n"), + call(f"AnnotationComment: {annotation.annotation_comment}\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_checksum_writer.py b/tests/spdx/writer/tagvalue/test_checksum_writer.py new file mode 100644 index 000000000..535b56088 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_checksum_writer.py @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx.model.checksum import ChecksumAlgorithm +from spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value +from tests.spdx.fixtures import checksum_fixture + + +@pytest.mark.parametrize( + "checksum, expected_string", + [ + (checksum_fixture(), "SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c"), + (checksum_fixture(algorithm=ChecksumAlgorithm.SHA3_256, value="fdsef"), "SHA3-256: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.SHA3_384, value="fdsef"), "SHA3-384: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.SHA3_512, value="fdsef"), "SHA3-512: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.BLAKE2B_256, value="fdsef"), "BLAKE2b-256: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.BLAKE2B_384, value="fdsef"), "BLAKE2b-384: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.BLAKE2B_512, value="fdsef"), "BLAKE2b-512: fdsef"), + ], +) +def test_checksum_writer(checksum, expected_string): + checksum_string = write_checksum_to_tag_value(checksum) + + assert checksum_string == expected_string diff --git a/tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py b/tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py new file mode 100644 index 000000000..55354835a --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +from spdx.writer.tagvalue.extracted_licensing_info_writer import write_extracted_licensing_info +from tests.spdx.fixtures import extracted_licensing_info_fixture + + +def test_extracted_licensing_info_writer(): + extracted_licensing_info = extracted_licensing_info_fixture() + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_extracted_licensing_info(extracted_licensing_info, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call(f"LicenseID: {extracted_licensing_info.license_id}\n"), + call(f"ExtractedText: {extracted_licensing_info.extracted_text}\n"), + call(f"LicenseName: {extracted_licensing_info.license_name}\n"), + call(f"LicenseCrossReference: {extracted_licensing_info.cross_references[0]}\n"), + call(f"LicenseComment: {extracted_licensing_info.comment}\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_file_writer.py b/tests/spdx/writer/tagvalue/test_file_writer.py new file mode 100644 index 000000000..27eb7ef49 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_file_writer.py @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +from spdx.writer.tagvalue.file_writer import write_file +from tests.spdx.fixtures import file_fixture + + +def test_file_writer(): + spdx_file = file_fixture() + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_file(spdx_file, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call("## File Information\n"), + call(f"FileName: {spdx_file.name}\n"), + call(f"SPDXID: {spdx_file.spdx_id}\n"), + call(f"FileType: {spdx_file.file_types[0].name}\n"), + call("FileChecksum: SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), + call(f"LicenseConcluded: {spdx_file.license_concluded}\n"), + call(f"LicenseInfoInFile: {spdx_file.license_info_in_file[0]}\n"), + call(f"LicenseInfoInFile: {spdx_file.license_info_in_file[1]}\n"), + call(f"LicenseInfoInFile: {spdx_file.license_info_in_file[2]}\n"), + call(f"LicenseComments: {spdx_file.license_comment}\n"), + call(f"FileCopyrightText: {spdx_file.copyright_text}\n"), + call(f"FileComment: {spdx_file.comment}\n"), + call(f"FileNotice: {spdx_file.notice}\n"), + call(f"FileContributor: {spdx_file.contributors[0]}\n"), + call(f"FileAttributionText: {spdx_file.attribution_texts[0]}\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_package_writer.py b/tests/spdx/writer/tagvalue/test_package_writer.py index 8cb492b34..38873984a 100644 --- a/tests/spdx/writer/tagvalue/test_package_writer.py +++ b/tests/spdx/writer/tagvalue/test_package_writer.py @@ -20,32 +20,35 @@ def test_package_writer(): handle.write.assert_has_calls( [ call("## Package Information\n"), - call("PackageName: packageName\n"), - call("SPDXID: SPDXRef-Package\n"), - call("PackageVersion: 12.2\n"), - call("PackageFileName: ./packageFileName\n"), - call("PackageSupplier: Person: supplierName (some@mail.com)\n"), - call("PackageOriginator: Person: originatorName (some@mail.com)\n"), - call("PackageDownloadLocation: https://download.com\n"), + call(f"PackageName: {package.name}\n"), + call(f"SPDXID: {package.spdx_id}\n"), + call(f"PackageVersion: {package.version}\n"), + call(f"PackageFileName: {package.file_name}\n"), + call(f"PackageSupplier: Person: {package.supplier.name} ({package.supplier.email})\n"), + call(f"PackageOriginator: Person: {package.originator.name} ({package.originator.email})\n"), + call(f"PackageDownloadLocation: {package.download_location}\n"), call("FilesAnalyzed: True\n"), - call("PackageVerificationCode: 85ed0817af83a24ad8da68c2b5094de69833983c (excludes: ./exclude.py)\n"), + call(f"PackageVerificationCode: {package.verification_code.value} (excludes: ./exclude.py)\n"), call("PackageChecksum: SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), - call("PackageHomePage: https://homepage.com\n"), - call("PackageSourceInfo: sourceInfo\n"), - call("PackageLicenseConcluded: MIT AND GPL-2.0-only\n"), - call("PackageLicenseInfoFromFiles: MIT\n"), - call("PackageLicenseInfoFromFiles: GPL-2.0-only\n"), - call("PackageLicenseInfoFromFiles: NOASSERTION\n"), - call("PackageLicenseDeclared: MIT AND GPL-2.0-only\n"), - call("PackageLicenseComments: packageLicenseComment\n"), - call("PackageCopyrightText: packageCopyrightText\n"), - call("PackageSummary: packageSummary\n"), - call("PackageDescription: packageDescription\n"), - call("PackageComment: packageComment\n"), - call("ExternalRef: PACKAGE-MANAGER maven-central org.apache.tomcat:tomcat:9.0.0.M4\n"), - call("ExternalRefComment: externalPackageRefComment\n"), - call("PackageAttributionText: packageAttributionText\n"), - call("PrimaryPackagePurpose: SOURCE\n"), + call(f"PackageHomePage: {package.homepage}\n"), + call(f"PackageSourceInfo: {package.source_info}\n"), + call(f"PackageLicenseConcluded: {package.license_concluded}\n"), + call(f"PackageLicenseInfoFromFiles: {package.license_info_from_files[0]}\n"), + call(f"PackageLicenseInfoFromFiles: {package.license_info_from_files[1]}\n"), + call(f"PackageLicenseInfoFromFiles: {package.license_info_from_files[2]}\n"), + call(f"PackageLicenseDeclared: {package.license_declared}\n"), + call(f"PackageLicenseComments: {package.license_comment}\n"), + call(f"PackageCopyrightText: {package.copyright_text}\n"), + call(f"PackageSummary: {package.summary}\n"), + call(f"PackageDescription: {package.description}\n"), + call(f"PackageComment: {package.comment}\n"), + call( + f"ExternalRef: PACKAGE-MANAGER {package.external_references[0].reference_type} " + f"{package.external_references[0].locator}\n" + ), + call(f"ExternalRefComment: {package.external_references[0].comment}\n"), + call(f"PackageAttributionText: {package.attribution_texts[0]}\n"), + call(f"PrimaryPackagePurpose: {package.primary_package_purpose.name}\n"), call("ReleaseDate: 2022-12-01T00:00:00Z\n"), call("BuiltDate: 2022-12-02T00:00:00Z\n"), call("ValidUntilDate: 2022-12-03T00:00:00Z\n"), diff --git a/tests/spdx/writer/tagvalue/test_relationship_writer.py b/tests/spdx/writer/tagvalue/test_relationship_writer.py new file mode 100644 index 000000000..2d0a129f1 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_relationship_writer.py @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +import pytest + +from spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx.model.spdx_none import SpdxNone +from spdx.writer.tagvalue.relationship_writer import write_relationship +from tests.spdx.fixtures import relationship_fixture + + +@pytest.mark.parametrize( + "relationship, expected_calls", + [ + ( + relationship_fixture(), + [ + call("Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-File\n"), + call("RelationshipComment: relationshipComment\n"), + ], + ), + ( + relationship_fixture(related_spdx_element_id=SpdxNoAssertion(), comment=None), + [call("Relationship: SPDXRef-DOCUMENT DESCRIBES NOASSERTION\n")], + ), + ( + relationship_fixture( + spdx_element_id="DocumentRef-External:SPDXRef-DOCUMENT", + related_spdx_element_id=SpdxNone(), + comment=None, + ), + [call("Relationship: DocumentRef-External:SPDXRef-DOCUMENT DESCRIBES NONE\n")], + ), + ], +) +def test_relationship_writer(relationship, expected_calls): + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_relationship(relationship, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls(expected_calls) diff --git a/tests/spdx/writer/tagvalue/test_snippet_writer.py b/tests/spdx/writer/tagvalue/test_snippet_writer.py new file mode 100644 index 000000000..39e661c87 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_snippet_writer.py @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +from spdx.writer.tagvalue.snippet_writer import write_snippet +from tests.spdx.fixtures import snippet_fixture + + +def test_snippet_writer(): + snippet = snippet_fixture() + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_snippet(snippet, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call("## Snippet Information\n"), + call(f"SnippetSPDXID: {snippet.spdx_id}\n"), + call(f"SnippetFromFileSPDXID: {snippet.file_spdx_id}\n"), + call("SnippetByteRange: 1:2\n"), + call("SnippetLineRange: 3:4\n"), + call(f"SnippetLicenseConcluded: {snippet.license_concluded}\n"), + call(f"LicenseInfoInSnippet: {snippet.license_info_in_snippet[0]}\n"), + call(f"LicenseInfoInSnippet: {snippet.license_info_in_snippet[1]}\n"), + call(f"LicenseInfoInSnippet: {snippet.license_info_in_snippet[2]}\n"), + call(f"SnippetLicenseComments: {snippet.license_comment}\n"), + call(f"SnippetCopyrightText: {snippet.copyright_text}\n"), + call(f"SnippetComment: {snippet.comment}\n"), + call(f"SnippetName: {snippet.name}\n"), + call(f"SnippetAttributionText: {snippet.attribution_texts[0]}\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py index b6d3b4ece..6aeda9030 100644 --- a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py @@ -3,12 +3,17 @@ # SPDX-License-Identifier: Apache-2.0 import os +from unittest.mock import MagicMock, call, mock_open, patch import pytest +from spdx.model.file import File +from spdx.model.package import Package +from spdx.model.relationship import Relationship, RelationshipType +from spdx.model.snippet import Snippet from spdx.parser.tagvalue import tagvalue_parser -from spdx.writer.tagvalue.tagvalue_writer import write_document_to_file -from tests.spdx.fixtures import document_fixture +from spdx.writer.tagvalue.tagvalue_writer import write_document, write_document_to_file +from tests.spdx.fixtures import checksum_fixture, document_fixture @pytest.fixture @@ -26,3 +31,97 @@ def test_write_tag_value(temporary_file_path: str): parsed_document = tagvalue_parser.parse_from_file(temporary_file_path) assert parsed_document == document + + +def test_correct_order_of_elements(): + packages = [ + Package(name="Test Package A", spdx_id="SPDXRef-Package-A", download_location=""), + Package(name="Test Package B", spdx_id="SPDXRef-Package-B", download_location=""), + ] + files = [ + File(name="Test File A", spdx_id="SPDXRef-File-A", checksums=[checksum_fixture()]), + File(name="Test File B", spdx_id="SPDXRef-File-B", checksums=[checksum_fixture()]), + ] + snippets = [ + Snippet(spdx_id="SPDXRef-Snippet-A", file_spdx_id="DocumentRef-External:SPDXRef-File", byte_range=(1, 2)), + Snippet(spdx_id="SPDXRef-Snippet-B", file_spdx_id="SPDXRef-File-A", byte_range=(1, 2)), + Snippet(spdx_id="SPDXRef-Snippet-C", file_spdx_id="SPDXRef-File-B", byte_range=(3, 4)), + ] + relationships = [Relationship("SPDXRef-Package-A", RelationshipType.CONTAINS, "SPDXRef-File-B")] + document = document_fixture( + files=files, + packages=packages, + snippets=snippets, + relationships=relationships, + annotations=[], + extracted_licensing_info=[], + ) + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_document(document, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call("## Document Information\n"), + call("SPDXVersion: SPDX-2.3\n"), + call("DataLicense: CC0-1.0\n"), + call("SPDXID: SPDXRef-DOCUMENT\n"), + call("DocumentName: documentName\n"), + call("DocumentNamespace: https://some.namespace\n"), + call("DocumentComment: documentComment\n"), + call("\n## External Document References\n"), + call( + "ExternalDocumentRef: DocumentRef-external https://namespace.com " + "SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n" + ), + call("\n"), + call("## Creation Information\n"), + call("LicenseListVersion: 3.19\n"), + call("Creator: Person: creatorName (some@mail.com)\n"), + call("Created: 2022-12-01T00:00:00Z\n"), + call("CreatorComment: creatorComment\n"), + call("\n"), + call("## Snippet Information\n"), + call("SnippetSPDXID: SPDXRef-Snippet-A\n"), + call("SnippetFromFileSPDXID: DocumentRef-External:SPDXRef-File\n"), + call("SnippetByteRange: 1:2\n"), + call("\n"), + call("## File Information\n"), + call("FileName: Test File A\n"), + call("SPDXID: SPDXRef-File-A\n"), + call("FileChecksum: SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), + call("\n"), + call("## Snippet Information\n"), + call("SnippetSPDXID: SPDXRef-Snippet-B\n"), + call("SnippetFromFileSPDXID: SPDXRef-File-A\n"), + call("SnippetByteRange: 1:2\n"), + call("\n"), + call("## Package Information\n"), + call("PackageName: Test Package A\n"), + call("SPDXID: SPDXRef-Package-A\n"), + call("PackageDownloadLocation: \n"), + call("FilesAnalyzed: True\n"), + call("\n"), + call("## File Information\n"), + call("FileName: Test File B\n"), + call("SPDXID: SPDXRef-File-B\n"), + call("FileChecksum: SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), + call("\n"), + call("## Snippet Information\n"), + call("SnippetSPDXID: SPDXRef-Snippet-C\n"), + call("SnippetFromFileSPDXID: SPDXRef-File-B\n"), + call("SnippetByteRange: 3:4\n"), + call("\n"), + call("## Package Information\n"), + call("PackageName: Test Package B\n"), + call("SPDXID: SPDXRef-Package-B\n"), + call("PackageDownloadLocation: \n"), + call("FilesAnalyzed: True\n"), + call("\n"), + call("\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py index b6b36a81a..4d2446213 100644 --- a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py @@ -1,9 +1,15 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +import pytest + +from spdx.model.actor import ActorType from spdx.model.relationship import RelationshipType -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import scan_relationships -from tests.spdx.fixtures import file_fixture, package_fixture, relationship_fixture +from spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import scan_relationships, write_actor +from tests.spdx.fixtures import actor_fixture, file_fixture, package_fixture, relationship_fixture def test_scan_relationships(): @@ -31,3 +37,26 @@ def test_scan_relationships(): assert relationships_to_write == [] assert contained_files_by_package_id == {first_package_spdx_id: files, second_package_spdx_id: files} + + +@pytest.mark.parametrize( + "element_to_write, expected_calls", + [ + (actor_fixture(), [call("ActorTest: Person: actorName (some@mail.com)\n")]), + ( + actor_fixture(actor_type=ActorType.ORGANIZATION, name="organizationName"), + [call("ActorTest: Organization: organizationName (some@mail.com)\n")], + ), + (actor_fixture(actor_type=ActorType.TOOL, name="toolName", email=None), [call("ActorTest: Tool: toolName\n")]), + (SpdxNoAssertion(), [call("ActorTest: NOASSERTION\n")]), + ], +) +def test_write_actor(element_to_write, expected_calls): + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_actor("ActorTest", element_to_write, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls(expected_calls)