mirror of
https://github.com/itplr-kosit/validator.git
synced 2026-05-25 16:55:39 +00:00
parent
a41336e9cf
commit
46fff79fe2
9 changed files with 509 additions and 349 deletions
|
|
@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- read saxon XdmNode with InputFactory
|
- read saxon XdmNode with InputFactory
|
||||||
|
- [CLI] custom output without the various log messages
|
||||||
|
- [CLI] options to set the log level (`-X` = full debug output, `-l <level>` set a specific level)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- InputFactory has methods to read any java.xml.transform.Source as Input not only StreamSources
|
- InputFactory has methods to read any java.xml.transform.Source as Input not only StreamSources
|
||||||
|
|
|
||||||
|
|
@ -19,188 +19,84 @@
|
||||||
|
|
||||||
package de.kosit.validationtool.cmd;
|
package de.kosit.validationtool.cmd;
|
||||||
|
|
||||||
import java.io.IOException;
|
import static de.kosit.validationtool.cmd.CommandLineOptions.DAEMON_SIGNAL;
|
||||||
import java.net.URI;
|
import static de.kosit.validationtool.cmd.CommandLineOptions.HELP;
|
||||||
import java.nio.file.Files;
|
import static de.kosit.validationtool.cmd.CommandLineOptions.createHelpOptions;
|
||||||
import java.nio.file.Path;
|
import static de.kosit.validationtool.cmd.CommandLineOptions.createOptions;
|
||||||
import java.nio.file.Paths;
|
import static de.kosit.validationtool.cmd.CommandLineOptions.printHelp;
|
||||||
import java.util.ArrayList;
|
import static de.kosit.validationtool.impl.Printer.writeErr;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.commons.cli.CommandLineParser;
|
import org.apache.commons.cli.CommandLineParser;
|
||||||
import org.apache.commons.cli.DefaultParser;
|
import org.apache.commons.cli.DefaultParser;
|
||||||
import org.apache.commons.cli.HelpFormatter;
|
|
||||||
import org.apache.commons.cli.Option;
|
|
||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.fusesource.jansi.AnsiRenderer.Code;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import de.kosit.validationtool.cmd.report.Line;
|
||||||
|
import de.kosit.validationtool.impl.Printer;
|
||||||
import de.kosit.validationtool.api.Configuration;
|
|
||||||
import de.kosit.validationtool.api.Input;
|
|
||||||
import de.kosit.validationtool.api.InputFactory;
|
|
||||||
import de.kosit.validationtool.api.Result;
|
|
||||||
import de.kosit.validationtool.cmd.assertions.Assertions;
|
|
||||||
import de.kosit.validationtool.config.ConfigurationLoader;
|
|
||||||
import de.kosit.validationtool.daemon.Daemon;
|
|
||||||
import de.kosit.validationtool.impl.ConversionService;
|
|
||||||
|
|
||||||
import net.sf.saxon.s9api.Processor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commandline Version des Prüftools. Parsed die Kommandozeile und führt die konfigurierten Aktionen aus.
|
* Commandline interface of the validator. It parses the commandline args and hands over actual execution to
|
||||||
|
* {@link Validator}.
|
||||||
|
*
|
||||||
|
* This separated from {@link Validator} to configure the slf4j simple logging.
|
||||||
*
|
*
|
||||||
* @author Andreas Penski
|
* @author Andreas Penski
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
// performance is not a problem here
|
||||||
@SuppressWarnings("squid:S3725") // performance is not a problem here
|
|
||||||
public class CommandLineApplication {
|
public class CommandLineApplication {
|
||||||
|
|
||||||
private static final Option HELP = Option.builder("?").longOpt("help").argName("Help").desc("Displays this help").build();
|
|
||||||
|
|
||||||
private static final Option SCENARIOS = Option.builder("s").required().longOpt("scenarios").hasArg()
|
|
||||||
.desc("Location of scenarios.xml e.g.").build();
|
|
||||||
|
|
||||||
private static final Option REPOSITORY = Option.builder("r").longOpt("repository").hasArg()
|
|
||||||
.desc("Directory containing scenario content").build();
|
|
||||||
|
|
||||||
private static final Option PRINT = Option.builder("p").longOpt("print").desc("Prints the check result to stdout").build();
|
|
||||||
|
|
||||||
private static final Option OUTPUT = Option.builder("o").longOpt("output-directory")
|
|
||||||
.desc("Defines the out directory for results. Defaults to cwd").hasArg().build();
|
|
||||||
|
|
||||||
private static final Option EXTRACT_HTML = Option.builder("h").longOpt("html")
|
|
||||||
.desc("Extract and save any html content within result as a separate file ").build();
|
|
||||||
|
|
||||||
private static final Option DEBUG = Option.builder("d").longOpt("debug").desc("Prints some more debug information").build();
|
|
||||||
|
|
||||||
private static final Option SERIALIZE_REPORT_INPUT = Option.builder("c").longOpt("serialize-report-input")
|
|
||||||
.desc("Serializes the report input to the cwd").build();
|
|
||||||
|
|
||||||
private static final Option CHECK_ASSERTIONS = Option.builder("c").longOpt("check-assertions").hasArg()
|
|
||||||
.desc("Check the result using defined assertions").argName("assertions-file").build();
|
|
||||||
|
|
||||||
private static final Option SERVER = Option.builder("D").longOpt("daemon").desc("Starts a daemon listing for validation requests")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
private static final Option HOST = Option.builder("H").longOpt("host").hasArg()
|
|
||||||
.desc("The hostname / IP address to bind the daemon. Default is localhost").build();
|
|
||||||
|
|
||||||
private static final Option PORT = Option.builder("P").longOpt("port").hasArg().desc("The port to bind the daemon. Default is 8080")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
private static final Option WORKER_COUNT = Option.builder("T").longOpt("threads").hasArg()
|
|
||||||
.desc("Number of threads processing validation requests").build();
|
|
||||||
|
|
||||||
private static final Option DISABLE_GUI = Option.builder("G").longOpt("disable-gui").desc("Disables the GUI of the daemon mode")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
private static final Option REPORT_POSTFIX = Option.builder(null).longOpt("report-postfix").hasArg()
|
|
||||||
.desc("Postfix of the generated report name").build();
|
|
||||||
|
|
||||||
private static final Option REPORT_PREFIX = Option.builder(null).longOpt("report-prefix").hasArg()
|
|
||||||
.desc("Prefix of the generated report name").build();
|
|
||||||
|
|
||||||
public static final int DAEMON_SIGNAL = 100;
|
|
||||||
|
|
||||||
private static final Option PRINT_MEM_STATS = Option.builder("m").longOpt("memory-stats").desc("Prints some memory stats").build();
|
|
||||||
|
|
||||||
private CommandLineApplication() {
|
private CommandLineApplication() {
|
||||||
// main class -> hide constructor
|
// main class -> hide constructor
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main-Funktion für die Kommandozeilen-Applikation.
|
* Main.
|
||||||
*
|
*
|
||||||
* @param args die Eingabe-Argumente
|
* @param args die Eingabe-Argumente
|
||||||
*/
|
*/
|
||||||
public static void main(final String[] args) {
|
public static void main(final String[] args) {
|
||||||
final int resultStatus = mainProgram(args);
|
final int resultStatus = mainProgram(args);
|
||||||
if (DAEMON_SIGNAL != resultStatus) {
|
if (DAEMON_SIGNAL != resultStatus) {
|
||||||
|
sayGoodby(resultStatus);
|
||||||
System.exit(resultStatus);
|
System.exit(resultStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private static void sayGoodby(final int resultStatus) {
|
||||||
* Hauptprogramm für die Kommandozeilen-Applikation.
|
Printer.writeOut("\n##############################");
|
||||||
*
|
if (resultStatus == 0) {
|
||||||
* @param args die Eingabe-Argumente
|
Printer.writeOut("# " + new Line(Code.GREEN).add("Validation succesful!").render(false, false) + " #");
|
||||||
*/
|
} else {
|
||||||
|
Printer.writeOut("# " + new Line(Code.RED).add("Validation failed!").render(false, false) + " #");
|
||||||
|
}
|
||||||
|
Printer.writeOut("##############################");
|
||||||
|
}
|
||||||
|
|
||||||
|
// for testing purposes. Unless jvm is terminated during tests. See above
|
||||||
static int mainProgram(final String[] args) {
|
static int mainProgram(final String[] args) {
|
||||||
int returnValue = 0;
|
|
||||||
final Options options = createOptions();
|
final Options options = createOptions();
|
||||||
|
int resultStatus;
|
||||||
|
try {
|
||||||
if (isHelpRequested(args)) {
|
if (isHelpRequested(args)) {
|
||||||
printHelp(options);
|
printHelp(options);
|
||||||
|
resultStatus = 0;
|
||||||
} else {
|
} else {
|
||||||
try {
|
|
||||||
final CommandLineParser parser = new DefaultParser();
|
final CommandLineParser parser = new DefaultParser();
|
||||||
final CommandLine cmd = parser.parse(options, args);
|
final CommandLine cmd = parser.parse(options, args);
|
||||||
if (cmd.hasOption(SERVER.getOpt())) {
|
configureLogging(cmd);
|
||||||
returnValue = startDaemonMode(cmd);
|
resultStatus = Validator.mainProgram(cmd);
|
||||||
} else if (cmd.getArgList().isEmpty()) {
|
|
||||||
printHelp(createOptions());
|
|
||||||
} else {
|
|
||||||
returnValue = processActions(cmd);
|
|
||||||
}
|
}
|
||||||
} catch (final ParseException e) {
|
} catch (final ParseException e) {
|
||||||
log.error("Error processing command line arguments: " + e.getMessage());
|
writeErr("Error processing command line arguments: {0}", e.getMessage(), e);
|
||||||
printHelp(options);
|
printHelp(options);
|
||||||
|
resultStatus = 1;
|
||||||
}
|
}
|
||||||
}
|
return resultStatus;
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int determinePort(final CommandLine cmd) {
|
|
||||||
int port = 8080;
|
|
||||||
if (checkOptionWithValue(PORT, cmd)) {
|
|
||||||
port = Integer.parseInt(cmd.getOptionValue(PORT.getOpt()));
|
|
||||||
}
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int determineThreads(final CommandLine cmd) {
|
|
||||||
int threads = Runtime.getRuntime().availableProcessors();
|
|
||||||
if (checkOptionWithValue(WORKER_COUNT, cmd)) {
|
|
||||||
threads = Integer.parseInt(cmd.getOptionValue(WORKER_COUNT.getOpt()));
|
|
||||||
}
|
|
||||||
return threads;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String determineHost(final CommandLine cmd) {
|
|
||||||
String host = "localhost";
|
|
||||||
if (checkOptionWithValue(HOST, cmd)) {
|
|
||||||
host = cmd.getOptionValue(HOST.getOpt());
|
|
||||||
}
|
|
||||||
return host;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int startDaemonMode(final CommandLine cmd) {
|
|
||||||
final Option[] unavailable = new Option[] { PRINT, CHECK_ASSERTIONS, DEBUG, OUTPUT, EXTRACT_HTML, REPORT_POSTFIX, REPORT_PREFIX };
|
|
||||||
warnUnusedOptions(cmd, unavailable, true);
|
|
||||||
final ConfigurationLoader config = Configuration.load(determineDefinition(cmd), determineRepository(cmd));
|
|
||||||
final Daemon validDaemon = new Daemon(determineHost(cmd), determinePort(cmd), determineThreads(cmd));
|
|
||||||
if (cmd.hasOption(DISABLE_GUI.getOpt())) {
|
|
||||||
validDaemon.setGuiEnabled(false);
|
|
||||||
}
|
|
||||||
validDaemon.startServer(config.build());
|
|
||||||
return DAEMON_SIGNAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void warnUnusedOptions(final CommandLine cmd, final Option[] unavailable, final boolean daemon) {
|
|
||||||
Arrays.stream(cmd.getOptions()).filter(o -> ArrayUtils.contains(unavailable, o))
|
|
||||||
.map(o -> "The option " + o.getLongOpt() + " is not available in daemon mode").forEach(log::error);
|
|
||||||
if (daemon && !cmd.getArgList().isEmpty()) {
|
|
||||||
log.info("Ignoring test targets in daemon mode");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isHelpRequested(final String[] args) {
|
private static boolean isHelpRequested(final String[] args) {
|
||||||
|
|
@ -217,200 +113,26 @@ public class CommandLineApplication {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int processActions(final CommandLine cmd) {
|
private static void configureLogging(final CommandLine cmd) throws ParseException {
|
||||||
try {
|
if (cmd.hasOption(CommandLineOptions.DEBUG_LOG.getOpt())) {
|
||||||
|
System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "DEBUG");
|
||||||
|
} else if (cmd.hasOption(CommandLineOptions.LOG_LEVEL.getOpt())) {
|
||||||
|
|
||||||
long start = System.currentTimeMillis();
|
final String level = Level.resolve(cmd.getOptionValue(CommandLineOptions.LOG_LEVEL.getOpt()));
|
||||||
final Option[] unavailable = new Option[] { HOST, PORT, WORKER_COUNT, DISABLE_GUI };
|
System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, level);
|
||||||
warnUnusedOptions(cmd, unavailable, false);
|
|
||||||
final Configuration config = Configuration.load(determineDefinition(cmd), determineRepository(cmd)).build();
|
|
||||||
|
|
||||||
final InternalCheck check = new InternalCheck(config);
|
|
||||||
final Path outputDirectory = determineOutputDirectory(cmd);
|
|
||||||
|
|
||||||
final Processor processor = config.getContentRepository().getProcessor();
|
|
||||||
if (cmd.hasOption(EXTRACT_HTML.getOpt())) {
|
|
||||||
check.getCheckSteps().add(new ExtractHtmlContentAction(processor, outputDirectory));
|
|
||||||
}
|
|
||||||
check.getCheckSteps().add(new SerializeReportAction(outputDirectory, processor, determineNamingStrategy(cmd)));
|
|
||||||
if (cmd.hasOption(SERIALIZE_REPORT_INPUT.getOpt())) {
|
|
||||||
check.getCheckSteps().add(new SerializeReportInputAction(outputDirectory, check.getConversionService()));
|
|
||||||
}
|
|
||||||
if (cmd.hasOption(PRINT.getOpt())) {
|
|
||||||
check.getCheckSteps().add(new PrintReportAction(processor));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd.hasOption(CHECK_ASSERTIONS.getOpt())) {
|
|
||||||
final Assertions assertions = loadAssertions(cmd.getOptionValue(CHECK_ASSERTIONS.getOpt()));
|
|
||||||
check.getCheckSteps().add(new CheckAssertionAction(assertions, processor));
|
|
||||||
}
|
|
||||||
if (cmd.hasOption(PRINT_MEM_STATS.getOpt())) {
|
|
||||||
check.getCheckSteps().add(new PrintMemoryStats());
|
|
||||||
}
|
|
||||||
|
|
||||||
log.info("Setup completed in {}ms\n", System.currentTimeMillis() - start);
|
|
||||||
|
|
||||||
final Collection<Path> targets = determineTestTargets(cmd);
|
|
||||||
start = System.currentTimeMillis();
|
|
||||||
final Map<Path, Result> results = new HashMap<>();
|
|
||||||
for (final Path p : targets) {
|
|
||||||
final Input input = InputFactory.read(p);
|
|
||||||
results.put(p, check.checkInput(input));
|
|
||||||
}
|
|
||||||
final boolean result = check.printAndEvaluate(results);
|
|
||||||
log.info("Processing {} object(s) completed in {}ms", targets.size(), System.currentTimeMillis() - start);
|
|
||||||
return result ? 0 : 1;
|
|
||||||
|
|
||||||
} catch (final Exception e) {
|
|
||||||
e.printStackTrace();// NOSONAR
|
|
||||||
if (cmd.hasOption(DEBUG.getOpt())) {
|
|
||||||
log.error(e.getMessage(), e);
|
|
||||||
} else {
|
} else {
|
||||||
log.error(e.getMessage());
|
System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "OFF");
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NamingStrategy determineNamingStrategy(final CommandLine cmd) {
|
private enum Level {
|
||||||
final DefaultNamingStrategy namingStrategy = new DefaultNamingStrategy();
|
|
||||||
if (cmd.hasOption(REPORT_PREFIX.getLongOpt())) {
|
|
||||||
namingStrategy.setPrefix(cmd.getOptionValue(REPORT_PREFIX.getLongOpt()));
|
|
||||||
}
|
|
||||||
if (cmd.hasOption(REPORT_POSTFIX.getLongOpt())) {
|
|
||||||
namingStrategy.setPostfix(cmd.getOptionValue(REPORT_POSTFIX.getLongOpt()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return namingStrategy;
|
INFO, WARN, DEBUG, TRACE, ERROR, OFF;
|
||||||
}
|
|
||||||
|
|
||||||
private static Assertions loadAssertions(final String optionValue) {
|
static String resolve(final String optionValue) throws ParseException {
|
||||||
final Path p = Paths.get(optionValue);
|
return Arrays.stream(values()).filter(e -> e.name().equalsIgnoreCase(optionValue)).map(Enum::name).findFirst()
|
||||||
Assertions a = null;
|
.orElseThrow(() -> new ParseException("Either specify trace,debug,info,warn,error as log level"));
|
||||||
if (Files.exists(p)) {
|
|
||||||
final ConversionService c = new ConversionService();
|
|
||||||
c.initialize(de.kosit.validationtool.cmd.assertions.ObjectFactory.class.getPackage());
|
|
||||||
a = c.readXml(p.toUri(), Assertions.class);
|
|
||||||
}
|
}
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Path determineOutputDirectory(final CommandLine cmd) {
|
|
||||||
final String value = cmd.getOptionValue(OUTPUT.getOpt());
|
|
||||||
final Path fir;
|
|
||||||
if (StringUtils.isNotBlank(value)) {
|
|
||||||
fir = Paths.get(value);
|
|
||||||
if ((!Files.exists(fir) && !fir.toFile().mkdirs()) || !Files.isDirectory(fir)) {
|
|
||||||
throw new IllegalStateException(String.format("Invalid target directory %s specified", value));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fir = Paths.get(""/* cwd */);
|
|
||||||
}
|
|
||||||
return fir;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Collection<Path> determineTestTargets(final CommandLine cmd) {
|
|
||||||
final Collection<Path> targets = new ArrayList<>();
|
|
||||||
if (!cmd.getArgList().isEmpty()) {
|
|
||||||
cmd.getArgList().forEach(e -> targets.addAll(determineTestTarget(e)));
|
|
||||||
}
|
|
||||||
if (targets.isEmpty()) {
|
|
||||||
throw new IllegalStateException("No test targets found. Nothing to check. Will quit now!");
|
|
||||||
}
|
|
||||||
return targets;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Collection<Path> determineTestTarget(final String s) {
|
|
||||||
final Path d = Paths.get(s);
|
|
||||||
if (Files.isDirectory(d)) {
|
|
||||||
return listDirectoryTargets(d);
|
|
||||||
} else if (Files.exists(d)) {
|
|
||||||
return Collections.singleton(d);
|
|
||||||
}
|
|
||||||
log.warn("The specified test target {} does not exist. Will be ignored", s);
|
|
||||||
return Collections.emptyList();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Collection<Path> listDirectoryTargets(final Path d) {
|
|
||||||
try ( final Stream<Path> stream = Files.list(d) ) {
|
|
||||||
return stream.filter(path -> path.toString().endsWith(".xml")).collect(Collectors.toList());
|
|
||||||
} catch (final IOException e) {
|
|
||||||
throw new IllegalStateException("IOException while list directory content. Can not determine test targets.", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static URI determineRepository(final CommandLine cmd) {
|
|
||||||
if (checkOptionWithValue(REPOSITORY, cmd)) {
|
|
||||||
final Path d = Paths.get(cmd.getOptionValue(REPOSITORY.getOpt()));
|
|
||||||
if (Files.isDirectory(d)) {
|
|
||||||
return d.toUri();
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
String.format("Not a valid path for repository definition specified: '%s'", d.toAbsolutePath()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static URI determineDefinition(final CommandLine cmd) {
|
|
||||||
checkOptionWithValue(SCENARIOS, cmd);
|
|
||||||
final Path f = Paths.get(cmd.getOptionValue(SCENARIOS.getOpt()));
|
|
||||||
if (Files.isRegularFile(f)) {
|
|
||||||
return f.toAbsolutePath().toUri();
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
String.format("Not a valid path for scenario definition specified: '%s'", f.toAbsolutePath()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean checkOptionWithValue(final Option option, final CommandLine cmd) {
|
|
||||||
final String opt = option.getOpt();
|
|
||||||
if (cmd.hasOption(opt)) {
|
|
||||||
final String value = cmd.getOptionValue(opt);
|
|
||||||
if (StringUtils.isNoneBlank(value)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(String.format("Option value required for Option '%s'", option.getLongOpt()));
|
|
||||||
}
|
|
||||||
} else if (option.isRequired()) {
|
|
||||||
|
|
||||||
throw new IllegalArgumentException(String.format("Option '%s' required ", option.getLongOpt()));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void printHelp(final Options options) {
|
|
||||||
// automatically generate the help statement
|
|
||||||
final HelpFormatter formatter = new HelpFormatter();
|
|
||||||
formatter.printHelp("check-tool -s <scenario-config-file> [OPTIONS] [FILE]... ", options, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Options createHelpOptions() {
|
|
||||||
final Options options = new Options();
|
|
||||||
options.addOption(HELP);
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Options createOptions() {
|
|
||||||
final Options options = new Options();
|
|
||||||
options.addOption(HELP);
|
|
||||||
options.addOption(SERVER);
|
|
||||||
options.addOption(HOST);
|
|
||||||
options.addOption(PORT);
|
|
||||||
options.addOption(SCENARIOS);
|
|
||||||
options.addOption(REPOSITORY);
|
|
||||||
options.addOption(PRINT);
|
|
||||||
options.addOption(OUTPUT);
|
|
||||||
options.addOption(EXTRACT_HTML);
|
|
||||||
options.addOption(DEBUG);
|
|
||||||
options.addOption(CHECK_ASSERTIONS);
|
|
||||||
options.addOption(PRINT_MEM_STATS);
|
|
||||||
options.addOption(WORKER_COUNT);
|
|
||||||
options.addOption(DISABLE_GUI);
|
|
||||||
options.addOption(REPORT_POSTFIX);
|
|
||||||
options.addOption(REPORT_PREFIX);
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
package de.kosit.validationtool.cmd;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.HelpFormatter;
|
||||||
|
import org.apache.commons.cli.Option;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Penski
|
||||||
|
*/
|
||||||
|
public class CommandLineOptions {
|
||||||
|
|
||||||
|
static final Option HELP = Option.builder("?").longOpt("help").argName("Help").desc("Displays this help").build();
|
||||||
|
|
||||||
|
static final Option SCENARIOS = Option.builder("s").required().longOpt("scenarios").hasArg().desc("Location of scenarios.xml e.g.")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
static final Option REPOSITORY = Option.builder("r").longOpt("repository").hasArg().desc("Directory containing scenario content")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
static final Option PRINT = Option.builder("p").longOpt("print").desc("Prints the check result to stdout").build();
|
||||||
|
|
||||||
|
static final Option OUTPUT = Option.builder("o").longOpt("output-directory")
|
||||||
|
.desc("Defines the out directory for results. Defaults to cwd").hasArg().build();
|
||||||
|
|
||||||
|
static final Option EXTRACT_HTML = Option.builder("h").longOpt("html")
|
||||||
|
.desc("Extract and save any html content within result as a separate file ").build();
|
||||||
|
|
||||||
|
static final Option DEBUG = Option.builder("d").longOpt("debug").desc("Prints some more debug information").build();
|
||||||
|
|
||||||
|
static final Option SERIALIZE_REPORT_INPUT = Option.builder("c").longOpt("serialize-report-input")
|
||||||
|
.desc("Serializes the report input to the cwd").build();
|
||||||
|
|
||||||
|
static final Option CHECK_ASSERTIONS = Option.builder("c").longOpt("check-assertions").hasArg()
|
||||||
|
.desc("Check the result using defined assertions").argName("assertions-file").build();
|
||||||
|
|
||||||
|
static final Option SERVER = Option.builder("D").longOpt("daemon").desc("Starts a daemon listing for validation requests").build();
|
||||||
|
|
||||||
|
static final Option HOST = Option.builder("H").longOpt("host").hasArg()
|
||||||
|
.desc("The hostname / IP address to bind the daemon. Default is localhost").build();
|
||||||
|
|
||||||
|
static final Option PORT = Option.builder("P").longOpt("port").hasArg().desc("The port to bind the daemon. Default is 8080").build();
|
||||||
|
|
||||||
|
static final Option WORKER_COUNT = Option.builder("T").longOpt("threads").hasArg()
|
||||||
|
.desc("Number of threads processing validation requests").build();
|
||||||
|
|
||||||
|
static final Option DISABLE_GUI = Option.builder("G").longOpt("disable-gui").desc("Disables the GUI of the daemon mode").build();
|
||||||
|
|
||||||
|
static final Option REPORT_POSTFIX = Option.builder(null).longOpt("report-postfix").hasArg()
|
||||||
|
.desc("Postfix of the generated report name").build();
|
||||||
|
|
||||||
|
static final Option REPORT_PREFIX = Option.builder(null).longOpt("report-prefix").hasArg().desc("Prefix of the generated report name")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
static final Option DEBUG_LOG = Option.builder("X").longOpt("debug-logging").desc("Enables full debug log. Alias for -l debug").build();
|
||||||
|
|
||||||
|
static final Option LOG_LEVEL = Option.builder("l").longOpt("log-level").hasArg()
|
||||||
|
.desc("Enables a certain log level for debugging " + "purposes").build();
|
||||||
|
|
||||||
|
public static final int DAEMON_SIGNAL = 100;
|
||||||
|
|
||||||
|
static final Option PRINT_MEM_STATS = Option.builder("m").longOpt("memory-stats").desc("Prints some memory stats").build();
|
||||||
|
|
||||||
|
static org.apache.commons.cli.Options createOptions() {
|
||||||
|
final org.apache.commons.cli.Options options = new org.apache.commons.cli.Options();
|
||||||
|
options.addOption(HELP);
|
||||||
|
options.addOption(SERVER);
|
||||||
|
options.addOption(HOST);
|
||||||
|
options.addOption(PORT);
|
||||||
|
options.addOption(SCENARIOS);
|
||||||
|
options.addOption(REPOSITORY);
|
||||||
|
options.addOption(PRINT);
|
||||||
|
options.addOption(OUTPUT);
|
||||||
|
options.addOption(EXTRACT_HTML);
|
||||||
|
options.addOption(DEBUG);
|
||||||
|
options.addOption(CHECK_ASSERTIONS);
|
||||||
|
options.addOption(PRINT_MEM_STATS);
|
||||||
|
options.addOption(WORKER_COUNT);
|
||||||
|
options.addOption(DISABLE_GUI);
|
||||||
|
options.addOption(REPORT_POSTFIX);
|
||||||
|
options.addOption(REPORT_PREFIX);
|
||||||
|
options.addOption(LOG_LEVEL);
|
||||||
|
options.addOption(DEBUG_LOG);
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printHelp(final org.apache.commons.cli.Options options) {
|
||||||
|
// automatically generate the help statement
|
||||||
|
final HelpFormatter formatter = new HelpFormatter();
|
||||||
|
formatter.printHelp("check-tool -s <scenario-config-file> [OPTIONS] [FILE]... ", options, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static org.apache.commons.cli.Options createHelpOptions() {
|
||||||
|
final org.apache.commons.cli.Options options = new org.apache.commons.cli.Options();
|
||||||
|
options.addOption(HELP);
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -100,7 +100,6 @@ class InternalCheck extends DefaultCheck {
|
||||||
final long rejected = results.entrySet().stream().filter(e -> !e.getValue().isAcceptable()).count();
|
final long rejected = results.entrySet().stream().filter(e -> !e.getValue().isAcceptable()).count();
|
||||||
final long errors = results.entrySet().stream().filter(e -> !e.getValue().isProcessingSuccessful()).count();
|
final long errors = results.entrySet().stream().filter(e -> !e.getValue().isProcessingSuccessful()).count();
|
||||||
final Line line = new Line();
|
final Line line = new Line();
|
||||||
line.add(String.format("Validation of %s objects finished. ", results.size()));
|
|
||||||
line.add("Acceptable: ").add(acceptable, Code.GREEN);
|
line.add("Acceptable: ").add(acceptable, Code.GREEN);
|
||||||
line.add(" Rejected: ").add(rejected, Code.RED);
|
line.add(" Rejected: ").add(rejected, Code.RED);
|
||||||
if (errors > 0) {
|
if (errors > 0) {
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import java.io.StringWriter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import de.kosit.validationtool.impl.Printer;
|
||||||
import de.kosit.validationtool.impl.tasks.CheckAction;
|
import de.kosit.validationtool.impl.tasks.CheckAction;
|
||||||
|
|
||||||
import net.sf.saxon.s9api.Processor;
|
import net.sf.saxon.s9api.Processor;
|
||||||
|
|
@ -47,7 +48,7 @@ class PrintReportAction implements CheckAction {
|
||||||
final StringWriter writer = new StringWriter();
|
final StringWriter writer = new StringWriter();
|
||||||
final Serializer serializer = this.processor.newSerializer(writer);
|
final Serializer serializer = this.processor.newSerializer(writer);
|
||||||
serializer.serializeNode(results.getReport());
|
serializer.serializeNode(results.getReport());
|
||||||
System.out.print(writer.toString()); // NOSONAR
|
Printer.writeOut(writer.toString());
|
||||||
} catch (final SaxonApiException e) {
|
} catch (final SaxonApiException e) {
|
||||||
log.error("Error while printing result to stdout", e);
|
log.error("Error while printing result to stdout", e);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
331
src/main/java/de/kosit/validationtool/cmd/Validator.java
Normal file
331
src/main/java/de/kosit/validationtool/cmd/Validator.java
Normal file
|
|
@ -0,0 +1,331 @@
|
||||||
|
package de.kosit.validationtool.cmd;
|
||||||
|
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.CHECK_ASSERTIONS;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.DAEMON_SIGNAL;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.DEBUG;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.DISABLE_GUI;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.EXTRACT_HTML;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.HELP;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.HOST;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.OUTPUT;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.PORT;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.PRINT;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.PRINT_MEM_STATS;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.REPORT_POSTFIX;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.REPORT_PREFIX;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.REPOSITORY;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.SCENARIOS;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.SERIALIZE_REPORT_INPUT;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.SERVER;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.WORKER_COUNT;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.createOptions;
|
||||||
|
import static de.kosit.validationtool.cmd.CommandLineOptions.printHelp;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.CommandLine;
|
||||||
|
import org.apache.commons.cli.Option;
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.fusesource.jansi.AnsiRenderer.Code;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import de.kosit.validationtool.api.Configuration;
|
||||||
|
import de.kosit.validationtool.api.Input;
|
||||||
|
import de.kosit.validationtool.api.InputFactory;
|
||||||
|
import de.kosit.validationtool.api.Result;
|
||||||
|
import de.kosit.validationtool.cmd.assertions.Assertions;
|
||||||
|
import de.kosit.validationtool.cmd.report.Line;
|
||||||
|
import de.kosit.validationtool.config.ConfigurationLoader;
|
||||||
|
import de.kosit.validationtool.daemon.Daemon;
|
||||||
|
import de.kosit.validationtool.impl.ConversionService;
|
||||||
|
import de.kosit.validationtool.impl.EngineInformation;
|
||||||
|
import de.kosit.validationtool.impl.Printer;
|
||||||
|
|
||||||
|
import net.sf.saxon.s9api.Processor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actual evaluation and processing of commandline argumtens.
|
||||||
|
*
|
||||||
|
* @author Andreas Penski
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@SuppressWarnings("squid:S3725")
|
||||||
|
public class Validator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hauptprogramm für die Kommandozeilen-Applikation.
|
||||||
|
*
|
||||||
|
* @param cmd parsed commandline.
|
||||||
|
*/
|
||||||
|
static int mainProgram(final CommandLine cmd) {
|
||||||
|
greeting();
|
||||||
|
final org.apache.commons.cli.Options options = createOptions();
|
||||||
|
int returnValue = 0;
|
||||||
|
if (cmd.hasOption(SERVER.getOpt())) {
|
||||||
|
returnValue = startDaemonMode(cmd);
|
||||||
|
} else if (cmd.hasOption(HELP.getOpt()) || cmd.getArgList().isEmpty()) {
|
||||||
|
printHelp(options);
|
||||||
|
} else if (cmd.getArgList().isEmpty()) {
|
||||||
|
printHelp(options);
|
||||||
|
} else {
|
||||||
|
returnValue = processActions(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void greeting() {
|
||||||
|
Printer.writeOut("{0} version {1}", EngineInformation.getName(), EngineInformation.getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int determinePort(final CommandLine cmd) {
|
||||||
|
int port = 8080;
|
||||||
|
if (checkOptionWithValue(PORT, cmd)) {
|
||||||
|
port = Integer.parseInt(cmd.getOptionValue(PORT.getOpt()));
|
||||||
|
}
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int determineThreads(final CommandLine cmd) {
|
||||||
|
int threads = Runtime.getRuntime().availableProcessors();
|
||||||
|
if (checkOptionWithValue(WORKER_COUNT, cmd)) {
|
||||||
|
threads = Integer.parseInt(cmd.getOptionValue(WORKER_COUNT.getOpt()));
|
||||||
|
}
|
||||||
|
return threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String determineHost(final CommandLine cmd) {
|
||||||
|
String host = "localhost";
|
||||||
|
if (checkOptionWithValue(HOST, cmd)) {
|
||||||
|
host = cmd.getOptionValue(HOST.getOpt());
|
||||||
|
}
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int startDaemonMode(final CommandLine cmd) {
|
||||||
|
final Option[] unavailable = new Option[] { PRINT, CHECK_ASSERTIONS, DEBUG, OUTPUT, EXTRACT_HTML, REPORT_POSTFIX, REPORT_PREFIX };
|
||||||
|
warnUnusedOptions(cmd, unavailable, true);
|
||||||
|
final ConfigurationLoader config = Configuration.load(determineDefinition(cmd), determineRepository(cmd));
|
||||||
|
final Daemon validDaemon = new Daemon(determineHost(cmd), determinePort(cmd), determineThreads(cmd));
|
||||||
|
if (cmd.hasOption(DISABLE_GUI.getOpt())) {
|
||||||
|
validDaemon.setGuiEnabled(false);
|
||||||
|
}
|
||||||
|
validDaemon.startServer(config.build());
|
||||||
|
return DAEMON_SIGNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void warnUnusedOptions(final CommandLine cmd, final Option[] unavailable, final boolean daemon) {
|
||||||
|
Arrays.stream(cmd.getOptions()).filter(o -> ArrayUtils.contains(unavailable, o))
|
||||||
|
.map(o -> "The option " + o.getLongOpt() + " is not available in daemon mode").forEach(log::error);
|
||||||
|
if (daemon && !cmd.getArgList().isEmpty()) {
|
||||||
|
log.info("Ignoring test targets in daemon mode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int processActions(final CommandLine cmd) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
final Option[] unavailable = new Option[] { HOST, PORT, WORKER_COUNT, DISABLE_GUI };
|
||||||
|
warnUnusedOptions(cmd, unavailable, false);
|
||||||
|
final URI scenarioLocation = determineDefinition(cmd);
|
||||||
|
final URI repositoryLocation = determineRepository(cmd);
|
||||||
|
reportConfiguration(scenarioLocation, repositoryLocation);
|
||||||
|
final Configuration config = Configuration.load(scenarioLocation, repositoryLocation).build();
|
||||||
|
|
||||||
|
final InternalCheck check = new InternalCheck(config);
|
||||||
|
final Path outputDirectory = determineOutputDirectory(cmd);
|
||||||
|
|
||||||
|
final Processor processor = config.getContentRepository().getProcessor();
|
||||||
|
if (cmd.hasOption(EXTRACT_HTML.getOpt())) {
|
||||||
|
check.getCheckSteps().add(new ExtractHtmlContentAction(processor, outputDirectory));
|
||||||
|
}
|
||||||
|
check.getCheckSteps().add(new SerializeReportAction(outputDirectory, processor, determineNamingStrategy(cmd)));
|
||||||
|
if (cmd.hasOption(SERIALIZE_REPORT_INPUT.getOpt())) {
|
||||||
|
check.getCheckSteps().add(new SerializeReportInputAction(outputDirectory, check.getConversionService()));
|
||||||
|
}
|
||||||
|
if (cmd.hasOption(PRINT.getOpt())) {
|
||||||
|
check.getCheckSteps().add(new PrintReportAction(processor));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd.hasOption(CHECK_ASSERTIONS.getOpt())) {
|
||||||
|
final Assertions assertions = loadAssertions(cmd.getOptionValue(CHECK_ASSERTIONS.getOpt()));
|
||||||
|
check.getCheckSteps().add(new CheckAssertionAction(assertions, processor));
|
||||||
|
}
|
||||||
|
if (cmd.hasOption(PRINT_MEM_STATS.getOpt())) {
|
||||||
|
check.getCheckSteps().add(new PrintMemoryStats());
|
||||||
|
}
|
||||||
|
printScenarios(check.getConfiguration());
|
||||||
|
log.info("Setup completed in {}ms\n", System.currentTimeMillis() - start);
|
||||||
|
|
||||||
|
final Collection<Path> targets = determineTestTargets(cmd);
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
final Map<Path, Result> results = new HashMap<>();
|
||||||
|
Printer.writeOut("\nProcessing of {0} objects started", targets.size());
|
||||||
|
long tick = System.currentTimeMillis();
|
||||||
|
for (final Path p : targets) {
|
||||||
|
final Input input = InputFactory.read(p);
|
||||||
|
results.put(p, check.checkInput(input));
|
||||||
|
if (((System.currentTimeMillis() - tick) / 1000) > 5) {
|
||||||
|
tick = System.currentTimeMillis();
|
||||||
|
Printer.writeOut("{0}/{1} objects processed", results.size(), targets.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final long processingTime = System.currentTimeMillis() - start;
|
||||||
|
Printer.writeOut("Processing of {0} objects completed in {1}ms", targets.size(), processingTime);
|
||||||
|
Printer.writeOut("Results:");
|
||||||
|
final boolean result = check.printAndEvaluate(results);
|
||||||
|
log.info("Processing {} object(s) completed in {}ms", targets.size(), processingTime);
|
||||||
|
return result ? 0 : 1;
|
||||||
|
|
||||||
|
} catch (final Exception e) {
|
||||||
|
e.printStackTrace();// NOSONAR
|
||||||
|
if (cmd.hasOption(DEBUG.getOpt())) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
} else {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void reportConfiguration(final URI scenarioLocation, final URI repositoryLocation) {
|
||||||
|
Printer.writeOut("Loading scenarios from {0}", scenarioLocation);
|
||||||
|
Printer.writeOut("Using repository {0}", repositoryLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void printScenarios(final Configuration configuration) {
|
||||||
|
Printer.writeOut("Loaded \"{0} {1}\" by {2} from {3} ", configuration.getName(), "1", configuration.getAuthor(),
|
||||||
|
configuration.getDate());
|
||||||
|
Printer.writeOut("\nThe following scenarios are available:");
|
||||||
|
configuration.getScenarios().forEach(e -> {
|
||||||
|
final Line line = new Line(Code.GREEN);
|
||||||
|
line.add(" * " + e.getName());
|
||||||
|
Printer.writeOut(line.render(false, false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static NamingStrategy determineNamingStrategy(final CommandLine cmd) {
|
||||||
|
final DefaultNamingStrategy namingStrategy = new DefaultNamingStrategy();
|
||||||
|
if (cmd.hasOption(REPORT_PREFIX.getLongOpt())) {
|
||||||
|
namingStrategy.setPrefix(cmd.getOptionValue(REPORT_PREFIX.getLongOpt()));
|
||||||
|
}
|
||||||
|
if (cmd.hasOption(REPORT_POSTFIX.getLongOpt())) {
|
||||||
|
namingStrategy.setPostfix(cmd.getOptionValue(REPORT_POSTFIX.getLongOpt()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return namingStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Assertions loadAssertions(final String optionValue) {
|
||||||
|
final Path p = Paths.get(optionValue);
|
||||||
|
Assertions a = null;
|
||||||
|
if (Files.exists(p)) {
|
||||||
|
final ConversionService c = new ConversionService();
|
||||||
|
c.initialize(de.kosit.validationtool.cmd.assertions.ObjectFactory.class.getPackage());
|
||||||
|
a = c.readXml(p.toUri(), Assertions.class);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Path determineOutputDirectory(final CommandLine cmd) {
|
||||||
|
final String value = cmd.getOptionValue(OUTPUT.getOpt());
|
||||||
|
final Path fir;
|
||||||
|
if (StringUtils.isNotBlank(value)) {
|
||||||
|
fir = Paths.get(value);
|
||||||
|
if ((!Files.exists(fir) && !fir.toFile().mkdirs()) || !Files.isDirectory(fir)) {
|
||||||
|
throw new IllegalStateException(String.format("Invalid target directory %s specified", value));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fir = Paths.get(""/* cwd */);
|
||||||
|
}
|
||||||
|
return fir;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Collection<Path> determineTestTargets(final CommandLine cmd) {
|
||||||
|
final Collection<Path> targets = new ArrayList<>();
|
||||||
|
if (!cmd.getArgList().isEmpty()) {
|
||||||
|
cmd.getArgList().forEach(e -> targets.addAll(determineTestTarget(e)));
|
||||||
|
}
|
||||||
|
if (targets.isEmpty()) {
|
||||||
|
throw new IllegalStateException("No test targets found. Nothing to check. Will quit now!");
|
||||||
|
}
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Collection<Path> determineTestTarget(final String s) {
|
||||||
|
final Path d = Paths.get(s);
|
||||||
|
if (Files.isDirectory(d)) {
|
||||||
|
return listDirectoryTargets(d);
|
||||||
|
} else if (Files.exists(d)) {
|
||||||
|
return Collections.singleton(d);
|
||||||
|
}
|
||||||
|
log.warn("The specified test target {} does not exist. Will be ignored", s);
|
||||||
|
return Collections.emptyList();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Collection<Path> listDirectoryTargets(final Path d) {
|
||||||
|
try ( final Stream<Path> stream = Files.list(d) ) {
|
||||||
|
return stream.filter(path -> path.toString().endsWith(".xml")).collect(Collectors.toList());
|
||||||
|
} catch (final IOException e) {
|
||||||
|
throw new IllegalStateException("IOException while list directory content. Can not determine test targets.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static URI determineRepository(final CommandLine cmd) {
|
||||||
|
if (checkOptionWithValue(REPOSITORY, cmd)) {
|
||||||
|
final Path d = Paths.get(cmd.getOptionValue(REPOSITORY.getOpt()));
|
||||||
|
if (Files.isDirectory(d)) {
|
||||||
|
return d.toUri();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format("Not a valid path for repository definition specified: '%s'", d.toAbsolutePath()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static URI determineDefinition(final CommandLine cmd) {
|
||||||
|
checkOptionWithValue(SCENARIOS, cmd);
|
||||||
|
final Path f = Paths.get(cmd.getOptionValue(SCENARIOS.getOpt()));
|
||||||
|
if (Files.isRegularFile(f)) {
|
||||||
|
return f.toAbsolutePath().toUri();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format("Not a valid path for scenario definition specified: '%s'", f.toAbsolutePath()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean checkOptionWithValue(final Option option, final CommandLine cmd) {
|
||||||
|
final String opt = option.getOpt();
|
||||||
|
if (cmd.hasOption(opt)) {
|
||||||
|
final String value = cmd.getOptionValue(opt);
|
||||||
|
if (StringUtils.isNoneBlank(value)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(String.format("Option value required for Option '%s'", option.getLongOpt()));
|
||||||
|
}
|
||||||
|
} else if (option.isRequired()) {
|
||||||
|
|
||||||
|
throw new IllegalArgumentException(String.format("Option '%s' required ", option.getLongOpt()));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -64,7 +64,7 @@ public class Line {
|
||||||
return render(true, false);
|
return render(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
String render(final boolean newLine, final boolean dotted) {
|
public String render(final boolean newLine, final boolean dotted) {
|
||||||
final List<String> joins = new ArrayList<>();
|
final List<String> joins = new ArrayList<>();
|
||||||
final List<Text> reversed = new ArrayList<>(this.texts);
|
final List<Text> reversed = new ArrayList<>(this.texts);
|
||||||
int replace = 0;
|
int replace = 0;
|
||||||
|
|
|
||||||
|
|
@ -18,4 +18,14 @@ public class Printer {
|
||||||
public static void writeOut(final String message, final Object... params) {
|
public static void writeOut(final String message, final Object... params) {
|
||||||
System.out.println(MessageFormat.format(message, params));
|
System.out.println(MessageFormat.format(message, params));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes to standard error channel.
|
||||||
|
*
|
||||||
|
* @param message the message with placeholders
|
||||||
|
* @param params the params.
|
||||||
|
*/
|
||||||
|
public static void writeErr(final String message, final Object... params) {
|
||||||
|
System.err.println(MessageFormat.format(message, params));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ import java.nio.file.Paths;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.assertj.core.api.Condition;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -51,7 +53,6 @@ public class CommandlineApplicationTest {
|
||||||
|
|
||||||
private final Path output = Paths.get("target/test-output");
|
private final Path output = Paths.get("target/test-output");
|
||||||
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() throws IOException {
|
public void setup() throws IOException {
|
||||||
this.commandLine = new CommandLine();
|
this.commandLine = new CommandLine();
|
||||||
|
|
@ -112,8 +113,7 @@ public class CommandlineApplicationTest {
|
||||||
@Test
|
@Test
|
||||||
public void testNotExistingTestTarget() {
|
public void testNotExistingTestTarget() {
|
||||||
final String[] args = new String[] { "-s", Paths.get(Simple.SCENARIOS).toString(), "-r",
|
final String[] args = new String[] { "-s", Paths.get(Simple.SCENARIOS).toString(), "-r",
|
||||||
Paths.get(Simple.REPOSITORY_URI).toString(),
|
Paths.get(Simple.REPOSITORY_URI).toString(), Paths.get(Simple.NOT_EXISTING).toString() };
|
||||||
Paths.get(Simple.NOT_EXISTING).toString() };
|
|
||||||
CommandLineApplication.mainProgram(args);
|
CommandLineApplication.mainProgram(args);
|
||||||
assertThat(this.commandLine.getErrorOutput()).isNotEmpty();
|
assertThat(this.commandLine.getErrorOutput()).isNotEmpty();
|
||||||
assertThat(this.commandLine.getErrorOutput()).contains("No test targets found");
|
assertThat(this.commandLine.getErrorOutput()).contains("No test targets found");
|
||||||
|
|
@ -122,8 +122,7 @@ public class CommandlineApplicationTest {
|
||||||
@Test
|
@Test
|
||||||
public void testValidMinimalConfiguration() {
|
public void testValidMinimalConfiguration() {
|
||||||
final String[] args = new String[] { "-s", Paths.get(Simple.SCENARIOS).toString(), "-r",
|
final String[] args = new String[] { "-s", Paths.get(Simple.SCENARIOS).toString(), "-r",
|
||||||
Paths.get(Simple.REPOSITORY_URI).toString(),
|
Paths.get(Simple.REPOSITORY_URI).toString(), Paths.get(Simple.SIMPLE_VALID).toString() };
|
||||||
Paths.get(Simple.SIMPLE_VALID).toString() };
|
|
||||||
CommandLineApplication.mainProgram(args);
|
CommandLineApplication.mainProgram(args);
|
||||||
assertThat(this.commandLine.getErrorOutput()).contains(RESULT_OUTPUT);
|
assertThat(this.commandLine.getErrorOutput()).contains(RESULT_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
@ -181,14 +180,15 @@ public class CommandlineApplicationTest {
|
||||||
Paths.get(Simple.REPOSITORY_URI).toString(), "-o", this.output.toString(), Paths.get(Simple.SIMPLE_VALID).toString() };
|
Paths.get(Simple.REPOSITORY_URI).toString(), "-o", this.output.toString(), Paths.get(Simple.SIMPLE_VALID).toString() };
|
||||||
CommandLineApplication.mainProgram(args);
|
CommandLineApplication.mainProgram(args);
|
||||||
assertThat(this.commandLine.getErrorOutput()).contains(RESULT_OUTPUT);
|
assertThat(this.commandLine.getErrorOutput()).contains(RESULT_OUTPUT);
|
||||||
assertThat(this.commandLine.getOutputLines().get(0)).contains("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
assertThat(this.commandLine.getOutputLines()).haveAtLeastOne(new Condition<>(
|
||||||
|
s -> StringUtils.contains(s, "<?xml version=\"1.0\" " + "encoding=\"UTF-8\"?>"), "Must " + "contain xml preambel"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHtmlExtraktion() throws IOException {
|
public void testHtmlExtraktion() throws IOException {
|
||||||
final String[] args = new String[] { "-s", Paths.get(Simple.SCENARIOS).toString(), "-h", "-o",
|
final String[] args = new String[] { "-s", Paths.get(Simple.SCENARIOS).toString(), "-h", "-o",
|
||||||
this.output.toAbsolutePath().toString(),
|
this.output.toAbsolutePath().toString(), "-r", Paths.get(Simple.REPOSITORY_URI).toString(),
|
||||||
"-r", Paths.get(Simple.REPOSITORY_URI).toString(), Paths.get(Simple.SIMPLE_VALID).toString() };
|
Paths.get(Simple.SIMPLE_VALID).toString() };
|
||||||
CommandLineApplication.mainProgram(args);
|
CommandLineApplication.mainProgram(args);
|
||||||
assertThat(this.commandLine.getErrorOutput()).contains(RESULT_OUTPUT);
|
assertThat(this.commandLine.getErrorOutput()).contains(RESULT_OUTPUT);
|
||||||
assertThat(Files.list(this.output).filter(f -> f.toString().endsWith(".html")).count()).isGreaterThan(0);
|
assertThat(Files.list(this.output).filter(f -> f.toString().endsWith(".html")).count()).isGreaterThan(0);
|
||||||
|
|
@ -198,8 +198,7 @@ public class CommandlineApplicationTest {
|
||||||
public void testAssertionsExtraktion() {
|
public void testAssertionsExtraktion() {
|
||||||
final String[] args = new String[] { "-d", "-s", Paths.get(Simple.SCENARIOS).toString(), "-r",
|
final String[] args = new String[] { "-d", "-s", Paths.get(Simple.SCENARIOS).toString(), "-r",
|
||||||
Paths.get(Simple.REPOSITORY_URI).toString(), "-o", this.output.toString(), "-c", Paths.get(ASSERTIONS).toString(),
|
Paths.get(Simple.REPOSITORY_URI).toString(), "-o", this.output.toString(), "-c", Paths.get(ASSERTIONS).toString(),
|
||||||
Paths.get(Simple.REPOSITORY_URI).toString(),
|
Paths.get(Simple.REPOSITORY_URI).toString(), Paths.get(Simple.SIMPLE_VALID).toString() };
|
||||||
Paths.get(Simple.SIMPLE_VALID).toString() };
|
|
||||||
CommandLineApplication.mainProgram(args);
|
CommandLineApplication.mainProgram(args);
|
||||||
assertThat(this.commandLine.getErrorOutput()).contains(RESULT_OUTPUT);
|
assertThat(this.commandLine.getErrorOutput()).contains(RESULT_OUTPUT);
|
||||||
assertThat(this.commandLine.getErrorOutput()).contains("Can not find assertions for ");
|
assertThat(this.commandLine.getErrorOutput()).contains("Can not find assertions for ");
|
||||||
|
|
@ -208,8 +207,7 @@ public class CommandlineApplicationTest {
|
||||||
@Test
|
@Test
|
||||||
public void testDebugFlag() {
|
public void testDebugFlag() {
|
||||||
final String[] args = new String[] { "-s", Paths.get(Simple.SCENARIOS).toString(), "-r", "unknown", "-o", this.output.toString(),
|
final String[] args = new String[] { "-s", Paths.get(Simple.SCENARIOS).toString(), "-r", "unknown", "-o", this.output.toString(),
|
||||||
"-d",
|
"-d", Paths.get(ASSERTIONS).toString() };
|
||||||
Paths.get(ASSERTIONS).toString() };
|
|
||||||
CommandLineApplication.mainProgram(args);
|
CommandLineApplication.mainProgram(args);
|
||||||
assertThat(this.commandLine.getErrorOutput()).contains("at de.kosit.validationtool");
|
assertThat(this.commandLine.getErrorOutput()).contains("at de.kosit.validationtool");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue