You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2015/09/22 08:01:12 UTC
[3/4] maven-surefire git commit: [SUREFIRE-524] Forked Process not
terminated if maven process aborted. Provide means to clean up.
[SUREFIRE-524] Forked Process not terminated if maven process aborted. Provide means to clean up.
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/cb97ba70
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/cb97ba70
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/cb97ba70
Branch: refs/heads/master
Commit: cb97ba70cb9ebe685f8f2a06e87b538795b5dd9b
Parents: c8ddd6b
Author: Tibor17 <ti...@lycos.com>
Authored: Tue Sep 22 07:52:49 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Tue Sep 22 07:52:49 2015 +0200
----------------------------------------------------------------------
.../plugin/failsafe/IntegrationTestMojo.java | 18 +++
.../plugin/surefire/AbstractSurefireMojo.java | 15 ++-
.../surefire/SurefireExecutionParameters.java | 2 +
.../surefire/booterclient/BooterSerializer.java | 1 +
.../surefire/booterclient/ForkStarter.java | 34 +++---
.../lazytestprovider/NotifiableTestStream.java | 4 +-
.../lazytestprovider/TestLessInputStream.java | 15 +--
.../TestProvidingInputStream.java | 13 ++-
...erDeserializerProviderConfigurationTest.java | 2 +-
...terDeserializerStartupConfigurationTest.java | 2 +-
.../TestLessInputStreamBuilderTest.java | 13 ++-
.../maven/plugin/surefire/SurefirePlugin.java | 18 +++
.../src/site/apt/examples/shutdown.apt.vm | 78 +++++++++++++
maven-surefire-plugin/src/site/apt/index.apt.vm | 2 +
maven-surefire-plugin/src/site/site.xml | 1 +
.../surefire/booter/BaseProviderFactory.java | 14 ++-
.../apache/maven/surefire/booter/Command.java | 33 +++++-
.../surefire/booter/MasterProcessCommand.java | 12 +-
.../surefire/booter/MasterProcessReader.java | 116 +++++++++++++++----
.../apache/maven/surefire/booter/Shutdown.java | 84 ++++++++++++++
.../maven/surefire/booter/ShutdownAware.java | 31 +++++
.../surefire/booter/SurefireReflector.java | 24 +++-
.../providerapi/ProviderParameters.java | 3 +
.../surefire/util/internal/StringUtils.java | 26 +++++
.../booter/MasterProcessCommandTest.java | 8 +-
.../maven/surefire/booter/BooterConstants.java | 1 +
.../surefire/booter/BooterDeserializer.java | 4 +-
.../maven/surefire/booter/ForkedBooter.java | 30 ++---
.../surefire/booter/ProviderConfiguration.java | 14 ++-
.../maven/surefire/booter/ProviderFactory.java | 1 +
.../maven/surefire/junit4/JUnit4Provider.java | 4 +-
.../surefire/junitcore/JUnitCoreProvider.java | 4 +-
.../maven/surefire/testng/TestNGProvider.java | 4 +-
33 files changed, 539 insertions(+), 92 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
index b359048..5e0c7ea 100644
--- a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
+++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
@@ -315,6 +315,19 @@ public class IntegrationTestMojo
@Parameter( property = "failsafe.skipAfterFailureCount", defaultValue = "0" )
private int skipAfterFailureCount;
+ /**
+ * After the plugin process is shutdown by sending SIGTERM signal (CTRL+C), SHUTDOWN command is received by every
+ * forked JVM. By default (shutdown=testset) forked JVM would not continue with new test which means that
+ * the current test may still continue to run.<br/>
+ * The parameter can be configured with other two values "exit" and "kill".<br/>
+ * Using "exit" forked JVM executes System.exit(1) after the plugin process has received SIGTERM signal.<br/>
+ * Using "kill" the JVM executes Runtime.halt(1) and kills itself.
+ *
+ * @since 2.19
+ */
+ @Parameter( property = "failsafe.shutdown", defaultValue = "testset" )
+ private String shutdown;
+
protected int getRerunFailingTestsCount()
{
return rerunFailingTestsCount;
@@ -613,6 +626,11 @@ public class IntegrationTestMojo
return skipAfterFailureCount;
}
+ public String getShutdown()
+ {
+ return shutdown;
+ }
+
@Override
public List<String> getIncludes()
{
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
index ff2e51e..d67e29f 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
@@ -76,6 +76,7 @@ import org.apache.maven.surefire.booter.ClasspathConfiguration;
import org.apache.maven.surefire.booter.KeyValueSource;
import org.apache.maven.surefire.booter.ProviderConfiguration;
import org.apache.maven.surefire.booter.ProviderParameterNames;
+import org.apache.maven.surefire.booter.Shutdown;
import org.apache.maven.surefire.booter.StartupConfiguration;
import org.apache.maven.surefire.booter.SurefireBooterForkException;
import org.apache.maven.surefire.booter.SurefireExecutionException;
@@ -827,6 +828,7 @@ public abstract class AbstractSurefireMojo
warnIfUselessUseSystemClassLoaderParameter();
warnIfDefunctGroupsCombinations();
warnIfRerunClashes();
+ warnIfWrongShutdownValue();
}
return true;
}
@@ -1467,7 +1469,8 @@ public abstract class AbstractSurefireMojo
reporterConfiguration,
testNg, // Not really used in provider. Limited to de/serializer.
testSuiteDefinition, providerProperties, null,
- false, cli, getSkipAfterFailureCount() );
+ false, cli, getSkipAfterFailureCount(),
+ Shutdown.parameterOf( getShutdown() ) );
}
private static Map<String, String> toStringProperties( Properties properties )
@@ -1973,6 +1976,7 @@ public abstract class AbstractSurefireMojo
checksum.add( getTestSourceDirectory() );
checksum.add( getTest() );
checksum.add( getIncludes() );
+ checksum.add( getShutdown() );
checksum.add( getExcludes() );
checksum.add( getLocalRepository() );
checksum.add( getSystemProperties() );
@@ -2365,6 +2369,15 @@ public abstract class AbstractSurefireMojo
}
}
+ private void warnIfWrongShutdownValue()
+ throws MojoFailureException
+ {
+ if ( !Shutdown.isKnown( getShutdown() ) )
+ {
+ throw new MojoFailureException( "Parameter \"shutdown\" should have values " + Shutdown.listParameters() );
+ }
+ }
+
final class TestNgProviderInfo
implements ProviderInfo
{
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
index 6bd09ff..247f5e8 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
@@ -120,4 +120,6 @@ public interface SurefireExecutionParameters
void setFailIfNoSpecifiedTests( boolean failIfNoSpecifiedTests );
int getSkipAfterFailureCount();
+
+ String getShutdown();
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
index 139e14b..21807f5 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
@@ -134,6 +134,7 @@ class BooterSerializer
properties.setProperty( FAILIFNOTESTS, String.valueOf( booterConfiguration.isFailIfNoTests() ) );
properties.setProperty( PROVIDER_CONFIGURATION, providerConfiguration.getProviderClassName() );
properties.setProperty( FAIL_FAST_COUNT, String.valueOf( booterConfiguration.getSkipAfterFailureCount() ) );
+ properties.setProperty( SHUTDOWN, booterConfiguration.getShutdown().name() );
List<CommandLineOption> mainCliOptions = booterConfiguration.getMainCliOptions();
if ( mainCliOptions != null )
{
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
index 39680b1..4742b7c 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
@@ -39,6 +39,7 @@ import org.apache.maven.surefire.booter.KeyValueSource;
import org.apache.maven.surefire.booter.PropertiesWrapper;
import org.apache.maven.surefire.booter.ProviderConfiguration;
import org.apache.maven.surefire.booter.ProviderFactory;
+import org.apache.maven.surefire.booter.Shutdown;
import org.apache.maven.surefire.booter.StartupConfiguration;
import org.apache.maven.surefire.booter.SurefireBooterForkException;
import org.apache.maven.surefire.booter.SurefireExecutionException;
@@ -109,9 +110,11 @@ public class ForkStarter
{
private static final long PING_IN_SECONDS = 10;
- private static final ThreadFactory DAEMON_THREAD_FACTORY = newDaemonThreadFactory();
+ private static final ThreadFactory FORKED_JVM_DAEMON_THREAD_FACTORY
+ = newDaemonThreadFactory( "surefire-fork-starter" );
- private static final ThreadFactory SHUTDOWN_HOOK_THREAD_FACTORY = newDaemonThreadFactory();
+ private static final ThreadFactory SHUTDOWN_HOOK_THREAD_FACTORY
+ = newDaemonThreadFactory( "surefire-jvm-killer-shutdownhook" );
private final ScheduledExecutorService pingThreadScheduler = createPingScheduler();
@@ -207,7 +210,7 @@ public class ForkStarter
new ForkClient( forkedReporterFactory, startupReportConfiguration.getTestVmSystemProperties() );
TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
TestLessInputStream stream = builder.build();
- Thread shutdown = createImmediateShutdownHookThread( builder );
+ Thread shutdown = createImmediateShutdownHookThread( builder, providerConfiguration.getShutdown() );
ScheduledFuture<?> ping = triggerPingTimerForShutdown( builder );
try
{
@@ -248,7 +251,7 @@ public class ForkStarter
{
ThreadPoolExecutor executorService = new ThreadPoolExecutor( forkCount, forkCount, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>( forkCount ) );
- executorService.setThreadFactory( DAEMON_THREAD_FACTORY );
+ executorService.setThreadFactory( FORKED_JVM_DAEMON_THREAD_FACTORY );
final Queue<String> tests = new ConcurrentLinkedQueue<String>();
@@ -265,7 +268,7 @@ public class ForkStarter
}
ScheduledFuture<?> ping = triggerPingTimerForShutdown( testStreams );
- Thread shutdown = createShutdownHookThread( testStreams );
+ Thread shutdown = createShutdownHookThread( testStreams, providerConfiguration.getShutdown() );
try
{
@@ -328,10 +331,10 @@ public class ForkStarter
ArrayList<Future<RunResult>> results = new ArrayList<Future<RunResult>>( 500 );
ThreadPoolExecutor executorService =
new ThreadPoolExecutor( forkCount, forkCount, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>() );
- executorService.setThreadFactory( DAEMON_THREAD_FACTORY );
+ executorService.setThreadFactory( FORKED_JVM_DAEMON_THREAD_FACTORY );
final TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
ScheduledFuture<?> ping = triggerPingTimerForShutdown( builder );
- Thread shutdown = createCachableShutdownHookThread( builder );
+ Thread shutdown = createCachableShutdownHookThread( builder, providerConfiguration.getShutdown() );
try
{
addShutDownHook( shutdown );
@@ -602,29 +605,32 @@ public class ForkStarter
}
}
- private static Thread createImmediateShutdownHookThread( final TestLessInputStreamBuilder builder )
+ private static Thread createImmediateShutdownHookThread( final TestLessInputStreamBuilder builder,
+ final Shutdown shutdownType )
{
return SHUTDOWN_HOOK_THREAD_FACTORY.newThread( new Runnable()
{
public void run()
{
- builder.getImmediateCommands().shutdown();
+ builder.getImmediateCommands().shutdown( shutdownType );
}
} );
}
- private static Thread createCachableShutdownHookThread( final TestLessInputStreamBuilder builder )
+ private static Thread createCachableShutdownHookThread( final TestLessInputStreamBuilder builder,
+ final Shutdown shutdownType )
{
return SHUTDOWN_HOOK_THREAD_FACTORY.newThread( new Runnable()
{
public void run()
{
- builder.getCachableCommands().shutdown();
+ builder.getCachableCommands().shutdown( shutdownType );
}
} );
}
- private static Thread createShutdownHookThread( final Iterable<TestProvidingInputStream> streams )
+ private static Thread createShutdownHookThread( final Iterable<TestProvidingInputStream> streams,
+ final Shutdown shutdownType )
{
return SHUTDOWN_HOOK_THREAD_FACTORY.newThread( new Runnable()
{
@@ -632,7 +638,7 @@ public class ForkStarter
{
for ( TestProvidingInputStream stream : streams )
{
- stream.shutdown();
+ stream.shutdown( shutdownType );
}
}
} );
@@ -640,7 +646,7 @@ public class ForkStarter
private static ScheduledExecutorService createPingScheduler()
{
- ThreadFactory threadFactory = newDaemonThreadFactory( "ping-thread-" + PING_IN_SECONDS + "sec" );
+ ThreadFactory threadFactory = newDaemonThreadFactory( "ping-timer-" + PING_IN_SECONDS + "sec" );
return Executors.newScheduledThreadPool( 1, threadFactory );
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/NotifiableTestStream.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/NotifiableTestStream.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/NotifiableTestStream.java
index d47645b..5c89173 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/NotifiableTestStream.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/NotifiableTestStream.java
@@ -19,6 +19,8 @@ package org.apache.maven.plugin.surefire.booterclient.lazytestprovider;
* under the License.
*/
+import org.apache.maven.surefire.booter.Shutdown;
+
/**
* Forked jvm notifies master process to provide a new test.
*
@@ -40,7 +42,7 @@ public interface NotifiableTestStream
*/
void skipSinceNextTest();
- void shutdown();
+ void shutdown( Shutdown shutdownType );
void noop();
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStream.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStream.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStream.java
index b15af89..04d39b3 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStream.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStream.java
@@ -20,6 +20,7 @@ package org.apache.maven.plugin.surefire.booterclient.lazytestprovider;
*/
import org.apache.maven.surefire.booter.Command;
+import org.apache.maven.surefire.booter.Shutdown;
import java.io.IOException;
import java.util.Iterator;
@@ -33,8 +34,8 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import static org.apache.maven.surefire.booter.Command.NOOP;
-import static org.apache.maven.surefire.booter.Command.SHUTDOWN;
import static org.apache.maven.surefire.booter.Command.SKIP_SINCE_NEXT_TEST;
+import static org.apache.maven.surefire.booter.Command.toShutdown;
/**
* Dispatches commands without tests.
@@ -73,11 +74,11 @@ public final class TestLessInputStream
}
}
- public void shutdown()
+ public void shutdown( Shutdown shutdownType )
{
if ( canContinue() )
{
- immediateCommands.add( SHUTDOWN );
+ immediateCommands.add( toShutdown( shutdownType ) );
barrier.release();
}
}
@@ -336,7 +337,7 @@ public final class TestLessInputStream
}
}
- public void shutdown()
+ public void shutdown( Shutdown shutdownType )
{
Lock lock = rwLock.readLock();
lock.lock();
@@ -344,7 +345,7 @@ public final class TestLessInputStream
{
for ( TestLessInputStream aliveStream : TestLessInputStreamBuilder.this.aliveStreams )
{
- aliveStream.shutdown();
+ aliveStream.shutdown( shutdownType );
}
}
finally
@@ -398,13 +399,13 @@ public final class TestLessInputStream
}
}
- public void shutdown()
+ public void shutdown( Shutdown shutdownType )
{
Lock lock = rwLock.readLock();
lock.lock();
try
{
- if ( TestLessInputStreamBuilder.this.addTailNodeIfAbsent( SHUTDOWN ) )
+ if ( TestLessInputStreamBuilder.this.addTailNodeIfAbsent( toShutdown( shutdownType ) ) )
{
release();
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStream.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStream.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStream.java
index dcc2997..766843d 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStream.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStream.java
@@ -20,6 +20,7 @@ package org.apache.maven.plugin.surefire.booterclient.lazytestprovider;
*/
import org.apache.maven.surefire.booter.Command;
+import org.apache.maven.surefire.booter.Shutdown;
import java.io.IOException;
import java.util.Queue;
@@ -27,11 +28,11 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
-import static org.apache.maven.surefire.booter.MasterProcessCommand.RUN_CLASS;
import static org.apache.maven.surefire.booter.MasterProcessCommand.TEST_SET_FINISHED;
-import static org.apache.maven.surefire.booter.Command.SKIP_SINCE_NEXT_TEST;
-import static org.apache.maven.surefire.booter.Command.SHUTDOWN;
import static org.apache.maven.surefire.booter.Command.NOOP;
+import static org.apache.maven.surefire.booter.Command.SKIP_SINCE_NEXT_TEST;
+import static org.apache.maven.surefire.booter.Command.toRunClass;
+import static org.apache.maven.surefire.booter.Command.toShutdown;
/**
* An {@link java.io.InputStream} that, when read, provides test class names out of a queue.
@@ -90,11 +91,11 @@ public final class TestProvidingInputStream
}
}
- public void shutdown()
+ public void shutdown( Shutdown shutdownType )
{
if ( canContinue() )
{
- commands.add( SHUTDOWN );
+ commands.add( toShutdown( shutdownType ) );
barrier.release();
}
}
@@ -115,7 +116,7 @@ public final class TestProvidingInputStream
if ( cmd == null )
{
String cmdData = testClassNames.poll();
- return cmdData == null ? Command.TEST_SET_FINISHED : new Command( RUN_CLASS, cmdData );
+ return cmdData == null ? Command.TEST_SET_FINISHED : toRunClass( cmdData );
}
else
{
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
index 9c8cc07..623edf3 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
@@ -237,7 +237,7 @@ public class BooterDeserializerProviderConfigurationTest
RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, null );
return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, true, reporterConfiguration,
new TestArtifactInfo( "5.0", "ABC" ), testSuiteDefinition, new HashMap<String, String>(), aTestTyped,
- readTestsFromInStream, cli, 0 );
+ readTestsFromInStream, cli, 0, Shutdown.DEFAULT );
}
private StartupConfiguration getTestStartupConfiguration( ClassLoaderConfiguration classLoaderConfiguration )
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
index 6f232fa..007640d 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
@@ -144,7 +144,7 @@ public class BooterDeserializerStartupConfigurationTest
RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, null );
return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, true, reporterConfiguration,
new TestArtifactInfo( "5.0", "ABC" ), testSuiteDefinition, new HashMap<String, String>(),
- BooterDeserializerProviderConfigurationTest.aTestTyped, true, cli, 0 );
+ BooterDeserializerProviderConfigurationTest.aTestTyped, true, cli, 0, Shutdown.DEFAULT );
}
private StartupConfiguration getTestStartupConfiguration( ClassLoaderConfiguration classLoaderConfiguration )
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStreamBuilderTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStreamBuilderTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStreamBuilderTest.java
index c1a075f..6dee0a4 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStreamBuilderTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestLessInputStreamBuilderTest.java
@@ -30,8 +30,9 @@ import java.util.NoSuchElementException;
import static org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestLessInputStream.TestLessInputStreamBuilder;
import static org.apache.maven.surefire.booter.Command.NOOP;
-import static org.apache.maven.surefire.booter.Command.SHUTDOWN;
import static org.apache.maven.surefire.booter.Command.SKIP_SINCE_NEXT_TEST;
+import static org.apache.maven.surefire.booter.MasterProcessCommand.SHUTDOWN;
+import static org.apache.maven.surefire.booter.Shutdown.EXIT;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -103,24 +104,24 @@ public class TestLessInputStreamBuilderTest
assertThat( is.availablePermits(), is( 1 ) );
builder.getCachableCommands().skipSinceNextTest();
assertThat( is.availablePermits(), is( 1 ) );
- builder.getImmediateCommands().shutdown();
+ builder.getImmediateCommands().shutdown( EXIT );
assertThat( is.availablePermits(), is( 2 ) );
is.beforeNextCommand();
- assertThat( is.nextCommand(), is( SHUTDOWN ) );
+ assertThat( is.nextCommand().getCommandType(), is( SHUTDOWN ) );
assertThat( is.availablePermits(), is( 1 ) );
is.beforeNextCommand();
assertThat( is.nextCommand(), is( SKIP_SINCE_NEXT_TEST ) );
assertThat( is.availablePermits(), is( 0 ) );
builder.getImmediateCommands().noop();
assertThat( is.availablePermits(), is( 1 ) );
- builder.getCachableCommands().shutdown();
- builder.getCachableCommands().shutdown();
+ builder.getCachableCommands().shutdown( EXIT );
+ builder.getCachableCommands().shutdown( EXIT );
assertThat( is.availablePermits(), is( 2 ) );
is.beforeNextCommand();
assertThat( is.nextCommand(), is( NOOP ) );
assertThat( is.availablePermits(), is( 1 ) );
is.beforeNextCommand();
- assertThat( is.nextCommand(), is( SHUTDOWN ) );
+ assertThat( is.nextCommand().getCommandType(), is( SHUTDOWN ) );
assertThat( is.availablePermits(), is( 0 ) );
e.expect( NoSuchElementException.class );
is.nextCommand();
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
index b26b493..88bb107 100644
--- a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
+++ b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
@@ -292,6 +292,19 @@ public class SurefirePlugin
@Parameter( property = "surefire.skipAfterFailureCount", defaultValue = "0" )
private int skipAfterFailureCount;
+ /**
+ * After the plugin process is shutdown by sending SIGTERM signal (CTRL+C), SHUTDOWN command is received by every
+ * forked JVM. By default (shutdown=testset) forked JVM would not continue with new test which means that
+ * the current test may still continue to run.<br/>
+ * The parameter can be configured with other two values "exit" and "kill".<br/>
+ * Using "exit" forked JVM executes System.exit(1) after the plugin process has received SIGTERM signal.<br/>
+ * Using "kill" the JVM executes Runtime.halt(1) and kills itself.
+ *
+ * @since 2.19
+ */
+ @Parameter( property = "surefire.shutdown", defaultValue = "testset" )
+ private String shutdown;
+
protected int getRerunFailingTestsCount()
{
return rerunFailingTestsCount;
@@ -466,6 +479,11 @@ public class SurefirePlugin
return skipAfterFailureCount;
}
+ public String getShutdown()
+ {
+ return shutdown;
+ }
+
public boolean isPrintSummary()
{
return printSummary;
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-surefire-plugin/src/site/apt/examples/shutdown.apt.vm
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/apt/examples/shutdown.apt.vm b/maven-surefire-plugin/src/site/apt/examples/shutdown.apt.vm
new file mode 100644
index 0000000..f50710b
--- /dev/null
+++ b/maven-surefire-plugin/src/site/apt/examples/shutdown.apt.vm
@@ -0,0 +1,78 @@
+ ------
+ Forked JVM Shutdown
+ ------
+ Tibor Digana <ti...@apache.org>
+ ------
+ September 2015
+ ------
+
+ ~~ Licensed to the Apache Software Foundation (ASF) under one
+ ~~ or more contributor license agreements. See the NOTICE file
+ ~~ distributed with this work for additional information
+ ~~ regarding copyright ownership. The ASF licenses this file
+ ~~ to you 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.
+
+ ~~ NOTE: For help with the syntax of this file, see:
+ ~~ http://maven.apache.org/doxia/references/apt-format.html
+
+Shutdown of Forked JVM
+
+* Embedded shutdown
+
+ After the test-set has completed, the process executes
+ <<<java.lang.System.exit(0)>>> which starts shutdown hooks. At this point
+ the process may run next 30 seconds until all non daemon Threads die.
+ After the period of time has elapsed, the process kills itself by
+ <<<java.lang.Runtime.halt(0)>>>.
+
+* Pinging forked JVM
+
+ The master process sends NOOP command to a forked JVM every 10 seconds.
+ Forked JVM is waiting for the command every 20 seconds.
+ If the master process is killed (received SIGKILL signal) or shutdown
+ (pressed CTRL+C, received SIGTERM signal), forked JVM terminates after
+ timing out waiting period.
+
+* Shutdown of forked JVM by stopping the build
+
+ After the master process of the build is shutdown by sending SIGTERM signal
+ or pressing CTRL+C, the master process sends SHUTDOWN command to every
+ forked JVM. By default (configuration parameter <<<shutdown=testset>>>)
+ forked JVM would not continue with new test which means that the current
+ test may still continue to run.
+ The parameter <<<shutdown>>> can be configured with other two values
+ <<<exit>>> and <<<kill>>>. Using <<<exit>>> forked JVM executes
+ <<<java.lang.System.exit(1)>>> after the master process has received SIGTERM.
+ Using <<<kill>>> the JVM executes <<<java.lang.Runtime.halt(1)>>>, example:
+
++---+
+<project>
+ [...]
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>${project.artifactId}</artifactId>
+ <version>${project.version}</version>
+ <configuration>
+ <shutdown>kill</shutdown>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ [...]
+</project>
++---+
+
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-surefire-plugin/src/site/apt/index.apt.vm
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/apt/index.apt.vm b/maven-surefire-plugin/src/site/apt/index.apt.vm
index c9f8c9e..09ea2c0 100644
--- a/maven-surefire-plugin/src/site/apt/index.apt.vm
+++ b/maven-surefire-plugin/src/site/apt/index.apt.vm
@@ -153,4 +153,6 @@ mvn verify
* {{{./examples/fork-options-and-parallel-execution.html}Fork Options and Parallel Test Execution}}
+ * {{{./examples/shutdown.html}Shutdown of Forked JVM}}
+
[]
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/maven-surefire-plugin/src/site/site.xml
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/site.xml b/maven-surefire-plugin/src/site/site.xml
index 833c0a9..b3e9cd2 100644
--- a/maven-surefire-plugin/src/site/site.xml
+++ b/maven-surefire-plugin/src/site/site.xml
@@ -54,6 +54,7 @@
<item name="New Error Summary" href="newerrorsummary.html"/>
<item name="Fork Options and Parallel Test Execution" href="examples/fork-options-and-parallel-execution.html"/>
<item name="Using Console Logs" href="examples/logging.html"/>
+ <item name="Shutdown of Forked JVM" href="examples/shutdown.html"/>
</menu>
</body>
</project>
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
index 0433a01..b33b5d0 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
@@ -46,7 +46,7 @@ import java.util.Map;
public class BaseProviderFactory
implements DirectoryScannerParametersAware, ReporterConfigurationAware, SurefireClassLoadersAware, TestRequestAware,
ProviderPropertiesAware, ProviderParameters, TestArtifactInfoAware, RunOrderParametersAware, MainCliOptionsAware,
- FailFastAware
+ FailFastAware, ShutdownAware
{
private static final int ROOT_CHANNEL = 0;
@@ -72,6 +72,8 @@ public class BaseProviderFactory
private int skipAfterFailureCount;
+ private Shutdown shutdown;
+
public BaseProviderFactory( ReporterFactory reporterFactory, boolean insideFork )
{
this.reporterFactory = reporterFactory;
@@ -206,4 +208,14 @@ public class BaseProviderFactory
{
return insideFork;
}
+
+ public Shutdown getShutdown()
+ {
+ return shutdown;
+ }
+
+ public void setShutdown( Shutdown shutdown )
+ {
+ this.shutdown = shutdown;
+ }
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-api/src/main/java/org/apache/maven/surefire/booter/Command.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/Command.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/Command.java
index 25bb2d1..070980c 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/Command.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/Command.java
@@ -20,6 +20,10 @@ package org.apache.maven.surefire.booter;
*/
import static org.apache.maven.surefire.util.internal.StringUtils.requireNonNull;
+import static org.apache.maven.surefire.util.internal.StringUtils.isBlank;
+import static org.apache.maven.surefire.booter.MasterProcessCommand.RUN_CLASS;
+import static org.apache.maven.surefire.booter.MasterProcessCommand.SHUTDOWN;
+import static org.apache.maven.surefire.booter.Shutdown.DEFAULT;
/**
* Encapsulates data and command sent from master to forked process.
@@ -31,7 +35,6 @@ public final class Command
{
public static final Command TEST_SET_FINISHED = new Command( MasterProcessCommand.TEST_SET_FINISHED );
public static final Command SKIP_SINCE_NEXT_TEST = new Command( MasterProcessCommand.SKIP_SINCE_NEXT_TEST );
- public static final Command SHUTDOWN = new Command( MasterProcessCommand.SHUTDOWN );
public static final Command NOOP = new Command( MasterProcessCommand.NOOP );
private final MasterProcessCommand command;
@@ -43,6 +46,16 @@ public final class Command
this.data = data;
}
+ public static Command toShutdown( Shutdown shutdownType )
+ {
+ return new Command( SHUTDOWN, shutdownType.name() );
+ }
+
+ public static Command toRunClass( String runClass )
+ {
+ return new Command( RUN_CLASS, runClass );
+ }
+
public Command( MasterProcessCommand command )
{
this( command, null );
@@ -58,6 +71,24 @@ public final class Command
return data;
}
+ /**
+ * @return {@link Shutdown} or {@link Shutdown#DEFAULT} if {@link #getData()} is null or blank string
+ * @throws IllegalArgumentException if string data {@link #getData()} is not applicable to enum {@link Shutdown}
+ */
+ public Shutdown toShutdownData()
+ {
+ if ( !isType( SHUTDOWN ) )
+ {
+ throw new IllegalStateException( "expected MasterProcessCommand.SHUTDOWN" );
+ }
+ return isBlank( data ) ? DEFAULT : Shutdown.valueOf( data );
+ }
+
+ public boolean isType( MasterProcessCommand command )
+ {
+ return command == this.command;
+ }
+
@Override
public boolean equals( Object o )
{
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessCommand.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessCommand.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessCommand.java
index 2129bf0..8059537 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessCommand.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessCommand.java
@@ -19,10 +19,13 @@ package org.apache.maven.surefire.booter;
* under the License.
*/
+import org.apache.maven.surefire.util.internal.StringUtils;
+
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
import static org.apache.maven.surefire.util.internal.StringUtils.FORK_STREAM_CHARSET_NAME;
import static org.apache.maven.surefire.util.internal.StringUtils.encodeStringForForkCommunication;
@@ -41,10 +44,13 @@ public enum MasterProcessCommand
RUN_CLASS( 0, String.class ),
TEST_SET_FINISHED( 1, Void.class ),
SKIP_SINCE_NEXT_TEST( 2, Void.class ),
- SHUTDOWN( 3, Void.class ),
+ SHUTDOWN( 3, Shutdown.class ),
+
/** To tell a forked process that the master process is still alive. Repeated after 10 seconds. */
NOOP( 4, Void.class );
+ private static final Charset ASCII = Charset.forName( "ASCII" );
+
private final int id;
private final Class<?> dataType;
@@ -157,6 +163,8 @@ public enum MasterProcessCommand
{
case RUN_CLASS:
return new String( data, FORK_STREAM_CHARSET_NAME );
+ case SHUTDOWN:
+ return StringUtils.decode( data, ASCII );
default:
return null;
}
@@ -173,6 +181,8 @@ public enum MasterProcessCommand
{
case RUN_CLASS:
return encodeStringForForkCommunication( data );
+ case SHUTDOWN:
+ return StringUtils.encode( data, ASCII );
default:
return new byte[0];
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java
index ab45d81..f2f783c 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessReader.java
@@ -37,14 +37,13 @@ import static java.lang.Thread.State.RUNNABLE;
import static java.lang.Thread.State.TERMINATED;
import static java.util.concurrent.locks.LockSupport.park;
import static java.util.concurrent.locks.LockSupport.unpark;
-import static org.apache.maven.surefire.booter.MasterProcessCommand.RUN_CLASS;
-import static org.apache.maven.surefire.booter.MasterProcessCommand.TEST_SET_FINISHED;
import static org.apache.maven.surefire.booter.MasterProcessCommand.decode;
import static org.apache.maven.surefire.util.internal.StringUtils.encodeStringForForkCommunication;
import static org.apache.maven.surefire.util.internal.StringUtils.isNotBlank;
import static org.apache.maven.surefire.util.internal.StringUtils.isBlank;
import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThread;
import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_NEXT_TEST;
+import static org.apache.maven.surefire.booter.Shutdown.DEFAULT;
/**
* Reader of commands coming from plugin(master) process.
@@ -65,11 +64,13 @@ public final class MasterProcessReader
private final Queue<Thread> waiters = new ConcurrentLinkedQueue<Thread>();
- private final Node head = new Node();
-
private final CountDownLatch startMonitor = new CountDownLatch( 1 );
- private volatile Node tail = head;
+ private final Node headTestClassQueue = new Node();
+
+ private volatile Node tailTestClassQueue = headTestClassQueue;
+
+ private volatile Shutdown shutdown;
private static class Node
{
@@ -87,6 +88,12 @@ public final class MasterProcessReader
return reader;
}
+ public MasterProcessReader setShutdown( Shutdown shutdown )
+ {
+ this.shutdown = shutdown;
+ return this;
+ }
+
public boolean awaitStarted()
throws TestSetFailedException
{
@@ -136,7 +143,7 @@ public final class MasterProcessReader
Iterable<String> getIterableClasses( PrintStream originalOutStream )
{
- return new ClassesIterable( head, originalOutStream );
+ return new ClassesIterable( headTestClassQueue, originalOutStream );
}
public void stop()
@@ -149,6 +156,11 @@ public final class MasterProcessReader
}
}
+ private boolean isStopped()
+ {
+ return state.get() == TERMINATED;
+ }
+
private static boolean isLastNode( Node current )
{
return current.successor.get() == current;
@@ -156,17 +168,20 @@ public final class MasterProcessReader
private boolean isQueueFull()
{
- return isLastNode( tail );
+ return isLastNode( tailTestClassQueue );
}
- private boolean addToQueue( String item )
+ /**
+ * thread-safety: Must be called from single thread like here the reader thread only.
+ */
+ private boolean addTestClassToQueue( String item )
{
- if ( tail.item == null )
+ if ( tailTestClassQueue.item == null )
{
- tail.item = item;
+ tailTestClassQueue.item = item;
Node newNode = new Node();
- tail.successor.set( newNode );
- tail = newNode;
+ tailTestClassQueue.successor.set( newNode );
+ tailTestClassQueue = newNode;
return true;
}
else
@@ -183,18 +198,21 @@ public final class MasterProcessReader
public void makeQueueFull()
{
// order between (#compareAndSet, and #get) matters in multithreading
- for ( Node tail = this.tail;
+ for ( Node tail = this.tailTestClassQueue;
!tail.successor.compareAndSet( null, tail ) && tail.successor.get() != tail;
tail = tail.successor.get() );
}
+ /**
+ * thread-safety: Must be called from single thread like here the reader thread only.
+ */
private void insertForQueue( Command cmd )
{
MasterProcessCommand expectedCommandType = cmd.getCommandType();
switch ( expectedCommandType )
{
case RUN_CLASS:
- addToQueue( cmd.getData() );
+ addTestClassToQueue( cmd.getData() );
break;
case TEST_SET_FINISHED:
makeQueueFull();
@@ -220,6 +238,9 @@ public final class MasterProcessReader
}
}
+ /**
+ * thread-safety: Must be called from single thread like here the reader thread only.
+ */
private void insert( Command cmd )
{
insertForQueue( cmd );
@@ -292,7 +313,7 @@ public final class MasterProcessReader
private void popUnread()
{
- if ( state.get() == TERMINATED )
+ if ( isStopped() )
{
clazz = null;
return;
@@ -315,7 +336,13 @@ public final class MasterProcessReader
/**
* {@link java.util.concurrent.locks.LockSupport#park()}
* may spuriously (that is, for no reason) return, therefore the loop here.
+ * Could be waken up by System.exit or closing the stream.
*/
+ if ( isStopped() )
+ {
+ clazz = null;
+ return;
+ }
} while ( current.item == null && !isLastNode( current ) );
clazz = current.item;
current = current.successor.get();
@@ -329,7 +356,7 @@ public final class MasterProcessReader
while ( tryNullWhiteClass() );
}
- if ( state.get() == TERMINATED )
+ if ( isStopped() )
{
clazz = null;
}
@@ -355,6 +382,9 @@ public final class MasterProcessReader
}
}
+ /**
+ * thread-safety: Must be called from single thread like here the reader thread only.
+ */
private Command read( DataInputStream stdIn )
throws IOException
{
@@ -408,15 +438,24 @@ public final class MasterProcessReader
}
else
{
- if ( command.getCommandType() == TEST_SET_FINISHED )
- {
- isTestSetFinished = true;
- wakeupWaiters();
- }
- else if ( command.getCommandType() == RUN_CLASS )
+ switch ( command.getCommandType() )
{
- wakeupWaiters();
+ case TEST_SET_FINISHED:
+ isTestSetFinished = true;
+ wakeupWaiters();
+ break;
+ case RUN_CLASS:
+ wakeupWaiters();
+ break;
+ case SHUTDOWN:
+ insertForQueue( Command.TEST_SET_FINISHED );
+ wakeupWaiters();
+ break;
+ default:
+ // checkstyle do nothing
+ break;
}
+
insertForListeners( command );
}
}
@@ -424,10 +463,16 @@ public final class MasterProcessReader
catch ( EOFException e )
{
MasterProcessReader.this.state.set( TERMINATED );
+ if ( !isTestSetFinished )
+ {
+ exitByConfiguration();
+ // does not go to finally
+ }
}
catch ( IOException e )
{
MasterProcessReader.this.state.set( TERMINATED );
+ // If #stop() method is called, reader thread is interrupted and cause is InterruptedException.
if ( !( e.getCause() instanceof InterruptedException ) )
{
System.err.println( "[SUREFIRE] std/in stream corrupted" );
@@ -439,10 +484,33 @@ public final class MasterProcessReader
// ensure fail-safe iterator as well as safe to finish in for-each loop using ClassesIterator
if ( !isTestSetFinished )
{
- insert( new Command( TEST_SET_FINISHED ) );
+ insert( Command.TEST_SET_FINISHED );
}
wakeupWaiters();
}
}
+
+ /**
+ * thread-safety: Must be called from single thread like here the reader thread only.
+ */
+ private void exitByConfiguration()
+ {
+ Shutdown shutdown = MasterProcessReader.this.shutdown; // won't read inconsistent changes through the stack
+ if ( shutdown != null && shutdown != DEFAULT )
+ {
+ insert( Command.TEST_SET_FINISHED ); // lazily
+ wakeupWaiters();
+ switch ( shutdown )
+ {
+ case EXIT:
+ System.exit( 1 );
+ case KILL:
+ Runtime.getRuntime().halt( 1 );
+ default:
+ // should not happen; otherwise you missed enum case
+ break;
+ }
+ }
+ }
}
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-api/src/main/java/org/apache/maven/surefire/booter/Shutdown.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/Shutdown.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/Shutdown.java
new file mode 100644
index 0000000..660a40e
--- /dev/null
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/Shutdown.java
@@ -0,0 +1,84 @@
+package org.apache.maven.surefire.booter;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+/**
+ * Specifies the way how the forked jvm should be terminated after
+ * class AbstractCommandStream is closed and CTRL+C.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public enum Shutdown
+{
+ DEFAULT( "testset" ),
+ EXIT( "exit" ),
+ KILL( "kill" );
+
+ private final String param;
+
+ Shutdown( String param )
+ {
+ this.param = param;
+ }
+
+ public String getParam()
+ {
+ return param;
+ }
+
+ public static boolean isKnown( String param )
+ {
+ for ( Shutdown shutdown : values() )
+ {
+ if ( shutdown.param.equals( param ) )
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static String listParameters()
+ {
+ String values = "";
+ for ( Shutdown shutdown : values() )
+ {
+ if ( values.length() != 0 )
+ {
+ values += ", ";
+ }
+ values += shutdown.getParam();
+ }
+ return values;
+ }
+
+ public static Shutdown parameterOf( String parameter )
+ {
+ for ( Shutdown shutdown : values() )
+ {
+ if ( shutdown.param.equals( parameter ) )
+ {
+ return shutdown;
+ }
+ }
+ return DEFAULT;
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-api/src/main/java/org/apache/maven/surefire/booter/ShutdownAware.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ShutdownAware.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ShutdownAware.java
new file mode 100644
index 0000000..a843b27
--- /dev/null
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ShutdownAware.java
@@ -0,0 +1,31 @@
+package org.apache.maven.surefire.booter;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+/**
+ * See the plugin configuration parameter <em>shutdown</em>.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.19
+ */
+public interface ShutdownAware
+{
+ void setShutdown( Shutdown shutdown );
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
index cf07331..96bc3c0 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
@@ -90,6 +90,10 @@ public class SurefireReflector
private final Class<Enum> commandLineOptionsClass;
+ private final Class<?> shutdownAwareClass;
+
+ private final Class<Enum> shutdownClass;
+
@SuppressWarnings( "unchecked" )
public SurefireReflector( ClassLoader surefireClassLoader )
@@ -114,8 +118,9 @@ public class SurefireReflector
booterParameters = surefireClassLoader.loadClass( ProviderParameters.class.getName() );
testListResolver = surefireClassLoader.loadClass( TestListResolver.class.getName() );
mainCliOptions = surefireClassLoader.loadClass( MainCliOptionsAware.class.getName() );
- commandLineOptionsClass =
- (Class<Enum>) surefireClassLoader.loadClass( CommandLineOption.class.getName() );
+ commandLineOptionsClass = (Class<Enum>) surefireClassLoader.loadClass( CommandLineOption.class.getName() );
+ shutdownAwareClass = surefireClassLoader.loadClass( ShutdownAware.class.getName() );
+ shutdownClass = (Class<Enum>) surefireClassLoader.loadClass( Shutdown.class.getName() );
}
catch ( ClassNotFoundException e )
{
@@ -299,6 +304,21 @@ public class SurefireReflector
ReflectionUtils.invokeSetter( o, "setSkipAfterFailureCount", int.class, skipAfterFailureCount );
}
+ public void setShutdown( Object o, Shutdown shutdown )
+ {
+ if ( shutdownAwareClass.isAssignableFrom( o.getClass() ) )
+ {
+ for ( Enum e : shutdownClass.getEnumConstants() )
+ {
+ if ( shutdown.ordinal() == e.ordinal() )
+ {
+ ReflectionUtils.invokeSetter( o, "setShutdown", shutdownClass, e );
+ break;
+ }
+ }
+ }
+ }
+
public void setDirectoryScannerParameters( Object o, DirectoryScannerParameters dirScannerParams )
{
final Object param = createDirectoryScannerParameters( dirScannerParams );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java b/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java
index 708b436..b6e6467 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java
@@ -19,6 +19,7 @@ package org.apache.maven.surefire.providerapi;
* under the License.
*/
+import org.apache.maven.surefire.booter.Shutdown;
import org.apache.maven.surefire.cli.CommandLineOption;
import org.apache.maven.surefire.report.ConsoleLogger;
import org.apache.maven.surefire.report.ReporterConfiguration;
@@ -143,4 +144,6 @@ public interface ProviderParameters
* in-plugin provider.
*/
boolean isInsideFork();
+
+ Shutdown getShutdown();
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/StringUtils.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/StringUtils.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/StringUtils.java
index 043b87b..06cd55e 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/StringUtils.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/StringUtils.java
@@ -339,6 +339,32 @@ public class StringUtils
return ByteBuffer.wrap( out, 0, outPos );
}
+ public static String decode( byte[] toDecode, Charset charset )
+ {
+ try
+ {
+ // @todo use new JDK 1.6 constructor String(byte bytes[], Charset charset)
+ return new String( toDecode, charset.name() );
+ }
+ catch ( UnsupportedEncodingException e )
+ {
+ throw new RuntimeException( "The JVM must support Charset " + charset, e );
+ }
+ }
+
+ public static byte[] encode( String toEncode, Charset charset )
+ {
+ try
+ {
+ // @todo use new JDK 1.6 method getBytes(Charset charset)
+ return toEncode.getBytes( charset.name() );
+ }
+ catch ( UnsupportedEncodingException e )
+ {
+ throw new RuntimeException( "The JVM must support Charset " + charset, e );
+ }
+ }
+
public static byte[] encodeStringForForkCommunication( String string )
{
try
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-api/src/test/java/org/apache/maven/surefire/booter/MasterProcessCommandTest.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/booter/MasterProcessCommandTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/booter/MasterProcessCommandTest.java
index 717ab4e..f7f7767 100644
--- a/surefire-api/src/test/java/org/apache/maven/surefire/booter/MasterProcessCommandTest.java
+++ b/surefire-api/src/test/java/org/apache/maven/surefire/booter/MasterProcessCommandTest.java
@@ -105,11 +105,11 @@ public class MasterProcessCommandTest
assertNull( decoded );
break;
case SHUTDOWN:
- assertEquals( Void.class, command.getDataType() );
- encoded = command.fromDataType( dummyData );
- assertThat( encoded.length, is( 0 ) );
+ assertEquals( Shutdown.class, command.getDataType() );
+ encoded = command.fromDataType( Shutdown.EXIT.name() );
+ assertThat( encoded.length, is( 4 ) );
decoded = command.toDataTypeAsString( encoded );
- assertNull( decoded );
+ assertThat( decoded, is( Shutdown.EXIT.name() ) );
break;
case NOOP:
assertEquals( Void.class, command.getDataType() );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java
index 749f0e9..d310b9a 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java
@@ -54,4 +54,5 @@ public final class BooterConstants
public static final String RERUN_FAILING_TESTS_COUNT = "rerunFailingTestsCount";
public static final String MAIN_CLI_OPTIONS = "mainCliOptions";
public static final String FAIL_FAST_COUNT = "failFastCount";
+ public static final String SHUTDOWN = "shutdown";
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
index b8f2d0b..2540a7f 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
@@ -102,10 +102,12 @@ public class BooterDeserializer
int failFastCount = properties.getIntProperty( FAIL_FAST_COUNT );
+ Shutdown shutdown = Shutdown.valueOf( properties.getProperty( SHUTDOWN ) );
+
return new ProviderConfiguration( dirScannerParams, runOrderParameters,
properties.getBooleanProperty( FAILIFNOTESTS ), reporterConfiguration, testNg,
testSuiteDefinition, properties.getProperties(), typeEncodedTestForFork,
- preferTestsFromInStream, fromStrings( cli ), failFastCount );
+ preferTestsFromInStream, fromStrings( cli ), failFastCount, shutdown );
}
public StartupConfiguration getProviderConfiguration()
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
index c7746e9..bf58ca9 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
@@ -40,6 +40,8 @@ import org.apache.maven.surefire.testset.TestSetFailedException;
import static org.apache.maven.surefire.booter.MasterProcessCommand.SHUTDOWN;
import static org.apache.maven.surefire.booter.MasterProcessCommand.NOOP;
+import static org.apache.maven.surefire.booter.Shutdown.DEFAULT;
+import static org.apache.maven.surefire.booter.Shutdown.KILL;
import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_BYE;
import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_ERROR;
import static org.apache.maven.surefire.booter.ForkingRunListener.encode;
@@ -138,7 +140,7 @@ public final class ForkedBooter
encodeAndWriteToOutput( ( (char) BOOTERCODE_BYE ) + ",0,BYE!\n", originalOut );
originalOut.flush();
// noinspection CallToSystemExit
- exit( 0, false );
+ exit( 0, DEFAULT );
}
catch ( Throwable t )
{
@@ -146,7 +148,7 @@ public final class ForkedBooter
// noinspection UseOfSystemOutOrSystemErr
t.printStackTrace( System.err );
// noinspection ProhibitedExceptionThrown,CallToSystemExit
- exit( 1, false );
+ exit( 1, DEFAULT );
}
finally
{
@@ -180,7 +182,7 @@ public final class ForkedBooter
{
public void update( Command command )
{
- exit( 1, true );
+ exit( 1, command.toShutdownData() );
}
};
}
@@ -194,7 +196,7 @@ public final class ForkedBooter
boolean hasPing = pingDone.getAndSet( false );
if ( !hasPing )
{
- exit( 1, true );
+ exit( 1, KILL );
}
}
};
@@ -206,18 +208,19 @@ public final class ForkedBooter
out.write( encodeBytes, 0, encodeBytes.length );
}
- private static void exit( int returnCode, boolean immediate )
+ private static void exit( int returnCode, Shutdown shutdownType )
{
MasterProcessReader.getReader().stop();
-
- if ( immediate )
- {
- Runtime.getRuntime().halt( returnCode );
- }
- else
+ switch ( shutdownType )
{
- launchLastDitchDaemonShutdownThread( returnCode );
- System.exit( returnCode );
+ case KILL:
+ Runtime.getRuntime().halt( returnCode );
+ case EXIT:
+ launchLastDitchDaemonShutdownThread( returnCode );
+ System.exit( returnCode );
+ case DEFAULT:
+ default:
+ break;
}
}
@@ -303,6 +306,7 @@ public final class ForkedBooter
bpf.setDirectoryScannerParameters( providerConfiguration.getDirScannerParams() );
bpf.setMainCliOptions( providerConfiguration.getMainCliOptions() );
bpf.setSkipAfterFailureCount( providerConfiguration.getSkipAfterFailureCount() );
+ bpf.setShutdown( providerConfiguration.getShutdown() );
String providerClass = startupConfiguration1.getActualClassName();
return (SurefireProvider) instantiateOneArg( classLoader, providerClass, ProviderParameters.class, bpf );
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java
index 69c7f2c..f4a3b42 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java
@@ -68,13 +68,16 @@ public class ProviderConfiguration
private int skipAfterFailureCount;
+ private Shutdown shutdown;
+
@SuppressWarnings( "checkstyle:parameternumber" )
public ProviderConfiguration( DirectoryScannerParameters directoryScannerParameters,
RunOrderParameters runOrderParameters, boolean failIfNoTests,
ReporterConfiguration reporterConfiguration, TestArtifactInfo testArtifact,
TestRequest testSuiteDefinition, Map<String, String> providerProperties,
TypeEncodedValue typeEncodedTestSet, boolean readTestsFromInStream,
- List<CommandLineOption> mainCliOptions, int skipAfterFailureCount )
+ List<CommandLineOption> mainCliOptions, int skipAfterFailureCount,
+ Shutdown shutdown )
{
this.runOrderParameters = runOrderParameters;
this.providerProperties = providerProperties;
@@ -87,6 +90,7 @@ public class ProviderConfiguration
this.readTestsFromInStream = readTestsFromInStream;
this.mainCliOptions = mainCliOptions;
this.skipAfterFailureCount = skipAfterFailureCount;
+ this.shutdown = shutdown;
}
public ReporterConfiguration getReporterConfiguration()
@@ -156,13 +160,13 @@ public class ProviderConfiguration
return mainCliOptions;
}
- public void setSkipAfterFailureCount( int skipAfterFailureCount )
+ public int getSkipAfterFailureCount()
{
- this.skipAfterFailureCount = skipAfterFailureCount;
+ return skipAfterFailureCount;
}
- public int getSkipAfterFailureCount()
+ public Shutdown getShutdown()
{
- return skipAfterFailureCount;
+ return shutdown;
}
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
index 5ad587f..85f9c45 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
@@ -100,6 +100,7 @@ public class ProviderFactory
surefireReflector.setIfDirScannerAware( o, providerConfiguration.getDirScannerParams() );
surefireReflector.setMainCliOptions( o, providerConfiguration.getMainCliOptions() );
surefireReflector.setSkipAfterFailureCount( o, providerConfiguration.getSkipAfterFailureCount() );
+ surefireReflector.setShutdown( o, providerConfiguration.getShutdown() );
Object provider = surefireReflector.instantiateProvider( startupConfiguration.getActualClassName(), o );
currentThread.setContextClassLoader( systemClassLoader );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
index 3321a82..045b194 100644
--- a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
+++ b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
@@ -101,7 +101,9 @@ public class JUnit4Provider
public JUnit4Provider( ProviderParameters booterParameters )
{
// don't start a thread in MasterProcessReader while we are in in-plugin process
- commandsReader = booterParameters.isInsideFork() ? MasterProcessReader.getReader() : null;
+ commandsReader = booterParameters.isInsideFork()
+ ? MasterProcessReader.getReader().setShutdown( booterParameters.getShutdown() )
+ : null;
providerParameters = booterParameters;
testClassLoader = booterParameters.getTestClassLoader();
scanResult = booterParameters.getScanResult();
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
index 2c7d5c9..799c211 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
@@ -89,7 +89,9 @@ public class JUnitCoreProvider
public JUnitCoreProvider( ProviderParameters providerParameters )
{
- commandsReader = providerParameters.isInsideFork() ? MasterProcessReader.getReader() : null;
+ commandsReader = providerParameters.isInsideFork()
+ ? MasterProcessReader.getReader().setShutdown( providerParameters.getShutdown() )
+ : null;
this.providerParameters = providerParameters;
testClassLoader = providerParameters.getTestClassLoader();
scanResult = providerParameters.getScanResult();
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/cb97ba70/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
index a317042..c2a1018 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
@@ -73,7 +73,9 @@ public class TestNGProvider
public TestNGProvider( ProviderParameters booterParameters )
{
// don't start a thread in MasterProcessReader while we are in in-plugin process
- commandsReader = booterParameters.isInsideFork() ? MasterProcessReader.getReader() : null;
+ commandsReader = booterParameters.isInsideFork()
+ ? MasterProcessReader.getReader().setShutdown( booterParameters.getShutdown() )
+ : null;
providerParameters = booterParameters;
testClassLoader = booterParameters.getTestClassLoader();
runOrderCalculator = booterParameters.getRunOrderCalculator();