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 2018/09/06 23:35:31 UTC

[maven-surefire] 02/02: [SUREFIRE-1565] Surefire should support parameterized reportsDirectory

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

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

commit 232d260cad3091f3315f880a061efdf7c03d9c65
Author: Tibor17 <ti...@apache.org>
AuthorDate: Fri Sep 7 01:35:21 2018 +0200

    [SUREFIRE-1565] Surefire should support parameterized reportsDirectory
---
 .../plugin/surefire/AbstractSurefireMojo.java      |  20 +---
 .../surefire/StartupReportConfiguration.java       |  28 ++---
 .../maven/plugin/surefire/SurefireHelper.java      |  49 +++++++++
 .../surefire/booterclient/BooterSerializer.java    |   6 +-
 .../booterclient/DefaultForkConfiguration.java     |  16 +--
 .../plugin/surefire/booterclient/ForkStarter.java  |  64 ++++++-----
 .../surefire/booterclient/output/ForkClient.java   |  18 ++--
 .../output/InPluginProcessDumpSingleton.java       |  57 ++++++----
 .../output/NativeStdErrStreamConsumer.java         |   3 +-
 .../surefire/report/ConsoleOutputFileReporter.java |  38 ++++---
 .../surefire/report/DefaultReporterFactory.java    |  26 ++---
 .../surefire/report/NullConsoleOutputReceiver.java |  59 ----------
 .../maven/plugin/surefire/SurefireHelperTest.java  |  26 ++++-
 ...ooterDeserializerProviderConfigurationTest.java |   2 +-
 ...BooterDeserializerStartupConfigurationTest.java |   4 +-
 .../booterclient/ForkingRunListenerTest.java       |  10 +-
 .../report/ConsoleOutputFileReporterTest.java      |   8 +-
 maven-surefire-plugin/src/site/fml/faq.fml         |   1 +
 .../maven/surefire/booter/DumpErrorSingleton.java  |  15 ++-
 .../surefire/util/internal/DumpFileUtils.java      |   8 +-
 .../apache/maven/surefire/booter/ForkedBooter.java |   3 +-
 .../maven/surefire/its/fixture/TestFile.java       |  11 +-
 .../jiras/Surefire1535TestNGParallelSuitesIT.java  | 119 +++++++++++++++++++--
 .../surefire-1535-parallel-testng/pom.xml          |  48 ++++-----
 .../src/test/java/it/ParallelTest1.java            |   1 +
 .../src/test/java/it/ParallelTest2.java            |   1 +
 26 files changed, 382 insertions(+), 259 deletions(-)

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 fa19214..cc3dff9 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
@@ -120,6 +120,7 @@ import static java.util.Collections.singletonMap;
 import static org.apache.commons.lang3.StringUtils.substringBeforeLast;
 import static org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS;
 import static org.apache.maven.plugin.surefire.util.DependencyScanner.filter;
+import static org.apache.maven.plugin.surefire.SurefireHelper.replaceThreadNumberPlaceholders;
 import static org.apache.maven.shared.utils.StringUtils.capitalizeFirstLetter;
 import static org.apache.maven.shared.utils.StringUtils.isEmpty;
 import static org.apache.maven.shared.utils.StringUtils.isNotBlank;
@@ -769,19 +770,6 @@ public abstract class AbstractSurefireMojo
 
     private int effectiveForkCount = -1;
 
-    /**
-     * The placeholder that is replaced by the executing thread's running number. The thread number
-     * range starts with 1
-     * Deprecated.
-     */
-    public static final String THREAD_NUMBER_PLACEHOLDER = "${surefire.threadNumber}";
-
-    /**
-     * The placeholder that is replaced by the executing fork's running number. The fork number
-     * range starts with 1
-     */
-    public static final String FORK_NUMBER_PLACEHOLDER = "${surefire.forkNumber}";
-
     protected abstract String getPluginName();
 
     protected abstract int getRerunFailingTestsCount();
@@ -1215,16 +1203,12 @@ public abstract class AbstractSurefireMojo
         SurefireProperties effectiveSystemProperties, int threadNumber )
     {
         SurefireProperties filteredProperties = new SurefireProperties( ( KeyValueSource) effectiveSystemProperties );
-        String threadNumberString = String.valueOf( threadNumber );
         for ( Entry<Object, Object> entry : effectiveSystemProperties.entrySet() )
         {
             if ( entry.getValue() instanceof String )
             {
                 String value = (String) entry.getValue();
-                value = value.replace( THREAD_NUMBER_PLACEHOLDER, threadNumberString );
-                value = value.replace( FORK_NUMBER_PLACEHOLDER, threadNumberString );
-
-                filteredProperties.put( entry.getKey(), value );
+                filteredProperties.put( entry.getKey(), replaceThreadNumberPlaceholders( value, threadNumber ) );
             }
         }
         return filteredProperties;
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java
index caf0db3..26d4d18 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java
@@ -35,6 +35,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
+import static org.apache.maven.plugin.surefire.SurefireHelper.replaceForkThreadsInPath;
 import static org.apache.maven.plugin.surefire.report.ConsoleReporter.BRIEF;
 import static org.apache.maven.plugin.surefire.report.ConsoleReporter.PLAIN;
 import static org.apache.commons.lang3.StringUtils.trimToNull;
@@ -47,10 +48,6 @@ import static org.apache.commons.lang3.StringUtils.trimToNull;
  */
 public final class StartupReportConfiguration
 {
-    public static final String BRIEF_REPORT_FORMAT = BRIEF;
-
-    public static final String PLAIN_REPORT_FORMAT = PLAIN;
-
     private final PrintStream originalSystemOut;
 
     private final PrintStream originalSystemErr;
@@ -151,31 +148,31 @@ public final class StartupReportConfiguration
         return rerunFailingTestsCount;
     }
 
-    public StatelessXmlReporter instantiateStatelessXmlReporter()
+    public StatelessXmlReporter instantiateStatelessXmlReporter( Integer forkNumber )
     {
         return isDisableXmlReport()
             ? null
-            : new StatelessXmlReporter( reportsDirectory, reportNameSuffix, trimStackTrace, rerunFailingTestsCount,
-                                        testClassMethodRunHistory, xsdSchemaLocation );
+            : new StatelessXmlReporter( resolveReportsDirectory( forkNumber ), reportNameSuffix, trimStackTrace,
+                rerunFailingTestsCount, testClassMethodRunHistory, xsdSchemaLocation );
     }
 
-    public FileReporter instantiateFileReporter()
+    public FileReporter instantiateFileReporter( Integer forkNumber )
     {
         return isUseFile() && isBriefOrPlainFormat()
-            ? new FileReporter( reportsDirectory, getReportNameSuffix(), encoding )
+            ? new FileReporter( resolveReportsDirectory( forkNumber ), reportNameSuffix, encoding )
             : null;
     }
 
     public boolean isBriefOrPlainFormat()
     {
         String fmt = getReportFormat();
-        return BRIEF_REPORT_FORMAT.equals( fmt ) || PLAIN_REPORT_FORMAT.equals( fmt );
+        return BRIEF.equals( fmt ) || PLAIN.equals( fmt );
     }
 
-    public TestcycleConsoleOutputReceiver instantiateConsoleOutputFileReporter()
+    public TestcycleConsoleOutputReceiver instantiateConsoleOutputFileReporter( Integer forkNumber )
     {
         return isRedirectTestOutputToFile()
-            ? new ConsoleOutputFileReporter( reportsDirectory, getReportNameSuffix() )
+            ? new ConsoleOutputFileReporter( resolveReportsDirectory( forkNumber ), reportNameSuffix, forkNumber )
             : new DirectConsoleOutput( originalSystemOut, originalSystemErr );
     }
 
@@ -183,7 +180,7 @@ public final class StartupReportConfiguration
     {
         if ( statisticsReporter == null )
         {
-            statisticsReporter = requiresRunHistory ? new StatisticsReporter( getStatisticsFile() ) : null;
+            statisticsReporter = requiresRunHistory ? new StatisticsReporter( statisticsFile ) : null;
         }
         return statisticsReporter;
     }
@@ -217,4 +214,9 @@ public final class StartupReportConfiguration
     {
         return encoding;
     }
+
+    private File resolveReportsDirectory( Integer forkNumber )
+    {
+        return forkNumber == null ? reportsDirectory : replaceForkThreadsInPath( reportsDirectory, forkNumber );
+    }
 }
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireHelper.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireHelper.java
index dd29cb4..44dbdd4 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireHelper.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireHelper.java
@@ -29,10 +29,14 @@ import org.apache.maven.surefire.suite.RunResult;
 import org.apache.maven.surefire.testset.TestSetFailedException;
 import org.apache.maven.surefire.util.internal.DumpFileUtils;
 
