ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Tomas Zezula <tomas.zez...@oracle.com>
Subject JUnitTask + JDK9 question
Date Fri, 01 Apr 2016 12:41:11 GMT
Hi All!

In the JDK 9 module environment running unit tests is more complex task than it was in the
classpath mode.
The problems of test compilation and execution are nicely described in the following thread
http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-March/thread.html#6587 on the jigsaw-dev
mailing list. Also there is lots of different test scenarios as described in
http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-March/007152.html.

Basically there are two problems:
The first problem is that modules enforce module boundaries, only exported packages are seen
from other modules.
The second problem is the module readability - dependency among modules.


 The tests can be executed in the following ways:

1st) In classpath mode - the current way JunitTask executes tests
All the libraries, project artifacts, junit and test classes are on classpath. In this scenario
the classpath artifacts become a part of the unnamed module. There is no problem with module
boundaries or readability as all artifacts are a part of a single module (unnamed module).
However the tests do not run in the same environment as the product which executes the project
in its own module. Also services registered in the module-infos are not available in the ServiceLoader.
This is probably not acceptable.

2nd) Blackbox testing.
The tests have its own module, in other words there is a module-info in the test sources in
addition to module-info in sources. All the libraries, project artifact, test classes and
junit are on modulepath. The test’s module-info requires the project module (sources) and
junit end exports all test packages to make them accessible by junit. The limitation is that
in such a setup only classes exported by the project module can be tested (unless -XaddExports:sourceModule/sourcePackage=testModule
is passed to the JVM). The -addmods:testModule JVM option is needed to make testModule active
and readable by junit. Next limitation is that the test classes cannot be in the same packages
as tested sources because split packages are not supported by the module system.
The module readability graph: http://wiki.netbeans.org/wiki/images/a/a9/Blackbox_module_path.png

The complete java command line is:
java -mp build/test/classes:build/classes/:lib/lib.jar:lib/junit.jar  -addmods:testModule
 -m junit/org.junit.runner.JUnitCore app.AppTest

3rd) Whitebox testing - probably most common
The tests are inlined into the source module.
All the libraries, project artifact, test classes and junit are on modulepath (there is an
option to keep junit on classpath which I will
explain later). As the test classes are in the same module as project sources there is no
problem with module boundaries and readability among project sources and tests. The test packages
need to be exported to be accessible by junit by -XaddExports:sourceModule/testPackage=junit
and made readable by JUnit -XaddReads:sourceModule=junit -addmods sourceModule.
The module readability graph: http://wiki.netbeans.org/wiki/images/c/ca/Whitebox_module_path.png

The complete java command line is:
java -mp build/classes/:lib/lib.jar:lib/junit.jar -Xpatch:sourceModule=build/test/classes
-addmods sourceModule -XaddExports:sourceModule/testPackage=junit -XaddReads:sourceModule=junit
-m junit/org.junit.runner.JUnitCore app.AppTest


There is also a possibility to keep the junit.jar on the classpath rather than on the modulepath.
In this case junit becomes a part of an unnamed module, when on modulepath it becomes an automatic
module. The same JVM options are required, only the -XaddReads:sourceModule=junit changes
to -XaddReads:sourceModule=ALL-UNNAMED. The disadvantage of this solution is that unit test
can read the unnamed module which contains junit but may contain other unwanted jar files
on classpath. The only advantage of these solution is that it does not need module execution
(-m JVM option).
The module readability graph: http://wiki.netbeans.org/wiki/images/3/38/Whitebox_class_path.png

The complete java command line is:
java -mp build/classes/:lib/lib.jar -cp lib/junit.jar -Xpatch:sourceModule=build/test/classes
-addmods sourceModule -XaddExports:sourceModule/testPackage=junit -XaddReads:sourceModule=ALL-UNNAMED
org.junit.runner.JUnitCore app.AppTest



The JUnit task needs to be extended to support all three scenarios.
There are two possibilities how to extend the JUnitTask:

1st) Minimal needed changes
Just add a modulepath to JUnit task. When junit library is not found on the classpath but
found on the module path do the modular execution by -m junit/<mainclz> rather than
classpath execution. The user is responsible for passing the -XPatch, -XaddExports, -XaddReads,
-addmods JVM options. Options like -XaddExports are harder to calculate as they require list
of test packages. But it can be done by the following pathconvert:

<dirset id="packages" dir="build/test/classes" includes="*"/>
<pathconvert refid="packages" property=“exports.cmd” pathsep=" ">
   <chainedmapper>
       <flattenmapper/>
       <globmapper from="*" to="-XaddExports:${module.name}/*=junit"/>
   </chainedmapper>
</pathconvert>


2nd) Extend Junit task to automatically set the -XPatch, -XaddExports, -XaddReads, -addmods
options for modular execution.
This will require adding more attributes to JUnit task (path to test classes to do the -XPatch,
ability to disable the automatic options).

As the 2nd solution is a superset of the 1st one I will start with it.
Any thoughts and comments are welcome
Thanks,
— Tomas
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org


Mime
View raw message