Commit aeb1e3f9 authored by Johannes Mey's avatar Johannes Mey
Browse files

update test infrastructure

parent 988e7143
......@@ -53,6 +53,7 @@ dependencies {
testFixturesApi group: 'org.assertj', name: 'assertj-core', version: '3.18.0'
testFixturesApi group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.0-rc1'
testFixturesApi group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: '2.12.0-rc1'
testFixturesApi group: 'commons-io', name: 'commons-io', version: '2.8.0'
}
test {
......
......@@ -43,14 +43,16 @@ aspect BackendAbstractGrammar {
if (getAbstract()) {
b.append("abstract ");
}
b.append(getName()).append(" ");
b.append(getName());
if (hasSuperType()) {
b.append(": ").append(getSuperType().getName()).append(" ");
b.append(" : ").append(getSuperType().getName());
}
b.append("::=");
for (Component component : getComponentList()) {
b.append(" ");
component.generateAbstractGrammar(b);
if (getNumComponent() > 0) {
b.append(" ::=");
for (Component component : getComponentList()) {
b.append(" ");
component.generateAbstractGrammar(b);
}
}
b.append(";");
super.generateAbstractGrammar(b);
......@@ -62,8 +64,7 @@ aspect BackendAbstractGrammar {
if (getNTA()) {
b.append("/");
}
if (!getName().equals("")) {
if (!getName().equals("") && !getName().equals(getTypeDecl().getName())) {
b.append(getName()).append(":");
}
b.append(getTypeDecl().getName());
......@@ -76,8 +77,7 @@ aspect BackendAbstractGrammar {
if (getNTA()) {
b.append("/");
}
if (!getName().equals("")) {
if (!getName().equals("") && !getName().equals(getTypeDecl().getName())) {
b.append(getName()).append(":");
}
b.append(getTypeDecl().getName()).append("*");
......@@ -91,7 +91,7 @@ aspect BackendAbstractGrammar {
b.append("/");
}
b.append("[");
if (!getName().equals("")) {
if (!getName().equals("") && !getName().equals(getTypeDecl().getName())) {
b.append(getName()).append(":");
}
b.append(getTypeDecl().getName()).append("]");
......@@ -187,7 +187,7 @@ aspect BackendAbstractGrammar {
}
public void SingleLineComment.generateAbstractGrammar(StringBuilder b) {
b.append("//").append(getText()).append("\n");
b.append("//").append(getText());
}
public void MultiLineComment.generateAbstractGrammar(StringBuilder b) {
......
......@@ -6,16 +6,34 @@ import com.github.jknack.handlebars.io.ClassPathTemplateLoader;
import com.github.jknack.handlebars.io.TemplateLoader;
import org.yaml.snakeyaml.Yaml;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.io.*;
import java.nio.file.Paths;
public class Mustache {
public static void javaMustache(String templateFileName, String yamlFileName, String outputFileName) throws IOException {
private Mustache() {
// hide public constructor
}
public static void javaMustache(String templateFileName, File yamlFile, String outputFileName) throws IOException {
//noinspection ResultOfMethodCallIgnored
Paths.get(outputFileName).getParent().toFile().mkdirs(); // create directory structure if necessary
Object context = new Yaml().load(new FileReader(yamlFile));
applyTemplate(templateFileName, outputFileName, context);
}
public static void javaMustache(String templateFileName, String yaml, String outputFileName) throws IOException {
//noinspection ResultOfMethodCallIgnored
Paths.get(outputFileName).getParent().toFile().mkdirs(); // create directory structure if necessary
Object context = new Yaml().load(new StringReader(yaml));
applyTemplate(templateFileName, outputFileName, context);
}
Object context = new Yaml().load(new FileReader(yamlFileName));
private static void applyTemplate(String templateFileName, String outputFileName, Object context) throws IOException {
TemplateLoader loader = new ClassPathTemplateLoader();
loader.setSuffix(".mustache"); // the default is ".hbs"
......
......@@ -21,7 +21,7 @@ public abstract class RelAstProcessor extends AbstractCompiler {
protected ValueOption optionOutputBaseDir;
protected ValueOption optionInputBaseDir;
public RelAstProcessor(String name, boolean jastAddCompliant) {
protected RelAstProcessor(String name, boolean jastAddCompliant) {
super(name, jastAddCompliant);
}
......
package org.jastadd.relast.tests;
import org.jastadd.relast.compiler.RelastSourceToSourceCompiler;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.nio.file.Paths;
import org.junit.jupiter.api.BeforeAll;
public class PreprocessorTest extends RelAstProcessorTestBase {
@Test
void testMinimalGrammar() throws IOException, InterruptedException {
directoryTest(RelastSourceToSourceCompiler.class, Paths.get("src/test/resources/MinimalGrammar"));
@BeforeAll
static void init() {
mainClass = RelastSourceToSourceCompiler.class;
}
}
- name: "Parse and reprint tests"
args:
- "--inputBaseDir=in"
- "--outputBaseDir=out"
- "CommentsA.relast"
out: "out"
expected: "in"
compare: true
// this file only contains comments
//
//
// like this one
/* or this one */
/* or this
one */
/**/
//test
/*test*/
//
- name: "MinimalGrammar"
- name: "Parse and reprint tests"
args:
- "--inputBaseDir=in"
- "--outputBaseDir=out"
- "Example.relast"
- name: "Comments in front"
args:
- "--inputBaseDir=in"
- "--outputBaseDir=out"
- "CommentInFront.relast"
out: "out"
expected: "in"
compare: true
......@@ -4,7 +4,7 @@ ZoneModel ::= <Size:IntPosition> SafetyZone:Zone*;
Zone ::= Coordinate*;
RobotArm ::= Joint* EndEffector <_AttributeTestSource:int> /<_AppropriateSpeed:double>/ ; // normally this would be: <AttributeTestSource:int> ;
RobotArm ::= Joint* EndEffector <_AttributeTestSource:int> /<_AppropriateSpeed:double>/; // normally this would be: <AttributeTestSource:int> ;
Joint ::= <Name> <CurrentPosition:IntPosition>; // normally this would be: <CurrentPosition:IntPosition>
......
......@@ -3,25 +3,25 @@ package org.jastadd.relast.tests;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.assertj.core.util.Files;
import org.jastadd.relast.tests.config.Configuration;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.*;
import java.util.stream.Stream;
public class RelAstProcessorTestBase {
protected static Class<?> mainClass;
protected static int runProcess(File workingDirectory, List<String> command, StringBuilder outStringBuider, StringBuilder errStringBuilder) throws IOException, InterruptedException {
File outFile = Files.newTemporaryFile();
......@@ -72,7 +72,7 @@ public class RelAstProcessorTestBase {
command.addAll(args);
}
System.out.println("Running java -jar -cp [...] " + className + " " + args.stream().reduce((s1, s2) -> s1 + " " + s2).orElse(""));
System.out.println("Running java -jar -cp [...] " + className + " " + (args != null ? args.stream().reduce((s1, s2) -> s1 + " " + s2).orElse("") : ""));
return runProcess(workingDirectory, command, outStringBuider, errStringBuilder);
}
......@@ -86,6 +86,9 @@ public class RelAstProcessorTestBase {
for (Configuration config : configs) {
FileUtils.forceMkdir(dir.resolve(config.getOut()).toFile());
FileUtils.cleanDirectory(dir.resolve(config.getOut()).toFile());
StringBuilder outBuilder = new StringBuilder();
StringBuilder errBuilder = new StringBuilder();
int returnValue = runJavaProcess(mainClass, dir.toFile(), Arrays.asList(config.getArgs()), outBuilder, errBuilder);
......@@ -96,46 +99,78 @@ public class RelAstProcessorTestBase {
System.err.println(err);
if (config.shouldFail()) {
Assertions.assertNotEquals(0, returnValue, "Zero return value of preprocessor for negative test.");
Assertions.assertNotEquals(0, returnValue, config.getName() + ": Zero return value of preprocessor for negative test.");
} else {
Assertions.assertEquals(0, returnValue, "Non-Zero return value of preprocessor for positive test.");
Assertions.assertEquals(0, returnValue, config.getName() + ": Non-Zero return value of preprocessor for positive test.");
}
for (String errMatchString : config.getErrMatches()) {
if (!err.matches(errMatchString)) {
Assertions.fail("Error stream does not match '" + errMatchString + "'");
}
checkOutput(config, out, err);
if (config.shouldCompare()) {
Path outPath = dir.resolve(config.getOut());
Path expectedPath = dir.resolve(config.getExpected());
comparePaths(outPath, expectedPath);
}
}
}
for (String errContainsString : config.getErrContains()) {
if (!err.contains(errContainsString)) {
Assertions.fail("Error stream does not contain '" + errContainsString + "'");
}
private void checkOutput(Configuration config, String out, String err) {
for (String errMatchString : config.getErrMatches()) {
if (!err.matches(errMatchString)) {
Assertions.fail("Error stream does not match '" + errMatchString + "'");
}
}
for (String outMatchString : config.getOutMatches()) {
if (!out.matches(outMatchString)) {
Assertions.fail("Error stream does not match '" + outMatchString + "'");
}
for (String errContainsString : config.getErrContains()) {
if (!err.contains(errContainsString)) {
Assertions.fail("Error stream does not contain '" + errContainsString + "'");
}
}
for (String outContainsString : config.getOutContains()) {
if (!out.contains(outContainsString)) {
Assertions.fail("Error stream does not contain '" + outContainsString + "'");
}
for (String outMatchString : config.getOutMatches()) {
if (!out.matches(outMatchString)) {
Assertions.fail("Output stream does not match '" + outMatchString + "'");
}
}
}
protected void ensureOutputDir(String outputDir) {
File outputDirFile = Paths.get(outputDir).toFile();
if (outputDirFile.exists()) {
assertTrue(outputDirFile.isDirectory());
if (Objects.requireNonNull(outputDirFile.list(), "Could not read output directory").length != 0) {
System.out.println("output directory is not empty!");
for (String outContainsString : config.getOutContains()) {
if (!out.contains(outContainsString)) {
Assertions.fail("Output stream does not contain '" + outContainsString + "'");
}
} else {
assertTrue(outputDirFile.mkdirs());
}
}
private void comparePaths(Path outPath, Path expectedPath) {
final Collection<File> files = FileUtils.listFiles(expectedPath.toFile(), TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
files.forEach(f -> {
final Path relative = expectedPath.relativize(f.toPath());
final String relativePath = relative.toFile().getPath();
final File bfile = new File(outPath.toFile(), relativePath);
if (bfile.exists()) {
try {
final Charset charset = Charset.defaultCharset();
final String expected = FileUtils.readFileToString(f, charset);
final String result = FileUtils.readFileToString(bfile, charset);
Assertions.assertEquals(expected, result);
} catch (IOException e) {
Assertions.fail("Unable to compare input files '" + f + "' and '" + bfile + "'", e);
}
} else {
Assertions.fail(relativePath + " expected to exist");
}
});
}
@TestFactory
Stream<DynamicTest> testAll() {
File baseDir = new File("src/test/resources/");
Assertions.assertTrue(baseDir.exists());
Assertions.assertTrue(baseDir.isDirectory());
File[] files = baseDir.listFiles((FileFilter) FileFilterUtils.directoryFileFilter());
Assertions.assertNotNull(files);
return Arrays.stream(files).map(File::toPath).map(f -> DynamicTest.dynamicTest(f.getFileName().toString(),
() -> directoryTest(mainClass, f)));
}
}
......@@ -9,6 +9,35 @@ public class Configuration {
private String[] errContains = new String[]{};
private String[] outMatches = new String[]{};
private String[] outContains = new String[]{};
private String in = "in";
private String out = "out";
private String expected = "expected";
private boolean compare = false;
public String getIn() {
return in;
}
public void setIn(String in) {
this.in = in;
}
public String getOut() {
return out;
}
public void setOut(String out) {
this.out = out;
}
public String getExpected() {
return expected;
}
public void setExpected(String expected) {
this.expected = expected;
}
@com.fasterxml.jackson.annotation.JsonGetter("out-matches")
public String[] getOutMatches() {
......@@ -46,7 +75,7 @@ public class Configuration {
}
@com.fasterxml.jackson.annotation.JsonSetter("err-contains")
public void setErrContains(String[] errMatches) {
public void setErrContains(String[] errContains) {
this.errContains = errContains;
}
......@@ -75,4 +104,14 @@ public class Configuration {
public void shouldFail(boolean fail) {
this.fail = fail;
}
@com.fasterxml.jackson.annotation.JsonGetter("compare")
public boolean shouldCompare() {
return compare;
}
@com.fasterxml.jackson.annotation.JsonSetter("compare")
public void shouldCompare(boolean compare) {
this.compare = compare;
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment