Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SUREFIRE-2051] Propagate exceptions while resolving artifacts in SurefireDependencyResolver #504

Merged
merged 1 commit into from Mar 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -48,6 +48,7 @@
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ResolutionErrorHandler;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.artifact.versioning.ArtifactVersion;
Expand Down Expand Up @@ -801,6 +802,9 @@ public abstract class AbstractSurefireMojo
@Component
private ProviderDetector providerDetector;

@Component
private ResolutionErrorHandler resolutionErrorHandler;

private Toolchain toolchain;

private int effectiveForkCount = -1;
Expand Down Expand Up @@ -1001,6 +1005,7 @@ private void setupStuff() throws MojoFailureException
getConsoleLogger(), getLocalRepository(),
getRemoteRepositories(),
getProjectRemoteRepositories(),
resolutionErrorHandler,
getPluginName(),
getSession().isOffline() );

Expand Down Expand Up @@ -2474,6 +2479,7 @@ private ForkNodeFactory getForkNodeFactory()
@Nonnull
private ForkConfiguration createForkConfiguration( @Nonnull Platform platform,
@Nonnull ResolvePathResultWrapper resolvedJavaModularityResult )
throws MojoExecutionException
{
File tmpDir = getSurefireTempDir();

Expand Down Expand Up @@ -2899,7 +2905,7 @@ private <T> void showArray( T[] array, String setting )
}
}

