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/16 01:00:09 UTC

[maven-surefire] branch SUREFIRE-1570 updated (0dc817c -> 8707187)

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

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


 discard 0dc817c  unit tests
     new 8707187  unit tests

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   (0dc817c)
            \
             N -- N -- N   refs/heads/SUREFIRE-1570 (8707187)

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 1 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:
 .../java/org/apache/maven/plugin/surefire/AbstractSurefireMojoTest.java  | 1 +
 1 file changed, 1 insertion(+)


[maven-surefire] 01/01: unit tests

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

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

commit 8707187b69bd34d0af944b64e0566b1a7aec5a2a
Author: tibordigana <ti...@apache.org>
AuthorDate: Sat May 16 02:53:45 2020 +0200

    unit tests
---
 .../plugin/surefire/AbstractSurefireMojo.java      |  46 ++---
 .../maven/plugin/surefire/JdkAttributes.java       |  21 ++-
 ...tributes.java => ResolvePathResultWrapper.java} |  28 +--
 .../booterclient/DefaultForkConfiguration.java     |   2 +-
 .../plugin/surefire/booterclient/Platform.java     |   2 +-
 .../plugin/surefire/AbstractSurefireMojoTest.java  | 210 ++++++++++++++++++++-
 .../AbstractSurefireMojoToolchainsTest.java        |  22 ++-
 .../apache/maven/plugin/surefire/module-info.class | Bin 0 -> 149 bytes
 8 files changed, 275 insertions(+), 56 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 9790371..490c6da 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
@@ -103,7 +103,6 @@ import java.io.IOException;
 import java.lang.reflect.Method;
 import java.math.BigDecimal;
 import java.nio.file.Files;
-import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -1379,29 +1378,29 @@ public abstract class AbstractSurefireMojo
         this.dependencyResolver = dependencyResolver;
     }
 
-    private boolean existsModuleDescriptor()
+    private boolean existsModuleDescriptor( File jdkHome )
     {
-        return getModuleDescriptor() != null;
+        return findModuleDescriptor( jdkHome ).getResolvePathResult() != null;
     }
 
-    private ResolvePathResult getModuleDescriptor()
+    private ResolvePathResultWrapper findModuleDescriptor( File jdkHome )
     {
         File mainBuildPath = getMainBuildPath();
 
         if ( mainBuildPath.isDirectory() && !new File( mainBuildPath, "module-info.class" ).exists() )
         {
-            return null;
+            return new ResolvePathResultWrapper( null, true );
         }
 
         try
         {
-            // .setJdkHome(  )
-            ResolvePathResult result = getLocationManager().resolvePath( ResolvePathRequest.ofFile( mainBuildPath ) );
-            return result.getModuleNameSource() == null ? null : result;
+            ResolvePathRequest<?> request = ResolvePathRequest.ofFile( mainBuildPath ).setJdkHome( jdkHome );
+            ResolvePathResult result = getLocationManager().resolvePath( request );
+            return new ResolvePathResultWrapper( result.getModuleNameSource() == null ? null : result, true );
         }
         catch ( Exception e )
         {
-            return null;
+            return new ResolvePathResultWrapper( null, true );
         }
     }
 
