You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2020/05/30 12:59:23 UTC

[maven-surefire] branch SUREFIRE-1733 updated (3c96766 -> 070bcd7)

This is an automated email from the ASF dual-hosted git repository.

tibordigana pushed a change to branch SUREFIRE-1733
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git.


 discard 3c96766  documentation
 discard c8eeeff  ITs for the TestNG, JUnit4 and JUnit5
 discard 95a9b2f  not using "--add-modules ALL-MODULE-PATH" using "--add-modules" with test module name
 discard 5c69506  little details
 discard a9ba0ed  more reliable test on Jenkins
 discard 42457e1  unit tests for all ProviderInfo
 discard 8dea82b  JPMS arguments should go to the arg file
 discard a0b2acb  [GH] Workflows j14
 discard d60b0db  IT failed on j7 and j8 because requires j9+
 discard 980d58a  adjusted Surefire1712ExtractedModulenameWithoutASMIT
 discard 265d7cf  [SUREFIRE-1733] Surefire and Failsafe JPMS additions for JUnit 5.x execution
     new 8c8756c  [SUREFIRE-1733] Surefire and Failsafe JPMS additions for JUnit 5.x execution
     new 070bcd7  [GH] Workflows j14

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (3c96766)
            \
             N -- N -- N   refs/heads/SUREFIRE-1733 (070bcd7)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:


[maven-surefire] 01/02: [SUREFIRE-1733] Surefire and Failsafe JPMS additions for JUnit 5.x execution

Posted by ti...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

tibordigana pushed a commit to branch SUREFIRE-1733
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git

commit 8c8756c20294d131733117bb9b991fb647dbc7b9
Author: tibordigana <ti...@apache.org>
AuthorDate: Wed May 6 01:31:12 2020 +0200

    [SUREFIRE-1733] Surefire and Failsafe JPMS additions for JUnit 5.x execution
---
 .../plugin/surefire/AbstractSurefireMojo.java      | 172 +++++++++++----
 .../apache/maven/plugin/surefire/ProviderInfo.java |   4 +
 ...ProviderInfo.java => ProviderRequirements.java} |  40 ++--
 .../booterclient/DefaultForkConfiguration.java     |   2 +-
 .../ModularClasspathForkConfiguration.java         |  70 ++++--
 .../AbstractSurefireMojoJava7PlusTest.java         | 243 ++++++++++++++++++++-
 .../plugin/surefire/AbstractSurefireMojoTest.java  |  24 +-
 ...ooterDeserializerProviderConfigurationTest.java |   3 +-
 ...BooterDeserializerStartupConfigurationTest.java |   6 +-
 .../booterclient/DefaultForkConfigurationTest.java |   7 +-
 .../booterclient/ForkConfigurationTest.java        | 187 +++++++++++++++-
 .../ModularClasspathForkConfigurationTest.java     |   8 +-
 .../src/site/apt/examples/jpms.apt.vm              | 205 +++++++++++++++++
 maven-surefire-plugin/src/site/site.xml            |   1 +
 .../maven/surefire/booter/ModularClasspath.java    |  18 +-
 .../surefire/booter/StartupConfiguration.java      |  15 +-
 .../surefire/its/MultiModuleProjectWithJPMSIT.java |  70 ++++++
 .../its/jiras/Surefire1570ModularFailsafeIT.java   |  14 +-
 ...larFailsafeIT.java => Surefire1733JUnitIT.java} |  39 ++--
 ...arFailsafeIT.java => Surefire1733TestngIT.java} |  39 ++--
 .../com.foo.api/pom.xml                            |  51 +++++
 .../src/main/java/com/foo/api/SomeInterface.java}  |  11 +-
 .../com.foo.api/src/main}/java/module-info.java    |  11 +-
 .../com.foo.impl/pom.xml                           |  85 +++++++
 .../src/main/java/com/foo/impl/Bar.java            |  51 +++++
 .../com.foo.impl/src/main}/java/module-info.java   |   9 +-
 .../src/test/java/com/foo/implt/BarIT.java         |  31 +--
 .../src/test/java/com/foo/implt/BarTest.java       |  31 +--
 .../com.foo.impl}/src/test/java/module-info.java   |  11 +-
 .../maven-multimodule-project-with-jpms/pom.xml    | 101 +++++++++
 .../src/test/java/module-info.java                 |   4 +-
 .../test/resources/surefire-1733-junit4/pom.xml    | 102 +++++++++
 .../src/main/java/main/Service.java}               |  10 +-
 .../src/main}/java/module-info.java                |   9 +-
 .../src/test/java/module-info.java                 |  12 +-
 .../src/test/java/test/MyIT.java                   |  33 +--
 .../src/test/java/test/MyTest.java                 |  33 +--
 .../test/resources/surefire-1733-testng/pom.xml    | 102 +++++++++
 .../src/main/java/main/Service.java}               |  10 +-
 .../src/main}/java/module-info.java                |   9 +-
 .../src/test/java/module-info.java                 |  13 +-
 .../src/test/java/test/MyIT.java                   |  33 +--
 .../src/test/java/test/MyTest.java                 |  34 +--
 43 files changed, 1666 insertions(+), 297 deletions(-)

diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
index 8ab5d64..38d34fb 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
@@ -90,6 +90,7 @@ import org.apache.maven.toolchain.DefaultToolchain;
 import org.apache.maven.toolchain.Toolchain;
 import org.apache.maven.toolchain.ToolchainManager;
 import org.apache.maven.toolchain.java.DefaultJavaToolChain;
+import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor;
 import org.codehaus.plexus.languages.java.jpms.ResolvePathRequest;
 import org.codehaus.plexus.languages.java.jpms.ResolvePathResult;
 import org.codehaus.plexus.logging.Logger;
@@ -124,8 +125,10 @@ import static java.lang.Integer.parseInt;
 import static java.lang.Thread.currentThread;
 import static java.util.Arrays.asList;
 import static java.util.Collections.addAll;
+import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonList;
 import static java.util.Collections.singletonMap;
+import static org.apache.maven.surefire.booter.Classpath.emptyClasspath;
 import static org.apache.maven.surefire.shared.lang3.StringUtils.substringBeforeLast;
 import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_WINDOWS;
 import static org.apache.maven.plugin.surefire.SurefireDependencyResolver.isWithinVersionSpec;
@@ -1388,27 +1391,32 @@ public abstract class AbstractSurefireMojo
 
     private ResolvePathResultWrapper findModuleDescriptor( File jdkHome )
     {
-        File mainBuildPath = getMainBuildPath();
+        ResolvePathResultWrapper test = findModuleDescriptor( jdkHome, getTestClassesDirectory(), false );
+        return test.getResolvePathResult() == null ? findModuleDescriptor( jdkHome, getMainBuildPath(), true ) : test;
+    }
 
-        if ( mainBuildPath.isDirectory() && !new File( mainBuildPath, "module-info.class" ).exists() )
+    private ResolvePathResultWrapper findModuleDescriptor( File jdkHome, File buildPath, boolean isMainDescriptor )
+    {
+        if ( buildPath.isDirectory() && !new File( buildPath, "module-info.class" ).exists() )
         {
-            return new ResolvePathResultWrapper( null, true );
+            return new ResolvePathResultWrapper( null, isMainDescriptor );
         }
 
         try
         {
-            ResolvePathRequest<?> request = ResolvePathRequest.ofFile( mainBuildPath ).setJdkHome( jdkHome );
+            ResolvePathRequest<?> request = ResolvePathRequest.ofFile( buildPath ).setJdkHome( jdkHome );
             ResolvePathResult result = getLocationManager().resolvePath( request );
-            return new ResolvePathResultWrapper( result.getModuleNameSource() == null ? null : result, true );
+            boolean isEmpty = result.getModuleNameSource() == null;
+            return new ResolvePathResultWrapper( isEmpty ? null : result, isMainDescriptor );
         }
         catch ( Exception e )
         {
-            return new ResolvePathResultWrapper( null, true );
+            return new ResolvePathResultWrapper( null, isMainDescriptor );
         }
     }
 
-    private boolean canExecuteProviderWithModularPath( Platform platform,
-                                                       ResolvePathResultWrapper resolvedJavaModularityResult )
+    private boolean canExecuteProviderWithModularPath( @Nonnull Platform platform,
+                                                       @Nonnull ResolvePathResultWrapper resolvedJavaModularityResult )
     {
         return useModulePath()
                 && platform.getJdkExecAttributesForTests().isJava9AtLeast()
@@ -1875,18 +1883,15 @@ public abstract class AbstractSurefireMojo
     {
         try
         {
-            Set<Artifact> providerArtifacts = provider.getProviderClasspath();
-            String providerName = provider.getProviderName();
             if ( isForking && canExecuteProviderWithModularPath( platform, resolvedJavaModularity ) )
             {
                 File jdkHome = platform.getJdkExecAttributesForTests().getJdkHome();
-                return newStartupConfigWithModularPath( classLoaderConfiguration, providerArtifacts, providerName,
-                    resolvedJavaModularity, scanResult, jdkHome.getAbsolutePath(), testClasspathWrapper );
+                return newStartupConfigWithModularPath( classLoaderConfiguration, provider, resolvedJavaModularity,
+                    scanResult, jdkHome.getAbsolutePath(), testClasspathWrapper );
             }
             else
             {
-                return newStartupConfigWithClasspath( classLoaderConfiguration, providerArtifacts, providerName,
-                        testClasspathWrapper );
+                return newStartupConfigWithClasspath( classLoaderConfiguration, provider, testClasspathWrapper );
             }
         }
         catch ( IOException e )
@@ -1896,11 +1901,12 @@ public abstract class AbstractSurefireMojo
     }
 
     private StartupConfiguration newStartupConfigWithClasspath(
-            @Nonnull ClassLoaderConfiguration classLoaderConfiguration, @Nonnull Set<Artifact> providerArtifacts,
-            @Nonnull String providerName, @Nonnull TestClassPath testClasspathWrapper )
+        @Nonnull ClassLoaderConfiguration classLoaderConfiguration, @Nonnull ProviderInfo providerInfo,
+        @Nonnull TestClassPath testClasspathWrapper ) throws MojoExecutionException
     {
         Classpath testClasspath = testClasspathWrapper.toClasspath();
-
+        Set<Artifact> providerArtifacts = providerInfo.getProviderClasspath();
+        String providerName = providerInfo.getProviderName();
         Classpath providerClasspath = classpathCache.getCachedClassPath( providerName );
         if ( providerClasspath == null )
         {
@@ -1921,9 +1927,9 @@ public abstract class AbstractSurefireMojo
 
         ClasspathConfiguration classpathConfiguration = new ClasspathConfiguration( testClasspath, providerClasspath,
                 inProcClasspath, effectiveIsEnableAssertions(), isChildDelegation() );
-
+        ProviderRequirements forkRequirements = new ProviderRequirements( false, false, false );
         return new StartupConfiguration( providerName, classpathConfiguration, classLoaderConfiguration,
-            ProcessCheckerType.toEnum( getEnableProcessChecker() ) );
+            ProcessCheckerType.toEnum( getEnableProcessChecker() ), providerInfo.getJpmsArguments( forkRequirements ) );
     }
 
     private static Set<Artifact> retainInProcArtifactsUnique( Set<Artifact> providerArtifacts,
@@ -1975,45 +1981,61 @@ public abstract class AbstractSurefireMojo
     }
 
     private StartupConfiguration newStartupConfigWithModularPath(
-        @Nonnull ClassLoaderConfiguration classLoaderConfiguration, @Nonnull Set<Artifact> providerArtifacts,
-        @Nonnull String providerName, @Nonnull ResolvePathResultWrapper moduleDescriptor,
-        @Nonnull DefaultScanResult scanResult, @Nonnull String javaHome, @Nonnull TestClassPath testClasspathWrapper )
-            throws IOException
+        @Nonnull ClassLoaderConfiguration classLoaderConfiguration, @Nonnull ProviderInfo providerInfo,
+        @Nonnull ResolvePathResultWrapper moduleDescriptor, @Nonnull DefaultScanResult scanResult,
+        @Nonnull String javaHome, @Nonnull TestClassPath testClasspathWrapper )
+            throws MojoExecutionException, IOException
     {
-        Classpath testClasspath = testClasspathWrapper.toClasspath();
+        boolean isMainDescriptor = moduleDescriptor.isMainModuleDescriptor();
+        JavaModuleDescriptor javaModuleDescriptor = moduleDescriptor.getResolvePathResult().getModuleDescriptor();
+        SortedSet<String> packages = new TreeSet<>();
 
+        Classpath testClasspath = testClasspathWrapper.toClasspath();
+        Set<Artifact> providerArtifacts = providerInfo.getProviderClasspath();
+        String providerName = providerInfo.getProviderName();
         Classpath providerClasspath = classpathCache.getCachedClassPath( providerName );
         if ( providerClasspath == null )
         {
             providerClasspath = classpathCache.setCachedClasspath( providerName, providerArtifacts );
         }
 
-        ResolvePathsRequest<String> req = ResolvePathsRequest.ofStrings( testClasspath.getClassPath() )
-                .setJdkHome( javaHome )
-                .setModuleDescriptor( moduleDescriptor.getResolvePathResult().getModuleDescriptor() );
-
-        ResolvePathsResult<String> result = getLocationManager().resolvePaths( req );
-        for ( Entry<String, Exception> entry : result.getPathExceptions().entrySet() )
+        final ProviderRequirements providerRequirements;
+        final Classpath testModulepath;
+        if ( isMainDescriptor )
         {
-            // Probably JDK version < 9. Other known causes: passing a non-jar or a corrupted jar.
-            getConsoleLogger()
-                    .warning( "Exception for '" + entry.getKey() + "'.", entry.getValue() );
-        }
+            providerRequirements = new ProviderRequirements( true, true, false );
+            ResolvePathsRequest<String> req = ResolvePathsRequest.ofStrings( testClasspath.getClassPath() )
+                    .setJdkHome( javaHome )
+                    .setModuleDescriptor( javaModuleDescriptor );
 
-        testClasspath = new Classpath( result.getClasspathElements() );
-        Classpath testModulepath = new Classpath( result.getModulepathElements().keySet() );
+            ResolvePathsResult<String> result = getLocationManager().resolvePaths( req );
+            for ( Entry<String, Exception> entry : result.getPathExceptions().entrySet() )
+            {
+                // Probably JDK version < 9. Other known causes: passing a non-jar or a corrupted jar.
+                getConsoleLogger()
+                        .warning( "Exception for '" + entry.getKey() + "'.", entry.getValue() );
+            }
 
-        SortedSet<String> packages = new TreeSet<>();
+            testClasspath = new Classpath( result.getClasspathElements() );
+            testModulepath = new Classpath( result.getModulepathElements().keySet() );
 
-        for ( String className : scanResult.getClasses() )
+            for ( String className : scanResult.getClasses() )
+            {
+                packages.add( substringBeforeLast( className, "." ) );
+            }
+        }
+        else
         {
-            packages.add( substringBeforeLast( className, "." ) );
+            providerRequirements = new ProviderRequirements( true, false, true );
+            testModulepath = testClasspath;
+            testClasspath = emptyClasspath();
         }
 
