maven-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tibordig...@apache.org
Subject maven-surefire git commit: [SUREFIRE-1356] ForkClient should distinguish between internal and stream errors
Date Wed, 05 Apr 2017 21:39:14 GMT
Repository: maven-surefire
Updated Branches:
  refs/heads/master a1d224a8e -> bdde67c5c


[SUREFIRE-1356] ForkClient should distinguish between internal and stream errors


Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/bdde67c5
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/bdde67c5
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/bdde67c5

Branch: refs/heads/master
Commit: bdde67c5c26691fc1899931c20a6d25b38bd9fbf
Parents: a1d224a
Author: Tibor17 <tibor17@lycos.com>
Authored: Wed Apr 5 23:38:58 2017 +0200
Committer: Tibor17 <tibor17@lycos.com>
Committed: Wed Apr 5 23:38:58 2017 +0200

----------------------------------------------------------------------
 .../maven/plugin/surefire/SurefireHelper.java   |  29 +-
 .../surefire/booterclient/ForkStarter.java      |  21 +-
 .../booterclient/output/ForkClient.java         | 276 +++++++++++--------
 .../output/InPluginProcessDumpSingleton.java    |  28 +-
 .../plugin/surefire/SurefireHelperTest.java     |  65 +++++
 .../apache/maven/surefire/JUnit4SuiteTest.java  |   4 +-
 .../surefire/booter/DumpErrorSingleton.java     |   4 +-
 7 files changed, 292 insertions(+), 135 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/bdde67c5/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireHelper.java
----------------------------------------------------------------------
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 bab37c7..8bdf75e 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
@@ -27,6 +27,7 @@ import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
 import org.apache.maven.surefire.cli.CommandLineOption;
 import org.apache.maven.surefire.suite.RunResult;
 import org.apache.maven.surefire.testset.TestSetFailedException;
+import org.apache.maven.surefire.util.internal.DumpFileUtils;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -35,6 +36,8 @@ import java.util.Collection;
 import java.util.List;
 
 import static java.util.Collections.unmodifiableList;
+import static org.apache.maven.surefire.booter.DumpErrorSingleton.DUMPSTREAM_FILE_EXT;
+import static org.apache.maven.surefire.booter.DumpErrorSingleton.DUMP_FILE_EXT;
 import static org.apache.maven.surefire.cli.CommandLineOption.LOGGING_LEVEL_DEBUG;
 import static org.apache.maven.surefire.cli.CommandLineOption.LOGGING_LEVEL_ERROR;
 import static org.apache.maven.surefire.cli.CommandLineOption.LOGGING_LEVEL_INFO;
