Antlr4 "Test Rig" and maven - java

I am struggling a little bit to figure out how I can use the antlr4 maven plug in to run the TestRig class?
I've read though the output of mvn antlr4:help -Ddetail=true, which is the only documentation I have been able to find, but this doesn't mention how to use the TestRig. So, what's the recommended way of using the test rig together with maven? using the grun alias method doesn't seem very elegant here.
UPDATED - Reasoning
Hello :)
Right, don't get me wrong but I really don't understand why you wouldn't want this functionality in the maven plugin? And I don't understand why its soul purpose should be to compile grammars?
Currently, if I maintain a build with Maven, and I use the antlr4-maven-plugin , it will install both the plugin and the antlr 4.1 in my maven repository. With this already there, why would I start adding things to my classpath and creating aliases when maven can take care of that? I mean, this is what maven is for really. If I had a antlr4:TestRig goal, then all I would do was use that. No need to manually maintain the class path, or create bash aliases. It would just work.
And be far far more elegant that hard-coding elements from my local maven repository in my class path, and maintaining bash aliases. Or alternatively, maintain two installations per. version of antlr I wish to use (one maintained by me, simply to use TestRig, and one maintained by maven for everything else).
Additionally, if I wanted to use a different version of antlr, then I wouldn't need to update the classpath and my aliases, maven would simply manage all this for me :)

This is how I invoke TestRig with Maven:
mvn exec:java -Dexec.mainClass="org.antlr.v4.runtime.misc.TestRig"
-Dexec.args="<DOT_NOTATION_GRAMMAR_CLASSPATH> <START_RULE>
-gui <INPUT_FILE>"
So if you've got MyGrammar.g4 in src/main/antlr4/com/test/parser with a starting rule of startRule:
mvn exec:java -Dexec.mainClass="org.antlr.v4.runtime.misc.TestRig"
-Dexec.args="com.test.parser.MyGrammar startRule
-gui <INPUT_FILE>"

I had a similar question, in that I wanted to use the TestRig -gui option for debugging my grammar. I didn't find a way to run the GUI via the antlr4-maven-plugin, but I did manage to build a satisfactory CLASSPATH. The key was to include target/classes.
# Assuming your project is in $PROJECT ..
CLASSPATH=".:/usr/local/lib/antlr-4.1-complete.jar:$PROJECT/target/classes"
alias grun='java org.antlr.v4.runtime.misc.TestRig'
mvn -q compile
grun MyGrammer startingRule -gui < test_input
Should produce a lovely GUI view of the syntax tree.

