xref: /aosp_15_r20/build/make/tools/sbom/sbom_data_test.py (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
1*9e94795aSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*9e94795aSAndroid Build Coastguard Worker#
3*9e94795aSAndroid Build Coastguard Worker# Copyright (C) 2023 The Android Open Source Project
4*9e94795aSAndroid Build Coastguard Worker#
5*9e94795aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*9e94795aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*9e94795aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*9e94795aSAndroid Build Coastguard Worker#
9*9e94795aSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
10*9e94795aSAndroid Build Coastguard Worker#
11*9e94795aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*9e94795aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*9e94795aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*9e94795aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*9e94795aSAndroid Build Coastguard Worker# limitations under the License.
16*9e94795aSAndroid Build Coastguard Worker
17*9e94795aSAndroid Build Coastguard Workerimport hashlib
18*9e94795aSAndroid Build Coastguard Workerimport unittest
19*9e94795aSAndroid Build Coastguard Workerimport sbom_data
20*9e94795aSAndroid Build Coastguard Worker
21*9e94795aSAndroid Build Coastguard WorkerBUILD_FINGER_PRINT = 'build_finger_print'
22*9e94795aSAndroid Build Coastguard WorkerSUPPLIER_GOOGLE = 'Organization: Google'
23*9e94795aSAndroid Build Coastguard WorkerSUPPLIER_UPSTREAM = 'Organization: upstream'
24*9e94795aSAndroid Build Coastguard Worker
25*9e94795aSAndroid Build Coastguard WorkerSPDXID_PREBUILT_PACKAGE1 = 'SPDXRef-PREBUILT-package1'
26*9e94795aSAndroid Build Coastguard WorkerSPDXID_PREBUILT_PACKAGE2 = 'SPDXRef-PREBUILT-package2'
27*9e94795aSAndroid Build Coastguard WorkerSPDXID_SOURCE_PACKAGE1 = 'SPDXRef-SOURCE-package1'
28*9e94795aSAndroid Build Coastguard WorkerSPDXID_UPSTREAM_PACKAGE1 = 'SPDXRef-UPSTREAM-package1'
29*9e94795aSAndroid Build Coastguard Worker
30*9e94795aSAndroid Build Coastguard WorkerSPDXID_FILE1 = 'SPDXRef-file1'
31*9e94795aSAndroid Build Coastguard WorkerSPDXID_FILE2 = 'SPDXRef-file2'
32*9e94795aSAndroid Build Coastguard WorkerSPDXID_FILE3 = 'SPDXRef-file3'
33*9e94795aSAndroid Build Coastguard WorkerSPDXID_FILE4 = 'SPDXRef-file4'
34*9e94795aSAndroid Build Coastguard Worker
35*9e94795aSAndroid Build Coastguard WorkerSPDXID_LICENSE1 = "SPDXRef-License-1"
36*9e94795aSAndroid Build Coastguard WorkerSPDXID_LICENSE2 = "SPDXRef-License-2"
37*9e94795aSAndroid Build Coastguard Worker
38*9e94795aSAndroid Build Coastguard Worker
39*9e94795aSAndroid Build Coastguard Workerclass SBOMDataTest(unittest.TestCase):
40*9e94795aSAndroid Build Coastguard Worker
41*9e94795aSAndroid Build Coastguard Worker  def setUp(self):
42*9e94795aSAndroid Build Coastguard Worker    # SBOM of a product
43*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc = sbom_data.Document(name='test doc',
44*9e94795aSAndroid Build Coastguard Worker                                       namespace='http://www.google.com/sbom/spdx/android',
45*9e94795aSAndroid Build Coastguard Worker                                       creators=[SUPPLIER_GOOGLE],
46*9e94795aSAndroid Build Coastguard Worker                                       created='2023-03-31T22:17:58Z',
47*9e94795aSAndroid Build Coastguard Worker                                       describes=sbom_data.SPDXID_PRODUCT)
48*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_external_ref(
49*9e94795aSAndroid Build Coastguard Worker        sbom_data.DocumentExternalReference(id='DocumentRef-external_doc_ref',
50*9e94795aSAndroid Build Coastguard Worker                                            uri='external_doc_uri',
51*9e94795aSAndroid Build Coastguard Worker                                            checksum='SHA1: 1234567890'))
52*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_package(
53*9e94795aSAndroid Build Coastguard Worker        sbom_data.Package(id=sbom_data.SPDXID_PRODUCT,
54*9e94795aSAndroid Build Coastguard Worker                          name=sbom_data.PACKAGE_NAME_PRODUCT,
55*9e94795aSAndroid Build Coastguard Worker                          download_location=sbom_data.VALUE_NONE,
56*9e94795aSAndroid Build Coastguard Worker                          supplier=SUPPLIER_GOOGLE,
57*9e94795aSAndroid Build Coastguard Worker                          version=BUILD_FINGER_PRINT,
58*9e94795aSAndroid Build Coastguard Worker                          files_analyzed=True,
59*9e94795aSAndroid Build Coastguard Worker                          verification_code='',
60*9e94795aSAndroid Build Coastguard Worker                          file_ids=[SPDXID_FILE1, SPDXID_FILE2, SPDXID_FILE3, SPDXID_FILE4]))
61*9e94795aSAndroid Build Coastguard Worker
62*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_package(
63*9e94795aSAndroid Build Coastguard Worker        sbom_data.Package(id=sbom_data.SPDXID_PLATFORM,
64*9e94795aSAndroid Build Coastguard Worker                          name=sbom_data.PACKAGE_NAME_PLATFORM,
65*9e94795aSAndroid Build Coastguard Worker                          download_location=sbom_data.VALUE_NONE,
66*9e94795aSAndroid Build Coastguard Worker                          supplier=SUPPLIER_GOOGLE,
67*9e94795aSAndroid Build Coastguard Worker                          version=BUILD_FINGER_PRINT,
68*9e94795aSAndroid Build Coastguard Worker                          ))
69*9e94795aSAndroid Build Coastguard Worker
70*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_package(
71*9e94795aSAndroid Build Coastguard Worker        sbom_data.Package(id=SPDXID_PREBUILT_PACKAGE1,
72*9e94795aSAndroid Build Coastguard Worker                          name='Prebuilt package1',
73*9e94795aSAndroid Build Coastguard Worker                          download_location=sbom_data.VALUE_NONE,
74*9e94795aSAndroid Build Coastguard Worker                          supplier=SUPPLIER_GOOGLE,
75*9e94795aSAndroid Build Coastguard Worker                          version=BUILD_FINGER_PRINT,
76*9e94795aSAndroid Build Coastguard Worker                          ))
77*9e94795aSAndroid Build Coastguard Worker
78*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_package(
79*9e94795aSAndroid Build Coastguard Worker        sbom_data.Package(id=SPDXID_SOURCE_PACKAGE1,
80*9e94795aSAndroid Build Coastguard Worker                          name='Source package1',
81*9e94795aSAndroid Build Coastguard Worker                          download_location=sbom_data.VALUE_NONE,
82*9e94795aSAndroid Build Coastguard Worker                          supplier=SUPPLIER_GOOGLE,
83*9e94795aSAndroid Build Coastguard Worker                          version=BUILD_FINGER_PRINT,
84*9e94795aSAndroid Build Coastguard Worker                          external_refs=[sbom_data.PackageExternalRef(
85*9e94795aSAndroid Build Coastguard Worker                              category=sbom_data.PackageExternalRefCategory.SECURITY,
86*9e94795aSAndroid Build Coastguard Worker                              type=sbom_data.PackageExternalRefType.cpe22Type,
87*9e94795aSAndroid Build Coastguard Worker                              locator='cpe:/a:jsoncpp_project:jsoncpp:1.9.4')]
88*9e94795aSAndroid Build Coastguard Worker                          ))
89*9e94795aSAndroid Build Coastguard Worker
90*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_package(
91*9e94795aSAndroid Build Coastguard Worker        sbom_data.Package(id=SPDXID_UPSTREAM_PACKAGE1,
92*9e94795aSAndroid Build Coastguard Worker                          name='Upstream package1',
93*9e94795aSAndroid Build Coastguard Worker                          supplier=SUPPLIER_UPSTREAM,
94*9e94795aSAndroid Build Coastguard Worker                          version='1.1',
95*9e94795aSAndroid Build Coastguard Worker                          ))
96*9e94795aSAndroid Build Coastguard Worker
97*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_SOURCE_PACKAGE1,
98*9e94795aSAndroid Build Coastguard Worker                                                          relationship=sbom_data.RelationshipType.VARIANT_OF,
99*9e94795aSAndroid Build Coastguard Worker                                                          id2=SPDXID_UPSTREAM_PACKAGE1))
100*9e94795aSAndroid Build Coastguard Worker
101*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.files.append(
102*9e94795aSAndroid Build Coastguard Worker        sbom_data.File(id=SPDXID_FILE1, name='/bin/file1',
103*9e94795aSAndroid Build Coastguard Worker                       checksum='SHA1: 356a192b7913b04c54574d18c28d46e6395428ab'))  # sha1 hash of 1
104*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.files.append(
105*9e94795aSAndroid Build Coastguard Worker        sbom_data.File(id=SPDXID_FILE2, name='/bin/file2',
106*9e94795aSAndroid Build Coastguard Worker                       checksum='SHA1: da4b9237bacccdf19c0760cab7aec4a8359010b0'))  # sha1 hash of 2
107*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.files.append(
108*9e94795aSAndroid Build Coastguard Worker        sbom_data.File(id=SPDXID_FILE3, name='/bin/file3',
109*9e94795aSAndroid Build Coastguard Worker                       checksum='SHA1: 77de68daecd823babbb58edb1c8e14d7106e83bb'))  # sha1 hash of 3
110*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.files.append(
111*9e94795aSAndroid Build Coastguard Worker        sbom_data.File(id=SPDXID_FILE4, name='file4.a',
112*9e94795aSAndroid Build Coastguard Worker                       checksum='SHA1: 1b6453892473a467d07372d45eb05abc2031647a'))  # sha1 of 4
113*9e94795aSAndroid Build Coastguard Worker
114*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_FILE1,
115*9e94795aSAndroid Build Coastguard Worker                                                          relationship=sbom_data.RelationshipType.GENERATED_FROM,
116*9e94795aSAndroid Build Coastguard Worker                                                          id2=sbom_data.SPDXID_PLATFORM))
117*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_FILE2,
118*9e94795aSAndroid Build Coastguard Worker                                                          relationship=sbom_data.RelationshipType.GENERATED_FROM,
119*9e94795aSAndroid Build Coastguard Worker                                                          id2=SPDXID_PREBUILT_PACKAGE1))
120*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_FILE3,
121*9e94795aSAndroid Build Coastguard Worker                                                          relationship=sbom_data.RelationshipType.GENERATED_FROM,
122*9e94795aSAndroid Build Coastguard Worker                                                          id2=SPDXID_SOURCE_PACKAGE1
123*9e94795aSAndroid Build Coastguard Worker                                                          ))
124*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_FILE1,
125*9e94795aSAndroid Build Coastguard Worker                                                          relationship=sbom_data.RelationshipType.STATIC_LINK,
126*9e94795aSAndroid Build Coastguard Worker                                                          id2=SPDXID_FILE4
127*9e94795aSAndroid Build Coastguard Worker                                                          ))
128*9e94795aSAndroid Build Coastguard Worker
129*9e94795aSAndroid Build Coastguard Worker  def test_package_verification_code(self):
130*9e94795aSAndroid Build Coastguard Worker    checksums = []
131*9e94795aSAndroid Build Coastguard Worker    for file in self.sbom_doc.files:
132*9e94795aSAndroid Build Coastguard Worker      checksums.append(file.checksum.split(': ')[1])
133*9e94795aSAndroid Build Coastguard Worker      checksums.sort()
134*9e94795aSAndroid Build Coastguard Worker    h = hashlib.sha1()
135*9e94795aSAndroid Build Coastguard Worker    h.update(''.join(checksums).encode(encoding='utf-8'))
136*9e94795aSAndroid Build Coastguard Worker    expected_package_verification_code = h.hexdigest()
137*9e94795aSAndroid Build Coastguard Worker
138*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.generate_packages_verification_code()
139*9e94795aSAndroid Build Coastguard Worker    self.assertEqual(expected_package_verification_code, self.sbom_doc.packages[0].verification_code)
140*9e94795aSAndroid Build Coastguard Worker
141*9e94795aSAndroid Build Coastguard Worker  def test_add_package_(self):
142*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_package(sbom_data.Package(id=SPDXID_PREBUILT_PACKAGE2,
143*9e94795aSAndroid Build Coastguard Worker                                                name='Prebuilt package2',
144*9e94795aSAndroid Build Coastguard Worker                                                download_location=sbom_data.VALUE_NONE,
145*9e94795aSAndroid Build Coastguard Worker                                                supplier=SUPPLIER_GOOGLE,
146*9e94795aSAndroid Build Coastguard Worker                                                version=BUILD_FINGER_PRINT,
147*9e94795aSAndroid Build Coastguard Worker                                                ))
148*9e94795aSAndroid Build Coastguard Worker    p = next((p for p in self.sbom_doc.packages if p.id == SPDXID_PREBUILT_PACKAGE2), None)
149*9e94795aSAndroid Build Coastguard Worker    self.assertNotEqual(p, None)
150*9e94795aSAndroid Build Coastguard Worker    self.assertEqual(p.declared_license_ids, [])
151*9e94795aSAndroid Build Coastguard Worker
152*9e94795aSAndroid Build Coastguard Worker    # Add same package with license 1
153*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_package(sbom_data.Package(id=SPDXID_PREBUILT_PACKAGE2,
154*9e94795aSAndroid Build Coastguard Worker                                                name='Prebuilt package2',
155*9e94795aSAndroid Build Coastguard Worker                                                download_location=sbom_data.VALUE_NONE,
156*9e94795aSAndroid Build Coastguard Worker                                                supplier=SUPPLIER_GOOGLE,
157*9e94795aSAndroid Build Coastguard Worker                                                version=BUILD_FINGER_PRINT,
158*9e94795aSAndroid Build Coastguard Worker                                                declared_license_ids=[SPDXID_LICENSE1]
159*9e94795aSAndroid Build Coastguard Worker                                                ))
160*9e94795aSAndroid Build Coastguard Worker    self.assertEqual(p.declared_license_ids, [SPDXID_LICENSE1])
161*9e94795aSAndroid Build Coastguard Worker
162*9e94795aSAndroid Build Coastguard Worker    # Add same package with license 2
163*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_package(sbom_data.Package(id=SPDXID_PREBUILT_PACKAGE2,
164*9e94795aSAndroid Build Coastguard Worker                                                name='Prebuilt package2',
165*9e94795aSAndroid Build Coastguard Worker                                                download_location=sbom_data.VALUE_NONE,
166*9e94795aSAndroid Build Coastguard Worker                                                supplier=SUPPLIER_GOOGLE,
167*9e94795aSAndroid Build Coastguard Worker                                                version=BUILD_FINGER_PRINT,
168*9e94795aSAndroid Build Coastguard Worker                                                declared_license_ids=[SPDXID_LICENSE2]
169*9e94795aSAndroid Build Coastguard Worker                                                ))
170*9e94795aSAndroid Build Coastguard Worker    self.assertEqual(p.declared_license_ids, [SPDXID_LICENSE1, SPDXID_LICENSE2])
171*9e94795aSAndroid Build Coastguard Worker
172*9e94795aSAndroid Build Coastguard Worker    # Add same package with license 2 again
173*9e94795aSAndroid Build Coastguard Worker    self.sbom_doc.add_package(sbom_data.Package(id=SPDXID_PREBUILT_PACKAGE2,
174*9e94795aSAndroid Build Coastguard Worker                                                name='Prebuilt package2',
175*9e94795aSAndroid Build Coastguard Worker                                                download_location=sbom_data.VALUE_NONE,
176*9e94795aSAndroid Build Coastguard Worker                                                supplier=SUPPLIER_GOOGLE,
177*9e94795aSAndroid Build Coastguard Worker                                                version=BUILD_FINGER_PRINT,
178*9e94795aSAndroid Build Coastguard Worker                                                declared_license_ids=[SPDXID_LICENSE2]
179*9e94795aSAndroid Build Coastguard Worker                                                ))
180*9e94795aSAndroid Build Coastguard Worker    self.assertEqual(p.declared_license_ids, [SPDXID_LICENSE1, SPDXID_LICENSE2])
181*9e94795aSAndroid Build Coastguard Worker
182*9e94795aSAndroid Build Coastguard Worker
183*9e94795aSAndroid Build Coastguard Workerif __name__ == '__main__':
184*9e94795aSAndroid Build Coastguard Worker  unittest.main(verbosity=2)
185