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 2019/02/04 22:27:26 UTC

[maven-surefire] branch SUREFIRE-1585-tibor2 updated (cb00ee2 -> afdc189)

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

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


 discard cb00ee2  [SUREFIRE-1585] Align JUnit Platform version at runtime
     new afdc189  [SUREFIRE-1585] Align JUnit Platform version at runtime

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   (cb00ee2)
            \
             N -- N -- N   refs/heads/SUREFIRE-1585-tibor2 (afdc189)

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:
 .../plugin/surefire/AbstractSurefireMojo.java      | 37 ++++++++++++++++++----
 .../surefire/SurefireDependencyResolver.java       | 34 ++++++++++----------
 .../maven/plugin/surefire/TestClassPath.java       | 26 ---------------
 .../surefire/SurefireDependencyResolverTest.java   |  8 ++---
 4 files changed, 50 insertions(+), 55 deletions(-)


[maven-surefire] 01/01: [SUREFIRE-1585] Align JUnit Platform version at runtime

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

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

commit afdc1896ddbb8f91357c2bacc2864b83d2142d92
Author: tibordigana <ti...@apache.org>
AuthorDate: Fri Feb 1 06:03:27 2019 +0100

    [SUREFIRE-1585] Align JUnit Platform version at runtime
---
 .../plugin/surefire/AbstractSurefireMojo.java      | 194 +++++++++++++++++----
 .../surefire/SurefireDependencyResolver.java       |  51 ++++--
 .../maven/plugin/surefire/TestClassPath.java       |  34 +---
 .../AbstractSurefireMojoJava7PlusTest.java         |   5 +-
 .../plugin/surefire/AbstractSurefireMojoTest.java  |   5 +-
 .../surefire/SurefireDependencyResolverTest.java   |   8 +-
 .../maven/surefire/its/JUnitPlatformEnginesIT.java |   8 +-
 7 files changed, 211 insertions(+), 94 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 7c76ef1..f2a4a91 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
@@ -21,6 +21,8 @@ package org.apache.maven.plugin.surefire;
  */
 
 import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
+import org.apache.maven.artifact.handler.ArtifactHandler;
 import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.plugins.annotations.Component;
 import org.apache.maven.repository.RepositorySystem;
@@ -663,6 +665,9 @@ public abstract class AbstractSurefireMojo
     @Parameter( defaultValue = "${project.pluginArtifactRepositories}", readonly = true, required = true )
     private List<ArtifactRepository> remoteRepositories;
 
