Skip to content

Commit

Permalink
Validate base data file with ilivalidator (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
domi-b authored Dec 6, 2023
2 parents a71b173 + 9df5f36 commit b70c468
Show file tree
Hide file tree
Showing 13 changed files with 477 additions and 4 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
Der Testbed-Runner ermöglicht das Testen von Constraints bzw. der dazugehörigen Methoden basierend auf Testdaten in einer definierten Ordnerstruktur.

## Anwendung
Der Runner funktioniert generisch auf einer entsprechenden Verzeichnisstruktur und globalen ilivalidator-Installation.

Diese Struktur ist folgendermassen aufgebaut:
Der Runner funktioniert generisch auf einer entsprechenden Verzeichnisstruktur mit diesem Aufbau:

```
TestSuiteA
Expand All @@ -23,3 +21,8 @@ TestSuiteA
FailCase-1_Merged.xtf
FailCase-1.log
```

Der Runner kann mit folgendem Befehl ausgeführt werden:
```bash
java -jar interlis-testbed-runner.jar --validator <Pfad zu ilivalidator.jar> <Pfad zum Testbed-Ordner (Standard: aktueller Ordner)>
```
15 changes: 15 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ repositories {
}

dependencies {
implementation platform('org.apache.logging.log4j:log4j-bom:2.22.0')
implementation 'org.apache.logging.log4j:log4j-api'
testImplementation 'org.apache.logging.log4j:log4j-core'
runtimeOnly 'org.apache.logging.log4j:log4j-core'

implementation 'commons-cli:commons-cli:1.6.0'

testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation 'org.junit.jupiter:junit-jupiter'
}
Expand All @@ -27,6 +34,14 @@ java {
withJavadocJar()
}

jar {
manifest {
attributes(
'Main-Class': application.mainClass
)
}
}

test {
useJUnitPlatform()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package ch.geowerkstatt.interlis.testbed.runner;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public final class InterlisValidator implements Validator {
private static final Logger LOGGER = LogManager.getLogger();

private final TestOptions options;

/**
* Creates a new instance of the InterlisValidator class.
*
* @param options the test options.
*/
public InterlisValidator(TestOptions options) {
this.options = options;

LOGGER.info("Using ilivalidator at " + options.ilivalidatorPath());
}

@Override
public boolean validate(Path filePath) throws ValidatorException {
var relativePath = options.basePath().relativize(filePath.getParent());
var logDirectory = options.outputPath().resolve(relativePath);

var filenameWithoutExtension = StringUtils.getFilenameWithoutExtension(filePath.getFileName().toString());
var logFile = logDirectory.resolve(filenameWithoutExtension + ".log");

try {
Files.createDirectories(logDirectory);

var processBuilder = new ProcessBuilder()
.command(
"java", "-jar", options.ilivalidatorPath().toString(),
"--log", logFile.toString(),
filePath.toString())
.directory(options.basePath().toFile());

var process = processBuilder.start();
var exitCode = process.waitFor();

if (exitCode == 0) {
LOGGER.info("Validation of " + filePath + " completed successfully.");
return true;
} else {
LOGGER.error("Validation of " + filePath + " failed with exit code " + exitCode + ". See " + logFile + " for details.");
return false;
}
} catch (IOException | InterruptedException e) {
throw new ValidatorException(e);
}
}
}
64 changes: 63 additions & 1 deletion src/main/java/ch/geowerkstatt/interlis/testbed/runner/Main.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
package ch.geowerkstatt.interlis.testbed.runner;

import org.apache.commons.cli.CommandLine;
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.ParseException;

import java.nio.file.Path;

public final class Main {
private static final String VALIDATOR_PATH_OPTION = "validator";

private Main() {
}

Expand All @@ -10,6 +21,57 @@ private Main() {
* @param args the command line arguments.
*/
public static void main(String[] args) {
System.out.println("Hello world!");
if (args.length == 0) {
printUsage(createCliOptions());
return;
}

var testOptions = parseTestOptions(args);
var validator = new InterlisValidator(testOptions);
var runner = new Runner(testOptions, validator);
if (!runner.run()) {
System.exit(1);
}
}

private static TestOptions parseTestOptions(String[] args) {
var options = createCliOptions();
try {
var parser = new DefaultParser();
var commandLine = parser.parse(options, args);
return getTestOptions(commandLine);
} catch (ParseException e) {
System.err.println("Error parsing command line arguments: " + e.getMessage());
printUsage(options);
System.exit(1);
return null;
}
}

private static void printUsage(Options options) {
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("java -jar interlis-testbed-runner.jar [options] [testbed directory (default: current directory)]", options);
}

private static TestOptions getTestOptions(CommandLine commandLine) throws ParseException {
var remainingArgs = commandLine.getArgList();
var basePath = remainingArgs.isEmpty() ? Path.of(".") : Path.of(remainingArgs.get(0));
var validatorPath = Path.of(commandLine.getOptionValue(VALIDATOR_PATH_OPTION));
return new TestOptions(basePath, validatorPath);
}

private static Options createCliOptions() {
var options = new Options();

var validatorPathOption = Option.builder("v")
.argName("path")
.longOpt(VALIDATOR_PATH_OPTION)
.hasArg()
.required()
.desc("path to ilivalidator.jar")
.build();
options.addOption(validatorPathOption);

return options;
}
}
64 changes: 64 additions & 0 deletions src/main/java/ch/geowerkstatt/interlis/testbed/runner/Runner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package ch.geowerkstatt.interlis.testbed.runner;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;

public final class Runner {
private static final Logger LOGGER = LogManager.getLogger();

private final TestOptions options;
private final Validator validator;

/**
* Creates a new instance of the Runner class.
*
* @param options the test options.
* @param validator the validator to use.
*/
public Runner(TestOptions options, Validator validator) {
this.options = options;
this.validator = validator;
}

/**
* Runs the testbed validation.
* @return {@code true} if the validation was successful, {@code false} otherwise.
*/
public boolean run() {
LOGGER.info("Starting validation of testbed at " + options.basePath());

try {
if (!validateBaseData()) {
LOGGER.error("Validation of base data failed.");
return false;
}
} catch (ValidatorException e) {
LOGGER.error("Validation could not run, check the configuration.", e);
return false;
}

LOGGER.info("Validation of testbed completed.");
return true;
}

private boolean validateBaseData() throws ValidatorException {
Optional<Path> filePath;
try {
filePath = options.baseDataFilePath();
} catch (IOException e) {
throw new ValidatorException(e);
}

if (filePath.isEmpty()) {
LOGGER.error("No base data file found.");
return false;
}

LOGGER.info("Validating base data file " + filePath.get());
return validator.validate(filePath.get());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package ch.geowerkstatt.interlis.testbed.runner;

public final class StringUtils {
private StringUtils() {
}

/**
* Gets the filename without the extension.
*
* @param filename the filename to get the name from.
* @return the filename without the extension.
*/
public static String getFilenameWithoutExtension(String filename) {
var lastDotIndex = filename.lastIndexOf('.');
if (lastDotIndex == -1) {
return filename;
}

return filename.substring(0, lastDotIndex);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package ch.geowerkstatt.interlis.testbed.runner;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import java.util.stream.Stream;

public record TestOptions(Path basePath, Path ilivalidatorPath) {
private static final String DATA_FILE_EXTENSION = ".xtf";
private static final String OUTPUT_DIR_NAME = "output";

/**
* Creates a new instance of the RunnerOptions class.
*
* @param basePath the base path of the testbed.
*/
public TestOptions {
basePath = basePath.toAbsolutePath().normalize();
ilivalidatorPath = ilivalidatorPath.toAbsolutePath().normalize();
}

/**
* Gets the path to the data file that is used as the base for all validations.
*
* @return the path to the base data file.
*/
public Optional<Path> baseDataFilePath() throws IOException {
try (var dataFiles = findDataFiles(basePath)) {
return dataFiles.findFirst();
}
}

/**
* Gets the path to the output directory.
*
* @return the path to the output directory.
*/
public Path outputPath() {
return basePath.resolve(OUTPUT_DIR_NAME);
}

private static Stream<Path> findDataFiles(Path basePath) throws IOException {
return Files.find(basePath, 1, (path, attributes) -> path.getFileName().toString().toLowerCase().endsWith(DATA_FILE_EXTENSION));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ch.geowerkstatt.interlis.testbed.runner;

import java.nio.file.Path;

public interface Validator {
/**
* Validates the given file.
*
* @param filePath the path to the file to validate.
* @return true if the validation was successful, false otherwise.
* @throws ValidatorException if the validation could not be performed.
*/
boolean validate(Path filePath) throws ValidatorException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package ch.geowerkstatt.interlis.testbed.runner;

/**
* Exception that is thrown when the validation failed to run.
*/
public final class ValidatorException extends Exception {
/**
* Creates a new instance of the ValidatorException class.
*
* @param message the message of the exception.
*/
public ValidatorException(String message) {
super(message);
}

/**
* Creates a new instance of the ValidatorException class.
*
* @param message the message of the exception.
* @param cause the cause of the exception.
*/
public ValidatorException(String message, Throwable cause) {
super(message, cause);
}

/**
* Creates a new instance of the ValidatorException class.
*
* @param cause the cause of the exception.
*/
public ValidatorException(Throwable cause) {
super(cause);
}
}
16 changes: 16 additions & 0 deletions src/main/resources/log4j2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%-5level %logger{3} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="ch.geowerkstatt.interlis.testbed.runner" level="trace" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Root level="error">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
10 changes: 10 additions & 0 deletions src/test/data/testbed/data.xtf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<ili:transfer xmlns:ili="http://www.interlis.ch/xtf/2.4/INTERLIS">
<ili:headersection>
<ili:models>
</ili:models>
<ili:sender>interlis-testbed-runner</ili:sender>
</ili:headersection>
<ili:datasection>
</ili:datasection>
</ili:transfer>
Loading

0 comments on commit b70c468

Please sign in to comment.