From e58c29700d03cd9683e6c377cdeeb76f1a319ba5 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Thu, 28 Jul 2022 18:35:08 +0200 Subject: [PATCH 01/11] implement `component.components` in model and basic normalization Signed-off-by: Jan Kowalleck --- src/models/component.ts | 3 +++ src/serialize/json/normalize.ts | 3 +++ src/serialize/xml/normalize.ts | 10 +++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/models/component.ts b/src/models/component.ts index 51ca99a55..26b411eb9 100644 --- a/src/models/component.ts +++ b/src/models/component.ts @@ -45,6 +45,7 @@ interface OptionalProperties { swid?: Component['swid'] version?: Component['version'] dependencies?: Component['dependencies'] + components?: Component['components'] cpe?: Component['cpe'] } @@ -65,6 +66,7 @@ export class Component implements Comparable { swid?: SWID version?: string dependencies: BomRefRepository + components: ComponentRepository /** @see bomRef */ readonly #bomRef: BomRef @@ -93,6 +95,7 @@ export class Component implements Comparable { this.version = op.version this.description = op.description this.dependencies = op.dependencies ?? new BomRefRepository() + this.components = op.components ?? new ComponentRepository() this.cpe = op.cpe } diff --git a/src/serialize/json/normalize.ts b/src/serialize/json/normalize.ts index 74d0ab758..2818bca1a 100644 --- a/src/serialize/json/normalize.ts +++ b/src/serialize/json/normalize.ts @@ -270,6 +270,9 @@ export class ComponentNormalizer extends Base { : this._factory.makeForSWID().normalize(data.swid, options), externalReferences: data.externalReferences.size > 0 ? this._factory.makeForExternalReference().normalizeRepository(data.externalReferences, options) + : undefined, + components: data.components.size > 0 + ? this.normalizeRepository(data.components, options) : undefined } : undefined diff --git a/src/serialize/xml/normalize.ts b/src/serialize/xml/normalize.ts index ff19d5dbb..17ffcc211 100644 --- a/src/serialize/xml/normalize.ts +++ b/src/serialize/xml/normalize.ts @@ -335,6 +335,13 @@ export class ComponentNormalizer extends Base { .normalizeRepository(data.externalReferences, options, 'reference') } : undefined + const components: SimpleXml.Element | undefined = data.components.size > 0 + ? { + type: 'element', + name: 'components', + children: this.normalizeRepository(data.components, options, 'component') + } + : undefined return { type: 'element', name: elementName, @@ -357,7 +364,8 @@ export class ComponentNormalizer extends Base { makeOptionalTextElement(data.cpe, 'cpe'), makeOptionalTextElement(data.purl, 'purl'), swid, - extRefs + extRefs, + components ].filter(isNotUndefined) } } From 3a02912e508fb54f9e25b9f11be01ef12ac37c87 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Thu, 28 Jul 2022 18:46:03 +0200 Subject: [PATCH 02/11] test `component.components` model Signed-off-by: Jan Kowalleck --- tests/unit/Models.Component.spec.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/unit/Models.Component.spec.js b/tests/unit/Models.Component.spec.js index 770c487ac..f1c8ebdbe 100644 --- a/tests/unit/Models.Component.spec.js +++ b/tests/unit/Models.Component.spec.js @@ -26,7 +26,7 @@ const { PackageURL } = require('packageurl-js') const { Models: { - Component, + Component, ComponentRepository, BomRef, BomRefRepository, ExternalReferenceRepository, ExternalReference, HashRepository, @@ -57,22 +57,24 @@ suite('Models.Component', () => { assert.strictEqual(component.supplier, undefined) assert.strictEqual(component.swid, undefined) assert.strictEqual(component.version, undefined) + assert.strictEqual(component.components.size, 0) }) test('constructor with OptionalProperties', () => { - const dummnBomRef = new BomRef('testing') + const dummyBomRef = new BomRef('testing') const dummyExtRef = new ExternalReference('../', 'other') const dummyLicense = new NamedLicense('mine') const dummyPurl = new PackageURL('npm', 'ns', 'app', '1.33.7', {}, undefined) const dummySupplier = new OrganizationalEntity({ name: 'dummySupplier' }) const dummySWID = new SWID('my-fake-swid', 'foo-bar') + const subComponent = new Component('library', 'MySubComponent') const component = new Component('application', 'foobar', { author: 'my author', bomRef: 'my-bomref', copyright: 'my copyright', cpe: 'cpe:2.3:a:microsoft:internet_explorer:8.0.6001:beta:*:*:*:*:*:*', - dependencies: new BomRefRepository([dummnBomRef]), + dependencies: new BomRefRepository([dummyBomRef]), description: 'this is a test', externalReferences: new ExternalReferenceRepository([dummyExtRef]), group: 'the-crew', @@ -82,7 +84,8 @@ suite('Models.Component', () => { scope: 'optional', supplier: dummySupplier, swid: dummySWID, - version: '1.33.7' + version: '1.33.7', + components: new ComponentRepository([subComponent]) }) assert.strictEqual(component.type, 'application') @@ -92,7 +95,7 @@ suite('Models.Component', () => { assert.strictEqual(component.copyright, 'my copyright') assert.strictEqual(component.cpe, 'cpe:2.3:a:microsoft:internet_explorer:8.0.6001:beta:*:*:*:*:*:*') assert.strictEqual(component.dependencies.size, 1) - assert.strictEqual(Array.from(component.dependencies)[0], dummnBomRef) + assert.strictEqual(Array.from(component.dependencies)[0], dummyBomRef) assert.strictEqual(component.description, 'this is a test') assert.strictEqual(component.externalReferences.size, 1) assert.strictEqual(Array.from(component.externalReferences)[0], dummyExtRef) @@ -106,5 +109,6 @@ suite('Models.Component', () => { assert.strictEqual(component.supplier, dummySupplier) assert.strictEqual(component.swid, dummySWID) assert.strictEqual(component.version, '1.33.7') + assert.strictEqual(Array.from(component.components)[0], subComponent) }) }) From 600a5015348fc33262e6cb5a0d8169cc2f67d431 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Thu, 28 Jul 2022 19:17:53 +0200 Subject: [PATCH 03/11] test `component.components` normalizer/serializer tests Signed-off-by: Jan Kowalleck --- HISTORY.md | 3 + tests/_data/models.js | 26 ++++++- .../json_sortedLists_spec1.2.json | 23 ++++++ .../json_sortedLists_spec1.3.json | 23 ++++++ .../json_sortedLists_spec1.4.json | 20 +++++ .../xml_sortedLists_spec1.2.json | 74 +++++++++++++++++++ .../xml_sortedLists_spec1.3.json | 74 +++++++++++++++++++ .../xml_sortedLists_spec1.4.json | 59 +++++++++++++++ .../json_complex_spec1.2.json.bin | 23 ++++++ .../json_complex_spec1.3.json.bin | 23 ++++++ .../json_complex_spec1.4.json.bin | 20 +++++ .../xml_complex_spec1.2.xml.bin | 15 ++++ .../xml_complex_spec1.3.xml.bin | 15 ++++ .../xml_complex_spec1.4.xml.bin | 12 +++ .../Serialize.JsonNormalize.test.js | 7 +- .../Serialize.JsonSerialize.test.js | 7 +- .../Serialize.XmlNormalize.test.js | 7 +- .../Serialize.XmlSerialize.test.js | 7 +- 18 files changed, 423 insertions(+), 15 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 0bdf245f9..3a0c4207f 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -5,10 +5,13 @@ All notable changes to this project will be documented in this file. ## unreleased * Added + * Implemented support for nested/bundled components via `bom.component.components`. ([#132] via [#136]) * CycloneDX spec version 1.4 made element `bom.component.version` optional. Therefore, serialization/normalization with this spec version will no longer render this element, when its value is empty. (via [#137], [#138]) +[#132]: https://github.com/CycloneDX/cyclonedx-javascript-library/issues/132 +[#136]: https://github.com/CycloneDX/cyclonedx-javascript-library/pull/136 [#137]: https://github.com/CycloneDX/cyclonedx-javascript-library/pull/137 [#138]: https://github.com/CycloneDX/cyclonedx-javascript-library/pull/138 diff --git a/tests/_data/models.js b/tests/_data/models.js index 2df057f35..828e12d06 100644 --- a/tests/_data/models.js +++ b/tests/_data/models.js @@ -128,7 +128,7 @@ module.exports.createComplexStructure = function () { component.scope = Enums.ComponentScope.Required component.supplier = new Models.OrganizationalEntity({ name: 'Component Supplier' }) component.supplier.url.add(new URL('https://localhost/componentSupplier-B')) - component.supplier.url.add(new URL('https://localhost/componentSupplier-A')) + component.supplier.url.add('https://localhost/componentSupplier-A') component.supplier.contact.add(new Models.OrganizationalContact({ name: 'The quick brown fox' })) component.supplier.contact.add((function (contact) { contact.name = 'Franz' @@ -150,12 +150,12 @@ module.exports.createComplexStructure = function () { return component })(new Models.Component(Enums.ComponentType.Library, 'dummy-component', { version: '1337-beta' }))) - bom.components.add(function (component) { + bom.components.add((function (component) { // interlink everywhere bom.metadata.component.dependencies.add(component.bomRef) bom.components.forEach(c => c.dependencies.add(component.bomRef)) return component - }(new Models.Component(Enums.ComponentType.Library, 'a-component', { + })(new Models.Component(Enums.ComponentType.Library, 'a-component', { bomRef: 'a-component', version: '', // empty string - not undefined dependencies: new Models.BomRefRepository([ @@ -163,5 +163,25 @@ module.exports.createComplexStructure = function () { ]) }))) + bom.components.add((function (component) { + // scenario: + // * `subComponentA` is a bundled dependency, that itself depends on `subComponentB`. + // * `subComponentB` is a transitive bundled dependency. + const subComponentA = new Models.Component(Enums.ComponentType.Library, 'SubComponentA', { + bomRef: `${component.bomRef.value}#SubComponentA` + }) + component.dependencies.add(subComponentA.bomRef) + component.components.add(subComponentA) + const subComponentB = new Models.Component(Enums.ComponentType.Library, 'SubComponentB', { + bomRef: `${component.bomRef.value}#SubComponentB` + }) + subComponentA.dependencies.add(subComponentB.bomRef) + component.components.add(subComponentB) + return component + })(new Models.Component( + Enums.ComponentType.Framework, 'SomeFrameworkBundle', { + bomRef: 'SomeFrameworkBundle' + }))) + return bom } diff --git a/tests/_data/normalizeResults/json_sortedLists_spec1.2.json b/tests/_data/normalizeResults/json_sortedLists_spec1.2.json index 232bfd92e..4fe5f53d7 100644 --- a/tests/_data/normalizeResults/json_sortedLists_spec1.2.json +++ b/tests/_data/normalizeResults/json_sortedLists_spec1.2.json @@ -161,6 +161,26 @@ "comment": "testing" } ] + }, + { + "type": "framework", + "name": "SomeFrameworkBundle", + "version": "", + "bom-ref": "SomeFrameworkBundle", + "components": [ + { + "type": "library", + "name": "SubComponentA", + "version": "", + "bom-ref": "SomeFrameworkBundle#SubComponentA" + }, + { + "type": "library", + "name": "SubComponentB", + "version": "", + "bom-ref": "SomeFrameworkBundle#SubComponentB" + } + ] } ], "dependencies": [ @@ -179,6 +199,9 @@ "a-component", "dummy-component" ] + }, + { + "ref": "SomeFrameworkBundle" } ] } \ No newline at end of file diff --git a/tests/_data/normalizeResults/json_sortedLists_spec1.3.json b/tests/_data/normalizeResults/json_sortedLists_spec1.3.json index 5009f5e82..0c57ba099 100644 --- a/tests/_data/normalizeResults/json_sortedLists_spec1.3.json +++ b/tests/_data/normalizeResults/json_sortedLists_spec1.3.json @@ -161,6 +161,26 @@ "comment": "testing" } ] + }, + { + "type": "framework", + "name": "SomeFrameworkBundle", + "version": "", + "bom-ref": "SomeFrameworkBundle", + "components": [ + { + "type": "library", + "name": "SubComponentA", + "version": "", + "bom-ref": "SomeFrameworkBundle#SubComponentA" + }, + { + "type": "library", + "name": "SubComponentB", + "version": "", + "bom-ref": "SomeFrameworkBundle#SubComponentB" + } + ] } ], "dependencies": [ @@ -179,6 +199,9 @@ "a-component", "dummy-component" ] + }, + { + "ref": "SomeFrameworkBundle" } ] } \ No newline at end of file diff --git a/tests/_data/normalizeResults/json_sortedLists_spec1.4.json b/tests/_data/normalizeResults/json_sortedLists_spec1.4.json index 4970604de..de94eb689 100644 --- a/tests/_data/normalizeResults/json_sortedLists_spec1.4.json +++ b/tests/_data/normalizeResults/json_sortedLists_spec1.4.json @@ -170,6 +170,23 @@ "comment": "testing" } ] + }, + { + "type": "framework", + "name": "SomeFrameworkBundle", + "bom-ref": "SomeFrameworkBundle", + "components": [ + { + "type": "library", + "name": "SubComponentA", + "bom-ref": "SomeFrameworkBundle#SubComponentA" + }, + { + "type": "library", + "name": "SubComponentB", + "bom-ref": "SomeFrameworkBundle#SubComponentB" + } + ] } ], "dependencies": [ @@ -188,6 +205,9 @@ "a-component", "dummy-component" ] + }, + { + "ref": "SomeFrameworkBundle" } ] } \ No newline at end of file diff --git a/tests/_data/normalizeResults/xml_sortedLists_spec1.2.json b/tests/_data/normalizeResults/xml_sortedLists_spec1.2.json index 46a118278..673dd8bbb 100644 --- a/tests/_data/normalizeResults/xml_sortedLists_spec1.2.json +++ b/tests/_data/normalizeResults/xml_sortedLists_spec1.2.json @@ -479,6 +479,72 @@ ] } ] + }, + { + "type": "element", + "name": "component", + "attributes": { + "type": "framework", + "bom-ref": "SomeFrameworkBundle" + }, + "children": [ + { + "type": "element", + "name": "name", + "children": "SomeFrameworkBundle" + }, + { + "type": "element", + "name": "version", + "children": "" + }, + { + "type": "element", + "name": "components", + "children": [ + { + "type": "element", + "name": "component", + "attributes": { + "type": "library", + "bom-ref": "SomeFrameworkBundle#SubComponentA" + }, + "children": [ + { + "type": "element", + "name": "name", + "children": "SubComponentA" + }, + { + "type": "element", + "name": "version", + "children": "" + } + ] + }, + { + "type": "element", + "name": "component", + "attributes": { + "type": "library", + "bom-ref": "SomeFrameworkBundle#SubComponentB" + }, + "children": [ + { + "type": "element", + "name": "name", + "children": "SubComponentB" + }, + { + "type": "element", + "name": "version", + "children": "" + } + ] + } + ] + } + ] } ] }, @@ -532,6 +598,14 @@ } } ] + }, + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle" + }, + "children": [] } ] } diff --git a/tests/_data/normalizeResults/xml_sortedLists_spec1.3.json b/tests/_data/normalizeResults/xml_sortedLists_spec1.3.json index 5d305ab27..2e8735742 100644 --- a/tests/_data/normalizeResults/xml_sortedLists_spec1.3.json +++ b/tests/_data/normalizeResults/xml_sortedLists_spec1.3.json @@ -479,6 +479,72 @@ ] } ] + }, + { + "type": "element", + "name": "component", + "attributes": { + "type": "framework", + "bom-ref": "SomeFrameworkBundle" + }, + "children": [ + { + "type": "element", + "name": "name", + "children": "SomeFrameworkBundle" + }, + { + "type": "element", + "name": "version", + "children": "" + }, + { + "type": "element", + "name": "components", + "children": [ + { + "type": "element", + "name": "component", + "attributes": { + "type": "library", + "bom-ref": "SomeFrameworkBundle#SubComponentA" + }, + "children": [ + { + "type": "element", + "name": "name", + "children": "SubComponentA" + }, + { + "type": "element", + "name": "version", + "children": "" + } + ] + }, + { + "type": "element", + "name": "component", + "attributes": { + "type": "library", + "bom-ref": "SomeFrameworkBundle#SubComponentB" + }, + "children": [ + { + "type": "element", + "name": "name", + "children": "SubComponentB" + }, + { + "type": "element", + "name": "version", + "children": "" + } + ] + } + ] + } + ] } ] }, @@ -532,6 +598,14 @@ } } ] + }, + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle" + }, + "children": [] } ] } diff --git a/tests/_data/normalizeResults/xml_sortedLists_spec1.4.json b/tests/_data/normalizeResults/xml_sortedLists_spec1.4.json index c112ed5e4..863f9e11a 100644 --- a/tests/_data/normalizeResults/xml_sortedLists_spec1.4.json +++ b/tests/_data/normalizeResults/xml_sortedLists_spec1.4.json @@ -508,6 +508,57 @@ ] } ] + }, + { + "type": "element", + "name": "component", + "attributes": { + "type": "framework", + "bom-ref": "SomeFrameworkBundle" + }, + "children": [ + { + "type": "element", + "name": "name", + "children": "SomeFrameworkBundle" + }, + { + "type": "element", + "name": "components", + "children": [ + { + "type": "element", + "name": "component", + "attributes": { + "type": "library", + "bom-ref": "SomeFrameworkBundle#SubComponentA" + }, + "children": [ + { + "type": "element", + "name": "name", + "children": "SubComponentA" + } + ] + }, + { + "type": "element", + "name": "component", + "attributes": { + "type": "library", + "bom-ref": "SomeFrameworkBundle#SubComponentB" + }, + "children": [ + { + "type": "element", + "name": "name", + "children": "SubComponentB" + } + ] + } + ] + } + ] } ] }, @@ -561,6 +612,14 @@ } } ] + }, + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle" + }, + "children": [] } ] } diff --git a/tests/_data/serializeResults/json_complex_spec1.2.json.bin b/tests/_data/serializeResults/json_complex_spec1.2.json.bin index 511c6c211..2948e206a 100644 --- a/tests/_data/serializeResults/json_complex_spec1.2.json.bin +++ b/tests/_data/serializeResults/json_complex_spec1.2.json.bin @@ -161,6 +161,26 @@ "comment": "testing" } ] + }, + { + "type": "framework", + "name": "SomeFrameworkBundle", + "version": "", + "bom-ref": "SomeFrameworkBundle", + "components": [ + { + "type": "library", + "name": "SubComponentA", + "version": "", + "bom-ref": "SomeFrameworkBundle#SubComponentA" + }, + { + "type": "library", + "name": "SubComponentB", + "version": "", + "bom-ref": "SomeFrameworkBundle#SubComponentB" + } + ] } ], "dependencies": [ @@ -179,6 +199,9 @@ "a-component", "dummy-component" ] + }, + { + "ref": "SomeFrameworkBundle" } ] } \ No newline at end of file diff --git a/tests/_data/serializeResults/json_complex_spec1.3.json.bin b/tests/_data/serializeResults/json_complex_spec1.3.json.bin index 82c32eff2..76226a063 100644 --- a/tests/_data/serializeResults/json_complex_spec1.3.json.bin +++ b/tests/_data/serializeResults/json_complex_spec1.3.json.bin @@ -161,6 +161,26 @@ "comment": "testing" } ] + }, + { + "type": "framework", + "name": "SomeFrameworkBundle", + "version": "", + "bom-ref": "SomeFrameworkBundle", + "components": [ + { + "type": "library", + "name": "SubComponentA", + "version": "", + "bom-ref": "SomeFrameworkBundle#SubComponentA" + }, + { + "type": "library", + "name": "SubComponentB", + "version": "", + "bom-ref": "SomeFrameworkBundle#SubComponentB" + } + ] } ], "dependencies": [ @@ -179,6 +199,9 @@ "a-component", "dummy-component" ] + }, + { + "ref": "SomeFrameworkBundle" } ] } \ No newline at end of file diff --git a/tests/_data/serializeResults/json_complex_spec1.4.json.bin b/tests/_data/serializeResults/json_complex_spec1.4.json.bin index e49067c6f..c1d8b6663 100644 --- a/tests/_data/serializeResults/json_complex_spec1.4.json.bin +++ b/tests/_data/serializeResults/json_complex_spec1.4.json.bin @@ -170,6 +170,23 @@ "comment": "testing" } ] + }, + { + "type": "framework", + "name": "SomeFrameworkBundle", + "bom-ref": "SomeFrameworkBundle", + "components": [ + { + "type": "library", + "name": "SubComponentA", + "bom-ref": "SomeFrameworkBundle#SubComponentA" + }, + { + "type": "library", + "name": "SubComponentB", + "bom-ref": "SomeFrameworkBundle#SubComponentB" + } + ] } ], "dependencies": [ @@ -188,6 +205,9 @@ "a-component", "dummy-component" ] + }, + { + "ref": "SomeFrameworkBundle" } ] } \ No newline at end of file diff --git a/tests/_data/serializeResults/xml_complex_spec1.2.xml.bin b/tests/_data/serializeResults/xml_complex_spec1.2.xml.bin index 891cf0ffa..4cdca743d 100644 --- a/tests/_data/serializeResults/xml_complex_spec1.2.xml.bin +++ b/tests/_data/serializeResults/xml_complex_spec1.2.xml.bin @@ -106,6 +106,20 @@ + + SomeFrameworkBundle + + + + SubComponentA + + + + SubComponentB + + + + @@ -116,5 +130,6 @@ + \ No newline at end of file diff --git a/tests/_data/serializeResults/xml_complex_spec1.3.xml.bin b/tests/_data/serializeResults/xml_complex_spec1.3.xml.bin index bee5e1826..a5a531154 100644 --- a/tests/_data/serializeResults/xml_complex_spec1.3.xml.bin +++ b/tests/_data/serializeResults/xml_complex_spec1.3.xml.bin @@ -106,6 +106,20 @@ + + SomeFrameworkBundle + + + + SubComponentA + + + + SubComponentB + + + + @@ -116,5 +130,6 @@ + \ No newline at end of file diff --git a/tests/_data/serializeResults/xml_complex_spec1.4.xml.bin b/tests/_data/serializeResults/xml_complex_spec1.4.xml.bin index 71348bc40..a76564d9a 100644 --- a/tests/_data/serializeResults/xml_complex_spec1.4.xml.bin +++ b/tests/_data/serializeResults/xml_complex_spec1.4.xml.bin @@ -113,6 +113,17 @@ + + SomeFrameworkBundle + + + SubComponentA + + + SubComponentB + + + @@ -123,5 +134,6 @@ + \ No newline at end of file diff --git a/tests/integration/Serialize.JsonNormalize.test.js b/tests/integration/Serialize.JsonNormalize.test.js index 929fe186f..d19feb60f 100644 --- a/tests/integration/Serialize.JsonNormalize.test.js +++ b/tests/integration/Serialize.JsonNormalize.test.js @@ -24,7 +24,7 @@ const { describe, beforeEach, afterEach, it } = require('mocha') const { createComplexStructure } = require('../_data/models') const { loadNormalizeResult } = require('../_data/normalize') /* uncomment next line to dump data */ -// const { writeNormalizeResult } = require('../_data/normalize') +const { writeNormalizeResult } = require('../_data/normalize') const { Serialize: { @@ -63,8 +63,9 @@ describe('Serialize.JsonNormalize', function () { const json = JSON.stringify(normalized, null, 2) - /* uncomment next line to dump data */ - // writeNormalizeResult(json, 'json_sortedLists', spec.version, 'json') + if (process.env.CJL_TEST_UPDATE_SNAPSHOTS) { + writeNormalizeResult(json, 'json_sortedLists', spec.version, 'json') + } assert.deepStrictEqual( JSON.parse(json), diff --git a/tests/integration/Serialize.JsonSerialize.test.js b/tests/integration/Serialize.JsonSerialize.test.js index 50fcaf8e9..9dd49d4d9 100644 --- a/tests/integration/Serialize.JsonSerialize.test.js +++ b/tests/integration/Serialize.JsonSerialize.test.js @@ -24,7 +24,7 @@ const { describe, beforeEach, afterEach, it } = require('mocha') const { createComplexStructure } = require('../_data/models') const { loadSerializeResult } = require('../_data/serialize') /* uncomment next line to dump data */ -// const { writeSerializeResult } = require('../_data/serialize') +const { writeSerializeResult } = require('../_data/serialize') const { Serialize: { @@ -60,8 +60,9 @@ describe('Serialize.JsonSerialize', function () { space: 4 }) - /* uncomment next line to dump data */ - // writeSerializeResult(serialized, 'json_complex', spec.version, 'json') + if (process.env.CJL_TEST_UPDATE_SNAPSHOTS) { + writeSerializeResult(serialized, 'json_complex', spec.version, 'json') + } assert.strictEqual( serialized, diff --git a/tests/integration/Serialize.XmlNormalize.test.js b/tests/integration/Serialize.XmlNormalize.test.js index ce2f8c3ef..9cd2ca599 100644 --- a/tests/integration/Serialize.XmlNormalize.test.js +++ b/tests/integration/Serialize.XmlNormalize.test.js @@ -24,7 +24,7 @@ const { describe, beforeEach, afterEach, it } = require('mocha') const { createComplexStructure } = require('../_data/models') const { loadNormalizeResult } = require('../_data/normalize') /* uncomment next line to dump data */ -// const { writeNormalizeResult } = require('../_data/normalize') +const { writeNormalizeResult } = require('../_data/normalize') const { Serialize: { @@ -63,8 +63,9 @@ describe('Serialize.XmlNormalize', function () { const json = JSON.stringify(normalized, null, 2) - /* uncomment next line to dump data */ - // writeNormalizeResult(json, 'xml_sortedLists', spec.version, 'json') + if (process.env.CJL_TEST_UPDATE_SNAPSHOTS) { + writeNormalizeResult(json, 'xml_sortedLists', spec.version, 'json') + } assert.deepStrictEqual( JSON.parse(json), diff --git a/tests/integration/Serialize.XmlSerialize.test.js b/tests/integration/Serialize.XmlSerialize.test.js index a4a486610..b62bd954e 100644 --- a/tests/integration/Serialize.XmlSerialize.test.js +++ b/tests/integration/Serialize.XmlSerialize.test.js @@ -24,7 +24,7 @@ const { describe, beforeEach, afterEach, it } = require('mocha') const { createComplexStructure } = require('../_data/models') const { loadSerializeResult } = require('../_data/serialize') /* uncomment next line to dump data */ -// const { writeSerializeResult } = require('../_data/serialize') +const { writeSerializeResult } = require('../_data/serialize') const { Serialize: { @@ -60,8 +60,9 @@ describe('Serialize.XmlSerialize', function () { space: 4 }) - /* uncomment next line to dump data */ - // writeSerializeResult(serialized, 'xml_complex', spec.version, 'xml') + if (process.env.CJL_TEST_UPDATE_SNAPSHOTS) { + writeSerializeResult(serialized, 'xml_complex', spec.version, 'xml') + } assert.strictEqual( serialized, From 1ea42a25f438b2f10a56128e31cb5b40c9695c50 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Thu, 28 Jul 2022 20:13:19 +0200 Subject: [PATCH 04/11] test `component.components` normalizer/serializer tests Signed-off-by: Jan Kowalleck --- tests/_data/models.js | 3 +++ tests/_data/normalizeResults/json_sortedLists_spec1.2.json | 3 ++- tests/_data/normalizeResults/json_sortedLists_spec1.3.json | 3 ++- tests/_data/normalizeResults/json_sortedLists_spec1.4.json | 3 ++- tests/_data/normalizeResults/xml_sortedLists_spec1.2.json | 7 +++++++ tests/_data/normalizeResults/xml_sortedLists_spec1.3.json | 7 +++++++ tests/_data/normalizeResults/xml_sortedLists_spec1.4.json | 7 +++++++ tests/_data/serializeResults/json_complex_spec1.2.json.bin | 3 ++- tests/_data/serializeResults/json_complex_spec1.3.json.bin | 3 ++- tests/_data/serializeResults/json_complex_spec1.4.json.bin | 3 ++- tests/_data/serializeResults/xml_complex_spec1.2.xml.bin | 1 + tests/_data/serializeResults/xml_complex_spec1.3.xml.bin | 1 + tests/_data/serializeResults/xml_complex_spec1.4.xml.bin | 1 + 13 files changed, 39 insertions(+), 6 deletions(-) diff --git a/tests/_data/models.js b/tests/_data/models.js index 828e12d06..eff41b143 100644 --- a/tests/_data/models.js +++ b/tests/_data/models.js @@ -177,6 +177,9 @@ module.exports.createComplexStructure = function () { }) subComponentA.dependencies.add(subComponentB.bomRef) component.components.add(subComponentB) + + bom.metadata.component.dependencies.add(component.bomRef) + return component })(new Models.Component( Enums.ComponentType.Framework, 'SomeFrameworkBundle', { diff --git a/tests/_data/normalizeResults/json_sortedLists_spec1.2.json b/tests/_data/normalizeResults/json_sortedLists_spec1.2.json index 4fe5f53d7..c7eb092df 100644 --- a/tests/_data/normalizeResults/json_sortedLists_spec1.2.json +++ b/tests/_data/normalizeResults/json_sortedLists_spec1.2.json @@ -197,7 +197,8 @@ "ref": "dummy.metadata.component", "dependsOn": [ "a-component", - "dummy-component" + "dummy-component", + "SomeFrameworkBundle" ] }, { diff --git a/tests/_data/normalizeResults/json_sortedLists_spec1.3.json b/tests/_data/normalizeResults/json_sortedLists_spec1.3.json index 0c57ba099..b6c6a49b8 100644 --- a/tests/_data/normalizeResults/json_sortedLists_spec1.3.json +++ b/tests/_data/normalizeResults/json_sortedLists_spec1.3.json @@ -197,7 +197,8 @@ "ref": "dummy.metadata.component", "dependsOn": [ "a-component", - "dummy-component" + "dummy-component", + "SomeFrameworkBundle" ] }, { diff --git a/tests/_data/normalizeResults/json_sortedLists_spec1.4.json b/tests/_data/normalizeResults/json_sortedLists_spec1.4.json index de94eb689..7e5ad97fb 100644 --- a/tests/_data/normalizeResults/json_sortedLists_spec1.4.json +++ b/tests/_data/normalizeResults/json_sortedLists_spec1.4.json @@ -203,7 +203,8 @@ "ref": "dummy.metadata.component", "dependsOn": [ "a-component", - "dummy-component" + "dummy-component", + "SomeFrameworkBundle" ] }, { diff --git a/tests/_data/normalizeResults/xml_sortedLists_spec1.2.json b/tests/_data/normalizeResults/xml_sortedLists_spec1.2.json index 673dd8bbb..9b09c8d43 100644 --- a/tests/_data/normalizeResults/xml_sortedLists_spec1.2.json +++ b/tests/_data/normalizeResults/xml_sortedLists_spec1.2.json @@ -596,6 +596,13 @@ "attributes": { "ref": "dummy-component" } + }, + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle" + } } ] }, diff --git a/tests/_data/normalizeResults/xml_sortedLists_spec1.3.json b/tests/_data/normalizeResults/xml_sortedLists_spec1.3.json index 2e8735742..c10380a97 100644 --- a/tests/_data/normalizeResults/xml_sortedLists_spec1.3.json +++ b/tests/_data/normalizeResults/xml_sortedLists_spec1.3.json @@ -596,6 +596,13 @@ "attributes": { "ref": "dummy-component" } + }, + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle" + } } ] }, diff --git a/tests/_data/normalizeResults/xml_sortedLists_spec1.4.json b/tests/_data/normalizeResults/xml_sortedLists_spec1.4.json index 863f9e11a..5e6ebe9a6 100644 --- a/tests/_data/normalizeResults/xml_sortedLists_spec1.4.json +++ b/tests/_data/normalizeResults/xml_sortedLists_spec1.4.json @@ -610,6 +610,13 @@ "attributes": { "ref": "dummy-component" } + }, + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle" + } } ] }, diff --git a/tests/_data/serializeResults/json_complex_spec1.2.json.bin b/tests/_data/serializeResults/json_complex_spec1.2.json.bin index 2948e206a..c9c89a80c 100644 --- a/tests/_data/serializeResults/json_complex_spec1.2.json.bin +++ b/tests/_data/serializeResults/json_complex_spec1.2.json.bin @@ -197,7 +197,8 @@ "ref": "dummy.metadata.component", "dependsOn": [ "a-component", - "dummy-component" + "dummy-component", + "SomeFrameworkBundle" ] }, { diff --git a/tests/_data/serializeResults/json_complex_spec1.3.json.bin b/tests/_data/serializeResults/json_complex_spec1.3.json.bin index 76226a063..c0781d6e5 100644 --- a/tests/_data/serializeResults/json_complex_spec1.3.json.bin +++ b/tests/_data/serializeResults/json_complex_spec1.3.json.bin @@ -197,7 +197,8 @@ "ref": "dummy.metadata.component", "dependsOn": [ "a-component", - "dummy-component" + "dummy-component", + "SomeFrameworkBundle" ] }, { diff --git a/tests/_data/serializeResults/json_complex_spec1.4.json.bin b/tests/_data/serializeResults/json_complex_spec1.4.json.bin index c1d8b6663..1acd119a4 100644 --- a/tests/_data/serializeResults/json_complex_spec1.4.json.bin +++ b/tests/_data/serializeResults/json_complex_spec1.4.json.bin @@ -203,7 +203,8 @@ "ref": "dummy.metadata.component", "dependsOn": [ "a-component", - "dummy-component" + "dummy-component", + "SomeFrameworkBundle" ] }, { diff --git a/tests/_data/serializeResults/xml_complex_spec1.2.xml.bin b/tests/_data/serializeResults/xml_complex_spec1.2.xml.bin index 4cdca743d..7f2b486fc 100644 --- a/tests/_data/serializeResults/xml_complex_spec1.2.xml.bin +++ b/tests/_data/serializeResults/xml_complex_spec1.2.xml.bin @@ -129,6 +129,7 @@ + diff --git a/tests/_data/serializeResults/xml_complex_spec1.3.xml.bin b/tests/_data/serializeResults/xml_complex_spec1.3.xml.bin index a5a531154..fccfb1e4d 100644 --- a/tests/_data/serializeResults/xml_complex_spec1.3.xml.bin +++ b/tests/_data/serializeResults/xml_complex_spec1.3.xml.bin @@ -129,6 +129,7 @@ + diff --git a/tests/_data/serializeResults/xml_complex_spec1.4.xml.bin b/tests/_data/serializeResults/xml_complex_spec1.4.xml.bin index a76564d9a..8398affc5 100644 --- a/tests/_data/serializeResults/xml_complex_spec1.4.xml.bin +++ b/tests/_data/serializeResults/xml_complex_spec1.4.xml.bin @@ -133,6 +133,7 @@ + From 96113faeb810cb59c7b40ff898710265da577064 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 29 Jul 2022 17:39:12 +0200 Subject: [PATCH 05/11] implement dependnecy graph for nested components Signed-off-by: Jan Kowalleck --- src/helpers/tree.ts | 20 ++++++++++++ src/models/component.ts | 7 ++++ src/serialize/json/normalize.ts | 8 +++-- src/serialize/xml/normalize.ts | 8 +++-- .../json_sortedLists_spec1.2.json | 14 +++++++- .../json_sortedLists_spec1.3.json | 14 +++++++- .../json_sortedLists_spec1.4.json | 14 +++++++- .../xml_sortedLists_spec1.2.json | 32 +++++++++++++++++++ .../xml_sortedLists_spec1.3.json | 32 +++++++++++++++++++ .../xml_sortedLists_spec1.4.json | 32 +++++++++++++++++++ .../json_complex_spec1.2.json.bin | 14 +++++++- .../json_complex_spec1.3.json.bin | 14 +++++++- .../json_complex_spec1.4.json.bin | 14 +++++++- .../xml_complex_spec1.2.xml.bin | 8 ++++- .../xml_complex_spec1.3.xml.bin | 8 ++++- .../xml_complex_spec1.4.xml.bin | 8 ++++- 16 files changed, 234 insertions(+), 13 deletions(-) create mode 100644 src/helpers/tree.ts diff --git a/src/helpers/tree.ts b/src/helpers/tree.ts new file mode 100644 index 000000000..ceee9b189 --- /dev/null +++ b/src/helpers/tree.ts @@ -0,0 +1,20 @@ +/*! +This file is part of CycloneDX JavaScript Library. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +SPDX-License-Identifier: Apache-2.0 +Copyright (c) OWASP Foundation. All Rights Reserved. +*/ + +export const treeIterator = Symbol('iterator of a tree/nesting-like structure') diff --git a/src/models/component.ts b/src/models/component.ts index 26b411eb9..aa2c60242 100644 --- a/src/models/component.ts +++ b/src/models/component.ts @@ -28,6 +28,7 @@ import { ExternalReferenceRepository } from './externalReference' import { LicenseRepository } from './license' import { SWID } from './swid' import { Comparable, SortableSet } from '../helpers/sortableSet' +import { treeIterator } from '../helpers/tree' interface OptionalProperties { bomRef?: BomRef['value'] @@ -137,4 +138,10 @@ export class Component implements Comparable { } export class ComponentRepository extends SortableSet { + * [treeIterator] (): Generator { + for (const component of this) { + yield component + yield * component.components[treeIterator]() + } + } } diff --git a/src/serialize/json/normalize.ts b/src/serialize/json/normalize.ts index 2818bca1a..780f2b22a 100644 --- a/src/serialize/json/normalize.ts +++ b/src/serialize/json/normalize.ts @@ -23,6 +23,7 @@ import * as Models from '../../models' import { Protocol as Spec, Version as SpecVersion } from '../../spec' import { NormalizerOptions } from '../types' import { JsonSchema, Normalized } from './types' +import { treeIterator } from '../../helpers/tree' export class Factory { readonly #spec: Spec @@ -397,9 +398,12 @@ export class DependencyGraphNormalizer extends Base { const allRefs = new Map() if (data.metadata.component !== undefined) { allRefs.set(data.metadata.component.bomRef, data.metadata.component.dependencies) + for (const component of data.metadata.component.components[treeIterator]()) { + allRefs.set(component.bomRef, component.dependencies) + } } - for (const c of data.components) { - allRefs.set(c.bomRef, new Models.BomRefRepository(c.dependencies)) + for (const component of data.components[treeIterator]()) { + allRefs.set(component.bomRef, new Models.BomRefRepository(component.dependencies)) } const normalized: Normalized.Dependency[] = [] diff --git a/src/serialize/xml/normalize.ts b/src/serialize/xml/normalize.ts index 17ffcc211..aaa6ca441 100644 --- a/src/serialize/xml/normalize.ts +++ b/src/serialize/xml/normalize.ts @@ -23,6 +23,7 @@ import * as Models from '../../models' import { Protocol as Spec, Version as SpecVersion } from '../../spec' import { NormalizerOptions } from '../types' import { SimpleXml, XmlSchema } from './types' +import { treeIterator } from '../../helpers/tree' export class Factory { readonly #spec: Spec @@ -517,9 +518,12 @@ export class DependencyGraphNormalizer extends Base { const allRefs = new Map() if (data.metadata.component !== undefined) { allRefs.set(data.metadata.component.bomRef, data.metadata.component.dependencies) + for (const component of data.metadata.component.components[treeIterator]()) { + allRefs.set(component.bomRef, new Models.BomRefRepository(component.dependencies)) + } } - for (const c of data.components) { - allRefs.set(c.bomRef, new Models.BomRefRepository(c.dependencies)) + for (const component of data.components[treeIterator]()) { + allRefs.set(component.bomRef, new Models.BomRefRepository(component.dependencies)) } const normalized: Array<(SimpleXml.Element & { attributes: { ref: string } })> = [] diff --git a/tests/_data/normalizeResults/json_sortedLists_spec1.2.json b/tests/_data/normalizeResults/json_sortedLists_spec1.2.json index c7eb092df..8b287bf97 100644 --- a/tests/_data/normalizeResults/json_sortedLists_spec1.2.json +++ b/tests/_data/normalizeResults/json_sortedLists_spec1.2.json @@ -202,7 +202,19 @@ ] }, { - "ref": "SomeFrameworkBundle" + "ref": "SomeFrameworkBundle", + "dependsOn": [ + "SomeFrameworkBundle#SubComponentA" + ] + }, + { + "ref": "SomeFrameworkBundle#SubComponentA", + "dependsOn": [ + "SomeFrameworkBundle#SubComponentB" + ] + }, + { + "ref": "SomeFrameworkBundle#SubComponentB" } ] } \ No newline at end of file diff --git a/tests/_data/normalizeResults/json_sortedLists_spec1.3.json b/tests/_data/normalizeResults/json_sortedLists_spec1.3.json index b6c6a49b8..c2505cc1d 100644 --- a/tests/_data/normalizeResults/json_sortedLists_spec1.3.json +++ b/tests/_data/normalizeResults/json_sortedLists_spec1.3.json @@ -202,7 +202,19 @@ ] }, { - "ref": "SomeFrameworkBundle" + "ref": "SomeFrameworkBundle", + "dependsOn": [ + "SomeFrameworkBundle#SubComponentA" + ] + }, + { + "ref": "SomeFrameworkBundle#SubComponentA", + "dependsOn": [ + "SomeFrameworkBundle#SubComponentB" + ] + }, + { + "ref": "SomeFrameworkBundle#SubComponentB" } ] } \ No newline at end of file diff --git a/tests/_data/normalizeResults/json_sortedLists_spec1.4.json b/tests/_data/normalizeResults/json_sortedLists_spec1.4.json index 7e5ad97fb..55f07f029 100644 --- a/tests/_data/normalizeResults/json_sortedLists_spec1.4.json +++ b/tests/_data/normalizeResults/json_sortedLists_spec1.4.json @@ -208,7 +208,19 @@ ] }, { - "ref": "SomeFrameworkBundle" + "ref": "SomeFrameworkBundle", + "dependsOn": [ + "SomeFrameworkBundle#SubComponentA" + ] + }, + { + "ref": "SomeFrameworkBundle#SubComponentA", + "dependsOn": [ + "SomeFrameworkBundle#SubComponentB" + ] + }, + { + "ref": "SomeFrameworkBundle#SubComponentB" } ] } \ No newline at end of file diff --git a/tests/_data/normalizeResults/xml_sortedLists_spec1.2.json b/tests/_data/normalizeResults/xml_sortedLists_spec1.2.json index 9b09c8d43..82f215338 100644 --- a/tests/_data/normalizeResults/xml_sortedLists_spec1.2.json +++ b/tests/_data/normalizeResults/xml_sortedLists_spec1.2.json @@ -612,6 +612,38 @@ "attributes": { "ref": "SomeFrameworkBundle" }, + "children": [ + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle#SubComponentA" + } + } + ] + }, + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle#SubComponentA" + }, + "children": [ + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle#SubComponentB" + } + } + ] + }, + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle#SubComponentB" + }, "children": [] } ] diff --git a/tests/_data/normalizeResults/xml_sortedLists_spec1.3.json b/tests/_data/normalizeResults/xml_sortedLists_spec1.3.json index c10380a97..ec12ebed3 100644 --- a/tests/_data/normalizeResults/xml_sortedLists_spec1.3.json +++ b/tests/_data/normalizeResults/xml_sortedLists_spec1.3.json @@ -612,6 +612,38 @@ "attributes": { "ref": "SomeFrameworkBundle" }, + "children": [ + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle#SubComponentA" + } + } + ] + }, + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle#SubComponentA" + }, + "children": [ + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle#SubComponentB" + } + } + ] + }, + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle#SubComponentB" + }, "children": [] } ] diff --git a/tests/_data/normalizeResults/xml_sortedLists_spec1.4.json b/tests/_data/normalizeResults/xml_sortedLists_spec1.4.json index 5e6ebe9a6..b2b190060 100644 --- a/tests/_data/normalizeResults/xml_sortedLists_spec1.4.json +++ b/tests/_data/normalizeResults/xml_sortedLists_spec1.4.json @@ -626,6 +626,38 @@ "attributes": { "ref": "SomeFrameworkBundle" }, + "children": [ + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle#SubComponentA" + } + } + ] + }, + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle#SubComponentA" + }, + "children": [ + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle#SubComponentB" + } + } + ] + }, + { + "type": "element", + "name": "dependency", + "attributes": { + "ref": "SomeFrameworkBundle#SubComponentB" + }, "children": [] } ] diff --git a/tests/_data/serializeResults/json_complex_spec1.2.json.bin b/tests/_data/serializeResults/json_complex_spec1.2.json.bin index c9c89a80c..dcd2cce31 100644 --- a/tests/_data/serializeResults/json_complex_spec1.2.json.bin +++ b/tests/_data/serializeResults/json_complex_spec1.2.json.bin @@ -202,7 +202,19 @@ ] }, { - "ref": "SomeFrameworkBundle" + "ref": "SomeFrameworkBundle", + "dependsOn": [ + "SomeFrameworkBundle#SubComponentA" + ] + }, + { + "ref": "SomeFrameworkBundle#SubComponentA", + "dependsOn": [ + "SomeFrameworkBundle#SubComponentB" + ] + }, + { + "ref": "SomeFrameworkBundle#SubComponentB" } ] } \ No newline at end of file diff --git a/tests/_data/serializeResults/json_complex_spec1.3.json.bin b/tests/_data/serializeResults/json_complex_spec1.3.json.bin index c0781d6e5..7743a5345 100644 --- a/tests/_data/serializeResults/json_complex_spec1.3.json.bin +++ b/tests/_data/serializeResults/json_complex_spec1.3.json.bin @@ -202,7 +202,19 @@ ] }, { - "ref": "SomeFrameworkBundle" + "ref": "SomeFrameworkBundle", + "dependsOn": [ + "SomeFrameworkBundle#SubComponentA" + ] + }, + { + "ref": "SomeFrameworkBundle#SubComponentA", + "dependsOn": [ + "SomeFrameworkBundle#SubComponentB" + ] + }, + { + "ref": "SomeFrameworkBundle#SubComponentB" } ] } \ No newline at end of file diff --git a/tests/_data/serializeResults/json_complex_spec1.4.json.bin b/tests/_data/serializeResults/json_complex_spec1.4.json.bin index 1acd119a4..bd68effde 100644 --- a/tests/_data/serializeResults/json_complex_spec1.4.json.bin +++ b/tests/_data/serializeResults/json_complex_spec1.4.json.bin @@ -208,7 +208,19 @@ ] }, { - "ref": "SomeFrameworkBundle" + "ref": "SomeFrameworkBundle", + "dependsOn": [ + "SomeFrameworkBundle#SubComponentA" + ] + }, + { + "ref": "SomeFrameworkBundle#SubComponentA", + "dependsOn": [ + "SomeFrameworkBundle#SubComponentB" + ] + }, + { + "ref": "SomeFrameworkBundle#SubComponentB" } ] } \ No newline at end of file diff --git a/tests/_data/serializeResults/xml_complex_spec1.2.xml.bin b/tests/_data/serializeResults/xml_complex_spec1.2.xml.bin index 7f2b486fc..880c0464e 100644 --- a/tests/_data/serializeResults/xml_complex_spec1.2.xml.bin +++ b/tests/_data/serializeResults/xml_complex_spec1.2.xml.bin @@ -131,6 +131,12 @@ - + + + + + + + \ No newline at end of file diff --git a/tests/_data/serializeResults/xml_complex_spec1.3.xml.bin b/tests/_data/serializeResults/xml_complex_spec1.3.xml.bin index fccfb1e4d..f77bb6104 100644 --- a/tests/_data/serializeResults/xml_complex_spec1.3.xml.bin +++ b/tests/_data/serializeResults/xml_complex_spec1.3.xml.bin @@ -131,6 +131,12 @@ - + + + + + + + \ No newline at end of file diff --git a/tests/_data/serializeResults/xml_complex_spec1.4.xml.bin b/tests/_data/serializeResults/xml_complex_spec1.4.xml.bin index 8398affc5..cd7146ac0 100644 --- a/tests/_data/serializeResults/xml_complex_spec1.4.xml.bin +++ b/tests/_data/serializeResults/xml_complex_spec1.4.xml.bin @@ -135,6 +135,12 @@ - + + + + + + + \ No newline at end of file From efb36f8494a97713f029abbf46a0facdeb522b48 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 29 Jul 2022 18:34:59 +0200 Subject: [PATCH 06/11] dropped unnessessary object clones when normalizing dependency graph Signed-off-by: Jan Kowalleck --- src/serialize/json/normalize.ts | 2 +- src/serialize/xml/normalize.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/serialize/json/normalize.ts b/src/serialize/json/normalize.ts index 780f2b22a..b7f918844 100644 --- a/src/serialize/json/normalize.ts +++ b/src/serialize/json/normalize.ts @@ -403,7 +403,7 @@ export class DependencyGraphNormalizer extends Base { } } for (const component of data.components[treeIterator]()) { - allRefs.set(component.bomRef, new Models.BomRefRepository(component.dependencies)) + allRefs.set(component.bomRef, component.dependencies) } const normalized: Normalized.Dependency[] = [] diff --git a/src/serialize/xml/normalize.ts b/src/serialize/xml/normalize.ts index aaa6ca441..bcdeb0088 100644 --- a/src/serialize/xml/normalize.ts +++ b/src/serialize/xml/normalize.ts @@ -519,11 +519,11 @@ export class DependencyGraphNormalizer extends Base { if (data.metadata.component !== undefined) { allRefs.set(data.metadata.component.bomRef, data.metadata.component.dependencies) for (const component of data.metadata.component.components[treeIterator]()) { - allRefs.set(component.bomRef, new Models.BomRefRepository(component.dependencies)) + allRefs.set(component.bomRef, component.dependencies) } } for (const component of data.components[treeIterator]()) { - allRefs.set(component.bomRef, new Models.BomRefRepository(component.dependencies)) + allRefs.set(component.bomRef, component.dependencies) } const normalized: Array<(SimpleXml.Element & { attributes: { ref: string } })> = [] From f94908580eb6be0947b862098bbf6f770a61a383 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 29 Jul 2022 18:43:19 +0200 Subject: [PATCH 07/11] more tests Signed-off-by: Jan Kowalleck --- tests/unit/Models.Component.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/Models.Component.spec.js b/tests/unit/Models.Component.spec.js index f1c8ebdbe..8c6e99e93 100644 --- a/tests/unit/Models.Component.spec.js +++ b/tests/unit/Models.Component.spec.js @@ -109,6 +109,7 @@ suite('Models.Component', () => { assert.strictEqual(component.supplier, dummySupplier) assert.strictEqual(component.swid, dummySWID) assert.strictEqual(component.version, '1.33.7') + assert.strictEqual(component.components.size, 1) assert.strictEqual(Array.from(component.components)[0], subComponent) }) }) From e0428562e8708d6ad6608999bb569ef52834ad24 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 29 Jul 2022 18:48:00 +0200 Subject: [PATCH 08/11] more verbose change log Signed-off-by: Jan Kowalleck --- HISTORY.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 3a0c4207f..a91a56f64 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -5,7 +5,8 @@ All notable changes to this project will be documented in this file. ## unreleased * Added - * Implemented support for nested/bundled components via `bom.component.components`. ([#132] via [#136]) + * Support for nested/bundled components via `bom.component.components` as added, + including normalization of models and extended integration in possible dependency graph. ([#132] via [#136]) * CycloneDX spec version 1.4 made element `bom.component.version` optional. Therefore, serialization/normalization with this spec version will no longer render this element, when its value is empty. (via [#137], [#138]) From 53563631617c5cbf2c7bde12e86484b9742ce786 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 29 Jul 2022 18:57:22 +0200 Subject: [PATCH 09/11] more verbose change log Signed-off-by: Jan Kowalleck --- HISTORY.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index a91a56f64..77589eb3c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -5,11 +5,11 @@ All notable changes to this project will be documented in this file. ## unreleased * Added - * Support for nested/bundled components via `bom.component.components` as added, - including normalization of models and extended integration in possible dependency graph. ([#132] via [#136]) - * CycloneDX spec version 1.4 made element `bom.component.version` optional. - Therefore, serialization/normalization with this spec version will no longer render this element, - when its value is empty. (via [#137], [#138]) + * Support for nested/bundled components via `Models.Component.components` as added, including + serialization/normalization of models and impact on dependency graphs rendering. ([#132] via [#136]) + * CycloneDX spec version 1.4 made element `Models.Component.version` optional. + Therefore, serialization/normalization with this spec version will no longer render this element + if its value is empty. (via [#137], [#138]) [#132]: https://github.com/CycloneDX/cyclonedx-javascript-library/issues/132 [#136]: https://github.com/CycloneDX/cyclonedx-javascript-library/pull/136 From b04a36e41e98173065d196c47c0013e48809dca5 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 29 Jul 2022 19:13:36 +0200 Subject: [PATCH 10/11] fix typo Signed-off-by: Jan Kowalleck --- HISTORY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 77589eb3c..2f1742b58 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. ## unreleased * Added - * Support for nested/bundled components via `Models.Component.components` as added, including + * Support for nested/bundled components via `Models.Component.components` was added, including serialization/normalization of models and impact on dependency graphs rendering. ([#132] via [#136]) * CycloneDX spec version 1.4 made element `Models.Component.version` optional. Therefore, serialization/normalization with this spec version will no longer render this element From fb10eea54933bc98784a1693be02641452b5c6b4 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 29 Jul 2022 19:20:32 +0200 Subject: [PATCH 11/11] hist Signed-off-by: Jan Kowalleck --- HISTORY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 2f1742b58..fdbc0315e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. ## unreleased * Added - * Support for nested/bundled components via `Models.Component.components` was added, including + * Support for nested/bundled (sub-)components via `Models.Component.components` was added, including serialization/normalization of models and impact on dependency graphs rendering. ([#132] via [#136]) * CycloneDX spec version 1.4 made element `Models.Component.version` optional. Therefore, serialization/normalization with this spec version will no longer render this element