+    @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true )
+    private List<ArtifactRepository> projectRemoteRepositories;
+
     /**
      * Flag to disable the generation of report files in xml format.
      *
@@ -983,7 +988,8 @@ public abstract class AbstractSurefireMojo
     private void executeAfterPreconditionsChecked( @Nonnull DefaultScanResult scanResult )
         throws MojoExecutionException, MojoFailureException
     {
-        List<ProviderInfo> providers = createProviders();
+        TestClassPath testClasspathWrapper = generateTestClasspath();
+        List<ProviderInfo> providers = createProviders( testClasspathWrapper );
 
         RunResult current = noTestsRun();
 
@@ -992,7 +998,7 @@ public abstract class AbstractSurefireMojo
         {
             try
             {
-                current = current.aggregate( executeProvider( provider, scanResult ) );
+                current = current.aggregate( executeProvider( provider, scanResult, testClasspathWrapper ) );
             }
             catch ( SurefireBooterForkException | SurefireExecutionException | TestSetFailedException e )
             {
@@ -1016,16 +1022,17 @@ public abstract class AbstractSurefireMojo
         dependencyResolver = new SurefireDependencyResolver( getRepositorySystem(),
                                                                    getConsoleLogger(), getLocalRepository(),
                                                                    getRemoteRepositories(),
+                                                                   getProjectRemoteRepositories(),
                                                                    getPluginName() );
     }
 
-    protected List<ProviderInfo> createProviders()
+    protected List<ProviderInfo> createProviders( TestClassPath testClasspathWrapper )
         throws MojoExecutionException
     {
         Artifact junitDepArtifact = getJunitDepArtifact();
         return new ProviderList( new DynamicProviderInfo( null ),
                               new TestNgProviderInfo( getTestNgArtifact() ),
-                              new JUnitPlatformProviderInfo( getJunitPlatformArtifact() ),
+                              new JUnitPlatformProviderInfo( getJunitPlatformArtifact(), testClasspathWrapper ),
                               new JUnitCoreProviderInfo( getJunitArtifact(), junitDepArtifact ),
                               new JUnit4ProviderInfo( getJunitArtifact(), junitDepArtifact ),
                               new JUnit3ProviderInfo() )
@@ -1117,7 +1124,8 @@ public abstract class AbstractSurefireMojo
     }
 
     @Nonnull
-    private RunResult executeProvider( @Nonnull ProviderInfo provider, @Nonnull DefaultScanResult scanResult )
+    private RunResult executeProvider( @Nonnull ProviderInfo provider, @Nonnull DefaultScanResult scanResult,
+                                       @Nonnull TestClassPath testClasspathWrapper )
         throws MojoExecutionException, MojoFailureException, SurefireExecutionException, SurefireBooterForkException,
         TestSetFailedException
     {
@@ -1132,8 +1140,8 @@ public abstract class AbstractSurefireMojo
         {
             createCopyAndReplaceForkNumPlaceholder( effectiveProperties, 1 ).copyToSystemProperties();
 
-            InPluginVMSurefireStarter surefireStarter =
-                createInprocessStarter( provider, classLoaderConfiguration, runOrderParameters, scanResult, platform );
+            InPluginVMSurefireStarter surefireStarter = createInprocessStarter( provider, classLoaderConfiguration,
+                    runOrderParameters, scanResult, platform, testClasspathWrapper );
             return surefireStarter.runSuitesInProcess( scanResult );
         }
         else
@@ -1149,7 +1157,8 @@ public abstract class AbstractSurefireMojo
             try
             {
                 forkStarter = createForkStarter( provider, forkConfiguration, classLoaderConfiguration,
-                                                       runOrderParameters, getConsoleLogger(), scanResult, platform );
+                                                       runOrderParameters, getConsoleLogger(), scanResult, platform,
+                                                       testClasspathWrapper );
 
                 return forkStarter.run( effectiveProperties, scanResult );
             }
@@ -1688,7 +1697,7 @@ public abstract class AbstractSurefireMojo
         return h;
     }
 
-    public File getStatisticsFile( String configurationHash )
+    private File getStatisticsFile( String configurationHash )
     {
         return new File( getBasedir(), ".surefire-" + configurationHash );
     }
@@ -1696,7 +1705,8 @@ public abstract class AbstractSurefireMojo
     private StartupConfiguration createStartupConfiguration( @Nonnull ProviderInfo provider, boolean isInprocess,
                                                              @Nonnull ClassLoaderConfiguration classLoaderConfiguration,
                                                              @Nonnull DefaultScanResult scanResult,
-                                                             @Nonnull Platform platform )
+                                                             @Nonnull Platform platform,
+                                                             @Nonnull TestClassPath testClasspathWrapper )
         throws MojoExecutionException
     {
         try
@@ -1714,11 +1724,12 @@ public abstract class AbstractSurefireMojo
                         .toString();
 
                 return newStartupConfigWithModularPath( classLoaderConfiguration, providerArtifacts, providerName,
-                        getModuleDescriptor(), scanResult, javaHome );
+                        getModuleDescriptor(), scanResult, javaHome, testClasspathWrapper );
             }
             else
             {
-                return newStartupConfigWithClasspath( classLoaderConfiguration, providerArtifacts, providerName );
+                return newStartupConfigWithClasspath( classLoaderConfiguration, providerArtifacts, providerName,
+                        testClasspathWrapper );
             }
         }
         catch ( IOException e )
@@ -1729,13 +1740,10 @@ public abstract class AbstractSurefireMojo
 
     private StartupConfiguration newStartupConfigWithClasspath(
             @Nonnull ClassLoaderConfiguration classLoaderConfiguration, @Nonnull Set<Artifact> providerArtifacts,
-            @Nonnull String providerName )
+            @Nonnull String providerName, @Nonnull TestClassPath testClasspathWrapper )
     {
-        TestClassPath testClasspathWrapper = generateTestClasspath();
         Classpath testClasspath = testClasspathWrapper.toClasspath();
 
-        testClasspathWrapper.avoidArtifactDuplicates( providerArtifacts );
-
         Classpath providerClasspath = ClasspathCache.getCachedClassPath( providerName );
         if ( providerClasspath == null )
         {
@@ -1806,14 +1814,11 @@ public abstract class AbstractSurefireMojo
     private StartupConfiguration newStartupConfigWithModularPath(
             @Nonnull ClassLoaderConfiguration classLoaderConfiguration, @Nonnull Set<Artifact> providerArtifacts,
             @Nonnull String providerName, @Nonnull File moduleDescriptor, @Nonnull DefaultScanResult scanResult,
-            @Nonnull String javaHome )
+            @Nonnull String javaHome, @Nonnull TestClassPath testClasspathWrapper )
             throws IOException
     {
-        TestClassPath testClasspathWrapper = generateTestClasspath();
         Classpath testClasspath = testClasspathWrapper.toClasspath();
 
-        testClasspathWrapper.avoidArtifactDuplicates( providerArtifacts );
-
         Classpath providerClasspath = ClasspathCache.getCachedClassPath( providerName );
         if ( providerClasspath == null )
         {
@@ -2141,11 +2146,12 @@ public abstract class AbstractSurefireMojo
     private ForkStarter createForkStarter( @Nonnull ProviderInfo provider, @Nonnull ForkConfiguration forkConfiguration,
                                            @Nonnull ClassLoaderConfiguration classLoaderConfiguration,
                                            @Nonnull RunOrderParameters runOrderParameters, @Nonnull ConsoleLogger log,
-                                           @Nonnull DefaultScanResult scanResult, @Nonnull Platform platform )
+                                           @Nonnull DefaultScanResult scanResult, @Nonnull Platform platform,
+                                           @Nonnull TestClassPath testClasspathWrapper )
         throws MojoExecutionException, MojoFailureException
     {
-        StartupConfiguration startupConfiguration =
-                createStartupConfiguration( provider, false, classLoaderConfiguration, scanResult, platform );
+        StartupConfiguration startupConfiguration = createStartupConfiguration( provider, false,
+                classLoaderConfiguration, scanResult, platform, testClasspathWrapper );
         String configChecksum = getConfigChecksum();
         StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum, true );
         ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );
@@ -2157,11 +2163,12 @@ public abstract class AbstractSurefireMojo
                                                               @Nonnull ClassLoaderConfiguration classLoaderConfig,
                                                               @Nonnull RunOrderParameters runOrderParameters,
                                                               @Nonnull DefaultScanResult scanResult,
-                                                              @Nonnull Platform platform )
+                                                              @Nonnull Platform platform,
+                                                              @Nonnull TestClassPath testClasspathWrapper )
         throws MojoExecutionException, MojoFailureException
     {
-        StartupConfiguration startupConfiguration =
-                createStartupConfiguration( provider, true, classLoaderConfig, scanResult, platform );
+        StartupConfiguration startupConfiguration = createStartupConfiguration( provider, true, classLoaderConfig,
+                scanResult, platform, testClasspathWrapper );
         String configChecksum = getConfigChecksum();
         StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum, false );
         ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );
@@ -2451,6 +2458,7 @@ public abstract class AbstractSurefireMojo
         checksum.add( isParallelOptimized() );
         checksum.add( isTrimStackTrace() );
         checksum.add( getRemoteRepositories() );
+        checksum.add( getProjectRemoteRepositories() );
         checksum.add( isDisableXmlReport() );
         checksum.add( isUseSystemClassLoader() );
         checksum.add( isUseManifestOnlyJar() );
@@ -2504,7 +2512,7 @@ public abstract class AbstractSurefireMojo
      */
     private TestClassPath generateTestClasspath()
     {
-        @SuppressWarnings( "unchecked" ) Set<Artifact> classpathArtifacts = getProject().getArtifacts();
+        Set<Artifact> classpathArtifacts = getProject().getArtifacts();
 
         if ( getClasspathDependencyScopeExclude() != null && !getClasspathDependencyScopeExclude().isEmpty() )
         {
@@ -2520,7 +2528,7 @@ public abstract class AbstractSurefireMojo
         }
 
         return new TestClassPath( classpathArtifacts, getClassesDirectory(),
-                getTestClassesDirectory(), getAdditionalClasspathElements(), getConsoleLogger() );
+                getTestClassesDirectory(), getAdditionalClasspathElements() );
     }
 
     /**
@@ -2561,7 +2569,7 @@ public abstract class AbstractSurefireMojo
         if ( existing == null )
         {
             List<String> items = new ArrayList<>();
-            for ( Artifact artifact : dependencyResolver.resolveArtifact( surefireArtifact ).getArtifacts() )
+            for ( Artifact artifact : dependencyResolver.resolvePluginArtifact( surefireArtifact ).getArtifacts() )
             {
                 getConsoleLogger().debug(
                     "Adding to " + getPluginName() + " booter test classpath: " + artifact.getFile().getAbsolutePath()
@@ -2866,11 +2874,16 @@ public abstract class AbstractSurefireMojo
     final class JUnitPlatformProviderInfo
         implements ProviderInfo
     {
-        private final Artifact junitArtifact;
+        private static final String PROVIDER_DEP_GID = "org.junit.platform";
+        private static final String PROVIDER_DEP_AID = "junit-platform-launcher";
 
-        JUnitPlatformProviderInfo( Artifact junitArtifact )
+        private final Artifact junitPlatformArtifact;
+        private final TestClassPath testClasspathWrapper;
+
+        JUnitPlatformProviderInfo( Artifact junitPlatformArtifact, TestClassPath testClasspathWrapper )
         {
-            this.junitArtifact = junitArtifact;
+            this.junitPlatformArtifact = junitPlatformArtifact;
+            this.testClasspathWrapper = testClasspathWrapper;
         }
 
         @Override
@@ -2883,7 +2896,7 @@ public abstract class AbstractSurefireMojo
         @Override
         public boolean isApplicable()
         {
-            return junitArtifact != null;
+            return junitPlatformArtifact != null;
         }
 
         @Override
@@ -2896,8 +2909,108 @@ public abstract class AbstractSurefireMojo
         @Nonnull
         public Set<Artifact> getProviderClasspath()
         {
-            String version = surefireBooterArtifact.getBaseVersion();
-            return dependencyResolver.getProviderClasspath( "surefire-junit-platform", version );
+            String surefireVersion = surefireBooterArtifact.getBaseVersion();
+            Map<String, Artifact> providerArtifacts =
+                    dependencyResolver.getProviderClasspathAsMap( "surefire-junit-platform", surefireVersion );
+            Map<String, Artifact> testDependencies = testClasspathWrapper.getTestDependencies();
+
+            if ( hasDependencyPlatformEngine( testDependencies ) )
+            {
+                String filterTestDependency = "org.junit.platform:junit-platform-engine";
+                logDebugOrCliShowErrors( "Test dependencies contain " + filterTestDependency );
+                narrowProviderDependencies( filterTestDependency, providerArtifacts, testDependencies );
+            }
+            else if ( hasDependencyJupiterAPI( testDependencies ) )
+            {
+                String api = "org.junit.jupiter:junit-jupiter-api";
+                String engineGroupId = "org.junit.jupiter";
+                String engineArtifactId = "junit-jupiter-engine";
+                String version = testDependencies.get( api ).getBaseVersion();
+                addEngineByApi( api, engineGroupId, engineArtifactId, providerArtifacts, testDependencies );
+                alignVersions( version, providerArtifacts, testDependencies );
+            }
+            else if ( hasDependencyJUnit4( testDependencies ) )
+            {
+                String version = testDependencies.get( "junit:junit" ).getBaseVersion();
+                addEngineByApi( "junit:junit", "junit", "junit", providerArtifacts, testDependencies );
+                alignVersions( version, providerArtifacts, testDependencies );
+            }
+            return new LinkedHashSet<>( providerArtifacts.values() );
+        }
+
+        private void addEngineByApi( String api,
+                                     String engineGroupId, String engineArtifactId,
+                                     Map<String, Artifact> providerArtifacts,
+                                     Map<String, Artifact> testDependencies )
+        {
+            String jupiterVersion = testDependencies.get( api ).getBaseVersion();
+            narrowProviderDependencies( api, providerArtifacts, testDependencies );
+            for ( Artifact jupiterDep : resolve( engineGroupId, engineArtifactId, jupiterVersion, null, "jar" ) )
+            {
+                String key = jupiterDep.getGroupId() + ":" + jupiterDep.getArtifactId();
+                if ( !testDependencies.containsKey( key ) )
+                {
+                    providerArtifacts.put( key, jupiterDep );
+                }
+            }
+        }
+
+        private void narrowProviderDependencies( String filterTestDependency,
+                                                 Map<String, Artifact> providerArtifacts,
+                                                 Map<String, Artifact> testDependencies )
+        {
+            Artifact engine = testDependencies.get( filterTestDependency );
+            String groupId = engine.getGroupId();
+            String artifactId = engine.getArtifactId();
+            String version = engine.getBaseVersion();
+            String classifier = engine.getClassifier();
+            String type = engine.getType();
+            for ( Artifact engineDep : resolve( groupId, artifactId, version, classifier, type ) )
+            {
+                providerArtifacts.remove( engineDep.getGroupId() + ":" + engineDep.getArtifactId() );
+                logDebugOrCliShowErrors( "Removed artifact " + engineDep + " from provider. "
+                        + "Already appears in test classpath." );
+            }
+            alignVersions( version, providerArtifacts, testDependencies );
+        }
+
+        private void alignVersions( String version,
+                                    Map<String, Artifact> providerArtifacts,
+                                    Map<String, Artifact> testDependencies )
+        {
+            for ( Artifact launcherArtifact : resolve( PROVIDER_DEP_GID, PROVIDER_DEP_AID, version, null, "jar" ) )
+            {
+                String key = launcherArtifact.getGroupId() + ":" + launcherArtifact.getArtifactId();
+                if ( !testDependencies.containsKey( key ) )
+                {
+                    providerArtifacts.put( key, launcherArtifact );
+                }
+            }
+        }
+
+        private Set<Artifact> resolve( String g, String a, String v, String c, String t )
+        {
+            ArtifactHandler handler = junitPlatformArtifact.getArtifactHandler();
+            Artifact artifact = new DefaultArtifact( g, a, v, null, t, c, handler );
+            logDebugOrCliShowErrors( "Resolving artifact " + g + ":" + a + ":" + v );
+            Set<Artifact> r = dependencyResolver.resolveProjectArtifact( artifact ).getArtifacts();
+            logDebugOrCliShowErrors( "Resolved artifact " + g + ":" + a + ":" + v + " to " + r );
+            return r;
+        }
+
+        private boolean hasDependencyJUnit4( Map<String, Artifact> providerArtifacts )
+        {
+            return providerArtifacts.containsKey( "junit:junit" );
+        }
+
+        private boolean hasDependencyJupiterAPI( Map<String, Artifact> providerArtifacts )
+        {
+            return providerArtifacts.containsKey( "org.junit.jupiter:junit-jupiter-api" );
+        }
+
+        private boolean hasDependencyPlatformEngine( Map<String, Artifact> providerArtifacts )
+        {
+            return providerArtifacts.containsKey( "org.junit.platform:junit-platform-engine" );
         }
     }
 
@@ -3423,6 +3536,17 @@ public abstract class AbstractSurefireMojo
         this.trimStackTrace = trimStackTrace;
     }
 
+    public List<ArtifactRepository> getProjectRemoteRepositories()
+    {
+        return projectRemoteRepositories;
+    }
+
+    @SuppressWarnings( "UnusedDeclaration" )
+    public void setProjectRemoteRepositories( List<ArtifactRepository> projectRemoteRepositories )
+    {
+        this.projectRemoteRepositories = projectRemoteRepositories;
+    }
+
     public List<ArtifactRepository> getRemoteRepositories()
     {
         return remoteRepositories;
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java
index b255f38..43f6c52 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java
@@ -20,6 +20,7 @@ package org.apache.maven.plugin.surefire;
  */
 
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -29,7 +30,6 @@ import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
-import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
 import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
