From 1e28414e659a273342b4b9a27b9e8e8f995d3f93 Mon Sep 17 00:00:00 2001 From: "A.J. Stein" Date: Thu, 25 Jan 2024 21:32:51 -0500 Subject: [PATCH] CLI commands allow files or URIs for #297 This PR adjusts the commands and supporting databind classes and ports them to use URIs. The commands will use the new UriUtils class and the toUri() function to use a remote URI supported as a URL and load the model, schema, or target file. If a local file, it will convert the file path to valid URI. Integration tests have been added to validate this functionality works with the update CLI commands. --- .../metaschema/databind/IBindingContext.java | 7 +- .../databind/io/yaml/YamlOperations.java | 14 +-- .../AbstractBoundDefinitionModelComplex.java | 3 +- .../AbstractValidateContentCommand.java | 59 ++++------ .../cli/commands/GenerateSchemaCommand.java | 22 ++-- .../ValidateContentUsingModuleCommand.java | 47 +++++--- .../cli/commands/ValidateModuleCommand.java | 27 ++--- .../nist/secauto/metaschema/cli/CLITest.java | 102 ++++++++++++------ 8 files changed, 163 insertions(+), 118 deletions(-) diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/IBindingContext.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/IBindingContext.java index 5c99b0580..84c6bfb00 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/IBindingContext.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/IBindingContext.java @@ -60,6 +60,7 @@ import java.io.IOException; import java.math.BigInteger; +import java.net.URI; import java.nio.file.Path; import java.time.ZonedDateTime; import java.util.List; @@ -346,7 +347,7 @@ default IValidationResult validate(@NonNull INodeItem nodeItem) { * if an error occurred when parsing the target as XML */ default IValidationResult validate( - @NonNull Path target, + @NonNull URI target, @NonNull Format asFormat, @NonNull IValidationSchemaProvider schemaProvider) throws IOException, SAXException { IValidationResult retval; @@ -362,7 +363,7 @@ default IValidationResult validate( JSONObject json = YamlOperations.yamlToJson(YamlOperations.parseYaml(target)); assert json != null; retval = new JsonSchemaContentValidator(schemaProvider.getJsonSchema()) - .validate(json, ObjectUtils.notNull(target.toUri())); + .validate(json, ObjectUtils.notNull(target)); break; default: throw new UnsupportedOperationException("Unsupported format: " + asFormat.name()); @@ -385,7 +386,7 @@ default IValidationResult validate( * @throws IOException * if an error occurred while loading the document */ - default IValidationResult validateWithConstraints(@NonNull Path target) throws IOException { + default IValidationResult validateWithConstraints(@NonNull URI target) throws IOException { IBoundLoader loader = newBoundLoader(); loader.disableFeature(DeserializationFeature.DESERIALIZE_VALIDATE_CONSTRAINTS); diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/yaml/YamlOperations.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/yaml/YamlOperations.java index d200af7f7..3f49fa1df 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/yaml/YamlOperations.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/yaml/YamlOperations.java @@ -26,6 +26,8 @@ package gov.nist.secauto.metaschema.databind.io.yaml; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; + import org.json.JSONException; import org.json.JSONObject; import org.yaml.snakeyaml.DumperOptions; @@ -36,11 +38,9 @@ import org.yaml.snakeyaml.representer.Representer; import org.yaml.snakeyaml.resolver.Resolver; -import java.io.BufferedReader; import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; +import java.io.InputStream; +import java.net.URI; import java.util.Map; import edu.umd.cs.findbugs.annotations.NonNull; @@ -84,9 +84,9 @@ private YamlOperations() { */ @SuppressWarnings({ "unchecked", "null" }) @NonNull - public static Map parseYaml(Path target) throws IOException { - try (BufferedReader reader = Files.newBufferedReader(target.toAbsolutePath(), StandardCharsets.UTF_8)) { - return (Map) YAML_PARSER.load(reader); + public static Map parseYaml(URI target) throws IOException { + try (InputStream is = ObjectUtils.notNull(target.toURL().openStream())) { + return (Map) YAML_PARSER.load(is); } } diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/AbstractBoundDefinitionModelComplex.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/AbstractBoundDefinitionModelComplex.java index f2e1bb716..64d613e47 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/AbstractBoundDefinitionModelComplex.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/model/impl/AbstractBoundDefinitionModelComplex.java @@ -120,8 +120,7 @@ public IBindingContext getBindingContext() { public CLASS newInstance() { Class clazz = getBoundClass(); try { - @SuppressWarnings("unchecked") - Constructor constructor + @SuppressWarnings("unchecked") Constructor constructor = (Constructor) clazz.getDeclaredConstructor(); return ObjectUtils.notNull(constructor.newInstance()); } catch (NoSuchMethodException ex) { diff --git a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java index ced64684f..821df1750 100644 --- a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java +++ b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java @@ -44,6 +44,7 @@ import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.metaschema.core.util.CustomCollectors; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.util.UriUtils; import gov.nist.secauto.metaschema.databind.IBindingContext; import gov.nist.secauto.metaschema.databind.IBindingContext.IValidationSchemaProvider; import gov.nist.secauto.metaschema.databind.io.Format; @@ -58,8 +59,8 @@ import java.io.FileNotFoundException; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; +import java.net.URI; +import java.net.URISyntaxException; import java.nio.file.Paths; import java.util.Arrays; import java.util.Collection; @@ -91,7 +92,7 @@ public abstract class AbstractValidateContentCommand private static final Option CONSTRAINTS_OPTION = ObjectUtils.notNull( Option.builder("c") .hasArg() - .argName("FILE") + .argName("URI") .desc("additional constraint definitions") .build()); @@ -116,38 +117,6 @@ public List getExtraArguments() { @SuppressWarnings("PMD.PreserveStackTrace") // intended @Override public void validateOptions(CallingContext callingContext, CommandLine cmdLine) throws InvalidArgumentException { - if (cmdLine.hasOption(CONSTRAINTS_OPTION)) { - String[] args = cmdLine.getOptionValues(CONSTRAINTS_OPTION); - for (String arg : args) { - Path constraint = Paths.get(arg); - if (!Files.exists(constraint)) { - throw new InvalidArgumentException( - "The provided external constraint file '" + constraint + "' does not exist."); - } - if (!Files.isRegularFile(constraint)) { - throw new InvalidArgumentException( - "The provided external constraint file '" + constraint + "' is not a file."); - } - if (!Files.isReadable(constraint)) { - throw new InvalidArgumentException( - "The provided external constraint file '" + constraint + "' is not readable."); - } - } - } - - List extraArgs = cmdLine.getArgList(); - if (extraArgs.size() != 1) { - throw new InvalidArgumentException("The source to validate must be provided."); - } - - Path source = Paths.get(extraArgs.get(0)); - if (!Files.exists(source)) { - throw new InvalidArgumentException("The provided source file '" + source + "' does not exist."); - } - if (!Files.isReadable(source)) { - throw new InvalidArgumentException("The provided source file '" + source + "' is not readable."); - } - if (cmdLine.hasOption(AS_OPTION)) { try { String toFormatText = cmdLine.getOptionValue(AS_OPTION); @@ -182,6 +151,7 @@ protected abstract IBindingContext getBindingContext(@NonNull Set constraintSets; @@ -190,11 +160,10 @@ public ExitStatus execute() { constraintSets = new LinkedHashSet<>(); String[] args = cmdLine.getOptionValues(CONSTRAINTS_OPTION); for (String arg : args) { - Path constraintPath = Paths.get(arg); - assert constraintPath != null; try { - constraintSets.add(constraintLoader.load(constraintPath)); - } catch (IOException | MetaschemaException ex) { + URI constraintUri = ObjectUtils.requireNonNull(UriUtils.toUri(arg, cwd)); + constraintSets.add(constraintLoader.load(constraintUri)); + } catch (IOException | MetaschemaException | URISyntaxException ex) { return ExitCode.IO_ERROR.exitMessage("Unable to load constraint set '" + arg + "'.").withThrowable(ex); } } @@ -213,8 +182,16 @@ public ExitStatus execute() { IBoundLoader loader = bindingContext.newBoundLoader(); List extraArgs = cmdLine.getArgList(); - @SuppressWarnings("null") Path source = resolvePathAgainstCWD(Paths.get(extraArgs.get(0))); - assert source != null; + // @SuppressWarnings("null") + String sourceName = extraArgs.get(0); + URI source; + + try { + source = UriUtils.toUri(sourceName, cwd); + } catch (URISyntaxException ex) { + return ExitCode.IO_ERROR.exitMessage("Cannot load source '%s' as it is not a valid file or URI.") + .withThrowable(ex); + } Format asFormat; if (cmdLine.hasOption(AS_OPTION)) { diff --git a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/GenerateSchemaCommand.java b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/GenerateSchemaCommand.java index 9f8a888ca..344c886d1 100644 --- a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/GenerateSchemaCommand.java +++ b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/GenerateSchemaCommand.java @@ -42,6 +42,7 @@ import gov.nist.secauto.metaschema.core.model.xml.ModuleLoader; import gov.nist.secauto.metaschema.core.util.CustomCollectors; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.util.UriUtils; import gov.nist.secauto.metaschema.databind.io.Format; import gov.nist.secauto.metaschema.schemagen.ISchemaGenerator; import gov.nist.secauto.metaschema.schemagen.ISchemaGenerator.SchemaFormat; @@ -54,6 +55,8 @@ import java.io.IOException; import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -148,14 +151,6 @@ public void validateOptions(CallingContext callingContext, CommandLine cmdLine) if (extraArgs.isEmpty() || extraArgs.size() > 2) { throw new InvalidArgumentException("Illegal number of arguments."); } - - Path module = Paths.get(extraArgs.get(0)); - if (!Files.exists(module)) { - throw new InvalidArgumentException("The provided metaschema module '" + module + "' does not exist."); - } - if (!Files.isReadable(module)) { - throw new InvalidArgumentException("The provided metaschema module '" + module + "' is not readable."); - } } @Override @@ -171,6 +166,7 @@ protected ExitStatus executeCommand( @NonNull CallingContext callingContext, @NonNull CommandLine cmdLine) { List extraArgs = cmdLine.getArgList(); + URI cwd = Paths.get("").toUri(); Path destination = null; if (extraArgs.size() > 1) { @@ -214,7 +210,15 @@ protected ExitStatus executeCommand( } } - Path input = Paths.get(extraArgs.get(0)); + URI input; + String inputName = extraArgs.get(0); + + try { + input = UriUtils.toUri(extraArgs.get(0), cwd); + } catch (URISyntaxException ex) { + return ExitCode.IO_ERROR.exitMessage( + String.format("Unable to load '%s' as it is not a valid file or URI.", inputName)).withThrowable(ex); + } assert input != null; try { ModuleLoader loader = new ModuleLoader(); diff --git a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/ValidateContentUsingModuleCommand.java b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/ValidateContentUsingModuleCommand.java index 25529fb5a..586049336 100644 --- a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/ValidateContentUsingModuleCommand.java +++ b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/ValidateContentUsingModuleCommand.java @@ -40,6 +40,7 @@ import gov.nist.secauto.metaschema.core.model.xml.ModuleLoader; import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.util.UriUtils; import gov.nist.secauto.metaschema.databind.IBindingContext; import gov.nist.secauto.metaschema.schemagen.ISchemaGenerator; import gov.nist.secauto.metaschema.schemagen.ISchemaGenerator.SchemaFormat; @@ -51,6 +52,8 @@ import java.io.BufferedReader; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -92,16 +95,19 @@ public Collection gatherOptions() { @Override public void validateOptions(CallingContext callingContext, CommandLine cmdLine) throws InvalidArgumentException { - super.validateOptions(callingContext, cmdLine); - - String metaschemaName = cmdLine.getOptionValue(MetaschemaCommandSupport.METASCHEMA_OPTION); - Path metaschema = Paths.get(metaschemaName); - if (!Files.exists(metaschema)) { - throw new InvalidArgumentException("The provided module '" + metaschema + "' does not exist."); - } - if (!Files.isReadable(metaschema)) { - throw new InvalidArgumentException("The provided module '" + metaschema + "' is not readable."); - } + // super.validateOptions(callingContext, cmdLine); + // + // String metaschemaName = + // cmdLine.getOptionValue(MetaschemaCommandSupport.METASCHEMA_OPTION); + // Path metaschema = Paths.get(metaschemaName); + // if (!Files.exists(metaschema)) { + // throw new InvalidArgumentException("The provided module '" + metaschema + "' + // does not exist."); + // } + // if (!Files.isReadable(metaschema)) { + // throw new InvalidArgumentException("The provided module '" + metaschema + "' + // is not readable."); + // } } @Override @@ -132,17 +138,30 @@ private Path getTempDir() throws IOException { @NonNull private IModule getModule(@NonNull Set constraintSets) throws MetaschemaException, IOException { + URI cwd = Paths.get("").toUri(); + if (module == null) { - String moduleName = getCommandLine().getOptionValue(MetaschemaCommandSupport.METASCHEMA_OPTION); - Path modulePath = Paths.get(moduleName); - assert modulePath != null; + String moduleName + = ObjectUtils.requireNonNull(getCommandLine().getOptionValue(MetaschemaCommandSupport.METASCHEMA_OPTION)); + URI moduleUri; + + try { + moduleUri = UriUtils.toUri(moduleName, cwd); + } catch (URISyntaxException ex) { + IOException newEx = new IOException( // NOPMD - intentional + String.format("Cannot load module as '%s' is not a valid file or URL.", moduleName)); + newEx.addSuppressed(ex); + throw newEx; + } + + assert moduleUri != null; ExternalConstraintsModulePostProcessor postProcessor = new ExternalConstraintsModulePostProcessor(constraintSets); ModuleLoader loader = new ModuleLoader(CollectionUtil.singletonList(postProcessor)); loader.allowEntityResolution(); - module = loader.load(modulePath); + module = loader.load(moduleUri); } assert module != null; return module; diff --git a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/ValidateModuleCommand.java b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/ValidateModuleCommand.java index 9d62cc459..8266f52c5 100644 --- a/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/ValidateModuleCommand.java +++ b/metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/ValidateModuleCommand.java @@ -42,15 +42,16 @@ import gov.nist.secauto.metaschema.core.model.xml.ModuleLoader; import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.metaschema.core.util.ObjectUtils; +import gov.nist.secauto.metaschema.core.util.UriUtils; import org.apache.commons.cli.CommandLine; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.xml.sax.SAXException; -import java.io.File; import java.io.IOException; -import java.nio.file.Path; +import java.net.URI; +import java.net.URISyntaxException; import java.nio.file.Paths; import java.util.LinkedList; import java.util.List; @@ -103,14 +104,6 @@ public void validateOptions(CallingContext callingContext, CommandLine cmdLine) if (extraArgs.size() != 1) { throw new InvalidArgumentException("The source to validate must be provided."); } - - File target = new File(extraArgs.get(0)); - if (!target.exists()) { - throw new InvalidArgumentException("The provided source file '" + target.getPath() + "' does not exist."); - } - if (!target.canRead()) { - throw new InvalidArgumentException("The provided source file '" + target.getPath() + "' is not readable."); - } } @Override @@ -121,15 +114,25 @@ public ICommandExecutor newExecutor(CallingContext callingContext, CommandLine c @SuppressWarnings({ "PMD.OnlyOneReturn", "unused" }) // readability @NonNull protected ExitStatus executeCommand(CallingContext callingContext, CommandLine cmdLine) { + URI cwd = Paths.get("").toUri(); List extraArgs = cmdLine.getArgList(); - Path target = Paths.get(extraArgs.get(0)); + String targetName = extraArgs.get(0); + URI target; + + try { + target = UriUtils.toUri(targetName, cwd); + } catch (URISyntaxException ex) { + return ExitCode.PROCESSING_ERROR + .exitMessage(String.format("The target '%s' cannot be loaded as it is not a valid file or URL.", targetName)); + } + assert target != null; IValidationResult schemaValidationResult; try { List schemaSources = getXmlSchemaSources(); schemaValidationResult = IContentValidator.validateWithXmlSchema( - ObjectUtils.notNull(target.toUri()), + ObjectUtils.notNull(target), schemaSources); } catch (IOException | SAXException ex) { return ExitCode.PROCESSING_ERROR.exit().withThrowable(ex); diff --git a/metaschema-cli/src/test/java/gov/nist/secauto/metaschema/cli/CLITest.java b/metaschema-cli/src/test/java/gov/nist/secauto/metaschema/cli/CLITest.java index 58efc831b..4965f3449 100644 --- a/metaschema-cli/src/test/java/gov/nist/secauto/metaschema/cli/CLITest.java +++ b/metaschema-cli/src/test/java/gov/nist/secauto/metaschema/cli/CLITest.java @@ -37,7 +37,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.stream.Stream; @@ -47,6 +47,8 @@ * Unit test for simple CLI. */ public class CLITest { + private static final ExitCode NO_EXPECTION_CLASS = null; + void evaluateResult(@NonNull ExitStatus status, @NonNull ExitCode expectedCode) { status.generateMessage(true); assertAll(() -> assertEquals(expectedCode, status.getExitCode(), "exit code mismatch"), @@ -63,33 +65,70 @@ void evaluateResult(@NonNull ExitStatus status, @NonNull ExitCode expectedCode, } private static Stream providesValues() { - ExitCode noExpectedExceptionClass = null; - List 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)); + ExitCode NO_EXCEPTION_CLASS = null; + List values = new LinkedList<>() { + { + add(Arguments.of(new String[] {}, ExitCode.INVALID_COMMAND, NO_EXCEPTION_CLASS)); + add(Arguments.of(new String[] { "-h" }, ExitCode.OK, NO_EXCEPTION_CLASS)); + add(Arguments.of(new String[] { "generate-schema", "--help" }, ExitCode.INVALID_COMMAND, + NO_EXCEPTION_CLASS)); + add(Arguments.of(new String[] { "validate", "--help" }, ExitCode.OK, NO_EXCEPTION_CLASS)); + add(Arguments.of(new String[] { "validate-content", "--help" }, ExitCode.INVALID_COMMAND, + NO_EXCEPTION_CLASS)); + add(Arguments.of( + new String[] { "validate", + "../databind/src/test/resources/metaschema/fields_with_flags/metaschema.xml" }, + ExitCode.OK, NO_EXCEPTION_CLASS)); + 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, NO_EXCEPTION_CLASS)); + 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, NO_EXCEPTION_CLASS)); + 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, NO_EXCEPTION_CLASS)); + add(Arguments.of( + new String[] { "validate", + "https://raw.githubusercontent.com/usnistgov/metaschema-java/28468999d802e69273df7e725d183c132e2b15d8/databind/src/test/resources/metaschema/simple/metaschema.xml", + "--show-stack-trace" }, + ExitCode.OK, NO_EXCEPTION_CLASS)); + add(Arguments.of( + new String[] { "generate-schema", + "https://raw.githubusercontent.com/usnistgov/metaschema-java/28468999d802e69273df7e725d183c132e2b15d8/databind/src/test/resources/metaschema/simple/metaschema.xml", + "--as", "xml", + }, + ExitCode.OK, NO_EXCEPTION_CLASS)); + add(Arguments.of( + new String[] { "generate-schema", + "https://raw.githubusercontent.com/usnistgov/metaschema-java/28468999d802e69273df7e725d183c132e2b15d8/databind/src/test/resources/metaschema/simple/metaschema.xml", + "--as", "json", + }, + ExitCode.OK, NO_EXCEPTION_CLASS)); + add(Arguments.of( + new String[] { "validate-content", + "-m", + "https://raw.githubusercontent.com/usnistgov/metaschema-java/28468999d802e69273df7e725d183c132e2b15d8/databind/src/test/resources/metaschema/simple/metaschema.xml", + "https://raw.githubusercontent.com/usnistgov/metaschema-java/28468999d802e69273df7e725d183c132e2b15d8/databind/src/test/resources/metaschema/simple/example.json", + "--as=json" + }, + ExitCode.OK, NO_EXCEPTION_CLASS)); + add(Arguments.of( + new String[] { "validate-content", + "-m", + "https://raw.githubusercontent.com/usnistgov/metaschema-java/28468999d802e69273df7e725d183c132e2b15d8/databind/src/test/resources/metaschema/simple/metaschema.xml", + "https://raw.githubusercontent.com/usnistgov/metaschema-java/28468999d802e69273df7e725d183c132e2b15d8/databind/src/test/resources/metaschema/simple/example.xml", + "--as=xml" + }, + ExitCode.OK, NO_EXCEPTION_CLASS)); + } + }; + return values.stream(); } @@ -97,10 +136,13 @@ private static Stream providesValues() { @MethodSource("providesValues") void testAllCommands(@NonNull String[] args, @NonNull ExitCode expectedExitCode, Class expectedThrownClass) { + String[] defaultArgs = { "--show-stack-trace" }; + String[] fullArgs = Stream.of(args, defaultArgs).flatMap(Stream::of) + .toArray(String[]::new); if (expectedThrownClass == null) { - evaluateResult(CLI.runCli(args), expectedExitCode); + evaluateResult(CLI.runCli(fullArgs), expectedExitCode); } else { - evaluateResult(CLI.runCli(args), expectedExitCode, expectedThrownClass); + evaluateResult(CLI.runCli(fullArgs), expectedExitCode, expectedThrownClass); } } }