@@ -46,6 +49,18 @@ import static org.apache.maven.surefire.cli.CommandLineOption.SHOW_ERRORS;
  */
 public final class SurefireHelper
 {
+    private static final String DUMP_FILE_DATE = DumpFileUtils.newFormattedDateFileName();
+
+    public static final String DUMP_FILE_PREFIX = DUMP_FILE_DATE + "-jvmRun";
+
+    public static final String DUMPSTREAM_FILENAME_FORMATTER = DUMP_FILE_PREFIX + "%d" +
DUMPSTREAM_FILE_EXT;
+
+    private static final String[] DUMP_FILES_PRINT =
+            {
+                    "[date]-jvmRun[N]" + DUMP_FILE_EXT,
+                    "[date]" + DUMPSTREAM_FILE_EXT,
+                    "[date]-jvmRun[N]" + DUMPSTREAM_FILE_EXT
+            };
 
     /**
      * Do not instantiate.
@@ -55,6 +70,11 @@ public final class SurefireHelper
         throw new IllegalAccessError( "Utility class" );
     }
 
+    public static String[] getDumpFilesToPrint()
+    {
+        return DUMP_FILES_PRINT.clone();
+    }
+
     public static void reportExecution( SurefireReportParameters reportParameters, RunResult
result,
                                         PluginConsoleLogger log, Exception firstForkException
)
         throws MojoFailureException, MojoExecutionException
@@ -201,8 +221,13 @@ public final class SurefireHelper
                     .append( reportParameters.getReportsDirectory() )
                     .append( " for the individual test results." )
                     .append( '\n' )
-                    .append( "Please refer to dump files (if any exist) "
-                                     + "[date]-jvmRun[N].dump, [date].dumpstream and [date]-jvmRun[N].dumpstream"
);
+                    .append( "Please refer to dump files (if any exist) " )
+                    .append( DUMP_FILES_PRINT[0] )
+                    .append( ", " )
+                    .append( DUMP_FILES_PRINT[1] )
+                    .append( " and " )
+                    .append( DUMP_FILES_PRINT[2] )
+                    .append( "." );
         }
 
         if ( firstForkException != null && firstForkException.getLocalizedMessage()
!= null )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/bdde67c5/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
index 5360b4c..b3a3f91 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
@@ -50,7 +50,6 @@ import org.apache.maven.surefire.report.StackTraceWriter;
 import org.apache.maven.surefire.suite.RunResult;
 import org.apache.maven.surefire.testset.TestRequest;
 import org.apache.maven.surefire.util.DefaultScanResult;
-import org.apache.maven.surefire.util.internal.DumpFileUtils;
 
 import java.io.Closeable;
 import java.io.File;
@@ -82,6 +81,7 @@ import static java.util.concurrent.Executors.newScheduledThreadPool;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.apache.maven.plugin.surefire.AbstractSurefireMojo.createCopyAndReplaceForkNumPlaceholder;
+import static org.apache.maven.plugin.surefire.SurefireHelper.DUMP_FILE_PREFIX;
 import static org.apache.maven.plugin.surefire.booterclient.ForkNumberBucket.drawNumber;
 import static org.apache.maven.plugin.surefire.booterclient.ForkNumberBucket.returnNumber;
 import static org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestLessInputStream
@@ -130,8 +130,6 @@ public class ForkStarter
 
     private static final AtomicInteger SYSTEM_PROPERTIES_FILE_COUNTER = new AtomicInteger();
 
-    private static final String DUMP_FILE_PREFIX = DumpFileUtils.newFormattedDateFileName()
+ "-jvmRun";
-
     private final ScheduledExecutorService pingThreadScheduler = createPingScheduler();
 
     private final ScheduledExecutorService timeoutCheckScheduler;
@@ -160,12 +158,15 @@ public class ForkStarter
     private final class CloseableCloser
         implements Runnable, Closeable
     {
+        private final int jvmRun;
+
         private final Queue<Closeable> testProvidingInputStream;
 
         private final Thread inputStreamCloserHook;
 
-        public CloseableCloser( Closeable... testProvidingInputStream )
+        public CloseableCloser( int jvmRun, Closeable... testProvidingInputStream )
         {
+            this.jvmRun = jvmRun;
             this.testProvidingInputStream = new ConcurrentLinkedQueue<Closeable>();
             addAll( this.testProvidingInputStream, testProvidingInputStream );
             if ( this.testProvidingInputStream.isEmpty() )
@@ -196,9 +197,10 @@ public class ForkStarter
                     // this exception happened => warning on console. The user would see
hint to check dump file only
                     // 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();
-                    log.warning( msg );
-                    InPluginProcessDumpSingleton.getSingleton().dumpException( e, msg, defaultReporterFactory
);
+                    String msg = "ForkStarter IOException: " + e.getLocalizedMessage() +
".";
+                    File dump = InPluginProcessDumpSingleton.getSingleton()
+                                        .dumpException( e, msg, defaultReporterFactory, jvmRun
);
+                    log.warning( msg + " See the dump file " + dump.getAbsolutePath() );
                 }
             }
         }
@@ -525,6 +527,7 @@ public class ForkStarter
         throws SurefireBooterForkException
     {
         int forkNumber = drawNumber();
+        forkClient.setForkNumber( forkNumber );
         try
         {
             return fork( testSet, providerProperties, forkClient, effectiveSystemProperties,
forkNumber,
@@ -600,8 +603,8 @@ public class ForkStarter
         }
 
         final ThreadedStreamConsumer threadedStreamConsumer = new ThreadedStreamConsumer(
forkClient );
-        final CloseableCloser closer =
-                new CloseableCloser( threadedStreamConsumer, requireNonNull( testProvidingInputStream,
"null param" ) );
+        final CloseableCloser closer = new CloseableCloser( forkNumber, threadedStreamConsumer,
+                                                            requireNonNull( testProvidingInputStream,
"null param" ) );
 
         log.debug( "Forking command line: " + cli );
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/bdde67c5/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
index 32fcea4..583460f 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
@@ -29,10 +29,10 @@ import org.apache.maven.surefire.report.RunListener;
 import org.apache.maven.surefire.report.StackTraceWriter;
 
 import java.io.BufferedReader;
+import java.io.File;
 import java.io.IOException;
 import java.io.StringReader;
 import java.nio.ByteBuffer;
-import java.util.NoSuchElementException;
 import java.util.Properties;
 import java.util.Queue;
 import java.util.Set;
@@ -102,6 +102,11 @@ public class ForkClient
 
     private volatile StackTraceWriter errorInFork;
 
+    private volatile int forkNumber;
+
+    // prevents from printing same warning
+    private boolean printedErrorStream;
+
     public ForkClient( DefaultReporterFactory defaultReporterFactory, Properties testVmSystemProperties,
                        NotifiableTestStream notifiableTestStream, ConsoleLogger log )
     {
@@ -177,134 +182,130 @@ public class ForkClient
         return testSetReporter;
     }
 
-    private void processLine( String s )
+    private void processLine( String event )
     {
+        final OperationalData op;
         try
         {
-            final byte operationId = (byte) s.charAt( 0 );
-            int comma = s.indexOf( ",", 3 );
-            if ( comma < 0 )
-            {
-                log.warning( s );
-                return;
-            }
-            int rest = s.indexOf( ",", comma );
-            final String remaining = s.substring( rest + 1 );
-
-            switch ( operationId )
-            {
-                case BOOTERCODE_TESTSET_STARTING:
-                    getTestSetReporter().testSetStarting( createReportEntry( remaining )
);
-                    setCurrentStartTime();
-                    break;
-                case BOOTERCODE_TESTSET_COMPLETED:
-                    testsInProgress.clear();
-                    
-                    getTestSetReporter().testSetCompleted( createReportEntry( remaining )
);
-                    break;
-                case BOOTERCODE_TEST_STARTING:
-                    ReportEntry reportEntry = createReportEntry( remaining );
-                    testsInProgress.offer( reportEntry.getSourceName() );
-                    
-                    getTestSetReporter().testStarting( createReportEntry( remaining ) );
-                    break;
-                case BOOTERCODE_TEST_SUCCEEDED:
-                    reportEntry = createReportEntry( remaining );
-                    testsInProgress.remove( reportEntry.getSourceName() );
-                    
-                    getTestSetReporter().testSucceeded( createReportEntry( remaining ) );
-                    break;
-                case BOOTERCODE_TEST_FAILED:
-                    reportEntry = createReportEntry( remaining );
-                    testsInProgress.remove( reportEntry.getSourceName() );
-                    
-                    getTestSetReporter().testFailed( createReportEntry( remaining ) );
-                    break;
-                case BOOTERCODE_TEST_SKIPPED:
-                    reportEntry = createReportEntry( remaining );
-                    testsInProgress.remove( reportEntry.getSourceName() );
-                    
-                    getTestSetReporter().testSkipped( createReportEntry( remaining ) );
-                    break;
-                case BOOTERCODE_TEST_ERROR:
-                    reportEntry = createReportEntry( remaining );
-                    testsInProgress.remove( reportEntry.getSourceName() );
-                    
-                    getTestSetReporter().testError( createReportEntry( remaining ) );
-                    break;
-                case BOOTERCODE_TEST_ASSUMPTIONFAILURE:
-                    reportEntry = createReportEntry( remaining );
-                    testsInProgress.remove( reportEntry.getSourceName() );
-                    
-                    getTestSetReporter().testAssumptionFailure( createReportEntry( remaining
) );
-                    break;
-                case BOOTERCODE_SYSPROPS:
-                    int keyEnd = remaining.indexOf( "," );
-                    StringBuilder key = new StringBuilder();
-                    StringBuilder value = new StringBuilder();
-                    unescapeString( key, remaining.substring( 0, keyEnd ) );
-                    unescapeString( value, remaining.substring( keyEnd + 1 ) );
-                    synchronized ( testVmSystemProperties )
-                    {
-                        testVmSystemProperties.put( key.toString(), value.toString() );
-                    }
-                    break;
-                case BOOTERCODE_STDOUT:
-                    writeTestOutput( remaining, true );
-                    break;
-                case BOOTERCODE_STDERR:
-                    writeTestOutput( remaining, false );
-                    break;
-                case BOOTERCODE_CONSOLE:
-                    getOrCreateConsoleLogger()
-                            .info( createConsoleMessage( remaining ) );
-                    break;
-                case BOOTERCODE_NEXT_TEST:
-                    notifiableTestStream.provideNewTest();
-                    break;
-                case BOOTERCODE_ERROR:
-                    errorInFork = deserializeStackTraceWriter( new StringTokenizer( remaining,
"," ) );
-                    break;
-                case BOOTERCODE_BYE:
-                    saidGoodBye = true;
-                    notifiableTestStream.acknowledgeByeEventReceived();
-                    break;
-                case BOOTERCODE_STOP_ON_NEXT_TEST:
-                    stopOnNextTest();
-                    break;
-                case BOOTERCODE_DEBUG:
-                    getOrCreateConsoleLogger()
-                            .debug( createConsoleMessage( remaining ) );
-                    break;
-                case BOOTERCODE_WARNING:
-                    getOrCreateConsoleLogger()
-                            .warning( createConsoleMessage( remaining ) );
-                    break;
-                default:
-                    InPluginProcessDumpSingleton.getSingleton().dumpText( s, defaultReporterFactory
);
-            }
-        }
-        catch ( NumberFormatException e )
-        {
-            // SUREFIRE-859
-            InPluginProcessDumpSingleton.getSingleton().dumpException( e, s, defaultReporterFactory
);
+            op = new OperationalData( event );
         }
-        catch ( NoSuchElementException e )
+        catch ( RuntimeException e )
         {
-            // SUREFIRE-859
-            InPluginProcessDumpSingleton.getSingleton().dumpException( e, s, defaultReporterFactory
);
+            logStreamWarning( e, event );
+            return;
         }
-        catch ( IndexOutOfBoundsException e )
+        final String remaining = op.getData();
+        switch ( op.getOperationId() )
         {
-            // native stream sent a text e.g. GC verbose
-            InPluginProcessDumpSingleton.getSingleton().dumpException( e, s, defaultReporterFactory
);
-            throw e;
+            case BOOTERCODE_TESTSET_STARTING:
+                getTestSetReporter().testSetStarting( createReportEntry( remaining ) );
+                setCurrentStartTime();
+                break;
+            case BOOTERCODE_TESTSET_COMPLETED:
+                testsInProgress.clear();
+
+                getTestSetReporter().testSetCompleted( createReportEntry( remaining ) );
+                break;
+            case BOOTERCODE_TEST_STARTING:
+                ReportEntry reportEntry = createReportEntry( remaining );
+                testsInProgress.offer( reportEntry.getSourceName() );
+
+                getTestSetReporter().testStarting( createReportEntry( remaining ) );
+                break;
+            case BOOTERCODE_TEST_SUCCEEDED:
+                reportEntry = createReportEntry( remaining );
+                testsInProgress.remove( reportEntry.getSourceName() );
+
+                getTestSetReporter().testSucceeded( createReportEntry( remaining ) );
+                break;
+            case BOOTERCODE_TEST_FAILED:
+                reportEntry = createReportEntry( remaining );
+                testsInProgress.remove( reportEntry.getSourceName() );
+
+                getTestSetReporter().testFailed( createReportEntry( remaining ) );
+                break;
+            case BOOTERCODE_TEST_SKIPPED:
+                reportEntry = createReportEntry( remaining );
+                testsInProgress.remove( reportEntry.getSourceName() );
+
+                getTestSetReporter().testSkipped( createReportEntry( remaining ) );
+                break;
+            case BOOTERCODE_TEST_ERROR:
+                reportEntry = createReportEntry( remaining );
+                testsInProgress.remove( reportEntry.getSourceName() );
+
+                getTestSetReporter().testError( createReportEntry( remaining ) );
+                break;
+            case BOOTERCODE_TEST_ASSUMPTIONFAILURE:
+                reportEntry = createReportEntry( remaining );
+                testsInProgress.remove( reportEntry.getSourceName() );
+
+                getTestSetReporter().testAssumptionFailure( createReportEntry( remaining
) );
+                break;
+            case BOOTERCODE_SYSPROPS:
+                int keyEnd = remaining.indexOf( "," );
+                StringBuilder key = new StringBuilder();
+                StringBuilder value = new StringBuilder();
+                unescapeString( key, remaining.substring( 0, keyEnd ) );
+                unescapeString( value, remaining.substring( keyEnd + 1 ) );
+                synchronized ( testVmSystemProperties )
+                {
+                    testVmSystemProperties.put( key.toString(), value.toString() );
+                }
+                break;
+            case BOOTERCODE_STDOUT:
+                writeTestOutput( remaining, true );
+                break;
+            case BOOTERCODE_STDERR:
+                writeTestOutput( remaining, false );
+                break;
+            case BOOTERCODE_CONSOLE:
+                getOrCreateConsoleLogger()
+                        .info( createConsoleMessage( remaining ) );
+                break;
+            case BOOTERCODE_NEXT_TEST:
+                notifiableTestStream.provideNewTest();
+                break;
+            case BOOTERCODE_ERROR:
+                errorInFork = deserializeStackTraceWriter( new StringTokenizer( remaining,
"," ) );
+                break;
+            case BOOTERCODE_BYE:
+                saidGoodBye = true;
+                notifiableTestStream.acknowledgeByeEventReceived();
+                break;
+            case BOOTERCODE_STOP_ON_NEXT_TEST:
+                stopOnNextTest();
+                break;
+            case BOOTERCODE_DEBUG:
+                getOrCreateConsoleLogger()
+                        .debug( createConsoleMessage( remaining ) );
+                break;
+            case BOOTERCODE_WARNING:
+                getOrCreateConsoleLogger()
+                        .warning( createConsoleMessage( remaining ) );
+                break;
+            default:
+                logStreamWarning( event );
         }
-        catch ( RuntimeException e )
+    }
+
+    private void logStreamWarning( String event )
+    {
+        logStreamWarning( null, event );
+    }
+
+    private void logStreamWarning( Throwable e, String event )
+    {
+        final String msg = "Corrupted stdin stream in forked JVM " + forkNumber + ".";
+        final InPluginProcessDumpSingleton util = InPluginProcessDumpSingleton.getSingleton();
+        final File dump =
+                e == null ? util.dumpText( msg + " Stream '" + event + "'.", defaultReporterFactory,
forkNumber )
+                        : util.dumpException( e, msg + " Stream '" + event + "'.", defaultReporterFactory,
forkNumber );
+
+        if ( !printedErrorStream )
         {
-            // e.g. ReporterException
-            InPluginProcessDumpSingleton.getSingleton().dumpException( e, s, defaultReporterFactory
);
-            throw e;
+            printedErrorStream = true;
+            log.warning( msg + " See the dump file " + dump.getAbsolutePath() );
         }
     }
 
@@ -438,4 +439,39 @@ 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;
+        private final String data;
+
+        OperationalData( String event )
+        {
+            operationId = (byte) event.charAt( 0 );
+            int comma = event.indexOf( ",", 3 );
+            if ( comma < 0 )
+            {
+                throw new IllegalArgumentException( "Stream stdin corrupted. Expected comma
after third character "
+                                                            + "in command '" + event + "'."
);
+            }
+            int rest = event.indexOf( ",", comma );
+            data = event.substring( rest + 1 );
+        }
+
+        byte getOperationId()
+        {
+            return operationId;
+        }
+
+        String getData()
+        {
+            return data;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/bdde67c5/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/InPluginProcessDumpSingleton.java
----------------------------------------------------------------------
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 6580c43..0676b52 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
@@ -21,8 +21,13 @@ package org.apache.maven.plugin.surefire.booterclient.output;
 
 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.DUMPSTREAM_FILENAME_FORMATTER;
+import static org.apache.maven.surefire.booter.DumpErrorSingleton.DUMPSTREAM_FILE_EXT;
+
 /**
  * Reports errors to dump file.
  * Used only within java process of the plugin itself and not the forked JVM.
@@ -42,6 +47,14 @@ public final class InPluginProcessDumpSingleton
         return SINGLETON;
     }
 
+    public synchronized File dumpException( Throwable t, String msg, DefaultReporterFactory
defaultReporterFactory,
+                                            int jvmRun )
+    {
+        File dump = newDumpFile( defaultReporterFactory, jvmRun );
+        DumpFileUtils.dumpException( t, msg == null ? "null" : msg, dump );
+        return dump;
+    }
+
     public synchronized void dumpException( Throwable t, String msg, DefaultReporterFactory
defaultReporterFactory )
     {
         DumpFileUtils.dumpException( t, msg == null ? "null" : msg, newDumpFile( defaultReporterFactory
) );
@@ -52,6 +65,13 @@ public final class InPluginProcessDumpSingleton
         DumpFileUtils.dumpException( t, newDumpFile( defaultReporterFactory ) );
     }
 
+    public synchronized File dumpText( String msg, DefaultReporterFactory defaultReporterFactory,
int jvmRun )
+    {
+        File dump = newDumpFile( defaultReporterFactory, jvmRun );
+        DumpFileUtils.dumpText( msg == null ? "null" : msg, dump );
+        return dump;
+    }
+
     public synchronized void dumpText( String msg, DefaultReporterFactory defaultReporterFactory
)
     {
         DumpFileUtils.dumpText( msg == null ? "null" : msg, newDumpFile( defaultReporterFactory
) );
@@ -60,6 +80,12 @@ public final class InPluginProcessDumpSingleton
     private File newDumpFile( DefaultReporterFactory defaultReporterFactory )
     {
         File reportsDirectory = defaultReporterFactory.getReportsDirectory();
-        return new File( reportsDirectory, creationDate + ".dumpstream" );
+        return new File( reportsDirectory, creationDate + DUMPSTREAM_FILE_EXT );
+    }
+
+    private static File newDumpFile( DefaultReporterFactory defaultReporterFactory, int jvmRun
)
+    {
+        File reportsDirectory = defaultReporterFactory.getReportsDirectory();
+        return new File( reportsDirectory, format( DUMPSTREAM_FILENAME_FORMATTER, jvmRun
) );
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/bdde67c5/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireHelperTest.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..b249aca
--- /dev/null
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireHelperTest.java
@@ -0,0 +1,65 @@
+package org.apache.maven.plugin.surefire;
+
+/*
+ * 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.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.Collections.addAll;
+import static java.util.Collections.singleton;
+import static org.fest.assertions.Assertions.assertThat;
+
+/**
+ * Test of {@link SurefireHelper}.
+ */
+public class SurefireHelperTest
+{
+    @Test
+    public void shouldBeThreeDumpFiles()
+    {
+        String[] dumps = SurefireHelper.getDumpFilesToPrint();
+        assertThat( dumps ).hasSize( 3 );
+        assertThat( dumps ).doesNotHaveDuplicates();
+        List<String> onlyStrings = new ArrayList<String>();
+        addAll( onlyStrings, dumps );
+        onlyStrings.removeAll( singleton( (String) null ) );
+        assertThat( onlyStrings ).hasSize( 3 );
+    }
+
+    @Test
+    public void shouldCloneDumpFiles()
+    {
+        String[] dumps1 = SurefireHelper.getDumpFilesToPrint();
+        String[] dumps2 = SurefireHelper.getDumpFilesToPrint();
+        assertThat( dumps1 ).isNotSameAs( dumps2 );
+    }
+
+    @Test
+    public void testConstants()
+    {
+        assertThat( SurefireHelper.DUMPSTREAM_FILENAME_FORMATTER )
+                .isEqualTo( SurefireHelper.DUMP_FILE_PREFIX + "%d.dumpstream" );
+
+        assertThat( String.format( SurefireHelper.DUMPSTREAM_FILENAME_FORMATTER, 5) )
+                .endsWith( "-jvmRun5.dumpstream" );
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/bdde67c5/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
b/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
index 4309ad3..9fb45bf 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java
@@ -21,6 +21,7 @@ package org.apache.maven.surefire;
 
 import junit.framework.JUnit4TestAdapter;
 import junit.framework.Test;
+import org.apache.maven.plugin.surefire.SurefireHelperTest;
 import org.apache.maven.plugin.surefire.SurefireReflectorTest;
 import org.apache.maven.plugin.surefire.SurefirePropertiesTest;
 import org.apache.maven.plugin.surefire.booterclient.BooterDeserializerProviderConfigurationTest;
@@ -72,7 +73,8 @@ import org.junit.runners.Suite;
     TestLessInputStreamBuilderTest.class,
     SPITest.class,
     SurefireReflectorTest.class,
-    ImmutableMapTest.class
+    ImmutableMapTest.class,
+    SurefireHelperTest.class,
 } )
 @RunWith( Suite.class )
 public class JUnit4SuiteTest

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/bdde67c5/surefire-api/src/main/java/org/apache/maven/surefire/booter/DumpErrorSingleton.java
----------------------------------------------------------------------
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 99c921d..fc92c70 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
@@ -35,8 +35,8 @@ import static org.apache.maven.surefire.util.internal.DumpFileUtils.newDumpFile;
  */
 public final class DumpErrorSingleton
 {
-    private static final String DUMP_FILE_EXT = ".dump";
-    private static final String DUMPSTREAM_FILE_EXT = ".dumpstream";
+    public static final String DUMP_FILE_EXT = ".dump";
+    public static final String DUMPSTREAM_FILE_EXT = ".dumpstream";
     private static final DumpErrorSingleton SINGLETON = new DumpErrorSingleton();
 
     private File dumpFile;


Mime
View raw message