@@ -41,7 +41,6 @@ import org.apache.maven.repository.RepositorySystem;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import static java.util.Collections.singletonList;
 import static org.apache.maven.artifact.Artifact.SCOPE_TEST;
 import static org.apache.maven.artifact.versioning.VersionRange.createFromVersionSpec;
 
@@ -76,18 +75,22 @@ final class SurefireDependencyResolver
 
     private final ArtifactRepository localRepository;
 
-    private final List<ArtifactRepository> remoteRepositories;
+    private final List<ArtifactRepository> pluginRemoteRepositories;
+
+    private final List<ArtifactRepository> projectRemoteRepositories;
 
     private final String pluginName;
 
     SurefireDependencyResolver( RepositorySystem repositorySystem, ConsoleLogger log,
                                 ArtifactRepository localRepository,
-                                List<ArtifactRepository> remoteRepositories, String pluginName )
+                                List<ArtifactRepository> pluginRemoteRepositories,
+                                List<ArtifactRepository> projectRemoteRepositories, String pluginName )
     {
         this.repositorySystem = repositorySystem;
         this.log = log;
         this.localRepository = localRepository;
-        this.remoteRepositories = remoteRepositories;
+        this.pluginRemoteRepositories = pluginRemoteRepositories;
+        this.projectRemoteRepositories = projectRemoteRepositories;
         this.pluginName = pluginName;
     }
 