+import javax.annotation.Nonnull;
+import java.io.File;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Deque;
+import java.util.LinkedList;
 import java.util.List;
 
 import static java.util.Collections.unmodifiableList;
@@ -54,8 +58,14 @@ public final class SurefireHelper
 
     public static final String DUMP_FILE_PREFIX = DUMP_FILE_DATE + "-jvmRun";
 
+    public static final String DUMP_FILENAME_FORMATTER = DUMP_FILE_PREFIX + "%d" + DUMP_FILE_EXT;
+
     public static final String DUMPSTREAM_FILENAME_FORMATTER = DUMP_FILE_PREFIX + "%d" + DUMPSTREAM_FILE_EXT;
 
+    public static final String DUMPSTREAM_FILENAME = DUMP_FILE_DATE + DUMPSTREAM_FILE_EXT;
+
+    public static final String DUMP_FILENAME = DUMP_FILE_DATE + DUMP_FILE_EXT;
+
     /**
      * The maximum path that does not require long path prefix on Windows.<br>
      * See {@code sun/nio/fs/WindowsPath} in
@@ -71,12 +81,26 @@ public final class SurefireHelper
 
     private static final String[] DUMP_FILES_PRINT =
             {
+                    "[date]" + DUMP_FILE_EXT,
                     "[date]-jvmRun[N]" + DUMP_FILE_EXT,
                     "[date]" + DUMPSTREAM_FILE_EXT,
                     "[date]-jvmRun[N]" + DUMPSTREAM_FILE_EXT
             };
 
     /**
+     * The placeholder that is replaced by the executing thread's running number. The thread number
+     * range starts with 1
+     * Deprecated.
+     */
+    private static final String THREAD_NUMBER_PLACEHOLDER = "${surefire.threadNumber}";
+
+    /**
+     * The placeholder that is replaced by the executing fork's running number. The fork number
+     * range starts with 1
+     */
+    private static final String FORK_NUMBER_PLACEHOLDER = "${surefire.forkNumber}";
+
+    /**
      * Do not instantiate.
      */
     private SurefireHelper()
@@ -84,6 +108,31 @@ public final class SurefireHelper
         throw new IllegalAccessError( "Utility class" );
     }
 
