13 namespace Fossology\Lib\Data {
16 const SPDXREF_PREFIX =
"LicenseRef-";
22 if (!function_exists(
'uuid_create')) {
23 define(
'UUID_TYPE_TIME', 1);
24 function uuid_create($type = UUID_TYPE_TIME)
26 return sprintf(
'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
27 mt_rand(0, 0xffff), mt_rand(0, 0xffff),
29 mt_rand(0, 0x0fff) | 0x4000,
30 mt_rand(0, 0x3fff) | 0x8000,
31 mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
36 require_once __DIR__ .
'/../agent/reportgenerator.php';
44 function assert_test($name, $condition, $detail =
'')
46 global $passed, $failed;
48 echo
" PASS: $name\n";
51 echo
" FAIL: $name" . ($detail ?
" -- $detail" :
"") .
"\n";
56 echo
"\n=== CycloneDX BomReportGenerator Tests ===\n\n";
58 echo
"Test 1: License with text content\n";
61 'name' =>
'MIT License',
62 'url' =>
'https://opensource.org/licenses/MIT',
63 'textContent' => base64_encode(
'Permission is hereby granted, free of charge...'),
64 'textContentType' =>
'text/plain'
66 $result = $generator->createLicense($licenseData);
68 assert_test(
'License has license key', isset($result[
'license']));
69 assert_test(
'License id is MIT', $result[
'license'][
'id'] ===
'MIT');
70 assert_test(
'License has url', $result[
'license'][
'url'] ===
'https://opensource.org/licenses/MIT');
71 assert_test(
'License has text block', isset($result[
'license'][
'text']));
72 assert_test(
'License text has content', isset($result[
'license'][
'text'][
'content']));
73 assert_test(
'License text contentType is text/plain', $result[
'license'][
'text'][
'contentType'] ===
'text/plain');
74 assert_test(
'License text encoding is base64', $result[
'license'][
'text'][
'encoding'] ===
'base64');
75 assert_test(
'License text decodes correctly',
76 base64_decode($result[
'license'][
'text'][
'content']) ===
'Permission is hereby granted, free of charge...');
80 echo
"Test 2: License without text content\n";
81 $licenseDataNoText = array(
83 'name' =>
'Apache License 2.0',
84 'url' =>
'https://www.apache.org/licenses/LICENSE-2.0'
86 $result2 = $generator->createLicense($licenseDataNoText);
88 assert_test(
'License has license key', isset($result2[
'license']));
89 assert_test(
'License id is Apache-2.0', $result2[
'license'][
'id'] ===
'Apache-2.0');
90 assert_test(
'License has NO text block', !isset($result2[
'license'][
'text']));
94 echo
"Test 3: LicenseRef expression\n";
96 'id' =>
'LicenseRef-fossology-custom',
97 'name' =>
'Custom License'
99 $result3 = $generator->createLicense($licenseRef);
101 assert_test(
'LicenseRef returns expression', isset($result3[
'expression']));
102 assert_test(
'Expression value correct', $result3[
'expression'] ===
'LicenseRef-fossology-custom');
103 assert_test(
'LicenseRef has NO license key', !isset($result3[
'license']));
107 echo
"Test 4: Component with copyright\n";
108 $componentData = array(
110 'name' =>
'openssl-3.0.12.tar.gz',
112 'scope' =>
'required',
113 'mimeType' =>
'application/gzip',
114 'copyright' =>
"Copyright 2000-2023 The OpenSSL Project Authors\nCopyright 1995-2023 Eric A. Young, Tim J. Hudson",
116 $generator->createHash(
'SHA-1',
'abc123'),
117 $generator->createHash(
'MD5',
'def456')
119 'licenses' => array($result)
121 $comp = $generator->createComponent($componentData);
123 assert_test(
'Component has type', $comp[
'type'] ===
'library');
124 assert_test(
'Component has name', $comp[
'name'] ===
'openssl-3.0.12.tar.gz');
125 assert_test(
'Component has bom-ref', $comp[
'bom-ref'] ===
'42');
126 assert_test(
'Component has copyright', isset($comp[
'copyright']));
127 assert_test(
'Copyright contains OpenSSL', strpos($comp[
'copyright'],
'OpenSSL') !==
false);
128 assert_test(
'Copyright contains both entries', strpos($comp[
'copyright'],
'Eric A. Young') !==
false);
129 assert_test(
'Component has hashes', count($comp[
'hashes']) === 2);
130 assert_test(
'Component has licenses', count($comp[
'licenses']) === 1);
134 echo
"Test 5: Component without copyright\n";
135 $compNoCopyright = $generator->createComponent(array(
137 'name' =>
'README.md'
140 assert_test(
'Component without copyright has no copyright key', !isset($compNoCopyright[
'copyright']));
144 echo
"Test 6: Full report structure\n";
145 $fileComponent = $generator->createComponent(array(
147 'name' =>
'src/main.c',
148 'bomref' =>
'42-100',
149 'copyright' =>
'Copyright 2023 Test Author',
150 'hashes' => array($generator->createHash(
'SHA-1',
'aaa')),
151 'licenses' => array($result)
154 $report = $generator->generateReport(array(
155 'tool-version' =>
'4.5.0',
156 'maincomponent' => $comp,
157 'components' => array($fileComponent)
160 assert_test(
'Report bomFormat is CycloneDX', $report[
'bomFormat'] ===
'CycloneDX');
161 assert_test(
'Report specVersion is 1.4', $report[
'specVersion'] ===
'1.4');
162 assert_test(
'Report version is integer 1', $report[
'version'] === 1);
163 assert_test(
'Report has serialNumber', !empty($report[
'serialNumber']));
164 assert_test(
'Report has metadata', isset($report[
'metadata']));
165 assert_test(
'Report metadata has tools', isset($report[
'metadata'][
'tools']));
166 assert_test(
'Tool vendor is FOSSology', $report[
'metadata'][
'tools'][0][
'vendor'] ===
'FOSSology');
167 assert_test(
'Tool version is 4.5.0', $report[
'metadata'][
'tools'][0][
'version'] ===
'4.5.0');
168 assert_test(
'Metadata has main component', isset($report[
'metadata'][
'component']));
169 assert_test(
'Main component has copyright', isset($report[
'metadata'][
'component'][
'copyright']));
170 assert_test(
'Report has components array', is_array($report[
'components']));
171 assert_test(
'Components count is 1', count($report[
'components']) === 1);
172 assert_test(
'File component has copyright', isset($report[
'components'][0][
'copyright']));
173 assert_test(
'Report has no externalReferences when not provided', !isset($report[
'externalReferences']));
177 echo
"Test 7: JSON validity\n";
178 $json = json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
179 assert_test(
'JSON encodes without error', json_last_error() === JSON_ERROR_NONE);
180 assert_test(
'JSON is not empty', strlen($json) > 100);
182 $decoded = json_decode($json,
true);
183 assert_test(
'JSON round-trip preserves bomFormat', $decoded[
'bomFormat'] ===
'CycloneDX');
184 assert_test(
'JSON round-trip preserves license text',
185 isset($decoded[
'metadata'][
'component'][
'licenses'][0][
'license'][
'text'][
'content']));
189 echo
"Test 8: Component with version\n";
190 $compWithVersion = $generator->createComponent(array(
193 'version' =>
'1.36.1'
196 assert_test(
'Component has version', isset($compWithVersion[
'version']));
197 assert_test(
'Version value is correct', $compWithVersion[
'version'] ===
'1.36.1');
199 $compNoVersion = $generator->createComponent(array(
204 assert_test(
'Empty version is not included', !isset($compNoVersion[
'version']));
208 echo
"Test 9: Component with purl\n";
209 $compWithPurl = $generator->createComponent(array(
212 'purl' =>
'pkg:deb/debian/busybox@1.36.1'
215 assert_test(
'Component has purl', isset($compWithPurl[
'purl']));
216 assert_test(
'PURL value is correct', $compWithPurl[
'purl'] ===
'pkg:deb/debian/busybox@1.36.1');
218 $compNoPurl = $generator->createComponent(array(
223 assert_test(
'Empty purl is not included', !isset($compNoPurl[
'purl']));
227 echo
"Test 10: Component with description\n";
228 $compWithDesc = $generator->createComponent(array(
231 'description' =>
'Open source SSL/TLS toolkit'
234 assert_test(
'Component has description', isset($compWithDesc[
'description']));
235 assert_test(
'Description value is correct', $compWithDesc[
'description'] ===
'Open source SSL/TLS toolkit');
237 $compNoDesc = $generator->createComponent(array(
242 assert_test(
'Empty description is not included', !isset($compNoDesc[
'description']));
246 echo
"Test 11: Component with properties (acknowledgements + comments)\n";
247 $compWithProps = $generator->createComponent(array(
249 'name' =>
'src/main.c',
250 'acknowledgements' =>
"Thanks to the OpenSSL team\nThanks to contributors",
251 'comments' =>
'Reviewed and approved by legal team'
254 assert_test(
'Component has properties', isset($compWithProps[
'properties']));
255 assert_test(
'Properties has 2 entries', count($compWithProps[
'properties']) === 2);
256 assert_test(
'First property is acknowledgement',
257 $compWithProps[
'properties'][0][
'name'] ===
'fossology:acknowledgement');
258 assert_test(
'Acknowledgement value is correct',
259 strpos($compWithProps[
'properties'][0][
'value'],
'OpenSSL') !==
false);
260 assert_test(
'Second property is comment',
261 $compWithProps[
'properties'][1][
'name'] ===
'fossology:comment');
262 assert_test(
'Comment value is correct',
263 $compWithProps[
'properties'][1][
'value'] ===
'Reviewed and approved by legal team');
265 $compOnlyAck = $generator->createComponent(array(
267 'name' =>
'src/util.c',
268 'acknowledgements' =>
'Thanks to maintainers',
271 assert_test(
'Only acknowledgement property when comments empty', count($compOnlyAck[
'properties']) === 1);
272 assert_test(
'Single property is acknowledgement',
273 $compOnlyAck[
'properties'][0][
'name'] ===
'fossology:acknowledgement');
275 $compNoProps = $generator->createComponent(array(
277 'name' =>
'src/test.c',
278 'acknowledgements' =>
'',
281 assert_test(
'No properties when both empty', !isset($compNoProps[
'properties']));
285 echo
"Test 12: Component with externalReferences\n";
286 $compWithExtRef = $generator->createComponent(array(
289 'externalReferences' => [
290 [
'type' =>
'distribution',
'url' =>
'https://www.openssl.org/source/openssl-3.0.12.tar.gz'],
291 [
'type' =>
'vcs',
'url' =>
'https://github.com/openssl/openssl']
295 assert_test(
'Component has externalReferences', isset($compWithExtRef[
'externalReferences']));
296 assert_test(
'ExternalReferences has 2 entries', count($compWithExtRef[
'externalReferences']) === 2);
297 assert_test(
'First ref type is distribution',
298 $compWithExtRef[
'externalReferences'][0][
'type'] ===
'distribution');
299 assert_test(
'First ref url is correct',
300 $compWithExtRef[
'externalReferences'][0][
'url'] ===
'https://www.openssl.org/source/openssl-3.0.12.tar.gz');
302 $compNoExtRef = $generator->createComponent(array(
305 'externalReferences' => []
307 assert_test(
'Empty externalReferences is not included', !isset($compNoExtRef[
'externalReferences']));
311 echo
"Test 13: Full report with externalReferences\n";
312 $reportWithExtRef = $generator->generateReport(array(
313 'tool-version' =>
'4.5.0',
314 'maincomponent' => $comp,
315 'components' => array($fileComponent),
316 'externalReferences' => [
317 [
'type' =>
'website',
'url' =>
'https://www.fossology.org']
321 assert_test(
'Report has externalReferences', isset($reportWithExtRef[
'externalReferences']));
322 assert_test(
'Report externalReferences has 1 entry', count($reportWithExtRef[
'externalReferences']) === 1);
323 assert_test(
'Report externalRef type is website',
324 $reportWithExtRef[
'externalReferences'][0][
'type'] ===
'website');
328 echo
"Test 14: Full component with all new fields\n";
329 $fullComp = $generator->createComponent(array(
332 'version' =>
'1.36.1',
334 'scope' =>
'required',
335 'mimeType' =>
'application/x-tar',
336 'copyright' =>
'Copyright 2023 BusyBox Authors',
337 'description' =>
'Tiny utilities for small and embedded systems',
338 'purl' =>
'pkg:generic/busybox@1.36.1',
339 'hashes' => array($generator->createHash(
'SHA-256',
'abc123def456')),
340 'licenses' => array($result),
341 'externalReferences' => [
342 [
'type' =>
'vcs',
'url' =>
'https://git.busybox.net/busybox/']
344 'acknowledgements' =>
'Thanks to Denys Vlasenko',
345 'comments' =>
'Primary build dependency'
348 assert_test(
'Full component has type', $fullComp[
'type'] ===
'library');
349 assert_test(
'Full component has name', $fullComp[
'name'] ===
'busybox');
350 assert_test(
'Full component has version', $fullComp[
'version'] ===
'1.36.1');
351 assert_test(
'Full component has bom-ref', $fullComp[
'bom-ref'] ===
'99');
352 assert_test(
'Full component has purl', $fullComp[
'purl'] ===
'pkg:generic/busybox@1.36.1');
353 assert_test(
'Full component has description',
354 $fullComp[
'description'] ===
'Tiny utilities for small and embedded systems');
355 assert_test(
'Full component has copyright', isset($fullComp[
'copyright']));
356 assert_test(
'Full component has hashes', count($fullComp[
'hashes']) === 1);
357 assert_test(
'Full component has licenses', count($fullComp[
'licenses']) === 1);
358 assert_test(
'Full component has externalReferences', count($fullComp[
'externalReferences']) === 1);
359 assert_test(
'Full component has properties', count($fullComp[
'properties']) === 2);
363 echo
"=== Results ===\n";
364 echo
"Passed: $passed | Failed: $failed\n";
367 echo
"\nSome tests FAILED!\n";
370 echo
"\nAll tests passed!\n";