Skip to content

Commit 407ee8b

Browse files
authored
Merge pull request #1212 from hcoles/feature/auto_add_junit_platform
Auto add junit-platform-launcher to classpath
2 parents 2c60cf1 + 9835518 commit 407ee8b

File tree

6 files changed

+129
-17
lines changed

6 files changed

+129
-17
lines changed

pitest-maven/src/main/java/org/pitest/maven/AbstractPitMojo.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package org.pitest.maven;
22

33
import org.apache.maven.artifact.Artifact;
4+
import org.apache.maven.execution.MavenSession;
45
import org.apache.maven.plugin.AbstractMojo;
56
import org.apache.maven.plugin.MojoExecutionException;
67
import org.apache.maven.plugin.MojoFailureException;
78
import org.apache.maven.plugins.annotations.Parameter;
89
import org.apache.maven.project.MavenProject;
10+
import org.eclipse.aether.RepositorySystem;
911
import org.pitest.coverage.CoverageSummary;
1012
import org.pitest.mutationtest.config.PluginServices;
1113
import org.pitest.mutationtest.config.ReportOptions;
@@ -16,6 +18,7 @@
1618
import org.slf4j.bridge.SLF4JBridgeHandler;
1719
import uk.org.lidalia.sysoutslf4j.context.SysOutOverSLF4J;
1820