@@ -115,23 +118,23 @@ final class SurefireDependencyResolver
         }
     }
 
-    ArtifactResolutionResult resolveArtifact( Artifact providerArtifact )
+    ArtifactResolutionResult resolvePluginArtifact( Artifact artifact )
+    {
+        return resolveArtifact( artifact, pluginRemoteRepositories );
+    }
+
+    ArtifactResolutionResult resolveProjectArtifact( Artifact artifact )
     {
-        return resolveArtifact( providerArtifact, null );
+        return resolveArtifact( artifact, projectRemoteRepositories );
     }
 
-    private ArtifactResolutionResult resolveArtifact( Artifact providerArtifact, @Nullable Artifact excludeArtifact )
+    private ArtifactResolutionResult resolveArtifact( Artifact artifact, List<ArtifactRepository> repositories )
     {
         ArtifactResolutionRequest request = new ArtifactResolutionRequest()
-                                                    .setArtifact( providerArtifact )
-                                                    .setRemoteRepositories( remoteRepositories )
+                                                    .setArtifact( artifact )
+                                                    .setRemoteRepositories( repositories )
                                                     .setLocalRepository( localRepository )
                                                     .setResolveTransitively( true );
-        if ( excludeArtifact != null )
-        {
-            String pattern = excludeArtifact.getGroupId() + ":" + excludeArtifact.getArtifactId();
-            request.setCollectionFilter( new ExcludesArtifactFilter( singletonList( pattern ) ) );
-        }
         return repositorySystem.resolve( request );
     }
 