-        getConsoleLogger().debug( "main module descriptor name: " + result.getMainModuleDescriptor().name() );
+        getConsoleLogger().debug( "main module descriptor name: " + javaModuleDescriptor.name() );
 
-        ModularClasspath modularClasspath = new ModularClasspath( result.getMainModuleDescriptor().name(),
-                testModulepath.getClassPath(), packages, getTestClassesDirectory() );
+        ModularClasspath modularClasspath = new ModularClasspath( javaModuleDescriptor.name(),
+            testModulepath.getClassPath(), packages, isMainDescriptor ? getTestClassesDirectory() : null,
+            isMainDescriptor );
 
         Artifact[] additionalInProcArtifacts = { getCommonArtifact(), getBooterArtifact(), getExtensionsArtifact(),
             getApiArtifact(), getSpiArtifact(), getLoggerApiArtifact(), getSurefireSharedUtilsArtifact() };
@@ -2032,8 +2054,10 @@ public abstract class AbstractSurefireMojo
         getConsoleLogger().debug( inProcClasspath.getLogMessage( "in-process classpath:" ) );
         getConsoleLogger().debug( inProcClasspath.getCompactLogMessage( "in-process(compact) classpath:" ) );
 
+        ProcessCheckerType processCheckerType = ProcessCheckerType.toEnum( getEnableProcessChecker() );
+        List<String[]> jpmsArgs = providerInfo.getJpmsArguments( providerRequirements );
         return new StartupConfiguration( providerName, classpathConfiguration, classLoaderConfiguration,
-            ProcessCheckerType.toEnum( getEnableProcessChecker() ) );
+            processCheckerType, jpmsArgs );
     }
 
     private Artifact getCommonArtifact()
@@ -2344,7 +2368,7 @@ public abstract class AbstractSurefireMojo
                                            @Nonnull RunOrderParameters runOrderParameters, @Nonnull ConsoleLogger log,
                                            @Nonnull DefaultScanResult scanResult,
                                            @Nonnull TestClassPath testClasspathWrapper, @Nonnull Platform platform,
-                                           ResolvePathResultWrapper resolvedJavaModularityResult )
+                                           @Nonnull ResolvePathResultWrapper resolvedJavaModularityResult )
         throws MojoExecutionException, MojoFailureException
     {
         StartupConfiguration startupConfiguration = createStartupConfiguration( provider, true,
@@ -3039,6 +3063,13 @@ public abstract class AbstractSurefireMojo
             convertTestNGParameters();
         }
 
+        @Nonnull
+        @Override
+        public List<String[]> getJpmsArguments( @Nonnull ProviderRequirements forkRequirements )
+        {
+            return emptyList();
+        }
+
         @Override
         @Nonnull
         public Set<Artifact> getProviderClasspath()
@@ -3069,6 +3100,13 @@ public abstract class AbstractSurefireMojo
         {
         }
 
+        @Nonnull
+        @Override
+        public List<String[]> getJpmsArguments( @Nonnull ProviderRequirements forkRequirements )
+        {
+            return emptyList();
+        }
+
         @Override
         @Nonnull
         public Set<Artifact> getProviderClasspath()
@@ -3110,6 +3148,13 @@ public abstract class AbstractSurefireMojo
         {
         }
 
+        @Nonnull
+        @Override
+        public List<String[]> getJpmsArguments( @Nonnull ProviderRequirements forkRequirements )
+        {
+            return emptyList();
+        }
+
         @Override
         @Nonnull
         public Set<Artifact> getProviderClasspath()
@@ -3153,6 +3198,14 @@ public abstract class AbstractSurefireMojo
             convertGroupParameters();
         }
 
+        @Nonnull
+        @Override
+        public List<String[]> getJpmsArguments( @Nonnull ProviderRequirements forkRequirements )
+        {
+            boolean hasTestDescriptor = forkRequirements.isModularPath() && forkRequirements.hasTestModuleDescriptor();
+            return hasTestDescriptor ? getJpmsArgs() : Collections.<String[]>emptyList();
+        }
+
         @Override
         @Nonnull
         public Set<Artifact> getProviderClasspath() throws MojoExecutionException
@@ -3209,6 +3262,23 @@ public abstract class AbstractSurefireMojo
             return new LinkedHashSet<>( providerArtifacts.values() );
         }
 
+        private List<String[]> getJpmsArgs()
+        {
+            List<String[]> args = new ArrayList<>();
+
+            args.add( new String[] {
+                "--add-opens",
+                "org.junit.platform.commons/org.junit.platform.commons.util=ALL-UNNAMED"
+            } );
+
+            args.add( new String[] {
+                "--add-opens",
+                "org.junit.platform.commons/org.junit.platform.commons.logging=ALL-UNNAMED"
+            } );
+
+            return args;
+        }
+
         private void addEngineByApi( String engineGroupId, String engineArtifactId, String engineVersion,
                                      Map<String, Artifact> providerArtifacts )
         {
@@ -3306,6 +3376,13 @@ public abstract class AbstractSurefireMojo
             convertGroupParameters();
         }
 
+        @Nonnull
+        @Override
+        public List<String[]> getJpmsArguments( @Nonnull ProviderRequirements forkRequirements )
+        {
+            return emptyList();
+        }
+
         @Override
         @Nonnull
         public Set<Artifact> getProviderClasspath()
@@ -3355,6 +3432,13 @@ public abstract class AbstractSurefireMojo
             convertTestNGParameters();
         }
 
+        @Nonnull
+        @Override
+        public List<String[]> getJpmsArguments( @Nonnull ProviderRequirements forkRequirements )
+        {
+            return emptyList();
+        }
+
         @Override
         @Nonnull
         public Set<Artifact> getProviderClasspath() throws MojoExecutionException
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
index fea74fd..66dd493 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
@@ -23,6 +23,7 @@ import org.apache.maven.artifact.Artifact;
 import org.apache.maven.plugin.MojoExecutionException;
 
 import javax.annotation.Nonnull;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -39,4 +40,7 @@ public interface ProviderInfo
     Set<Artifact> getProviderClasspath() throws MojoExecutionException;
 
     void addProviderProperties() throws MojoExecutionException;
+
+    @Nonnull
+    List<String[]> getJpmsArguments( @Nonnull ProviderRequirements forkRequirements );
 }
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderRequirements.java
similarity index 51%
copy from maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
copy to maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderRequirements.java
index fea74fd..793667a 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderRequirements.java
@@ -19,24 +19,36 @@ package org.apache.maven.plugin.surefire;
  * under the License.
  */
 
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.plugin.MojoExecutionException;
-
-import javax.annotation.Nonnull;
-import java.util.Set;
-
 /**
- * @author Kristian Rosenvold
+ * Used to get additional provider-specific JVM arguments.
+ *
+ * @see ProviderInfo#getJpmsArguments(ProviderRequirements)
  */
-public interface ProviderInfo
+final class ProviderRequirements
 {
-    @Nonnull
-    String getProviderName();
+    private final boolean modularPath;
+    private final boolean mainModuleDescriptor;
+    private final boolean testModuleDescriptor;
+
+    ProviderRequirements( boolean modularPath, boolean mainModuleDescriptor, boolean testModuleDescriptor )
+    {
+        this.modularPath = modularPath;
+        this.mainModuleDescriptor = mainModuleDescriptor;
+        this.testModuleDescriptor = testModuleDescriptor;
+    }
 
-    boolean isApplicable();
+    boolean isModularPath()
+    {
+        return modularPath;
+    }
 
-    @Nonnull
-    Set<Artifact> getProviderClasspath() throws MojoExecutionException;
+    boolean hasMainModuleDescriptor()
+    {
+        return mainModuleDescriptor;
+    }
 
-    void addProviderProperties() throws MojoExecutionException;
+    boolean hasTestModuleDescriptor()
+    {
+        return testModuleDescriptor;
+    }
 }
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java
index 5336ac6..a2c38b8 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java
@@ -170,7 +170,7 @@ public abstract class DefaultForkConfiguration
     }
 
     @Nonnull
