Skip to content

Commit 0f1ff2c

Browse files
add SPDX generation test
This is to ensure that both the new and old versions of the SPDX writers satisfy the same tests. This uses an Image instance that was generated during the call of "tern report -i golang:1.12-alpine" Signed-off-by: Armin Tänzer <armin.taenzer@tngtech.com>
1 parent 9f80484 commit 0f1ff2c

File tree

6 files changed

+92
-5
lines changed

6 files changed

+92
-5
lines changed

tern/formats/spdx/spdxjson/generator.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import json
1111
import logging
12+
import pickle
1213

1314
from tern.formats.spdx.spdx import SPDX
1415
from tern.formats.spdx import spdx_common
@@ -158,6 +159,7 @@ def generate(self, image_obj_list, print_inclusive=False):
158159
# images. Hence we will assume only one image is analyzed and the
159160
# input is a list of length 1
160161
image_obj = image_obj_list[0]
162+
161163
template = SPDX()
162164
report = get_document_dict(image_obj, template)
163165

tern/formats/spdx_new/layer_helpers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def get_layer_dict(layer_obj: ImageLayer) -> Tuple[SpdxPackage, List[Relationshi
109109
The analyzed files will go in a separate part of the document."""
110110

111111
comment = get_layer_package_comment(layer_obj)
112-
verification_code = get_layer_verification_code(layer_obj)
112+
verification_code = get_layer_verification_code(layer_obj) if layer_obj.files_analyzed else None
113113

114114
layer_licenses = get_layer_licenses(layer_obj)
115115
license_info_from_files = []
@@ -128,7 +128,7 @@ def get_layer_dict(layer_obj: ImageLayer) -> Tuple[SpdxPackage, List[Relationshi
128128
file_name=layer_obj.tar_file,
129129
download_location=SpdxNone(),
130130
files_analyzed=bool(layer_obj.files_analyzed),
131-
verification_code=verification_code if bool(layer_obj.files_analyzed) else None,
131+
verification_code=verification_code,
132132
checksums=[get_layer_checksum(layer_obj)],
133133
license_concluded=SpdxNoAssertion(),
134134
license_declared=SpdxNoAssertion(),

tern/formats/spdx_new/make_spdx_model.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from tern.formats.spdx_new.constants import DOCUMENT_ID, DOCUMENT_NAME, SPDX_VERSION, DATA_LICENSE, DOCUMENT_COMMENT, \
1818
LICENSE_LIST_VERSION, CREATOR_NAME, DOCUMENT_NAME_SNAPSHOT, DOCUMENT_NAMESPACE_SNAPSHOT
1919
from tern.formats.spdx_new.file_helpers import get_layer_files_list
20-
from tern.formats.spdx_new.general_helpers import get_current_timestamp, get_uuid, get_image_spdxref
20+
from tern.formats.spdx_new.general_helpers import get_current_timestamp, get_uuid
2121
from tern.classes.image import Image
2222
from tern.formats.spdx.spdx import SPDX
2323
from tern.formats.spdx_new.file_helpers import get_files_list
@@ -51,7 +51,6 @@ def make_spdx_model(image_obj_list: List[Image]) -> Document:
5151
data_license=DATA_LICENSE,
5252
document_comment=DOCUMENT_COMMENT,
5353
)
54-
describes_relationship = Relationship(DOCUMENT_ID, RelationshipType.DESCRIBES, get_image_spdxref(image_obj))
5554
packages = [get_image_dict(image_obj, template)]
5655
image_layer_relationships = get_image_layer_relationships(image_obj)
5756

@@ -69,7 +68,7 @@ def make_spdx_model(image_obj_list: List[Image]) -> Document:
6968
creation_info=creation_info,
7069
packages=packages,
7170
files=files,
72-
relationships=[describes_relationship] + image_layer_relationships + layer_file_relationships,
71+
relationships=image_layer_relationships + layer_file_relationships,
7372
extracted_licensing_info=extracted_licensing_info
7473
)
7574

tests/golang_test_image.pkl

2.19 MB
Binary file not shown.

tests/large_tern_scan_image.pkl

3.76 MB
Binary file not shown.

tests/test_spdx_generation.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import json
2+
import os
3+
import pickle
4+
import unittest
5+
6+
from tern.classes.docker_image import DockerImage
7+
from tern.formats.spdx.spdxjson.generator import SpdxJSON
8+
9+
10+
class TestSPDXGeneration(unittest.TestCase):
11+
test_package = {
12+
"name": "alpine-keys",
13+
"SPDXID": "SPDXRef-alpine-keys-2.1-r2",
14+
"versionInfo": "2.1-r2",
15+
"supplier": "Organization: Alpine Linux",
16+
"downloadLocation": "NOASSERTION",
17+
"filesAnalyzed": False,
18+
"licenseConcluded": "NOASSERTION",
19+
"licenseDeclared": "MIT",
20+
"copyrightText": "NONE",
21+
"externalRefs": [
22+
{
23+
"referenceCategory": "PACKAGE-MANAGER",
24+
"referenceLocator": "pkg:apk/alpine/alpine-keys@2.1-r2?arch=x86_64",
25+
"referenceType": "purl"
26+
}
27+
],
28+
"comment": "alpine-keys:\n\twarning: No metadata for key: copyright\n\twarning: No metadata for key: download_url\n\twarning: No metadata for key: checksum\n\twarning: No metadata for key: pkg_licenses\n\twarning: No metadata for key: pkg_format\n\twarning: No metadata for key: src_name\n\twarning: No metadata for key: src_version\n"
29+
}
30+
31+
test_describes_relationship = {
32+
"spdxElementId": "SPDXRef-DOCUMENT",
33+
"relatedSpdxElement": "SPDXRef-golang-1.12-alpine",
34+
"relationshipType": "DESCRIBES"
35+
}
36+
37+
test_contains_relationship = {
38+
"spdxElementId": "SPDXRef-5216338b40",
39+
"relatedSpdxElement": "SPDXRef-alpine-keys-2.1-r2",
40+
"relationshipType": "CONTAINS"
41+
}
42+
43+
test_has_prerequisite_relationship = {
44+
"spdxElementId": "SPDXRef-3957f7032f",
45+
"relatedSpdxElement": "SPDXRef-7306dca01e",
46+
"relationshipType": "HAS_PREREQUISITE"
47+
}
48+
49+
test_extracted_licensing_info = {
50+
"extractedText": "MPL-2.0 GPL-2.0-or-later",
51+
"licenseId": "LicenseRef-f30c02b"
52+
}
53+
54+
def test_spdx_generation_from_pickled_image(self):
55+
json_file_path = "spdx_test.json"
56+
test_image_file_path = "large_tern_scan_image.pkl" # generated during "tern report -i golang:1.12-alpine"
57+
with open(test_image_file_path, "rb") as f:
58+
image = pickle.load(f)
59+
image_list = [image]
60+
61+
json_as_string = SpdxJSON().generate(image_list)
62+
with open(json_file_path, "w") as f:
63+
f.write(json_as_string)
64+
65+
with open(json_file_path, "r") as f:
66+
json_dict = json.load(f)
67+
assert json_dict["SPDXID"] == "SPDXRef-DOCUMENT"
68+
assert json_dict["spdxVersion"] == "SPDX-2.2"
69+
assert len(json_dict["packages"]) == 21
70+
assert self.test_package in json_dict["packages"]
71+
assert len(json_dict["relationships"]) == 25
72+
assert self.test_describes_relationship in json_dict["relationships"]
73+
assert self.test_contains_relationship in json_dict["relationships"]
74+
assert self.test_has_prerequisite_relationship in json_dict["relationships"]
75+
assert len(json_dict["hasExtractedLicensingInfos"]) == 4
76+
assert self.test_extracted_licensing_info in json_dict["hasExtractedLicensingInfos"]
77+
78+
os.remove(json_file_path)
79+
80+
81+
def test_spdx_generation_from_docker_image(self):
82+
docker_image = DockerImage('vmware/tern@sha256:20b32a9a20752aa1ad7582c6'
83+
'67704fda9f004cc4bfd8601fac7f2656c7567bb4')
84+
85+
json_as_string = SpdxJSON().generate([docker_image])
86+
i = 0

0 commit comments

Comments
 (0)