Skip to content

Commit ee77f65

Browse files
committed
Run test against actual schema files (Java)
This change modifies the Java Unit tests to use the schemas in this repository to validate the examples, instead of those bundled in the `cyclonedx-java-core` artifact. Closes #256
1 parent 5868a43 commit ee77f65

File tree

4 files changed

+267
-103
lines changed

4 files changed

+267
-103
lines changed

tools/pom.xml

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@
5454
<lib.commons.io.version>2.17.0</lib.commons.io.version>
5555
<lib.commons.lang3.version>3.17.0</lib.commons.lang3.version>
5656
<lib.commons.text.version>1.12.0</lib.commons.text.version>
57+
<lib.json.schema.validator>1.5.5</lib.json.schema.validator>
5758
<lib.unirest.version>1.4.9</lib.unirest.version>
58-
<lib.cyclonedx.core.java.version>10.0.0</lib.cyclonedx.core.java.version>
59+
<lib.slf4j.api>2.0.16</lib.slf4j.api>
5960
</properties>
6061

6162
<scm>
@@ -98,6 +99,24 @@
9899
</repository>
99100
</repositories>
100101

102+
<dependencyManagement>
103+
<dependencies>
104+
105+
<dependency>
106+
<groupId>org.slf4j</groupId>
107+
<artifactId>slf4j-api</artifactId>
108+
<version>${lib.slf4j.api}</version>
109+
</dependency>
110+
111+
<dependency>
112+
<groupId>org.slf4j</groupId>
113+
<artifactId>slf4j-simple</artifactId>
114+
<version>${lib.slf4j.api}</version>
115+
</dependency>
116+
117+
</dependencies>
118+
</dependencyManagement>
119+
101120
<dependencies>
102121
<!-- Apache Commons -->
103122
<dependency>
@@ -123,16 +142,22 @@
123142
<scope>compile</scope>
124143
</dependency>
125144
<!-- Unit tests -->
145+
<dependency>
146+
<groupId>com.networknt</groupId>
147+
<artifactId>json-schema-validator</artifactId>
148+
<version>${lib.json.schema.validator}</version>
149+
<scope>test</scope>
150+
</dependency>
126151
<dependency>
127152
<groupId>org.junit.jupiter</groupId>
128-
<artifactId>junit-jupiter-engine</artifactId>
129-
<version>5.7.0</version>
153+
<artifactId>junit-jupiter-api</artifactId>
154+
<version>5.11.4</version>
130155
<scope>test</scope>
131156
</dependency>
157+
<!-- Runtime-only test dependency -->
132158
<dependency>
133-
<groupId>org.cyclonedx</groupId>
134-
<artifactId>cyclonedx-core-java</artifactId>
135-
<version>${lib.cyclonedx.core.java.version}</version>
159+
<groupId>org.slf4j</groupId>
160+
<artifactId>slf4j-simple</artifactId>
136161
<scope>test</scope>
137162
</dependency>
138163
</dependencies>
@@ -142,15 +167,15 @@
142167
<plugin>
143168
<groupId>org.apache.maven.plugins</groupId>
144169
<artifactId>maven-surefire-plugin</artifactId>
145-
<version>3.5.1</version>
170+
<version>3.5.2</version>
146171
</plugin>
147172
</plugins>
148173
<testResources>
149174
<testResource>
150-
<directory>${basedir}/../schema</directory>
175+
<directory>${project.basedir}/../schema</directory>
151176
</testResource>
152177
<testResource>
153-
<directory>src/test/resources/</directory>
178+
<directory>src/test/resources</directory>
154179
</testResource>
155180
</testResources>
156181
</build>

tools/src/test/java/org/cyclonedx/schema/BaseSchemaVerificationTest.java

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,14 @@ List<String> getAllResources() throws Exception {
3333
return files;
3434
}
3535

36-
List<String> getResources(final String resourceDirectory) throws Exception {
37-
final List<String> files = new ArrayList<>();
38-
String dir = resourceDirectory;
39-
if (!resourceDirectory.endsWith("/")) {
40-
dir += "/";
41-
}
42-
try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(dir)) {
36+
private List<String> getResources(final String resourceDirectory) throws Exception {
37+
final List<String> resources = new ArrayList<>();
38+
try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(resourceDirectory)) {
4339
if (in != null) {
44-
files.addAll(IOUtils.readLines(in, StandardCharsets.UTF_8));
40+
IOUtils.readLines(in, StandardCharsets.UTF_8)
41+
.forEach(resource -> resources.add(resourceDirectory + resource));
4542
}
4643
}
47-
return files;
44+
return resources;
4845
}
4946
}

