RFE simplify usage of patched module [by Robert Scholte, from jdk-dev]

Christian Stein sormuras at gmail.com
Sat Feb 15 05:34:36 UTC 2020


On Fri, Feb 14, 2020 at 10:31 PM Alex Buckley <alex.buckley at oracle.com>
wrote:

> On 2/14/2020 11:29 AM, Christian Stein wrote:
> >> A different way to address those use cases would be to ship the
> >> logic just described for `--patch-module-descriptor` in a launcher
> >> offered by the test framework itself.
> >
> > That's too late in the build game. You already need this merged
> > descriptor at compile time. And you need the user to define the
> > additional elements (modifiers and directives), as no build tool
> > may infer them always correctly by inspecting the test sources...
>
> Fair point, and thanks for reminding me about your "Testing In The
> Modular World" document.
>
> The thing I'm having trouble with is that javac already lets you specify
> the --add-reads options on org.junit.jupiter.api & friends that are
> needed to compile test code. If Maven expects the user to painfully
> configure the POM to pass --patch-module-descriptor to javac, why can't
> the POM offer an easy way to make Maven itself (in the `test-compile`
> phase?) pass some defined-behind-the-scenes --add-reads options?
>
>
Maven and other build tools would add the `--patch-module-descriptor`
automacially and point to the user-defined "patch module compilation unit"
that only contains the extra directives: like `requires java.sql;`, or
`requires org.testng.core;` or ... `requires org.junit.jupiter;`. Or all of
them.

Those extra directives needed by test modules to compile and run
are a deliberate decision made by the user -- on a per test module basis.
No build tool may infer those decisions correctly.

Similarly, at run time, you propose to always open the main module to
> the same org.junit.platform.commons module -- `module-info.test` is more
>

Not the main module. Only the current test module. Assuming, that you
run tests from a single test module at a time.


> or less the same for every JUnit project -- so why doesn't the POM have
> an easy way to let Maven itself (in the `test` phase?) pass --add-opens
> to java?
>

Opening a module for deep-reflection is just a single aspect of the
"Testing In The Modular World" story. Btw. `open module` or `--add-opens`
is only required iff the test framework of choice reflects into your test
modules. I already have a ServiceProvider-based variation running locally,
that uses this standard technique to pass the execution control to the
main-like entry-point of each test module.


> There are no new modularity "primitives" here (by which I mean features
> of the module system itself, such as open modules) ... there is just
> detailed configuration which, in the testing context, should be done by
> the build tool rather than the user.
>

Except for configuration parts that cannot be inferred. Here the user
has to resort to javac and java command line options, like `--add-reads`,
and must negotiate with the build tool how to pass those options.

And all of this tedious and errorprone textual configuration **after**
having declared a concise, tool-agnostic, well-definend and beautiful
inter-module test module using the official `module-info.java` syntax:

- test.base/test/module-info.java:

open /*test*/ module test.base {
  requires com.greetings; // module under test
  requires org.astro; // module under test
  requires java.sql; // system-provided module needed by test code
  requires org.junit.jupiter; // framework reflecting entry-points
  requires org.assertj.core; // ...and more test-related modules
}

Leaving this compile-able DSL behind **only** for in(tra)-module
(white-box) testing is ... inconvenient and hard to explain. Like
Robert wrote in his initial request to simplify the usage of patch
module.

Assuming `--patch-module-descriptor` was already available, the
org.astro test story would read:

- org.astro/main/module-info.java:

module org.astro {
  exports org.astro;
  requires java.logging;
}

- org.astro/test/module-info.java:

open /*test*/ module org.astro /*extends main module org.astro*/ {
  requires java.sql; // system-provided module needed by test code
  requires org.junit.jupiter; // framework reflecting entry-points
  requires org.assertj.core; // ...and more test-related modules
}

A build tool now easily may detect that `--patch-module-descriptor`
is required at test compile and run time. It could infer it from the
same module name or simply by seeing a main and a test
`module-info.java` compilation unit within the sources of the
org.astro Maven-/Gradle-/pro-/Bach-/any-build-tool-"module".

Build tools could pass the following argument to javac/java
while being in their test-scope tasks. Of course, implying that
org.astro/test/module-info.java is the current "primary" module
descriptor:

--patch-module-descriptor org.astro=org.astro/main/module-info.java

That's it.

The primary test-relevant modular directives are enriched by
those of the main module as declared in org.astro/main/module-info.java
resulting effectively in a synthetic in-module test module descriptor that
resembles the inter-module test descriptor presented above:

- SYNTHETIC test module for org.astro

open /*test*/ module org.astro /*extends main module org.astro*/ {
  requires java.sql; // system-provided module needed by test code
  requires org.junit.jupiter; // framework reflecting entry-points
  requires org.assertj.core; // ...and more test-related modules
  //
  exports org.astro; // patched from org.astro/main/module-info.java
  requires java.logging; // patched from org.astro/main/module-info.java
}

Cheers,
Christian


More information about the jigsaw-dev mailing list