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 2019/07/21 09:56:13 UTC

[maven-surefire] 02/02: [SUREFIRE-1675] Forked JVM terminates with 'halt' when another module's tests fail

This is an automated email from the ASF dual-hosted git repository.

tibordigana pushed a commit to branch SUREFIRE-1675
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git

commit 777559872b9ddc8d2771e1e7220f9815420a2a27
Author: tibordigana <ti...@apache.org>
AuthorDate: Sat Jul 20 14:55:27 2019 +0200

    [SUREFIRE-1675] Forked JVM terminates with 'halt' when another module's tests fail
---
 Jenkinsfile                                        |   6 +-
 .../maven/surefire/booter/CommandReader.java       |   3 +-
 .../apache/maven/surefire/booter/ForkedBooter.java | 121 +++++++++++++++++----
 surefire-its/pom.xml                               |   2 +-
 ...Surefire946KillMainProcessInReusableForkIT.java | 109 +++++++++++++++----
 .../surefire-946-dummy-dependency/pom.xml          |  39 +++++++
 .../src/main/java/dummy/DummyClass.java}           |  31 ++----
 .../pom.xml                                        |   7 ++
 .../test/java/junit44/environment/Basic01Test.java |   2 +
 .../test/java/junit44/environment/Basic02Test.java |   2 +
 .../test/java/junit44/environment/Basic03Test.java |   2 +
 .../test/java/junit44/environment/Basic04Test.java |   2 +
 .../test/java/junit44/environment/Basic05Test.java |   2 +
 .../test/java/junit44/environment/Basic06Test.java |   2 +
 .../test/java/junit44/environment/Basic07Test.java |   2 +
 .../test/java/junit44/environment/Basic08Test.java |   2 +
 .../test/java/junit44/environment/Basic09Test.java |   2 +
 .../test/java/junit44/environment/Basic10Test.java |   2 +
 .../surefire-946-self-destruct-plugin/pom.xml      |   6 -
 19 files changed, 265 insertions(+), 79 deletions(-)

diff --git a/Jenkinsfile b/Jenkinsfile
index 175c763..ae2de8f 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -30,7 +30,7 @@ properties(
     ]
 )
 
-final def oses = ['linux':'ubuntu && !H24', 'windows':'Windows && !windows-2016-1']
+final def oses = ['linux':'ubuntu && !H24', 'windows':'Windows']
 final def mavens = env.BRANCH_NAME == 'master' ? ['3.6.x', '3.2.x'] : ['3.6.x']
 // all non-EOL versions and the first EA
 final def jdks = [13, 12, 11, 8, 7]
@@ -109,7 +109,7 @@ timeout(time: 12, unit: 'HOURS') {
         currentBuild.result = 'FAILURE'
         throw e
     } finally {
-        // jenkinsNotify()
+        jenkinsNotify()
     }
 }
 