21+
import javax.inject.Inject;
1922
import java.io.File;
2023
import java.nio.charset.Charset;
2124
import java.util.ArrayList;
@@ -37,6 +40,13 @@ public class AbstractPitMojo extends AbstractMojo {
3740

3841
private final PluginServices plugins;
3942

43+
/**
44+
* The current build session instance.
45+
*/
46+
@Parameter(defaultValue = "${session}", readonly = true)
47+
private MavenSession session;
48+
49+
4050
// Concrete List types declared for all fields to work around maven 2 bug
4151

4252
/**
@@ -385,18 +395,22 @@ public class AbstractPitMojo extends AbstractMojo {
385395

386396
private final GoalStrategy goalStrategy;
387397

388-
public AbstractPitMojo() {
398+
private final RepositorySystem repositorySystem;
399+
400+
@Inject
401+
public AbstractPitMojo(RepositorySystem repositorySystem) {
389402
this(new RunPitStrategy(), new DependencyFilter(PluginServices.makeForLoader(
390403
AbstractPitMojo.class.getClassLoader())), PluginServices.makeForLoader(
391-
AbstractPitMojo.class.getClassLoader()), new NonEmptyProjectCheck());
404+
AbstractPitMojo.class.getClassLoader()), new NonEmptyProjectCheck(), repositorySystem);
392405
}
393406

394-
public AbstractPitMojo(final GoalStrategy strategy, final Predicate<Artifact> filter,
395-
final PluginServices plugins, final Predicate<MavenProject> emptyProjectCheck) {
407+
public AbstractPitMojo(GoalStrategy strategy, Predicate<Artifact> filter,
408+
PluginServices plugins, Predicate<MavenProject> emptyProjectCheck, RepositorySystem repositorySystem) {
396409
this.goalStrategy = strategy;
397410
this.filter = filter;
398411
this.plugins = plugins;
399412
this.notEmptyProject = emptyProjectCheck;
413+
this.repositorySystem = repositorySystem;
400414
}
401415

402416
@Override
@@ -740,6 +754,14 @@ public String getProjectBase() {
740754
return projectBase;
741755
}
742756

757+
public MavenSession session() {
758+
return session;
759+
}
760+
761+
public RepositorySystem repositorySystem() {
762+
return repositorySystem;
763+
}
764+
743765
static class RunDecision {
744766
private List<String> reasons = new ArrayList<>(4);
745767

pitest-maven/src/main/java/org/pitest/maven/MojoToReportOptionsConverter.java

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
import org.apache.maven.plugin.logging.Log;
2121
import org.apache.maven.project.MavenProject;
2222
import org.codehaus.plexus.util.xml.Xpp3Dom;
23+
import org.eclipse.aether.artifact.DefaultArtifact;
24+
import org.eclipse.aether.resolution.ArtifactRequest;
25+
import org.eclipse.aether.resolution.ArtifactResolutionException;
26+
import org.eclipse.aether.resolution.ArtifactResult;
2327
import org.pitest.classinfo.ClassName;
2428
import org.pitest.classpath.DirectoryClassPathRoot;
2529
import org.pitest.functional.FCollection;
@@ -40,6 +44,7 @@
4044
import java.util.Enumeration;
4145
import java.util.HashSet;
4246
import java.util.List;
47+
import java.util.Optional;
4348
import java.util.Properties;
4449
import java.util.Set;
4550
import java.util.function.Function;
@@ -77,18 +82,84 @@ public ReportOptions convert() {
7782

7883
classPath.addAll(this.mojo.getAdditionalClasspathElements());
7984

85+
autoAddJUnitPlatform(classPath);
86+
removeExcludedDependencies(classPath);
87+
88+
ReportOptions option = parseReportOptions(classPath);
89+
return updateFromSurefire(option);
90+
91+
}
92+
93+
/**
94+
* The junit 5 plugin needs junit-platform-launcher to run, but this will not be on the classpath
95+
* of the project. We want to use the same version that surefire (and therefore the SUT) uses, not
96+
* the one the plugin was built against.
97+
* <p>
98+
* It is not declared as a normal dependency, instead surefire picks the version to use based on
99+
* other junit jars on the classpath. We're forced to do something similar here.
100+
*
101+
* @param classPath classpath to modify
102+
*/
103+
private void autoAddJUnitPlatform(List<String> classPath) {
104+
List<Artifact> junitDependencies = this.mojo.getProject().getArtifacts().stream()
105+
.filter(a -> a.getGroupId().equals("org.junit.platform"))
106+
.collect(Collectors.toList());
107+
108+
// If the launcher has been manually added to the dependencies, there is nothing to do
109+
if (junitDependencies.stream().anyMatch(a -> a.getArtifactId().equals("junit-platform-launcher"))) {
110+
return;
111+
}
112+
113+
Optional<Artifact> maybeJUnitPlatform = findJUnitArtifact(junitDependencies);
114+
if (!maybeJUnitPlatform.isPresent()) {
115+
this.log.debug("JUnit 5 not on classpath");
116+
return;
117+
}
118+
119+
// Look for platform engine or platform commons on classpath
120+
Artifact toMatch = maybeJUnitPlatform.get();
121+
122+
// Assume that platform launcher has been released with same version number as engine and commons
123+
DefaultArtifact platformLauncher = new DefaultArtifact(toMatch.getGroupId(), "junit-platform-launcher", "jar",
124+
toMatch.getVersion());
125+
126+
try {
127+
ArtifactRequest r = new ArtifactRequest();
128+
r.setArtifact(platformLauncher);
129+
130+
r.setRepositories(this.mojo.getProject().getRemotePluginRepositories());
131+
ArtifactResult resolved = this.mojo.repositorySystem().resolveArtifact(mojo.session().getRepositorySession(), r);
132+
133+
this.log.info("Auto adding " + resolved + " to classpath.");
134+
classPath.add(resolved.getArtifact().getFile().getAbsolutePath());
135+
} catch (ArtifactResolutionException e) {
136+
this.log.error("Could not resolve " + platformLauncher);
137+
throw new RuntimeException(e);
138+
}
139+
140+
}
141+
142+
private static Optional<Artifact> findJUnitArtifact(List<Artifact> junitDependencies) {
143+
Optional<Artifact> maybeEngine = junitDependencies.stream()
144+
.filter(a -> a.getArtifactId().equals("junit-platform-engine"))
145+
.findAny();
146+
if (maybeEngine.isPresent()) {
147+
return maybeEngine;
148+
}
149+
150+
return junitDependencies.stream()
151+
.filter(a -> a.getArtifactId().equals("junit-platform-commons"))
152+
.findAny();
153+
}
154+
155+
private void removeExcludedDependencies(List<String> classPath) {
80156
for (Object artifact : this.mojo.getProject().getArtifacts()) {
81157
final Artifact dependency = (Artifact) artifact;
82-
83158
if (this.mojo.getClasspathDependencyExcludes().contains(
84159
dependency.getGroupId() + ":" + dependency.getArtifactId())) {
85160
classPath.remove(dependency.getFile().getPath());
86161
}
87162
}
88-
89-
ReportOptions option = parseReportOptions(classPath);
90-
return updateFromSurefire(option);
91-
92163
}
93164

94165
private ReportOptions parseReportOptions(final List<String> classPath) {
@@ -270,6 +341,11 @@ private void addOwnDependenciesToClassPath(final List<String> classPath) {
270341
+ dependency.getArtifactId() + " to SUT classpath");
271342
classPath.add(dependency.getFile().getAbsolutePath());
272343
}
344+
345+
// If the user as explicitly added junit platform classes to the pitest classpath, trust that they
346+
// know what they're doing and add them in
347+
this.mojo.getPluginArtifactMap().values().stream().filter(a -> a.getGroupId().equals("org.junit.platform"))
348+
.forEach(dependency -> classPath.add(dependency.getFile().getAbsolutePath()));
273349
}
274350

