From 579dc511e0cb307ad3027dc09d4829e7eeaa4403 Mon Sep 17 00:00:00 2001 From: Gil Cesar Faria Date: Wed, 22 Apr 2020 12:49:25 -0300 Subject: [PATCH 1/3] Moves to src/test/java to replicate issue #20 --- src/test/{resources => java}/dummy/TestGrammarInitializer.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/{resources => java}/dummy/TestGrammarInitializer.java (100%) diff --git a/src/test/resources/dummy/TestGrammarInitializer.java b/src/test/java/dummy/TestGrammarInitializer.java similarity index 100% rename from src/test/resources/dummy/TestGrammarInitializer.java rename to src/test/java/dummy/TestGrammarInitializer.java From 49b48a39714c4d03489b85fa48cca8bfe466aa61 Mon Sep 17 00:00:00 2001 From: Gil Cesar Faria Date: Wed, 22 Apr 2020 12:49:52 -0300 Subject: [PATCH 2/3] fixes for issues #20 and #21 --- .../antlr/antlr4test/GrammarTestMojo.java | 58 +++++++++++------ .../com/khubla/antlr/antlr4test/Scenario.java | 25 +++----- .../antlr/antlr4test/ScenarioExecutor.java | 62 +++++++++++++++---- .../antlr/antlr4test/TestGrammarTestMojo.java | 7 ++- 4 files changed, 101 insertions(+), 51 deletions(-) diff --git a/src/main/java/com/khubla/antlr/antlr4test/GrammarTestMojo.java b/src/main/java/com/khubla/antlr/antlr4test/GrammarTestMojo.java index e2d5436..0405e92 100644 --- a/src/main/java/com/khubla/antlr/antlr4test/GrammarTestMojo.java +++ b/src/main/java/com/khubla/antlr/antlr4test/GrammarTestMojo.java @@ -27,20 +27,19 @@ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT */ package com.khubla.antlr.antlr4test; -import java.io.*; -import java.lang.reflect.*; -import java.net.*; -import java.nio.charset.*; -import java.util.*; - -import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.tree.*; -import org.apache.maven.plugin.*; -import org.apache.maven.plugins.annotations.*; +import java.io.File; +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; -import org.bitbucket.cowwoc.diffmatchpatch.*; -import org.codehaus.plexus.util.*; /** * @author Tom Everett @@ -89,7 +88,7 @@ public class GrammarTestMojo extends AbstractMojo { * example files */ @Parameter(defaultValue = "/src/test/resources/examples") - private String exampleFiles; + private String exampleFiles = "/src/test/resources/examples"; /** * packageName */ @@ -108,7 +107,7 @@ public class GrammarTestMojo extends AbstractMojo { * file encoding */ @Parameter(defaultValue = "UTF-8") - private String fileEncoding; + private String fileEncoding = "UTF-8"; /** * Full qualified class name to initialize grammar (Lexer and/or Parser) before @@ -270,14 +269,35 @@ public void setScenarios(List scenarios) { } private void testScenarios() throws Exception { + Log mojoLogger = getLog(); + // check if baseDir has been set with some value. + // fix for issue #21 + if (baseDir == null) { + // If not, set to the current directory + baseDir = new File("."); + } for (Scenario scenario : scenarios) { /* * drop message */ - System.out.println("Evaluating Scenario: " + scenario.getScenarioName()); + mojoLogger.info("Evaluating Scenario: " + scenario.getScenarioName()); + // fix for issue #21 + if (scenario.getBaseDir() == null) { + // The base dir does not get its default value + // in Scenario class under certain unknown conditions + // if it is the case, inject the default value from Mojo + scenario.setBaseDir(baseDir); + } + // fix for issue #21 + if (scenario.getExampleFiles() == null) { + // The examples dir does not get its default value + // in Scenario class under certain unknown conditions + // if it is the case, inject the default value from Mojo + scenario.setExampleFiles(exampleFiles); + } if (scenario.isVerbose()) { - System.out.println("baseDir: " + scenario.getBaseDir()); - System.out.println("exampleFiles: " + scenario.getExampleFiles()); + mojoLogger.info("baseDir: " + scenario.getBaseDir()); + mojoLogger.info("exampleFiles: " + scenario.getExampleFiles()); // only check errors if scenario is enabled // so other scenarios are not prevented of being executed. if (scenario.isEnabled()) { @@ -290,11 +310,11 @@ private void testScenarios() throws Exception { } } if (scenario.isEnabled()) { - ScenarioExecutor executor = new ScenarioExecutor(scenario); + ScenarioExecutor executor = new ScenarioExecutor(scenario, mojoLogger); executor.testGrammars(); executor = null; } else { - System.out.println("Scenario " + scenario.getScenarioName() + " is disabled. Skipping."); + mojoLogger.warn("Scenario " + scenario.getScenarioName() + " is disabled. Skipping."); } } } diff --git a/src/main/java/com/khubla/antlr/antlr4test/Scenario.java b/src/main/java/com/khubla/antlr/antlr4test/Scenario.java index 94e9dec..867bfdf 100644 --- a/src/main/java/com/khubla/antlr/antlr4test/Scenario.java +++ b/src/main/java/com/khubla/antlr/antlr4test/Scenario.java @@ -80,7 +80,7 @@ public class Scenario { * example files */ @Parameter(defaultValue = "/src/test/resources/examples") - private String exampleFiles; + private String exampleFiles = "/src/test/resources/examples"; /** * packageName */ @@ -95,10 +95,11 @@ public class Scenario { * file encoding */ @Parameter(defaultValue = "UTF-8") - private String fileEncoding; + private String fileEncoding = "UTF-8"; /** - * Full qualified class name to initialize grammar (Lexer and/or Parser) before test starts + * Full qualified class name to initialize grammar (Lexer and/or Parser) before + * test starts */ @Parameter private String grammarInitializer = null; @@ -110,7 +111,7 @@ public String getScenarioName() { public void setScenarioName(String scenarioName) { this.scenarioName = scenarioName; } - + public String getGrammarName() { return grammarName; } @@ -126,7 +127,7 @@ public CaseInsensitiveType getCaseInsensitiveType() { public void setCaseInsensitiveType(CaseInsensitiveType caseInsensitiveType) { this.caseInsensitiveType = caseInsensitiveType; } - + public String getEntryPoint() { return entryPoint; } @@ -206,22 +207,14 @@ public String getGrammarInitializer() { public void setGrammarInitializer(String grammarInitializer) { this.grammarInitializer = grammarInitializer; } - + /** * Returns the File pointing to the directory where example files can be found. + * * @return */ public File getExampleFilesDir() { return new File(getBaseDir() + "/" + getExampleFiles()); } - - /** - * get a classloader that can find the files we need - */ - public ClassLoader getClassLoader() throws MalformedURLException, ClassNotFoundException { - final URL antlrGeneratedURL = new File(baseDir + "/target/classes").toURI().toURL(); - final URL[] urls = new URL[] { antlrGeneratedURL }; - return new URLClassLoader(urls, Thread.currentThread().getContextClassLoader()); - } - + } diff --git a/src/main/java/com/khubla/antlr/antlr4test/ScenarioExecutor.java b/src/main/java/com/khubla/antlr/antlr4test/ScenarioExecutor.java index 1ed9bc1..7d98523 100644 --- a/src/main/java/com/khubla/antlr/antlr4test/ScenarioExecutor.java +++ b/src/main/java/com/khubla/antlr/antlr4test/ScenarioExecutor.java @@ -30,7 +30,11 @@ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; import java.nio.charset.Charset; +import java.util.HashMap; import java.util.List; import org.antlr.v4.runtime.CharStream; @@ -41,15 +45,19 @@ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.TokenStream; import org.antlr.v4.runtime.tree.Trees; +import org.apache.maven.plugin.logging.Log; import org.bitbucket.cowwoc.diffmatchpatch.DiffMatchPatch; import org.codehaus.plexus.util.FileUtils; public class ScenarioExecutor { private Scenario scenario = null; + private Log log = null; + private HashMap classLoaderMap = new HashMap<>(); - public ScenarioExecutor(Scenario scenario) { + public ScenarioExecutor(Scenario scenario, Log log) { this.scenario = scenario; + this.log = log; } public void testGrammars() throws Exception { @@ -94,29 +102,34 @@ private void testGrammar(Scenario scenario, File grammarFile) throws Exception { final String lexerClassName = nn + "Lexer"; final String parserClassName = nn + "Parser"; if (scenario.isVerbose()) { - System.out.println("Lexer classname is: " + lexerClassName); - System.out.println("Parser classname is: " + parserClassName); + log.info("Lexer classname is: " + lexerClassName); + log.info("Parser classname is: " + parserClassName); } /* * classloader */ - final ClassLoader classLoader = scenario.getClassLoader(); + // create grammarClassLoader as child of current thread's context classloader + final ClassLoader grammarClassLoader = getClassLoader(scenario, "/target/classes"); + // testClassLoader should be grammarClassLoader's child so test classes can find + // grammar classes + final ClassLoader testClassLoader = getClassLoader(scenario, "/target/test-classes", grammarClassLoader); /* * get the classes we need */ - final Class lexerClass = classLoader.loadClass(lexerClassName).asSubclass(Lexer.class); - final Class parserClass = classLoader.loadClass(parserClassName).asSubclass(Parser.class); + final Class lexerClass = grammarClassLoader.loadClass(lexerClassName).asSubclass(Lexer.class); + final Class parserClass = grammarClassLoader.loadClass(parserClassName) + .asSubclass(Parser.class); Class initializerClass = null; String grammarInitializer = scenario.getGrammarInitializer(); if (grammarInitializer != null && !"".equals(grammarInitializer)) { - initializerClass = classLoader.loadClass(grammarInitializer).asSubclass(GrammarInitializer.class); + initializerClass = testClassLoader.loadClass(grammarInitializer).asSubclass(GrammarInitializer.class); } /* * get ctors */ final Constructor lexerConstructor = lexerClass.getConstructor(CharStream.class); final Constructor parserConstructor = parserClass.getConstructor(TokenStream.class); - System.out.println("Parsing :" + grammarFile.getAbsolutePath()); + log.info("Parsing :" + grammarFile.getAbsolutePath()); CharStream antlrFileStream; if (scenario.getCaseInsensitiveType() == CaseInsensitiveType.None) { antlrFileStream = CharStreams.fromPath(grammarFile.toPath(), Charset.forName(scenario.getFileEncoding())); @@ -144,7 +157,7 @@ private void testGrammar(Scenario scenario, File grammarFile) throws Exception { * initializer lexer and parser */ if (initializerClass != null) { - System.out.println(initializerClass.getName()); + log.info(initializerClass.getName()); GrammarInitializer initializer = (GrammarInitializer) initializerClass.newInstance(); initializer.initialize(lexer, parser); } @@ -154,8 +167,9 @@ private void testGrammar(Scenario scenario, File grammarFile) throws Exception { */ if (scenario.isVerbose()) { tokens.fill(); + log.info("Token List: "); for (final Object tok : tokens.getTokens()) { - System.out.println(tok); + log.info(tok.toString()); } } @@ -168,7 +182,8 @@ private void testGrammar(Scenario scenario, File grammarFile) throws Exception { */ if (scenario.isShowTree()) { final String lispTree = Trees.toStringTree(parserRuleContext, parser); - System.out.println(lispTree); + log.info("Parsed Tree: "); + log.info(lispTree); } /* * check syntax @@ -188,8 +203,7 @@ private void testGrammar(Scenario scenario, File grammarFile) throws Exception { } throw new Exception(sb.toString()); } else { - System.out.println( - "Parse tree for '" + grammarFile.getName() + "' matches '" + treeFile.getName() + "'"); + log.info("Parse tree for '" + grammarFile.getName() + "' matches '" + treeFile.getName() + "'"); } } } @@ -203,4 +217,26 @@ private void testGrammar(Scenario scenario, File grammarFile) throws Exception { antlrFileStream = null; } + /** + * build a classloader that can find the files we need + */ + private ClassLoader getClassLoader(Scenario scenario, String relativePath, ClassLoader parent) + throws MalformedURLException, ClassNotFoundException { + final URL antlrGeneratedURL = new File(scenario.getBaseDir(), relativePath).toURI().toURL(); + // check if classloader for this URL was already created. + ClassLoader ret = classLoaderMap.get(antlrGeneratedURL); + if (ret == null) { + // if not, create a new one and cache it to avoid recreating. + final URL[] urls = new URL[] { antlrGeneratedURL }; + ret = new URLClassLoader(urls, parent); + classLoaderMap.put(antlrGeneratedURL, ret); + } + return ret; + } + + private ClassLoader getClassLoader(Scenario scenario, String relativePath) + throws MalformedURLException, ClassNotFoundException { + // create a classloader child of Thread.currentThread().getContextClassLoader(). + return getClassLoader(scenario, relativePath, Thread.currentThread().getContextClassLoader()); + } } diff --git a/src/test/java/test/com/khubla/antlr/antlr4test/TestGrammarTestMojo.java b/src/test/java/test/com/khubla/antlr/antlr4test/TestGrammarTestMojo.java index b8a62f1..db3d247 100644 --- a/src/test/java/test/com/khubla/antlr/antlr4test/TestGrammarTestMojo.java +++ b/src/test/java/test/com/khubla/antlr/antlr4test/TestGrammarTestMojo.java @@ -185,8 +185,7 @@ public void testGrammarInitializer() throws Exception { grammarTestMojo.setBaseDir(new File(getAbsolutePath("../..")).getCanonicalFile()); grammarTestMojo.setFileEncoding("UTF-8"); grammarTestMojo.execute(); - - + } catch (final Exception e) { e.printStackTrace(); Assert.fail("Unexpected exception " + e); @@ -214,7 +213,9 @@ public void testScenarioConfiguration() throws Exception { assertEquals(5, scenarios.size()); HashMap scenarioMap = new HashMap<>(); for (Scenario scenario : scenarios) { - scenario.setBaseDir(new File(getAbsolutePath("../..")).getCanonicalFile()); +// commented to simulate conditions described in issue #21 to replicate the issue +// https://github.com/antlr/antlr4test-maven-plugin/issues/21 +// scenario.setBaseDir(new File(getAbsolutePath("../..")).getCanonicalFile()); scenario.setFileEncoding("UTF-8"); scenarioMap.put(scenario.getScenarioName(), scenario); } From 7f5c529b10a06804bdcdab1d54707e25bbf0b3b3 Mon Sep 17 00:00:00 2001 From: Gil Cesar Faria Date: Wed, 22 Apr 2020 15:18:14 -0300 Subject: [PATCH 3/3] Fix issues #20 and #21 --- .../antlr/antlr4test/GrammarTestMojo.java | 34 ++++++++++++++++++- .../antlr/antlr4test/ScenarioExecutor.java | 16 +++++---- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/khubla/antlr/antlr4test/GrammarTestMojo.java b/src/main/java/com/khubla/antlr/antlr4test/GrammarTestMojo.java index 0405e92..7ef8ed3 100644 --- a/src/main/java/com/khubla/antlr/antlr4test/GrammarTestMojo.java +++ b/src/main/java/com/khubla/antlr/antlr4test/GrammarTestMojo.java @@ -122,6 +122,14 @@ public class GrammarTestMojo extends AbstractMojo { @Parameter private List scenarios = null; + /* read outputDirectory from pom project.build.outputDirectory */ + @Parameter(defaultValue = "${project.build.outputDirectory}", readonly = true) + private String outputDirectory = "/target/classes"; + + /* read testOutputDirectory from pom project.build.testOutputDirectory */ + @Parameter(defaultValue = "${project.build.testOutputDirectory}", readonly = true) + private String testOutputDirectory = "/target/test-classes"; + /** * ctor * @@ -268,6 +276,30 @@ public void setScenarios(List scenarios) { this.scenarios = scenarios; } + public String getGrammarInitializer() { + return grammarInitializer; + } + + public void setGrammarInitializer(String grammarInitializer) { + this.grammarInitializer = grammarInitializer; + } + + public String getOutputDirectory() { + return outputDirectory; + } + + public void setOutputDirectory(String outputDirectory) { + this.outputDirectory = outputDirectory; + } + + public String getTestOutputDirectory() { + return testOutputDirectory; + } + + public void setTestOutputDirectory(String testOutputDirectory) { + this.testOutputDirectory = testOutputDirectory; + } + private void testScenarios() throws Exception { Log mojoLogger = getLog(); // check if baseDir has been set with some value. @@ -310,7 +342,7 @@ private void testScenarios() throws Exception { } } if (scenario.isEnabled()) { - ScenarioExecutor executor = new ScenarioExecutor(scenario, mojoLogger); + ScenarioExecutor executor = new ScenarioExecutor(this, scenario, mojoLogger); executor.testGrammars(); executor = null; } else { diff --git a/src/main/java/com/khubla/antlr/antlr4test/ScenarioExecutor.java b/src/main/java/com/khubla/antlr/antlr4test/ScenarioExecutor.java index 7d98523..4af09cc 100644 --- a/src/main/java/com/khubla/antlr/antlr4test/ScenarioExecutor.java +++ b/src/main/java/com/khubla/antlr/antlr4test/ScenarioExecutor.java @@ -53,9 +53,11 @@ public class ScenarioExecutor { private Scenario scenario = null; private Log log = null; + private GrammarTestMojo mojo = null; private HashMap classLoaderMap = new HashMap<>(); - public ScenarioExecutor(Scenario scenario, Log log) { + public ScenarioExecutor(GrammarTestMojo mojo, Scenario scenario, Log log) { + this.mojo = mojo; this.scenario = scenario; this.log = log; } @@ -109,10 +111,10 @@ private void testGrammar(Scenario scenario, File grammarFile) throws Exception { * classloader */ // create grammarClassLoader as child of current thread's context classloader - final ClassLoader grammarClassLoader = getClassLoader(scenario, "/target/classes"); + final ClassLoader grammarClassLoader = getClassLoader(mojo.getOutputDirectory()); // testClassLoader should be grammarClassLoader's child so test classes can find // grammar classes - final ClassLoader testClassLoader = getClassLoader(scenario, "/target/test-classes", grammarClassLoader); + final ClassLoader testClassLoader = getClassLoader(mojo.getTestOutputDirectory(), grammarClassLoader); /* * get the classes we need */ @@ -220,9 +222,9 @@ private void testGrammar(Scenario scenario, File grammarFile) throws Exception { /** * build a classloader that can find the files we need */ - private ClassLoader getClassLoader(Scenario scenario, String relativePath, ClassLoader parent) + private ClassLoader getClassLoader(String path, ClassLoader parent) throws MalformedURLException, ClassNotFoundException { - final URL antlrGeneratedURL = new File(scenario.getBaseDir(), relativePath).toURI().toURL(); + final URL antlrGeneratedURL = new File(path).toURI().toURL(); // check if classloader for this URL was already created. ClassLoader ret = classLoaderMap.get(antlrGeneratedURL); if (ret == null) { @@ -234,9 +236,9 @@ private ClassLoader getClassLoader(Scenario scenario, String relativePath, Class return ret; } - private ClassLoader getClassLoader(Scenario scenario, String relativePath) + private ClassLoader getClassLoader(String path) throws MalformedURLException, ClassNotFoundException { // create a classloader child of Thread.currentThread().getContextClassLoader(). - return getClassLoader(scenario, relativePath, Thread.currentThread().getContextClassLoader()); + return getClassLoader(path, Thread.currentThread().getContextClassLoader()); } }