Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/test_2.x_js.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# docs: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions

name: CT CDX-1.x JavaScript

on:
push:
branches: ['master', 'main', '2.0-dev']
pull_request:
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

defaults:
run:
working-directory: tools/src/test/js/schema-v2

# https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token
permissions: {}

jobs:
test_js:
timeout-minutes: 30
runs-on: ubuntu-latest
steps:
- name: Checkout
# see https://github.com/actions/checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup Node.js
# see https://github.com/actions/setup-node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '26.x'
package-manager-cache: false
- name: Install Dependencies
run: npm install
- name: Run test
run: npm test
41 changes: 41 additions & 0 deletions .github/workflows/test_2.x_php.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# docs: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions

name: CT CDX-2.x PHP

on:
push:
branches: ['master', 'main', '2.0-dev']
pull_request:
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

defaults:
run:
working-directory: tools/src/test/php/schema-v2

# https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token
permissions: {}

jobs:
test_php:
timeout-minutes: 30
runs-on: ubuntu-latest
steps:
- name: Checkout
# see https://github.com/actions/checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup PHP
# see https://github.com/shivammathur/setup-php
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
php-version: "8.5"
tools: composer:v2
- name: Install Dependencies
run: composer install
- name: Run test
run: composer run test
4 changes: 2 additions & 2 deletions schema/2.0/model/cyclonedx-cryptography-2.0.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
}
},
"algorithmFamily": {
"$ref": "../cryptography-defs.schema.json#/definitions/algorithmFamiliesEnum",
"$ref": "../../cryptography-defs.schema.json#/definitions/algorithmFamiliesEnum",
Comment thread
jkowalleck marked this conversation as resolved.
Outdated
"title": "Algorithm Family",
"description": "A valid algorithm family identifier. If specified, this value shall be one of the enumeration of valid algorithm Family identifiers defined in the `cryptography-defs.schema.json` subschema.",
"examples": [
Expand All @@ -94,7 +94,7 @@
"description": "An identifier for the parameter set of the cryptographic algorithm. Examples: in AES128, '128' identifies the key length in bits, in SHA256, '256' identifies the digest length, '128' in SHAKE128 identifies its maximum security level in bits, and 'SHA2-128s' identifies a parameter set used in SLH-DSA (FIPS205)."
},
"ellipticCurve": {
"$ref": "../cryptography-defs.schema.json#/definitions/ellipticCurvesEnum",
"$ref": "../../cryptography-defs.schema.json#/definitions/ellipticCurvesEnum",
Comment thread
jkowalleck marked this conversation as resolved.
Outdated
"title": "Elliptic Curve",
"description": "The specific underlying Elliptic Curve (EC) definition employed which is an indicator of the level of security strength, performance and complexity. If specified, this value shall be one of the enumeration of valid elliptic curves identifiers defined in the `cryptography-defs.schema.json` subschema."
},
Expand Down
2 changes: 1 addition & 1 deletion schema/2.0/model/cyclonedx-license-2.0.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
"description": "An identifier which can be used to reference the license elsewhere in the BOM. Every `bom-ref` must be unique within the BOM.\nValue SHOULD not start with the BOM-Link intro 'urn:cdx:' to avoid conflicts with BOM-Links."
},
"id": {
"$ref": "../spdx.schema.json",
"$ref": "../../spdx.schema.json",
Comment thread
jkowalleck marked this conversation as resolved.
Outdated
"title": "License ID (SPDX)",
"description": "A valid SPDX license identifier. If specified, this value must be one of the enumeration of valid SPDX license identifiers defined in the spdx.schema.json (or spdx.xml) subschema which is synchronized with the official SPDX license list.",
"examples": ["Apache-2.0"]
Expand Down
2 changes: 2 additions & 0 deletions tools/src/test/js/schema-v2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/node_modules/
/package-lock.json
Empty file.
21 changes: 21 additions & 0 deletions tools/src/test/js/schema-v2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# validate the JSON schema with `AJV`

uses https://ajv.js.org/
for validation of a schema.

## requirements

* node >=26.0

## setup

```shell
npm install
```

## usage

```shell
npm test
```

135 changes: 135 additions & 0 deletions tools/src/test/js/schema-v2/json-schema-functional-tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
"use strict";

/**
* validate all test data for a given version of CycloneDX.
* call the script via `node <this-file> -v <CDX-version>`
*/

import {readFile, stat} from 'node:fs/promises'
import {dirname, basename, join} from 'node:path'
import {fileURLToPath} from 'node:url'
import {parseArgs} from 'node:util'


import Ajv2020 from "ajv/dist/2020.js"
import draft7MetaSchema from "ajv/dist/refs/json-schema-draft-07.json" with {type: "json"};

import addFormats from "ajv-formats"
import addFormats2019 from "ajv-formats-draft2019"
import {glob} from 'glob'


const _thisDir = dirname(fileURLToPath(import.meta.url))

// region config

const testschemaVersion = (parseArgs({options: {v: {type: 'string', short: 'v'}}}).values.v ?? '').trim()
const schemaRootDir = join(_thisDir, '..', '..', '..', '..', '..', 'schema')
const schemaDir = join(schemaRootDir, testschemaVersion)
const schemaFile = join(schemaDir, `cyclonedx-${testschemaVersion}.schema.json`)
const schemaModelDir = join(schemaDir, `model`)
const testdataDir = join(_thisDir, '..', '..', 'resources', testschemaVersion)

const schemaGlob = '*.schema.json'

if (testschemaVersion.length === 0) {
throw new Error('missing testschemaVersion. expected via argument')
}
console.debug('DEBUG | testschemaVersion = ', testschemaVersion);

if (!await stat(schemaFile).then(s => s.isFile()).catch(() => false)) {
throw new Error(`missing schemaFile: ${schemaFile}`);
}
console.debug('DEBUG | schemaFile = ', schemaFile);

if (!await stat(schemaModelDir).then(s => s.isDirectory()).catch(() => false)) {
throw new Error(`missing schemaModelDir: ${schemaModelDir}`);
}
console.debug('DEBUG | schemaModelDir = ', schemaModelDir);


if (!await stat(testdataDir).then(s => s.isDirectory()).catch(() => false)) {
throw new Error(`missing testdataDir: ${testdataDir}`);
}
console.debug('DEBUG | testdataDir = ', testdataDir);

// endregion config

// region validator

const [spdxSchema, cryptoDefsSchema, bomSchema, bomSchemaModules] = await Promise.all([
readFile(join(schemaRootDir, 'spdx.schema.json'), 'utf-8').then(JSON.parse),
readFile(join(schemaRootDir, 'cryptography-defs.schema.json'), 'utf-8').then(JSON.parse),
readFile(schemaFile, 'utf-8').then(JSON.parse),
glob(join(schemaModelDir, schemaGlob)).then(fs => Promise.all(fs.map(
f => readFile(f, 'utf-8').then(JSON.parse).then(s => [basename(f), s])
)))
])

const ajv = new Ajv2020({
// not running in strict - this is done in the linter-test already
strict: false,
validateFormats: true,
addUsedSchema: false,
});
ajv.addMetaSchema(draft7MetaSchema);
ajv.addSchema(spdxSchema)
ajv.addSchema(spdxSchema, 'https://cyclonedx.org/schema/spdx.schema.json')
ajv.addSchema(cryptoDefsSchema)
ajv.addSchema(cryptoDefsSchema, 'https://cyclonedx.org/schema/cryptography-defs.schema.json')
for (const [f, s] of bomSchemaModules) {
console.log('DEBUG | addSchema', f)
ajv.addSchema(s)
}

addFormats(ajv)
addFormats2019(ajv, {formats: ['idn-email']})
// there is just no working implementation for format "iri-reference"
// see https://github.com/luzlab/ajv-formats-draft2019/issues/22
ajv.addFormat('iri-reference', true)

const _ajvValidate = ajv.compile(bomSchema)


/**
* @param {string} file - file path to validate
* @return {null|object}
*/
async function validateFile(file) {
return _ajvValidate(JSON.parse(await readFile(file, 'utf-8')))
? null
: _ajvValidate.errors
}

// endregion validator

let errCnt = 0

for (const file of await glob(join(testdataDir, 'valid-*.json'))) {
console.log('\ntest', file, '...');
const validationErrors = await validateFile(file)
if (validationErrors === null) {
console.log('OK.')
} else {
++errCnt;
console.error('ERROR: Unexpected validation error for file:', file);
console.error(validationErrors)
}
}

for (const file of await glob(join(testdataDir, 'invalid-*.json'))) {
console.log('\ntest', file, '...');
const validationErrors = await validateFile(file)
if (validationErrors === null) {
++errCnt;
console.error('ERROR: Missing expected validation error for file:', file);

} else {
console.log('OK.')
}
}


// Exit statuses should be in the range 0 to 254.
// The status 0 is used to terminate the program successfully.
process.exitCode = Math.min(errCnt, 254)
22 changes: 22 additions & 0 deletions tools/src/test/js/schema-v2/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"private": true,
"type": "module",
"engines": {
"node": ">=20.0"
},
"dependencies": {
"ajv": "^8.20",
"ajv-formats": "^3.0.1",
"ajv-formats-draft2019": "^1.6.1",
"glob": "^13.0.0",
"npm-run-all2": "^9.0.3"
},
"devDependencies": {
"@types/node": ">=26.0"
},
"scripts": {
"test": "run-s \"test:*\"",
"test:json-schema-functional": "run-s \"test:json-schema-functional:*\"",
"test:json-schema-functional:2.0": "node -- json-schema-functional-tests.js -v 2.0"
}
}
2 changes: 2 additions & 0 deletions tools/src/test/php/schema-v2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/vendor/
/composer.lock
Empty file.
21 changes: 21 additions & 0 deletions tools/src/test/php/schema-v2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# validate the JSON schema with `opis/json-schema`

uses https://opis.io/json-schema/2.x/php-loader.html
for validation of a schema

## requirements

* php >= 8.4
* php composer

## setup

```shell
composer update
```

## usage

```shell
composer run test
```
22 changes: 22 additions & 0 deletions tools/src/test/php/schema-v2/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"minimum-stability": "stable",
"require": {
"php": "^8.4",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"opis/json-schema": "2.6.0"
},
"require-dev": {
"roave/security-advisories": "dev-latest"
},
"scripts": {
"test": [
"@test:json-schema-functional"
],
"test:json-schema-functional": [
"@test:json-schema-functional:2.0"
],
"test:json-schema-functional:2.0": "@php -f json-schema-functional-tests.php -- -v 2.0 --"
}
}
Loading
Loading