Skip to content

Commit

Permalink
Validation tests in the TS layer
Browse files Browse the repository at this point in the history
  • Loading branch information
EricWittmann committed Jan 18, 2023
1 parent 0734792 commit 47b2ee1
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 45 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
<version.org.codehaus.mojo.exec-maven-plugin>3.1.0</version.org.codehaus.mojo.exec-maven-plugin>
<version.com.github.eirslett.frontend-maven-plugin>1.12.1</version.com.github.eirslett.frontend-maven-plugin>
<version.org.sonatype.plugins.nexus-staging-maven-plugin>1.6.13</version.org.sonatype.plugins.nexus-staging-maven-plugin>
<version.apicurio-unified-model-generator-plugin>1.0.8.Final</version.apicurio-unified-model-generator-plugin>
<version.apicurio-unified-model-generator-plugin>1.0.9-SNAPSHOT</version.apicurio-unified-model-generator-plugin>
<version.jsweet-maven-plugin>3.1.0</version.jsweet-maven-plugin>
</properties>

Expand Down
76 changes: 37 additions & 39 deletions src/main/ts/tests/util/tutils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {ValidationProblemSeverity} from "../../src/io/apicurio/datamodels/validation/ValidationProblemSeverity";
import {ValidationProblem} from "../../src/io/apicurio/datamodels/validation/ValidationProblem";

var fs = require("fs");
const fs = require("fs");