tools/src/test/java/org/cyclonedx/schema/JsonSchemaVerificationTest.java

Lines changed: 106 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13,68 +13,130 @@
1313
*/
1414
package org.cyclonedx.schema;
1515

16-
import java.io.File;
16+
import static java.util.Objects.requireNonNull;
17+
import static org.junit.jupiter.api.Assertions.assertFalse;
18+
import static org.junit.jupiter.api.Assertions.assertTrue;
19+
20+
import com.fasterxml.jackson.core.JsonParser;
21+
import com.fasterxml.jackson.databind.JsonNode;
22+
import com.fasterxml.jackson.databind.ObjectMapper;
23+
import com.fasterxml.jackson.databind.json.JsonMapper;
24+
import com.networknt.schema.DefaultJsonMetaSchemaFactory;
25+
import com.networknt.schema.DisallowUnknownKeywordFactory;
26+
import com.networknt.schema.JsonMetaSchema;
27+
import com.networknt.schema.JsonMetaSchemaFactory;
28+
import com.networknt.schema.JsonSchema;
29+
import com.networknt.schema.JsonSchemaFactory;
30+
import com.networknt.schema.NonValidationKeyword;
31+
import com.networknt.schema.SchemaId;
32+
import com.networknt.schema.SchemaValidatorsConfig;
33+
import java.io.IOException;
34+
import java.io.InputStream;
35+
import java.net.URISyntaxException;
1736
import java.util.ArrayList;
1837
import java.util.Collection;
1938
import java.util.List;
20-
21-
import org.cyclonedx.parsers.JsonParser;
22-
import org.cyclonedx.Version;
39+
import org.apache.commons.lang3.StringUtils;
2340
import org.junit.jupiter.api.DynamicTest;
2441
import org.junit.jupiter.api.TestFactory;
2542

