I'm new to Ant and wrote up a simple build.xml with some help yesterday. However after looking at the output from running ant -verbose it appears as if a class I have to handle many JUnit tests isn't being called appropriately.
<project name="JUnit_tests" default="run" basedir=".">
<!-- Define variable properties -->
<property name="src" value="${basedir}"/>
<property name="junit" value="org.junit.runner.JUnitCore"/>
<!--<property name="junit" value="org.junit.runner.JUnitCore"/>-->
<!-- Appends all jars in the current directory to the classpath -->
<path id="compile.classpath">
<fileset dir="./">
<include name="*.jar"/>
</fileset>
</path>
<!-- Compiles all code in the current directory and append to the classpath -->
<target name="compile">
<javac destdir="${src}" srcdir="${src}">
<classpath refid="compile.classpath"/>
</javac>
</target>
<!-- Runs the Test code with junit argument as long as compile was run previously -->
<target name="run" depends="compile">
<java classname="Tests" fork="true">
<arg value="${junit}"/>
</java>
</target>
My JUnit tests are in the Tests class, and I need to run the class with
java org.junit.runner.JUnitCore Tests
However based on the following output I believe it's being called as
java Tests org.junit.runner.JUnitCore
Ant -verbose output:
run:
[java] Executing '/usr/lib/jvm/java-6-sun-1.6.0.26/jre/bin/java' with arguments:
[java] 'Tests'
[java] 'org.junit.runner.JUnitCore'
[java]
[java] The ' characters around the executable and arguments are
[java] not part of the command.
[java] Exception in thread "main" java.lang.NoSuchMethodError: main
[java] Java Result: 1
Any ideas? I've been doing research but couldn't find much about the order of arguments, specifically with a java call. Thanks!
You have interverted your argument (which is Tests) and the main class which is org.junit.runner.JUnitCore.
<arg> are the arguments of the program
<jvmarg> are the arguments of the JVM
In between the two of them, you will have the main class.
Java usage:
Usage: java [-options] class [args...]
In your case, you want to execute the main method of org.junit.runner.JUnitCore and the arguments passed to that main method should be Tests
Related
We use non-java tests. Each one of them executes our tool which is written in Java.
I'm trying to use Eclemma for creating the coverage report of the tests.
Lets start with one test. We compile the code with build.xml. I would like somehow to create a coverage report for each test and then to merge them into one main report.
I found out that Jacoco has CMD interface I could use in order to merge those reports. But I don't understand how do I run the tool with coverage package?
Which coverage package should I use? Is it Eclemma or Jacoco?
How do I run the tool with the coverage package? Should I add it into the build.xml file? Should I add it to the command line?
I'm a bit confused about the whole idea of coverage in Java. In dynamic langues such as Python and Perl, I just execute the code with the coverage module, which creates the coverage report.
The command we use to execute out tool:
gandu -vm /usr/pkgs/java/1.6.0.25-64/bin/java -configuration /.ganduData -data /.ganduData -configuration /ganduInternalConfig --session_id 1582722179
Should I add some options?
The build in build.xml:
<target name="pde-build" depends="clean, init">
<java classname="org.eclipse.equinox.launcher.Main" fork="true" failonerror="true">
<arg value="-application" />
<arg value="org.eclipse.ant.core.antRunner" />
<arg value="-buildfile" />
<arg value="${eclipseLocation}/plugins/org.eclipse.pde.build_${pdeBuildPluginVersion}/scripts/productBuild/productBuild.xml" />
<arg value="-Dtimestamp=${timestamp}" />
<classpath>
<pathelement location="${eclipseLocation}/plugins/org.eclipse.equinox.launcher_${equinoxLauncherPluginVersion}.jar" />
</classpath>
</java>
</target>
Should I add the following command?
<arg value="-autVMArgs" />
<arg value="-Xmx800m;-XX:MaxPermSize=600M;-javaagent:${jacoco-agent-path}=destfile=${jacoco-report},append=true"/>
Update: Thanks to the two answer I have managed to create the report using the CLI. But it looks like it shows (almost) zero coverage. It shows red (uncovered) on printed lines that I see that have been executed (they were printed to the stdout).
The project contains a lot of packages but for first try I'm trying to create coverage report for a specific package. I ran:
gandu -vm /usr/pkgs/java/1.6.0.25-64/bin/java -configuration /.ganduData -data /.ganduData --session_id 1583967465 -vmargs -Xmx256m -Xms128m -javaagent:/jacoco_coverage/jacoco-0.8.5/lib/jacocoagent.jar
and then I ran:
/usr/pkgs/java/1.6.0.16-64/bin/java -jar /jacoco_coverage/jacoco-0.8.5/lib/jacococli.jar report jacoco.exec --classfiles /gandu_repo/com.core.gandu/bin/ --html temp_dir --sourcefiles /gandu_repo/com.core.gandu/src/
The output:
[WARN] Some classes do not match with execution data.
[WARN] For report generation the same class files must be used as at runtime.
[WARN] Execution data for class <PATH> does not match.
[INFO] Analyzing 8 classes.
I have trouble understanding how classfiles and sourcefiles. The file that I'm trying to get coverage on is Application. In the bin I have in some inner folder Application.class and in src I have in some inner folder Application.java. I even tried to add full path for the those files in classfiles and sourcefiles but still don't have coverage (all red). What could be the problem?
The structure of the tool:
The root contains alot of packages and each one has folder bin and src. Each src contains folders recursively with Java files. The bin has the same structure for class files.
As I know, the only place to add java agent is in the configuration of the unit tests.
Agent should be added to the JVM that executes application under test. Your confusion probably comes from the fact that usually unit tests are executed in the same JVM as code under test.
From your description unclear how JVM with the application is started.
However consider following src/Main.java as an example:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws Exception {
String input;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
input = reader.readLine();
}
if ("hello".equals(input)) {
System.out.println("Hello, World!");
}
}
}
after compilation
javac -d classes src/Main.java
This application can be executed in JVM with JaCoCo Java Agent taken from JaCoCo zip distribution as following
java -javaagent:jacoco/lib/jacocoagent.jar -cp classes Main
Then tests are executed - e.g. in this case manual input of "hello".
After graceful termination of JVM, you'll get jacoco.exec file.
By passing this jacoco.exec, source and class files to the JaCoCo Command Line Interface you can create HTML report:
java -jar jacoco/lib/jacococli.jar report jacoco.exec --classfiles classes --sourcefiles src --html report
Which coverage package should I use? Is it Eclemma or Jacoco?
EclEmma is a plugin for Eclipse IDE based on JaCoCo.
If for testing you execute your application from Eclipse IDE then you can start it with JaCoCo using EclEmma. Here is the same example executed in Eclipse IDE:
However this is not suitable for other scenarios such as Ant builds.
How do I run the tool with the coverage package? Should I add it into the build.xml file? Should I add it to the command line?
This depends on how you execute your application - if for tests your application is executed by Ant, then you can use JaCoCo Ant Tasks for configuration of agent and generation of report. As an example here is build.xml for Ant that produces the same report for src/Example.java as the above commands:
<project xmlns:jacoco="antlib:org.jacoco.ant" name="Example Ant Build with JaCoCo" default="rebuild">
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
<classpath path="jacoco/lib/jacocoant.jar"/>
</taskdef>
<target name="clean">
<delete dir="classes"/>
<delete dir="report"/>
<delete file="jacoco.exec"/>
</target>
<target name="compile">
<mkdir dir="classes"/>
<javac srcdir="src" destdir="classes" debug="true" includeantruntime="false"/>
</target>
<target name="run" depends="compile">
<jacoco:agent property="jacocoAgent" />
<java classname="Main" fork="true">
<classpath path="classes"/>
<jvmarg value="${jacocoAgent}"/>
</java>
</target>
<target name="report" depends="run">
<jacoco:report>
<executiondata>
<file file="jacoco.exec"/>
</executiondata>
<structure name="JaCoCo Ant Example">
<classfiles>
<fileset dir="classes"/>
</classfiles>
<sourcefiles encoding="UTF-8">
<fileset dir="src"/>
</sourcefiles>
</structure>
<html destdir="report"/>
</jacoco:report>
</target>
<target name="rebuild" depends="clean,report"/>
</project>
If application is executed by some custom homemade tool, then maybe be better to add the agent to the command line directly.
I'm trying to use Daikon to test a large project so I needed ant to compile and run everything for me. Since I'm new to ant I'm trying to get familiar with it through a simple example given to Daikon. So, the best candidate example is the associated StackAr package with Daikon.
To run Daikon normally I will execute the following command after compiling all the java files I'm targeting.
java daikon.Chicory --daikon DataStructures.StackArTester
which is equivalent to this command
java -cp "/usr/lib/daikonparent/daikon-5.2.20/daikon.jar:." daikon.Chicory --daikon DataStructures.StackArTester
Both commands will run daikon.jar using Chicory interface with the flag --daikon and will take the StackArTester.class to instrument it and run it.
Now, my attempt to run the same command using ant looks as the following:
<project name="StackAr" default="compile" basedir=".">
<description>
simple example build file
</description>
<!-- set global properties for this build -->
<property name="src" location="DataStructures"/>
<property name="build" location="DataStructures"/>
<target name="init">
<!-- Create the time stamp -->
<tstamp/>
</target>
<target name="compile" depends="init"
description="compile the source">
<!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}"
destdir="."
debug="on"
/>
</target>
<target name="run" description="run StackArTester">
<java classname="DataStructures.StackArTester">
<classpath>
<pathelement location="."/>
</classpath>
</java>
</target>
<target name="inv" description="run daikon">
<java classname="daikon.Chicory" >
<arg value="--daikon" />
<arg value="DataStructures.StackArTester"/>
<classpath>
<pathelement path="/usr/lib/daikonparent/daikon-5.2.20/daikon.jar"/>
</classpath>
</java>
</target>
<target name="clean"
description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
</target>
</project>
The target compile is used to compile all the source files and is working. Also, the target run is used as a test to run the targeted .class file and is working. The target inv is where I'm having trouble and it's suppose to be equivalent to the two command above.
My issue is that I'm not sure how I'm suppose to pass the .calss file to Daikon. From the results I have seen I'm positive that first argument/flag --daikon is recognized. However, for the second argument DataStructures.StackArTester in most of my tires I see that it's recognized, but Daikon has an issue with its classpath. Runing the script above ant inv will generate the following error message:
Buildfile: /usr/lib/daikonparent/daikon-5.2.20/examples/java-examples/StackAr/build.xml
inv:
[java]
[java] Executing target program: java -cp /usr/share/ant/lib/ant-launcher.jar:/usr/lib/daikonparent/daikon-5.2.20/daikon.jar:/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar:/usr/lib/jvm/java-7-openjdk-amd64/lib/tools.jar:/usr/share/ant/lib/ant-testutil.jar:/usr/share/ant/lib/ant-apache-log4j.jar:/usr/share/ant/lib/ant-javamail.jar:/usr/share/ant/lib/ant-jsch.jar:/usr/share/ant/lib/ant-apache-regexp.jar:/usr/share/ant/lib/ant-antlr.jar:/usr/share/ant/lib/ant-swing.jar:/usr/share/ant/lib/ant-apache-oro.jar:/usr/share/ant/lib/ant-apache-bcel.jar:/usr/share/ant/lib/ant-apache-xalan2.jar:/usr/share/ant/lib/ant-junit.jar:/usr/share/ant/lib/ant-launcher.jar:/usr/share/ant/lib/ant-apache-bsf.jar:/usr/share/ant/lib/ant-jdepend.jar:/usr/share/ant/lib/ant-apache-resolver.jar:/usr/share/ant/lib/ant-jmf.jar:/usr/share/ant/lib/ant-commons-logging.jar:/usr/share/ant/lib/ant-commons-net.jar:/usr/share/ant/lib/ant-junit4.jar:/usr/share/ant/lib/ant.jar:/usr/lib/jvm/java-7-openjdk-amd64/lib/tools.jar -ea -Xmx1000m -javaagent:/usr/lib/daikonparent/daikon-5.2.20/java/ChicoryPremain.jar=--daikon --dtrace-file=StackArTester.dtrace.gz DataStructures.StackArTester
[java] entered daikon.chicory.Runtime.setDtrace(./StackArTester.dtrace.gz, false)...
[java] Error: Could not find or load main class DataStructures.StackArTester
[java] Chicory warning: No methods were instrumented.
[java] Warning: Did not run Daikon because target exited with 1 status
[java] Java Result: 1
BUILD SUCCESSFUL
Total time: 0 seconds
Note that the error is
Error: Could not find or load main class DataStructures.StackArTester
I'm out of ideas about what I might try. Hopefully the information above is enough. Please note that I'm in the same directory when executing the original commands and the ant command.
Thakns ...
The error
[java] Error: Could not find or load main class DataStructures.StackArTester
means that Java did not find the class DataStructures.StackArTester on your classpath.
On the line that starts with [java] Executing target program, the -cp command-line argument is your classpath. The classpath must contain a directory or jar file containing DataStructures/StackArTester.class. You just need to augment the classpath.
I am creating a java agent that will be used to to do some bytecode modification to some classes org.eclipse.jdt.core.JDTCompilerAdapter is one of them. I am using javassit to modify some the execute() method of org.eclipse.jdt.core.JDTCompilerAdapter. So I have included ecj as in my agent project (using gradle)
compile group: 'org.eclipse.jdt.core.compiler' ,name: 'ecj', version :'4.3.1'
As I need to use some classes from ecj.
The goal of the agent is to intercept the calls to execute method, modify the execute method to add some calls to some of my classes in the aim of triggering some processing.
I am testing the agent against a Simple java project with 2 classes. the project is builded with ant and uses JDTCompilerAdapter as a compiler.
Here is the build.xml file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="build" name="TestProject">
<property file="build.properties" />
<property name="debuglevel" value="source,lines,vars"/>
<property name="target" value="1.7"/>
<property name="source" value="1.7"/>
<path id="PClasspath">
<pathelement location="bin"/>
</path>
<target name="init">
<mkdir dir="bin"/>
<copy includeemptydirs="false" todir="bin">
<fileset dir="src">
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
<target name="clean">
<delete dir="bin"/>
</target>
<target depends="clean" name="cleanall"/>
<target depends="init" name="build">
<javac debug="true" debuglevel="${debuglevel}" destdir="bin" includeantruntime="false" source="${source}" target="${target}">
<src path="src"/>
<classpath refid="PClasspath"/>
</javac>
</target>
<!--
<target description="copy Eclipse compiler jars to ant lib directory" name="init-eclipse-compiler">
<copy todir="${ant.library.dir}">
<fileset dir="${ECLIPSE_JDT_CORE}" includes="*.jar"/>
</copy>
</target>-->
<target name="build-e" >
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
<antcall target="build"/>
</target>
The agent is to be used when building a project.
So for testing the agent I use this command:
java -jar agent-wrapper.jar --outdir ./out --exec ./build_wrapper.sh
build_wrapper.sh contains this (I have added ecj dependency so I could compile the project with JDTCompilerAdapter as I have in bulid.xml <property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/> :
../ant/bin/ant -lib ../eclipse/plugins/ecj-4.3.1.jar build-e
The idea is that the agent-wrapper will parse the argument (outdir is used to generate some stuff and exec is a script used to launch a the build of my test project) get the command to be executed from build_wrapper.sh (in this case ../ant/bin/ant -lib ../eclipse/plugins/ecj-4.3.1.jar build-e) and add it self as java agent to the command.
The problem occurs during the execution of the agent. Here is the output:
java -jar custom-agent.jar --outdir ./out --exec ./build_wrapper.sh [10:18:53]
Picked up JAVA_TOOL_OPTIONS: -javaagent:/Users/dev/TestAgent/project/custom-agent.jar=OUTDIR=/Users/dev/TestAgent/project/./out
objc[30474]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/bin/java and /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.
Buildfile: /Users/dev/TestAgent/project/build.xml
build-e:
init:
[mkdir] Created dir: /Users/dev/TestAgent/project/bin
build:
BUILD FAILED
/Users/dev/TestAgent/project/build.xml:47: The following error occurred while executing this line:
/Users/dev/TestAgent/project/build.xml:32: Class org.eclipse.jdt.core.JDTCompilerAdapter could not be loaded because of an invalid dependency.
Total time: 2 seconds
abnormal termination, exit code: 1
When I don't use ecj-4.3.1.jar inside my agent project, the build runs well I intercept the call to execute() method but I can't use the other classes from ecj jar.
The show stopper error is "Class org.eclipse.jdt.core.JDTCompilerAdapter could not be loaded because of an invalid dependency."
First hint at the fault might be found from reading this link
http://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-ant_javac_adapter.htm
The second hint might be that one of the jars required for running the JDTCompilerAdapter is missing.
To get the JDTCompilerAdapter to work I copied both the JDTCompilerAdapter.jar and org.eclipse.jdt.core.jar into the ant/lib folder.
There are differences based on version of eclipse and the version of java which are documented in the link mentioned above.
This question already has answers here:
Problem running a Jar file
(2 answers)
Closed 5 years ago.
I've currently got an eclipse project with two main methods and was wondering if it's possible to create a jar file which runs an Apache Ant script when the jar file is executed. I've provided an Ant script below where two main methods are run. Thanks in advance.
<?xml version="1.0"?>
<project name="Test" default="run_external">
<target name="compile">
<delete dir="bin" />
<mkdir dir="bin" />
<javac srcdir="src" destdir="bin" />
</target>
<target name="run_external" depends="compile">
<parallel>
<exec executable="cmd" dir="bin">
<arg value="/c start cmd.exe /k java test.Main" />
</exec>
<exec executable="cmd" dir="bin">
<arg value="/c start cmd.exe /k java test.Main2" />
</exec>
</parallel>
</target>
</project>
Why would you need Ant? From the comment I deduce that you want your Java program to launch another one. If so, simply use:
Runtime.getRuntime().exec("java -jar otherprogram.jar");
or whatever the command line is. Please note that there are more advanced versions of Runtime.getRuntime().exec(), so have a look at the javadoc.
EDIT: from Runtime.getRuntime().exec() docs:
Executes the specified string command in a separate process.
So you are spawning another indipendent JVM.
Don't use directly java ..., instead compose the command using environment variables: this is only for demostrating the function.
Anyway, if you need to do this at startup, I suggest you use a shell script launching the three programs.
Create a jar using ant
<target name="jar" depends="compile">
<mkdir dir="${jar.dir}"/>
<jar destfile="${jar.dir}/helloworld.jar" basedir="${classes.dir}"/>
</target>
When you include multiple main classes in one jar file, then each must be invoked using the -cp flag and with the fully qualified name of the main class specified.
java -cp helloworld.jar com.test.Main1 && java -cp helloworld.jar com.test.Main2
This will give you an output (I just printed the class names)
I am main 1
I am main 2
Alternatively
Based on your requirement you can create single entry point ( I will prefer this), I mean a single class with main method and then call the other main methods from this class
example
create a class
public class Main {
public static void main(String[] args) {
Main1.main(args);
Main2.main(args);
}
}
Include this main class in Manifest.MF
<target name="jar" depends="compile">
<mkdir dir="${jar.dir}"/>
<jar destfile="${jar.dir}/helloworld.jar" basedir="${classes.dir}">
<manifest>
<attribute name="Main-Class" value="com.test.Main"/>
</manifest>
</jar>
</target>
And execute
java -jar helloworld.jar
Output of this
I am main 1
I am main 2
My program getting command line arguments. How can I pass it when I use Ant?
Extending Richard Cook's answer.
Here's the ant task to run any program (including, but not limited to Java programs):
<target name="run">
<exec executable="name-of-executable">
<arg value="${arg0}"/>
<arg value="${arg1}"/>
</exec>
</target>
Here's the task to run a Java program from a .jar file:
<target name="run-java">
<java jar="path for jar">
<arg value="${arg0}"/>
<arg value="${arg1}"/>
</java>
</target>
You can invoke either from the command line like this:
ant -Darg0=Hello -Darg1=World run
Make sure to use the -Darg syntax; if you ran this:
ant run arg0 arg1
then ant would try to run targets arg0 and arg1.
If you do not want to handle separate properties for each possible argument, I suggest you'd use:
<arg line="${args}"/>
You can check if the property is not set using a specific target with an unless attribute and inside do:
<input message="Type the desired command line arguments:" addProperty="args"/>
Putting it all together gives:
<target name="run" depends="compile, input-runargs" description="run the project">
<!-- You can use exec here, depending on your needs -->
<java classname="Main">
<arg line="${args}"/>
</java>
</target>
<target name="input-runargs" unless="args" description="prompts for command line arguments if necessary">
<input addProperty="args" message="Type the desired command line arguments:"/>
</target>
You can use it as follows:
ant
ant run
ant run -Dargs='--help'
The first two commands will prompt for the command-line arguments, whereas the latter won't.
The only effective mechanism for passing parameters into a build is to use Java properties:
ant -Done=1 -Dtwo=2
The following example demonstrates how you can check and ensure the expected parameters have been passed into the script
<project name="check" default="build">
<condition property="params.set">
<and>
<isset property="one"/>
<isset property="two"/>
</and>
</condition>
<target name="check">
<fail unless="params.set">
Must specify the parameters: one, two
</fail>
</target>
<target name="build" depends="check">
<echo>
one = ${one}
two = ${two}
</echo>
</target>
</project>
Can you be a bit more specific about what you're trying to do and how you're trying to do it?
If you're attempting to invoke the program using the <exec> task you might do the following:
<exec executable="name-of-executable">
<arg value="arg0"/>
<arg value="arg1"/>
</exec>
What I did in the end is make a batch file to extract the CLASSPATH from the ant file, then run java directly using this:
In my build.xml:
<target name="printclasspath">
<pathconvert property="classpathProp" refid="project.class.path"/>
<echo>${classpathProp}</echo>
</target>
In another script called 'run.sh':
export CLASSPATH=$(ant -q printclasspath | grep echo | cut -d \ -f 7):build
java "$#"
It's no longer cross-platform, but at least it's relatively easy to use, and one could provide a .bat file that does the same as the run.sh. It's a very short batch script. It's not like migrating the entire build to platform-specific batch files.
I think it's a shame there's not some option in ant whereby you could do something like:
ant -- arg1 arg2 arg3
mpirun uses this type of syntax; ssh also can use this syntax I think.