@@ -1409,7 +1408,7 @@ public abstract class AbstractSurefireMojo
     {
         return useModulePath()
                 && platform.getJdkExecAttributesForTests().isJava9AtLeast()
-                && existsModuleDescriptor();
+                && existsModuleDescriptor( platform.getJdkExecAttributesForTests().getJdkHome() );
     }
 
     /**
@@ -1875,16 +1874,12 @@ public abstract class AbstractSurefireMojo
             String providerName = provider.getProviderName();
             if ( isForking && canExecuteProviderWithModularPath( platform ) )
             {
-                String jvmExecutable = platform.getJdkExecAttributesForTests().getJvmExecutable();
-                String javaHome = Paths.get( jvmExecutable )
-                        .toAbsolutePath()
-                        .normalize()
-                        .getParent()
-                        .getParent()
-                        .toString();
+                JdkAttributes jdkAttributes = platform.getJdkExecAttributesForTests();
+                File jdkHome = jdkAttributes.getJdkHome();
+                ResolvePathResult resolvePathResult = findModuleDescriptor( jdkHome ).getResolvePathResult();
 
                 return newStartupConfigWithModularPath( classLoaderConfiguration, providerArtifacts, providerName,
-                        getModuleDescriptor(), scanResult, javaHome, testClasspathWrapper );
+                        resolvePathResult, scanResult, jdkHome.getAbsolutePath(), testClasspathWrapper );
             }
             else
             {
@@ -2551,13 +2546,17 @@ public abstract class AbstractSurefireMojo
             }
 
             File jdkHome = toJdkHomeFromJvmExec( pathToJava.getPath() );
-            if ( !environmentVariables.containsKey( "JAVA_HOME" ) )
+            if ( jdkHome == null )
+            {
+                getConsoleLogger().warning( "Cannot determine JAVA_HOME of jvm exec path " + pathToJava );
+            }
+            else if ( !environmentVariables.containsKey( "JAVA_HOME" ) )
             {
                 environmentVariables.put( "JAVA_HOME", jdkHome.getAbsolutePath() );
             }
             BigDecimal version = jdkHome == null ? null : toJdkVersionFromReleaseFile( jdkHome );
             boolean javaVersion9 = version == null ? isJava9AtLeast( pathToJava.getPath() ) : isJava9AtLeast( version );
-            return new JdkAttributes( pathToJava.getPath(), javaVersion9 );
+            return new JdkAttributes( pathToJava, jdkHome, javaVersion9 );
         }
 
         if ( toolchain != null )
@@ -2566,6 +2565,7 @@ public abstract class AbstractSurefireMojo
             if ( isNotEmpty( jvmToUse ) )
             {
                 boolean javaVersion9 = false;
+                String jdkHome = null;
 
                 if ( toolchain instanceof DefaultToolchain )
                 {
@@ -2579,7 +2579,8 @@ public abstract class AbstractSurefireMojo
                     DefaultJavaToolChain defaultJavaToolChain = (DefaultJavaToolChain) toolchain;
                     if ( !environmentVariables.containsKey( "JAVA_HOME" ) )
                     {
-                        environmentVariables.put( "JAVA_HOME", defaultJavaToolChain.getJavaHome() );
+                        jdkHome = defaultJavaToolChain.getJavaHome();
+                        environmentVariables.put( "JAVA_HOME", jdkHome );
                     }
                 }
 
@@ -2588,7 +2589,8 @@ public abstract class AbstractSurefireMojo
                     javaVersion9 = isJava9AtLeast( jvmToUse );
                 }
 
-                return new JdkAttributes( jvmToUse, javaVersion9 );
+                return new JdkAttributes( new File( jvmToUse ),
+                    jdkHome == null ? toJdkHomeFromJvmExec( jvmToUse ) : new File( jdkHome ), javaVersion9 );
             }
         }
 
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/JdkAttributes.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/JdkAttributes.java
index 96049a5..f8ab5f7 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/JdkAttributes.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/JdkAttributes.java
@@ -19,7 +19,10 @@ package org.apache.maven.plugin.surefire;
  * under the License.
  */
 
+import java.io.File;
+
 import static java.util.Objects.requireNonNull;