26-
import static org.junit.jupiter.api.Assertions.assertTrue;
27-
import static org.junit.jupiter.api.Assertions.assertFalse;
43+
class JsonSchemaVerificationTest extends BaseSchemaVerificationTest {
44+
45+
private static final ObjectMapper MAPPER = new JsonMapper();
46+
47+
private static final JsonSchema VERSION_12;
48+
private static final JsonSchema VERSION_13;
49+
private static final JsonSchema VERSION_14;
50+
private static final JsonSchema VERSION_15;
51+
private static final JsonSchema VERSION_16;
52+
53+
static {
54+
JsonMetaSchemaFactory metaSchemaFactory = new DefaultJsonMetaSchemaFactory() {
55+
@Override
56+
public JsonMetaSchema getMetaSchema(
57+
String iri, JsonSchemaFactory schemaFactory, SchemaValidatorsConfig config) {
58+
return addCustomKeywords(super.getMetaSchema(iri, schemaFactory, config));
59+
}
60+
};
61+
JsonSchemaFactory factory = JsonSchemaFactory.builder()
62+
.defaultMetaSchemaIri(SchemaId.V7)
63+
.metaSchema(addCustomKeywords(JsonMetaSchema.getV7()))
64+
.metaSchemaFactory(metaSchemaFactory)
65+
.build();
66+
ClassLoader cl = JsonSchemaVerificationTest.class.getClassLoader();
67+
try {
68+
VERSION_12 = factory.getSchema(
69+
requireNonNull(cl.getResource("bom-1.2-strict.schema.json")).toURI());
70+
VERSION_13 = factory.getSchema(
71+
requireNonNull(cl.getResource("bom-1.3-strict.schema.json")).toURI());
72+
VERSION_14 = factory.getSchema(
73+
requireNonNull(cl.getResource("bom-1.4.schema.json")).toURI());
74+
VERSION_15 = factory.getSchema(
75+
requireNonNull(cl.getResource("bom-1.5.schema.json")).toURI());
76+
VERSION_16 = factory.getSchema(
77+
requireNonNull(cl.getResource("bom-1.6.schema.json")).toURI());
78+
} catch (URISyntaxException e) {
79+
throw new IllegalStateException(e);
80+
}
81+
}
2882

29-
public class JsonSchemaVerificationTest extends BaseSchemaVerificationTest {
83+
private static JsonMetaSchema addCustomKeywords(JsonMetaSchema metaSchema) {
84+
return JsonMetaSchema.builder(metaSchema)
85+
// Non-standard keywords in the CycloneDX schema files.
86+
.keyword(new NonValidationKeyword("deprecated"))
87+
.keyword(new NonValidationKeyword("meta:enum"))
88+
.unknownKeywordFactory(new DisallowUnknownKeywordFactory())
89+
.build();
90+
}
3091

3192
@TestFactory
3293
Collection<DynamicTest> dynamicTestsWithCollection() throws Exception {
33-
final List<String> files = getAllResources();
94+
final List<String> resources = getAllResources();
3495
final List<DynamicTest> dynamicTests = new ArrayList<>();
35-
for (final String file: files) {
36-
if (file.endsWith(".json")) {
37-
final Version schemaVersion;
38-
if (file.endsWith("-1.2.json")) {
39-
schemaVersion = Version.VERSION_12;
40-
} else if (file.endsWith("-1.3.json")) {
41-
schemaVersion = Version.VERSION_13;
42-
} else if (file.endsWith("-1.4.json")) {
43-
schemaVersion = Version.VERSION_14;
44-
} else if (file.endsWith("-1.5.json")) {
45-
schemaVersion = Version.VERSION_15;
46-
} else if (file.endsWith("-1.6.json")) {
47-
schemaVersion = Version.VERSION_16;
48-
} else {
49-
schemaVersion = null;
50-
}
51-
if (file.startsWith("valid") && schemaVersion != null) {
52-
dynamicTests.add(DynamicTest.dynamicTest(file, () -> assertTrue(
53-
isValidJson(schemaVersion, "/" + schemaVersion.getVersionString() + "/" + file), file)));
54-
} else if (file.startsWith("invalid") && schemaVersion != null) {
55-
dynamicTests.add(DynamicTest.dynamicTest(file, () -> assertFalse(
56-
isValidJson(schemaVersion, "/" + schemaVersion.getVersionString() + "/" + file), file)));
96+
for (final String resource : resources) {
97+
String resourceName = StringUtils.substringAfterLast(resource, "/");
98+
if (resourceName.endsWith(".json")) {
99+
JsonSchema schema = getSchema(resourceName);
100+
if (schema != null) {
101+
if (resourceName.startsWith("valid")) {
102+
dynamicTests.add(DynamicTest.dynamicTest(
103+
resource, () -> assertTrue(isValid(schema, resource), resource)));
104+
} else if (resourceName.startsWith("invalid")) {
105+
dynamicTests.add(DynamicTest.dynamicTest(
106+
resource, () -> assertFalse(isValid(schema, resource), resource)));
107+
}
57108
}
58109
}
59110
}
60111
return dynamicTests;
61112
}
62113

63-
private boolean isValidJson(Version version, String resource) throws Exception {
64-
final File file = new File(this.getClass().getResource(resource).getFile());
65-
final JsonParser parser = new JsonParser();
66-
return parser.isValid(file, version);
67-
68-
// Uncomment to provide more detailed validation errors
69-
/*
70-
try {
71-
final String jsonString = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
72-
parser.getJsonSchema(version, true).validate(new JSONObject(jsonString));
73-
return true;
74-
} catch (ValidationException e) {
75-
e.printStackTrace();
114+
private boolean isValid(JsonSchema schema, String resource) {
115+
try (InputStream input = getClass().getClassLoader().getResourceAsStream(resource);
116+
JsonParser parser = MAPPER.createParser(input)) {
117+
JsonNode node = parser.readValueAsTree();
118+
return schema.validate(node).isEmpty();
119+
} catch (IOException e) {
76120
return false;
77121
}
78-
*/
122+
}
123+
124+
private JsonSchema getSchema(String resourceName) {
125+
if (resourceName.endsWith("-1.2.json")) {
126+
return VERSION_12;
127+
}
128+
if (resourceName.endsWith("-1.3.json")) {
129+
return VERSION_13;
130+
}
131+
if (resourceName.endsWith("-1.4.json")) {
132+
return VERSION_14;
133+
}
134+
if (resourceName.endsWith("-1.5.json")) {
135+
return VERSION_15;
136+
}
137+
if (resourceName.endsWith("-1.6.json")) {
138+
return VERSION_16;
139+
}
140+
return null;
79141
}
80142
}

0 commit comments

Comments
 (0)