Why would the Maven plugin run the TestRig class? The Maven plugin's job is converting the .g4 grammar files to .java source files in the proper package locations and ensuring those generated files get compiled. TestRig is not used for any part of that.
Edit: I have been using ANTLR for many years, in many applications. In all that time I have never updated my system classpath, nor operated ANTLR/gunit/TestRig from the command line or created aliases for it. Doing so is not helpful for automated testing and inevitably leads users into the problems you described. That said, the thought that TestRig needed special support in the Maven plugin also never crossed my mind, because better solutions already exist.
Some alternatives
You can use the surefire plugin, and write a JUnit test that performs operations on your grammar directly (create a lexer/parser, parse some input, and perhaps even call inspect() on the resulting parse tree.
You can use the surefire plugin, and write a JUnit test that explicitly calls TestRig.main(String[]) with the correct arguments.
You can modify the ANTLR 4 Maven plugin to add a new goal for running TestRig, and submit a pull request to the project to have it included in a future release (you would need to make a very compelling case since there are already 2 alternatives that are more suited to long-term successful testing of a project using ANTLR 4).

I like the idea of using Maven to run the TestRig. But I do not like to add the dependency org.antlr:antlr4 to my code (because I already have org.antlr:antlr4-runtime) so my solution is to configure the exec plugin with an additional dependency.
<properties>
<antlr.version>4.7.1</antlr.version>
</properties>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>TestRigGui</id>
<phase>none</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>org.antlr.v4.gui.TestRig</mainClass>
<arguments>
<!-- Grammar -->
<argument>de.humanfork.experiment.antlr.Hello</argument>
<!-- start rule -->
<argument>hello_rule</argument>
<!-- enable gui -->
<argument>-gui</argument>
<!-- input file -->
<argument>example.txt</argument>
</arguments>
<includePluginDependencies>true</includePluginDependencies>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
<version>${antlr.version}</version>
</dependency>
</dependencies>
</plugin>
Then use: mvn exec:java#TestRigGui to start the GUI
BTW: in ANTLR 4.7.1 the TestRig main class is: org.antlr.v4.gui.TestRig

Related

Configure maven plugin version without changing pom.xml manually

Problem Description
I'm working with a collection of old projects from defects4j. My problem now is that since I want to combine those projects with a newer maven plugin, a regression test tool, there are some issue with the maven surefire plugin version.
In the pom.xml that come along with the projects, there are no specifications of surefire version:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>plain</id>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
<runOrder>random</runOrder>
</configuration>
</execution>
</executions>
</plugin>
However, the regression tool (made into a maven plugin), require surefire version of 2.14 and above. So I get error like this:
[ERROR] Failed to execute goal edu.illinois:starts-maven-plugin:1.4-SNAPSHOT:select (default-cli) on project commons-lang: Unsupported Surefire version: 2.12.4. Use version 2.13 and above
Efforts Done
I checked several stackoverflow posts, and they talked about the effective pom. When I run mvn help:effective-pom, I can see that the version of surefire used is
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
Question
Since the project collection in defects4j does not specify surefire version in their pom.xml, is there a way to specify the surefire version used to 2.14 or above from command line? I want to prevent from manually editing the pom every time.
Update
by running mvn dependency:resolve-plugins, i get
Plugin Resolved: maven-surefire-plugin-2.12.4.jar
So it seems to me that somehow maven use 2.12.4 as a default. The reason maybe that I used this version previously. How do I fix this?
Without modifying the pom manually?
Any advice will be welcomed!
Update:
Problem solved by editing maven's super pom.
Maven takes the newest version from the repository if there was no version fixed in your POM, parent POM or the super POM (from which every Maven project inherits).
It is best practise to fix a version "manually" in the POM. The best place for this is a parent POM from which the projects inherit (this means, only one place to change).
You cannot just supply a version from command line. Unless you do some tricks like putting <version>${surefire.version}</version> into the plugin definition and set this property from command line.
I'm 4+ years removed from working with poms so don't remember everything, but consider a couple of things.
First, since the pom you show isn't specifying the version of surefire to use I don't think that the 2.12.4 version can be coming from that directly. Try getting a dependency tree to see where things are coming from. Try How can you display the Maven dependency tree for the *plugins* in your project? for that and a few other suggestions.
Second, I think I recall that in your own pom you should be able to specify the version of plugin to associate with a dependency that doesn't specify one. You'll have to research that option yourself.
I think your best bet is the dependency tree to find what's using what and where things are coming from. If you get the tree and still can't figure out what to do try adding the tree output to your question. (You can edit out parts that are proprietary, or clearly unrelated.)

Maven prevent build if there is uncommitted changes

Is there any way to check if there is not committed files or untracked files in git repo and prevent maven build?
I mean if I run
mvn install
And install should fail with warning that there is something to commit.
I need this because I want to know hash of commit which corresponds to some builded .war file. Sometimes I forgot to commit changes and build .war file, and as a result I can't reproduce this build exactly as it was.
Generally these kinds of problems are resolved by never building releases out of developer workstations.
One way to avoid that is to have a single machine where the git repository is pulled into a clean directory, and the build is launched from there. Then you always use the "mainline build" for your testing and deployment.
Jenkins is an automated tool that drives clean builds as described above. There are other tools available, but Jenkins is the most popular.
The best way to know if you have everything committed is to run a git status and read the response. However, even with that understanding, it is very easy to forget to push your commit into the origin, and when you do push it, there is also a chance that you merged commits. In short, you might have to just take more care in your process, instead of relying on tools to take care for you.
One can use a git hook to accomplish this; I would use something like a jenkins or hudson to accomplish this, but since you asked about using git, the hook should look like:
# pre-commit
git diff || true
Mark it as executable and you should be golden.
For modified (but not for untracked) files, Maven SCM plugin can help you, specifically scm:check-local-modification
Add this to the plugins section:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-plugin</artifactId>
<version>1.11.2</version>
<executions>
<execution>
<goals>
<goal>check-local-modification</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
</plugin>
Chose the phase carefully to define where you want the build to stop if there are local modifications. The above example would prevent any compilation. If you want to be able to compile the modified code, consider setting the phase to package. That way, you would be able to compile and unit test the modified code, but not to package it to a jar file.

Configuring IntelliJ to Use Groovy Compiler Instead of Java Compiler

In my maven project, I'm currently mixing my Java code with some Groovy code. I'm using Groovy mostly to construct the beans at this point. Some of my Java code uses the Groovy beans directly.
I configured the Maven Compiler Plugin like this:-
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<compilerId>groovy-eclipse-compiler</compilerId>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-compiler</artifactId>
<version>2.8.0-01</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-batch</artifactId>
<version>2.1.5-03</version>
</dependency>
</dependencies>
</plugin>
When I run my testcases using mvn test, it works just fine.
However, when I run the testcases directly from IntelliJ by right clicking the test file and run it, I'm getting "cannot find symbol" errors on the Groovy beans. When I read the error log, IntelliJ uses Java compiler to compile my project before running the test... thus, the tests fail.
I can't seem to figure out how to instruct IntelliJ to always use the Groovy compiler instead of Java compiler.
What should I change under SDK so that Groovy compiler will be used? I tried adding Groovy related JAR files, but I got other errors.
UPDATE 1: Per #Seagull suggestion
I added groovy JARs under "Global Libraries":-
When I executed the test file directly from IntelliJ, I'm getting some Groovy warnings and I still get the same error:-
Thanks.
I had this problem on the latest version of Intellij ideaIC-15.0.3-custom-jdk-bundled.dmg on MAC 10.10.5, JDK 1.8.0_60.
Including all steps for posterity...
From the terminal, I installed the latest version of groovy, using sdkman: sdk install groovy 2.4.5
In Intellij, right-click on top project > select "Add Framework Support..." > Add groovy 2.4.5 (if it hasn't already been added).
In Intellij, "Preferences" > "Build, Execution, Deployment" > "Compiler" > "Resource patterns:" > change the order from !?*.java;!?*.groovy to !?*.groovy;!?*.java
Recompile the project (Command+Shift+F9), it should now compile successfully.
This is the reply from the IntelliJ support team on January 2, 2014 regarding this problem:-
IDEA uses groovyc to generate Java stubs for Groovy classes to allow
for seamless interop. Unfortunately stub generation code doesn't
launch AST transformations (e.g. Immutable) and so the methods
generated by those transformations don't make it into Java stubs,
hence Java compiler doesn't see them.
Unfortunately I see no workarounds that don't require modifying your
project. One would be to place Groovy files into a separate module.
Another would be to change the call places into Groovy. The third one
would be to replace #Immutable with #Canonical and generate the
constructor so that it's actually in the code (and the stubs will
contain it).
You may also vote/watch http://youtrack.jetbrains.com/issue/IDEA-52379
to support Eclipse Groovy compiler.
I ended up removing both #Immutable and #Canonical and create my own constructors, for 2 reasons:-
It allows me to run my test case directly from IntelliJ.
It cleans up JaCoCo code coverage report significantly caused by the unused constructors provided for free by #Immutable and #Canonical.

How can I test a maven archetype that I've just created?

I've created a few archetypes for a project that work fine for now, but I'd like to be able to verify that the code generated from the archetypes continues to work in the future.
What I'd like is a phase of the archetype build that takes the archetype just created, runs mvn archetype:generate on it, and then runs mvn verify on the generated code to verify that the generated code is actually OK. If need be I'll write my own mojo to do this, but wanted to see if a solution already exists. I see the archetype:integration-test goal, but it doesn't seem to be doing what I want.
UPDATE 2013: This is now much easier than the other answers suggest.
https://issues.apache.org/jira/browse/ARCHETYPE-334 was completed in Aug 2011
To use, simply place the word install inside the goal.txt file mentioned above, and the tests from the project you are archetyping will be invoked as part of a normal build. (And/or verify in the case of OP.)
However, if you new to making archetypes be aware that this popular mini-guide is out of date and, while it will work for making an archetype it will not work for having archetype integration tests run. You should instead be creating an archetype-metadata.xml file as described here. (This is much nicer to work with as well, as it uses file sets!)
Also note these integration tests do not respond to -DskipTests but this can be remedied as follows:
<build>
<plugins>
<plugin>
<artifactId>maven-archetype-plugin</artifactId>
<version>2.2</version>
<configuration>
<skip>${skipTests}</skip>
</configuration>
</plugin>
</plugins>
</build>
(Although this looks like it skips the entire plugin, it actually works, probably because it falls back to a legacy mode; whereas I could not find any successful way to skip just the integration-test goal execution using code above.)
beside the the approach of using the maven-invoker-plugin, we are using a different approach. With the help of the Maven Verifier you can test your maven plugins and archetypes easily.
Just add the following dependency into your pom of your maven test project:
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-verifier</artifactId>
<version>1.2</version>
</dependency>
Now you are able to use
org.apache.maven.it.Verifier
into your normal JUnit Tests. With the verifier you can run maven goals and some assertions about the result.
For a complete example just check out the integration test maven modules of our javascript-archetypes:
https://github.com/akquinet/javascript-archetypes
I was struggling a little with this myself, and figured that when using current v2.3 of the maven-archetype-plugin, in addition to a src/test/resources/projects/first/goal.txt, one also needs a src/test/resources/projects/first/archetype.properties containing something like this:
sourceEncoding=UTF-8
groupId=integrationtest.group
artifactId=integrationtest.artifactId
version=1.0.0-SNAPSHOT
package=org.eclipse.xtend.xtend-archetype.integrationtest
packageInPathFormat=org/eclipse/xtend/xtend-archetype/integrationtest
This pull request illustrates a complete working example.
I see the archetype:integration-test goal, but it doesn't seem to be doing what I want.
Unless I misunderstood what you want, the archetype:integration-test goal seems to be a very good solution:
Execute the archetype integration
tests, consisting of a creation of a
project from the current archetype
with defined properties and optional
comparison with reference copy. An IT
consists of a directory in
src/test/resources/projects
containing:
goal.txt (content actually not used, but future version should interpret it
as a goal to run against the generated
project: see ARCHETYPE-334),
archetype.properties with properties for project generation,
optional reference/ directory containing a reference copy of the
expected project created from the IT.
According to the above description, this goals allows precisely to run Integration Test(s) to check a project generated with the current archetype against an expected result and this looks like a clean, simple, self contained way to test an archetype.
Why is this approach not satisfying? What did I miss?
I guess that would be a scenario for a continuous integration server like hudson.
You'd define a job that
empties a directory (shell script)
creates a new project based on the archetype (mvn archetype:generate)
runs the project (mvn package)
While this could probably somehow be fit into one maven lifecycle, it would feel like an awful mess. Use CI instead.

Moving to Maven from GNUMake

I've been a long time user of the Make build system, but I have decided to begin learning the Maven build system. While I've read through most of the online docs, none seem to give me the analogies I'm looking for. I understand the system's lifecycle, but I have not see one reference to compile step dependencies. For example, I want to generate a JFlex grammar as part of the compile lifecycle step. Currently, I see no way of making that step a pre-compile phase step. Documentation seems to be limited on this. In general, the concept of step dependencies seem to be baked into Maven and require a plugin for any alteration. Is this the case? What am I missing, because currently the Maven build system seems very limited in how you can setup compilation steps.
You can do anything in Maven. It generally has a default way to do each thing, and then you can hook in and override if you want to do something special. Sometimes it takes a lot of Stack Overflowing and head scratching to figure it out.
There is even an official JFlex Maven plugin.
Whenever possible, find someone who has made a Maven plugin do what you want. Even if it isn't 100% right, it may at least give you an idea on how to make maven do something.
Minimal configuration
This configuration generates java code of a parser for all grammar files (.jflex , *.jlex , *.lex , .flex ) found in src/main/jflex/ and its sub-directories. The name and package of the generated Java source code are the ones defined in the grammar. The generated Java source code is placed in target/generated-source/jflex , in sub-directories following the Java convention on package names.
pom.xml
<project>
<!-- ... -->
<build>
<plugins>
<plugin>
<groupId>de.jflex</groupId>
<artifactId>jflex-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<!-- ... -->
</build>
<!-- ... -->
</project>
This feels like the maven way to do things. Put your stuff in the right folders (src/main/flex), and this plugin will automatically build it into your project. If you want to do fancier custom stuff, there are some options. but Maven is all about favoring convention over configuration.
To be frank I think that your current mindset maps much better to ant than to maven, and I would suggest starting with that.

Categories