Skip to content

Commit a19e025

Browse files
feat(CSAF2.1): #365 add recommended test 6.2.45
1 parent 5894082 commit a19e025

File tree

8 files changed

+8869
-2
lines changed

8 files changed

+8869
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,6 @@ The following tests are not yet implemented and therefore missing:
354354
- Recommended Test 6.2.42
355355
- Recommended Test 6.2.43
356356
- Recommended Test 6.2.44
357-
- Recommended Test 6.2.45
358357
- Recommended Test 6.2.46
359358
360359
**Informative Tests**
@@ -461,6 +460,7 @@ export const recommendedTest_6_2_17: DocumentTest
461460
export const recommendedTest_6_2_18: DocumentTest
462461
export const recommendedTest_6_2_22: DocumentTest
463462
export const recommendedTest_6_2_23: DocumentTest
463+
export const recommendedTest_6_2_45: DocumentTest
464464
```
465465
466466
[(back to top)](#bsi-csaf-validator-lib)

csaf_2_1/recommendedTests.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ export { recommendedTest_6_2_27 } from './recommendedTests/recommendedTest_6_2_2
3232
export { recommendedTest_6_2_28 } from './recommendedTests/recommendedTest_6_2_28.js'
3333
export { recommendedTest_6_2_29 } from './recommendedTests/recommendedTest_6_2_29.js'
3434
export { recommendedTest_6_2_38 } from './recommendedTests/recommendedTest_6_2_38.js'
35+
export { recommendedTest_6_2_45 } from './recommendedTests/recommendedTest_6_2_45.js'
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import Ajv from 'ajv/dist/jtd.js'
2+
import { parse, validate } from 'license-expressions'
3+
import license_information from '../../lib/license/license_information.js'
4+
5+
const ajv = new Ajv()
6+
7+
/*
8+
This is the jtd schema that needs to match the input document so that the
9+
test is activated. If this schema doesn't match, it normally means that the input
10+
document does not validate against the csaf JSON schema or optional fields that
11+
the test checks are not present.
12+
*/
13+
const inputSchema = /** @type {const} */ ({
14+
additionalProperties: true,
15+
properties: {
16+
document: {
17+
additionalProperties: true,
18+
properties: {
19+
license_expression: {
20+
type: 'string',
21+
},
22+
},
23+
},
24+
},
25+
})
26+
27+
const ABOUT_CODE_LICENSE_REF_PREFIX = 'LicenseRef-scancode-'
28+
29+
const ABOUT_CODE_LICENSE_KEYS = new Set(
30+
license_information.licenses
31+
.filter((license) => license.source === 'aboutCode')
32+
.map((license) => license.license_key)
33+
)
34+
35+
const SPDX_LICENSE_KEYS = new Set(
36+
license_information.licenses
37+
.filter((license) => license.source === 'spdx')
38+
.map((license) => license.license_key)
39+
)
40+
41+
const validateSchema = ajv.compile(inputSchema)
42+
43+
/**
44+
* Check whether the license identifier ref is listed in Aboutcode's "ScanCode LicenseDB"
45+
* @param {string} licenseRefToCheck
46+
* @return {boolean}
47+
*/
48+
function isAboutCodeLicense(licenseRefToCheck) {
49+
if (!licenseRefToCheck.startsWith(ABOUT_CODE_LICENSE_REF_PREFIX)) {
50+
return false
51+
} else {
52+
const licenseKey = licenseRefToCheck.substring(
53+
ABOUT_CODE_LICENSE_REF_PREFIX.length
54+
)
55+
return ABOUT_CODE_LICENSE_KEYS.has(licenseKey)
56+
}
57+
}
58+
59+
/**
60+
* Recursively checks if a parsed license expression has not existing licenses
61+
*
62+
* @param {import('license-expressions').ParsedSpdxExpression} parsedExpression - The parsed license expression
63+
* @returns {Array<string>} all not existing licenses
64+
*/
65+
function allNonExistingLicenses(parsedExpression) {
66+
/** @type {Array<string>} */
67+
const nonExistingLicenses = []
68+
if (
69+
'licenseRef' in parsedExpression &&
70+
!isAboutCodeLicense(parsedExpression.licenseRef)
71+
) {
72+
nonExistingLicenses.push(parsedExpression.licenseRef)
73+
}
74+
75+
if (
76+
'license' in parsedExpression &&
77+
!SPDX_LICENSE_KEYS.has(parsedExpression.license)
78+
) {
79+
nonExistingLicenses.push(parsedExpression.license)
80+
}
81+
82+
if (
83+
'exception' in parsedExpression &&
84+
parsedExpression.exception &&
85+
!SPDX_LICENSE_KEYS.has(parsedExpression.exception)
86+
) {
87+
nonExistingLicenses.push(parsedExpression.exception)
88+
}
89+
90+
// If it's a conjunction, check both sides
91+
if ('conjunction' in parsedExpression) {
92+
nonExistingLicenses.push(...allNonExistingLicenses(parsedExpression.left))
93+
nonExistingLicenses.push(...allNonExistingLicenses(parsedExpression.right))
94+
}
95+
96+
return nonExistingLicenses
97+
}
98+
99+
/**
100+
* Checks if a license expression string contains Non-Existing licenses
101+
*
102+
* @param {string} licenseToCheck - The license expression to check
103+
* @returns {Array<string>} all Non-Existing licenses
104+
*/
105+
export function allNonExistingLicensesInLicenseString(licenseToCheck) {
106+
const parseResult = parse(licenseToCheck)
107+
return allNonExistingLicenses(parseResult)
108+
}
109+
110+
/**
111+
* It MUST be tested that all license identifier and exceptions used exist.
112+
* This SHALL be tested for the SPDX license list and Aboutcode's "ScanCode LicenseDB".
113+
* The test MAY be skipped for other license inventorying entities.
114+
*
115+
* @param {unknown} doc
116+
*/
117+
export function recommendedTest_6_2_45(doc) {
118+
/*
119+
The `ctx` variable holds the state that is accumulated during the test run and is
120+
finally returned by the function.
121+
*/
122+
const ctx = {
123+
warnings:
124+
/** @type {Array<{ instancePath: string; message: string }>} */ ([]),
125+
}
126+
127+
if (!validateSchema(doc)) {
128+
return ctx
129+
}
130+
131+
const licenseToCheck = doc.document.license_expression
132+
133+
const nonExistingLicenseIdentifier =
134+
allNonExistingLicensesInLicenseString(licenseToCheck)
135+
136+
nonExistingLicenseIdentifier.forEach((licenseKey) => {
137+
ctx.warnings.push({
138+
instancePath: '/document/license_expression',
139+
message:
140+
`License identifier ${licenseKey} does not exist in` +
141+
`SPDX license list and Aboutcode's ScanCode LicenseDB`,
142+
})
143+
})
144+
145+
return ctx
146+
}

0 commit comments

Comments
 (0)