private Classpath getArtifactClasspath( Artifact surefireArtifact )
private Classpath getArtifactClasspath( Artifact surefireArtifact ) throws MojoExecutionException
{
Classpath existing = classpathCache.getCachedClassPath( surefireArtifact.getArtifactId() );
if ( existing == null )
Expand Down Expand Up @@ -3154,7 +3160,7 @@ public List<String[]> getJpmsArguments( @Nonnull ProviderRequirements forkRequir

@Override
@Nonnull
public Set<Artifact> getProviderClasspath()
public Set<Artifact> getProviderClasspath() throws MojoExecutionException
{
Artifact surefireArtifact = getBooterArtifact();
String version = surefireArtifact.getBaseVersion();
Expand Down Expand Up @@ -3191,7 +3197,7 @@ public List<String[]> getJpmsArguments( @Nonnull ProviderRequirements forkRequir

@Override
@Nonnull
public Set<Artifact> getProviderClasspath()
public Set<Artifact> getProviderClasspath() throws MojoExecutionException
{
// add the JUnit provider as default - it doesn't require JUnit to be present,
// since it supports POJO tests.
Expand Down Expand Up @@ -3239,7 +3245,7 @@ public List<String[]> getJpmsArguments( @Nonnull ProviderRequirements forkRequir

@Override
@Nonnull
public Set<Artifact> getProviderClasspath()
public Set<Artifact> getProviderClasspath() throws MojoExecutionException
{
String version = getBooterArtifact().getBaseVersion();
return surefireDependencyResolver.getProviderClasspath( "surefire-junit4", version );
Expand Down Expand Up @@ -3365,7 +3371,7 @@ private List<String[]> getJpmsArgs()
}

private void addEngineByApi( String engineGroupId, String engineArtifactId, String engineVersion,
Map<String, Artifact> providerArtifacts )
Map<String, Artifact> providerArtifacts ) throws MojoExecutionException
{
for ( Artifact dep : resolve( engineGroupId, engineArtifactId, engineVersion, null, "jar" ) )
{
Expand All @@ -3380,7 +3386,7 @@ private void narrowDependencies( Map<String, Artifact> providerArtifacts,
providerArtifacts.keySet().removeAll( testDependencies.keySet() );
}

private void alignProviderVersions( Map<String, Artifact> providerArtifacts )
private void alignProviderVersions( Map<String, Artifact> providerArtifacts ) throws MojoExecutionException
{
String version = junitPlatformArtifact.getBaseVersion();
for ( Artifact launcherArtifact : resolve( PROVIDER_DEP_GID, PROVIDER_DEP_AID, version, null, "jar" ) )
Expand All @@ -3393,7 +3399,7 @@ private void alignProviderVersions( Map<String, Artifact> providerArtifacts )
}
}

private Set<Artifact> resolve( String g, String a, String v, String c, String t )
private Set<Artifact> resolve( String g, String a, String v, String c, String t ) throws MojoExecutionException
{
ArtifactHandler handler = junitPlatformArtifact.getArtifactHandler();
Artifact artifact = new DefaultArtifact( g, a, v, null, t, c, handler );
Expand Down Expand Up @@ -3471,7 +3477,7 @@ public List<String[]> getJpmsArguments( @Nonnull ProviderRequirements forkRequir

@Override
@Nonnull
public Set<Artifact> getProviderClasspath()
public Set<Artifact> getProviderClasspath() throws MojoExecutionException
{
String version = getBooterArtifact().getBaseVersion();
return surefireDependencyResolver.getProviderClasspath( "surefire-junit47", version );
Expand Down Expand Up @@ -4082,6 +4088,11 @@ public void setTempDir( String tempDir )
this.tempDir = tempDir;
}

public void setResolutionErrorHandler( ResolutionErrorHandler resolutionErrorHandler )
{
this.resolutionErrorHandler = resolutionErrorHandler;
}

private static String getEffectiveForkMode( String forkMode )
{
if ( "pertest".equalsIgnoreCase( forkMode ) )
Expand Down
Expand Up @@ -32,15 +32,18 @@

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.ResolutionErrorHandler;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
import org.apache.maven.repository.RepositorySystem;

Expand Down Expand Up @@ -87,22 +90,25 @@ final class SurefireDependencyResolver

private final List<ArtifactRepository> projectRemoteRepositories;

private final String pluginName;
private final ResolutionErrorHandler resolutionErrorHandler;

private final String pluginName;

private final boolean offline;

SurefireDependencyResolver( RepositorySystem repositorySystem, ConsoleLogger log,
ArtifactRepository localRepository,
List<ArtifactRepository> pluginRemoteRepositories,
List<ArtifactRepository> projectRemoteRepositories,
ResolutionErrorHandler resolutionErrorHandler,
String pluginName, boolean offline )
{
this.repositorySystem = repositorySystem;
this.log = log;
this.localRepository = localRepository;
this.pluginRemoteRepositories = pluginRemoteRepositories;
this.projectRemoteRepositories = projectRemoteRepositories;
this.resolutionErrorHandler = resolutionErrorHandler;
this.pluginName = pluginName;
this.offline = offline;
}
Expand Down Expand Up @@ -132,6 +138,7 @@ static boolean isWithinVersionSpec( @Nullable Artifact artifact, @Nonnull String
}

Map<String, Artifact> resolvePluginDependencies( Plugin plugin, Map<String, Artifact> pluginResolvedDependencies )
throws MojoExecutionException
{
Map<String, Artifact> resolved = new LinkedHashMap<>();
Collection<Dependency> pluginDependencies = plugin.getDependencies();
Expand All @@ -153,28 +160,30 @@ Map<String, Artifact> resolvePluginDependencies( Plugin plugin, Map<String, Arti
return resolved;
}

ArtifactResolutionResult resolvePluginArtifact( Artifact artifact )
ArtifactResolutionResult resolvePluginArtifact( Artifact artifact ) throws MojoExecutionException
{
return resolvePluginArtifact( artifact, new RuntimeArtifactFilter() );
}

ArtifactResolutionResult resolveProjectArtifact( Artifact artifact )
ArtifactResolutionResult resolveProjectArtifact( Artifact artifact ) throws MojoExecutionException
{
return resolveProjectArtifact( artifact, new RuntimeArtifactFilter() );
}

private ArtifactResolutionResult resolvePluginArtifact( Artifact artifact, ArtifactFilter filter )
throws MojoExecutionException
{
return resolveArtifact( artifact, pluginRemoteRepositories, filter );
}

private ArtifactResolutionResult resolveProjectArtifact( Artifact artifact, ArtifactFilter filter )
throws MojoExecutionException
{
return resolveArtifact( artifact, projectRemoteRepositories, filter );
}

private ArtifactResolutionResult resolveArtifact( Artifact artifact, List<ArtifactRepository> repositories,
ArtifactFilter filter )
ArtifactFilter filter ) throws MojoExecutionException
{
ArtifactResolutionRequest request = new ArtifactResolutionRequest()
.setOffline( offline )
Expand All @@ -184,11 +193,22 @@ private ArtifactResolutionResult resolveArtifact( Artifact artifact, List<Artifa
.setCollectionFilter( filter )
.setRemoteRepositories( repositories );

return repositorySystem.resolve( request );
ArtifactResolutionResult result = repositorySystem.resolve( request );
try
{
resolutionErrorHandler.throwErrors( request, result );
}
catch ( ArtifactResolutionException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}

return result;
}

@Nonnull
Set<Artifact> getProviderClasspath( String providerArtifactId, String providerVersion )
throws MojoExecutionException
{
Dependency provider = toProviderDependency( providerArtifactId, providerVersion );

Expand All @@ -211,6 +231,7 @@ Set<Artifact> getProviderClasspath( String providerArtifactId, String providerVe

@Nonnull
Map<String, Artifact> getProviderClasspathAsMap( String providerArtifactId, String providerVersion )
throws MojoExecutionException
{
return artifactMapByVersionlessId( getProviderClasspath( providerArtifactId, providerVersion ) );
}
Expand Down
Expand Up @@ -44,6 +44,7 @@
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.DefaultResolutionErrorHandler;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
Expand Down Expand Up @@ -157,6 +158,7 @@ public void setupMojo()
plugin.setVersion( mojoArtifact.getVersion() );
when( pluginDescriptor.getPlugin() ).thenReturn( plugin );
mojo.setPluginDescriptor( pluginDescriptor );
mojo.setResolutionErrorHandler( new DefaultResolutionErrorHandler() );
}

@Test
Expand Down
Expand Up @@ -27,12 +27,15 @@

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.DefaultResolutionErrorHandler;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.surefire.SurefireDependencyResolver.RuntimeArtifactFilter;
import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
import org.apache.maven.repository.RepositorySystem;
Expand All @@ -49,6 +52,7 @@
import static org.apache.maven.artifact.versioning.VersionRange.createFromVersionSpec;
import static org.apache.maven.plugin.surefire.SurefireDependencyResolver.PROVIDER_GROUP_ID;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
Expand Down Expand Up @@ -108,7 +112,7 @@ public void shouldBeFailWithinRange() throws InvalidVersionSpecificationExceptio
}

@Test
public void testResolveArtifact() throws InvalidVersionSpecificationException
public void testResolveArtifact() throws InvalidVersionSpecificationException, MojoExecutionException
{
final Artifact provider = createArtifact( "surefire-junit-platform" );
RepositorySystem repositorySystem = mock( RepositorySystem.class );
Expand Down Expand Up @@ -152,7 +156,8 @@ public ArtifactResolutionResult answer( InvocationOnMock invocation )
} );

SurefireDependencyResolver surefireDependencyResolver =
new SurefireDependencyResolver( repositorySystem, null, null, null, null, null, false );
new SurefireDependencyResolver( repositorySystem, null, null, null, null,
new DefaultResolutionErrorHandler(), null, false );

ArtifactResolutionResult actualResult = surefireDependencyResolver.resolvePluginArtifact( provider );

Expand Down Expand Up @@ -246,7 +251,8 @@ public Artifact answer( InvocationOnMock invocation )
ConsoleLogger log = mock( ConsoleLogger.class );

SurefireDependencyResolver surefireDependencyResolver =
new SurefireDependencyResolver( repositorySystem, log, null, null, null, null, false );
new SurefireDependencyResolver( repositorySystem, log, null, null, null,
new DefaultResolutionErrorHandler(), null, false );

when( log.isDebugEnabled() )
.thenReturn( true );
Expand Down Expand Up @@ -275,6 +281,35 @@ public Artifact answer( InvocationOnMock invocation )
.isSameAs( ext );
}

@Test
public void testGetProviderClasspathShouldPropagateTheResolutionException() throws Exception
{
Artifact provider = createArtifact( "surefire-junit-platform" );
provider.setFile( null );

Set<Artifact> providerArtifacts = new LinkedHashSet<>();
providerArtifacts.add( provider );

ArtifactResolutionResult result = mock( ArtifactResolutionResult.class );
when( result.getArtifacts() ).thenReturn( providerArtifacts );
when( result.hasMetadataResolutionExceptions() ).thenReturn( true );
ArtifactResolutionException resolutionException =
new ArtifactResolutionException( "failed to resolve", provider );
when( result.getMetadataResolutionException( 0 ) ).thenReturn( resolutionException );

RepositorySystem repositorySystem = mock( RepositorySystem.class );
when( repositorySystem.resolve( any( ArtifactResolutionRequest.class ) ) ).thenReturn( result );
when( repositorySystem.createDependencyArtifact( any( Dependency.class ) ) ).thenReturn( provider );

SurefireDependencyResolver surefireDependencyResolver =
new SurefireDependencyResolver( repositorySystem, mock( ConsoleLogger.class ), null, null, null,
new DefaultResolutionErrorHandler(), null, false );

assertThatThrownBy( () -> surefireDependencyResolver.getProviderClasspath( "surefire-junit-platform", "1" ) )
.isInstanceOf( MojoExecutionException.class )
.hasCause( resolutionException );
}

@Test
public void testResolvePluginDependencies() throws Exception
{
Expand Down Expand Up @@ -306,7 +341,8 @@ public void testResolvePluginDependencies() throws Exception
singletonMap( PROVIDER_GROUP_ID + ":surefire-shadefire", providerAsArtifact );

SurefireDependencyResolver surefireDependencyResolver =
new SurefireDependencyResolver( repositorySystem, null, null, null, null, null, false );
new SurefireDependencyResolver( repositorySystem, null, null, null, null,
new DefaultResolutionErrorHandler(), null, false );

Map<String, Artifact> providers =
surefireDependencyResolver.resolvePluginDependencies( plugin, pluginResolvedDependencies );
Expand Down