275351
private Collection<Predicate<String>> globStringsToPredicates(

pitest-maven/src/main/java/org/pitest/maven/PitMojo.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
import org.apache.maven.plugins.annotations.LifecyclePhase;
44
import org.apache.maven.plugins.annotations.Mojo;
55
import org.apache.maven.plugins.annotations.ResolutionScope;
6+
import org.eclipse.aether.RepositorySystem;
7+
8+
import javax.inject.Inject;
69

710
/**
811
* Goal which runs a coverage mutation report
@@ -13,4 +16,8 @@
1316
threadSafe = true)
1417
public class PitMojo extends AbstractPitMojo {
1518

19+
@Inject
20+
public PitMojo(RepositorySystem repositorySystem) {
21+
super(repositorySystem);
22+
}
1623
}

pitest-maven/src/main/java/org/pitest/maven/ScmMojo.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,14 @@
3333
import org.apache.maven.scm.manager.ScmManager;
3434
import org.apache.maven.scm.repository.ScmRepository;
3535
import org.codehaus.plexus.util.StringUtils;
36+
import org.eclipse.aether.RepositorySystem;
3637
import org.pitest.functional.FCollection;
3738
import org.pitest.mutationtest.config.PluginServices;
3839
import org.pitest.mutationtest.config.ReportOptions;
3940
import org.pitest.mutationtest.tooling.CombinedStatistics;
4041

42+
import javax.inject.Inject;
43+
4144
/**
4245
* Goal which runs a coverage mutation report only for files that have been
4346
* modified or introduced locally based on the source control configured in
@@ -96,16 +99,20 @@ public class ScmMojo extends AbstractPitMojo {
9699
@Parameter(property = "scmRootDir", defaultValue = "${project.parent.basedir}")
97100
private File scmRootDir;
98101

99-
public ScmMojo(final RunPitStrategy executionStrategy,
100-
final ScmManager manager, Predicate<Artifact> filter,
101-
PluginServices plugins, boolean analyseLastCommit, Predicate<MavenProject> nonEmptyProjectCheck) {
102-
super(executionStrategy, filter, plugins, nonEmptyProjectCheck);
102+
public ScmMojo(RunPitStrategy executionStrategy,
103+
ScmManager manager, Predicate<Artifact> filter,
104+
PluginServices plugins,
105+
boolean analyseLastCommit,
106+
Predicate<MavenProject> nonEmptyProjectCheck,
107+
RepositorySystem repositorySystem) {
108+
super(executionStrategy, filter, plugins, nonEmptyProjectCheck, repositorySystem);
103109
this.manager = manager;
104110
this.analyseLastCommit = analyseLastCommit;
105111
}
106112

107-
public ScmMojo() {
108-
113+
@Inject
114+
public ScmMojo(RepositorySystem repositorySystem) {
115+
super(repositorySystem);
109116
}
110117

111118
@Override

pitest-maven/src/test/java/org/pitest/maven/BasePitMojoTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ protected String createPomWithConfiguration(final String config) {
9797

9898
protected AbstractPitMojo createPITMojo(final String config) throws Exception {
9999
final AbstractPitMojo pitMojo = new AbstractPitMojo(this.executionStrategy, this.filter,
100-
this.plugins, p -> true);
100+
this.plugins, p -> true, null);
101101
configurePitMojo(pitMojo, config);
102102
return pitMojo;
103103
}

pitest-maven/src/test/java/org/pitest/maven/ScmMojoTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public class ScmMojoTest extends BasePitMojoTest {
5353
public void setUp() throws Exception {
5454
super.setUp();
5555
this.testee = new ScmMojo(this.executionStrategy, this.manager,
56-
this.filter, this.plugins, false, i -> true);
56+
this.filter, this.plugins, false, i -> true, null);
5757
this.testee.setScmRootDir(new File("foo"));
5858
when(this.project.getBuild()).thenReturn(this.build);
5959
when(this.project.getParent()).thenReturn(null);

0 commit comments

Comments
 (0)