Skip to content
Snippets Groups Projects
Commit 55ed9bd0 authored by Johannes Mey's avatar Johannes Mey
Browse files

initial commit for new version

parent ea4e069e
No related branches found
No related tags found
No related merge requests found
Showing
with 497 additions and 274 deletions
[submodule "src/main/jastadd/mustache"]
path = src/main/jastadd/mustache
url = ../mustache.git
apply plugin: 'java'
apply plugin: 'jastadd'
apply plugin: 'application'
apply plugin: "idea"
plugins {
id 'java-library'
id 'org.jastadd'
id 'java'
id 'idea'
id 'java-test-fixtures'
id 'com.github.ben-manes.versions' version '0.34.0'
}
sourceCompatibility = 1.8
mainClassName = 'org.jastadd.relast.compiler.RelastSourceToSourceCompiler'
targetCompatibility = 1.8
repositories {
jcenter()
}
buildscript {
repositories.jcenter()
dependencies {
classpath 'org.jastadd:jastaddgradle:1.13.3'
sourceSets {
model {
java {
srcDir "src/gen/java"
}
}
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.0'
testCompile 'org.assertj:assertj-core:3.12.1'
compile 'org.jastadd:jastadd:2.3.4'
runtime 'org.jastadd:jastadd:2.3.4'
compile group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
task modelJar(type: Jar) {
group = "build"
archiveBaseName = 'model'
from sourceSets.model.output
}
sourceSets {
main {
java.srcDir "src/gen/java"
java.srcDir "buildSrc/gen/java"
artifacts {
archives modelJar
}
dependencies {
modelImplementation group: 'org.jastadd', name: 'jastadd', version: '2.3.4'
modelImplementation group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
compileOnly files(modelJar.archiveFile.get())
api group: 'org.jastadd', name: 'jastadd', version: '2.3.4'
api group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
implementation group: 'com.github.jknack', name: 'handlebars', version: '4.2.0'
implementation group: 'org.yaml', name: 'snakeyaml', version: '1.27'
// test
testRuntimeClasspath files(modelJar.archiveFile.get())
// test fixtures
testFixturesApi group: 'org.slf4j', name: 'slf4j-jdk14', version: '1.7.30'
testFixturesApi group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.7.0'
testFixturesApi group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.7.0'
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'
}
test {
......@@ -41,61 +61,47 @@ test {
maxHeapSize = '1G'
}
jar {
manifest {
attributes "Main-Class": 'org.jastadd.relast.compiler.RelastSourceToSourceCompiler'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
// Input and output files for relast
def relastInputFiles = [
"src/main/jastadd/RelAst.relast",
"src/main/jastadd/mustache/Mustache.relast"
]
def relastOutputFiles = [
"src/gen/jastadd/RelAst.ast",
"src/gen/jastadd/RelAst.jadd",
"src/gen/jastadd/RelAstRefResolver.jadd",
"src/gen/jastadd/RelAstResolverStubs.jrag"
]
task relast(type: JavaExec) {
classpath = files("libs/relast.jar")
group = 'Build'
main = "-jar"
doFirst {
delete "src/gen/jastadd/*.ast"
delete "src/gen/jastadd/RelAst.jadd"
delete "src/gen/jastadd/RelAstRefResolver.jadd"
delete "src/gen/jastadd/RelAstResolverStubs.jrag"
delete relastOutputFiles
mkdir "src/gen/jastadd/"
}
args = [
"libs/relast.jar",
"./src/main/jastadd/RelAst.relast",
"--listClass=java.util.ArrayList",
"--jastAddList=JastAddList",
"--useJastAddNames",
"--file",
"--resolverHelper",
"--grammarName=./src/gen/jastadd/RelAst"
]
] + relastInputFiles
inputs.files file("../libs/relast.jar"),
file("src/main/jastadd/RelAst.relast")
outputs.files file("./src/gen/jastadd/RelAst.ast"),
file("src/gen/jastadd/RelAst.jadd"),
file("src/gen/jastadd/RelAstRefResolver.jadd"),
file('src/gen/jastadd/RelAstResolverStubs.jrag')
inputs.files relastInputFiles
outputs.files relastOutputFiles
}
jastadd {
configureModuleBuild()
modules {
//noinspection GroovyAssignabilityCheck
module("RelAst") {
java {
basedir "."
include "src/main/**/*.java"
include "src/gen/**/*.java"
}
module("Preprocessor") {
jastadd {
basedir "."
include "src/main/jastadd/**/*.ast"
include "src/main/jastadd/**/*.jadd"
include "src/main/jastadd/**/*.jrag"
......@@ -122,8 +128,8 @@ jastadd {
}
cleanGen.doFirst {
delete "src/gen/java/org"
delete "src/gen-res/BuildInfo.properties"
delete "src/gen"
delete "src/gen-res"
}
preprocessParser.doFirst {
......@@ -132,7 +138,7 @@ jastadd {
}
module = "RelAst"
module = "Preprocessor"
astPackage = 'org.jastadd.relast.ast'
......@@ -149,3 +155,11 @@ jastadd {
}
generateAst.dependsOn relast
clean.dependsOn(cleanGen)
modelJar.dependsOn(generateAst, modelClasses)
modelClasses.dependsOn(generateAst)
compileJava.dependsOn(modelJar)
jar.dependsOn(modelJar)
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
No preview for this file type
pluginManagement {
plugins {
id 'org.jastadd' version '1.13.3'
}
}
Subproject commit c10bed0d03e3fa18b8133ce1de48de7646899615
......@@ -32,56 +32,80 @@ import org.jastadd.option.Option;
import java.io.PrintStream;
import java.util.*;
import java.util.stream.Collectors;
/**
* Tracks JastAdd configuration options.
*
* @author Jesper Öqvist <jesper.oqvist@cs.lth.se>
*/
public class JastAddConfiguration extends org.jastadd.Configuration {
public class PreprocessorConfiguration extends org.jastadd.Configuration {
/**
* Indicates if there were unknown command-line options
*/
final boolean unknownOptions;
private boolean isJastAddCompliant;
public boolean isJastAddCompliant() {
return isJastAddCompliant;
}
private final Map<String, Option<?>> options = new HashMap<>();
private final boolean isJastAddCompliant;
private final ArgumentParser argParser;
/**
* Parse options from an argument list.
*
* @param args Command-line arguments to build configuration from
* @param err output stream to print configuration warnings to
*/
public JastAddConfiguration(String[] args, PrintStream err, boolean isJastAddCompliant, Collection<Option<?>> extraOptions) {
ArgumentParser argParser = new ArgumentParser();
public PreprocessorConfiguration(String[] args, PrintStream err, boolean isJastAddCompliant, Collection<Option<?>> extraOptions) {
argParser = new ArgumentParser();
this.isJastAddCompliant = isJastAddCompliant;
if (isJastAddCompliant) {
Collection<Option<?>> jastAddOptions = allJastAddOptions();
for (Option<?> o : jastAddOptions) {
options.put(o.name(), o);
}
argParser.addOptions(jastAddOptions);
}
// if the JastAdd options are supported, we have to check for duplicates!
Set<String> jastAddOptionNames = jastAddOptions.stream().map(o -> o.name()).collect(Collectors.toSet());
for (Option option : extraOptions) {
if (jastAddOptionNames.contains(option.name())) {
if (options.containsKey(option.name())) {
System.err.println("Unable to add option '" + option.name() + "', because there is a JastAdd option with the same name.");
} else {
argParser.addOption(option);
options.put(option.name(), option);
}
}
} else {
argParser.addOptions(extraOptions);
}
unknownOptions = !argParser.parseArgs(args, err);
filenames = argParser.getFilenames();
}
public ArgumentParser getArgParser() {
return argParser;
}
public Optional<Option> getOption(String name) {
return options.containsKey(name) ? Optional.of(options.get(name)) : Optional.empty();
}
public boolean isJastAddCompliant() {
return isJastAddCompliant;
}
/**
* Print help
*
* @param out Output stream to print help to.
*/
@Override
public void printHelp(PrintStream out) {
out.println("This program reads a number of .jrag, .jadd, and .ast files");
out.println("Options:");
argParser.printHelp(out);
out.println();
out.println("Arguments:");
out.println(" Names of abstract grammr (.ast) and aspect (.jrag and .jadd) files.");
}
/**
* @return all files
*/
......
package org.jastadd.relast.compiler;
import org.jastadd.JastAddConfiguration;
import org.jastadd.PreprocessorConfiguration;
import org.jastadd.option.FlagOption;
import org.jastadd.option.Option;
import java.util.ArrayList;
......@@ -8,20 +9,16 @@ import java.util.ArrayList;
public abstract class AbstractCompiler {
private final boolean jastAddCompliant;
protected ArrayList<Option<?>> options;
private final String name;
private JastAddConfiguration configuration;
protected ArrayList<Option<?>> options;
private PreprocessorConfiguration configuration;
public AbstractCompiler(String name, boolean jastaddCompliant) {
this.name = name;
this.jastAddCompliant = jastaddCompliant;
}
public JastAddConfiguration getConfiguration() throws CompilerException {
if (configuration == null) {
throw new CompilerException("Configuration only supported for JastAdd-compliant compilers!");
}
public PreprocessorConfiguration getConfiguration() {
return configuration;
}
......@@ -29,7 +26,12 @@ public abstract class AbstractCompiler {
options = new ArrayList<>();
initOptions();
configuration = new JastAddConfiguration(args, System.err, jastAddCompliant, options);
configuration = new PreprocessorConfiguration(args, System.err, jastAddCompliant, options);
if (configuration.shouldPrintHelp()) {
configuration.printHelp(System.out);
return 0;
}
return compile();
}
......@@ -37,10 +39,13 @@ public abstract class AbstractCompiler {
protected abstract int compile() throws CompilerException;
protected void initOptions() {
// there are no options by default
if (!jastAddCompliant) {
addOption(new FlagOption("version", "print version info"));
addOption(new FlagOption("help", "print command-line usage info"));
}
}
protected <OptionType extends Option<?>> OptionType addOption(OptionType option) {
protected <O extends Option<?>> O addOption(O option) {
options.add(option);
return option;
}
......
package org.jastadd.relast.compiler;
import com.github.jknack.handlebars.Handlebars;
import com.github.jknack.handlebars.Template;
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;
public class Mustache {
public static void javaMustache(String templateFileName, String yamlFileName, String outputFileName) throws IOException {
Object context = new Yaml().load(new FileReader(yamlFileName));
TemplateLoader loader = new ClassPathTemplateLoader();
loader.setSuffix(".mustache"); // the default is ".hbs"
Handlebars handlebars = new Handlebars(loader);
handlebars.prettyPrint(true); // set handlebars to mustache mode (skip some whitespace)
Template template = handlebars.compile(templateFileName);
try (Writer w = new FileWriter(outputFileName)) {
template.apply(context, w);
w.flush();
}
}
}
package org.jastadd.relast.compiler;
import org.jastadd.option.ValueOption;
import org.jastadd.relast.ast.GrammarFile;
import org.jastadd.relast.ast.Program;
import org.jastadd.relast.parser.RelAstParser;
import org.jastadd.relast.scanner.RelAstScanner;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;
public abstract class RelAstProcessor extends AbstractCompiler {
protected ValueOption optionOutputBaseDir;
protected ValueOption optionInputBaseDir;
public RelAstProcessor(String name, boolean jastAddCompliant) {
super(name, jastAddCompliant);
}
protected static boolean isGrammarFile(String fileName) {
String extension = fileName.subSequence(fileName.lastIndexOf('.'), fileName.length()).toString();
return extension.equals(".relast") || extension.equals(".ast");
}
@Override
protected void initOptions() {
optionOutputBaseDir = addOption(new ValueOption("outputBaseDir", "base directory for generated files"));
optionInputBaseDir = addOption(new ValueOption("inputBaseDir", "base directory for input files"));
super.initOptions();
}
@Override
protected int compile() throws CompilerException {
final Path inputBasePath;
if (optionInputBaseDir.isMatched()) {
inputBasePath = Paths.get(optionInputBaseDir.value()).toAbsolutePath();
} else {
inputBasePath = Paths.get(".").toAbsolutePath();
printMessage("No input base dir is set. Assuming current directory '" + inputBasePath.toAbsolutePath().toString() + "'.");
}
if (!inputBasePath.toFile().exists()) {
printMessage("Input path '" + inputBasePath.toAbsolutePath().toString() + "' does not exist. Exiting...");
System.exit(-1);
} else if (!inputBasePath.toFile().isDirectory()) {
printMessage("Input path '" + inputBasePath.toAbsolutePath().toString() + "' is not a directory. Exiting...");
System.exit(-1);
}
final Path outputBasePath;
if (optionOutputBaseDir.isMatched()) {
outputBasePath = Paths.get(optionOutputBaseDir.value()).toAbsolutePath();
} else {
throw new CompilerException("No output base dir is set.");
}
if (outputBasePath.toFile().exists() && !outputBasePath.toFile().isDirectory()) {
printMessage("Output path '" + inputBasePath.toAbsolutePath().toString() + "' exists, but is not a directory. Exiting...");
}
printMessage("Running " + getName());
// gather all files
Collection<Path> inputFiles = new ArrayList<>();
getConfiguration().getFiles().forEach(name -> relativizeFileName(inputBasePath, Paths.get(name)).ifPresent(inputFiles::add));
Program program = parseProgram(inputFiles);
return processGrammar(program, inputBasePath, outputBasePath);
}
protected abstract int processGrammar(Program program, Path inputBasePath, Path outputBasePath) throws CompilerException;
private Optional<Path> relativizeFileName(Path inputBasePath, Path filePath) {
if (filePath.isAbsolute()) {
if (filePath.startsWith(inputBasePath)) {
return Optional.of(filePath.relativize(inputBasePath));
} else {
printMessage("Path '" + filePath + "' is not contained in the base path '" + inputBasePath + "'.");
return Optional.empty();
}
} else {
return Optional.of(inputBasePath.resolve(filePath));
}
}
protected void printMessage(String message) {
System.out.println(message);
}
protected void writeToFile(Path path, String str) throws CompilerException {
//noinspection ResultOfMethodCallIgnored
path.getParent().toFile().mkdirs(); // create directory structure if necessary
try (PrintWriter writer = new PrintWriter(path.toFile())) {
writer.print(str);
} catch (Exception e) {
throw new CompilerException("Could not write to file " + path, e);
}
}
private Program parseProgram(Collection<Path> inputFiles) {
Program program = new Program();
RelAstParser parser = new RelAstParser();
inputFiles.stream().filter(path -> isGrammarFile(path.toString())).forEach(
path -> {
try (BufferedReader reader = Files.newBufferedReader(path)) {
RelAstScanner scanner = new RelAstScanner(reader);
GrammarFile inputGrammar = (GrammarFile) parser.parse(scanner);
inputGrammar.setFileName(path.toString());
program.addGrammarFile(inputGrammar);
inputGrammar.treeResolveAll();
} catch (IOException | beaver.Parser.Exception e) {
printMessage("Could not parse grammar file " + path);
e.printStackTrace();
}
}
);
return program;
}
}
package org.jastadd.relast.compiler;
import beaver.Parser;
import org.jastadd.option.ValueOption;
import org.jastadd.relast.ast.GrammarFile;
import org.jastadd.relast.ast.Program;
import org.jastadd.relast.parser.RelAstParser;
import org.jastadd.relast.scanner.RelAstScanner;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;
public class RelastSourceToSourceCompiler extends AbstractCompiler {
public class RelastSourceToSourceCompiler extends RelAstProcessor {
protected ValueOption optionOutputBaseDir;
protected ValueOption optionInputBaseDir;
public RelastSourceToSourceCompiler(String name, boolean jastAddCompliant) {
super(name, jastAddCompliant);
}
......@@ -42,103 +28,16 @@ public class RelastSourceToSourceCompiler extends AbstractCompiler {
}
@Override
protected void initOptions() {
optionOutputBaseDir = addOption(new ValueOption("outputBaseDir", "base directory for generated files"));
optionInputBaseDir = addOption(new ValueOption("inputBaseDir", "base directory for input files"));
}
@Override
protected int compile() throws CompilerException {
final Path inputBasePath;
if (optionInputBaseDir.isMatched()) {
inputBasePath = Paths.get(optionInputBaseDir.value()).toAbsolutePath();
} else {
inputBasePath = Paths.get(".").toAbsolutePath();
printMessage("No input base dir is set. Assuming current directory '" + inputBasePath.toAbsolutePath().toString() + "'.");
}
if (!inputBasePath.toFile().exists()) {
printMessage("Input path '" + inputBasePath.toAbsolutePath().toString() + "' does not exist. Exiting...");
System.exit(-1);
} else if (!inputBasePath.toFile().isDirectory()) {
printMessage("Input path '" + inputBasePath.toAbsolutePath().toString() + "' is not a directory. Exiting...");
System.exit(-1);
}
final Path outputBasePath;
if (optionOutputBaseDir.isMatched()) {
outputBasePath = Paths.get(optionOutputBaseDir.value()).toAbsolutePath();
} else {
throw new CompilerException("No output base dir is set.");
}
if (outputBasePath.toFile().exists() && !outputBasePath.toFile().isDirectory()) {
printMessage("Output path '" + inputBasePath.toAbsolutePath().toString() + "' exists, but is not a directory. Exiting...");
}
printMessage("Running RelAST Preprocessor");
// gather all files
Collection<Path> inputFiles = new ArrayList<>();
getConfiguration().getFiles().forEach(name -> relativizeFileName(inputBasePath, Paths.get(name)).ifPresent(path -> inputFiles.add(path)));
Program program = parseProgram(inputFiles);
protected int processGrammar(Program program, Path inputBasePath, Path outputBasePath) throws CompilerException {
printMessage("Writing output files");
for (GrammarFile grammarFile : program.getGrammarFileList()) {
printMessage("Writing output file " + grammarFile.getFileName());
// TODO decide and document what the file name should be, the full path or a simple name?
writeToFile(outputBasePath.resolve(inputBasePath.relativize(Paths.get(grammarFile.getFileName()))), grammarFile.generateAbstractGrammar());
}
return 0;
}
private Optional<Path> relativizeFileName(Path inputBasePath, Path filePath) {
if (filePath.isAbsolute()) {
if (filePath.startsWith(inputBasePath)) {
return Optional.of(filePath.relativize(inputBasePath));
} else {
printMessage("Path '" + filePath + "' is not contained in the base path '" + inputBasePath + "'.");
return Optional.empty();
}
} else {
return Optional.of(inputBasePath.resolve(filePath));
}
}
private void printMessage(String message) {
System.out.println(message);
}
private void writeToFile(Path path, String str) throws CompilerException {
try (PrintWriter writer = new PrintWriter(path.toFile())) {
writer.print(str);
} catch (Exception e) {
throw new CompilerException("Could not write to file " + path, e);
}
}
private Program parseProgram(Collection<Path> inputFiles) throws CompilerException {
Program program = new Program();
RelAstParser parser = new RelAstParser();
inputFiles.stream().filter(path -> isGrammarFile(path.toString())).forEach(
path -> {
try (BufferedReader reader = Files.newBufferedReader(path)) {
RelAstScanner scanner = new RelAstScanner(reader);
GrammarFile inputGrammar = (GrammarFile) parser.parse(scanner);
inputGrammar.setFileName(path.toString());
program.addGrammarFile(inputGrammar);
inputGrammar.treeResolveAll();
} catch (IOException | Parser.Exception e) {
printMessage("Could not parse grammar file " + path);
e.printStackTrace();
}
}
);
return program;
}
}
package org.jastadd.relast.compiler;
import java.util.*;
import java.util.function.Predicate;
import static java.util.stream.Collectors.toList;
public class Utils {
public static <T> List<T> filterToList(Collection<T> collection, Predicate<T> predicate) {
return collection.stream().filter(predicate).collect(toList());
}
public static <T> Set<T> asSet(T... t) {
return new HashSet<T>(Arrays.asList(t));
}
}
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
\ No newline at end of file
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;
public class PreprocessorTest extends RelAstProcessorTestBase {
@Test
void testMinimalGrammar() throws IOException, InterruptedException {
directoryTest(RelastSourceToSourceCompiler.class, Paths.get("src/test/resources/MinimalGrammar"));
}
}
package org.jastadd.ros2rag.tests;
import org.jastadd.relast.compiler.CompilerException;
import org.jastadd.relast.compiler.RelastSourceToSourceCompiler;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.nio.file.Paths;
import java.util.Objects;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class RelAstTest {
void transform(boolean jastAddCompliant, String inputDir, String outputDir) throws CompilerException {
System.out.println("Running test in directory '" + Paths.get(".").toAbsolutePath() + "'.");
assertTrue(Paths.get(inputDir).toFile().exists(), "input directory does not exist");
assertTrue(Paths.get(inputDir).toFile().isDirectory(), "input directory is not a directory");
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!");
}
} else {
assertTrue(outputDirFile.mkdir());
}
String[] args = {
"--outputBaseDir=" + outputDir,
"--inputBaseDir=" + inputDir,
"Example.relast"
};
new RelastSourceToSourceCompiler("testCompiler", jastAddCompliant).run(args);
}
@Test
void transformMinimalExample() throws CompilerException {
transform(false,"src/test/resources/in", "src/test/resources/out-simple");
transform(true,"src/test/resources/in", "src/test/resources/out-compliant");
}
}
- name: "MinimalGrammar"
args:
- "--inputBaseDir=in"
- "--outputBaseDir=out"
- "Example.relast"
- name: "Comments in front"
args:
- "--inputBaseDir=in"
- "--outputBaseDir=out"
- "CommentInFront.relast"
// comment
CommentInFront ;
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.assertj.core.util.Files;
import org.jastadd.relast.tests.config.Configuration;
import org.junit.jupiter.api.Assertions;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
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;
public class RelAstProcessorTestBase {
protected static int runProcess(File workingDirectory, List<String> command, StringBuilder outStringBuider, StringBuilder errStringBuilder) throws IOException, InterruptedException {
File outFile = Files.newTemporaryFile();
File errFile = Files.newTemporaryFile();
ProcessBuilder pb = new ProcessBuilder(command).
directory(workingDirectory)
.redirectOutput(outFile)
.redirectError(errFile);
Process p = pb.start();
try {
p.waitFor();
} catch (InterruptedException e) {
if (Thread.interrupted()) // Clears interrupted status!
throw e;
}
try (BufferedReader outReader = new BufferedReader(new FileReader(outFile))) {
String outLine;
while ((outLine = outReader.readLine()) != null) {
outStringBuider.append(outLine).append("\n");
}
}
try (BufferedReader errReader = new BufferedReader(new FileReader(errFile))) {
String errLine;
while ((errLine = errReader.readLine()) != null) {
errStringBuilder.append(errLine).append("\n");
}
}
return p.exitValue();
}
protected static int runJavaProcess(Class<?> klass, File workingDirectory, List<String> args, StringBuilder outStringBuider, StringBuilder errStringBuilder) throws IOException, InterruptedException {
String javaHome = System.getProperty("java.home");
String javaBin = javaHome + File.separator + "bin" + File.separator + "java";
String classpath = System.getProperty("java.class.path");
String className = klass.getName();
List<String> command = new LinkedList<>();
command.add(javaBin);
command.add("-cp");
command.add(classpath);
command.add(className);
if (args != null) {
command.addAll(args);
}
System.out.println("Running java -jar -cp [...] " + className + " " + args.stream().reduce((s1, s2) -> s1 + " " + s2).orElse(""));
return runProcess(workingDirectory, command, outStringBuider, errStringBuilder);
}
protected void directoryTest(Class<?> mainClass, Path dir) throws IOException, InterruptedException {
dir = dir.toAbsolutePath();
Path configFile = dir.resolve("config.yaml");
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
List<Configuration> configs = mapper.readValue(configFile.toFile(), new TypeReference<List<Configuration>>() {
});
for (Configuration config : configs) {
StringBuilder outBuilder = new StringBuilder();
StringBuilder errBuilder = new StringBuilder();
int returnValue = runJavaProcess(mainClass, dir.toFile(), Arrays.asList(config.getArgs()), outBuilder, errBuilder);
String out = outBuilder.toString();
String err = errBuilder.toString();
System.out.println(out);
System.err.println(err);
if (config.shouldFail()) {
Assertions.assertNotEquals(0, returnValue, "Zero return value of preprocessor for negative test.");
} else {
Assertions.assertEquals(0, returnValue, "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 + "'");
}
}
for (String errContainsString : config.getErrContains()) {
if (!err.contains(errContainsString)) {
Assertions.fail("Error stream does not contain '" + errContainsString + "'");
}
}
for (String outMatchString : config.getOutMatches()) {
if (!out.matches(outMatchString)) {
Assertions.fail("Error stream does not match '" + outMatchString + "'");
}
}
for (String outContainsString : config.getOutContains()) {
if (!out.contains(outContainsString)) {
Assertions.fail("Error stream does not contain '" + outContainsString + "'");
}
}
}
}
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!");
}
} else {
assertTrue(outputDirFile.mkdirs());
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment