1
2
3
4
5
6 package gov.nist.secauto.metaschema.cli;
7
8 import static org.assertj.core.api.Assertions.assertThat;
9 import static org.junit.jupiter.api.Assertions.assertAll;
10 import static org.junit.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertNull;
12
13 import gov.nist.secauto.metaschema.cli.processor.ExitCode;
14 import gov.nist.secauto.metaschema.cli.processor.ExitStatus;
15
16 import org.junit.jupiter.api.Test;
17 import org.junit.jupiter.params.ParameterizedTest;
18 import org.junit.jupiter.params.provider.Arguments;
19 import org.junit.jupiter.params.provider.MethodSource;
20
21 import java.util.LinkedList;
22 import java.util.List;
23 import java.util.stream.Stream;
24
25 import edu.umd.cs.findbugs.annotations.NonNull;
26 import nl.altindag.log.LogCaptor;
27
28
29
30
31 public class CLITest {
32 private static final ExitCode NO_EXCEPTION_CLASS = null;
33
34 void evaluateResult(@NonNull ExitStatus status, @NonNull ExitCode expectedCode) {
35 status.generateMessage(true);
36 assertAll(() -> assertEquals(expectedCode, status.getExitCode(), "exit code mismatch"),
37 () -> assertNull(status.getThrowable(), "expected null Throwable"));
38 }
39
40 void evaluateResult(@NonNull ExitStatus status, @NonNull ExitCode expectedCode,
41 @NonNull Class<? extends Throwable> thrownClass) {
42 Throwable thrown = status.getThrowable();
43 assertAll(
44 () -> assertEquals(expectedCode, status.getExitCode(), "exit code mismatch"),
45 () -> assertEquals(thrownClass, thrown == null ? null : thrown.getClass(), "expected Throwable mismatch"));
46 }
47
48 private static Stream<Arguments> providesValues() {
49 @SuppressWarnings("serial")
50 List<Arguments> values = new LinkedList<>() {
51 {
52 add(Arguments.of(new String[] {}, ExitCode.INVALID_COMMAND,
53 NO_EXCEPTION_CLASS));
54 add(Arguments.of(new String[] { "-h" }, ExitCode.OK, NO_EXCEPTION_CLASS));
55 add(Arguments.of(new String[] { "generate-schema", "--help" }, ExitCode.OK,
56 NO_EXCEPTION_CLASS));
57 add(Arguments.of(new String[] { "generate-diagram", "--help" }, ExitCode.OK,
58 NO_EXCEPTION_CLASS));
59 add(Arguments.of(new String[] { "validate", "--help" }, ExitCode.OK,
60 NO_EXCEPTION_CLASS));
61 add(Arguments.of(new String[] { "validate-content", "--help" }, ExitCode.OK,
62 NO_EXCEPTION_CLASS));
63 add(Arguments.of(new String[] { "convert", "--help" }, ExitCode.OK,
64 NO_EXCEPTION_CLASS));
65 add(Arguments.of(new String[] { "metapath", "list-functions", "--help" }, ExitCode.OK,
66 NO_EXCEPTION_CLASS));
67 add(Arguments.of(new String[] { "metapath", "eval", "--help" }, ExitCode.OK,
68 NO_EXCEPTION_CLASS));
69 add(Arguments.of(
70 new String[] { "validate",
71 "../databind/src/test/resources/metaschema/fields_with_flags/metaschema.xml"
72 },
73 ExitCode.OK, NO_EXCEPTION_CLASS));
74 add(Arguments.of(
75 new String[] { "generate-schema", "--overwrite", "--as",
76 "JSON",
77 "../databind/src/test/resources/metaschema/fields_with_flags/metaschema.xml",
78 "target/schema-test.json" },
79 ExitCode.OK, NO_EXCEPTION_CLASS));
80 add(Arguments.of(
81 new String[] { "validate-content", "--as=xml",
82 "-m=../databind/src/test/resources/metaschema/bad_index-has-key/metaschema.xml",
83 "../databind/src/test/resources/metaschema/bad_index-has-key/example.xml",
84 "--show-stack-trace" },
85 ExitCode.FAIL, NO_EXCEPTION_CLASS));
86 add(Arguments.of(
87 new String[] { "validate-content", "--as=json",
88 "-m=../databind/src/test/resources/metaschema/bad_index-has-key/metaschema.xml",
89 "../databind/src/test/resources/metaschema/bad_index-has-key/example.json", "--show-stack-trace" },
90 ExitCode.FAIL, NO_EXCEPTION_CLASS));
91 add(Arguments.of(
92 new String[] { "validate",
93 "../databind/src/test/resources/metaschema/simple/metaschema.xml",
94 "--show-stack-trace" },
95 ExitCode.OK, NO_EXCEPTION_CLASS));
96 add(Arguments.of(
97 new String[] { "generate-schema",
98 "../databind/src/test/resources/metaschema/simple/metaschema.xml",
99 "--as", "xml",
100 },
101 ExitCode.OK, NO_EXCEPTION_CLASS));
102 add(Arguments.of(
103 new String[] { "generate-schema",
104 "../databind/src/test/resources/metaschema/simple/metaschema.xml",
105 "--as", "json",
106 },
107 ExitCode.OK, NO_EXCEPTION_CLASS));
108 add(Arguments.of(
109 new String[] { "generate-diagram",
110 "../databind/src/test/resources/metaschema/simple/metaschema.xml"
111 },
112 ExitCode.OK, NO_EXCEPTION_CLASS));
113 add(Arguments.of(
114 new String[] { "validate-content",
115 "-m",
116 "../databind/src/test/resources/metaschema/simple/metaschema.xml",
117 "../databind/src/test/resources/metaschema/simple/example.json",
118 "--as=json"
119 },
120 ExitCode.OK, NO_EXCEPTION_CLASS));
121 add(Arguments.of(
122 new String[] { "validate-content",
123 "-m",
124 "../databind/src/test/resources/metaschema/simple/metaschema.xml",
125 "../databind/src/test/resources/metaschema/simple/example.xml",
126 "--as=xml"
127 },
128 ExitCode.OK, NO_EXCEPTION_CLASS));
129 add(Arguments.of(
130 new String[] { "validate-content",
131 "-m",
132 "../databind/src/test/resources/metaschema/simple/metaschema.xml",
133 "https://bad.domain.example.net/example.xml",
134 "--as=xml"
135 },
136 ExitCode.IO_ERROR, java.net.UnknownHostException.class));
137 add(Arguments.of(
138 new String[] { "validate-content",
139 "-m",
140 "../databind/src/test/resources/metaschema/simple/metaschema.xml",
141 "https://github.com/no-example.xml",
142 "--as=xml"
143 },
144 ExitCode.IO_ERROR, java.io.FileNotFoundException.class));
145 add(Arguments.of(
146 new String[] { "validate-content",
147 "-m",
148 "src/test/resources/content/schema-validation-module.xml",
149 "src/test/resources/content/schema-validation-module-missing-required.xml",
150 "--as=xml"
151 },
152
153 ExitCode.FAIL, NO_EXCEPTION_CLASS));
154 add(Arguments.of(
155 new String[] { "validate-content",
156 "-m",
157 "src/test/resources/content/schema-validation-module.xml",
158 "src/test/resources/content/schema-validation-module-missing-required.xml",
159 "--as=xml",
160 "--disable-schema-validation"
161 },
162
163 ExitCode.FAIL, NO_EXCEPTION_CLASS));
164 add(Arguments.of(
165 new String[] { "validate-content",
166 "-m",
167 "src/test/resources/content/schema-validation-module.xml",
168 "src/test/resources/content/schema-validation-module-missing-required.xml",
169 "--as=xml",
170 "--disable-schema-validation",
171 "--disable-constraint-validation"
172 },
173 ExitCode.OK, NO_EXCEPTION_CLASS));
174 add(Arguments.of(
175 new String[] { "metapath", "list-functions" },
176 ExitCode.OK, NO_EXCEPTION_CLASS));
177 add(Arguments.of(
178 new String[] { "convert",
179 "-m",
180 "../core/metaschema/schema/metaschema/metaschema-module-metaschema.xml",
181 "--to=yaml",
182 "../core/metaschema/schema/metaschema/metaschema-module-metaschema.xml",
183 },
184 ExitCode.OK, NO_EXCEPTION_CLASS));
185 }
186 };
187 return values.stream();
188 }
189
190 @ParameterizedTest
191 @MethodSource("providesValues")
192 void testAllCommands(@NonNull String[] args, @NonNull ExitCode expectedExitCode,
193 Class<? extends Throwable> expectedThrownClass) {
194 String[] defaultArgs = { "--show-stack-trace" };
195 String[] fullArgs = Stream.of(args, defaultArgs).flatMap(Stream::of)
196 .toArray(String[]::new);
197 if (expectedThrownClass == null) {
198 evaluateResult(CLI.runCli(fullArgs), expectedExitCode);
199 } else {
200 evaluateResult(CLI.runCli(fullArgs), expectedExitCode, expectedThrownClass);
201 }
202 }
203
204 @Test
205 void test() {
206 try (LogCaptor captor = LogCaptor.forRoot()) {
207 String[] cliArgs = { "validate-content",
208 "-m",
209 "src/test/resources/content/215-module.xml",
210 "src/test/resources/content/215.xml",
211 "--disable-schema-validation"
212 };
213 CLI.runCli(cliArgs);
214 assertThat(captor.getErrorLogs().toString())
215 .contains("expect-default-non-zero: Expect constraint '. > 0' did not match the data",
216 "expect-custom-non-zero: No default message, custom error message for expect-custom-non-zero constraint.",
217 "matches-default-regex-letters-only: Value '1' did not match the pattern",
218 "matches-custom-regex-letters-only: No default message, custom error message for matches-custom-regex-letters-only constraint.",
219 "cardinality-default-two-minimum: The cardinality '1' is below the required minimum '2' for items matching",
220 "index-items-default: Index 'index-items-default' has duplicate key for items",
221 "index-items-custom: No default message, custom error message for index-item-custom.",
222 "is-unique-default: Unique constraint violation at paths",
223 "is-unique-custom: No default message, custom error message for is-unique-custom.",
224 "index-has-key-default: Key reference [2] not found in index 'index-items-default' for item",
225 "index-has-key-custom: No default message, custom error message for index-has-key-custom.");
226 }
227 }
228 }