+    @Nonnull
+    public static String replaceThreadNumberPlaceholders( @Nonnull String argLine, int threadNumber )
+    {
+        String threadNumberAsString = String.valueOf( threadNumber );
+        return argLine.replace( THREAD_NUMBER_PLACEHOLDER, threadNumberAsString )
+                .replace( FORK_NUMBER_PLACEHOLDER, threadNumberAsString );
+    }
+
+    public static File replaceForkThreadsInPath( File path, int replacement )
+    {
+        Deque<String> dirs = new LinkedList<String>();
+        File root = path;
+        while ( !root.exists() )
+        {
+            dirs.addFirst( replaceThreadNumberPlaceholders( root.getName(), replacement ) );
+            root = root.getParentFile();
+        }
+        File replacedPath = root;
+        for ( String dir : dirs )
+        {
+            replacedPath = new File( replacedPath, dir );
+        }
+        return replacedPath;
+    }
+
     public static String[] getDumpFilesToPrint()
     {
         return DUMP_FILES_PRINT.clone();
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 9c501db..fe72fce 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
@@ -39,6 +39,7 @@ import java.io.IOException;
 import java.util.Collections;
 import java.util.List;
 
+import static org.apache.maven.plugin.surefire.SurefireHelper.replaceForkThreadsInPath;
 import static org.apache.maven.surefire.booter.AbstractPathConfiguration.CHILD_DELEGATION;
 import static org.apache.maven.surefire.booter.AbstractPathConfiguration.CLASSPATH;
 import static org.apache.maven.surefire.booter.AbstractPathConfiguration.ENABLE_ASSERTIONS;
@@ -99,7 +100,7 @@ class BooterSerializer
      */
     File serialize( KeyValueSource sourceProperties, ProviderConfiguration booterConfiguration,
                     StartupConfiguration providerConfiguration, Object testSet, boolean readTestsFromInStream,
-                    Long pid )
+                    Long pid, int forkNumber )
         throws IOException
     {
         SurefireProperties properties = new SurefireProperties( sourceProperties );
@@ -159,8 +160,9 @@ class BooterSerializer
 
         ReporterConfiguration reporterConfiguration = booterConfiguration.getReporterConfiguration();
         boolean rep = reporterConfiguration.isTrimStackTrace();
+        File reportsDirectory = replaceForkThreadsInPath( reporterConfiguration.getReportsDirectory(), forkNumber );
         properties.setProperty( ISTRIMSTACKTRACE, rep );
-        properties.setProperty( REPORTSDIRECTORY, reporterConfiguration.getReportsDirectory() );
+        properties.setProperty( REPORTSDIRECTORY, reportsDirectory );
         ClassLoaderConfiguration classLoaderConfig = providerConfiguration.getClassLoaderConfiguration();
         properties.setProperty( USESYSTEMCLASSLOADER, toString( classLoaderConfig.isUseSystemClassLoader() ) );
         properties.setProperty( USEMANIFESTONLYJAR, toString( classLoaderConfig.isUseManifestOnlyJar() ) );
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java
index c35d01c..591491d 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java
@@ -37,9 +37,9 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
 
-import static org.apache.maven.plugin.surefire.AbstractSurefireMojo.FORK_NUMBER_PLACEHOLDER;
-import static org.apache.maven.plugin.surefire.AbstractSurefireMojo.THREAD_NUMBER_PLACEHOLDER;
+import static org.apache.maven.plugin.surefire.SurefireHelper.replaceForkThreadsInPath;
 import static org.apache.maven.plugin.surefire.util.Relocator.relocate;
+import static org.apache.maven.plugin.surefire.SurefireHelper.replaceThreadNumberPlaceholders;
 import static org.apache.maven.surefire.booter.Classpath.join;
 
 /**
@@ -169,7 +169,7 @@ public abstract class DefaultForkConfiguration
     private File getWorkingDirectory( int forkNumber )
             throws SurefireBooterForkException
     {
-        File cwd = new File( replaceThreadNumberPlaceholder( getWorkingDirectory().getAbsolutePath(), forkNumber ) );
+        File cwd = replaceForkThreadsInPath( getWorkingDirectory(), forkNumber );
 
         if ( !cwd.exists() && !cwd.mkdirs() )
         {
@@ -184,14 +184,6 @@ public abstract class DefaultForkConfiguration
         return cwd;
     }
 
-    @Nonnull
-    private static String replaceThreadNumberPlaceholder( @Nonnull String argLine, int threadNumber )
-    {
-        String threadNumberAsString = String.valueOf( threadNumber );
-        return argLine.replace( THREAD_NUMBER_PLACEHOLDER, threadNumberAsString )
-                .replace( FORK_NUMBER_PLACEHOLDER, threadNumberAsString );
-    }
-
     /**
      * Replaces expressions <pre>@{property-name}</pre> with the corresponding properties
      * from the model. This allows late evaluation of property values when the plugin is executed (as compared
@@ -331,7 +323,7 @@ public abstract class DefaultForkConfiguration
     private String newJvmArgLine( int forks )
     {
         String interpolatedArgs = stripNewLines( interpolateArgLineWithPropertyExpressions() );
-        String argsWithReplacedForkNumbers = replaceThreadNumberPlaceholder( interpolatedArgs, forks );
+        String argsWithReplacedForkNumbers = replaceThreadNumberPlaceholders( interpolatedArgs, forks );
         return extendJvmArgLine( argsWithReplacedForkNumbers );
     }
 
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 44b5bff..74645a4 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
@@ -197,8 +197,9 @@ public class ForkStarter
                     // if tests failed, but if this does not happen then printing warning to console is the only way to
                     // inform the users.
                     String msg = "ForkStarter IOException: " + e.getLocalizedMessage() + ".";
+                    File reportsDir = defaultReporterFactory.getReportsDirectory();
                     File dump = InPluginProcessDumpSingleton.getSingleton()
-                                        .dumpException( e, msg, defaultReporterFactory, jvmRun );
+                                        .dumpStreamException( e, msg, reportsDir, jvmRun );
                     log.warning( msg + " See the dump file " + dump.getAbsolutePath() );
                 }
             }
@@ -264,21 +265,25 @@ public class ForkStarter
     private RunResult run( SurefireProperties effectiveSystemProperties, Map<String, String> providerProperties )
             throws SurefireBooterForkException
     {
-        DefaultReporterFactory forkedReporterFactory = new DefaultReporterFactory( startupReportConfiguration, log );
-        defaultReporterFactories.add( forkedReporterFactory );
         TestLessInputStreamBuilder builder = new TestLessInputStreamBuilder();
         PropertiesWrapper props = new PropertiesWrapper( providerProperties );
         TestLessInputStream stream = builder.build();
-        ForkClient forkClient = new ForkClient( forkedReporterFactory, stream, log, new AtomicBoolean() );
         Thread shutdown = createImmediateShutdownHookThread( builder, providerConfiguration.getShutdown() );
         ScheduledFuture<?> ping = triggerPingTimerForShutdown( builder );
+        int forkNumber = drawNumber();
         try
         {
             addShutDownHook( shutdown );
-            return fork( null, props, forkClient, effectiveSystemProperties, stream, false );
+            DefaultReporterFactory forkedReporterFactory =
+                    new DefaultReporterFactory( startupReportConfiguration, log, forkNumber );
+            defaultReporterFactories.add( forkedReporterFactory );
+            ForkClient forkClient =
+                    new ForkClient( forkedReporterFactory, stream, log, new AtomicBoolean(), forkNumber );
+            return fork( null, props, forkClient, effectiveSystemProperties, forkNumber, stream, false );
         }
         finally
         {
+            returnNumber( forkNumber );
             removeShutdownHook( shutdown );
             ping.cancel( true );
             builder.removeStream( stream );
@@ -344,10 +349,12 @@ public class ForkStarter
                     public RunResult call()
                         throws Exception
                     {
-                        DefaultReporterFactory reporter = new DefaultReporterFactory( startupReportConfiguration, log );
+                        int forkNumber = drawNumber();
+                        DefaultReporterFactory reporter =
+                                new DefaultReporterFactory( startupReportConfiguration, log, forkNumber );
                         defaultReporterFactories.add( reporter );
-                        ForkClient forkClient =
-                                new ForkClient( reporter, testProvidingInputStream, log, printedErrorStream )
+                        ForkClient forkClient = new ForkClient( reporter, testProvidingInputStream, log,
+                                printedErrorStream, forkNumber )
                         {
                             @Override
                             protected void stopOnNextTest()
@@ -358,9 +365,16 @@ public class ForkStarter
                                 }
                             }
                         };
-
-                        return fork( null, new PropertiesWrapper( providerConfiguration.getProviderProperties() ),
-                                 forkClient, effectiveSystemProperties, testProvidingInputStream, true );
+                        Map<String, String> providerProperties = providerConfiguration.getProviderProperties();
+                        try
+                        {
+                            return fork( null, new PropertiesWrapper( providerProperties ), forkClient,
+                                    effectiveSystemProperties, forkNumber, testProvidingInputStream, true );
+                        }
+                        finally
+                        {
+                            returnNumber( forkNumber );
+                        }
                     }
                 };
                 results.add( executorService.submit( pf ) );
@@ -408,11 +422,12 @@ public class ForkStarter
                     public RunResult call()
                         throws Exception
                     {
+                        int forkNumber = drawNumber();
                         DefaultReporterFactory forkedReporterFactory =
-                            new DefaultReporterFactory( startupReportConfiguration, log );
+                            new DefaultReporterFactory( startupReportConfiguration, log, forkNumber );
                         defaultReporterFactories.add( forkedReporterFactory );
                         ForkClient forkClient = new ForkClient( forkedReporterFactory, builder.getImmediateCommands(),
-                                log, printedErrorStream )
+                                log, printedErrorStream, forkNumber )
                         {
                             @Override
                             protected void stopOnNextTest()
@@ -428,10 +443,11 @@ public class ForkStarter
                         {
                             return fork( testSet,
                                          new PropertiesWrapper( providerConfiguration.getProviderProperties() ),
-                                         forkClient, effectiveSystemProperties, stream, false );
+                                         forkClient, effectiveSystemProperties, forkNumber, stream, false );
                         }
                         finally
                         {
+                            returnNumber( forkNumber );
                             builder.removeStream( stream );
                         }
                     }
@@ -522,24 +538,6 @@ public class ForkStarter
     }
 
     private RunResult fork( Object testSet, KeyValueSource providerProperties, ForkClient forkClient,
-                            SurefireProperties effectiveSystemProperties,
-                            AbstractForkInputStream testProvidingInputStream, boolean readTestsFromInStream )
-        throws SurefireBooterForkException
-    {
-        int forkNumber = drawNumber();
-        forkClient.setForkNumber( forkNumber );
-        try
-        {
-            return fork( testSet, providerProperties, forkClient, effectiveSystemProperties, forkNumber,
-                         testProvidingInputStream, readTestsFromInStream );
-        }
-        finally
-        {
-            returnNumber( forkNumber );
-        }
-    }
-
-    private RunResult fork( Object testSet, KeyValueSource providerProperties, ForkClient forkClient,
                             SurefireProperties effectiveSystemProperties, int forkNumber,
                             AbstractForkInputStream testProvidingInputStream, boolean readTestsFromInStream )
         throws SurefireBooterForkException
@@ -553,7 +551,7 @@ public class ForkStarter
             BooterSerializer booterSerializer = new BooterSerializer( forkConfiguration );
             Long pluginPid = forkConfiguration.getPluginPlatform().getPluginPid();
             surefireProperties = booterSerializer.serialize( providerProperties, providerConfiguration,
-                    startupConfiguration, testSet, readTestsFromInStream, pluginPid );
+                    startupConfiguration, testSet, readTestsFromInStream, pluginPid, forkNumber );
 
             log.debug( "Determined Maven Process ID " + pluginPid );
 
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 4871e2a..254111b 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
@@ -107,6 +107,8 @@ public class ForkClient
      */
     private final AtomicBoolean printedErrorStream;
 
+    private final int forkNumber;
+
     /**
      * Used by single Thread started by {@link ThreadedStreamConsumer} and therefore does not need to be volatile.
      */
@@ -119,15 +121,14 @@ public class ForkClient
 
     private volatile StackTraceWriter errorInFork;
 
-    private volatile int forkNumber;
-
     public ForkClient( DefaultReporterFactory defaultReporterFactory, NotifiableTestStream notifiableTestStream,
-                       ConsoleLogger log, AtomicBoolean printedErrorStream )
+                       ConsoleLogger log, AtomicBoolean printedErrorStream, int forkNumber )
     {
         this.defaultReporterFactory = defaultReporterFactory;
         this.notifiableTestStream = notifiableTestStream;
         this.log = log;
         this.printedErrorStream = printedErrorStream;
+        this.forkNumber = forkNumber;
     }
 
     protected void stopOnNextTest()