@@ -142,7 +145,7 @@ final class SurefireDependencyResolver
 
         Artifact providerArtifact = repositorySystem.createDependencyArtifact( provider );
 
-        ArtifactResolutionResult result = resolveArtifact( providerArtifact );
+        ArtifactResolutionResult result = resolvePluginArtifact( providerArtifact );
 
         if ( log.isDebugEnabled() )
         {
@@ -157,17 +160,29 @@ final class SurefireDependencyResolver
         return orderProviderArtifacts( result.getArtifacts() );
     }
 
+    @Nonnull
+    Map<String, Artifact> getProviderClasspathAsMap( String providerArtifactId, String providerVersion )
+    {
+        Map<String, Artifact> cpArtifactsMapping = new LinkedHashMap<>();
+        for ( Artifact cpArtifact : getProviderClasspath( providerArtifactId, providerVersion ) )
+        {
+            String key = cpArtifact.getGroupId() + ":" + cpArtifact.getArtifactId();
+            cpArtifactsMapping.put( key, cpArtifact );
+        }
+        return cpArtifactsMapping;
+    }
+
     Set<Artifact> addProviderToClasspath( Map<String, Artifact> pluginArtifactMap, Artifact mojoPluginArtifact,
                                           Artifact surefireCommon, Artifact surefireApi, Artifact surefireLoggerApi )
     {
         Set<Artifact> providerArtifacts = new LinkedHashSet<>();
-        ArtifactResolutionResult artifactResolutionResult = resolveArtifact( mojoPluginArtifact );
+        ArtifactResolutionResult artifactResolutionResult = resolvePluginArtifact( mojoPluginArtifact );
         for ( Artifact artifact : pluginArtifactMap.values() )
         {
             if ( !artifactResolutionResult.getArtifacts().contains( artifact ) )
             {
                 providerArtifacts.add( artifact );
-                for ( Artifact dependency : resolveArtifact( artifact ).getArtifacts() )
+                for ( Artifact dependency : resolvePluginArtifact( artifact ).getArtifacts() )
                 {
                     String groupId = dependency.getGroupId();
                     String artifactId = dependency.getArtifactId();
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/TestClassPath.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/TestClassPath.java
index ee8fadb..3a37816 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/TestClassPath.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/TestClassPath.java
@@ -20,14 +20,13 @@ package org.apache.maven.plugin.surefire;
  */
 
 import org.apache.maven.artifact.Artifact;
-import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.surefire.booter.Classpath;
 
 import java.io.File;
 import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Set;
+import java.util.Map;
 
 import static java.util.Collections.addAll;
 import static org.apache.maven.shared.utils.StringUtils.split;
@@ -38,45 +37,26 @@ final class TestClassPath
     private final File classesDirectory;
     private final File testClassesDirectory;
     private final String[] additionalClasspathElements;
-    private final ConsoleLogger logger;
 
     TestClassPath( Iterable<Artifact> artifacts,
                    File classesDirectory,
                    File testClassesDirectory,
-                   String[] additionalClasspathElements,
-                   ConsoleLogger logger )
+                   String[] additionalClasspathElements )
     {
         this.artifacts = artifacts;
         this.classesDirectory = classesDirectory;
         this.testClassesDirectory = testClassesDirectory;
         this.additionalClasspathElements = additionalClasspathElements;
-        this.logger = logger;
     }
 
-    void avoidArtifactDuplicates( Set<Artifact> providerArtifacts )
+    Map<String, Artifact> getTestDependencies()
     {
+        Map<String, Artifact> artifactMapping = new LinkedHashMap<>();
         for ( Artifact artifact : artifacts )
         {
-            Iterator<Artifact> it = providerArtifacts.iterator();
-            while ( it.hasNext() )
-            {
-                Artifact providerArtifact = it.next();
-                String classifier1 = providerArtifact.getClassifier();
-                String classifier2 = artifact.getClassifier();
-                if ( providerArtifact.getGroupId().equals( artifact.getGroupId() )
-                        && providerArtifact.getArtifactId().equals( artifact.getArtifactId() )
-                        && providerArtifact.getType().equals( artifact.getType() )
-                        && ( classifier1 == null ? classifier2 == null : classifier1.equals( classifier2 ) ) )
-                {
-                    it.remove();
-                    if ( logger.isDebugEnabled() )
-                    {
-                        logger.debug( "Removed artifact " + providerArtifact + " from provider. "
-                                + "Already appears in test classpath." );
-                    }
-                }
-            }
+            artifactMapping.put( artifact.getGroupId() + ":" + artifact.getArtifactId(), artifact );
         }
+        return artifactMapping;
     }
 
     Classpath toClasspath()
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 0f9ee80..2d268bc 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
@@ -108,7 +108,7 @@ public class AbstractSurefireMojoJava7PlusTest
 
         TestClassPath testClasspath =
                 new TestClassPath( asList( modular, nonModular, junit, hamcrest ), classesDir, testClassesDir,
-                        null, null );
+                        null );
 
         doReturn( testClasspath ).when( mojo, "generateTestClasspath" );
         doReturn( 1 ).when( mojo, "getEffectiveForkCount" );
@@ -171,11 +171,10 @@ public class AbstractSurefireMojoJava7PlusTest
 
         StartupConfiguration conf = invokeMethod( mojo, "newStartupConfigWithModularPath",
                 classLoaderConfiguration, providerClasspath, "org.asf.Provider", moduleInfo, scanResult,
-                "" );
+                "", testClasspath );
 
         verify( mojo, times( 1 ) ).effectiveIsEnableAssertions();
         verify( mojo, times( 1 ) ).isChildDelegation();
-        verifyPrivate( mojo, times( 1 ) ).invoke( "generateTestClasspath" );
         verify( mojo, times( 1 ) ).getEffectiveForkCount();
         verify( mojo, times( 1 ) ).getTestClassesDirectory();
         verify( scanResult, times( 1 ) ).getClasses();
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 a6fc708..c9a332a 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
@@ -247,7 +247,7 @@ public class AbstractSurefireMojoTest
         File classesDir = mockFile( "classes" );
         File testClassesDir = mockFile( "test-classes" );
         TestClassPath testClasspath =
-                new TestClassPath( asList( junit, hamcrest ), classesDir, testClassesDir, null, null );
+                new TestClassPath( asList( junit, hamcrest ), classesDir, testClassesDir, null );
 
         doReturn( testClasspath ).when( mojo, "generateTestClasspath" );
         doReturn( 1 ).when( mojo, "getEffectiveForkCount" );
@@ -267,11 +267,10 @@ public class AbstractSurefireMojoTest
         when( mojo.getConsoleLogger() ).thenReturn( new PluginConsoleLogger( logger ) );
 
         StartupConfiguration conf = invokeMethod( mojo, "newStartupConfigWithClasspath",
-                classLoaderConfiguration, providerArtifacts, "org.asf.Provider" );
+                classLoaderConfiguration, providerArtifacts, "org.asf.Provider", testClasspath );
 
         verify( mojo, times( 1 ) ).effectiveIsEnableAssertions();
         verify( mojo, times( 1 ) ).isChildDelegation();
