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.7', $report[
'specVersion'] ===
'1.7');
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 manufacturer is FOSSology',
167 $report[
'metadata'][
'tools'][
'components'][0][
'manufacturer'][
'name'] ===
'FOSSology');
168 assert_test(
'Tool has no vendor', !isset($report[
'metadata'][
'tools'][
'components'][0][
'vendor']));
169 assert_test(
'Tool version is 4.5.0', $report[
'metadata'][
'tools'][
'components'][0][
'version'] ===
'4.5.0');
170 assert_test(
'Metadata has main component', isset($report[
'metadata'][
'component']));
171 assert_test(
'Main component has copyright', isset($report[
'metadata'][
'component'][
'copyright']));
172 assert_test(
'Report has components array', is_array($report[
'components']));
173 assert_test(
'Components count is 1', count($report[
'components']) === 1);
174 assert_test(
'File component has copyright', isset($report[
'components'][0][
'copyright']));
175 assert_test(
'Report has no externalReferences when not provided', !isset($report[
'externalReferences']));
179 echo
"Test 7: JSON validity\n";
180 $json = json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
181 assert_test(
'JSON encodes without error', json_last_error() === JSON_ERROR_NONE);
182 assert_test(
'JSON is not empty', strlen($json) > 100);
184 $decoded = json_decode($json,
true);
185 assert_test(
'JSON round-trip preserves bomFormat', $decoded[
'bomFormat'] ===
'CycloneDX');
186 assert_test(
'JSON round-trip preserves license text',
187 isset($decoded[
'metadata'][
'component'][
'licenses'][0][
'license'][
'text'][
'content']));
191 echo
"Test 8: Component with version\n";
192 $compWithVersion = $generator->createComponent(array(
195 'version' =>
'1.36.1'
198 assert_test(
'Component has version', isset($compWithVersion[
'version']));
199 assert_test(
'Version value is correct', $compWithVersion[
'version'] ===
'1.36.1');
201 $compNoVersion = $generator->createComponent(array(
206 assert_test(
'Empty version is not included', !isset($compNoVersion[
'version']));
210 echo
"Test 9: Component with purl\n";
211 $compWithPurl = $generator->createComponent(array(
214 'purl' =>
'pkg:deb/debian/busybox@1.36.1'
217 assert_test(
'Component has purl', isset($compWithPurl[
'purl']));
218 assert_test(
'PURL value is correct', $compWithPurl[
'purl'] ===
'pkg:deb/debian/busybox@1.36.1');
220 $compNoPurl = $generator->createComponent(array(
225 assert_test(
'Empty purl is not included', !isset($compNoPurl[
'purl']));
229 echo
"Test 10: Component with description\n";
230 $compWithDesc = $generator->createComponent(array(
233 'description' =>
'Open source SSL/TLS toolkit'
236 assert_test(
'Component has description', isset($compWithDesc[
'description']));
237 assert_test(
'Description value is correct', $compWithDesc[
'description'] ===
'Open source SSL/TLS toolkit');
239 $compNoDesc = $generator->createComponent(array(
244 assert_test(
'Empty description is not included', !isset($compNoDesc[
'description']));
248 echo
"Test 11: Component with properties (acknowledgements + comments)\n";
249 $compWithProps = $generator->createComponent(array(
251 'name' =>
'src/main.c',
252 'acknowledgements' =>
"Thanks to the OpenSSL team\nThanks to contributors",
253 'comments' =>
'Reviewed and approved by legal team'
256 assert_test(
'Component has properties', isset($compWithProps[
'properties']));
257 assert_test(
'Properties has 2 entries', count($compWithProps[
'properties']) === 2);
258 assert_test(
'First property is acknowledgement',
259 $compWithProps[
'properties'][0][
'name'] ===
'fossology:acknowledgement');
260 assert_test(
'Acknowledgement value is correct',
261 strpos($compWithProps[
'properties'][0][
'value'],
'OpenSSL') !==
false);
262 assert_test(
'Second property is comment',
263 $compWithProps[
'properties'][1][
'name'] ===
'fossology:comment');
264 assert_test(
'Comment value is correct',
265 $compWithProps[
'properties'][1][
'value'] ===
'Reviewed and approved by legal team');
267 $compOnlyAck = $generator->createComponent(array(
269 'name' =>
'src/util.c',
270 'acknowledgements' =>
'Thanks to maintainers',
273 assert_test(
'Only acknowledgement property when comments empty', count($compOnlyAck[
'properties']) === 1);
274 assert_test(
'Single property is acknowledgement',
275 $compOnlyAck[
'properties'][0][
'name'] ===
'fossology:acknowledgement');
277 $compNoProps = $generator->createComponent(array(
279 'name' =>
'src/test.c',
280 'acknowledgements' =>
'',
283 assert_test(
'No properties when both empty', !isset($compNoProps[
'properties']));
287 echo
"Test 12: Component with externalReferences\n";
288 $compWithExtRef = $generator->createComponent(array(
291 'externalReferences' => [
292 [
'type' =>
'distribution',
'url' =>
'https://www.openssl.org/source/openssl-3.0.12.tar.gz'],
293 [
'type' =>
'vcs',
'url' =>
'https://github.com/openssl/openssl']
297 assert_test(
'Component has externalReferences', isset($compWithExtRef[
'externalReferences']));
298 assert_test(
'ExternalReferences has 2 entries', count($compWithExtRef[
'externalReferences']) === 2);
299 assert_test(
'First ref type is distribution',
300 $compWithExtRef[
'externalReferences'][0][
'type'] ===
'distribution');
301 assert_test(
'First ref url is correct',
302 $compWithExtRef[
'externalReferences'][0][
'url'] ===
'https://www.openssl.org/source/openssl-3.0.12.tar.gz');
304 $compNoExtRef = $generator->createComponent(array(
307 'externalReferences' => []
309 assert_test(
'Empty externalReferences is not included', !isset($compNoExtRef[
'externalReferences']));
313 echo
"Test 13: Full report with externalReferences\n";
314 $reportWithExtRef = $generator->generateReport(array(
315 'tool-version' =>
'4.5.0',
316 'maincomponent' => $comp,
317 'components' => array($fileComponent),
318 'externalReferences' => [
319 [
'type' =>
'website',
'url' =>
'https://www.fossology.org']
323 assert_test(
'Report has externalReferences', isset($reportWithExtRef[
'externalReferences']));
324 assert_test(
'Report externalReferences has 1 entry', count($reportWithExtRef[
'externalReferences']) === 1);
325 assert_test(
'Report externalRef type is website',
326 $reportWithExtRef[
'externalReferences'][0][
'type'] ===
'website');
330 echo
"Test 14: Full component with all new fields\n";
331 $fullComp = $generator->createComponent(array(
334 'version' =>
'1.36.1',
336 'scope' =>
'required',
337 'mimeType' =>
'application/x-tar',
338 'copyright' =>
'Copyright 2023 BusyBox Authors',
339 'description' =>
'Tiny utilities for small and embedded systems',
340 'purl' =>
'pkg:generic/busybox@1.36.1',
341 'hashes' => array($generator->createHash(
'SHA-256',
'abc123def456')),
342 'licenses' => array($result),
343 'externalReferences' => [
344 [
'type' =>
'vcs',
'url' =>
'https://git.busybox.net/busybox/']
346 'acknowledgements' =>
'Thanks to Denys Vlasenko',
347 'comments' =>
'Primary build dependency'
350 assert_test(
'Full component has type', $fullComp[
'type'] ===
'library');
351 assert_test(
'Full component has name', $fullComp[
'name'] ===
'busybox');
352 assert_test(
'Full component has version', $fullComp[
'version'] ===
'1.36.1');
353 assert_test(
'Full component has bom-ref', $fullComp[
'bom-ref'] ===
'99');
354 assert_test(
'Full component has purl', $fullComp[
'purl'] ===
'pkg:generic/busybox@1.36.1');
355 assert_test(
'Full component has description',
356 $fullComp[
'description'] ===
'Tiny utilities for small and embedded systems');
357 assert_test(
'Full component has copyright', isset($fullComp[
'copyright']));
358 assert_test(
'Full component has hashes', count($fullComp[
'hashes']) === 1);
359 assert_test(
'Full component has licenses', count($fullComp[
'licenses']) === 1);
360 assert_test(
'Full component has externalReferences', count($fullComp[
'externalReferences']) === 1);
361 assert_test(
'Full component has properties', count($fullComp[
'properties']) === 2);
365 echo
"Test 15: LicenseRef expression with bom-ref and acknowledgement\n";
366 $licenseRefWithRef = $generator->createLicense(array(
367 'id' =>
'LicenseRef-fossology-BSD-style',
368 'bom-ref' =>
'lic-scanner-320-42',
369 'acknowledgement' =>
'declared'
372 assert_test(
'Expression value correct',
373 $licenseRefWithRef[
'expression'] ===
'LicenseRef-fossology-BSD-style');
374 assert_test(
'Expression has bom-ref', $licenseRefWithRef[
'bom-ref'] ===
'lic-scanner-320-42');
375 assert_test(
'Expression has acknowledgement', $licenseRefWithRef[
'acknowledgement'] ===
'declared');
376 assert_test(
'Expression has only schema keys',
377 array_keys($licenseRefWithRef) === array(
'expression',
'bom-ref',
'acknowledgement'));
381 echo
"=== Results ===\n";
382 echo
"Passed: $passed | Failed: $failed\n";
385 echo
"\nSome tests FAILED!\n";
388 echo
"\nAll tests passed!\n";