-    protected List<String> toCompleteClasspath( StartupConfiguration conf ) throws SurefireBooterForkException
+    protected List<String> toCompleteClasspath( @Nonnull StartupConfiguration conf ) throws SurefireBooterForkException
     {
         AbstractPathConfiguration pathConfig = conf.getClasspathConfiguration();
         if ( pathConfig.isClassPathConfig() == pathConfig.isModularPathConfig() )
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfiguration.java
index 52729c3..16e8905 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfiguration.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfiguration.java
@@ -45,8 +45,8 @@ import java.util.Properties;
 import static java.io.File.createTempFile;
 import static java.io.File.pathSeparatorChar;
 import static org.apache.maven.plugin.surefire.SurefireHelper.escapeToPlatformPath;
-import static org.apache.maven.surefire.shared.utils.StringUtils.replace;
 import static org.apache.maven.surefire.api.util.internal.StringUtils.NL;
+import static org.apache.maven.surefire.shared.utils.StringUtils.replace;
 
 /**
  * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
@@ -90,13 +90,15 @@ public class ModularClasspathForkConfiguration
 
             ModularClasspath modularClasspath = modularClasspathConfiguration.getModularClasspath();
 
+            boolean isMainDescriptor = modularClasspath.isMainDescriptor();
             String moduleName = modularClasspath.getModuleNameFromDescriptor();
             List<String> modulePath = modularClasspath.getModulePath();
             Collection<String> packages = modularClasspath.getPackages();
             File patchFile = modularClasspath.getPatchFile();
             List<String> classpath = toCompleteClasspath( config );
 
-            File argsFile = createArgsFile( moduleName, modulePath, classpath, packages, patchFile, startClass );
+            File argsFile = createArgsFile( moduleName, modulePath, classpath, packages, patchFile, startClass,
+                isMainDescriptor, config.getJpmsArguments() );
 
             cli.createArg().setValue( "@" + escapeToPlatformPath( argsFile.getAbsolutePath() ) );
         }
@@ -112,7 +114,8 @@ public class ModularClasspathForkConfiguration
     @Nonnull
     File createArgsFile( @Nonnull String moduleName, @Nonnull List<String> modulePath,
                          @Nonnull List<String> classPath, @Nonnull Collection<String> packages,
-                         @Nonnull File patchFile, @Nonnull String startClassName )
+                         File patchFile, @Nonnull String startClassName, boolean isMainDescriptor,
+                         @Nonnull List<String[]> providerJpmsArguments )
             throws IOException
     {
         File surefireArgs = createTempFile( "surefireargs", "", getTempDirectory() );
@@ -167,38 +170,57 @@ public class ModularClasspathForkConfiguration
                         .append( NL );
             }
 
-            args.append( "--patch-module" )
-                    .append( NL )
-                    .append( moduleName )
-                    .append( '=' )
-                    .append( '"' )
-                    .append( replace( patchFile.getPath(), "\\", "\\\\" ) )
-                    .append( '"' )
-                    .append( NL );
-
-            for ( String pkg : packages )
+            if ( isMainDescriptor )
             {
-                args.append( "--add-exports" )
+                args.append( "--patch-module" )
+                        .append( NL )
+                        .append( moduleName )
+                        .append( '=' )
+                        .append( '"' )
+                        .append( replace( patchFile.getPath(), "\\", "\\\\" ) )
+                        .append( '"' )
+                        .append( NL );
+
+                for ( String pkg : packages )
+                {
+                    args.append( "--add-exports" )
+                            .append( NL )
+                            .append( moduleName )
+                            .append( '/' )
+                            .append( pkg )
+                            .append( '=' )
+                            .append( "ALL-UNNAMED" )
+                            .append( NL );
+                }
+
+                args.append( "--add-modules" )
+                        .append( NL )
+                        .append( moduleName )
+                        .append( NL );
+
+                args.append( "--add-reads" )
                         .append( NL )
                         .append( moduleName )
-                        .append( '/' )
-                        .append( pkg )
                         .append( '=' )
                         .append( "ALL-UNNAMED" )
                         .append( NL );
             }
+            else
+            {
+                for ( String[] entries : providerJpmsArguments )
+                {
+                    for ( String entry : entries )
+                    {
+                        args.append( entry )
+                            .append( NL );
+                    }
+                }
 
-            args.append( "--add-modules" )
-                    .append( NL )
-                    .append( moduleName )
-                    .append( NL );
-
-            args.append( "--add-reads" )
+                args.append( "--add-modules" )
                     .append( NL )
                     .append( moduleName )
-                    .append( '=' )
-                    .append( "ALL-UNNAMED" )
                     .append( NL );
+            }
 
             args.append( startClassName );
 
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoJava7PlusTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoJava7PlusTest.java
index d02c7fd..7d5343c 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoJava7PlusTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoJava7PlusTest.java
@@ -58,8 +58,10 @@ import static java.util.Collections.singleton;
 import static java.util.Collections.singletonMap;
 import static org.apache.maven.artifact.versioning.VersionRange.createFromVersion;
 import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Index.atIndex;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -134,10 +136,10 @@ public class AbstractSurefireMojoJava7PlusTest
         ClassLoaderConfiguration classLoaderConfiguration = new ClassLoaderConfiguration( false, true );
 
         VersionRange v5 = createFromVersion( "1" );
-        Artifact provider = new DefaultArtifact( "org.apache.maven.surefire", "surefire-provider", v5, "runtime",
-                "jar", "", handler );
-        provider.setFile( mockFile( "surefire-provider.jar" ) );
-        Set<Artifact> providerClasspath = singleton( provider );
+        Artifact providerArtifact = new DefaultArtifact( "org.apache.maven.surefire", "surefire-provider",
+            v5, "runtime", "jar", "", handler );
+        providerArtifact.setFile( mockFile( "surefire-provider.jar" ) );
+        Set<Artifact> providerClasspath = singleton( providerArtifact );
 
         ResolvePathResult moduleInfo = mock( ResolvePathResult.class );
         when( moduleInfo.getModuleDescriptor() ).thenReturn( descriptor );
@@ -205,8 +207,12 @@ public class AbstractSurefireMojoJava7PlusTest
         artifacts.put( "org.apache.maven.surefire:surefire-shared-utils", utils );
         when( mojo.getPluginArtifactMap() ).thenReturn( artifacts );
 
+        ProviderInfo providerInfo = mock( ProviderInfo.class );
+        when( providerInfo.getProviderName() ).thenReturn( "org.asf.Provider" );
+        when( providerInfo.getProviderClasspath() ).thenReturn( providerClasspath );
+
         StartupConfiguration conf = invokeMethod( mojo, "newStartupConfigWithModularPath",
-            classLoaderConfiguration, providerClasspath, "org.asf.Provider",
+            classLoaderConfiguration, providerInfo,
             new ResolvePathResultWrapper( moduleInfo, true ), scanResult, "", testClasspath );
 
         verify( mojo, times( 1 ) ).effectiveIsEnableAssertions();
@@ -262,6 +268,204 @@ public class AbstractSurefireMojoJava7PlusTest
                 .containsExactly( "modular.jar", "classes" );
     }
 
+    @Test
+    @SuppressWarnings( "checkstyle:linelength" )
+    public void shouldHaveStartupConfigForModularClasspathAndTestDescriptor()
+        throws Exception
+    {
+        AbstractSurefireMojo mojo = spy( new Mojo() );
+        doReturn( locationManager )
+            .when( mojo, "getLocationManager" );
+
+        when( handler.isAddedToClasspath() ).thenReturn( true );
+
+        VersionRange v1 = createFromVersion( "1" );
+        Artifact modular = new DefaultArtifact( "x", "modular", v1, "compile", "jar", "", handler );
+        modular.setFile( mockFile( "modular.jar" ) );
+
+        VersionRange v2 = createFromVersion( "1" );
+        Artifact nonModular = new DefaultArtifact( "x", "non-modular", v2, "test", "jar", "", handler );
+        nonModular.setFile( mockFile( "non-modular.jar" ) );
+
+        VersionRange v3 = createFromVersion( "4.12" );
+        Artifact junit = new DefaultArtifact( "junit", "junit", v3, "test", "jar", "", handler );
+        junit.setFile( mockFile( "junit.jar" ) );
+
+        VersionRange v4 = createFromVersion( "1.3.0" );
+        Artifact hamcrest = new DefaultArtifact( "org.hamcrest", "hamcrest-core", v4, "test", "jar", "", handler );
+        hamcrest.setFile( mockFile( "hamcrest.jar" ) );
+
+        File classesDir = mockFile( "classes" );
+        File testClassesDir = mockFile( "test-classes" );
+
+        TestClassPath testClasspath =
+            new TestClassPath( asList( modular, nonModular, junit, hamcrest ), classesDir, testClassesDir,
+                null );
+
+        doReturn( testClasspath ).when( mojo, "generateTestClasspath" );
+        doReturn( 1 ).when( mojo, "getEffectiveForkCount" );
+        doReturn( true ).when( mojo, "effectiveIsEnableAssertions" );
+        when( mojo.isChildDelegation() ).thenReturn( false );
+        when( mojo.getTestClassesDirectory() ).thenReturn( testClassesDir );
+
+        DefaultScanResult scanResult = mock( DefaultScanResult.class );
+        when( scanResult.getClasses() ).thenReturn( asList( "org.apache.A", "org.apache.B" ) );
+
+        ClassLoaderConfiguration classLoaderConfiguration = new ClassLoaderConfiguration( false, true );
+
+        VersionRange v5 = createFromVersion( "1" );
+        Artifact providerArtifact = new DefaultArtifact( "org.apache.maven.surefire", "surefire-provider",
+            v5, "runtime", "jar", "", handler );
+        providerArtifact.setFile( mockFile( "surefire-provider.jar" ) );
+        Set<Artifact> providerClasspath = singleton( providerArtifact );
+
+        ResolvePathResult moduleInfo = mock( ResolvePathResult.class );
+        when( moduleInfo.getModuleDescriptor() ).thenReturn( descriptor );
+
+        when( descriptor.name() ).thenReturn( "abc" );
+
+        Logger logger = mock( Logger.class );
+        when( logger.isDebugEnabled() ).thenReturn( true );
+        doNothing().when( logger ).debug( anyString() );
+        when( mojo.getConsoleLogger() ).thenReturn( new PluginConsoleLogger( logger ) );
+
+        Artifact common = new DefaultArtifact( "org.apache.maven.surefire", "maven-surefire-common", v5, "runtime",
+            "jar", "", handler );
+        common.setFile( mockFile( "maven-surefire-common.jar" ) );
+
+        Artifact ext = new DefaultArtifact( "org.apache.maven.surefire", "surefire-extensions-api", v5, "runtime",
+            "jar", "", handler );
+        ext.setFile( mockFile( "surefire-extensions-api.jar" ) );
+
+        Artifact api = new DefaultArtifact( "org.apache.maven.surefire", "surefire-api", v5, "runtime",
+            "jar", "", handler );
+        api.setFile( mockFile( "surefire-api.jar" ) );
+
+        Artifact loggerApi = new DefaultArtifact( "org.apache.maven.surefire", "surefire-logger-api", v5, "runtime",
+            "jar", "", handler );
+        loggerApi.setFile( mockFile( "surefire-logger-api.jar" ) );
+
+        Artifact spi = new DefaultArtifact( "org.apache.maven.surefire", "surefire-extensions-spi",
+            createFromVersion( "1" ), "runtime", "jar", "", handler );
+        spi.setFile( mockFile( "surefire-extensions-spi.jar" ) );
+
+        Artifact booter = new DefaultArtifact( "org.apache.maven.surefire", "surefire-booter",
+            createFromVersion( "1" ), "runtime", "jar", "", handler );
+        booter.setFile( mockFile( "surefire-booter.jar" ) );
+
+        Artifact utils = new DefaultArtifact( "org.apache.maven.surefire", "surefire-shared-utils",
+            createFromVersion( "1" ), "runtime", "jar", "", handler );
+        utils.setFile( mockFile( "surefire-shared-utils.jar" ) );
+
+        Map<String, Artifact> artifacts = new HashMap<>();
+        artifacts.put( "org.apache.maven.surefire:maven-surefire-common", common );
+        artifacts.put( "org.apache.maven.surefire:surefire-extensions-api", ext );
+        artifacts.put( "org.apache.maven.surefire:surefire-api", api );
+        artifacts.put( "org.apache.maven.surefire:surefire-logger-api", loggerApi );
+        artifacts.put( "org.apache.maven.surefire:surefire-extensions-spi", spi );
+        artifacts.put( "org.apache.maven.surefire:surefire-booter", booter );
+        artifacts.put( "org.apache.maven.surefire:surefire-shared-utils", utils );
+        when( mojo.getPluginArtifactMap() ).thenReturn( artifacts );
+
+        ProviderInfo providerInfo = mock( ProviderInfo.class );
+        when( providerInfo.getProviderName() ).thenReturn( "org.asf.Provider" );
+        when( providerInfo.getProviderClasspath() ).thenReturn( providerClasspath );
+
+        StartupConfiguration conf = invokeMethod( mojo, "newStartupConfigWithModularPath",
+            classLoaderConfiguration, providerInfo,
+            new ResolvePathResultWrapper( moduleInfo, false ), scanResult, "", testClasspath );
+
+        verify( mojo, times( 1 ) ).effectiveIsEnableAssertions();
+        verify( mojo, times( 1 ) ).isChildDelegation();
+        verify( mojo, never() ).getTestClassesDirectory();
+        ArgumentCaptor<String> argument = ArgumentCaptor.forClass( String.class );
+        verify( logger, times( 9 ) ).debug( argument.capture() );
+        assertThat( argument.getAllValues() )
+            .containsExactly( "main module descriptor name: abc",
+                "test classpath:",
+                "test modulepath:  test-classes  classes  modular.jar  non-modular.jar  junit.jar  hamcrest.jar",
+                "provider classpath:  surefire-provider.jar",
+                "test(compact) classpath:",
+                "test(compact) modulepath:  test-classes  classes  modular.jar  non-modular.jar  junit.jar  hamcrest.jar",
+                "provider(compact) classpath:  surefire-provider.jar",
+                "in-process classpath:  surefire-provider.jar  maven-surefire-common.jar  surefire-booter.jar  surefire-extensions-api.jar  surefire-api.jar  surefire-extensions-spi.jar  surefire-logger-api.jar  surefire-shared-utils.jar",
+                "in-process(compact) classpath:  surefire-provider.jar  maven-surefire-common.jar  surefire-booter.jar  surefire-extensions-api.jar  surefire-api.jar  surefire-extensions-spi.jar  surefire-logger-api.jar  surefire-shared-utils.jar"
+            );
+
+        assertThat( conf ).isNotNull();
+        assertThat( conf.isShadefire() ).isFalse();
+        assertThat( conf.isProviderMainClass() ).isFalse();
+        assertThat( conf.isManifestOnlyJarRequestedAndUsable() ).isFalse();
+        assertThat( conf.getClassLoaderConfiguration() ).isSameAs( classLoaderConfiguration );
+        assertThat( conf.getProviderClassName() ).isEqualTo( "org.asf.Provider" );
+        assertThat( conf.getActualClassName() ).isEqualTo( "org.asf.Provider" );
+        assertThat( conf.getClasspathConfiguration() ).isNotNull();
+        assertThat( ( Object ) conf.getClasspathConfiguration().getTestClasspath() )
+            .isEqualTo( Classpath.emptyClasspath() );
+        assertThat( ( Object ) conf.getClasspathConfiguration().getProviderClasspath() )
+            .isEqualTo( new Classpath( singleton( "surefire-provider.jar" ) ) );
+        assertThat( conf.getClasspathConfiguration() ).isInstanceOf( ModularClasspathConfiguration.class );
+        ModularClasspathConfiguration mcc = ( ModularClasspathConfiguration ) conf.getClasspathConfiguration();
+        assertThat( mcc.getModularClasspath().getModuleNameFromDescriptor() ).isEqualTo( "abc" );
+        assertThat( mcc.getModularClasspath().getPackages() ).isEmpty();
+        assertThat( mcc.getModularClasspath().getPatchFile() )
+            .isNull();
+        assertThat( mcc.getModularClasspath().getModulePath() )
+            .hasSize( 6 )
+            .containsSequence( "test-classes", "classes", "modular.jar", "non-modular.jar",
+                "junit.jar", "hamcrest.jar" );
+    }
+
+    @Test
+    public void testAllProviderInfo()
+    {
+        Mojo mojo = new Mojo();
+
+        ProviderRequirements providerRequirements = new ProviderRequirements( true, false, true );
+
+        ProviderInfo providerInfo = mojo.newDynamicProviderInfo();
+        assertThat( providerInfo.getProviderName() )
+            .isEqualTo( "custom.Provider" );
+        assertThat( providerInfo.getJpmsArguments( providerRequirements ) )
+            .isEmpty();
+
+        providerInfo = mojo.newJUnit3ProviderInfo();
+        assertThat( providerInfo.getProviderName() )
+            .isEqualTo( "org.apache.maven.surefire.junit.JUnit3Provider" );
+        assertThat( providerInfo.getJpmsArguments( providerRequirements ) )
+            .isEmpty();
+
+        providerInfo = mojo.newJUnit4ProviderInfo();
+        assertThat( providerInfo.getProviderName() )
+            .isEqualTo( "org.apache.maven.surefire.junit4.JUnit4Provider" );
+        assertThat( providerInfo.getJpmsArguments( providerRequirements ) )
+            .isEmpty();
+
+        providerInfo = mojo.newJUnit47ProviderInfo();
+        assertThat( providerInfo.getProviderName() )
+            .isEqualTo( "org.apache.maven.surefire.junitcore.JUnitCoreProvider" );
+        assertThat( providerInfo.getJpmsArguments( providerRequirements ) )
+            .isEmpty();
+
+        providerInfo = mojo.newTestNgProviderInfo();
+        assertThat( providerInfo.getProviderName() )
+            .isEqualTo( "org.apache.maven.surefire.testng.TestNGProvider" );
+        assertThat( providerInfo.getJpmsArguments( providerRequirements ) )
+            .isEmpty();
+
+        providerInfo = mojo.newJUnitPlatformProviderInfo();
+        assertThat( providerInfo.getProviderName() )
+            .isEqualTo( "org.apache.maven.surefire.junitplatform.JUnitPlatformProvider" );
+        List<String[]> args = providerInfo.getJpmsArguments( providerRequirements );
+        assertThat( args )
+            .isNotEmpty()
+            .hasSize( 2 )
+            .contains( new String[] {
+            "--add-opens", "org.junit.platform.commons/org.junit.platform.commons.util=ALL-UNNAMED"}, atIndex( 0 ) )
+            .contains( new String[] {
+            "--add-opens", "org.junit.platform.commons/org.junit.platform.commons.logging=ALL-UNNAMED"}, atIndex( 1 ) );
+    }
+
     private static File mockFile( String absolutePath )
     {
         File f = mock( File.class );
@@ -275,6 +479,35 @@ public class AbstractSurefireMojoJava7PlusTest
     public static class Mojo
             extends AbstractSurefireMojo
     {
+        ProviderInfo newDynamicProviderInfo()
+        {
+            return new DynamicProviderInfo( "custom.Provider" );
+        }
+
+        ProviderInfo newJUnit3ProviderInfo()
+        {
+            return new JUnit3ProviderInfo();
+        }
+
+        ProviderInfo newJUnit4ProviderInfo()
+        {
+            return new JUnit4ProviderInfo( null, null );
+        }
+
+        ProviderInfo newJUnit47ProviderInfo()
+        {
+            return new JUnitCoreProviderInfo( null, null );
+        }
+
+        ProviderInfo newTestNgProviderInfo()
+        {
+            return new TestNgProviderInfo( null );
+        }
+
+        ProviderInfo newJUnitPlatformProviderInfo()
+        {
+            return new JUnitPlatformProviderInfo( null, null );
+        }
 
         @Override
         protected String getPluginName()
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoTest.java
index 0440816..a08224c 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoTest.java
@@ -165,6 +165,8 @@ public class AbstractSurefireMojoTest
     {
         AbstractSurefireMojo mojo = spy( new Mojo() );
         mojo.setMainBuildPath( tempFolder.newFolder() );
+        File testClassesDir = tempFolder.newFolder();
+        mojo.setTestClassesDirectory( testClassesDir );
         File jdkHome = new File( System.getProperty( "java.home" ) );
         ResolvePathResultWrapper wrapper = invokeMethod( mojo, "findModuleDescriptor", jdkHome );
 
@@ -200,6 +202,8 @@ public class AbstractSurefireMojoTest
             .when( mojo, "getLocationManager" );
         File classesDir = tempFolder.newFolder();
         mojo.setMainBuildPath( classesDir );
+        File testClassesDir = tempFolder.newFolder();
+        mojo.setTestClassesDirectory( testClassesDir );
         File descriptorFile = new File( classesDir, "module-info.class" );
         assertThat( descriptorFile.createNewFile() ).isTrue();
         File jdkHome = new File( System.getProperty( "java.home" ) );
@@ -255,6 +259,8 @@ public class AbstractSurefireMojoTest
             .when( mojo, "getLocationManager" );
         File classesDir = tempFolder.newFolder();
         mojo.setMainBuildPath( classesDir );
+        File testClassesDir = tempFolder.newFolder();
+        mojo.setTestClassesDirectory( testClassesDir );
 
         File descriptorFile = new File( classesDir, "module-info.class" );
         assertThat( descriptorFile.createNewFile() ).isTrue();
@@ -523,8 +529,12 @@ public class AbstractSurefireMojoTest
         doNothing().when( logger ).debug( anyString() );
         when( mojo.getConsoleLogger() ).thenReturn( new PluginConsoleLogger( logger ) );
 
+        ProviderInfo providerInfo = mock( ProviderInfo.class );
+        when( providerInfo.getProviderName() ).thenReturn( "org.asf.Provider" );
+        when( providerInfo.getProviderClasspath() ).thenReturn( providerArtifacts );
+
         StartupConfiguration conf = invokeMethod( mojo, "newStartupConfigWithClasspath",
-                classLoaderConfiguration, providerArtifacts, "org.asf.Provider", testClasspath );
+                classLoaderConfiguration, providerInfo, testClasspath );
 
         verify( mojo, times( 1 ) ).effectiveIsEnableAssertions();
         verify( mojo, times( 1 ) ).isChildDelegation();
@@ -661,9 +671,6 @@ public class AbstractSurefireMojoTest
         when( resolvePathsResult.getPathExceptions() ).thenReturn( emptyMap() );
         when( resolvePathsResult.getClasspathElements() ).thenReturn( emptyList() );
         when( resolvePathsResult.getModulepathElements() ).thenReturn( emptyMap() );
-        JavaModuleDescriptor desc = mock( JavaModuleDescriptor.class );
-        when( desc.name() ).thenReturn( "" );
-        when( resolvePathsResult.getMainModuleDescriptor() ).thenReturn( desc );
 
         mojo.setLogger( mock( Logger.class ) );
         mojo.setUseModulePath( true );
@@ -676,6 +683,7 @@ public class AbstractSurefireMojoTest
 
         File classesDirectory = new File( baseDir, "mock-dir" );
         File testClassesDirectory = new File( baseDir, "mock-dir" );
+        mojo.setTestClassesDirectory( testClassesDirectory );
         TestClassPath testClassPath = new TestClassPath( Collections.<Artifact>emptySet(),
             classesDirectory, testClassesDirectory, new String[0] );
 
@@ -703,6 +711,9 @@ public class AbstractSurefireMojoTest
         mojo.setPluginArtifactMap( artifacts );
 
         ResolvePathResult resolvePathResult = mock( ResolvePathResult.class );
+        JavaModuleDescriptor desc = mock( JavaModuleDescriptor.class );
+        when( desc.name() ).thenReturn( "" );
+        when( resolvePathResult.getModuleDescriptor() ).thenReturn( desc );
         ResolvePathResultWrapper wrapper = new ResolvePathResultWrapper( resolvePathResult, true );
         // ### END
 
@@ -2013,6 +2024,7 @@ public class AbstractSurefireMojoTest
             extends AbstractSurefireMojo implements SurefireReportParameters
     {
         private File mainBuildPath;
+        private File testClassesDirectory;
         private boolean useModulePath;
 
         private JUnitPlatformProviderInfo createJUnitPlatformProviderInfo( Artifact junitPlatformArtifact,
@@ -2102,13 +2114,13 @@ public class AbstractSurefireMojoTest
         @Override
         public File getTestClassesDirectory()
         {
-            return null;
+            return testClassesDirectory;
         }
 
         @Override
         public void setTestClassesDirectory( File testClassesDirectory )
         {
-
+            this.testClassesDirectory = testClassesDirectory;
         }
 
         @Override
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
index ac3eba5..7a08390 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
@@ -286,7 +286,8 @@ public class BooterDeserializerProviderConfigurationTest
     {
         ClasspathConfiguration classpathConfiguration = new ClasspathConfiguration( true, true );
 
-        return new StartupConfiguration( "com.provider", classpathConfiguration, classLoaderConfiguration, ALL );
+        return new StartupConfiguration( "com.provider", classpathConfiguration, classLoaderConfiguration, ALL,
+            Collections.<String[]>emptyList() );
     }
 
     private File getTestSourceDirectory()
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
index 5a2d6cf..6fe2ddc 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
@@ -46,6 +46,7 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 
@@ -142,7 +143,7 @@ public class BooterDeserializerStartupConfigurationTest
     public void testProcessCheckerNull() throws IOException
     {
         StartupConfiguration startupConfiguration = new StartupConfiguration( "com.provider", classpathConfiguration,
-                getManifestOnlyJarForkConfiguration(), null );
+                getManifestOnlyJarForkConfiguration(), null, Collections.<String[]>emptyList() );
         assertNull( saveAndReload( startupConfiguration ).getProcessChecker() );
     }
 
@@ -204,7 +205,8 @@ public class BooterDeserializerStartupConfigurationTest
 
     private StartupConfiguration getTestStartupConfiguration( ClassLoaderConfiguration classLoaderConfiguration )
     {
-        return new StartupConfiguration( "com.provider", classpathConfiguration, classLoaderConfiguration, ALL );
+        return new StartupConfiguration( "com.provider", classpathConfiguration, classLoaderConfiguration, ALL,
+            Collections.<String[]>emptyList() );
     }
 
     private File getTestSourceDirectory()
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfigurationTest.java
index 45a6b4a..1ed7a10 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfigurationTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfigurationTest.java
@@ -37,6 +37,7 @@ import org.powermock.modules.junit4.PowerMockRunner;
 
 import javax.annotation.Nonnull;
 import java.io.File;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
@@ -307,7 +308,7 @@ public class DefaultForkConfigurationTest
         ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true );
         ClasspathConfiguration cc = new ClasspathConfiguration( true, true );
         StartupConfiguration conf = new StartupConfiguration( "org.apache.maven.shadefire.surefire.MyProvider",
-                cc, clc, null );
+                cc, clc, null, Collections.<String[]>emptyList() );
         StartupConfiguration confMock = spy( conf );
         mockStatic( Relocator.class );
         when( Relocator.relocate( anyString() ) ).thenCallRealMethod();
@@ -327,8 +328,8 @@ public class DefaultForkConfigurationTest
     {
         ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true );
         ClasspathConfiguration cc = new ClasspathConfiguration( true, true );
-        StartupConfiguration conf =
-                new StartupConfiguration( "org.apache.maven.surefire.MyProvider", cc, clc, null );
+        StartupConfiguration conf = new StartupConfiguration( "org.apache.maven.surefire.MyProvider",
+            cc, clc, null, Collections.<String[]>emptyList() );
         StartupConfiguration confMock = spy( conf );
         mockStatic( Relocator.class );
         when( Relocator.relocate( anyString() ) ).thenCallRealMethod();
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
index bc01ee8..b1db277 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
@@ -19,31 +19,44 @@ package org.apache.maven.plugin.surefire.booterclient;
  * under the License.
  */
 
-import org.apache.maven.surefire.shared.io.FileUtils;
-import org.apache.maven.surefire.shared.lang3.SystemUtils;
 import org.apache.maven.plugin.surefire.JdkAttributes;
+import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.OutputStreamFlushableCommandline;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger;
-import org.apache.maven.surefire.shared.utils.StringUtils;
-import org.apache.maven.surefire.shared.utils.cli.Commandline;
 import org.apache.maven.surefire.booter.ClassLoaderConfiguration;
 import org.apache.maven.surefire.booter.Classpath;
 import org.apache.maven.surefire.booter.ClasspathConfiguration;
+import org.apache.maven.surefire.booter.ModularClasspath;
+import org.apache.maven.surefire.booter.ModularClasspathConfiguration;
 import org.apache.maven.surefire.booter.StartupConfiguration;
 import org.apache.maven.surefire.booter.SurefireBooterForkException;
 import org.apache.maven.surefire.extensions.ForkNodeFactory;
+import org.apache.maven.surefire.shared.io.FileUtils;
+import org.apache.maven.surefire.shared.lang3.SystemUtils;
+import org.apache.maven.surefire.shared.utils.StringUtils;
+import org.apache.maven.surefire.shared.utils.cli.Commandline;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import javax.annotation.Nonnull;
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 
+import static java.nio.file.Files.readAllBytes;
 import static java.util.Collections.singletonList;
+import static org.apache.maven.surefire.api.util.internal.StringUtils.NL;
 import static org.apache.maven.surefire.booter.Classpath.emptyClasspath;
 import static org.apache.maven.surefire.booter.ProcessCheckerType.ALL;
+import static org.fest.assertions.Assertions.assertThat;
 import static org.fest.util.Files.temporaryFolder;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -57,7 +70,7 @@ public class ForkConfigurationTest
 {
     private static final StartupConfiguration STARTUP_CONFIG = new StartupConfiguration( "",
             new ClasspathConfiguration( true, true ),
-            new ClassLoaderConfiguration( true, true ), ALL );
+            new ClassLoaderConfiguration( true, true ), ALL, Collections.<String[]>emptyList() );
 
     private static int idx = 0;
 
@@ -79,6 +92,161 @@ public class ForkConfigurationTest
     }
 
     @Test
