diff --git a/pitest-entry/src/main/java/org/pitest/coverage/execute/CoverageCommunicationThread.java b/pitest-entry/src/main/java/org/pitest/coverage/execute/CoverageCommunicationThread.java deleted file mode 100644 index 1e29bd1e6..000000000 --- a/pitest-entry/src/main/java/org/pitest/coverage/execute/CoverageCommunicationThread.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.pitest.coverage.execute; - -import java.net.ServerSocket; -import java.util.List; -import java.util.function.Consumer; - -import org.pitest.coverage.CoverageResult; -import org.pitest.util.CommunicationThread; - -public class CoverageCommunicationThread extends CommunicationThread { - - public CoverageCommunicationThread(final ServerSocket socket, - final CoverageOptions arguments, final List tus, - final Consumer handler) { - super(socket, new SendData(arguments, tus), new Receive(handler)); - - } - -} diff --git a/pitest-entry/src/main/java/org/pitest/coverage/execute/CoverageProcess.java b/pitest-entry/src/main/java/org/pitest/coverage/execute/CoverageProcess.java index 1eb127a07..f5f49d7b0 100644 --- a/pitest-entry/src/main/java/org/pitest/coverage/execute/CoverageProcess.java +++ b/pitest-entry/src/main/java/org/pitest/coverage/execute/CoverageProcess.java @@ -9,20 +9,21 @@ import org.pitest.coverage.CoverageResult; import org.pitest.process.ProcessArgs; import org.pitest.process.WrappingProcess; +import org.pitest.util.CommunicationThread; import org.pitest.util.ExitCode; public class CoverageProcess { private final WrappingProcess process; - private final CoverageCommunicationThread crt; + private final CommunicationThread crt; public CoverageProcess(final ProcessArgs processArgs, final CoverageOptions arguments, final ServerSocket socket, final List testClasses, final Consumer handler) { this.process = new WrappingProcess(socket.getLocalPort(), processArgs, CoverageMinion.class); - this.crt = new CoverageCommunicationThread(socket, arguments, testClasses, - handler); + + this.crt = new CommunicationThread(socket, new SendData(arguments, testClasses), new Receive(handler)); } public void start() throws IOException, InterruptedException { diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/execute/MutationTestCommunicationThread.java b/pitest-entry/src/main/java/org/pitest/mutationtest/execute/MutationTestCommunicationThread.java deleted file mode 100644 index 9fa078b0c..000000000 --- a/pitest-entry/src/main/java/org/pitest/mutationtest/execute/MutationTestCommunicationThread.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2011 Henry Coles - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and limitations under the License. - */ -package org.pitest.mutationtest.execute; - -import java.net.ServerSocket; -import java.util.Map; -import java.util.function.Consumer; -import java.util.logging.Logger; - -import org.pitest.mutationtest.DetectionStatus; -import org.pitest.mutationtest.MutationStatusTestPair; -import org.pitest.mutationtest.engine.MutationIdentifier; -import org.pitest.util.CommunicationThread; -import org.pitest.util.Id; -import org.pitest.util.Log; -import org.pitest.util.ReceiveStrategy; -import org.pitest.util.SafeDataInputStream; -import org.pitest.util.SafeDataOutputStream; - -public class MutationTestCommunicationThread extends CommunicationThread { - - private static final Logger LOG = Log.getLogger(); - - private static class SendData implements Consumer { - private final MinionArguments arguments; - - SendData(final MinionArguments arguments) { - this.arguments = arguments; - } - - @Override - public void accept(final SafeDataOutputStream dos) { - dos.write(this.arguments); - dos.flush(); - } - } - - private static class Receive implements ReceiveStrategy { - - private final Map idMap; - - Receive(final Map idMap) { - this.idMap = idMap; - } - - @Override - public void apply(final byte control, final SafeDataInputStream is) { - switch (control) { - case Id.DESCRIBE: - handleDescribe(is); - break; - case Id.REPORT: - handleReport(is); - break; - } - } - - private void handleReport(final SafeDataInputStream is) { - final MutationIdentifier mutation = is.read(MutationIdentifier.class); - final MutationStatusTestPair value = is - .read(MutationStatusTestPair.class); - this.idMap.put(mutation, value); - LOG.fine(mutation + " " + value); - } - - private void handleDescribe(final SafeDataInputStream is) { - final MutationIdentifier mutation = is.read(MutationIdentifier.class); - this.idMap.put(mutation, MutationStatusTestPair.notAnalysed(1, - DetectionStatus.STARTED)); - } - - } - - private final Map idMap; - - public MutationTestCommunicationThread(final ServerSocket socket, - final MinionArguments arguments, - final Map idMap) { - super(socket, new SendData(arguments), new Receive(idMap)); - this.idMap = idMap; - } - - public MutationStatusTestPair getStatus(final MutationIdentifier id) { - return this.idMap.get(id); - } - -} diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/execute/MutationTestProcess.java b/pitest-entry/src/main/java/org/pitest/mutationtest/execute/MutationTestProcess.java index f817b76c3..7d921ae63 100644 --- a/pitest-entry/src/main/java/org/pitest/mutationtest/execute/MutationTestProcess.java +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/execute/MutationTestProcess.java @@ -2,27 +2,32 @@ import java.io.IOException; import java.net.ServerSocket; -import java.util.HashMap; +import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import org.pitest.mutationtest.MutationStatusMap; import org.pitest.mutationtest.MutationStatusTestPair; import org.pitest.mutationtest.engine.MutationDetails; +import org.pitest.mutationtest.engine.MutationIdentifier; import org.pitest.process.ProcessArgs; import org.pitest.process.WrappingProcess; +import org.pitest.util.CommunicationThread; import org.pitest.util.ExitCode; public class MutationTestProcess { - private final WrappingProcess process; - private final MutationTestCommunicationThread thread; + private final WrappingProcess process; + private final CommunicationThread thread; + private final Map idMap; public MutationTestProcess(final ServerSocket socket, final ProcessArgs processArgs, final MinionArguments arguments) { this.process = new WrappingProcess(socket.getLocalPort(), processArgs, MutationTestMinion.class); - this.thread = new MutationTestCommunicationThread(socket, arguments, - new HashMap<>()); + + this.idMap = new ConcurrentHashMap<>(); + this.thread = new CommunicationThread(socket, new SendData(arguments), new Receive(idMap)); } @@ -34,7 +39,7 @@ public void start() throws IOException, InterruptedException { public void results(final MutationStatusMap allmutations) throws IOException { for (final MutationDetails each : allmutations.allMutations()) { - final MutationStatusTestPair status = this.thread.getStatus(each.getId()); + final MutationStatusTestPair status = this.idMap.get(each.getId()); if (status != null) { allmutations.setStatusForMutation(each, status); } @@ -44,10 +49,20 @@ public void results(final MutationStatusMap allmutations) throws IOException { public ExitCode waitToDie() { try { + // Wait a moment to give the monitoring thread time to finish naturally. This + // happens when the monitored process sends a "DONE" signal over the socket, + // the process itself should exit shortly after sending the signal Optional maybeExit = this.thread.waitToFinish(5); + + // While the monitored process reports being alive, keep polling + // the monitoring thread to see if it has finished. while (!maybeExit.isPresent() && this.process.isAlive()) { maybeExit = this.thread.waitToFinish(10); } + + // If the monitored thread is still live, but the process is dead + // then either the process never properly started or it died + // before reporting its exit return maybeExit.orElse(ExitCode.MINION_DIED); } finally { this.process.destroy(); diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/execute/Receive.java b/pitest-entry/src/main/java/org/pitest/mutationtest/execute/Receive.java new file mode 100644 index 000000000..ef17ae79e --- /dev/null +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/execute/Receive.java @@ -0,0 +1,49 @@ +package org.pitest.mutationtest.execute; + +import org.pitest.mutationtest.DetectionStatus; +import org.pitest.mutationtest.MutationStatusTestPair; +import org.pitest.mutationtest.engine.MutationIdentifier; +import org.pitest.util.Id; +import org.pitest.util.Log; +import org.pitest.util.ReceiveStrategy; +import org.pitest.util.SafeDataInputStream; + +import java.util.Map; +import java.util.logging.Logger; + +class Receive implements ReceiveStrategy { + private static final Logger LOG = Log.getLogger(); + + private final Map idMap; + + Receive(final Map idMap) { + this.idMap = idMap; + } + + @Override + public void apply(final byte control, final SafeDataInputStream is) { + switch (control) { + case Id.DESCRIBE: + handleDescribe(is); + break; + case Id.REPORT: + handleReport(is); + break; + } + } + + private void handleReport(final SafeDataInputStream is) { + final MutationIdentifier mutation = is.read(MutationIdentifier.class); + final MutationStatusTestPair value = is + .read(MutationStatusTestPair.class); + this.idMap.put(mutation, value); + LOG.fine(mutation + " " + value); + } + + private void handleDescribe(final SafeDataInputStream is) { + final MutationIdentifier mutation = is.read(MutationIdentifier.class); + this.idMap.put(mutation, MutationStatusTestPair.notAnalysed(1, + DetectionStatus.STARTED)); + } + +} \ No newline at end of file diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/execute/SendData.java b/pitest-entry/src/main/java/org/pitest/mutationtest/execute/SendData.java new file mode 100644 index 000000000..32213e5be --- /dev/null +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/execute/SendData.java @@ -0,0 +1,19 @@ +package org.pitest.mutationtest.execute; + +import org.pitest.util.SafeDataOutputStream; + +import java.util.function.Consumer; + +class SendData implements Consumer { + private final MinionArguments arguments; + + SendData(final MinionArguments arguments) { + this.arguments = arguments; + } + + @Override + public void accept(final SafeDataOutputStream dos) { + dos.write(this.arguments); + dos.flush(); + } +} diff --git a/pitest-entry/src/main/java/org/pitest/util/CommunicationThread.java b/pitest-entry/src/main/java/org/pitest/util/CommunicationThread.java index 64bf3ff8f..08c42e493 100644 --- a/pitest-entry/src/main/java/org/pitest/util/CommunicationThread.java +++ b/pitest-entry/src/main/java/org/pitest/util/CommunicationThread.java @@ -25,7 +25,7 @@ import java.util.logging.Level; import java.util.logging.Logger; -public class CommunicationThread { +public final class CommunicationThread { private static final Logger LOG = Log.getLogger();