@@ -205,6 +205,7 @@ static def sourcesPatternCsv() {
             '**/maven-surefire-report-plugin/src/main/java,' +
             '**/surefire-api/src/main/java,' +
             '**/surefire-booter/src/main/java,' +
+            '**/surefire-extensions-api/src/main/java,' +
             '**/surefire-grouper/src/main/java,' +
             '**/surefire-its/src/main/java,' +
             '**/surefire-logger-api/src/main/java,' +
@@ -220,6 +221,7 @@ static def classPatternCsv() {
             '**/maven-surefire-report-plugin/target/classes,' +
             '**/surefire-api/target/classes,' +
             '**/surefire-booter/target/classes,' +
+            '**/surefire-extensions-api/target/classes,' +
             '**/surefire-grouper/target/classes,' +
             '**/surefire-its/target/classes,' +
             '**/surefire-logger-api/target/classes,' +
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java
index b4e303e..15b1dd0 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java
@@ -207,8 +207,9 @@ public final class CommandReader
 
     public void stop()
     {
-        if ( state.compareAndSet( NEW, TERMINATED ) || state.compareAndSet( RUNNABLE, TERMINATED ) )
+        if ( !isStopped() )
         {
+            state.set( TERMINATED );
             makeQueueFull();
             listeners.clear();
             commandThread.interrupt();
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 ebc1b27..c7e11b3 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
@@ -30,6 +30,8 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
 import java.lang.reflect.InvocationTargetException;
 import java.security.AccessControlException;
 import java.security.AccessController;
@@ -47,6 +49,7 @@ import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.apache.maven.surefire.booter.SystemPropertyManager.setSystemProperties;
 import static org.apache.maven.surefire.util.ReflectionUtils.instantiateOneArg;
 import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThreadFactory;
+import static org.apache.maven.surefire.util.internal.StringUtils.NL;
 
 /**
  * The part of the booter that is unique to a forked vm.
@@ -62,12 +65,13 @@ public final class ForkedBooter
 {
     private static final long DEFAULT_SYSTEM_EXIT_TIMEOUT_IN_SECONDS = 30L;
     private static final long PING_TIMEOUT_IN_SECONDS = 30L;
-    private static final long ONE_SECOND_IN_MILLIS = 1000L;
+    private static final long ONE_SECOND_IN_MILLIS = 1_000L;
     private static final String LAST_DITCH_SHUTDOWN_THREAD = "surefire-forkedjvm-last-ditch-daemon-shutdown-thread-";
     private static final String PING_THREAD = "surefire-forkedjvm-ping-";
 
     private final CommandReader commandReader = CommandReader.getReader();
     private final ForkedChannelEncoder eventChannel = new ForkedChannelEncoder( System.out );
+    private final Semaphore exitBarrier = new Semaphore( 0 );
 
     private volatile long systemExitTimeoutInSeconds = DEFAULT_SYSTEM_EXIT_TIMEOUT_IN_SECONDS;
     private volatile PingScheduler pingScheduler;
@@ -83,7 +87,6 @@ public final class ForkedBooter
     {
         BooterDeserializer booterDeserializer =
                 new BooterDeserializer( createSurefirePropertiesIfFileExists( tmpDir, surefirePropsFileName ) );
-        // todo: print PID in debug console logger in version 2.21.2
         pingScheduler = isDebugging() ? null : listenToShutdownCommands( booterDeserializer.getPluginPid() );
         setSystemProperties( new File( tmpDir, effectiveSystemPropertiesFileName ) );
 
@@ -91,6 +94,12 @@ public final class ForkedBooter
         DumpErrorSingleton.getSingleton()
                 .init( providerConfiguration.getReporterConfiguration().getReportsDirectory(), dumpFileName );
 
+        if ( isDebugging() )
+        {
+            DumpErrorSingleton.getSingleton()
+                    .dumpText( "Found Maven process ID " + booterDeserializer.getPluginPid() );
+        }
+
         startupConfiguration = booterDeserializer.getProviderConfiguration();
         systemExitTimeoutInSeconds = providerConfiguration.systemExitTimeout( DEFAULT_SYSTEM_EXIT_TIMEOUT_IN_SECONDS );
 
@@ -118,18 +127,21 @@ public final class ForkedBooter
         {
             runSuitesInProcess();
         }
-        catch ( InvocationTargetException t )
+        catch ( InvocationTargetException e )
         {
-            Throwable e = t.getTargetException();
-            DumpErrorSingleton.getSingleton().dumpException( e );
-            eventChannel.consoleErrorLog( new LegacyPojoStackTraceWriter( "test subsystem", "no method", e ), false );
+            Throwable t = e.getTargetException();
+            DumpErrorSingleton.getSingleton().dumpException( t );
+            eventChannel.consoleErrorLog( new LegacyPojoStackTraceWriter( "test subsystem", "no method", t ), false );
         }
         catch ( Throwable t )
         {
             DumpErrorSingleton.getSingleton().dumpException( t );
             eventChannel.consoleErrorLog( new LegacyPojoStackTraceWriter( "test subsystem", "no method", t ), false );
         }
-        acknowledgedExit();
+        finally
+        {
+            acknowledgedExit();
+        }
     }
 
     private Object createTestSet( TypeEncodedValue forkedTestSet, boolean readTestsFromCommandReader, ClassLoader cl )
@@ -202,7 +214,11 @@ public final class ForkedBooter
                                  && !pingMechanism.pingScheduler.isShutdown() )
                     {
                         DumpErrorSingleton.getSingleton()
-                                .dumpText( "Killing self fork JVM. Maven process died." );
+                                .dumpText( "Killing self fork JVM. Maven process died."
+                                        + NL
+                                        + "Thread dump before killing the process (" + getProcessName() + "):"
+                                        + NL
+                                        + generateThreadDump() );
 
                         kill();
                     }
@@ -239,17 +255,33 @@ public final class ForkedBooter
                 if ( shutdown.isKill() )
                 {
                     DumpErrorSingleton.getSingleton()
-                            .dumpText( "Killing self fork JVM. Received SHUTDOWN command from Maven shutdown hook." );
+                            .dumpText( "Killing self fork JVM. Received SHUTDOWN command from Maven shutdown hook."
+                                    + NL
+                                    + "Thread dump before killing the process (" + getProcessName() + "):"
+                                    + NL
+                                    + generateThreadDump() );
                     kill();
                 }
                 else if ( shutdown.isExit() )
                 {
                     cancelPingScheduler();
                     DumpErrorSingleton.getSingleton()
-                            .dumpText( "Exiting self fork JVM. Received SHUTDOWN command from Maven shutdown hook." );
+                            .dumpText( "Exiting self fork JVM. Received SHUTDOWN command from Maven shutdown hook."
+                                    + NL
+                                    + "Thread dump before exiting the process (" + getProcessName() + "):"
+                                    + NL
+                                    + generateThreadDump() );
+                    exitBarrier.release();
                     exit1();
                 }
-                // else refers to shutdown=testset, but not used now, keeping reader open
+                else
+                {
+                    // else refers to shutdown=testset, but not used now, keeping reader open
+                    DumpErrorSingleton.getSingleton()
+                            .dumpText( "Thread dump for process (" + getProcessName() + "):"
+                                    + NL
+                                    + generateThreadDump() );
+                }
             }
         };
     }
@@ -267,7 +299,11 @@ public final class ForkedBooter
                     if ( !hasPing )
                     {
                         DumpErrorSingleton.getSingleton()
-                                .dumpText( "Killing self fork JVM. PING timeout elapsed." );
+                                .dumpText( "Killing self fork JVM. PING timeout elapsed."
+                                        + NL
+                                        + "Thread dump before killing the process (" + getProcessName() + "):"
+                                        + NL
+                                        + generateThreadDump() );
 
                         kill();
                     }
@@ -295,20 +331,19 @@ public final class ForkedBooter
 
     private void acknowledgedExit()
     {
-        final Semaphore barrier = new Semaphore( 0 );
         commandReader.addByeAckListener( new CommandListener()
                                           {
                                               @Override
                                               public void update( Command command )
                                               {
-                                                  barrier.release();
+                                                  exitBarrier.release();
                                               }
                                           }
         );
         eventChannel.bye();
         launchLastDitchDaemonShutdownThread( 0 );
         long timeoutMillis = max( systemExitTimeoutInSeconds * ONE_SECOND_IN_MILLIS, ONE_SECOND_IN_MILLIS );
-        acquireOnePermit( barrier, timeoutMillis );
+        acquireOnePermit( exitBarrier, timeoutMillis );
         cancelPingScheduler();
         commandReader.stop();
         System.exit( 0 );
@@ -342,14 +377,24 @@ public final class ForkedBooter
     @SuppressWarnings( "checkstyle:emptyblock" )
     private void launchLastDitchDaemonShutdownThread( final int returnCode )
     {
-        getJvmTerminator().schedule( new Runnable()
-                                        {
-                                            @Override
-                                            public void run()
-                                            {
-                                                kill( returnCode );
-                                            }
-                                        }, systemExitTimeoutInSeconds, SECONDS
+        getJvmTerminator()
+                .schedule( new Runnable()
+                {
+                    @Override
+                    public void run()
+                    {
+                        DumpErrorSingleton.getSingleton()
+                                .dumpText( "Thread dump for process ("
+                                        + getProcessName()
+                                        + ") after "
+                                        + systemExitTimeoutInSeconds
+                                        + " seconds shutdown timeout:"
+                                        + NL
+                                        + generateThreadDump() );
+
+                        kill( returnCode );
+                    }
+                }, systemExitTimeoutInSeconds, SECONDS
         );
     }
 
@@ -472,4 +517,34 @@ public final class ForkedBooter
             return pingScheduler.isShutdown();
         }
     }
+
+    private static String generateThreadDump()
+    {
+        StringBuilder dump = new StringBuilder();
+        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
+        ThreadInfo[] threadInfos = threadMXBean.getThreadInfo( threadMXBean.getAllThreadIds(), 100 );
+        for ( ThreadInfo threadInfo : threadInfos )
+        {
+            dump.append( '"' );
+            dump.append( threadInfo.getThreadName() );
+            dump.append( "\" " );
+            Thread.State state = threadInfo.getThreadState();
+            dump.append( "\n   java.lang.Thread.State: " );
+            dump.append( state );
+            StackTraceElement[] stackTraceElements = threadInfo.getStackTrace();
+            for ( StackTraceElement stackTraceElement : stackTraceElements )
+            {
+                dump.append( "\n        at " );
+                dump.append( stackTraceElement );
+            }
+            dump.append( "\n\n" );
+        }
+        return dump.toString();
+    }
+
+    private static String getProcessName()
+    {
+        return ManagementFactory.getRuntimeMXBean()
+                .getName();
+    }
 }
diff --git a/surefire-its/pom.xml b/surefire-its/pom.xml
index 2c4a7e6..cd9eb26 100644
--- a/surefire-its/pom.xml
+++ b/surefire-its/pom.xml
@@ -175,7 +175,7 @@
                     <forkMode>once</forkMode>
                     <argLine>-server -Xmx64m -XX:+UseG1GC -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Djava.awt.headless=true -Djdk.net.URLClassPath.disableClassPathURLCheck=true</argLine>
                     <includes>
-                        <include>org/apache/**/*IT*.java</include>
+                        <include>org/apache/**/Surefire946KillMainProcessInReusableForkIT.java</include>
                     </includes>
                     <!-- Pass current surefire version to the main suite so that it -->
                     <!-- can forward to all integration test projects. SUREFIRE-513 -->
diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire946KillMainProcessInReusableForkIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire946KillMainProcessInReusableForkIT.java
index a5740c0..8caf620 100644
--- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire946KillMainProcessInReusableForkIT.java
+++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire946KillMainProcessInReusableForkIT.java
@@ -19,48 +19,109 @@ package org.apache.maven.surefire.its.jiras;
  * under the License.
  */
 
+import com.googlecode.junittoolbox.ParallelParameterized;
 import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
+import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+import org.w3c.dom.Document;
 
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathFactory;
+import java.io.File;
+import java.util.ArrayList;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+@RunWith( ParallelParameterized.class )
 public class Surefire946KillMainProcessInReusableForkIT
     extends SurefireJUnit4IntegrationTestCase
 {
-    // there are 10 test classes that each would wait 2 seconds.
-    private static final int TEST_SLEEP_TIME = 2000;
+    // there are 10 test classes that each would wait 3.5 seconds.
+    private static final int TEST_SLEEP_TIME = 3_500;
 
-    @BeforeClass
-    public static void installSelfdestructPlugin()
-    {
-        unpack( Surefire946KillMainProcessInReusableForkIT.class, "surefire-946-self-destruct-plugin", "plugin" ).executeInstall();
-    }
+    private String classifierOfDummyDependency;
+
+    @Parameter
+    public String shutdownMavenMethod;
+
+    @Parameter( 1 )
+    public String shutdownSurefireMethod;
 
-    @Test( timeout = 30000 )
-    public void testHalt()
+    @Parameters( name = "{0}-{1}")
+    public static Iterable<Object[]> data()
     {
-        doTest( "halt" );
+        ArrayList<Object[]> args = new ArrayList<>();
+        args.add( new Object[] { "halt", "exit" } );
+        args.add( new Object[] { "halt", "kill" } );
+        args.add( new Object[] { "exit", "exit" } );
+        args.add( new Object[] { "exit", "kill" } );
+        args.add( new Object[] { "interrupt", "exit" } );
+        args.add( new Object[] { "interrupt", "kill" } );
+        return args;
     }
 
-    @Test( timeout = 30000 )
-    public void testExit()
+    @BeforeClass
+    public static void installSelfdestructPlugin()
     {
-        doTest( "exit" );
+        unpack( Surefire946KillMainProcessInReusableForkIT.class, "surefire-946-self-destruct-plugin", "plugin" )
+                .executeInstall();
     }
 
-    @Test( timeout = 30000 )
-    public void testInterrupt()
+    @Before
+    public void dummyDep()
     {
-        doTest( "interrupt" );
+        classifierOfDummyDependency = shutdownMavenMethod + shutdownSurefireMethod;
+        unpack( Surefire946KillMainProcessInReusableForkIT.class,
+                "surefire-946-dummy-dependency", classifierOfDummyDependency )
+                .sysProp( "distinct.classifier", classifierOfDummyDependency )
+                .executeInstall();
     }
 
-    private void doTest( String method )
+    @Test( timeout = 60_000 )
+    public void test() throws Exception
     {
-        unpack( "surefire-946-killMainProcessInReusableFork" )
-            .sysProp( "selfdestruct.timeoutInMillis", "5000" )
-            .sysProp( "selfdestruct.method", method )
-            .sysProp( "testSleepTime", String.valueOf( TEST_SLEEP_TIME ) )
-            .addGoal( "org.apache.maven.plugins.surefire:maven-selfdestruct-plugin:selfdestruct" )
-            .setForkJvm()
-            .forkPerThread().threadCount( 1 ).reuseForks( true ).maven().withFailure().executeTest();
+        unpack( "surefire-946-killMainProcessInReusableFork",
+                "-" + shutdownMavenMethod + "-" + shutdownSurefireMethod )
+                .sysProp( "distinct.classifier", classifierOfDummyDependency )
+                .sysProp( "surefire.shutdown", shutdownSurefireMethod )
+                .sysProp( "selfdestruct.timeoutInMillis", "5000" )
+                .sysProp( "selfdestruct.method", shutdownMavenMethod )
+                .sysProp( "testSleepTime", String.valueOf( TEST_SLEEP_TIME ) )
+                .addGoal( "org.apache.maven.plugins.surefire:maven-selfdestruct-plugin:selfdestruct" )
+                .setForkJvm()
+                .forkPerThread().threadCount( 1 ).reuseForks( true ).maven().withFailure().executeTest();
+
+
+        XPathFactory xpathFactory = XPathFactory.newInstance();
+        XPath xpath = xpathFactory.newXPath();
+        File settings = new File( System.getProperty( "maven.settings.file" ) ).getCanonicalFile();
+        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( settings );
+        String localRepository = xpath.evaluate( "/settings/localRepository", doc );
+        assertThat( localRepository )
+                .isNotNull()
+                .isNotEmpty();
+
+        File dep = new File( localRepository,
+                "org/apache/maven/plugins/surefire/surefire-946-dummy-dependency/0.1/"
+                        + "surefire-946-dummy-dependency-0.1-" + classifierOfDummyDependency + ".jar" );
+
+        assertThat( dep )
+                .exists();
+
+        boolean deleted;
+        int iterations = 0;
+        do
+        {
+            Thread.sleep( 1_000L );
+            deleted = dep.delete();
+        }
+        while ( !deleted && ++iterations < 10 );
+        assertThat( deleted )
+                .isTrue();
     }
 }
diff --git a/surefire-its/src/test/resources/surefire-946-dummy-dependency/pom.xml b/surefire-its/src/test/resources/surefire-946-dummy-dependency/pom.xml
new file mode 100644
index 0000000..d2fdf86
--- /dev/null
+++ b/surefire-its/src/test/resources/surefire-946-dummy-dependency/pom.xml
@@ -0,0 +1,39 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.maven.plugins.surefire</groupId>
+    <artifactId>surefire-946-dummy-dependency</artifactId>
+    <version>0.1</version>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <maven.compiler.source>1.7</maven.compiler.source>
+        <maven.compiler.target>1.7</maven.compiler.target>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <!--
+                No test sources here.
+                Purpose to pre-install.
+                See the Surefire946KillMainProcessInReusableForkIT.
+                -->
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${surefire.version}</version>
+                <configuration>
+                    <skipTests>true</skipTests>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>3.1.2</version>
+                <configuration>
+                    <classifier>${distinct.classifier}</classifier>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic01Test.java b/surefire-its/src/test/resources/surefire-946-dummy-dependency/src/main/java/dummy/DummyClass.java
similarity index 67%
copy from surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic01Test.java
copy to surefire-its/src/test/resources/surefire-946-dummy-dependency/src/main/java/dummy/DummyClass.java
index 8c52d1b..014cabb 100644
--- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic01Test.java
+++ b/surefire-its/src/test/resources/surefire-946-dummy-dependency/src/main/java/dummy/DummyClass.java
@@ -1,5 +1,3 @@
-package junit44.environment;
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -19,27 +17,16 @@ package junit44.environment;
  * under the License.
  */
 
-import org.junit.AfterClass;
-import org.junit.Test;
+package dummy;
 
-public class Basic01Test
+/**
+ *
+ */
+public class DummyClass
 {
-
-    @Test
-    public void testNothing()
+    @Override
+    public String toString()
     {
+        return "JVM handles a file handler to 'surefire-946-dummy-dependency-0.1.jar'.";
     }
-
-    @AfterClass
-    public static void waitSomeTimeAround()
-    {
-        try
-        {
-            Thread.sleep( Integer.getInteger( "testSleepTime", 2000 ) );
-        }
-        catch ( InterruptedException ignored )
-        {
-        }
-    }
-
-}
+}
\ No newline at end of file
diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/pom.xml b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/pom.xml
index 53bb0a3..2240fe4 100644
--- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/pom.xml
+++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/pom.xml
@@ -27,12 +27,19 @@
 	<name>Tests killing the main maven process when using reusable forks</name>
 
 	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<maven.compiler.source>1.7</maven.compiler.source>
 		<maven.compiler.target>1.7</maven.compiler.target>
 	</properties>
 
 	<dependencies>
 		<dependency>
+			<groupId>org.apache.maven.plugins.surefire</groupId>
+			<artifactId>surefire-946-dummy-dependency</artifactId>
+			<version>0.1</version>
+			<classifier>${distinct.classifier}</classifier>
+		</dependency>
+		<dependency>
 			<groupId>junit</groupId>
 			<artifactId>junit</artifactId>
 			<version>4.4</version>
diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic01Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic01Test.java
index 8c52d1b..77971fd 100644
--- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic01Test.java
+++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic01Test.java
@@ -19,6 +19,7 @@ package junit44.environment;
  * under the License.
  */
 
+import dummy.DummyClass;
 import org.junit.AfterClass;
 import org.junit.Test;
 
@@ -28,6 +29,7 @@ public class Basic01Test
     @Test
     public void testNothing()
     {
+        System.out.println( new DummyClass().toString() );
     }
 
     @AfterClass
diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic02Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic02Test.java
index 6ef33f9..1133efe 100644
--- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic02Test.java
+++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic02Test.java
@@ -19,6 +19,7 @@ package junit44.environment;
  * under the License.
  */
 
+import dummy.DummyClass;
 import org.junit.AfterClass;
 import org.junit.Test;
 
@@ -28,6 +29,7 @@ public class Basic02Test
     @Test
     public void testNothing()
     {
+        System.out.println( new DummyClass().toString() );
     }
 
     @AfterClass
diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic03Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic03Test.java
index b1d7c71..15b1bd9 100644
--- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic03Test.java
+++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic03Test.java
@@ -19,6 +19,7 @@ package junit44.environment;
  * under the License.
  */
 
+import dummy.DummyClass;
 import org.junit.AfterClass;
 import org.junit.Test;
 
@@ -28,6 +29,7 @@ public class Basic03Test
     @Test
     public void testNothing()
     {
+        System.out.println( new DummyClass().toString() );
     }
 
     @AfterClass
diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic04Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic04Test.java
index 6d082cb..4151336 100644
--- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic04Test.java
+++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic04Test.java
@@ -19,6 +19,7 @@ package junit44.environment;
  * under the License.
  */
 
+import dummy.DummyClass;
 import org.junit.AfterClass;
 import org.junit.Test;
 
@@ -28,6 +29,7 @@ public class Basic04Test
     @Test
     public void testNothing()
     {
+        System.out.println( new DummyClass().toString() );
     }
 
     @AfterClass
diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic05Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic05Test.java
index 92f5f15..3f14261 100644
--- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic05Test.java
+++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic05Test.java
@@ -19,6 +19,7 @@ package junit44.environment;
  * under the License.
  */
 
+import dummy.DummyClass;
 import org.junit.AfterClass;
 import org.junit.Test;
 
@@ -28,6 +29,7 @@ public class Basic05Test
     @Test
     public void testNothing()
     {
+        System.out.println( new DummyClass().toString() );
     }
 
     @AfterClass
diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic06Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic06Test.java
index 2a44568..1925665 100644
--- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic06Test.java
+++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic06Test.java
@@ -19,6 +19,7 @@ package junit44.environment;
  * under the License.
  */
 
+import dummy.DummyClass;
 import org.junit.AfterClass;
 import org.junit.Test;
 
@@ -28,6 +29,7 @@ public class Basic06Test
     @Test
     public void testNothing()
     {
+        System.out.println( new DummyClass().toString() );
     }
 
     @AfterClass
diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic07Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic07Test.java
index 64f180e..77436bb 100644
--- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic07Test.java
+++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic07Test.java
@@ -19,6 +19,7 @@ package junit44.environment;
  * under the License.
  */
 
+import dummy.DummyClass;
 import org.junit.AfterClass;
 import org.junit.Test;
 
@@ -28,6 +29,7 @@ public class Basic07Test
     @Test
     public void testNothing()
     {
+        System.out.println( new DummyClass().toString() );
     }
 
     @AfterClass
diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic08Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic08Test.java
index 5a4c382..ed62c32 100644
--- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic08Test.java
+++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic08Test.java
@@ -19,6 +19,7 @@ package junit44.environment;
  * under the License.
  */
 
+import dummy.DummyClass;
 import org.junit.AfterClass;
 import org.junit.Test;
 
@@ -28,6 +29,7 @@ public class Basic08Test
     @Test
     public void testNothing()
     {
+        System.out.println( new DummyClass().toString() );
     }
 
     @AfterClass
diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic09Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic09Test.java
index 2461d11..87043e2 100644
--- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic09Test.java
+++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic09Test.java
@@ -19,6 +19,7 @@ package junit44.environment;
  * under the License.
  */
 
+import dummy.DummyClass;
 import org.junit.AfterClass;
 import org.junit.Test;
 
@@ -28,6 +29,7 @@ public class Basic09Test
     @Test
     public void testNothing()
     {
+        System.out.println( new DummyClass().toString() );
     }
 
     @AfterClass
diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic10Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic10Test.java
index 1e57b13..d481da7 100644
--- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic10Test.java
+++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic10Test.java
@@ -19,6 +19,7 @@ package junit44.environment;
  * under the License.
  */
 
+import dummy.DummyClass;
 import org.junit.AfterClass;
 import org.junit.Test;
 
@@ -28,6 +29,7 @@ public class Basic10Test
     @Test
     public void testNothing()
     {
+        System.out.println( new DummyClass().toString() );
     }
 
     @AfterClass
diff --git a/surefire-its/src/test/resources/surefire-946-self-destruct-plugin/pom.xml b/surefire-its/src/test/resources/surefire-946-self-destruct-plugin/pom.xml
index ad4ff00..5abb052 100644
--- a/surefire-its/src/test/resources/surefire-946-self-destruct-plugin/pom.xml
+++ b/surefire-its/src/test/resources/surefire-946-self-destruct-plugin/pom.xml
@@ -22,12 +22,6 @@
       <artifactId>maven-plugin-api</artifactId>
       <version>2.0</version>
     </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>3.8.1</version>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
 
   <build>