@@ -317,10 +318,11 @@ public class ForkClient
             String msg = "Corrupted STDOUT by directly writing to native stream in forked JVM " + forkNumber + ".";
 
             InPluginProcessDumpSingleton util = InPluginProcessDumpSingleton.getSingleton();
+            File reportsDir = defaultReporterFactory.getReportsDirectory();
             File dump =
                     e == null
-                    ? util.dumpText( msg + " Stream '" + event + "'.", defaultReporterFactory, forkNumber )
-                    : util.dumpException( e, msg + " Stream '" + event + "'.", defaultReporterFactory, forkNumber );
+                    ? util.dumpStreamText( msg + " Stream '" + event + "'.", reportsDir, forkNumber )
+                    : util.dumpStreamException( e, msg + " Stream '" + event + "'.", reportsDir, forkNumber );
 
             if ( printedErrorStream.compareAndSet( false, true ) )
             {
@@ -491,12 +493,6 @@ public class ForkClient
         return !testsInProgress.isEmpty();
     }
 
-    public void setForkNumber( int forkNumber )
-    {
-        assert this.forkNumber == 0;
-        this.forkNumber = forkNumber;
-    }
-
     private static final class OperationalData
     {
         private final byte operationId;
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/InPluginProcessDumpSingleton.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/InPluginProcessDumpSingleton.java
index 0676b52..d7bbe9f 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/InPluginProcessDumpSingleton.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/InPluginProcessDumpSingleton.java
@@ -19,14 +19,15 @@ package org.apache.maven.plugin.surefire.booterclient.output;
  * under the License.
  */
 
-import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
 import org.apache.maven.surefire.util.internal.DumpFileUtils;
 
 import java.io.File;
 
 import static java.lang.String.format;
+import static org.apache.maven.plugin.surefire.SurefireHelper.DUMP_FILENAME;
+import static org.apache.maven.plugin.surefire.SurefireHelper.DUMP_FILENAME_FORMATTER;
+import static org.apache.maven.plugin.surefire.SurefireHelper.DUMPSTREAM_FILENAME;
 import static org.apache.maven.plugin.surefire.SurefireHelper.DUMPSTREAM_FILENAME_FORMATTER;
-import static org.apache.maven.surefire.booter.DumpErrorSingleton.DUMPSTREAM_FILE_EXT;
 
 /**
  * Reports errors to dump file.
@@ -36,8 +37,6 @@ public final class InPluginProcessDumpSingleton
 {
     private static final InPluginProcessDumpSingleton SINGLETON = new InPluginProcessDumpSingleton();
 
-    private final String creationDate = DumpFileUtils.newFormattedDateFileName();
-
     private InPluginProcessDumpSingleton()
     {
     }
@@ -47,45 +46,59 @@ public final class InPluginProcessDumpSingleton
         return SINGLETON;
     }
 
-    public synchronized File dumpException( Throwable t, String msg, DefaultReporterFactory defaultReporterFactory,
-                                            int jvmRun )
+    public synchronized File dumpStreamException( Throwable t, String msg, File reportsDirectory, int jvmRun )
     {
-        File dump = newDumpFile( defaultReporterFactory, jvmRun );
+        File dump = newDumpStreamFile( reportsDirectory, jvmRun );
         DumpFileUtils.dumpException( t, msg == null ? "null" : msg, dump );
         return dump;
     }
 
-    public synchronized void dumpException( Throwable t, String msg, DefaultReporterFactory defaultReporterFactory )
+    public synchronized void dumpStreamException( Throwable t, String msg, File reportsDirectory )
     {
-        DumpFileUtils.dumpException( t, msg == null ? "null" : msg, newDumpFile( defaultReporterFactory ) );
+        DumpFileUtils.dumpException( t, msg == null ? "null" : msg, newDumpStreamFile( reportsDirectory ) );
     }
 
-    public synchronized void dumpException( Throwable t, DefaultReporterFactory defaultReporterFactory )
+    public synchronized File dumpStreamText( String msg, File reportsDirectory, int jvmRun )
     {
-        DumpFileUtils.dumpException( t, newDumpFile( defaultReporterFactory ) );
+        File dump = newDumpStreamFile( reportsDirectory, jvmRun );
+        DumpFileUtils.dumpText( msg == null ? "null" : msg, dump );
+        return dump;
     }
 
-    public synchronized File dumpText( String msg, DefaultReporterFactory defaultReporterFactory, int jvmRun )
+    public synchronized void dumpStreamText( String msg, File reportsDirectory )
     {
-        File dump = newDumpFile( defaultReporterFactory, jvmRun );
-        DumpFileUtils.dumpText( msg == null ? "null" : msg, dump );
-        return dump;
+        DumpFileUtils.dumpText( msg == null ? "null" : msg, newDumpStreamFile( reportsDirectory ) );
+    }
+
+    public synchronized void dumpException( Throwable t, String msg, File reportsDirectory, int jvmRun )
+    {
+        File dump = newDumpFile( reportsDirectory, jvmRun );
+        DumpFileUtils.dumpException( t, msg == null ? "null" : msg, dump );
     }
 
-    public synchronized void dumpText( String msg, DefaultReporterFactory defaultReporterFactory )
+    public synchronized void dumpException( Throwable t, String msg, File reportsDirectory )
     {
-        DumpFileUtils.dumpText( msg == null ? "null" : msg, newDumpFile( defaultReporterFactory ) );
+        File dump = newDumpFile( reportsDirectory );
+        DumpFileUtils.dumpException( t, msg == null ? "null" : msg, dump );
     }
 
-    private File newDumpFile( DefaultReporterFactory defaultReporterFactory )
+    private File newDumpStreamFile( File reportsDirectory )
     {
-        File reportsDirectory = defaultReporterFactory.getReportsDirectory();
-        return new File( reportsDirectory, creationDate + DUMPSTREAM_FILE_EXT );
+        return new File( reportsDirectory, DUMPSTREAM_FILENAME );
     }
 
-    private static File newDumpFile( DefaultReporterFactory defaultReporterFactory, int jvmRun )
+    private static File newDumpStreamFile( File reportsDirectory, int jvmRun )
     {
-        File reportsDirectory = defaultReporterFactory.getReportsDirectory();
         return new File( reportsDirectory, format( DUMPSTREAM_FILENAME_FORMATTER, jvmRun ) );
     }
+
+    private static File newDumpFile( File reportsDirectory, int jvmRun )
+    {
+        return new File( reportsDirectory, format( DUMP_FILENAME_FORMATTER, jvmRun ) );
+    }
+
+    private static File newDumpFile( File reportsDirectory )
+    {
+        return new File( reportsDirectory, DUMP_FILENAME );
+    }
 }
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/NativeStdErrStreamConsumer.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/NativeStdErrStreamConsumer.java
index d460583..ace4f8a 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/NativeStdErrStreamConsumer.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/NativeStdErrStreamConsumer.java
@@ -42,6 +42,7 @@ public final class NativeStdErrStreamConsumer
     @Override
     public void consumeLine( String line )
     {
-        InPluginProcessDumpSingleton.getSingleton().dumpText( line, defaultReporterFactory );
+        InPluginProcessDumpSingleton.getSingleton()
+                .dumpStreamText( line, defaultReporterFactory.getReportsDirectory() );
     }
 }
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java
index bbbd9c4..5bce92a 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java
@@ -19,6 +19,9 @@ package org.apache.maven.plugin.surefire.report;
  * under the License.
  */
 
+import org.apache.maven.plugin.surefire.booterclient.output.InPluginProcessDumpSingleton;
+import org.apache.maven.surefire.report.ReportEntry;
+
 import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -27,9 +30,6 @@ import java.io.IOException;
 import java.util.concurrent.atomic.AtomicStampedReference;
 import java.util.concurrent.locks.ReentrantLock;
 
-import org.apache.maven.surefire.booter.DumpErrorSingleton;
-import org.apache.maven.surefire.report.ReportEntry;
-
 import static org.apache.maven.plugin.surefire.report.FileReporter.getReportFile;
 
 /**
@@ -48,6 +48,7 @@ public class ConsoleOutputFileReporter
 
     private final File reportsDirectory;
     private final String reportNameSuffix;
+    private final Integer forkNumber;
 
     private final AtomicStampedReference<FilterOutputStream> fileOutputStream =
             new AtomicStampedReference<FilterOutputStream>( null, OPEN );
@@ -56,10 +57,11 @@ public class ConsoleOutputFileReporter
 
     private volatile String reportEntryName;
 
-    public ConsoleOutputFileReporter( File reportsDirectory, String reportNameSuffix )
+    public ConsoleOutputFileReporter( File reportsDirectory, String reportNameSuffix, Integer forkNumber )
     {
         this.reportsDirectory = reportsDirectory;
         this.reportNameSuffix = reportNameSuffix;
+        this.forkNumber = forkNumber;
     }
 
     @Override
@@ -124,9 +126,7 @@ public class ConsoleOutputFileReporter
         }
         catch ( IOException e )
         {
-            DumpErrorSingleton.getSingleton()
-                    .dumpException( e );
-
+            dumpException( e );
             throw new RuntimeException( e );
         }
         finally
@@ -143,10 +143,9 @@ public class ConsoleOutputFileReporter
             // close null-output.txt report file
             close( true );
         }
-        catch ( IOException ignored )
+        catch ( IOException e )
         {
-            DumpErrorSingleton.getSingleton()
-                    .dumpException( ignored );
+            dumpException( e );
         }
         finally
         {
@@ -162,10 +161,9 @@ public class ConsoleOutputFileReporter
         {
             close( false );
         }
-        catch ( IOException ignored )
+        catch ( IOException e )
         {
-            DumpErrorSingleton.getSingleton()
-                    .dumpException( ignored );
+            dumpException( e );
         }
     }
 
@@ -183,4 +181,18 @@ public class ConsoleOutputFileReporter
             }
         }
     }
+
+    private void dumpException( IOException e )
+    {
+        if ( forkNumber == null )
+        {
+            InPluginProcessDumpSingleton.getSingleton()
+                    .dumpException( e, e.getLocalizedMessage(), reportsDirectory );
+        }
+        else
+        {
+            InPluginProcessDumpSingleton.getSingleton()
+                    .dumpException( e, e.getLocalizedMessage(), reportsDirectory, forkNumber );
+        }
+    }
 }
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java
index 15b4306..1fd2bfe 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java
@@ -63,9 +63,10 @@ import static org.apache.maven.surefire.util.internal.ObjectUtils.useNonNull;
 public class DefaultReporterFactory
     implements ReporterFactory
 {
+    private final Collection<TestSetRunListener> listeners = new ConcurrentLinkedQueue<TestSetRunListener>();
     private final StartupReportConfiguration reportConfiguration;
     private final ConsoleLogger consoleLogger;
-    private final Collection<TestSetRunListener> listeners;
+    private final Integer forkNumber;
 
     private RunStatistics globalStats = new RunStatistics();
 
@@ -80,9 +81,15 @@ public class DefaultReporterFactory
 
     public DefaultReporterFactory( StartupReportConfiguration reportConfiguration, ConsoleLogger consoleLogger )
     {
+        this( reportConfiguration, consoleLogger, null );
+    }
+
+    public DefaultReporterFactory( StartupReportConfiguration reportConfiguration, ConsoleLogger consoleLogger,
+                                   Integer forkNumber )
+    {
         this.reportConfiguration = reportConfiguration;
         this.consoleLogger = consoleLogger;
-        listeners = new ConcurrentLinkedQueue<TestSetRunListener>();
+        this.forkNumber = forkNumber;
     }
 
     @Override
@@ -113,26 +120,24 @@ public class DefaultReporterFactory
 
     private FileReporter createFileReporter()
     {
-        final FileReporter fileReporter = reportConfiguration.instantiateFileReporter();
+        FileReporter fileReporter = reportConfiguration.instantiateFileReporter( forkNumber );
         return useNonNull( fileReporter, NullFileReporter.INSTANCE );
     }
 
     private StatelessXmlReporter createSimpleXMLReporter()
     {
-        final StatelessXmlReporter xmlReporter = reportConfiguration.instantiateStatelessXmlReporter();
+        StatelessXmlReporter xmlReporter = reportConfiguration.instantiateStatelessXmlReporter( forkNumber );
         return useNonNull( xmlReporter, NullStatelessXmlReporter.INSTANCE );
     }
 
     private TestcycleConsoleOutputReceiver createConsoleOutputReceiver()
     {
-        final TestcycleConsoleOutputReceiver consoleOutputReceiver =
-                reportConfiguration.instantiateConsoleOutputFileReporter();
-        return useNonNull( consoleOutputReceiver, NullConsoleOutputReceiver.INSTANCE );
+        return reportConfiguration.instantiateConsoleOutputFileReporter( forkNumber );
     }
 
     private StatisticsReporter createStatisticsReporter()
     {
-        final StatisticsReporter statisticsReporter = reportConfiguration.getStatisticsReporter();
+        StatisticsReporter statisticsReporter = reportConfiguration.getStatisticsReporter();
         return useNonNull( statisticsReporter, NullStatisticsReporter.INSTANCE );
     }
 
@@ -147,10 +152,7 @@ public class DefaultReporterFactory
     {
         for ( DefaultReporterFactory factory : factories )
         {
-            for ( TestSetRunListener listener : factory.listeners )
-            {
-                listeners.add( listener );
-            }
+            listeners.addAll( factory.listeners );
         }
     }
 
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullConsoleOutputReceiver.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullConsoleOutputReceiver.java
deleted file mode 100644
index 327c77d..0000000
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullConsoleOutputReceiver.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.apache.maven.plugin.surefire.report;
-
-/*
- * 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.
- */
-
-import org.apache.maven.surefire.report.ReportEntry;
-
-/**
- * ConsoleReporter doing nothing rather than using null.
- *
- * @author <a href="mailto:britter@apache.org">Benedikt Ritter</a>
- * @since 2.20
- */
-class NullConsoleOutputReceiver
-    implements TestcycleConsoleOutputReceiver
-{
-
-    static final NullConsoleOutputReceiver INSTANCE = new NullConsoleOutputReceiver();
-
-    private NullConsoleOutputReceiver()
-    {
-    }
-
-    @Override
-    public void testSetStarting( ReportEntry reportEntry )
-    {
-    }
-
-    @Override
-    public void testSetCompleted( ReportEntry report )
-    {
-    }
-
-    @Override
-    public void close()
-    {
-    }
-
-    @Override
-    public void writeTestOutput( byte[] buf, int off, int len, boolean stdout )
-    {
-    }
-}
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireHelperTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireHelperTest.java
index c00f7f9..40ab309 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireHelperTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireHelperTest.java
@@ -21,6 +21,7 @@ package org.apache.maven.plugin.surefire;
 
 import org.junit.Test;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -37,15 +38,36 @@ import static org.junit.Assume.assumeTrue;
 public class SurefireHelperTest
 {
     @Test
+    public void shouldReplaceForkNumberPath()
+    {
+        File root = new File( System.getProperty( "user.dir", "" ) );
+        File pathWithPlaceholder = new File( root, "${surefire.forkNumber}" );
+        File changed = SurefireHelper.replaceForkThreadsInPath( pathWithPlaceholder, 5 );
+        assertThat( changed.getPath() )
+                .isEqualTo( new File( root, "5" ).getPath() );
+    }
+
+    @Test
+    public void shouldReplaceLongForkNumberPath()
+    {
+        File root = new File( System.getProperty( "user.dir", "" ) );
+        File subDir = new File( root, "reports-${surefire.forkNumber}" );
+        File pathWithPlaceholder = new File( subDir, "subfolder" );
+        File changed = SurefireHelper.replaceForkThreadsInPath( pathWithPlaceholder, 5 );
+        assertThat( changed.getPath() )
+                .isEqualTo( new File( new File( root, "reports-5" ), "subfolder" ).getPath() );
+    }
+
+    @Test
     public void shouldBeThreeDumpFiles()
     {
         String[] dumps = SurefireHelper.getDumpFilesToPrint();
-        assertThat( dumps ).hasSize( 3 );
+        assertThat( dumps ).hasSize( 4 );
         assertThat( dumps ).doesNotHaveDuplicates();
         List<String> onlyStrings = new ArrayList<String>();
         addAll( onlyStrings, dumps );
         onlyStrings.removeAll( singleton( (String) null ) );
-        assertThat( onlyStrings ).hasSize( 3 );
+        assertThat( onlyStrings ).hasSize( 4 );
     }
 
     @Test
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 26b8be7..4777ce8 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
@@ -220,7 +220,7 @@ public class BooterDeserializerProviderConfigurationTest
             test = "aTest";
         }
         final File propsTest = booterSerializer.serialize( props, booterConfiguration, testProviderConfiguration, test,
-                                                           readTestsFromInStream, 51L );
+                                                           readTestsFromInStream, 51L, 1 );
         BooterDeserializer booterDeserializer = new BooterDeserializer( new FileInputStream( propsTest ) );
         assertEquals( 51L, (Object) booterDeserializer.getPluginPid() );
         return booterDeserializer.deserialize();
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 fc00bcd..7a1a7e2 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
@@ -125,8 +125,8 @@ public class BooterDeserializerStartupConfigurationTest
         PropertiesWrapper props = new PropertiesWrapper( new HashMap<String, String>() );
         BooterSerializer booterSerializer = new BooterSerializer( forkConfiguration );
         String aTest = "aTest";