+    public void testEnv() throws Exception
+    {
+        Map<String, String> env = new HashMap<>();
+        env.put( "key1", "val1" );
+        env.put( "key2", "val2" );
+        env.put( "key3", "val3" );
+        String[] exclEnv = {"PATH"};
+
+        String jvm = new File( new File( System.getProperty( "java.home" ), "bin" ), "java" ).getCanonicalPath();
+        Platform platform = new Platform().withJdkExecAttributesForTests( new JdkAttributes( jvm, false ) );
+
+        ForkConfiguration config = new DefaultForkConfiguration( emptyClasspath(), basedir, "", basedir,
+            new Properties(), "", env, exclEnv, false, 1, true,
+            platform, new NullConsoleLogger(), mock( ForkNodeFactory.class ) )
+        {
+
+            @Override
+            protected void resolveClasspath( @Nonnull OutputStreamFlushableCommandline cli,
+                                             @Nonnull String booterThatHasMainMethod,
+                                             @Nonnull StartupConfiguration config,
+                                             @Nonnull File dumpLogDirectory )
+            {
+
+            }
+        };
+
+        List<String[]> providerJpmsArgs = new ArrayList<>();
+        providerJpmsArgs.add( new String[]{ "arg2", "arg3" } );
+
+        File cpElement = getTempClasspathFile();
+        List<String> cp = singletonList( cpElement.getAbsolutePath() );
+
+        ClasspathConfiguration cpConfig = new ClasspathConfiguration( new Classpath( cp ), emptyClasspath(),
+            emptyClasspath(), true, true );
+        ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true );
+        StartupConfiguration startup = new StartupConfiguration( "cls", cpConfig, clc, ALL, providerJpmsArgs );
+
+        Commandline cli = config.createCommandLine( startup, 1, temporaryFolder() );
+
+        assertThat( cli.getEnvironmentVariables() )
+            .contains( "key1=val1", "key2=val2", "key3=val3" )
+            .excludes( "PATH=" )
+            .doesNotHaveDuplicates();
+    }
+
+    @Test
+    public void testCliArgs() throws Exception
+    {
+        String jvm = new File( new File( System.getProperty( "java.home" ), "bin" ), "java" ).getCanonicalPath();
+        Platform platform = new Platform().withJdkExecAttributesForTests( new JdkAttributes( jvm, false ) );
+
+        ModularClasspathForkConfiguration config = new ModularClasspathForkConfiguration( emptyClasspath(), basedir,
+            "", basedir, new Properties(), "arg1", Collections.<String, String>emptyMap(), new String[0], false, 1,
+            true, platform, new NullConsoleLogger(), mock( ForkNodeFactory.class ) );
+
+        assertThat( config.isDebug() ).isFalse();
+
+        List<String[]> providerJpmsArgs = new ArrayList<>();
+        providerJpmsArgs.add( new String[]{ "arg2", "arg3" } );
+
+        ModularClasspath modulepath = new ModularClasspath( "test.module", Collections.<String>emptyList(),
+            Collections.<String>emptyList(), null, false );
+        ModularClasspathConfiguration cpConfig = new ModularClasspathConfiguration( modulepath, emptyClasspath(),
+            emptyClasspath(), emptyClasspath(), false, true );
+        ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true );
+        StartupConfiguration startup = new StartupConfiguration( "cls", cpConfig, clc, ALL, providerJpmsArgs );
+
+        Commandline cli = config.createCommandLine( startup, 1, temporaryFolder() );
+        String cliAsString = cli.toString();
+
+        assertThat( cliAsString )
+            .contains( "arg1" );
+
+        // "/path/to/java arg1 @/path/to/argfile"
+        int beginOfFileArg = cliAsString.indexOf( '@', cliAsString.lastIndexOf( "arg1" ) );
+        assertThat( beginOfFileArg ).isPositive();
+        int endOfFileArg = cliAsString.indexOf( '"', beginOfFileArg );
+        if ( endOfFileArg == -1 )
+        {
+            endOfFileArg = cliAsString.length();
+        }
+        assertThat( endOfFileArg ).isPositive();
+        Path argFile = Paths.get( cliAsString.substring( beginOfFileArg + 1, endOfFileArg ) );
+        String argFileText = new String( readAllBytes( argFile ) );
+        assertThat( argFileText )
+            .contains( "arg2" )
+            .contains( "arg3" )
+            .contains( "--add-modules" + NL + "test.module" );
+    }
+
+    @Test
+    public void testDebugLine() throws Exception
+    {
+        String jvm = new File( new File( System.getProperty( "java.home" ), "bin" ), "java" ).getCanonicalPath();
+        Platform platform = new Platform().withJdkExecAttributesForTests( new JdkAttributes( jvm, false ) );
+
+        ConsoleLogger logger = mock( ConsoleLogger.class );
+        ForkNodeFactory forkNodeFactory = mock( ForkNodeFactory.class );
+
+        ForkConfiguration config = new DefaultForkConfiguration( emptyClasspath(), basedir,
+            "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005", basedir, new Properties(), "",
+            Collections.<String, String>emptyMap(), new String[0], true, 1, true,
+            platform, logger, forkNodeFactory )
+        {
+
+            @Override
+            protected void resolveClasspath( @Nonnull OutputStreamFlushableCommandline cli,
+                                             @Nonnull String booterThatHasMainMethod,
+                                             @Nonnull StartupConfiguration config,
+                                             @Nonnull File dumpLogDirectory )
+            {
+
+            }
+        };
+
+        assertThat( config.isDebug() )
+            .isTrue();
+
+        assertThat( config.getDebugLine() )
+            .isEqualTo( "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005" );
+
+        assertThat( config.getForkCount() )
+            .isEqualTo( 1 );
+
+        assertThat( config.isReuseForks() )
+            .isTrue();
+
+        assertThat( config.getForkNodeFactory() )
+            .isSameAs( forkNodeFactory );
+
+        File cpElement = getTempClasspathFile();
+        List<String> cp = singletonList( cpElement.getAbsolutePath() );
+
+        ClasspathConfiguration cpConfig = new ClasspathConfiguration( new Classpath( cp ), emptyClasspath(),
+            emptyClasspath(), true, true );
+        ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true );
+        StartupConfiguration startup = new StartupConfiguration( "org.apache.maven.surefire.JUnitProvider#main",
+            cpConfig, clc, ALL, Collections.<String[]>emptyList() );
+
+        assertThat( startup.isProviderMainClass() )
+            .isTrue();
+
+        assertThat( startup.getProviderClassName() )
+            .isEqualTo( "org.apache.maven.surefire.JUnitProvider#main" );
+
+        assertThat( startup.isShadefire() )
+            .isFalse();
+
+        Commandline cli = config.createCommandLine( startup, 1, temporaryFolder() );
+
+        assertThat( cli.toString() )
+            .contains( "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005" );
+    }
+
+    @Test
     @SuppressWarnings( { "checkstyle:methodname", "checkstyle:magicnumber" } )
     public void testCreateCommandLine_UseSystemClassLoaderForkOnce_ShouldConstructManifestOnlyJar()
         throws IOException, SurefireBooterForkException