+import static org.apache.maven.surefire.booter.SystemUtils.toJdkHomeFromJvmExec;
 
 /**
  * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
@@ -27,20 +30,32 @@ import static java.util.Objects.requireNonNull;
  */
 public final class JdkAttributes
 {
-    private final String jvmExecutable;
+    private final File jvmExecutable;
+    private final File jdkHome;
     private final boolean java9AtLeast;
 
-    public JdkAttributes( String jvmExecutable, boolean java9AtLeast )
+    public JdkAttributes( File jvmExecutable, File jdkHome, boolean java9AtLeast )
     {
         this.jvmExecutable = requireNonNull( jvmExecutable, "null path to java executable" );
+        this.jdkHome = jdkHome;
         this.java9AtLeast = java9AtLeast;
     }
 
-    public String getJvmExecutable()
+    public JdkAttributes( String jvmExecutable, boolean java9AtLeast )
+    {
+        this( new File( jvmExecutable ), toJdkHomeFromJvmExec( jvmExecutable ), java9AtLeast );
+    }
+
+    public File getJvmExecutable()
     {
         return jvmExecutable;
     }
 
+    public File getJdkHome()
+    {
+        return jdkHome;
+    }
+
     public boolean isJava9AtLeast()
     {
         return java9AtLeast;
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/JdkAttributes.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ResolvePathResultWrapper.java
similarity index 55%
copy from maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/JdkAttributes.java
copy to maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ResolvePathResultWrapper.java
index 96049a5..9197d89 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/JdkAttributes.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ResolvePathResultWrapper.java
@@ -19,30 +19,32 @@ package org.apache.maven.plugin.surefire;
  * under the License.
  */
 
-import static java.util.Objects.requireNonNull;
+import org.codehaus.plexus.languages.java.jpms.ResolvePathResult;
 
 /**
- * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
- * @since 2.20.1
+ * Wraps {@link ResolvePathResult} and place marker.
  */
-public final class JdkAttributes
+final class ResolvePathResultWrapper
 {
-    private final String jvmExecutable;
-    private final boolean java9AtLeast;
+    private final ResolvePathResult resolvePathResult;
+    private final boolean isMainModuleDescriptor;
 
-    public JdkAttributes( String jvmExecutable, boolean java9AtLeast )
+    ResolvePathResultWrapper( ResolvePathResult resolvePathResult, boolean isMainModuleDescriptor )
     {
-        this.jvmExecutable = requireNonNull( jvmExecutable, "null path to java executable" );
-        this.java9AtLeast = java9AtLeast;
+        this.resolvePathResult = resolvePathResult;
+        this.isMainModuleDescriptor = isMainModuleDescriptor;
     }
 
-    public String getJvmExecutable()
+    ResolvePathResult getResolvePathResult()
     {
-        return jvmExecutable;
+        return resolvePathResult;
     }
 
-    public boolean isJava9AtLeast()
+    /**
+     * @return {@code true} if module-info appears in src/main/java module
+     */
+    boolean isMainModuleDescriptor()
     {
-        return java9AtLeast;
+        return isMainModuleDescriptor;
     }
 }
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 443bf45..af09d67 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
@@ -144,7 +144,7 @@ public abstract class DefaultForkConfiguration
             cli.addEnvironment( entry.getKey(), value == null ? "" : value );
         }
 
-        cli.setExecutable( getJdkForTests().getJvmExecutable() );
+        cli.setExecutable( getJdkForTests().getJvmExecutable().getAbsolutePath() );
 
         String jvmArgLine = newJvmArgLine( forkNumber );
         if ( !jvmArgLine.isEmpty() )
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/Platform.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/Platform.java
index 074a3cb..14196f8 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/Platform.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/Platform.java
@@ -38,7 +38,7 @@ public final class Platform
 {
     private final RunnableFuture<Long> pluginPidJob;
 
-    private volatile JdkAttributes jdk;
+    private final JdkAttributes jdk;
 
     public Platform()
     {
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 3d366aa..bbef6e2 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
@@ -33,6 +33,7 @@ import org.apache.maven.model.Plugin;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
 import org.apache.maven.plugin.surefire.AbstractSurefireMojo.JUnitPlatformProviderInfo;
+import org.apache.maven.plugin.surefire.booterclient.Platform;
 import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.ProjectBuildingRequest;
@@ -43,15 +44,22 @@ import org.apache.maven.shared.transfer.dependencies.DependableCoordinate;
 import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver;
 import org.apache.maven.surefire.booter.ClassLoaderConfiguration;
 import org.apache.maven.surefire.booter.Classpath;
+import org.apache.maven.surefire.booter.ModularClasspathConfiguration;
 import org.apache.maven.surefire.booter.StartupConfiguration;
 import org.apache.maven.surefire.extensions.ForkNodeFactory;
 import org.apache.maven.surefire.suite.RunResult;
+import org.apache.maven.surefire.util.DefaultScanResult;
 import org.apache.maven.toolchain.Toolchain;
+import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor;
+import org.codehaus.plexus.languages.java.jpms.LocationManager;
+import org.codehaus.plexus.languages.java.jpms.ResolvePathRequest;
+import org.codehaus.plexus.languages.java.jpms.ResolvePathResult;
 import org.codehaus.plexus.logging.Logger;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
@@ -63,6 +71,8 @@ import org.powermock.modules.junit4.PowerMockRunner;
 
 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.Collection;
 import java.util.Collections;
@@ -75,21 +85,25 @@ import java.util.Map;
 import java.util.Set;
 
 import static java.io.File.separatorChar;
+import static java.nio.file.Files.write;
 import static java.util.Arrays.asList;
 import static java.util.Collections.emptySet;
 import static java.util.Collections.singleton;
 import static java.util.Collections.singletonList;
-import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_WINDOWS;
 import static org.apache.maven.artifact.versioning.VersionRange.createFromVersion;
 import static org.apache.maven.artifact.versioning.VersionRange.createFromVersionSpec;
+import static org.apache.maven.surefire.shared.lang3.JavaVersion.JAVA_9;
+import static org.apache.maven.surefire.shared.lang3.JavaVersion.JAVA_RECENT;
+import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_WINDOWS;
+import static org.codehaus.plexus.languages.java.jpms.ModuleNameSource.MODULEDESCRIPTOR;
 import static org.fest.assertions.Assertions.assertThat;
 import static org.fest.assertions.MapAssert.entry;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 import static org.powermock.api.mockito.PowerMockito.doNothing;
 import static org.powermock.api.mockito.PowerMockito.doReturn;
 import static org.powermock.api.mockito.PowerMockito.mock;
@@ -109,6 +123,9 @@ public class AbstractSurefireMojoTest
     @Rule
     public final ExpectedException e = ExpectedException.none();
 
+    @Rule
+    public final TemporaryFolder tempFolder = new TemporaryFolder();
+
     @Mock
     private ArtifactHandler handler;
 
@@ -140,6 +157,119 @@ public class AbstractSurefireMojoTest
     }
 
     @Test
+    public void noModuleDescriptorFile() throws Exception
+    {
+        AbstractSurefireMojo mojo = spy( new Mojo() );
+        mojo.setMainBuildPath( tempFolder.newFolder() );
+        File jdkHome = new File( System.getProperty( "java.home" ) );
+        ResolvePathResultWrapper wrapper = invokeMethod( mojo, "findModuleDescriptor", jdkHome );
+
+        assertThat( wrapper )
+            .isNotNull();
+
+        assertThat( wrapper.getResolvePathResult() )
+            .isNull();
+
+        assertThat( invokeMethod( mojo, "existsModuleDescriptor", jdkHome ) )
+            .isEqualTo( false );
+
+        when( mojo.useModulePath() ).thenReturn( true );
+
+        File jvmExecutable = new File( jdkHome, IS_OS_WINDOWS ? "bin\\java.exe" : "bin/java" );
+        JdkAttributes jdkAttributes = new JdkAttributes( jvmExecutable, jdkHome, true );
+        Platform platform = new Platform().withJdkExecAttributesForTests( jdkAttributes );
+        assertThat( invokeMethod( mojo, "canExecuteProviderWithModularPath", platform ) )
+            .isEqualTo( false );
+    }
+
+    @Test
+    public void correctModuleDescriptor() throws Exception
+    {
+        AbstractSurefireMojo mojo = spy( new Mojo() );
+        LocationManager locationManager = mock( LocationManager.class );
+        ResolvePathResult result = mock( ResolvePathResult.class );
+        when( result.getModuleNameSource() ).thenReturn( MODULEDESCRIPTOR );
+        JavaModuleDescriptor descriptor = mock( JavaModuleDescriptor.class );
+        when( result.getModuleDescriptor() ).thenReturn( descriptor );
+        when( locationManager.resolvePath( any( ResolvePathRequest.class ) ) ).thenReturn( result );
+        doReturn( locationManager )
+            .when( mojo, "getLocationManager" );
+        File classesDir = tempFolder.newFolder();
+        mojo.setMainBuildPath( classesDir );
+        File descriptorFile = new File( classesDir, "module-info.class" );
+        assertThat( descriptorFile.createNewFile() ).isTrue();
+        File jdkHome = new File( System.getProperty( "java.home" ) );
+        ResolvePathResultWrapper wrapper = invokeMethod( mojo, "findModuleDescriptor", jdkHome );
+
+        assertThat( wrapper )
+            .isNotNull();
+
+        assertThat( wrapper.getResolvePathResult() )
+            .isSameAs( result );
+
+        assertThat( wrapper.getResolvePathResult().getModuleNameSource() )
+            .isSameAs( MODULEDESCRIPTOR );
+
+        assertThat( wrapper.getResolvePathResult().getModuleDescriptor() )
+            .isSameAs( descriptor );
+
+        assertThat( invokeMethod( mojo, "existsModuleDescriptor", jdkHome ) )
+            .isEqualTo( true );
+
+        when( mojo.useModulePath() ).thenReturn( true );
+
+        File jvmExecutable = new File( jdkHome, IS_OS_WINDOWS ? "bin\\java.exe" : "bin/java" );
+        JdkAttributes jdkAttributes = new JdkAttributes( jvmExecutable, jdkHome, true );
+        Platform platform = new Platform().withJdkExecAttributesForTests( jdkAttributes );
+        assertThat( invokeMethod( mojo, "canExecuteProviderWithModularPath", platform ) )
+            .isEqualTo( true );
+
+        jdkAttributes = new JdkAttributes( jvmExecutable, jdkHome, false );
+        platform = new Platform().withJdkExecAttributesForTests( jdkAttributes );
+        assertThat( invokeMethod( mojo, "canExecuteProviderWithModularPath", platform ) )
+            .isEqualTo( false );
+
+        when( mojo.useModulePath() ).thenReturn( false );
+
+        jdkAttributes = new JdkAttributes( jvmExecutable, jdkHome, true );
+        platform = new Platform().withJdkExecAttributesForTests( jdkAttributes );
+        assertThat( invokeMethod( mojo, "canExecuteProviderWithModularPath", platform ) )
+            .isEqualTo( false );
+    }
+
+    @Test
+    @SuppressWarnings( "checkstyle:magicnumber" )
+    public void corruptedModuleDescriptor() throws Exception
+    {
+        if ( !JAVA_RECENT.atLeast( JAVA_9 ) )
+        {
+            return;
+        }
+
+        AbstractSurefireMojo mojo = spy( new Mojo() );
+        doReturn( new LocationManager() )
+            .when( mojo, "getLocationManager" );
+        File classesDir = tempFolder.newFolder();
+        mojo.setMainBuildPath( classesDir );
+
+        File descriptorFile = new File( classesDir, "module-info.class" );
+        assertThat( descriptorFile.createNewFile() ).isTrue();
+        write( descriptorFile.toPath(), new byte[]{(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE} );
+
+        File jdkHome = new File( System.getProperty( "java.home" ) );
+        ResolvePathResultWrapper wrapper = invokeMethod( mojo, "findModuleDescriptor", jdkHome );
+
+        assertThat( wrapper )
+            .isNotNull();
+
+        assertThat( wrapper.getResolvePathResult() )
+            .isNull();
+
+        assertThat( invokeMethod( mojo, "existsModuleDescriptor", jdkHome ) )
+            .isEqualTo( false );
+    }
+
+    @Test
     public void shouldShowArray() throws Exception
     {
         Logger logger = mock( Logger.class );
@@ -512,6 +642,71 @@ public class AbstractSurefireMojoTest
     }
 
     @Test
+    public void shouldCreateStartupConfigWithModularPath() throws Exception
+    {
+        String baseDir = System.getProperty( "user.dir" );
+
+        /*if ( !JAVA_RECENT.atLeast( JAVA_9 ) )
+        {
+            return;
+        }*/
+
+        Mojo mojo = new Mojo();
+
+        // ### BEGIN
+        // we cannot mock private method newStartupConfigWithModularPath() - mocking the data to prevent from errors
+        mojo.setLogger( mock( Logger.class ) );
+        mojo.setUseModulePath( true );
+        setInternalState( mojo, "locationManager", new LocationManager() );
+
+        File jdkHome = new File( System.getProperty( "java.home" ) );
+        File jvmExecutable = new File( jdkHome, IS_OS_WINDOWS ? "bin\\java.exe" : "bin/java" );
+        JdkAttributes jdkAttributes = new JdkAttributes( jvmExecutable, jdkHome, true );
+        Platform platform = new Platform().withJdkExecAttributesForTests( jdkAttributes );
+
+        File classesDirectory = new File( baseDir, "mock-dir" );
+        File testClassesDirectory = new File( baseDir, "mock-dir" );
+        TestClassPath testClassPath = new TestClassPath( Collections.<Artifact>emptySet(),
+            classesDirectory, testClassesDirectory, new String[0] );
+
+        ProviderInfo providerInfo = mock( ProviderInfo.class );
+        when( providerInfo.getProviderName() ).thenReturn( "provider mock" );
+        when( providerInfo.getProviderClasspath() ).thenReturn( Collections.<Artifact>emptySet() );
+
+        DefaultScanResult defaultScanResult = mock( DefaultScanResult.class );
+        when( defaultScanResult.getClasses() ).thenReturn( Collections.<String>emptyList() );
+
+        Path pathToModularDescriptor =
+            Paths.get( baseDir, "src", "test", "resources", "org", "apache", "maven", "plugin", "surefire" );
+        mojo.setMainBuildPath( pathToModularDescriptor.toFile() );
+
+        Map<String, Artifact> artifacts = new HashMap<>();
+        Artifact dummyArtifact = mock( Artifact.class );
+        when( dummyArtifact.getFile() ).thenReturn( new File( baseDir, "mock-file" ) );
+        artifacts.put( "org.apache.maven.surefire:maven-surefire-common", dummyArtifact );
+        artifacts.put( "org.apache.maven.surefire:surefire-extensions-api", dummyArtifact );
+        artifacts.put( "org.apache.maven.surefire:surefire-api", dummyArtifact );
+        artifacts.put( "org.apache.maven.surefire:surefire-logger-api", dummyArtifact );
+        artifacts.put( "org.apache.maven.surefire:surefire-extensions-spi", dummyArtifact );
+        artifacts.put( "org.apache.maven.surefire:surefire-booter", dummyArtifact );
+        artifacts.put( "org.apache.maven.surefire:surefire-shared-utils", dummyArtifact );
+        mojo.setPluginArtifactMap( artifacts );
+        // ### END
+
+        StartupConfiguration actualConfig = invokeMethod( mojo, "createStartupConfiguration",
+            new Class[] {ProviderInfo.class, boolean.class, ClassLoaderConfiguration.class, DefaultScanResult.class,
+                Platform.class, TestClassPath.class},
+            providerInfo, true, mock( ClassLoaderConfiguration.class ), defaultScanResult,
+            platform, testClassPath );
+
+        assertThat( actualConfig )
+            .isNotNull();
+
+        assertThat( actualConfig.getClasspathConfiguration() )
+            .isInstanceOf( ModularClasspathConfiguration.class );
+    }
+
+    @Test
     public void shouldExistTmpDirectory() throws IOException
     {
         String systemTmpDir = System.getProperty( "java.io.tmpdir" );
@@ -1804,6 +1999,9 @@ public class AbstractSurefireMojoTest
     public static class Mojo
             extends AbstractSurefireMojo implements SurefireReportParameters
     {
+        private File mainBuildPath;
+        private boolean useModulePath;
+
         private JUnitPlatformProviderInfo createJUnitPlatformProviderInfo( Artifact junitPlatformArtifact,
                                                                            TestClassPath testClasspathWrapper )
         {
@@ -1903,13 +2101,13 @@ public class AbstractSurefireMojoTest
         @Override
         public File getMainBuildPath()
         {
-            return null;
+            return mainBuildPath;
         }
 
         @Override
         public void setMainBuildPath( File mainBuildPath )
         {
-
+            this.mainBuildPath = mainBuildPath;
         }
 
         @Override
@@ -2185,13 +2383,13 @@ public class AbstractSurefireMojoTest
         @Override
         protected boolean useModulePath()
         {
-            return false;
+            return useModulePath;
         }
 
         @Override
         protected void setUseModulePath( boolean useModulePath )
         {
-
+            this.useModulePath = useModulePath;
         }
 
         @Override
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoToolchainsTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoToolchainsTest.java
index 64437fb..ddcb169 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoToolchainsTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoToolchainsTest.java
@@ -37,6 +37,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
+import static java.io.File.separatorChar;
 import static java.util.Collections.emptyMap;
 import static java.util.Collections.singletonList;
 import static java.util.Collections.singletonMap;
@@ -155,7 +156,8 @@ public class AbstractSurefireMojoToolchainsTest
         assertThat( mojo.getEnvironmentVariables() ).isEmpty();
         JdkAttributes effectiveJvm = invokeMethod( mojo, "getEffectiveJvm" );
         assertThat( mojo.getEnvironmentVariables() ).includes( MapAssert.entry( "JAVA_HOME", "/some/path" ) );
-        assertThat( effectiveJvm.getJvmExecutable() ).contains( "/path/from/toolchain" );
+        assertThat( effectiveJvm.getJvmExecutable().getPath() )
+            .contains( "/path/from/toolchain".replace( '/', separatorChar ) );
     }
 
     @Test
@@ -171,7 +173,8 @@ public class AbstractSurefireMojoToolchainsTest
 
         JdkAttributes effectiveJvm = invokeMethod( mojo, "getEffectiveJvm" );
         assertThat( mojo.getEnvironmentVariables() ).includes( MapAssert.entry( "JAVA_HOME", "/already/set/path" ) );
-        assertThat( effectiveJvm.getJvmExecutable() ).contains( "/path/from/toolchain" );
+        assertThat( effectiveJvm.getJvmExecutable().getPath() )
+            .contains( "/path/from/toolchain".replace( '/', separatorChar ) );
     }
 
     /**
@@ -191,9 +194,9 @@ public class AbstractSurefireMojoToolchainsTest
 
         assertThat( mojo.getEnvironmentVariables() ).isEmpty();
         JdkAttributes effectiveJvm = invokeMethod( mojo, "getEffectiveJvm" );
-        assertThat( mojo.getEnvironmentVariables() ).
-            includes( MapAssert.entry( "JAVA_HOME", currentJdkHome.getAbsolutePath() ) );
-        assertThat( effectiveJvm.getJvmExecutable() ).contains( javaExecutablePath );
+        assertThat( mojo.getEnvironmentVariables() )
+            .includes( MapAssert.entry( "JAVA_HOME", currentJdkHome.getAbsolutePath() ) );
+        assertThat( effectiveJvm.getJvmExecutable().getPath() ).contains( javaExecutablePath );
     }
 
     /**
@@ -207,15 +210,14 @@ public class AbstractSurefireMojoToolchainsTest
         mojo.setEnvironmentVariables( singletonMap( "JAVA_HOME", "/already/set/path" ) );
 
         File currentJdkHome = toJdkHomeFromJre();
-        String javaExecutablePath = FilenameUtils.concat(
-            currentJdkHome.getAbsolutePath(), "bin/java" );
+        String javaExecutablePath = FilenameUtils.concat( currentJdkHome.getAbsolutePath(), "bin/java" );
 
         mojo.setJvm( javaExecutablePath );
 
         JdkAttributes effectiveJvm = invokeMethod( mojo, "getEffectiveJvm" );
-        assertThat( mojo.getEnvironmentVariables() ).
-            includes( MapAssert.entry( "JAVA_HOME", "/already/set/path" ) );
-        assertThat( effectiveJvm.getJvmExecutable() ).contains( javaExecutablePath );
+        assertThat( mojo.getEnvironmentVariables() )
+            .includes( MapAssert.entry( "JAVA_HOME", "/already/set/path" ) );
+        assertThat( effectiveJvm.getJvmExecutable().getPath() ).contains( javaExecutablePath );
     }
 
 
diff --git a/maven-surefire-common/src/test/resources/org/apache/maven/plugin/surefire/module-info.class b/maven-surefire-common/src/test/resources/org/apache/maven/plugin/surefire/module-info.class
new file mode 100644
index 0000000..51e6dcd
Binary files /dev/null and b/maven-surefire-common/src/test/resources/org/apache/maven/plugin/surefire/module-info.class differ