-        final File propsTest =
-            booterSerializer.serialize( props, getProviderConfiguration(), startupConfiguration, aTest, false, null );
+        File propsTest = booterSerializer.serialize( props, getProviderConfiguration(), startupConfiguration, aTest,
+                false, null, 1 );
         BooterDeserializer booterDeserializer = new BooterDeserializer( new FileInputStream( propsTest ) );
         assertNull( booterDeserializer.getPluginPid() );
         return booterDeserializer.getProviderConfiguration();
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java
index 7d2e6be..0fd275f 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java
@@ -223,7 +223,7 @@ public class ForkingRunListenerTest
         TestSetMockReporterFactory providerReporterFactory = new TestSetMockReporterFactory();
         NullConsoleLogger log = new NullConsoleLogger();
         ForkClient forkStreamClient =
-                new ForkClient( providerReporterFactory, new MockNotifiableTestStream(), log, null );
+                new ForkClient( providerReporterFactory, new MockNotifiableTestStream(), log, null, 1 );
 
         forkStreamClient.consumeMultiLineContent( content.toString( "UTF-8" ) );
 
@@ -248,7 +248,7 @@ public class ForkingRunListenerTest
         TestSetMockReporterFactory providerReporterFactory = new TestSetMockReporterFactory();
         NullConsoleLogger log = new NullConsoleLogger();
         ForkClient forkStreamClient =
