Skip to content

Commit

Permalink
chore: adapt runTest.js script to allow csaf 2.1 tests
Browse files Browse the repository at this point in the history
  • Loading branch information
domachine committed Mar 3, 2025
1 parent 57ea438 commit d46843a
Showing 1 changed file with 117 additions and 35 deletions.
152 changes: 117 additions & 35 deletions scripts/runTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,126 @@
/**
* @file Script to validate JSON files against given tests
*
* Usage: node <script-path>.js json/file/path.json mandatoryTest_6_1_1
* Usage: node <script-path>.js -f <json-file-path> -t <test-name> [-c <csaf-version>]
*
* `mandatoryTest_6_1_1` is a sample here. You can insert any test name from lib/mandatoryTests.js,
* `lib/optionalTests.js`, `lib/schemaTests.js` and `lib/schemaTests.js`.
* -f <json-file-path>
* Specifies the path to the csaf json file to validate the given test against.
*
* -t <test-name>
* Specifies the test(s) to run. The values that you can pass here depend on the value
* of the `-c` option which specifies the used csaf version. If you use 2.0 here you
* can insert any test name from `mandatoryTests.js`, `optionalTests.js`,
* `informativeTests.js` and `schemaTests.js`.
* If you use 2.1 here you can insert any test name from `csaf_2_1/mandatoryTests.js`,
* `csaf_2_1/optionalTests.js`, `csaf_2_1/informativeTests.js` and `csaf_2_1/schemaTests.js`.
* Some presets are also allowed such as `mandatory`, `optional`, `informative`,
* `schema` and `base`.
*
* -c <csaf-version> (default: 2.0)
* Specifies the csaf version to use. The currently allowed versions are `2.0` (the default)
* and `2.1`.
*/

import { readFile } from 'fs/promises'
import * as schemaTests from '../schemaTests.js'
import * as mandatoryTests from '../mandatoryTests.js'
import * as optionalTests from '../optionalTests.js'
import * as informativeTests from '../informativeTests.js'
import validate from '../validate.js'
import { parseArgs } from 'node:util'
import assert from 'node:assert'

/**
* Types a function that can lazily load a set of tests. This is used to speed up the script
* by avoiding to load unused test sets.
*
* @typedef {() => Promise<Record<string, import('../lib/shared/types.js').DocumentTest>>} DocumentTestLoader
*/

/**
* This is the main function that reads the file, executes the resolved test
* and logs the result.
*
* @param {object} ctx
* @param {DocumentTestLoader} ctx.schemaTests
* @param {DocumentTestLoader} ctx.mandatoryTests
* @param {DocumentTestLoader} ctx.optionalTests
* @param {DocumentTestLoader} ctx.informativeTests
* @param {object} params
* @param {string} params.testName
* @param {string} params.filePath
*/
const main = async (
{ informativeTests, mandatoryTests, optionalTests, schemaTests },
{ testName, filePath }
) => {
const json = JSON.parse(await readFile(filePath, { encoding: 'utf-8' }))

const matchingTests =
testName === 'mandatory'
? Object.values(await mandatoryTests())
: testName === 'optional'
? Object.values(await optionalTests())
: testName === 'informative'
? Object.values(await informativeTests())
: testName === 'schema'
? Object.values(await schemaTests())
: testName === 'base'
? Object.values(await schemaTests()).concat(
Object.values(await mandatoryTests())
)
: Object.values(await mandatoryTests())
.concat(Object.values(await optionalTests()))
.concat(Object.values(await informativeTests()))
.concat(Object.values(await schemaTests()))
.filter((t) => t.name === testName)

if (!matchingTests.length)
throw new Error(`No test matching "${testName}" found`)
const result = await validate(matchingTests, json)
process.exitCode = result.isValid ? 0 : 1
console.log(JSON.stringify(result, null, 2))
}

const { values: cliOptions } = parseArgs({
options: {
file: {
type: 'string',
short: 'f',
},
'csaf-version': {
type: 'string',
short: 'c',
default: '2.0',
},
test: {
type: 'string',
short: 't',
},
},
})

const filePath = cliOptions.file
const testName = cliOptions.test
assert(filePath)
assert(testName)

const [, , filePath, testName] = process.argv

const json = JSON.parse(await readFile(filePath, { encoding: 'utf-8' }))

const matchingTests =
testName === 'mandatory'
? Object.values(mandatoryTests)
: testName === 'optional'
? Object.values(optionalTests)
: testName === 'informative'
? Object.values(informativeTests)
: testName === 'schema'
? Object.values(schemaTests)
: testName === 'base'
? Object.values(schemaTests).concat(Object.values(mandatoryTests))
: /** @type {Array<import('../lib/shared/types.js').DocumentTest>} */ (
Object.values(mandatoryTests)
)
.concat(Object.values(optionalTests))
.concat(Object.values(informativeTests))
.concat(Object.values(schemaTests))
.filter((t) => t.name === testName)

if (!matchingTests.length)
throw new Error(`No test matching "${testName}" found`)
const result = await validate(matchingTests, json)
process.exitCode = result.isValid ? 0 : 1
console.log(JSON.stringify(result, null, 2))
if (cliOptions['csaf-version'] === '2.0') {
await main(
{
mandatoryTests: () => import('../mandatoryTests.js'),
informativeTests: () => import('../informativeTests.js'),
optionalTests: () => import('../optionalTests.js'),
schemaTests: () => import('../schemaTests.js'),
},
{ filePath, testName }
)
} else if (cliOptions['csaf-version'] === '2.1') {
await main(
{
mandatoryTests: () => import('../csaf_2_1/mandatoryTests.js'),
informativeTests: () => import('../csaf_2_1/informativeTests.js'),
optionalTests: () => import('../csaf_2_1/optionalTests.js'),
schemaTests: () => import('../csaf_2_1/schemaTests.js'),
},
{ filePath, testName }
)
} else {
throw new Error('Unknown CSAF version')
}

0 comments on commit d46843a

Please sign in to comment.