/* * ****************************************************************************** * MontiCore Language Workbench * Copyright (c) 2015, MontiCore, All rights reserved. * * This project is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this project. If not, see <http://www.gnu.org/licenses/>. * ****************************************************************************** */ package de.monticore.codegen; import static org.junit.Assert.assertTrue; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collection; import java.util.List; import java.util.Optional; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.JavaCompiler; import javax.tools.JavaCompiler.CompilationTask; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import org.apache.commons.io.FileUtils; import com.google.common.collect.Lists; import de.monticore.MontiCoreConfiguration; import de.se_rwth.commons.logging.Log; /** * TODO: Write me! * * @author (last commit) $Author$ * @version $Revision$, $Date$ */ public abstract class GeneratorTest { /** * Parent folder for the generated code */ protected static final String OUTPUT_FOLDER = "target/generated-sources/monticore/codetocompile"; protected static final String GRAMMAR_EXTENSION = ".mc4"; /** * Base generator arguments */ private List<String> generatorArguments = Lists .newArrayList( getConfigProperty(MontiCoreConfiguration.Options.MODELPATH.toString()), "src/test/resources", getConfigProperty(MontiCoreConfiguration.Options.OUT.toString()), OUTPUT_FOLDER, getConfigProperty(MontiCoreConfiguration.Options.HANDCODEDPATH.toString()), "src/test/resources"); protected static final String LOG = "GeneratorTest"; /** * Generated source code using the generator which has to be tested * * @param model */ protected abstract void doGenerate(String model); /** * Gets path to the generated code for the given model * * @param model * @return path to the generated code */ protected abstract Path getPathToGeneratedCode(String model); /** * Test generation of code for a correct model * * @param model */ public abstract void testCorrect(String model); public void testCorrect(String model, boolean compileGeneratedCode) { if (compileGeneratedCode) { testCorrect(model); } else { doGenerate(model); } } public void testCorrect(String model, Path pathToCompile) { doGenerate(model); doCompile(model, pathToCompile); // TODO: fix compile path of visitor } /** * TODO: extend path to compile * * @param model * @param pathToCompile */ protected void doCompile(String model, Path pathToCompile) { boolean compilationSuccess = compile(pathToCompile); assertTrue("There are compile errors in generated code for the model: " + model, compilationSuccess); } /** * Test generation of code for a false model TODO: Write me! * * @param model * @param errorsNumber expected errors */ protected void testFalse(String model, int errorsNumber) { // implement } /** * Compiles the files in the given directory, printing errors to the console * if any occur. * * @param sourceCodePath the source directory to be compiled * @return true if the compilation succeeded */ protected boolean compile(Path sourceCodePath) { DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); boolean compilationSuccess = false; Optional<CompilationTask> task = setupCompilation(sourceCodePath, diagnostics); if (!task.isPresent()) { return compilationSuccess; } compilationSuccess = task.get().call(); if (!compilationSuccess) { for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) { Log.error(diagnostic.toString()); } } return compilationSuccess; } /** * Instantiates all the parameters required for a CompilationTask and returns * the finished task. * * @param sourceCodePath the source directory to be compiled * @param diagnostics a bin for any error messages that may be generated by * the compiler * @return the compilationtask that will compile any entries in the given * directory */ protected Optional<CompilationTask> setupCompilation(Path sourceCodePath, DiagnosticCollector<JavaFileObject> diagnostics) { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); if (compiler != null) { StandardJavaFileManager fileManager = compiler .getStandardFileManager(diagnostics, null, null); // set compiler's classpath to be same as the runtime's String sPath = Paths.get("target/generated-sources/monticore/codetocompile") .toAbsolutePath().toString(); List<String> optionList = Lists.newArrayList("-classpath", System.getProperty("java.class.path") + File.pathSeparator + sPath, "-sourcepath", sPath); // System.out.println("Options" + optionList); Iterable<? extends JavaFileObject> javaFileObjects = getJavaFileObjects(sourceCodePath, fileManager); // System.out.println("Java files" + javaFileObjects); return Optional.of(compiler.getTask(null, fileManager, diagnostics, optionList, null, javaFileObjects)); } return Optional.empty(); } /** * Creates an Iterable over all the JavaFileObjects contained in a given * directory. * * @param sourceCodePath the directory from which JavaFileObjects are to be * retrieved * @param fileManager the StandardJavaFileManager to be used for the * JavaFileObject creation * @return the JavaFileObjects contained in the given directory */ protected Iterable<? extends JavaFileObject> getJavaFileObjects(Path sourceCodePath, StandardJavaFileManager fileManager) { Collection<File> files = FileUtils.listFiles(sourceCodePath.toFile(), new String[] { "java" }, true); return fileManager.getJavaFileObjects(files.toArray(new File[files.size()])); } protected void dependencies(String... dependencies) { for (String dependency : dependencies) { if (!Files.exists(getPathToGeneratedCode(dependency))) { doGenerate(dependency); compile(getPathToGeneratedCode(dependency)); } } } /** * @return generatorArguments */ public List<String> getGeneratorArguments() { return this.generatorArguments; } /** * @param generatorArguments the generatorArguments to set */ public void setGeneratorArguments(List<String> generatorArguments) { this.generatorArguments = generatorArguments; } public static String getConfigProperty(String property) { return new StringBuilder("-").append(property).toString(); } }