-                new ForkClient( providerReporterFactory, new MockNotifiableTestStream(), log, null );
+                new ForkClient( providerReporterFactory, new MockNotifiableTestStream(), log, null, 1 );
 
         forkStreamClient.consumeMultiLineContent( content.toString( "UTF-8" ) );
 
@@ -277,7 +277,7 @@ public class ForkingRunListenerTest
         NotifiableTestStream notifiableTestStream = new MockNotifiableTestStream();
         NullConsoleLogger log = new NullConsoleLogger();
 
-        ForkClient forkStreamClient = new ForkClient( providerReporterFactory, notifiableTestStream, log, null );
+        ForkClient forkStreamClient = new ForkClient( providerReporterFactory, notifiableTestStream, log, null, 1 );
         forkStreamClient.consumeMultiLineContent( content.toString( "UTF-8" ) );
 
         MockReporter reporter = (MockReporter) forkStreamClient.getReporter();
@@ -285,7 +285,7 @@ public class ForkingRunListenerTest
         Assert.assertEquals( expected, reporter.getFirstData() );
         Assert.assertEquals( 1, reporter.getEvents().size() );
 
-        forkStreamClient = new ForkClient( providerReporterFactory, notifiableTestStream, log, null );
+        forkStreamClient = new ForkClient( providerReporterFactory, notifiableTestStream, log, null, 2 );
         forkStreamClient.consumeMultiLineContent( anotherContent.toString( "UTF-8" ) );
         MockReporter reporter2 = (MockReporter) forkStreamClient.getReporter();
         Assert.assertEquals( MockReporter.TEST_SKIPPED, reporter2.getFirstEvent() );
@@ -355,7 +355,7 @@ public class ForkingRunListenerTest
             TestSetMockReporterFactory providerReporterFactory = new TestSetMockReporterFactory();
             NullConsoleLogger log = new NullConsoleLogger();
             final ForkClient forkStreamClient =
-                    new ForkClient( providerReporterFactory, new MockNotifiableTestStream(), log, null );
+                    new ForkClient( providerReporterFactory, new MockNotifiableTestStream(), log, null, 1 );
             forkStreamClient.consumeMultiLineContent( content.toString( ) );
             reporter = (MockReporter) forkStreamClient.getReporter();
         }
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/ConsoleOutputFileReporterTest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/ConsoleOutputFileReporterTest.java
index df011d9..2ee6186 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/ConsoleOutputFileReporterTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/ConsoleOutputFileReporterTest.java
@@ -46,7 +46,7 @@ public class ConsoleOutputFileReporterTest
         //noinspection ResultOfMethodCallIgnored
         reportDir.mkdirs();
         ReportEntry reportEntry = new SimpleReportEntry( getClass().getName(), getClass().getName() );
-        ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter( reportDir, null );
+        ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter( reportDir, null, null );
         reporter.testSetStarting( reportEntry );
         reporter.writeTestOutput( "some text".getBytes( US_ASCII ), 0, 5, true );
         reporter.testSetCompleted( reportEntry );
@@ -74,7 +74,7 @@ public class ConsoleOutputFileReporterTest
         reportDir.mkdirs();
         String suffixText = "sampleSuffixText";
         ReportEntry reportEntry = new SimpleReportEntry( getClass().getName(), getClass().getName() );
-        ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter( reportDir, suffixText );
+        ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter( reportDir, suffixText, null );
         reporter.testSetStarting( reportEntry );
         reporter.writeTestOutput( "some text".getBytes( US_ASCII ), 0, 5, true );
         reporter.testSetCompleted( reportEntry );
@@ -97,7 +97,7 @@ public class ConsoleOutputFileReporterTest
         File reportDir = new File( new File( System.getProperty( "user.dir" ), "target" ), "tmp3" );
         //noinspection ResultOfMethodCallIgnored
         reportDir.mkdirs();
-        ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter( reportDir, null );
+        ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter( reportDir, null, null );
         reporter.writeTestOutput( "some text".getBytes( US_ASCII ), 0, 5, true );
         reporter.testSetCompleted( new SimpleReportEntry( getClass().getName(), getClass().getName() ) );
         reporter.close();
@@ -119,7 +119,7 @@ public class ConsoleOutputFileReporterTest
         File reportDir = new File( new File( System.getProperty( "user.dir" ), "target" ), "tmp4" );
         //noinspection ResultOfMethodCallIgnored
         reportDir.mkdirs();
-        final ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter( reportDir, null );
+        final ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter( reportDir, null, null );
         reporter.testSetStarting( new SimpleReportEntry( getClass().getName(), getClass().getName() ) );
         ExecutorService scheduler = Executors.newFixedThreadPool( 10 );
         final ArrayList<Callable<Void>> jobs = new ArrayList<Callable<Void>>();
