Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Unreleased]

## [2.1.0] - 2020-03-01
### Added
- [#73](https://github.com/pitest/pitclipse/pull/113) Support for JUnit 5 tests

### Removed
- [#113](https://github.com/pitest/pitclipse/pull/113) Support for Eclipse Mars, Eclipse Neon

## [2.0.2] - 2020-02-18
### Changed
- [#74](https://github.com/pitest/pitclipse/issues/74) Prevent the dependencies of analyzed projects from messing up with Pitest
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ It is also possible to run a single JUnit test class. Specific PIT options can b

Preferences also allow to change mutation settings (`Window > Preferences > Pitest`).

> **/!\\** JUnit 5 is not supported at the moment

## Installation

### From the Eclipse Marketplace
Expand Down
31 changes: 16 additions & 15 deletions bundles/README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
# Pitclipse Architecture <!-- omit in toc -->

- [Overview](#Overview)
- [Event flow](#Event-flow)
- [How can I be notified when a new PIT application is launched?](#How-can-I-be-notified-when-a-new-PIT-application-is-launched)
- [How do I listen for new PIT results?](#How-do-I-listen-for-new-PIT-results)
- [How do I listen for new PIT mutations results?](#How-do-I-listen-for-new-PIT-mutations-results)
- [Overview](#overview)
- [Event flow](#event-flow)
- [How can I be notified when a new PIT application is launched?](#how-can-i-be-notified-when-a-new-pit-application-is-launched)
- [How do I listen for new PIT results?](#how-do-i-listen-for-new-pit-results)
- [How do I listen for new PIT mutations results?](#how-do-i-listen-for-new-pit-mutations-results)

## Overview

This folder defines Pitclipse's source plug-ins. Here is an overview of their purposes.

Bundle | Purpose
------ | -------
`org.pitest` | Wraps Pitest JAR as an Eclipse plug-in
`org.pitest.pitclipse.core` | Defines extension points and handlers forwarding Pitest results to registered extensions.
`org.pitest.pitclipse.launch` | Provides a PIT Mutation launch configuration.
`org.pitest.pitclipse.launch.ui` | Integrates Pitclipse's launch configurations within Eclipse IDE's UI.
`org.pitest.pitclipse.listeners` | Fragment for `org.pitest` allowing Pitest to discover Pitclipse's mutation listeners.
`org.pitest.pitclipse.preferences.ui` | Provides a Pitclipse Preferences page.
`org.pitest.pitclipse.runner` | Allows to execute Pitest within an Eclipse runtime.
`org.pitest.pitclipse.ui` | Provides views to display Pitest's results.
| Bundle | Purpose |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `org.pitest` | Wraps Pitest JARs as an Eclipse plug-in |
| `org.pitest.pitest-junit5-plugin` | Wraps JARs of the [pitest-junit5-plugin](https://github.com/pitest/pitest-junit5-plugin) as an Eclipse plug-in |
| `org.pitest.pitclipse.core` | Defines extension points and handlers forwarding Pitest results to registered extensions. |
| `org.pitest.pitclipse.launch` | Provides a PIT Mutation launch configuration. |
| `org.pitest.pitclipse.launch.ui` | Integrates Pitclipse's launch configurations within Eclipse IDE's UI. |
| `org.pitest.pitclipse.listeners` | Fragment for `org.pitest` allowing Pitest to discover Pitclipse's mutation listeners. |
| `org.pitest.pitclipse.preferences.ui` | Provides a Pitclipse Preferences page. |
| `org.pitest.pitclipse.runner` | Allows to execute Pitest within an Eclipse runtime. |
| `org.pitest.pitclipse.ui` | Provides views to display Pitest's results. |

## Event flow

Expand Down
2 changes: 1 addition & 1 deletion bundles/org.pitest.pitclipse.core/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Pitclipse Core
Bundle-SymbolicName: org.pitest.pitclipse.core;singleton:=true
Bundle-Version: 2.0.2
Bundle-Version: 2.1.0
Bundle-Activator: org.pitest.pitclipse.core.PitCoreActivator
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.11.1,4.0.0)",
org.eclipse.jdt.core;bundle-version="[3.11.2,4.0.0)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
*/
public class PitCoreActivator extends Plugin {

private static final String ORG_PITEST_JUNIT5_PLUGIN = "org.pitest.pitest-junit5-plugin";
private static final String ORG_PITEST_PITCLIPSE_LISTENERS = "org.pitest.pitclipse.listeners";
private static final String ORG_PITEST_PITCLIPSE_RUNNER = "org.pitest.pitclipse.runner";
private static final String ORG_PITEST = "org.pitest";
Expand All @@ -72,6 +73,8 @@ public class PitCoreActivator extends Plugin {
private IPreferenceStore preferences;

private ImmutableList<String> pitClasspath = of();

private ImmutableList<String> pitestJunit5PluginClasspath = of();

private File resultDir;

Expand All @@ -85,6 +88,10 @@ private void setPitClasspath(List<String> classpath) {
pitClasspath = copyOf(classpath);
}

public List<String> getPitestJunit5PluginClasspath() {
return pitestJunit5PluginClasspath;
}

public IPreferenceStore getPreferenceStore() {
if (preferences == null) {
preferences = new ScopedPreferenceStore(InstanceScope.INSTANCE, PLUGIN_ID);
Expand Down Expand Up @@ -130,6 +137,12 @@ public void start(BundleContext context) throws Exception { // NOPMD - Base
pitclipseClasspath.add(getBundleFile(Platform.getBundle(ORG_PITEST_PITCLIPSE_LISTENERS)).getCanonicalPath() + File.separator + "bin");
}
setPitClasspath(pitclipseClasspath.build());

if (Platform.getBundle(ORG_PITEST_JUNIT5_PLUGIN) != null) {
pitestJunit5PluginClasspath = ImmutableList.of(
getBundleFile(Platform.getBundle(ORG_PITEST_JUNIT5_PLUGIN)).getCanonicalPath() + File.separator + jarDir + File.separator + "pitest-junit5-plugin.jar"
);
}
}

private void setupStateDirectories() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Pitclipse Launch Configurations UI
Bundle-SymbolicName: org.pitest.pitclipse.launch.ui;singleton:=true
Bundle-Version: 2.0.2
Bundle-Version: 2.1.0
Bundle-Vendor: Pitest.org
Automatic-Module-Name: org.pitest.pitclipse.launch.ui
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Expand Down
5 changes: 3 additions & 2 deletions bundles/org.pitest.pitclipse.launch/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Pitclipse Launch Configurations
Bundle-SymbolicName: org.pitest.pitclipse.launch;singleton:=true
Bundle-Version: 2.0.2
Bundle-Version: 2.1.0
Bundle-Vendor: Pitest.org
Automatic-Module-Name: org.pitest.pitclipse.launch
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Expand All @@ -11,7 +11,8 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.11.1,4.0.0)",
org.eclipse.jdt.launching;bundle-version="[3.8.0,4.0.0)",
org.pitest.pitclipse.core,
org.pitest.pitclipse.runner,
org.eclipse.jdt.core;bundle-version="[3.11.2,4.0.0)"
org.eclipse.jdt.core;bundle-version="[3.11.2,4.0.0)",
org.eclipse.jdt.junit.core
Export-Package: org.pitest.pitclipse.launch,
org.pitest.pitclipse.launch.config
Import-Package: com.google.common.base;version="21.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.junit.JUnitCore;
import org.eclipse.jdt.launching.JavaLaunchDelegate;
import org.pitest.pitclipse.core.extension.handler.ExtensionPointHandler;
import org.pitest.pitclipse.core.extension.point.PitRuntimeOptions;
Expand All @@ -33,14 +37,14 @@
import org.pitest.pitclipse.launch.config.ProjectFinder;
import org.pitest.pitclipse.launch.config.SourceDirFinder;
import org.pitest.pitclipse.runner.PitOptions;
import org.pitest.pitclipse.runner.PitOptions.PitOptionsBuilder;
import org.pitest.pitclipse.runner.PitRunner;
import org.pitest.pitclipse.runner.config.PitConfiguration;
import org.pitest.pitclipse.runner.io.SocketProvider;

import java.util.List;

import static org.pitest.pitclipse.core.PitCoreActivator.getDefault;
import static org.pitest.pitclipse.core.PitCoreActivator.log;

/**
* <p>Abstract launch configuration used to execute PIT in a background VM.</p>
Expand All @@ -56,6 +60,7 @@ public abstract class AbstractPitLaunchDelegate extends JavaLaunchDelegate {
private static final String PIT_RUNNER = PitRunner.class.getCanonicalName();
private int portNumber;
private final PitConfiguration pitConfiguration;
private boolean projectUsesJunit5 = false;

public AbstractPitLaunchDelegate(PitConfiguration pitConfiguration) {
this.pitConfiguration = pitConfiguration;
Expand All @@ -72,11 +77,15 @@ public String getMainTypeName(ILaunchConfiguration launchConfig) throws CoreExce

@Override
public String[] getClasspath(ILaunchConfiguration launchConfig) throws CoreException {
List<String> newClasspath = ImmutableList.<String>builder()
.addAll(getDefault().getPitClasspath())
.addAll(ImmutableList.copyOf(super.getClasspath(launchConfig)))
.build();
log("Classpath: " + newClasspath);
ImmutableList.Builder<String> builder = ImmutableList.<String>builder()
.addAll(getDefault().getPitClasspath());
builder.addAll(ImmutableList.copyOf(super.getClasspath(launchConfig)));
if (projectUsesJunit5) {
// Allow Pitest to detect Junit5 tests
builder.addAll(getDefault().getPitestJunit5PluginClasspath());
}
List<String> newClasspath = builder.build();

return newClasspath.toArray(new String[newClasspath.size()]);
}

Expand All @@ -94,7 +103,10 @@ public void launch(ILaunchConfiguration configuration, String mode, ILaunch laun
.withPackageFinder(getPackageFinder()).withClassFinder(getClassFinder())
.withSourceDirFinder(getSourceDirFinder()).withPitConfiguration(pitConfiguration).build();

PitOptions options = configWrapper.getPitOptions();
projectUsesJunit5 = isJUnit5InClasspathOf(configWrapper.getProject());
PitOptionsBuilder optionsBuilder = configWrapper.getPitOptionsBuilder();
PitOptions options = optionsBuilder.withUseJUnit5(projectUsesJunit5)
.build();

super.launch(configuration, mode, launch, monitor);

Expand All @@ -104,6 +116,15 @@ public void launch(ILaunchConfiguration configuration, String mode, ILaunch laun
portNumber, options, configWrapper.getMutatedProjects()));

}

private static boolean isJUnit5InClasspathOf(IJavaProject project) throws JavaModelException {
for (IClasspathEntry classpathEntry : project.getRawClasspath()) {
if (JUnitCore.JUNIT5_CONTAINER_PATH.equals(classpathEntry.getPath())) {
return true;
}
}
return false;
}

protected abstract ProjectFinder getProjectFinder();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ public boolean isTestLaunch() throws CoreException {
}

public PitOptions getPitOptions() throws CoreException {
return getPitOptionsBuilder().build();
}

public PitOptions.PitOptionsBuilder getPitOptionsBuilder() throws CoreException {
List<String> classPath = getClassesFromProject();
List<File> sourceDirs = getSourceDirsForProject();
int threadCount = getThreadCount();
Expand All @@ -137,7 +141,7 @@ public PitOptions getPitOptions() throws CoreException {
List<String> packages = getPackagesToTest();
builder.withPackagesToTest(packages);
}
return builder.build();
return builder;
}

public static Builder builder() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Pitclipse's Pitest Listeners
Bundle-SymbolicName: org.pitest.pitclipse.listeners
Bundle-Version: 2.0.2
Bundle-Version: 2.1.0
Fragment-Host: org.pitest;bundle-version="1.4.11"
Automatic-Module-Name: org.pitest.pitclipse.listeners
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Pitclipse Preferences UI
Bundle-SymbolicName: org.pitest.pitclipse.preferences.ui;singleton:=true
Bundle-Version: 2.0.2
Bundle-Version: 2.1.0
Bundle-Vendor: Pitest.org
Automatic-Module-Name: org.pitest.pitclipse.preferences.ui
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Expand Down
2 changes: 1 addition & 1 deletion bundles/org.pitest.pitclipse.runner/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Pitclipse Runner
Bundle-SymbolicName: org.pitest.pitclipse.runner
Bundle-Version: 2.0.2
Bundle-Version: 2.1.0
Bundle-Vendor: Pitest.org
Automatic-Module-Name: org.pitest.pitclipse.runner
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ private String[] toCliArgs(PitOptions options) {
builder.addAll(mutatorsFrom(options));
builder.add("--timeoutConst", Integer.toString(options.getTimeout()));
builder.add("--timeoutFactor", options.getTimeoutFactor().toPlainString());
if (options.getUseJUnit5()) {
// Specify that the 'pitest-junit5-plugin' should be used to discover tests
builder.add("--testPlugin", "junit5");
}
String additionalClasspath = additionalClassPath(options);
if (!additionalClasspath.isEmpty()) {
builder.add("--classPath", additionalClasspath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,12 @@ public final class PitOptions implements Serializable {
private final ImmutableList<String> mutators;
private final int timeout;
private final BigDecimal timeoutFactor;
private final boolean useJUnit5;

private PitOptions(String classUnderTest, ImmutableList<String> classesToMutate, ImmutableList<File> sourceDirs,
File reportDir, ImmutableList<String> packages, ImmutableList<String> classPath, int threads, File historyLocation,
ImmutableList<String> excludedClasses, ImmutableList<String> excludedMethods,
ImmutableList<String> avoidCallsTo, ImmutableList<String> mutators, int timeout, BigDecimal timeoutFactor) {
ImmutableList<String> avoidCallsTo, ImmutableList<String> mutators, int timeout, BigDecimal timeoutFactor, boolean useJUnit5) {
this.classUnderTest = classUnderTest;
this.threads = threads;
this.historyLocation = historyLocation;
Expand All @@ -73,6 +74,7 @@ private PitOptions(String classUnderTest, ImmutableList<String> classesToMutate,
this.mutators = mutators;
this.timeout = timeout;
this.timeoutFactor = timeoutFactor;
this.useJUnit5 = useJUnit5;
}

public File getReportDirectory() {
Expand Down Expand Up @@ -102,6 +104,7 @@ public static final class PitOptionsBuilder {
private ImmutableList<String> mutators = copyOf(split(DEFAULT_MUTATORS));
private int timeout = 3000;
private BigDecimal timeoutFactor = BigDecimal.valueOf(1.25);
private boolean useJUnit5 = false;

private PitOptionsBuilder() {
}
Expand Down Expand Up @@ -136,7 +139,8 @@ public PitOptions build() {
initialiseReportDir();
initialiseHistoryLocation();
return new PitOptions(classUnderTest, classesToMutate, sourceDirs, reportDir, packages, classPath, threads,
historyLocation, excludedClasses, excludedMethods, avoidCallsTo, mutators, timeout, timeoutFactor);
historyLocation, excludedClasses, excludedMethods, avoidCallsTo, mutators, timeout, timeoutFactor,
useJUnit5);
}

private void initialiseReportDir() {
Expand Down Expand Up @@ -242,6 +246,11 @@ public PitOptionsBuilder withMutators(List<String> mutators) {
return this;
}

public PitOptionsBuilder withUseJUnit5(boolean useJUnit5) {
this.useJUnit5 = useJUnit5;
return this;
}

private static List<String> split(String toSplit) {
return ImmutableList.copyOf(Splitter.on(',').trimResults().omitEmptyStrings().split(toSplit));
}
Expand Down Expand Up @@ -310,6 +319,10 @@ public int getTimeout() {
public BigDecimal getTimeoutFactor() {
return timeoutFactor;
}

public boolean getUseJUnit5() {
return useJUnit5;
}

@Override
public String toString() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,19 @@ public static void main(String[] args) {

try (PitClient client = new PitClient(port)) {
client.connect();
System.out.println("Connected");
Optional<PitRequest> request = client.readRequest();
Optional<PitResults> results = request.transform(executePit());

results.toJavaUtil().ifPresent(client::sendResults);
System.out.println("Closing server");

} catch (IOException e) {
// An error occurred while closing the client
e.printStackTrace();
}
System.out.println("Closed");
}

public static Function<PitRequest, PitResults> executePit() {
return request -> {
System.out.println("Received request: " + request);
String[] cliArgs = PitCliArguments.from(request.getOptions());
MutationCoverageReport.main(cliArgs);
File reportDir = request.getReportDirectory();
Expand All @@ -69,7 +65,6 @@ public static Function<PitRequest, PitResults> executePit() {
.withProjects(request.getProjects())
.withMutations(mutations)
.build();
System.out.println("Sending results: " + results);
return results;
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ public ObjectStreamSocket listen(int portNumber) {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(portNumber);
System.out.println("Listening on: " + serverSocket.getInetAddress() + ":" + portNumber);
Socket connection = serverSocket.accept();
return ObjectStreamSocket.make(connection);
} catch (IOException e) {
Expand Down Expand Up @@ -94,7 +93,6 @@ private Optional<ObjectStreamSocket> doConnect(int portNumber) {
try {
InetAddress localhost = InetAddress.getByName(null);
Socket socket = new Socket();
System.out.println("Connecting to: " + localhost + ":" + portNumber);
SocketAddress endpoint = new InetSocketAddress(localhost, portNumber);
socket.connect(endpoint, DEFAULT_TIMEOUT);
return Optional.of(ObjectStreamSocket.make(socket));
Expand Down
Loading