export function readJSON(path: string): any {
let fileContent: string = fs.readFileSync(path);
Expand All @@ -15,42 +17,38 @@ export function readTXT(path: string): string {
return "";
}

//
// export function formatSeverity(severity: ValidationProblemSeverity): string {
// if (severity == ValidationProblemSeverity.ignore) {
// return "ignore";
// } else if (severity == ValidationProblemSeverity.low) {
// return "low";
// } else if (severity == ValidationProblemSeverity.medium) {
// return "medium";
// } else if (severity == ValidationProblemSeverity.high) {
// return "high";
// }
// }
//
//
// export function readSeverity(severity: string): ValidationProblemSeverity {
// if (severity == "ignore") {
// return ValidationProblemSeverity.ignore;
// } else if (severity == "low") {
// return ValidationProblemSeverity.low;
// } else if (severity == "medium") {
// return ValidationProblemSeverity.medium;
// } else if (severity == "high") {
// return ValidationProblemSeverity.high;
// }
// }

//
// export function formatProblems(problems: ValidationProblem[]): string[] {
// let es: string[] = [];
// problems.forEach(problem => {
// es.push(`[${problem.errorCode}] |${formatSeverity(problem.severity)}| {${problem.nodePath.toString()}->${problem.property}} :: ${problem.message}`);
// });
// return es;
// }


export function normalize(value: string): string {
return value.trim().replace("\r\n", "\n");

export function formatSeverity(severity: ValidationProblemSeverity): string {
if (severity == ValidationProblemSeverity.ignore) {
return "ignore";
} else if (severity == ValidationProblemSeverity.low) {
return "low";
} else if (severity == ValidationProblemSeverity.medium) {
return "medium";
} else if (severity == ValidationProblemSeverity.high) {
return "high";
}
}


export function readSeverity(severity: string): ValidationProblemSeverity {
if (severity == "ignore") {
return ValidationProblemSeverity.ignore;
} else if (severity == "low") {
return ValidationProblemSeverity.low;
} else if (severity == "medium") {
return ValidationProblemSeverity.medium;
} else if (severity == "high") {
return ValidationProblemSeverity.high;
}
}


export function formatProblems(problems: ValidationProblem[]): string[] {
let es: string[] = [];
problems.forEach(problem => {
es.push(`[${problem.errorCode}] |${formatSeverity(problem.severity)}| {${problem.nodePath.toString(true)}->${problem.property}} :: ${problem.message}`);
});
return es;
}

106 changes: 106 additions & 0 deletions src/main/ts/tests/validation.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@

import {Library} from "../src/io/apicurio/datamodels/Library";
import {readJSON} from "./util/tutils";
import {readTXT} from "./util/tutils";
import {formatProblems} from "./util/tutils";
import {readSeverity} from "./util/tutils";
import {IValidationSeverityRegistry} from "../src/io/apicurio/datamodels/validation/IValidationSeverityRegistry";
import {ValidationProblemSeverity} from "../src/io/apicurio/datamodels/validation/ValidationProblemSeverity";
import {IReferenceResolver} from "../src/io/apicurio/datamodels/refs/IReferenceResolver";
import {ReferenceUtil} from "../src/io/apicurio/datamodels/refs/ReferenceUtil";
import {Node} from "../src/io/apicurio/datamodels/models/Node";
import {Document} from "../src/io/apicurio/datamodels/models/Document";
import {ValidationProblem} from "../src/io/apicurio/datamodels/validation/ValidationProblem";


interface TestSpec {
name: string;
test: string;
severity?: string;
}

class CustomSeverityRegistry implements IValidationSeverityRegistry {

constructor(private severity: ValidationProblemSeverity) {}

public lookupSeverity(): ValidationProblemSeverity {
return this.severity;
}

}

class ValidationTestReferenceResolver implements IReferenceResolver {

public resolveRef(reference: string, from: Node): Node {
if (!reference) {
return null;
}
if (reference.indexOf("test:") != 0) {
return null;
}

let colonIdx: number = reference.indexOf(":");
let hashIdx: number = reference.indexOf("#");
let resourceName: string = reference.substring(colonIdx + 1, hashIdx);
if (!resourceName) {
throw "Invalid resource name from reference: " + reference;
}
let fragment: string = reference.substring(hashIdx + 1);
if (!fragment) {
throw "Invalid fragment from reference: " + reference;
}
let content: any = readJSON("tests/fixtures/validation/shared/" + resourceName);
if (!resourceName) {
throw "Failed to load JSON from reference: " + reference;
}
let resolvedContent: any = ReferenceUtil.resolveFragmentFromJS(content, fragment);
if (!resourceName) {
throw "Failed to resolve content for reference: " + reference;
}
return this.toModel(resolvedContent, from);
}

public toModel(jsonNode: any, from: Node): Node {
let rval: Node = from.emptyClone();
rval.attach(from.parent());
return Library.readNode(jsonNode, rval);
}

}
Library.addReferenceResolver(new ValidationTestReferenceResolver());


let allTests: TestSpec[] = readJSON("tests/fixtures/validation/tests.json");
allTests.forEach(spec => {
test(spec.name, () => {
// Read the source JSON file
let testPath: string = "tests/fixtures/validation/" + spec.test;
let json: any = readJSON(testPath);
expect(json).not.toBeNull();

// Parse/read the document
let document: Document = Library.readDocument(json);

// Validate the document
let severityRegistry: IValidationSeverityRegistry = null;
if (spec.severity) {
severityRegistry = new CustomSeverityRegistry(readSeverity(spec.severity));
}
let problems: ValidationProblem[] = Library.validate(document, severityRegistry);

// Format the list of problems into a string for comparison with the expected value
let actual: string[] = formatProblems(problems);

// Load the expected result and compare with actual
let expectedStr: string = readTXT(testPath + ".expected");
expect(expectedStr).not.toBeNull();
let expected: string[] = [];
if (expectedStr) {
expected = expectedStr.split(/\r?\n/);
expected = expected.filter(val => val != null && val != undefined && val != "");
}
actual.sort();
expected.sort();
expect(actual).toEqual(expected);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
import io.apicurio.datamodels.Library;
import io.apicurio.datamodels.models.Document;
import io.apicurio.datamodels.models.Node;
import io.apicurio.datamodels.models.openapi.v30.OpenApi30SchemaImpl;
import io.apicurio.datamodels.models.util.JsonUtil;
import io.apicurio.datamodels.refs.IReferenceResolver;
import io.apicurio.datamodels.refs.ReferenceUtil;
Expand Down Expand Up @@ -236,11 +235,9 @@ public Node resolveRef(String reference, Node from) {
Assert.assertNotNull("Failed to load test resource: " + resourceName, resourceContent);
ObjectNode content = (ObjectNode) JsonUtil.parseJSON(resourceContent);
Assert.assertNotNull("Could not parse test resource: " + resourceName, content);
ObjectNode resolvedContent = (ObjectNode) ReferenceUtil.resolveFragmentFromJS(content, fragment);
ObjectNode resolvedContent = ReferenceUtil.resolveFragmentFromJS(content, fragment);
Assert.assertNotNull("Failed to resolve fragment: " + fragment, resolvedContent);
// TODO clone the "from" node to a new empty impl. For now, hard-code it.
//Node emptyClone = ModelCloner.createEmptyClone(from);
Node emptyClone = new OpenApi30SchemaImpl();
Node emptyClone = from.emptyClone();
emptyClone.attach(from.parent());
return Library.readNode(resolvedContent, emptyClone);
}
Expand Down

0 comments on commit 47b2ee1

Please sign in to comment.