-        verifyPrivate( mojo, times( 1 ) ).invoke( "generateTestClasspath" );
         verify( mojo, times( 1 ) ).getEffectiveForkCount();
         ArgumentCaptor<String> argument = ArgumentCaptor.forClass( String.class );
         verify( logger, times( 6 ) ).debug( argument.capture() );
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireDependencyResolverTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireDependencyResolverTest.java
index ab57aef..fb03f4a 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireDependencyResolverTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireDependencyResolverTest.java
@@ -145,9 +145,9 @@ public class SurefireDependencyResolverTest
                 } );
 
         SurefireDependencyResolver surefireDependencyResolver =
-                new SurefireDependencyResolver( repositorySystem, null, null, null, null );
+                new SurefireDependencyResolver( repositorySystem, null, null, null, null, null );
 
-        ArtifactResolutionResult actualResult = surefireDependencyResolver.resolveArtifact( provider );
+        ArtifactResolutionResult actualResult = surefireDependencyResolver.resolvePluginArtifact( provider );
 
         assertThat( actualResult )
                 .isSameAs( expectedResult );
@@ -243,7 +243,7 @@ public class SurefireDependencyResolverTest
         ConsoleLogger log = mock( ConsoleLogger.class );
 
         SurefireDependencyResolver surefireDependencyResolver =