diff --git a/maven-surefire-plugin/src/site/fml/faq.fml b/maven-surefire-plugin/src/site/fml/faq.fml
index b73dde6..96053cf 100644
--- a/maven-surefire-plugin/src/site/fml/faq.fml
+++ b/maven-surefire-plugin/src/site/fml/faq.fml
@@ -130,6 +130,7 @@ under the License.
         <![CDATA[ [date]-jvmRun[N].dump]]><br/>
         <![CDATA[ [date]-jvmRun[N].dumpstream]]><br/>
         <![CDATA[ [date].dumpstream]]><br/>
+        <![CDATA[ [date].dump]]><br/>
         </code>
 
         Forked JVM process and plugin process communicate via std/out. If this channel is corrupted, for a whatever
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/DumpErrorSingleton.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/DumpErrorSingleton.java
index e287f05..97e37d0 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/DumpErrorSingleton.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/DumpErrorSingleton.java
@@ -19,7 +19,6 @@ package org.apache.maven.surefire.booter;
  * under the License.
  */
 
-import org.apache.maven.surefire.report.ReporterConfiguration;
 import org.apache.maven.surefire.util.internal.DumpFileUtils;
 
 import java.io.File;
@@ -51,10 +50,10 @@ public final class DumpErrorSingleton
         return SINGLETON;
     }
 
-    public synchronized void init( String dumpFileName, ReporterConfiguration configuration )
+    public synchronized void init( File reportsDir, String dumpFileName )
     {
-        dumpFile = createDumpFile( dumpFileName, configuration );
-        dumpStreamFile = createDumpStreamFile( dumpFileName, configuration );
+        dumpFile = createDumpFile( reportsDir, dumpFileName );
+        dumpStreamFile = createDumpStreamFile( reportsDir, dumpFileName );
     }
 
     public synchronized void dumpException( Throwable t, String msg )
@@ -87,13 +86,13 @@ public final class DumpErrorSingleton
         DumpFileUtils.dumpText( msg == null ? "null" : msg, dumpStreamFile );
     }
 
-    private File createDumpFile( String dumpFileName, ReporterConfiguration configuration )
+    private File createDumpFile( File reportsDir, String dumpFileName )
     {
-        return newDumpFile( dumpFileName + DUMP_FILE_EXT, configuration );
+        return newDumpFile( reportsDir, dumpFileName + DUMP_FILE_EXT );
     }
 
-    private File createDumpStreamFile( String dumpFileName, ReporterConfiguration configuration )
+    private File createDumpStreamFile( File reportsDir, String dumpFileName )
     {
-        return newDumpFile( dumpFileName + DUMPSTREAM_FILE_EXT, configuration );
+        return newDumpFile( reportsDir, dumpFileName + DUMPSTREAM_FILE_EXT );
     }
 }
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/DumpFileUtils.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/DumpFileUtils.java
index c83ae1f..cc2d04a 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/DumpFileUtils.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/DumpFileUtils.java
@@ -19,8 +19,6 @@ package org.apache.maven.surefire.util.internal;
  * under the License.
  */
 
-import org.apache.maven.surefire.report.ReporterConfiguration;
-
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -49,12 +47,12 @@ public final class DumpFileUtils
     /**
      * New dump file. Synchronized object appears in main memory and perfectly visible in other threads.
      *
+     * @param reportsDir    only report directory
      * @param dumpFileName    dump file name
-     * @param configuration    only report directory
      */
-    public static synchronized File newDumpFile( String dumpFileName, ReporterConfiguration configuration )
+    public static synchronized File newDumpFile( File reportsDir, String dumpFileName )
     {
-        return new File( configuration.getReportsDirectory(), dumpFileName );
+        return new File( reportsDir, dumpFileName );
     }
 
     public static void dumpException( Throwable t, File dumpFile )
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 bbb3294..03ef036 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
@@ -95,7 +95,8 @@ public final class ForkedBooter
         setSystemProperties( new File( tmpDir, effectiveSystemPropertiesFileName ) );
 
         providerConfiguration = booterDeserializer.deserialize();
-        DumpErrorSingleton.getSingleton().init( dumpFileName, providerConfiguration.getReporterConfiguration() );
+        DumpErrorSingleton.getSingleton()
+                .init( providerConfiguration.getReporterConfiguration().getReportsDirectory(), dumpFileName );
 
         startupConfiguration = booterDeserializer.getProviderConfiguration();
         systemExitTimeoutInSeconds = providerConfiguration.systemExitTimeout( DEFAULT_SYSTEM_EXIT_TIMEOUT_IN_SECONDS );
diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/TestFile.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/TestFile.java
index f68eb35..abf17cb 100644
--- a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/TestFile.java
+++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/TestFile.java
@@ -31,8 +31,10 @@ import java.util.List;
 import org.apache.commons.io.FileUtils;
 
 import junit.framework.Assert;
+import org.hamcrest.Matcher;
 
 import static junit.framework.Assert.assertTrue;
+import static org.hamcrest.Matchers.containsString;
 
 /**
  * @author Kristian Rosenvold
@@ -129,12 +131,12 @@ public class TestFile
         return file.isFile();
     }
 
-    public TestFile assertContainsText( String text )
+    public TestFile assertContainsText( Matcher<String> matcher )
     {
         final List<String> list = surefireVerifier.loadFile( file, encoding );
         for ( String line : list )
         {
-            if ( line.contains( text ) )
+            if ( matcher.matches( line ) )
             {
                 return this;
             }
@@ -143,6 +145,11 @@ public class TestFile
         return null;
     }
 
+    public TestFile assertContainsText( String text )
+    {
+        return assertContainsText( containsString( text ) );
+    }
+
     public URI toURI()
     {
         return file.toURI();
diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1535TestNGParallelSuitesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1535TestNGParallelSuitesIT.java
index a3ffd5b..0c8061d 100644
--- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1535TestNGParallelSuitesIT.java
+++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1535TestNGParallelSuitesIT.java
@@ -19,20 +19,125 @@ package org.apache.maven.surefire.its.jiras;
  * under the License.
  */
 
+import org.apache.maven.it.VerificationException;
+import org.apache.maven.surefire.its.fixture.OutputValidator;
 import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
+import org.apache.maven.surefire.its.fixture.SurefireLauncher;
+import org.apache.maven.surefire.its.fixture.TestFile;
 import org.junit.Test;
 
