diff --git a/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestWorker.java b/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestWorker.java index 1f257f624..0cb9480fe 100644 --- a/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestWorker.java +++ b/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestWorker.java @@ -38,6 +38,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.concurrent.ConcurrentLinkedDeque; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -168,11 +169,11 @@ private static Container createNewContainer() { return new UnContainer() { @Override public List execute(final TestUnit group) { - final List results = new ArrayList<>(); + final Collection results = new ConcurrentLinkedDeque<>(); final ExitingResultCollector rc = new ExitingResultCollector( new ConcreteResultCollector(results)); group.execute(rc); - return results; + return new ArrayList<>(results); } }; } diff --git a/pitest/src/main/java/org/pitest/testapi/ResultCollector.java b/pitest/src/main/java/org/pitest/testapi/ResultCollector.java index 8d7806395..b23739701 100644 --- a/pitest/src/main/java/org/pitest/testapi/ResultCollector.java +++ b/pitest/src/main/java/org/pitest/testapi/ResultCollector.java @@ -14,6 +14,11 @@ */ package org.pitest.testapi; +/** + * All implementations of this interface should be thread-safe, as the methods can be + * called from various threads and also from parallel running tests, depending on the used + * test engine. + */ public interface ResultCollector { void notifyEnd(Description description, Throwable t); diff --git a/pitest/src/main/java/org/pitest/testapi/TestUnitExecutionListener.java b/pitest/src/main/java/org/pitest/testapi/TestUnitExecutionListener.java index e807d71db..3529329f4 100644 --- a/pitest/src/main/java/org/pitest/testapi/TestUnitExecutionListener.java +++ b/pitest/src/main/java/org/pitest/testapi/TestUnitExecutionListener.java @@ -8,6 +8,10 @@ *

At least one of the {@code executionStarted} methods needs to be overwritten * by subclasses as the default implementations call each other for backwards compatibility * and thus would cause a stack overflow error if called. + * + *

All implementations of this interface should be thread-safe, as the methods can be + * called from various threads and also from parallel running tests, depending on the used + * test engine. */ public interface TestUnitExecutionListener { default void executionStarted(Description description) { diff --git a/pitest/src/main/java/org/pitest/testapi/execute/ExitingResultCollector.java b/pitest/src/main/java/org/pitest/testapi/execute/ExitingResultCollector.java index 7dac22150..686a8096a 100644 --- a/pitest/src/main/java/org/pitest/testapi/execute/ExitingResultCollector.java +++ b/pitest/src/main/java/org/pitest/testapi/execute/ExitingResultCollector.java @@ -17,10 +17,12 @@ import org.pitest.testapi.Description; import org.pitest.testapi.ResultCollector; +import java.util.concurrent.atomic.AtomicBoolean; + public class ExitingResultCollector implements ResultCollector { private final ResultCollector child; - private boolean hadFailure = false; + private final AtomicBoolean hadFailure = new AtomicBoolean(false); public ExitingResultCollector(final ResultCollector child) { this.child = child; @@ -38,14 +40,14 @@ public void notifyStart(final Description description) { @Override public boolean shouldExit() { - return this.hadFailure; + return this.hadFailure.get(); } @Override public void notifyEnd(final Description description, final Throwable t) { this.child.notifyEnd(description, t); if (t != null) { - this.hadFailure = true; + this.hadFailure.set(true); } } @@ -55,4 +57,4 @@ public void notifyEnd(final Description description) { this.child.notifyEnd(description); } -} \ No newline at end of file +} diff --git a/pitest/src/main/java/org/pitest/testapi/execute/containers/ConcreteResultCollector.java b/pitest/src/main/java/org/pitest/testapi/execute/containers/ConcreteResultCollector.java index e45f979c6..7a007cfca 100644 --- a/pitest/src/main/java/org/pitest/testapi/execute/containers/ConcreteResultCollector.java +++ b/pitest/src/main/java/org/pitest/testapi/execute/containers/ConcreteResultCollector.java @@ -25,6 +25,11 @@ public final class ConcreteResultCollector implements ResultCollector { private final Collection feedback; + /** + * @param feedback the collection where to collect test results; this collection should be thread-safe + * as it can be called from various threads and also from parallel running tests, + * depending on the used test engine. + */ public ConcreteResultCollector(final Collection feedback) { this.feedback = feedback; } diff --git a/pitest/src/main/java/org/pitest/testapi/execute/containers/UnContainer.java b/pitest/src/main/java/org/pitest/testapi/execute/containers/UnContainer.java index a1dde0217..8f228be56 100644 --- a/pitest/src/main/java/org/pitest/testapi/execute/containers/UnContainer.java +++ b/pitest/src/main/java/org/pitest/testapi/execute/containers/UnContainer.java @@ -16,7 +16,9 @@ package org.pitest.testapi.execute.containers; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.concurrent.ConcurrentLinkedDeque; import org.pitest.testapi.TestResult; import org.pitest.testapi.TestUnit; @@ -26,10 +28,10 @@ public class UnContainer implements Container { @Override public List execute(final TestUnit group) { - final List results = new ArrayList<>(12); + final Collection results = new ConcurrentLinkedDeque<>(); final ConcreteResultCollector rc = new ConcreteResultCollector(results); group.execute(rc); - return results; + return new ArrayList<>(results); } }