-                new SurefireDependencyResolver( repositorySystem, log, null, null, null );
+                new SurefireDependencyResolver( repositorySystem, log, null, null, null, null );
 
         when( log.isDebugEnabled() )
                 .thenReturn( true );
@@ -349,7 +349,7 @@ public class SurefireDependencyResolverTest
                 } );
 
         SurefireDependencyResolver surefireDependencyResolver =
-                new SurefireDependencyResolver( repositorySystem, null, null, null, null );
+                new SurefireDependencyResolver( repositorySystem, null, null, null, null, null );
 
         Map<String, Artifact> pluginArtifactsMapping = new HashMap<>();
         pluginArtifactsMapping.put( plugin.getGroupId() + ":" + plugin.getArtifactId(), plugin );
diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformEnginesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformEnginesIT.java
index 6147c2f..af8f366 100644
--- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformEnginesIT.java
+++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformEnginesIT.java
@@ -59,13 +59,13 @@ public class JUnitPlatformEnginesIT
     @Parameters(name = "{0}")
     public static Iterable<Object[]> regexVersions()
     {
-        ArrayList<Object[]> args = new ArrayList<Object[]>();
+        ArrayList<Object[]> args = new ArrayList<>();
         args.add( new Object[] { "1.0.3", "5.0.3", "1.0.0", "1.0.0" } );
         args.add( new Object[] { "1.1.1", "5.1.1", "1.0.0", "1.0.0" } );
         args.add( new Object[] { "1.2.0", "5.2.0", "1.1.0", "1.0.0" } );
         args.add( new Object[] { "1.3.2", "5.3.2", "1.1.1", "1.0.0" } );
         args.add( new Object[] { "1.4.0-SNAPSHOT", "5.4.0-SNAPSHOT", "1.1.1", "1.0.0" } );
-        args.add( new Object[] { "1.4.0-RC1", "5.4.0-RC1", "1.1.1", "1.0.0" } );
+        args.add( new Object[] { "1.4.0-RC2", "5.4.0-RC2", "1.1.1", "1.0.0" } );
         return args;
     }
 
@@ -124,7 +124,7 @@ public class JUnitPlatformEnginesIT
                 regex( toRegex( "*surefire-api-*.jar*" ) ),
                 regex( toRegex( "*surefire-logger-api-*.jar*" ) ),
                 regex( toRegex( "*common-java5-*.jar*" ) ),
-                regex( toRegex( "*junit-platform-launcher-1.3.2.jar*" ) )
+                regex( toRegex( "*junit-platform-launcher-" + platform + ".jar*" ) )
         ) );
 
         lines = validator.loadLogLines( startsWith( "[DEBUG] boot(compact) classpath" ) );
@@ -148,7 +148,7 @@ public class JUnitPlatformEnginesIT
                 regex( toRegex( "*opentest4j-" + opentest + ".jar*" ) ),
                 regex( toRegex( "*junit-jupiter-api-" + jupiter + ".jar*" ) ),
                 regex( toRegex( "*surefire-junit-platform-*.jar*" ) ),
-                regex( toRegex(  "*junit-platform-launcher-1.3.2.jar*" ) )
+                regex( toRegex(  "*junit-platform-launcher-" + platform + ".jar*" ) )
         ) );
     }