@@ -90,7 +258,8 @@ public class ForkConfigurationTest
         ClasspathConfiguration cpConfig = new ClasspathConfiguration( new Classpath( cp ), emptyClasspath(),
                 emptyClasspath(), true, true );
         ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true );
-        StartupConfiguration startup = new StartupConfiguration( "", cpConfig, clc, ALL );
+        StartupConfiguration startup =
+            new StartupConfiguration( "", cpConfig, clc, ALL, Collections.<String[]>emptyList() );
 
         Commandline cli = config.createCommandLine( startup, 1, temporaryFolder() );
 
@@ -110,7 +279,8 @@ public class ForkConfigurationTest
         ClasspathConfiguration cpConfig = new ClasspathConfiguration( new Classpath( cp ), emptyClasspath(),
                 emptyClasspath(), true, true );
         ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true );
-        StartupConfiguration startup = new StartupConfiguration( "", cpConfig, clc, ALL );
+        StartupConfiguration startup =
+            new StartupConfiguration( "", cpConfig, clc, ALL, Collections.<String[]>emptyList() );
 
         Commandline commandLine = config.createCommandLine( startup, 1, temporaryFolder() );
         assertTrue( commandLine.toString().contains( "abc def" ) );
@@ -125,7 +295,8 @@ public class ForkConfigurationTest
         ClasspathConfiguration cpConfig = new ClasspathConfiguration( emptyClasspath(), emptyClasspath(),
                 emptyClasspath(), true, true );
         ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true );
-        StartupConfiguration startup = new StartupConfiguration( "", cpConfig, clc, ALL );
+        StartupConfiguration startup =
+            new StartupConfiguration( "", cpConfig, clc, ALL, Collections.<String[]>emptyList() );
         ForkConfiguration config = getForkConfiguration( cwd.getCanonicalFile() );
         Commandline commandLine = config.createCommandLine( startup, 1, temporaryFolder() );
 
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfigurationTest.java
index cfa7dce..b1320d5 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfigurationTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfigurationTest.java
@@ -79,8 +79,8 @@ public class ModularClasspathForkConfigurationTest
         Collection<String> packages = singleton( "org.apache.abc" );
         String startClassName = ForkedBooter.class.getName();
 
-        File jigsawArgsFile =
-                config.createArgsFile( "abc", modulePath, classPath, packages, patchFile, startClassName );
+        File jigsawArgsFile = config.createArgsFile( "abc", modulePath, classPath, packages, patchFile,
+            startClassName, true, Collections.<String[]>emptyList() );
 
         assertThat( jigsawArgsFile )
                 .isNotNull();
@@ -136,7 +136,7 @@ public class ModularClasspathForkConfigurationTest
         assertThat( argsFileLines.get( 12 ) )
                 .isEqualTo( ForkedBooter.class.getName() );
 
-        ModularClasspath modularClasspath = new ModularClasspath( "abc", modulePath, packages, patchFile );
+        ModularClasspath modularClasspath = new ModularClasspath( "abc", modulePath, packages, patchFile, true );
         Classpath testClasspathUrls = new Classpath( singleton( "target" + separator + "test-classes" ) );
         Classpath surefireClasspathUrls = Classpath.emptyClasspath();
         ModularClasspathConfiguration modularClasspathConfiguration =
@@ -144,7 +144,7 @@ public class ModularClasspathForkConfigurationTest
                         emptyClasspath(), true, true );
         ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true );
         StartupConfiguration startupConfiguration = new StartupConfiguration( "JUnitCoreProvider",
-            modularClasspathConfiguration, clc, null );
+            modularClasspathConfiguration, clc, null, Collections.<String[]>emptyList() );
         OutputStreamFlushableCommandline cli = new OutputStreamFlushableCommandline();
         config.resolveClasspath( cli, ForkedBooter.class.getName(), startupConfiguration,
                 createTempFile( "surefire", "surefire-reports" ) );