+import java.nio.charset.Charset;
+
+import static org.hamcrest.CoreMatchers.anyOf;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+
 public class Surefire1535TestNGParallelSuitesIT
         extends SurefireJUnit4IntegrationTestCase
 {
+    private static final Charset UTF8 = Charset.forName( "UTF-8" );
+
+    @Test
+    public void forks2() throws VerificationException
+    {
+        OutputValidator validator = unpack()
+                .activateProfile( "forked-reports-directory" )
+                .forkCount( 2 )
+                .executeTest();
+
+        TestFile testFile = validator.getSurefireReportsFile( "../surefire-reports-1/TEST-TestSuite.xml", UTF8 );
+        testFile.assertFileExists();
+        testFile.assertContainsText( "<testcase name=\"test\" classname=\"it.ParallelTest" );
+
+        testFile = validator.getSurefireReportsFile( "../surefire-reports-2/TEST-TestSuite.xml", UTF8 );
+        testFile.assertFileExists();
+        testFile.assertContainsText( "<testcase name=\"test\" classname=\"it.ParallelTest" );
+
+        validator.assertThatLogLine( containsString( "Tests run: 2, Failures: 0, Errors: 0, Skipped: 0" ), is( 1 ) )
+                .assertThatLogLine( containsString( "Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, " ), is( 2 ) )
+                .assertThatLogLine( containsString( "Suite1.xml" ), is( 1 ) )
+                .assertThatLogLine( containsString( "Suite2.xml" ), is( 1 ) )
+                .assertThatLogLine( containsString( "test 1" ), is( 1 ) )
+                .assertThatLogLine( containsString( "test 2" ), is( 1 ) )
+                .assertThatLogLine( containsString( "Running TestSuite" ), is( 2 ) );
+    }
+
     @Test
-    public void testParallelSuites()
+    public void forks2Redirected() throws VerificationException
+    {
+        OutputValidator validator = unpack()
+                .activateProfile( "forked-reports-directory" )
+                .forkCount( 2 )
+                .redirectToFile( true )
+                .executeTest();
+
+        TestFile testFile = validator.getSurefireReportsFile( "../surefire-reports-1/TEST-TestSuite.xml", UTF8 );
+        testFile.assertFileExists();
+        testFile.assertContainsText( "<testcase name=\"test\" classname=\"it.ParallelTest" );
+
+        testFile = validator.getSurefireReportsFile( "../surefire-reports-2/TEST-TestSuite.xml", UTF8 );
+        testFile.assertFileExists();
+        testFile.assertContainsText( "<testcase name=\"test\" classname=\"it.ParallelTest" );
+
+        validator.assertThatLogLine( containsString( "Tests run: 2, Failures: 0, Errors: 0, Skipped: 0" ), is( 1 ) )
+                .assertThatLogLine( containsString( "Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, " ), is( 2 ) )
+                .assertThatLogLine( containsString( "Running TestSuite" ), is( 2 ) );
+
+        TestFile outFile = validator.getSurefireReportsFile( "../surefire-reports-1/TestSuite-output.txt" );
+        outFile.assertFileExists();
+        outFile.assertContainsText( anyOf( containsString( "Suite1.xml" ), containsString( "Suite2.xml" ) ) );
+        outFile.assertContainsText( anyOf( containsString( "test 1" ), containsString( "test 2" ) ) );
+
+        outFile = validator.getSurefireReportsFile( "../surefire-reports-2/TestSuite-output.txt" );
+        outFile.assertFileExists();
+        outFile.assertContainsText( anyOf( containsString( "Suite1.xml" ), containsString( "Suite2.xml" ) ) );
+        outFile.assertContainsText( anyOf( containsString( "test 1" ), containsString( "test 2" ) ) );
+    }
+
+    @Test
+    public void forks0() throws VerificationException
+    {
+        OutputValidator validator = unpack()
+                .forkCount( 0 )
+                .executeTest();
+
+        TestFile testFile = validator.getSurefireReportsFile( "TEST-TestSuite.xml" );
+        testFile.assertFileExists();
+        testFile.assertContainsText( "<testcase name=\"test\" classname=\"it.ParallelTest1\"" );
+        testFile.assertContainsText( "<testcase name=\"test\" classname=\"it.ParallelTest2\"" );
+
+        validator.assertThatLogLine( containsString( "Suite1.xml" ), is( 1 ) )
+                .assertThatLogLine( containsString( "Suite2.xml" ), is( 1 ) )
+                .assertThatLogLine( containsString( "test 1" ), is( 1 ) )
+                .assertThatLogLine( containsString( "test 2" ), is( 1 ) )
+                .assertThatLogLine( containsString( "Running TestSuite" ), is( 1 ) );
+    }
+
+    @Test
+    public void forks0Redirected() throws VerificationException
+    {
+        OutputValidator validator = unpack()
+                .forkCount( 0 )
+                .redirectToFile( true )
+                .executeTest();
+
+        TestFile testFile = validator.getSurefireReportsXmlFile( "TEST-TestSuite.xml" );
+        testFile.assertFileExists();
+        testFile.assertContainsText( "<testcase name=\"test\" classname=\"it.ParallelTest1\"" );
+        testFile.assertContainsText( "<testcase name=\"test\" classname=\"it.ParallelTest2\"" );
+
+        validator.assertThatLogLine( containsString( "Running TestSuite" ), is( 1 ) );
+
+        TestFile outFile = validator.getSurefireReportsFile( "TestSuite-output.txt" );
+        outFile.assertFileExists();
+        outFile.assertContainsText( "Suite1.xml" );
+        outFile.assertContainsText( "Suite1.xml" );
+        outFile.assertContainsText( "test 1" );
+        outFile.assertContainsText( "test 2" );
+    }
+
+    private SurefireLauncher unpack()
     {
-        unpack("/surefire-1535-parallel-testng")
-                .maven()
-                .sysProp( "testNgVersion", "5.7" )
-                .sysProp( "testNgClassifier", "jdk15" )
-                .executeTest()
-                .assertTestSuiteResults( 2, 0, 0, 0 );
+        return unpack("/surefire-1535-parallel-testng");
     }
 }
diff --git a/surefire-its/src/test/resources/surefire-1535-parallel-testng/pom.xml b/surefire-its/src/test/resources/surefire-1535-parallel-testng/pom.xml
index 942ddb6..c7aba88 100644
--- a/surefire-its/src/test/resources/surefire-1535-parallel-testng/pom.xml
+++ b/surefire-its/src/test/resources/surefire-1535-parallel-testng/pom.xml
@@ -33,33 +33,30 @@
         <maven.compiler.target>1.6</maven.compiler.target>
     </properties>
 
+    <dependencies>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>5.7</version>
+            <classifier>jdk15</classifier>
+        </dependency>
+    </dependencies>
+
     <profiles>
         <profile>
-            <id>testng-old</id>
-            <activation>
-                <property><name>testNgClassifier</name></property>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>org.testng</groupId>
-                    <artifactId>testng</artifactId>
-                    <version>${testNgVersion}</version>
-                    <classifier>${testNgClassifier}</classifier>
-                </dependency>
-            </dependencies>
-        </profile>
-        <profile>
-            <id>testng-new</id>
-            <activation>
-                <property><name>!testNgClassifier</name></property>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>org.testng</groupId>
-                    <artifactId>testng</artifactId>
-                    <version>${testNgVersion}</version>
-                </dependency>
-            </dependencies>
+            <id>forked-reports-directory</id>
+            <build>
+                <pluginManagement>
+                    <plugins>
+                        <plugin>
+                            <artifactId>maven-surefire-plugin</artifactId>
+                            <configuration>
+                                <reportsDirectory>target/surefire-reports-${surefire.forkNumber}</reportsDirectory>
+                            </configuration>
+                        </plugin>
+                    </plugins>
+                </pluginManagement>
+            </build>
         </profile>
     </profiles>
 
@@ -69,7 +66,6 @@
                 <artifactId>maven-surefire-plugin</artifactId>
                 <version>${surefire.version}</version>
                 <configuration>
-                    <forkCount>2</forkCount>
                     <reuseForks>false</reuseForks>
                     <suiteXmlFiles>
                         <suiteXmlFile>src/test/resources/Suite1.xml</suiteXmlFile>
diff --git a/surefire-its/src/test/resources/surefire-1535-parallel-testng/src/test/java/it/ParallelTest1.java b/surefire-its/src/test/resources/surefire-1535-parallel-testng/src/test/java/it/ParallelTest1.java
index 177c420..0590851 100644
--- a/surefire-its/src/test/resources/surefire-1535-parallel-testng/src/test/java/it/ParallelTest1.java
+++ b/surefire-its/src/test/resources/surefire-1535-parallel-testng/src/test/java/it/ParallelTest1.java
@@ -29,6 +29,7 @@ public class ParallelTest1
 {
     public void test() throws Exception
     {
+        System.out.println( "test 1" );
         TimeUnit.SECONDS.sleep( 1L );
     }
 }
diff --git a/surefire-its/src/test/resources/surefire-1535-parallel-testng/src/test/java/it/ParallelTest2.java b/surefire-its/src/test/resources/surefire-1535-parallel-testng/src/test/java/it/ParallelTest2.java
index d56fa62..8467ea7 100644
--- a/surefire-its/src/test/resources/surefire-1535-parallel-testng/src/test/java/it/ParallelTest2.java
+++ b/surefire-its/src/test/resources/surefire-1535-parallel-testng/src/test/java/it/ParallelTest2.java
@@ -29,6 +29,7 @@ public class ParallelTest2
 {
     public void test() throws Exception
     {
+        System.out.println( "test 2" );
         TimeUnit.SECONDS.sleep( 1L );
     }
 }