You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kr...@apache.org on 2013/01/09 18:36:11 UTC
git commit: [SUREFIRE-946] prevent hanging main process if forked
process was killed (softly)
Updated Branches:
refs/heads/master 350dd6fd7 -> e54dbd810
[SUREFIRE-946] prevent hanging main process if forked process was killed (softly)
Fixed with extended IT
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/e54dbd81
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/e54dbd81
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/e54dbd81
Branch: refs/heads/master
Commit: e54dbd810f62fe723800f11279b881bff244b707
Parents: 350dd6f
Author: agudian <an...@gmail.com>
Authored: Sat Jan 5 21:13:12 2013 +0100
Committer: Kristian Rosenvold <kr...@apache.org>
Committed: Wed Jan 9 18:24:38 2013 +0100
----------------------------------------------------------------------
.../plugin/surefire/booterclient/ForkStarter.java | 140 +++++++++++----
.../lazytestprovider/TestProvidingInputStream.java | 29 ++-
.../surefire/booterclient/output/ForkClient.java | 22 ++-
.../maven/surefire/booter/ForkingRunListener.java | 3 +
.../apache/maven/surefire/booter/ForkedBooter.java | 74 ++++++--
.../maven/surefire/its/CrashDetectionIT.java | 7 +-
6 files changed, 215 insertions(+), 60 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/e54dbd81/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 620dfd4..892c6a9 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
@@ -21,6 +21,8 @@ package org.apache.maven.plugin.surefire.booterclient;
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
+import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -36,6 +38,7 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+
import org.apache.maven.plugin.surefire.AbstractSurefireMojo;
import org.apache.maven.plugin.surefire.CommonReflector;
import org.apache.maven.plugin.surefire.StartupReportConfiguration;
@@ -63,14 +66,13 @@ import org.apache.maven.surefire.report.StackTraceWriter;
import org.apache.maven.surefire.suite.RunResult;
import org.apache.maven.surefire.util.DefaultScanResult;
-
/**
* Starts the fork or runs in-process.
* <p/>
* Lives only on the plugin-side (not present in remote vms)
* <p/>
* Knows how to fork new vms and also how to delegate non-forking invocation to SurefireStarter directly
- *
+ *
* @author Jason van Zyl
* @author Emmanuel Venisse
* @author Brett Porter
@@ -80,6 +82,36 @@ import org.apache.maven.surefire.util.DefaultScanResult;
*/
public class ForkStarter
{
+ /**
+ * Closes an InputStream
+ */
+ private final class InputStreamCloser
+ extends Thread
+ {
+ private InputStream testProvidingInputStream;
+
+ public InputStreamCloser( InputStream testProvidingInputStream )
+ {
+ this.testProvidingInputStream = testProvidingInputStream;
+ }
+
+ @Override
+ public void run()
+ {
+ if ( testProvidingInputStream != null )
+ {
+ try
+ {
+ testProvidingInputStream.close();
+ }
+ catch ( IOException e )
+ {
+ // ignore
+ }
+ }
+ }
+ }
+
private final int forkedProcessTimeoutInSeconds;
private final ProviderConfiguration providerConfiguration;
@@ -105,7 +137,6 @@ public class ForkStarter
}
};
-
public ForkStarter( ProviderConfiguration providerConfiguration, StartupConfiguration startupConfiguration,
ForkConfiguration forkConfiguration, int forkedProcessTimeoutInSeconds,
StartupReportConfiguration startupReportConfiguration )
@@ -167,8 +198,9 @@ public class ForkStarter
{
ArrayList<Future<RunResult>> results = new ArrayList<Future<RunResult>>( forkCount );
- ExecutorService executorService = new ThreadPoolExecutor( forkCount, forkCount, 60, TimeUnit.SECONDS,
- new ArrayBlockingQueue<Runnable>( forkCount ) );
+ ExecutorService executorService =
+ new ThreadPoolExecutor( forkCount, forkCount, 60, TimeUnit.SECONDS,
+ new ArrayBlockingQueue<Runnable>( forkCount ) );
try
{
@@ -196,16 +228,15 @@ public class ForkStarter
public RunResult call()
throws Exception
{
- TestProvidingInputStream testProvidingInputStream =
- new TestProvidingInputStream( messageQueue );
+ TestProvidingInputStream testProvidingInputStream = new TestProvidingInputStream( messageQueue );
ForkClient forkClient =
- new ForkClient( defaultReporterFactory, startupReportConfiguration.getTestVmSystemProperties(),
+ new ForkClient( defaultReporterFactory,
+ startupReportConfiguration.getTestVmSystemProperties(),
testProvidingInputStream );
return fork( null, new PropertiesWrapper( providerConfiguration.getProviderProperties() ),
- forkClient, effectiveSystemProperties, finalThreadNumber,
- testProvidingInputStream );
+ forkClient, effectiveSystemProperties, finalThreadNumber, testProvidingInputStream );
}
};
@@ -270,12 +301,13 @@ public class ForkStarter
if ( thisThreadsThreadNumber > forkCount )
{
// this would be a bug in the ThreadPoolExecutor
- throw new IllegalStateException(
- "More threads than " + forkCount + " have been created by the ThreadPoolExecutor." );
+ throw new IllegalStateException( "More threads than " + forkCount
+ + " have been created by the ThreadPoolExecutor." );
}
- ForkClient forkClient = new ForkClient( defaultReporterFactory,
- startupReportConfiguration.getTestVmSystemProperties() );
+ ForkClient forkClient =
+ new ForkClient( defaultReporterFactory,
+ startupReportConfiguration.getTestVmSystemProperties() );
return fork( testSet, new PropertiesWrapper( providerConfiguration.getProviderProperties() ),
forkClient, effectiveSystemProperties, thisThreadsThreadNumber, null );
}
@@ -353,8 +385,9 @@ public class ForkStarter
AbstractSurefireMojo.createCopyAndReplaceThreadNumPlaceholder( effectiveSystemProperties,
threadNumber );
systPropsFile =
- SystemPropertyManager.writePropertiesFile( filteredProperties, forkConfiguration.getTempDirectory(),
- "surefire_" + systemPropertiesFileCounter++,
+ SystemPropertyManager.writePropertiesFile( filteredProperties,
+ forkConfiguration.getTempDirectory(), "surefire_"
+ + systemPropertiesFileCounter++,
forkConfiguration.isDebug() );
}
}
@@ -365,22 +398,31 @@ public class ForkStarter
final Classpath bootClasspathConfiguration = forkConfiguration.getBootClasspath();
- final Classpath additionlClassPathUrls = startupConfiguration.useSystemClassLoader()
- ? startupConfiguration.getClasspathConfiguration().getTestClasspath()
- : null;
+ final Classpath additionlClassPathUrls =
+ startupConfiguration.useSystemClassLoader() ? startupConfiguration.getClasspathConfiguration().getTestClasspath()
+ : null;
// Surefire-booter + all test classes if "useSystemClassloader"
// Surefire-booter if !useSystemClassLoader
Classpath bootClasspath = Classpath.join( bootClasspathConfiguration, additionlClassPathUrls );
- @SuppressWarnings( "unchecked" ) OutputStreamFlushableCommandline cli =
+ @SuppressWarnings( "unchecked" )
+ OutputStreamFlushableCommandline cli =
forkConfiguration.createCommandLine( bootClasspath.getClassPath(),
startupConfiguration.getClassLoaderConfiguration(),
startupConfiguration.isShadefire(), threadNumber );
+ final InputStreamCloser inputStreamCloserHook;
if ( testProvidingInputStream != null )
{
testProvidingInputStream.setFlushReceiverProvider( cli );
+
+ inputStreamCloserHook = new InputStreamCloser( testProvidingInputStream );
+ addShutDownHook( inputStreamCloserHook );
+ }
+ else
+ {
+ inputStreamCloserHook = null;
}
cli.createArg().setFile( surefireProperties );
@@ -410,7 +452,6 @@ public class ForkStarter
throw new SurefireBooterForkException( "Error occurred in starting fork, check output in log" );
}
-
}
catch ( CommandLineTimeOutException e )
{
@@ -424,6 +465,11 @@ public class ForkStarter
finally
{
threadedStreamConsumer.close();
+ if ( inputStreamCloserHook != null )
+ {
+ removeShutdownHook( inputStreamCloserHook );
+ inputStreamCloserHook.run();
+ }
if ( runResult == null )
{
runResult = defaultReporterFactory.getGlobalRunStatistics().getRunResult();
@@ -433,16 +479,16 @@ public class ForkStarter
StackTraceWriter errorInFork = forkClient.getErrorInFork();
if ( errorInFork != null )
{
- //noinspection ThrowFromFinallyBlock
- throw new RuntimeException(
- "There was an error in the forked process\n" + errorInFork.writeTraceToString() );
+ // noinspection ThrowFromFinallyBlock
+ throw new RuntimeException( "There was an error in the forked process\n"
+ + errorInFork.writeTraceToString() );
}
if ( !forkClient.isSaidGoodBye() )
{
- //noinspection ThrowFromFinallyBlock
+ // noinspection ThrowFromFinallyBlock
throw new RuntimeException(
- "The forked VM terminated without saying properly goodbye. VM crash or System.exit called ?" +
- "\nCommand was" + cli.toString() );
+ "The forked VM terminated without saying properly goodbye. VM crash or System.exit called ?"
+ + "\nCommand was" + cli.toString() );
}
}
@@ -460,15 +506,14 @@ public class ForkStarter
{
final ClasspathConfiguration classpathConfiguration = startupConfiguration.getClasspathConfiguration();
ClassLoader testsClassLoader = classpathConfiguration.createTestClassLoader( false );
- ClassLoader surefireClassLoader =
- classpathConfiguration.createInprocSurefireClassLoader( testsClassLoader );
+ ClassLoader surefireClassLoader = classpathConfiguration.createInprocSurefireClassLoader( testsClassLoader );
CommonReflector commonReflector = new CommonReflector( surefireClassLoader );
Object reporterFactory = commonReflector.createReportingReporterFactory( startupReportConfiguration );
final ProviderFactory providerFactory =
- new ProviderFactory( startupConfiguration, providerConfiguration, surefireClassLoader, testsClassLoader,
- reporterFactory );
+ new ProviderFactory( startupConfiguration, providerConfiguration, surefireClassLoader,
+ testsClassLoader, reporterFactory );
SurefireProvider surefireProvider = providerFactory.createProvider( false );
return surefireProvider.getSuites();
}
@@ -478,4 +523,37 @@ public class ForkStarter
}
}
+ // TODO use ShutdownHookUtils, once it's public again
+ public static void addShutDownHook( Thread hook )
+ {
+ try
+ {
+ Runtime.getRuntime().addShutdownHook( hook );
+ }
+ catch ( IllegalStateException ignore )
+ {
+ // ignore
+ }
+ catch ( AccessControlException ignore )
+ {
+ // ignore
+ }
+ }
+
+ // TODO use ShutdownHookUtils, once it's public again
+ public static void removeShutdownHook( Thread hook )
+ {
+ try
+ {
+ Runtime.getRuntime().removeShutdownHook( hook );
+ }
+ catch ( IllegalStateException ignore )
+ {
+ // ignore
+ }
+ catch ( AccessControlException ignore )
+ {
+ // ignore
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/e54dbd81/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 1e63234..df14d35 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
@@ -25,16 +25,14 @@ import java.util.Queue;
import java.util.concurrent.Semaphore;
/**
- * An {@link InputStream} that, when read, provides test class names out of
- * a queue.
+ * An {@link InputStream} that, when read, provides test class names out of a queue.
* <p/>
- * The Stream provides only one test at a time, but only after {@link #provideNewTest()}
- * has been invoked.
+ * The Stream provides only one test at a time, but only after {@link #provideNewTest()} has been invoked.
* <p/>
- * After providing each test class name, followed by a newline character, a flush is
- * performed on the {@link FlushReceiver} provided by the {@link FlushReceiverProvider}
- * that can be set using {@link #setFlushReceiverProvider(FlushReceiverProvider)}.
- *
+ * After providing each test class name, followed by a newline character, a flush is performed on the
+ * {@link FlushReceiver} provided by the {@link FlushReceiverProvider} that can be set using
+ * {@link #setFlushReceiverProvider(FlushReceiverProvider)}.
+ *
* @author Andreas Gudian
*/
public class TestProvidingInputStream
@@ -50,9 +48,11 @@ public class TestProvidingInputStream
private FlushReceiverProvider flushReceiverProvider;
+ private boolean closed = false;
+
/**
* C'tor
- *
+ *
* @param testItemQueue source of the tests to be read from this stream
*/
public TestProvidingInputStream( Queue<String> testItemQueue )
@@ -81,6 +81,11 @@ public class TestProvidingInputStream
semaphore.acquireUninterruptibly();
+ if ( closed )
+ {
+ return -1;
+ }
+
String currentElement = testItemQueue.poll();
if ( null != currentElement )
{
@@ -111,4 +116,10 @@ public class TestProvidingInputStream
{
semaphore.release();
}
+
+ public void close()
+ {
+ closed = true;
+ semaphore.release();
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/e54dbd81/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
index 9fde697..932f148 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
@@ -44,7 +44,7 @@ import org.apache.maven.surefire.util.internal.StringUtils;
/**
* Knows how to reconstruct *all* the state transmitted over stdout by the forked process.
- *
+ *
* @author Kristian Rosenvold
*/
public class ForkClient
@@ -156,7 +156,11 @@ public class ForkClient
case ForkingRunListener.BOOTERCODE_ERROR:
errorInFork = deserializeStackStraceWriter( new StringTokenizer( remaining, "," ) );
break;
+ case ForkingRunListener.BOOTERCODE_CRASH:
+ closeTestProvidingInputStream();
+ break;
case ForkingRunListener.BOOTERCODE_BYE:
+ closeTestProvidingInputStream();
saidGoodBye = true;
break;
default:
@@ -173,6 +177,14 @@ public class ForkClient
}
}
+ private void closeTestProvidingInputStream()
+ {
+ if ( null != testProvidingInputStream )
+ {
+ testProvidingInputStream.close();
+ }
+ }
+
public void consumeMultiLineContent( String s )
throws IOException
{
@@ -217,9 +229,9 @@ public class ForkClient
String stackTraceMessage = nullableCsv( tokens.nextToken() );
String smartStackTrace = nullableCsv( tokens.nextToken() );
String stackTrace = tokens.hasMoreTokens() ? nullableCsv( tokens.nextToken() ) : null;
- stackTraceWriter = stackTrace != null
- ? new DeserializedStacktraceWriter( stackTraceMessage, smartStackTrace, stackTrace )
- : null;
+ stackTraceWriter =
+ stackTrace != null ? new DeserializedStacktraceWriter( stackTraceMessage, smartStackTrace, stackTrace )
+ : null;
return stackTraceWriter;
}
@@ -242,7 +254,7 @@ public class ForkClient
/**
* Used when getting reporters on the plugin side of a fork.
- *
+ *
* @param channelNumber The logical channel number
* @return A mock provider reporter
*/
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/e54dbd81/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java
index 9974c5c..6ec7223 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java
@@ -69,6 +69,8 @@ public class ForkingRunListener
public static final byte BOOTERCODE_TEST_SKIPPED = (byte) '9';
+ public static final byte BOOTERCODE_CRASH = (byte) 'C';
+
public static final byte BOOTERCODE_TEST_ASSUMPTIONFAILURE = (byte) 'G';
public static final byte BOOTERCODE_CONSOLE = (byte) 'H';
@@ -81,6 +83,7 @@ public class ForkingRunListener
public static final byte BOOTERCODE_BYE = (byte) 'Z';
+
private final PrintStream target;
private final Integer testSetChannelId;
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/e54dbd81/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 c06297a..4b04a99 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
@@ -21,6 +21,7 @@ package org.apache.maven.surefire.booter;
import java.io.File;
import java.io.FileInputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
@@ -35,7 +36,7 @@ import org.apache.maven.surefire.util.LazyTestsToRun;
* <p/>
* Deals with deserialization of the booter wire-level protocol
* <p/>
- *
+ *
* @author Jason van Zyl
* @author Emmanuel Venisse
* @author Kristian Rosenvold
@@ -43,10 +44,58 @@ import org.apache.maven.surefire.util.LazyTestsToRun;
public class ForkedBooter
{
+ private final static long SYSTEM_EXIT_TIMEOUT = 30 * 1000;
+
+ private final static String GOODBYE_MESSAGE = ( (char) ForkingRunListener.BOOTERCODE_BYE ) + ",0,BYE!";
+
+ private final static String CRASH_MESSAGE = ( (char) ForkingRunListener.BOOTERCODE_CRASH ) + ",0,F!";
+
+ private static boolean sayGoodbye = false;
+
+ private static final class GoodbyeReporterAndStdStreamCloser
+ implements Runnable
+ {
+
+ private InputStream originalIn;
+
+ private PrintStream originalOut;
+
+ public GoodbyeReporterAndStdStreamCloser()
+ {
+ this.originalIn = System.in;
+ this.originalOut = System.out;
+ }
+
+ public void run()
+ {
+ try
+ {
+ originalIn.close();
+ }
+ catch ( IOException e )
+ {
+ }
+
+ if ( sayGoodbye )
+ {
+ originalOut.println( GOODBYE_MESSAGE );
+ }
+ else
+ {
+ originalOut.println( CRASH_MESSAGE );
+ }
+
+ originalOut.flush();
+ originalOut.close();
+ }
+ }
+
/**
* This method is invoked when Surefire is forked - this method parses and organizes the arguments passed to it and
- * then calls the Surefire class' run method. <p/> The system exit code will be 1 if an exception is thrown.
- *
+ * then calls the Surefire class' run method.
+ * <p/>
+ * The system exit code will be 1 if an exception is thrown.
+ *
* @param args Commandline arguments
* @throws Throwable Upon throwables
*/
@@ -54,6 +103,9 @@ public class ForkedBooter
throws Throwable
{
final PrintStream originalOut = System.out;
+
+ Runtime.getRuntime().addShutdownHook( new Thread( new GoodbyeReporterAndStdStreamCloser() ) );
+
try
{
if ( args.length > 1 )
@@ -71,8 +123,8 @@ public class ForkedBooter
boolean readTestsFromInputStream = providerConfiguration.isReadTestsFromInStream();
final ClasspathConfiguration classpathConfiguration = startupConfiguration.getClasspathConfiguration();
- final ClassLoader testClassLoader = classpathConfiguration.createForkingTestClassLoader(
- startupConfiguration.isManifestOnlyJarRequestedAndUsable() );
+ final ClassLoader testClassLoader =
+ classpathConfiguration.createForkingTestClassLoader( startupConfiguration.isManifestOnlyJarRequestedAndUsable() );
startupConfiguration.writeSurefireTestClasspathProperty();
@@ -92,8 +144,7 @@ public class ForkedBooter
try
{
- runSuitesInProcess( testSet, testClassLoader, startupConfiguration, providerConfiguration,
- originalOut );
+ runSuitesInProcess( testSet, testClassLoader, startupConfiguration, providerConfiguration, originalOut );
}
catch ( InvocationTargetException t )
{
@@ -111,10 +162,8 @@ public class ForkedBooter
ForkingRunListener.encode( stringBuffer, stackTraceWriter, false );
originalOut.println( ( (char) ForkingRunListener.BOOTERCODE_ERROR ) + ",0," + stringBuffer.toString() );
}
- // Say bye.
- originalOut.println( ( (char) ForkingRunListener.BOOTERCODE_BYE ) + ",0,BYE!" );
- originalOut.flush();
- // noinspection CallToSystemExit
+
+ sayGoodbye = true;
exit( 0 );
}
catch ( Throwable t )
@@ -127,15 +176,12 @@ public class ForkedBooter
}
}
- private final static long SYSTEM_EXIT_TIMEOUT = 30 * 1000;
-
private static void exit( final int returnCode )
{
launchLastDitchDaemonShutdownThread( returnCode );
System.exit( returnCode );
}
-
private static RunResult runSuitesInProcess( Object testSet, ClassLoader testsClassLoader,
StartupConfiguration startupConfiguration,
ProviderConfiguration providerConfiguration,
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/e54dbd81/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/CrashDetectionIT.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/CrashDetectionIT.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/CrashDetectionIT.java
index 7dc868f..31e3e01 100644
--- a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/CrashDetectionIT.java
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/CrashDetectionIT.java
@@ -27,8 +27,13 @@ import org.apache.maven.surefire.its.fixture.SurefireIntegrationTestCase;
public class CrashDetectionIT
extends SurefireIntegrationTestCase
{
- public void testArgLine()
+ public void testCrashInFork()
{
unpack( "crash-detection" ).maven().withFailure().executeTest();
}
+
+ public void testCrashInReusableFork()
+ {
+ unpack( "crash-detection" ).forkOncePerThread().threadCount( 1 ).maven().withFailure().executeTest();
+ }
}