diff --git a/maven-surefire-plugin/src/site/apt/examples/jpms.apt.vm b/maven-surefire-plugin/src/site/apt/examples/jpms.apt.vm
new file mode 100644
index 0000000..5168d12
--- /dev/null
+++ b/maven-surefire-plugin/src/site/apt/examples/jpms.apt.vm
@@ -0,0 +1,205 @@
+ ------
+ Java Modularity (JPMS) in Tests
+ ------
+ dev@maven.apache.org
+ ------
+ 2020-05-29
+ ------
+
+ ~~ Licensed to the Apache Software Foundation (ASF) under one
+ ~~ or more contributor license agreements.  See the NOTICE file
+ ~~ distributed with this work for additional information
+ ~~ regarding copyright ownership.  The ASF licenses this file
+ ~~ to you under the Apache License, Version 2.0 (the
+ ~~ "License"); you may not use this file except in compliance
+ ~~ with the License.  You may obtain a copy of the License at
+ ~~
+ ~~   http://www.apache.org/licenses/LICENSE-2.0
+ ~~
+ ~~ Unless required by applicable law or agreed to in writing,
+ ~~ software distributed under the License is distributed on an
+ ~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~~ KIND, either express or implied.  See the License for the
+ ~~ specific language governing permissions and limitations
+ ~~ under the License.
+
+ ~~ NOTE: For help with the syntax of this file, see:
+ ~~ http://maven.apache.org/doxia/references/apt-format.html
+
+Using Java Modularity (JPMS) in Tests
+
+* Examples using TestNG
+
+  The Surefire project provides the integration tests with
+  {{{https://github.com/apache/maven-surefire/tree/master/surefire-its/src/test/resources/surefire-1733-testng}TestNG}}
+  demonstrating the Java Modularity (JPMS).
+
+  The JDK version must be 9 or higher. The POM contains the dependency <<<org.testng:testng:7.1.0>>> which is
+  an automatic module. It activates the internal provider <<<surefire-testng>>> in the plugin. The frameworks with
+  assertions API are used, i.e. <<<org.hamcrest:hamcrest:7.1.0>>> (automatic module)
+  and <<<org.assertj:assertj-core:3.16.1>>> (named module).
+
++---+
+<properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <maven.compiler.release>${java.specification.version}</maven.compiler.release>
+</properties>
+
+<dependencies>
+    <dependency>
+        <groupId>org.testng</groupId>
+        <artifactId>testng</artifactId>
+        <version>7.1.0</version>
+        <scope>test</scope>
+    </dependency>
+    <dependency>
+        <groupId>org.hamcrest</groupId>
+        <artifactId>hamcrest</artifactId>
+        <version>2.2</version>
+        <scope>test</scope>
+    </dependency>
+    <dependency>
+        <groupId>org.assertj</groupId>
+        <artifactId>assertj-core</artifactId>
+        <version>3.16.1</version>
+        <scope>test</scope>
+    </dependency>
+</dependencies>
++---+
+
+  The most important parts are the module descriptors. This is the module descriptor located in <<<src/main/java>>>:
+
++---+
+module main
+{
+    exports main;
+}
++---+
+
+  This is the module descriptor in <<<src/test/java>>>:
+
++---+
+module test
+{
+    requires main;
+    requires org.testng;
+    requires org.hamcrest;
+    requires org.assertj.core;
+    exports test to org.testng;
+}
++---+
+
+* Examples using JUnit4
+
+  The Surefire project provides the integration tests with
+  {{{https://github.com/apache/maven-surefire/tree/master/surefire-its/src/test/resources/surefire-1733-junit4}JUnit4}}
+  demonstrating the Java Modularity (JPMS).
+
+  The JDK version must be 9 or higher. The POM contains the dependency <<<junit:junit:4.13>>> which is
+  an automatic module. It activates the internal provider <<<surefire-junit4>>> or <<<surefire-junit47>>> in the plugin.
+
++---+
+<properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <maven.compiler.release>${java.specification.version}</maven.compiler.release>
+</properties>
+
+<dependencies>
+    <dependency>
+        <groupId>junit</groupId>
+        <artifactId>junit</artifactId>
+        <version>4.13</version>
+        <scope>test</scope>
+        <exclusions>
+            <exclusion>
+                <groupId>org.hamcrest</groupId>
+                <artifactId>hamcrest-core</artifactId>
+            </exclusion>
+        </exclusions>
+    </dependency>
+    <dependency>
+        <groupId>org.hamcrest</groupId>
+        <artifactId>hamcrest</artifactId>
+        <version>2.2</version>
+        <scope>test</scope>
+    </dependency>
+</dependencies>
++---+
+
+  The most important parts are the module descriptors. This is the module descriptor located in <<<src/main/java>>>:
+
++---+
+module main
+{
+    exports main;
+}
++---+
+
+  This is the module descriptor in <<<src/test/java>>>:
+
++---+
+module test
+{
+    requires main;
+    requires junit;
+    requires org.hamcrest;
+    exports test to junit;
+}
++---+
+
+* Examples using JUnit5
+
+  The Surefire project provides the integration tests with
+  {{{https://github.com/apache/maven-surefire/tree/master/surefire-its/src/test/resources/maven-multimodule-project-with-jpms}JUnit5}}
+  demonstrating the Java Modularity (JPMS) in Maven multi-module project.
+
+  The JDK version must be 9 or higher. The POM contains the dependency
+  <<<org.junit.jupiter:junit-jupiter-engine:5.6.2>>> which is named module. It activates the internal provider
+  <<<surefire-junit-platform>>> in the plugin.
+
++---+
+<artifactId>com.foo.impl</artifactId>
+
+<dependencies>
+    <dependency>
+        <groupId>com.foo</groupId>
+        <artifactId>com.foo.api</artifactId>
+        <version>${project.version}</version>
+    </dependency>
+    <dependency>
+        <groupId>org.slf4j</groupId>
+        <artifactId>slf4j-simple</artifactId>
+    </dependency>
+    <dependency>
+        <groupId>org.junit.jupiter</groupId>
+        <artifactId>junit-jupiter-engine</artifactId>
+        <scope>test</scope>
+    </dependency>
+</dependencies>
++---+
+
+  The most important parts are the module descriptors. This is the module descriptor located in <<<src/main/java>>>:
+
++---+
+module com.foo.impl
+{
+    exports com.foo.impl;
+    requires com.foo.api;
+    requires org.slf4j;
+    requires org.slf4j.simple;
+}
++---+
+
+  This is the module descriptor in <<<src/test/java>>>:
+
++---+
+open module com.foo.test
+{
+    exports com.foo.implt;
+    requires com.foo.impl;
+    requires org.slf4j;
+    requires org.slf4j.simple;
+    requires transitive org.junit.jupiter.engine;
+    requires transitive org.junit.jupiter.api;
+}
++---+
diff --git a/maven-surefire-plugin/src/site/site.xml b/maven-surefire-plugin/src/site/site.xml
index b1f722c..0768638 100644
--- a/maven-surefire-plugin/src/site/site.xml
+++ b/maven-surefire-plugin/src/site/site.xml
@@ -38,6 +38,7 @@
       <item name="Download" href="../download.html"/>
     </menu>
     <menu name="Examples">
+      <item name="Java Modularity (JPMS) in Tests" href="examples/jpms.html"/>
       <item name="TCP/IP Communication between Forks" href="examples/process-communication.html"/>
       <item name="Using TestNG" href="examples/testng.html"/>
       <item name="Using JUnit" href="examples/junit.html"/>
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ModularClasspath.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ModularClasspath.java
index 7bf8bd0..89aa131 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ModularClasspath.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ModularClasspath.java
@@ -26,6 +26,7 @@ import java.util.List;
 
 import static java.util.Collections.unmodifiableCollection;
 import static java.util.Collections.unmodifiableList;
+import static java.util.Objects.requireNonNull;
 
 /**
  * Jigsaw class-path and module-path.
@@ -39,15 +40,20 @@ public final class ModularClasspath
     private final List<String> modulePath;
     private final Collection<String> packages;
     private final File patchFile;
+    private final boolean isMainDescriptor;
 
-    public ModularClasspath( @Nonnull String moduleNameFromDescriptor, @Nonnull List<String> modulePath,
+    public ModularClasspath( @Nonnull String moduleNameFromDescriptor,
+                             @Nonnull List<String> modulePath,
                              @Nonnull Collection<String> packages,
-                             @Nonnull File patchFile )
+                             File patchFile,
+                             boolean isMainDescriptor )
     {
         this.moduleNameFromDescriptor = moduleNameFromDescriptor;
         this.modulePath = modulePath;
         this.packages = packages;
-        this.patchFile = patchFile;
+        this.patchFile =
+            isMainDescriptor ? requireNonNull( patchFile, "patchFile should not be null" ) : patchFile;
+        this.isMainDescriptor = isMainDescriptor;
     }
 
     @Nonnull
@@ -68,9 +74,13 @@ public final class ModularClasspath
         return unmodifiableCollection( packages );
     }
 
-    @Nonnull
     public File getPatchFile()
     {
         return patchFile;
     }
+
+    public boolean isMainDescriptor()
+    {
+        return isMainDescriptor;
+    }
 }
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/StartupConfiguration.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/StartupConfiguration.java
index d6a3dd0..7a9d1e4 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/StartupConfiguration.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/StartupConfiguration.java
@@ -20,6 +20,8 @@ package org.apache.maven.surefire.booter;
  */
 
 import javax.annotation.Nonnull;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * Configuration that is used by the SurefireStarter but does not make it into the provider itself.
@@ -34,16 +36,19 @@ public class StartupConfiguration
     private final AbstractPathConfiguration classpathConfiguration;
     private final ClassLoaderConfiguration classLoaderConfiguration;
     private final ProcessCheckerType processChecker;
+    private final List<String[]> jpmsArguments;
 
     public StartupConfiguration( @Nonnull String providerClassName,
                                  @Nonnull AbstractPathConfiguration classpathConfiguration,
                                  @Nonnull ClassLoaderConfiguration classLoaderConfiguration,
-                                 ProcessCheckerType processChecker )
+                                 ProcessCheckerType processChecker,
+                                 @Nonnull List<String[]> jpmsArguments )
     {
         this.classpathConfiguration = classpathConfiguration;
         this.classLoaderConfiguration = classLoaderConfiguration;
         this.providerClassName = providerClassName;
         this.processChecker = processChecker;
+        this.jpmsArguments = jpmsArguments;
     }
 
     public boolean isProviderMainClass()
@@ -56,7 +61,8 @@ public class StartupConfiguration
                                                    ClassLoaderConfiguration classLoaderConfig,
                                                    ProcessCheckerType processChecker )
     {
-        return new StartupConfiguration( providerClassName, classpathConfig, classLoaderConfig, processChecker );
+        return new StartupConfiguration( providerClassName, classpathConfig, classLoaderConfig,
+            processChecker, Collections.<String[]>emptyList() );
     }
 
     public AbstractPathConfiguration getClasspathConfiguration()
@@ -133,4 +139,9 @@ public class StartupConfiguration
     {
         return processChecker;
     }
+
+    public List<String[]> getJpmsArguments()
+    {
+        return jpmsArguments;
+    }
 }
diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/MultiModuleProjectWithJPMSIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/MultiModuleProjectWithJPMSIT.java
new file mode 100644
index 0000000..8b011ae
--- /dev/null
+++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/MultiModuleProjectWithJPMSIT.java
@@ -0,0 +1,70 @@
+package org.apache.maven.surefire.its;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.maven.surefire.its.fixture.OutputValidator;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * Integration test for <a href="https://issues.apache.org/jira/browse/SUREFIRE-1733">SUREFIRE-1733</a>.
+ */
+public class MultiModuleProjectWithJPMSIT extends AbstractJigsawIT
+{
+    @Test
+    public void test() throws Exception
+    {
+        OutputValidator validator = assumeJava9()
+            .debugLogging()
+            .executeVerify()
+            .verifyErrorFreeLog()
+            .assertThatLogLine( containsString( "Lets see JDKModulePath" ), is( 2 ) )
+            .assertThatLogLine( containsString( "Lets see JDKModulePath: null" ), is( 0 ) );
+
+        List<String> lines = validator.loadLogLines( containsString( "Lets see JDKModulePath" ) );
+        int i = 0;
+        for ( String line : lines )
+        {
+            assertThat( line )
+                .contains( "com.foo.api" )
+                .contains( "junit-jupiter-api" )
+                .contains( "junit-jupiter-engine" )
+                .contains( "slf4j-simple" )
+                .contains( "slf4j-api" )
+                .contains( "jakarta.xml.bind-api" )
+                .contains( "jakarta.ws.rs-api" )
+                .contains( "jakarta.persistence-api" );
+
+            assertThat( line )
+                .contains( i++ == 0 ? "test-classes" : "com.foo.impl" );
+        }
+    }
+
+    @Override
+    protected String getProjectDirectoryName()
+    {
+        return "maven-multimodule-project-with-jpms";
+    }
+}
diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1570ModularFailsafeIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1570ModularFailsafeIT.java
index eb1ff06..bb575b0 100644
--- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1570ModularFailsafeIT.java
+++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1570ModularFailsafeIT.java
@@ -19,11 +19,10 @@ package org.apache.maven.surefire.its.jiras;
  * under the License.
  */
 
-import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
+import org.apache.maven.surefire.its.AbstractJigsawIT;
 import org.junit.Before;
 import org.junit.Test;
 
-import static org.apache.maven.surefire.its.fixture.HelperAssertions.assumeJavaVersion;
 import static org.apache.maven.surefire.its.fixture.HelperAssertions.assumeJavaVersionExcluded;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.is;
@@ -34,23 +33,28 @@ import static org.hamcrest.Matchers.is;
  */
 @SuppressWarnings( "checkstyle:magicnumber" )
 public class Surefire1570ModularFailsafeIT
-    extends SurefireJUnit4IntegrationTestCase
+    extends AbstractJigsawIT
 {
     @Before
     public void setUp()
     {
-        assumeJavaVersion( 9d );
         assumeJavaVersionExcluded( 11d );
     }
 
     @Test
     public void shouldRunWithJupiterApi() throws Exception
     {
-        unpack( "surefire-1570" )
+        assumeJava9()
             .debugLogging()
             .executeVerify()
             .verifyErrorFreeLog()
             .assertThatLogLine( containsString( "Lets see JDKModulePath" ), is( 2 ) )
             .assertThatLogLine( containsString( "Lets see JDKModulePath: null" ), is( 0 ) );
     }
+
+    @Override
+    protected String getProjectDirectoryName()
+    {
+        return "surefire-1570";
+    }
 }
diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1570ModularFailsafeIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1733JUnitIT.java
similarity index 52%
copy from surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1570ModularFailsafeIT.java
copy to surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1733JUnitIT.java
index eb1ff06..242fede 100644
--- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1570ModularFailsafeIT.java
+++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1733JUnitIT.java
@@ -19,38 +19,35 @@ package org.apache.maven.surefire.its.jiras;
  * under the License.
  */
 
-import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
-import org.junit.Before;
+import org.apache.maven.surefire.its.AbstractJigsawIT;
 import org.junit.Test;
 
-import static org.apache.maven.surefire.its.fixture.HelperAssertions.assumeJavaVersion;
-import static org.apache.maven.surefire.its.fixture.HelperAssertions.assumeJavaVersionExcluded;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.is;
 
 /**
- *
- * @see <a href="https://issues.apache.org/jira/browse/SUREFIRE-1570">SUREFIRE-1570</a>
+ * Integration test for <a href="https://issues.apache.org/jira/browse/SUREFIRE-1733">SUREFIRE-1733</a>.
  */
-@SuppressWarnings( "checkstyle:magicnumber" )
-public class Surefire1570ModularFailsafeIT
-    extends SurefireJUnit4IntegrationTestCase
+public class Surefire1733JUnitIT extends AbstractJigsawIT
 {
-    @Before
-    public void setUp()
-    {
-        assumeJavaVersion( 9d );
-        assumeJavaVersionExcluded( 11d );
-    }
-
     @Test
-    public void shouldRunWithJupiterApi() throws Exception
+    public void test() throws Exception
     {
-        unpack( "surefire-1570" )
+        assumeJava9()
             .debugLogging()
             .executeVerify()
-            .verifyErrorFreeLog()
-            .assertThatLogLine( containsString( "Lets see JDKModulePath" ), is( 2 ) )
-            .assertThatLogLine( containsString( "Lets see JDKModulePath: null" ), is( 0 ) );
+            .assertTestSuiteResults( 1, 0, 0, 0 )
+            .assertIntegrationTestSuiteResults( 1, 0, 0, 0 )
+            .assertThatLogLine( containsString( "Running test.MyTest" ), is( 1 ) )
+            .assertThatLogLine( containsString( "Running test.MyIT" ), is( 1 ) )
+            .assertThatLogLine( containsString( "class main.Service in the module \"main\"" ), is( 2 ) )
+            .assertThatLogLine( containsString( "class test.MyTest in the module \"test\"" ), is( 1 ) )
+            .assertThatLogLine( containsString( "class test.MyIT in the module \"test\"" ), is( 1 ) );
+    }
+
+    @Override
+    protected String getProjectDirectoryName()
+    {
+        return "surefire-1733-junit4";
     }
 }
diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1570ModularFailsafeIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1733TestngIT.java
similarity index 52%
copy from surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1570ModularFailsafeIT.java
copy to surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1733TestngIT.java
index eb1ff06..53210c7 100644
--- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1570ModularFailsafeIT.java
+++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1733TestngIT.java
@@ -19,38 +19,35 @@ package org.apache.maven.surefire.its.jiras;
  * under the License.
  */
 
-import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
-import org.junit.Before;
+import org.apache.maven.surefire.its.AbstractJigsawIT;
 import org.junit.Test;
 
-import static org.apache.maven.surefire.its.fixture.HelperAssertions.assumeJavaVersion;
-import static org.apache.maven.surefire.its.fixture.HelperAssertions.assumeJavaVersionExcluded;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.is;
 
 /**
- *
- * @see <a href="https://issues.apache.org/jira/browse/SUREFIRE-1570">SUREFIRE-1570</a>
+ * Integration test for <a href="https://issues.apache.org/jira/browse/SUREFIRE-1733">SUREFIRE-1733</a>.
  */
-@SuppressWarnings( "checkstyle:magicnumber" )
-public class Surefire1570ModularFailsafeIT
-    extends SurefireJUnit4IntegrationTestCase
+public class Surefire1733TestngIT extends AbstractJigsawIT
 {
-    @Before
-    public void setUp()
-    {
-        assumeJavaVersion( 9d );
-        assumeJavaVersionExcluded( 11d );
-    }
-
     @Test
-    public void shouldRunWithJupiterApi() throws Exception
+    public void test() throws Exception
     {
-        unpack( "surefire-1570" )
+        assumeJava9()
             .debugLogging()
             .executeVerify()
-            .verifyErrorFreeLog()
-            .assertThatLogLine( containsString( "Lets see JDKModulePath" ), is( 2 ) )
-            .assertThatLogLine( containsString( "Lets see JDKModulePath: null" ), is( 0 ) );
+            .assertTestSuiteResults( 1, 0, 0, 0 )
+            .assertIntegrationTestSuiteResults( 1, 0, 0, 0 )
+            .assertThatLogLine( containsString( "Running test.MyTest" ), is( 1 ) )
+            .assertThatLogLine( containsString( "Running test.MyIT" ), is( 1 ) )
+            .assertThatLogLine( containsString( "class main.Service in the module \"main\"" ), is( 2 ) )
+            .assertThatLogLine( containsString( "class test.MyTest in the module \"test\"" ), is( 1 ) )
+            .assertThatLogLine( containsString( "class test.MyIT in the module \"test\"" ), is( 1 ) );
+    }
+
+    @Override
+    protected String getProjectDirectoryName()
+    {
+        return "surefire-1733-testng";
     }
 }
diff --git a/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.api/pom.xml b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.api/pom.xml
new file mode 100644
index 0000000..6e1883c
--- /dev/null
+++ b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.api/pom.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>com.foo</groupId>
+        <artifactId>com.foo</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>com.foo.api</artifactId>
+    
+    <dependencies>
+        <dependency>
+            <groupId>jakarta.persistence</groupId>
+            <artifactId>jakarta.persistence-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.ws.rs</groupId>
+            <artifactId>jakarta.ws.rs-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.xml.bind</groupId>
+            <artifactId>jakarta.xml.bind-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.api/src/main/java/com/foo/api/SomeInterface.java
similarity index 86%
copy from surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
copy to surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.api/src/main/java/com/foo/api/SomeInterface.java
index 7bbf986..43ecf73 100644
--- a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
+++ b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.api/src/main/java/com/foo/api/SomeInterface.java
@@ -1,3 +1,5 @@
+package com.foo.api;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -17,9 +19,10 @@
  * under the License.
  */
 
-module wtf.g4s8.oot.test
+/**
+ *
+ */
+public interface SomeInterface
 {
-    requires wtf.g4s8.oot;
-    requires org.junit.jupiter.api;
-    requires transitive org.hamcrest;
+    void doItNow( Class<?> observer );
 }
diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.api/src/main/java/module-info.java
similarity index 81%
copy from surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
copy to surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.api/src/main/java/module-info.java
index 7bbf986..95b05f7 100644
--- a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
+++ b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.api/src/main/java/module-info.java
@@ -17,9 +17,12 @@
  * under the License.
  */
 
-module wtf.g4s8.oot.test
+module com.foo.api
 {
-    requires wtf.g4s8.oot;
-    requires org.junit.jupiter.api;
-    requires transitive org.hamcrest;
+    exports com.foo.api;
+    requires org.slf4j;
+    requires java.persistence;
+    requires java.ws.rs;
+    requires java.xml.bind;
+    requires jakarta.activation;
 }
diff --git a/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/pom.xml b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/pom.xml
new file mode 100644
index 0000000..fd160fe
--- /dev/null
+++ b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/pom.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>com.foo</groupId>
+        <artifactId>com.foo</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>com.foo.impl</artifactId>
+    
+    <dependencies>
+        <dependency>
+            <groupId>com.foo</groupId>
+            <artifactId>com.foo.api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+<!--                    <multiReleaseOutput>true</multiReleaseOutput>-->
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestEntries>
+<!--                            <Multi-Release>true</Multi-Release>-->
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>integration-tests</id>
+                        <goals>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/main/java/com/foo/impl/Bar.java b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/main/java/com/foo/impl/Bar.java
new file mode 100644
index 0000000..50009e3
--- /dev/null
+++ b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/main/java/com/foo/impl/Bar.java
@@ -0,0 +1,51 @@
+package com.foo.impl;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import com.foo.api.SomeInterface;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ */
+public class Bar implements SomeInterface
+{
+    private static final Logger LOG = LoggerFactory.getLogger( Bar.class );
+
+    private boolean weAreAmongModules;
+
+    @Override
+    public void doItNow( Class<?> observer )
+    {
+        ModuleLayer.boot().modules().forEach( m -> {
+            if ( m == observer.getModule() || m == Bar.class.getModule() || m == Logger.class.getModule() )
+            {
+                weAreAmongModules = true;
+            }
+        } );
+        LOG.info( "" );
+        LOG.info( "Let's see if I or SLF4J are among boot layer modules: {}", weAreAmongModules );
+        if ( !weAreAmongModules )
+        {
+            LOG.info( "Maybe we are in child layer? Or this is not module path?" );
+        }
+    }
+}
diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/main/java/module-info.java
similarity index 86%
copy from surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
copy to surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/main/java/module-info.java
index 7bbf986..13ca174 100644
--- a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
+++ b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/main/java/module-info.java
@@ -17,9 +17,10 @@
  * under the License.
  */
 
-module wtf.g4s8.oot.test
+module com.foo.impl
 {
-    requires wtf.g4s8.oot;
-    requires org.junit.jupiter.api;
-    requires transitive org.hamcrest;
+    exports com.foo.impl;
+    requires com.foo.api;
+    requires org.slf4j;
+    requires org.slf4j.simple;
 }
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/test/java/com/foo/implt/BarIT.java
similarity index 62%
copy from maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
copy to surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/test/java/com/foo/implt/BarIT.java
index fea74fd..acb4c7f 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
+++ b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/test/java/com/foo/implt/BarIT.java
@@ -1,4 +1,4 @@
-package org.apache.maven.plugin.surefire;
+package com.foo.implt;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,24 +19,25 @@ package org.apache.maven.plugin.surefire;
  * under the License.
  */
 
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.plugin.MojoExecutionException;
+import com.foo.impl.Bar;
 
-import javax.annotation.Nonnull;
-import java.util.Set;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
- * @author Kristian Rosenvold
+ *
  */
-public interface ProviderInfo
+public class BarIT
 {
-    @Nonnull
-    String getProviderName();
-
-    boolean isApplicable();
-
-    @Nonnull
-    Set<Artifact> getProviderClasspath() throws MojoExecutionException;
+    private static final Logger LOG = LoggerFactory.getLogger( BarIT.class );
 
-    void addProviderProperties() throws MojoExecutionException;
+    @Test
+    void shouldPrintModulePath()
+    {
+        Bar bar = new Bar();
+        LOG.info( "======INTEGRATION TEST=======" );
+        LOG.info( "Lets see JDKModulePath: {}", System.getProperty( "jdk.module.path" ) );
+        bar.doItNow( getClass() );
+    }
 }
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/test/java/com/foo/implt/BarTest.java
similarity index 62%
copy from maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
copy to surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/test/java/com/foo/implt/BarTest.java
index fea74fd..f639198 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
+++ b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/test/java/com/foo/implt/BarTest.java
@@ -1,4 +1,4 @@
-package org.apache.maven.plugin.surefire;
+package com.foo.implt;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,24 +19,25 @@ package org.apache.maven.plugin.surefire;
  * under the License.
  */
 
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.plugin.MojoExecutionException;
+import com.foo.impl.Bar;
 
-import javax.annotation.Nonnull;
-import java.util.Set;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
- * @author Kristian Rosenvold
+ *
  */
-public interface ProviderInfo
+public class BarTest
 {
-    @Nonnull
-    String getProviderName();
-
-    boolean isApplicable();
-
-    @Nonnull
-    Set<Artifact> getProviderClasspath() throws MojoExecutionException;
+    private static final Logger LOG = LoggerFactory.getLogger( BarTest.class );
 
-    void addProviderProperties() throws MojoExecutionException;
+    @Test
+    void shouldPrintModulePath()
+    {
+        Bar bar = new Bar();
+        LOG.info( "======UNIT TEST=======" );
+        LOG.info( "Lets see JDKModulePath: {}", System.getProperty( "jdk.module.path" ) );
+        bar.doItNow( getClass() );
+    }
 }
diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/test/java/module-info.java
similarity index 77%
copy from surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
copy to surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/test/java/module-info.java
index 7bbf986..1906b6a 100644
--- a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
+++ b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/com.foo.impl/src/test/java/module-info.java
@@ -17,9 +17,12 @@
  * under the License.
  */
 
-module wtf.g4s8.oot.test
+open module com.foo.test
 {
-    requires wtf.g4s8.oot;
-    requires org.junit.jupiter.api;
-    requires transitive org.hamcrest;
+    exports com.foo.implt;
+    requires com.foo.impl;
+    requires org.slf4j;
+    requires org.slf4j.simple;
+    requires transitive org.junit.jupiter.engine;
+    requires transitive org.junit.jupiter.api;
 }
diff --git a/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/pom.xml b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/pom.xml
new file mode 100644
index 0000000..00e047f
--- /dev/null
+++ b/surefire-its/src/test/resources/maven-multimodule-project-with-jpms/pom.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.foo</groupId>
+    <artifactId>com.foo</artifactId>
+    <version>1.0.0</version>
+    <packaging>pom</packaging>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <maven.compiler.release>${java.specification.version}</maven.compiler.release>
+    </properties>
+
+    <modules>
+        <module>com.foo.api</module>
+        <module>com.foo.impl</module>
+    </modules>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>jakarta.persistence</groupId>
+                <artifactId>jakarta.persistence-api</artifactId>
+                <version>2.2.3</version>
+            </dependency>
+            <dependency>
+                <groupId>jakarta.ws.rs</groupId>
+                <artifactId>jakarta.ws.rs-api</artifactId>
+                <version>2.1.6</version>
+            </dependency>
+            <dependency>
+                <groupId>jakarta.xml.bind</groupId>
+                <artifactId>jakarta.xml.bind-api</artifactId>
+                <version>2.3.2</version>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-api</artifactId>
+                <version>1.8.0-beta2</version>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-simple</artifactId>
+                <version>1.8.0-beta2</version>
+            </dependency>
+            <dependency>
+               <groupId>org.junit.jupiter</groupId>
+               <artifactId>junit-jupiter-engine</artifactId>
+               <version>5.6.2</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <version>3.8.1</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-surefire-plugin</artifactId>
+                    <version>${surefire.version}</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-jar-plugin</artifactId>
+                    <version>3.2.0</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-failsafe-plugin</artifactId>
+                    <version>${surefire.version}</version>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+</project>
diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java b/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
index 7bbf986..5291a22 100644
--- a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
+++ b/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
@@ -17,9 +17,9 @@
  * under the License.
  */
 
-module wtf.g4s8.oot.test
+open module wtf.g4s8.oot.test
 {
     requires wtf.g4s8.oot;
-    requires org.junit.jupiter.api;
+    requires transitive org.junit.jupiter.engine;
     requires transitive org.hamcrest;
 }
diff --git a/surefire-its/src/test/resources/surefire-1733-junit4/pom.xml b/surefire-its/src/test/resources/surefire-1733-junit4/pom.xml
new file mode 100644
index 0000000..c309b7f
--- /dev/null
+++ b/surefire-its/src/test/resources/surefire-1733-junit4/pom.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.example</groupId>
+    <artifactId>surefire-1733-junit4</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <maven.compiler.release>${java.specification.version}</maven.compiler.release>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.13</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.hamcrest</groupId>
+                    <artifactId>hamcrest-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <version>2.2</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <version>3.8.1</version>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${surefire.version}</version>
+                <configuration>
+                    <test>MyTest</test>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <version>${surefire.version}</version>
+                <executions>
+                    <execution>
+                        <id>it</id>
+                        <phase>integration-test</phase>
+                        <goals>
+                            <goal>integration-test</goal>
+                        </goals>
+                        <configuration>
+                            <test>MyIT</test>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>verify</id>
+                        <phase>verify</phase>
+                        <goals>
+                            <goal>verify</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java b/surefire-its/src/test/resources/surefire-1733-junit4/src/main/java/main/Service.java
similarity index 86%
copy from surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
copy to surefire-its/src/test/resources/surefire-1733-junit4/src/main/java/main/Service.java
index 7bbf986..68592db 100644
--- a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
+++ b/surefire-its/src/test/resources/surefire-1733-junit4/src/main/java/main/Service.java
@@ -1,3 +1,5 @@
+package main;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -17,9 +19,9 @@
  * under the License.
  */
 
-module wtf.g4s8.oot.test
+/**
+ *
+ */
+public class Service
 {
-    requires wtf.g4s8.oot;
-    requires org.junit.jupiter.api;
-    requires transitive org.hamcrest;
 }
diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java b/surefire-its/src/test/resources/surefire-1733-junit4/src/main/java/module-info.java
similarity index 86%
copy from surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
copy to surefire-its/src/test/resources/surefire-1733-junit4/src/main/java/module-info.java
index 7bbf986..216ec8a 100644
--- a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
+++ b/surefire-its/src/test/resources/surefire-1733-junit4/src/main/java/module-info.java
@@ -17,9 +17,10 @@
  * under the License.
  */
 
-module wtf.g4s8.oot.test
+/**
+ *
+ */
+module main
 {
-    requires wtf.g4s8.oot;
-    requires org.junit.jupiter.api;
-    requires transitive org.hamcrest;
+    exports main;
 }
diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java b/surefire-its/src/test/resources/surefire-1733-junit4/src/test/java/module-info.java
similarity index 86%
copy from surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
copy to surefire-its/src/test/resources/surefire-1733-junit4/src/test/java/module-info.java
index 7bbf986..4334908 100644
--- a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
+++ b/surefire-its/src/test/resources/surefire-1733-junit4/src/test/java/module-info.java
@@ -17,9 +17,13 @@
  * under the License.
  */
 
-module wtf.g4s8.oot.test
+/**
+ *
+ */
+/*open*/ module test
 {
-    requires wtf.g4s8.oot;
-    requires org.junit.jupiter.api;
-    requires transitive org.hamcrest;
+    requires main;
+    requires junit;
+    requires org.hamcrest;
+    exports test to junit;
 }
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java b/surefire-its/src/test/resources/surefire-1733-junit4/src/test/java/test/MyIT.java
similarity index 55%
copy from maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
copy to surefire-its/src/test/resources/surefire-1733-junit4/src/test/java/test/MyIT.java
index fea74fd..3e3eb52 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
+++ b/surefire-its/src/test/resources/surefire-1733-junit4/src/test/java/test/MyIT.java
@@ -1,4 +1,4 @@
-package org.apache.maven.plugin.surefire;
+package test;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,24 +19,27 @@ package org.apache.maven.plugin.surefire;
  * under the License.
  */
 
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.plugin.MojoExecutionException;
+import main.Service;
+import org.junit.Test;
 
-import javax.annotation.Nonnull;
-import java.util.Set;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
 
 /**
- * @author Kristian Rosenvold
+ *
  */
-public interface ProviderInfo
+public class MyIT
 {
-    @Nonnull
-    String getProviderName();
-
-    boolean isApplicable();
-
-    @Nonnull
-    Set<Artifact> getProviderClasspath() throws MojoExecutionException;
+    @Test
+    public void test()
+    {
+        Service service = new Service();
+        String moduleName = service.getClass().getModule().getName();
+        System.out.println( service.getClass() + " in the module \"" + moduleName + "\"" );
+        assertThat( moduleName, is( "main" ) );
 
-    void addProviderProperties() throws MojoExecutionException;
+        moduleName = getClass().getModule().getName();
+        System.out.println( getClass() + " in the module \"" + moduleName + "\"" );
+        assertThat( moduleName, is( "test" ) );
+    }
 }
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java b/surefire-its/src/test/resources/surefire-1733-junit4/src/test/java/test/MyTest.java
similarity index 55%
copy from maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
copy to surefire-its/src/test/resources/surefire-1733-junit4/src/test/java/test/MyTest.java
index fea74fd..c839350 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
+++ b/surefire-its/src/test/resources/surefire-1733-junit4/src/test/java/test/MyTest.java
@@ -1,4 +1,4 @@
-package org.apache.maven.plugin.surefire;
+package test;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,24 +19,27 @@ package org.apache.maven.plugin.surefire;
  * under the License.
  */
 
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.plugin.MojoExecutionException;
+import main.Service;
+import org.junit.Test;
 
-import javax.annotation.Nonnull;
-import java.util.Set;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
 
 /**
- * @author Kristian Rosenvold
+ *
  */
-public interface ProviderInfo
+public class MyTest
 {
-    @Nonnull
-    String getProviderName();
-
-    boolean isApplicable();
-
-    @Nonnull
-    Set<Artifact> getProviderClasspath() throws MojoExecutionException;
+    @Test
+    public void test()
+    {
+        Service service = new Service();
+        String moduleName = service.getClass().getModule().getName();
+        System.out.println( service.getClass() + " in the module \"" + moduleName + "\"" );
+        assertThat( moduleName, is( "main" ) );
 
-    void addProviderProperties() throws MojoExecutionException;
+        moduleName = getClass().getModule().getName();
+        System.out.println( getClass() + " in the module \"" + moduleName + "\"" );
+        assertThat( moduleName, is( "test" ) );
+    }
 }
diff --git a/surefire-its/src/test/resources/surefire-1733-testng/pom.xml b/surefire-its/src/test/resources/surefire-1733-testng/pom.xml
new file mode 100644
index 0000000..630d09d
--- /dev/null
+++ b/surefire-its/src/test/resources/surefire-1733-testng/pom.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.example</groupId>
+    <artifactId>surefire-1733-testng</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <maven.compiler.release>${java.specification.version}</maven.compiler.release>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>7.1.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <version>2.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <version>3.16.1</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <version>3.8.1</version>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${surefire.version}</version>
+                <configuration>
+                    <test>MyTest</test>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <version>${surefire.version}</version>
+                <executions>
+                    <execution>
+                        <id>it</id>
+                        <phase>integration-test</phase>
+                        <goals>
+                            <goal>integration-test</goal>
+                        </goals>
+                        <configuration>
+                            <test>MyIT</test>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>verify</id>
+                        <phase>verify</phase>
+                        <goals>
+                            <goal>verify</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java b/surefire-its/src/test/resources/surefire-1733-testng/src/main/java/main/Service.java
similarity index 86%
copy from surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
copy to surefire-its/src/test/resources/surefire-1733-testng/src/main/java/main/Service.java
index 7bbf986..68592db 100644
--- a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
+++ b/surefire-its/src/test/resources/surefire-1733-testng/src/main/java/main/Service.java
@@ -1,3 +1,5 @@
+package main;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -17,9 +19,9 @@
  * under the License.
  */
 
-module wtf.g4s8.oot.test
+/**
+ *
+ */
+public class Service
 {
-    requires wtf.g4s8.oot;
-    requires org.junit.jupiter.api;
-    requires transitive org.hamcrest;
 }
diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java b/surefire-its/src/test/resources/surefire-1733-testng/src/main/java/module-info.java
similarity index 86%
copy from surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
copy to surefire-its/src/test/resources/surefire-1733-testng/src/main/java/module-info.java
index 7bbf986..216ec8a 100644
--- a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
+++ b/surefire-its/src/test/resources/surefire-1733-testng/src/main/java/module-info.java
@@ -17,9 +17,10 @@
  * under the License.
  */
 
-module wtf.g4s8.oot.test
+/**
+ *
+ */
+module main
 {
-    requires wtf.g4s8.oot;
-    requires org.junit.jupiter.api;
-    requires transitive org.hamcrest;
+    exports main;
 }
diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java b/surefire-its/src/test/resources/surefire-1733-testng/src/test/java/module-info.java
similarity index 83%
copy from surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
copy to surefire-its/src/test/resources/surefire-1733-testng/src/test/java/module-info.java
index 7bbf986..8b1ec9c 100644
--- a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java
+++ b/surefire-its/src/test/resources/surefire-1733-testng/src/test/java/module-info.java
@@ -17,9 +17,14 @@
  * under the License.
  */
 
-module wtf.g4s8.oot.test
+/**
+ *
+ */
+/*open*/ module test
 {
-    requires wtf.g4s8.oot;
-    requires org.junit.jupiter.api;
-    requires transitive org.hamcrest;
+    requires main;
+    requires org.testng;
+    requires org.hamcrest;
+    requires org.assertj.core;
+    exports test to org.testng;
 }
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java b/surefire-its/src/test/resources/surefire-1733-testng/src/test/java/test/MyIT.java
similarity index 55%
copy from maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
copy to surefire-its/src/test/resources/surefire-1733-testng/src/test/java/test/MyIT.java
index fea74fd..534672d 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
+++ b/surefire-its/src/test/resources/surefire-1733-testng/src/test/java/test/MyIT.java
@@ -1,4 +1,4 @@
-package org.apache.maven.plugin.surefire;
+package test;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,24 +19,27 @@ package org.apache.maven.plugin.surefire;
  * under the License.
  */
 
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.plugin.MojoExecutionException;
+import main.Service;
+import org.testng.annotations.Test;
 
-import javax.annotation.Nonnull;
-import java.util.Set;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
 
 /**
- * @author Kristian Rosenvold
+ *
  */
-public interface ProviderInfo
+public class MyIT
 {
-    @Nonnull
-    String getProviderName();
-
-    boolean isApplicable();
-
-    @Nonnull
-    Set<Artifact> getProviderClasspath() throws MojoExecutionException;
+    @Test
+    public void test()
+    {
+        Service service = new Service();
+        String moduleName = service.getClass().getModule().getName();
+        System.out.println( service.getClass() + " in the module \"" + moduleName + "\"" );
+        assertThat( moduleName, is( "main" ) );
 
-    void addProviderProperties() throws MojoExecutionException;
+        moduleName = getClass().getModule().getName();
+        System.out.println( getClass() + " in the module \"" + moduleName + "\"" );
+        assertThat( moduleName, is( "test" ) );
+    }
 }
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java b/surefire-its/src/test/resources/surefire-1733-testng/src/test/java/test/MyTest.java
similarity index 54%
copy from maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
copy to surefire-its/src/test/resources/surefire-1733-testng/src/test/java/test/MyTest.java
index fea74fd..c13d1f1 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
+++ b/surefire-its/src/test/resources/surefire-1733-testng/src/test/java/test/MyTest.java
@@ -1,4 +1,4 @@
-package org.apache.maven.plugin.surefire;
+package test;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,24 +19,28 @@ package org.apache.maven.plugin.surefire;
  * under the License.
  */
 
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.plugin.MojoExecutionException;
+import main.Service;
+import org.testng.annotations.Test;
 
-import javax.annotation.Nonnull;
-import java.util.Set;
+import static org.assertj.core.api.Assertions.assertThat;
 
 /**
- * @author Kristian Rosenvold
+ *
  */
-public interface ProviderInfo
+public class MyTest
 {
-    @Nonnull
-    String getProviderName();
-
-    boolean isApplicable();
-
-    @Nonnull
-    Set<Artifact> getProviderClasspath() throws MojoExecutionException;
+    @Test
+    public void test()
+    {
+        Service service = new Service();
+        String moduleName = service.getClass().getModule().getName();
+        System.out.println( service.getClass() + " in the module \"" + moduleName + "\"" );
+        assertThat( moduleName )
+                .isEqualTo( "main" );
 
-    void addProviderProperties() throws MojoExecutionException;
+        moduleName = getClass().getModule().getName();
+        System.out.println( getClass() + " in the module \"" + moduleName + "\"" );
+        assertThat( moduleName )
+                .isEqualTo( "test" );
+    }
 }


[maven-surefire] 02/02: [GH] Workflows j14

Posted by ti...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

tibordigana pushed a commit to branch SUREFIRE-1733
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git

commit 070bcd763e0639e325db6c5101fa0080627d2d49
Author: tibordigana <ti...@apache.org>
AuthorDate: Fri May 22 11:59:14 2020 +0200

    [GH] Workflows j14
---
 .github/workflows/maven.yml     | 4 ++--
 .github/workflows/smoketest.yml | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 7139801..1cfd2e3 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -33,10 +33,10 @@ jobs:
       - name: Checkout
         uses: actions/checkout@v1
 
-      - name: Set up JDK 11
+      - name: Set up JDK 14
         uses: actions/setup-java@v1
         with:
-          java-version: 11
+          java-version: 14
 
       - name: Build with Maven
         run: mvn install -e -B -V -nsu --no-transfer-progress -P run-its
diff --git a/.github/workflows/smoketest.yml b/.github/workflows/smoketest.yml
index 3377cc5..7500579 100644
--- a/.github/workflows/smoketest.yml
+++ b/.github/workflows/smoketest.yml
@@ -27,10 +27,10 @@ jobs:
       - name: Checkout
         uses: actions/checkout@v1
 
-      - name: Set up JDK 11
+      - name: Set up JDK 14
         uses: actions/setup-java@v1
         with:
-          java-version: 11
+          java-version: 14
 
       - name: Build with Maven
         run: mvn install -e -B -V -nsu --no-transfer-progress -P run-its -DskipITs