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 2016/12/26 15:28:17 UTC

[9/9] maven-surefire git commit: [SUREFIRE-1322] Surefire and Failsafe should dump critical errors in dump file and console

[SUREFIRE-1322] Surefire and Failsafe should dump critical errors in dump file and console


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

Branch: refs/heads/master
Commit: 303cc8acdaf677bee9751da94de16e07083febb7
Parents: 9964119
Author: Tibor17 <ti...@lycos.com>
Authored: Mon Dec 26 16:26:18 2016 +0100
Committer: Tibor17 <ti...@lycos.com>
Committed: Mon Dec 26 16:26:18 2016 +0100

----------------------------------------------------------------------
 .../plugin/failsafe/IntegrationTestMojo.java    |  47 ++++++---
 .../maven/plugin/failsafe/VerifyMojo.java       |  71 ++++---------
 .../plugin/failsafe/xmlsummary/ErrorType.java   |   1 +
 .../failsafe/xmlsummary/FailsafeSummary.java    |   1 +
 .../xmlsummary/FailsafeSummaryXmlUtils.java     |   1 +
 .../maven/plugin/failsafe/xmlsummary/JAXB.java  |   1 +
 .../failsafe/xmlsummary/ObjectFactory.java      |   1 +
 .../failsafe/MarshallerUnmarshallerTest.java    |   1 +
 .../maven/plugin/failsafe/RunResultTest.java    |   1 +
 .../maven/plugin/failsafe/failsafe-summary.xml  |   1 +
 .../maven/plugin/surefire/SurefireHelper.java   |  25 +++--
 .../surefire/booterclient/ForkStarter.java      |  30 ++++--
 .../booterclient/output/ForkClient.java         |   6 +-
 .../output/LostCommandsDumpSingleton.java       |   1 +
 .../surefire/report/DefaultReporterFactory.java |   6 ++
 .../src/site/apt/developing.apt.vm              |   4 +-
 .../src/site/apt/examples/shutdown.apt.vm       |   5 +-
 maven-surefire-plugin/src/site/apt/index.apt.vm |   9 +-
 maven-surefire-plugin/src/site/fml/faq.fml      |  25 ++++-
 .../src/site/resources/xsd/bindings.xml         |   1 +
 .../src/site/resources/xsd/failsafe-summary.xsd |   1 +
 .../maven/surefire/booter/CommandReader.java    |  18 +++-
 .../apache/maven/surefire/suite/RunResult.java  | 101 ++-----------------
 .../surefire/util/internal/DumpFileUtils.java   |   1 +
 .../maven/surefire/suite/RunResultTest.java     |  83 +--------------
 .../maven/surefire/booter/ForkedBooter.java     |  74 ++++++++++----
 .../surefire/its/CheckTestNgExecuteErrorIT.java |  28 ++++-
 .../surefire/its/fixture/OutputValidator.java   |   9 +-
 .../jiras/Surefire141PluggableProvidersIT.java  |  35 +++++--
 29 files changed, 281 insertions(+), 307 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
index c0048d5..2d78109 100644
--- a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
+++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
@@ -19,12 +19,6 @@ package org.apache.maven.plugin.failsafe;
  * under the License.
  */
 
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugin.surefire.AbstractSurefireMojo;
@@ -36,6 +30,16 @@ import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.shared.utils.StringUtils;
 import org.apache.maven.surefire.suite.RunResult;
 
+import javax.xml.bind.JAXBException;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+
+import static org.apache.maven.plugin.failsafe.xmlsummary.FailsafeSummaryXmlUtils.writeSummary;
 import static org.apache.maven.shared.utils.ReaderFactory.FILE_ENCODING;
 
 /**
@@ -46,9 +50,9 @@ import static org.apache.maven.shared.utils.ReaderFactory.FILE_ENCODING;
  * @noinspection JavaDoc,
  */
 @Mojo( name = "integration-test", requiresProject = true, requiresDependencyResolution = ResolutionScope.TEST,
-       defaultPhase = LifecyclePhase.INTEGRATION_TEST, threadSafe = true )
+             defaultPhase = LifecyclePhase.INTEGRATION_TEST, threadSafe = true )
 public class IntegrationTestMojo
-    extends AbstractSurefireMojo
+        extends AbstractSurefireMojo
 {
 
     private static final String FAILSAFE_IN_PROGRESS_CONTEXT_KEY = "failsafe-in-progress";
@@ -235,7 +239,7 @@ public class IntegrationTestMojo
      * By default, Surefire forks your tests using a manifest-only JAR; set this parameter to "false" to force it to
      * launch your tests with a plain old Java classpath. (See the
      * <a href="http://maven.apache.org/plugins/maven-failsafe-plugin/examples/class-loading.html">
-     *     http://maven.apache.org/plugins/maven-failsafe-plugin/examples/class-loading.html</a>
+     * http://maven.apache.org/plugins/maven-failsafe-plugin/examples/class-loading.html</a>
      * for a more detailed explanation of manifest-only JARs and their benefits.)
      * <br/>
      * Beware, setting this to "false" may cause your tests to fail on Windows if your classpath is too long.
@@ -326,7 +330,7 @@ public class IntegrationTestMojo
      * Defaults to "0".<br/>
      * See the prerequisites and limitations in documentation:<br/>
      * <a href="http://maven.apache.org/plugins/maven-failsafe-plugin/examples/skip-after-failure.html">
-     *     http://maven.apache.org/plugins/maven-failsafe-plugin/examples/skip-after-failure.html</a>
+     * http://maven.apache.org/plugins/maven-failsafe-plugin/examples/skip-after-failure.html</a>
      *
      * @since 2.19
      */
@@ -353,7 +357,7 @@ public class IntegrationTestMojo
 
     @SuppressWarnings( "unchecked" )
     protected void handleSummary( RunResult summary, Exception firstForkException )
-        throws MojoExecutionException, MojoFailureException
+            throws MojoExecutionException, MojoFailureException
     {
         File summaryFile = getSummaryFile();
         if ( !summaryFile.getParentFile().isDirectory() )
@@ -365,12 +369,16 @@ public class IntegrationTestMojo
         try
         {
             Object token = getPluginContext().get( FAILSAFE_IN_PROGRESS_CONTEXT_KEY );
-            summary.writeSummary( summaryFile, token != null, getEncodingOrDefault() );
+            writeSummary( summary, summaryFile, token != null, toCharset( getEncodingOrDefault() ) );
         }
         catch ( IOException e )
         {
             throw new MojoExecutionException( e.getMessage(), e );
         }
+        catch ( JAXBException e )
+        {
+            throw new MojoExecutionException( e.getMessage(), e );
+        }
 
         getPluginContext().put( FAILSAFE_IN_PROGRESS_CONTEXT_KEY, FAILSAFE_IN_PROGRESS_CONTEXT_KEY );
     }
@@ -379,10 +387,12 @@ public class IntegrationTestMojo
     {
         if ( StringUtils.isEmpty( encoding ) )
         {
-            getConsoleLogger().warning( "File encoding has not been set, using platform encoding "
-                + FILE_ENCODING
-                + ", i.e. build is platform dependent! The file encoding for reports output files "
-                + "should be provided by the POM property ${project.reporting.outputEncoding}." );
+            getConsoleLogger()
+                    .warning( "File encoding has not been set, using platform encoding "
+                                      + FILE_ENCODING
+                                      + ", i.e. build is platform dependent! The file encoding for reports output files"
+                                      + " should be provided by the POM property ${project.reporting.outputEncoding}."
+            );
             return FILE_ENCODING;
         }
         else
@@ -741,4 +751,9 @@ public class IntegrationTestMojo
     {
         return suiteXmlFiles != null && suiteXmlFiles.length != 0;
     }
+
+    static Charset toCharset( String encoding )
+    {
+        return Charset.forName( Charset.isSupported( encoding ) ? encoding : encoding.toUpperCase( Locale.ROOT ) );
+    }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/VerifyMojo.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/VerifyMojo.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/VerifyMojo.java
index 5d0b035..a56d521 100644
--- a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/VerifyMojo.java
+++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/VerifyMojo.java
@@ -19,18 +19,11 @@ package org.apache.maven.plugin.failsafe;
  * under the License.
  */
 
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.Collection;
-
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.failsafe.xmlsummary.FailsafeSummaryXmlUtils;
 import org.apache.maven.plugin.surefire.SurefireHelper;
 import org.apache.maven.plugin.surefire.SurefireReportParameters;
 import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
@@ -41,11 +34,12 @@ import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.surefire.cli.CommandLineOption;
 import org.apache.maven.surefire.suite.RunResult;
 
+import javax.xml.bind.JAXBException;
+import java.io.File;
+import java.util.Collection;
+
 import static org.apache.maven.plugin.surefire.SurefireHelper.reportExecution;
-import static org.apache.maven.shared.utils.ReaderFactory.FILE_ENCODING;
 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.io.IOUtil.close;
 import static org.apache.maven.surefire.suite.RunResult.noTestsRun;
 
 /**
@@ -54,10 +48,11 @@ import static org.apache.maven.surefire.suite.RunResult.noTestsRun;
  * @author Stephen Connolly
  * @author Jason van Zyl
  */
+@SuppressWarnings( "unused" )
 @Mojo( name = "verify", defaultPhase = LifecyclePhase.VERIFY, requiresProject = true, threadSafe = true )
 public class VerifyMojo
-    extends AbstractMojo
-    implements SurefireReportParameters
+        extends AbstractMojo
+        implements SurefireReportParameters
 {
 
     /**
@@ -167,44 +162,28 @@ public class VerifyMojo
     private volatile PluginConsoleLogger consoleLogger;
 
     public void execute()
-        throws MojoExecutionException, MojoFailureException
+            throws MojoExecutionException, MojoFailureException
     {
         cli = commandLineOptions();
         if ( verifyParameters() )
         {
-            logDebugOrCliShowErrors(
-                capitalizeFirstLetter( getPluginName() ) + " report directory: " + getReportsDirectory() );
+            logDebugOrCliShowErrors( capitalizeFirstLetter( getPluginName() )
+                                             + " report directory: " + getReportsDirectory() );
 
             RunResult summary;
             try
             {
-                final String encoding;
-                if ( isEmpty( this.encoding ) )
-                {
-                    getConsoleLogger()
-                            .warning( "File encoding has not been set, using platform encoding "
-                                              + FILE_ENCODING
-                                              + ", i.e. build is platform dependent! The file encoding for "
-                                              + "reports output files should be provided by the POM property "
-                                              + "${project.reporting.outputEncoding}." );
-                    encoding = FILE_ENCODING;
-                }
-                else
-                {
-                    encoding = this.encoding;
-                }
-
-                summary = existsSummaryFile() ? readSummary( encoding, summaryFile ) : noTestsRun();
+                summary = existsSummaryFile() ? readSummary( summaryFile ) : noTestsRun();
 
                 if ( existsSummaryFiles() )
                 {
                     for ( final File summaryFile : summaryFiles )
                     {
-                        summary = summary.aggregate( readSummary( encoding, summaryFile ) );
+                        summary = summary.aggregate( readSummary( summaryFile ) );
                     }
                 }
             }
-            catch ( IOException e )
+            catch ( JAXBException e )
             {
                 throw new MojoExecutionException( e.getMessage(), e );
             }
@@ -228,29 +207,13 @@ public class VerifyMojo
         return consoleLogger;
     }
 
-    private RunResult readSummary( String encoding, File summaryFile )
-        throws IOException
+    private RunResult readSummary( File summaryFile ) throws JAXBException
     {
-        FileInputStream fileInputStream = null;
-        BufferedInputStream bufferedInputStream = null;
-        Reader reader = null;
-        try
-        {
-            fileInputStream = new FileInputStream( summaryFile );
-            bufferedInputStream = new BufferedInputStream( fileInputStream );
-            reader = new InputStreamReader( bufferedInputStream, encoding );
-            return RunResult.fromInputStream( bufferedInputStream, encoding );
-        }
-        finally
-        {
-            close( reader );
-            close( bufferedInputStream );
-            close( fileInputStream );
-        }
+        return FailsafeSummaryXmlUtils.toRunResult( summaryFile );
     }
 
     protected boolean verifyParameters()
-        throws MojoFailureException
+            throws MojoFailureException
     {
         if ( isSkip() || isSkipTests() || isSkipITs() || isSkipExec() )
         {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/ErrorType.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/ErrorType.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/ErrorType.java
new file mode 100644
index 0000000..f301527
--- /dev/null
+++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/ErrorType.java
@@ -0,0 +1 @@
+package org.apache.maven.plugin.failsafe.xmlsummary;

/*
 * 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 javax.xml.bind.annotation.XmlEnum;
import javax.xml.bind.annotation.XmlEnumValue;
import javax.xml.bind.annotation.XmlType;
 
/**
 * <p>Java class for errorType.
 * <p/>
 * <p>The following schema fragment specifies the expected content contained within this class.
 * <p/>
 * <pre>
 * &lt;simpleType name="errorType">
 *   &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
 *     &lt;enumeration value="255"/>
 *     &lt;enumeration value="254"/>
 *   &lt;/restriction>
 * &lt;/simpleType>
 * </pre>
 */
@XmlType( name = "errorType" )
@XmlEnum( Integer.class )
public enum ErrorType
{

    @XmlEnumValue( "255" )
    FAILURE( 255 ),

    @XmlEnumValue( "254" )
    NO_TESTS( 254 );

    private final int value;

    ErrorType( int v )
    {
        value = v;
    }

    public static ErrorType fromValue( Integer v )
    {
        if ( v == null )
        {
            return null;
        }

        for ( ErrorType c : ErrorType.values() )
        {
            if ( c.value == v )
            {
                return c;
            }
        }
        throw new IllegalArgumentException( "" + v );
 
    }

    public int value()
    {
        return value;
    }

}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/FailsafeSummary.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/FailsafeSummary.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/FailsafeSummary.java
new file mode 100644
index 0000000..d20fd4f
--- /dev/null
+++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/FailsafeSummary.java
@@ -0,0 +1 @@
+package org.apache.maven.plugin.failsafe.xmlsummary;

/*
 * 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 javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.X
 mlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import static java.util.Collections.emptyList;
import static org.apache.maven.plugin.failsafe.xmlsummary.ErrorType.FAILURE;
import static org.apache.maven.plugin.failsafe.xmlsummary.ErrorType.NO_TESTS;


/**
 * <p>Java class for anonymous complex type.
 * <p/>
 * <p>The following schema fragment specifies the expected content contained within this class.
 * <p/>
 * <pre>
 * &lt;complexType>
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="completed" type="{http://www.w3.org/2001/XMLSchema}int"/>
 *         &lt;element name="errors" type="{http://www.w3.org/2001/XMLSc
 hema}int"/>
 *         &lt;element name="failures" type="{http://www.w3.org/2001/XMLSchema}int"/>
 *         &lt;element name="skipped" type="{http://www.w3.org/2001/XMLSchema}int"/>
 *         &lt;element name="failureMessage" type="{http://www.w3.org/2001/XMLSchema}string"/>
 *       &lt;/sequence>
 *       &lt;attribute name="result" type="{}errorType" />
 *       &lt;attribute name="timeout" use="required" type="{http://www.w3.org/2001/XMLSchema}boolean" />
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 */
@XmlAccessorType( XmlAccessType.FIELD )
@XmlType( name = "", propOrder = {
                                         "completed",
                                         "errors",
                                         "failures",
                                         "skipped",
                                         "failureMessage"
} )
@XmlRootElement( name = "failsafe-summary" )
public class FailsafeSummary
{
    private static fin
 al String ERROR_MSG_PREFIX = "org.apache.maven.surefire.booter.SurefireBooterForkException: ";
    private static final Pattern STACK_TRACE_ELEMENT1 = Pattern.compile( "^\\tat.*\\(.*\\.java\\:[\\d]+\\)$" );
    private static final Pattern STACK_TRACE_ELEMENT2 = Pattern.compile( "^\\tat.*\\(Native Method\\)$" );
    private static final Pattern STACK_TRACE_ELEMENT3 = Pattern.compile( "^Caused by\\: .*" );

    private int completed;

    private int errors;

    private int failures;

    private int skipped;

    @XmlElement( required = true, nillable = true )
    private String failureMessage;

    @XmlAttribute( name = "result" )
    private ErrorType result;

    @XmlAttribute( name = "timeout", required = true )
    private boolean timeout;

    /**
     * Gets the value of the completed property.
     */
    public int getCompleted()
    {
        return completed;
    }

    /**
     * Sets the value of the completed property.
     */
    public void setCompleted( int value )
 
    {
        this.completed = value;
    }

    /**
     * Gets the value of the errors property.
     */
    public int getErrors()
    {
        return errors;
    }

    /**
     * Sets the value of the errors property.
     */
    public void setErrors( int value )
    {
        this.errors = value;
    }

    /**
     * Gets the value of the failures property.
     */
    public int getFailures()
    {
        return failures;
    }

    /**
     * Sets the value of the failures property.
     */
    public void setFailures( int value )
    {
        this.failures = value;
    }

    /**
     * Gets the value of the skipped property.
     */
    public int getSkipped()
    {
        return skipped;
    }

    /**
     * Sets the value of the skipped property.
     */
    public void setSkipped( int value )
    {
        this.skipped = value;
    }

    /**
     * Gets the value of the failureMessage property.
     *
     * @return possible object is
     * {@link String }
   
   */
    public String getFailureMessage()
    {
        return failureMessage;
    }

    /**
     * Sets the value of the failureMessage property.
     *
     * @param value allowed object is
     *              {@link String }
     */
    public void setFailureMessage( String value )
    {
        this.failureMessage = value;
    }

    /**
     * Gets the value of the result property.
     *
     * @return possible object is
     * {@link ErrorType }
     */
    public ErrorType getResult()
    {
        return result;
    }

    /**
     * Sets the value of the result property.
     *
     * @param value allowed object is
     *              {@link ErrorType }
     */
    public void setResult( ErrorType value )
    {
        this.result = value;
    }

    /**
     * Gets the value of the timeout property.
     */
    public boolean isTimeout()
    {
        return timeout;
    }

    /**
     * Sets the value of the timeout property.
     */
    public void setTimeout( boolea
 n value )
    {
        this.timeout = value;
    }

    public boolean hasNoTests()
    {
        return getResult() == NO_TESTS;
    }

    public boolean isFailure()
    {
        return getResult() == FAILURE;
    }

    public List<String> extractExceptionMessageLines() throws IOException
    {
        if ( getFailureMessage() == null )
        {
            return emptyList();
        }

        List<String> msg = new ArrayList<String>();
        LineNumberReader reader = new LineNumberReader( new StringReader( getFailureMessage() ) );
        for ( @SuppressWarnings( "checkstyle:innerassignment" ) String line; ( line = reader.readLine() ) != null; )
        {
            if ( !STACK_TRACE_ELEMENT1.matcher( line ).matches()
                         && !STACK_TRACE_ELEMENT2.matcher( line ).matches()
                         && !STACK_TRACE_ELEMENT3.matcher( line ).matches() )
            {
                line = line.trim();
                msg.add( line.startsWith( ERROR_MSG_P
 REFIX ) ? line.substring( ERROR_MSG_PREFIX.length() ) : line );
            }
            else
            {
                break;
            }
        }
        return msg;
    }

    @Override
    public boolean equals( Object o )
    {
        if ( this == o )
        {
            return true;
        }

        if ( o == null || getClass() != o.getClass() )
        {
            return false;
        }

        FailsafeSummary summary = (FailsafeSummary) o;

        return getCompleted() == summary.getCompleted()
                       && getErrors() == summary.getErrors()
                       && getFailures() == summary.getFailures()
                       && getSkipped() == summary.getSkipped()
                       && isTimeout() == summary.isTimeout()
                       && equal( getFailureMessage(), summary.getFailureMessage() )
                       && getResult() == summary.getResult();
    }

    @Override
    public int hashCode()
    {
        int result1 = 
 getCompleted();
        result1 = 31 * result1 + getErrors();
        result1 = 31 * result1 + getFailures();
        result1 = 31 * result1 + getSkipped();
        result1 = 31 * result1 + ( getFailureMessage() != null ? getFailureMessage().hashCode() : 0 );
        result1 = 31 * result1 + ( getResult() != null ? getResult().hashCode() : 0 );
        result1 = 31 * result1 + ( isTimeout() ? 1 : 0 );
        return result1;
    }

    private boolean equal( String s1, String s2 )
    {
        return s1 == null ? s2 == null : s1.equals( s2 );
    }
}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/FailsafeSummaryXmlUtils.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/FailsafeSummaryXmlUtils.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/FailsafeSummaryXmlUtils.java
new file mode 100644
index 0000000..6bfa945
--- /dev/null
+++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/FailsafeSummaryXmlUtils.java
@@ -0,0 +1 @@
+package org.apache.maven.plugin.failsafe.xmlsummary;

/*
 * 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.suite.RunResult;

import javax.xml.bind.JAXBException;
import java.io.File;
import java.io.FileOutp
 utStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;

/**
 * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
 * @since 2.19.2
 */
public final class FailsafeSummaryXmlUtils
{
    public static final Charset UTF8 = Charset.forName( "UTF-8" );

    private FailsafeSummaryXmlUtils()
    {
        throw new IllegalStateException( "No instantiable constructor." );
    }

    public static RunResult toRunResult( File failsafeSummaryXml ) throws JAXBException
    {
        FailsafeSummary failsafeSummary = JAXB.unmarshal( failsafeSummaryXml, FailsafeSummary.class );

        return new RunResult( failsafeSummary.getCompleted(), failsafeSummary.getErrors(),
                                    failsafeSummary.getFailures(), failsafeSummary.getSkipped(),
                                    failsafeSummary.getFailureMessage(), failsafeSummary.isTimeout()
        );
    }

    public static void fromRunResultToFile(
  RunResult fromRunResult, File toFailsafeSummaryXml )
            throws JAXBException, IOException
    {
        fromRunResultToFile( fromRunResult, toFailsafeSummaryXml, UTF8 );
    }

    public static void fromRunResultToFile( RunResult fromRunResult, File toFailsafeSummaryXml, Charset encoding )
            throws JAXBException, IOException
    {
        FailsafeSummary summary = new FailsafeSummary();
        summary.setCompleted( fromRunResult.getCompletedCount() );
        summary.setFailureMessage( fromRunResult.getFailure() );
        summary.setErrors( fromRunResult.getErrors() );
        summary.setFailures( fromRunResult.getFailures() );
        summary.setSkipped( fromRunResult.getSkipped() );
        summary.setTimeout( fromRunResult.isTimeout() );
        summary.setResult( ErrorType.fromValue( fromRunResult.getFailsafeCode() ) );

        String unmarshalled = JAXB.marshal( summary, encoding );

        OutputStreamWriter os = new OutputStreamWriter( new FileOutputS
 tream( toFailsafeSummaryXml ), encoding );
        try
        {
            os.write( unmarshalled );
            os.flush();
        }
        finally
        {
            os.close();
        }
    }

    public static void writeSummary( RunResult mergedSummary, File mergedSummaryFile, boolean inProgress,
                                     Charset encoding )
            throws IOException, JAXBException
    {
        if ( !mergedSummaryFile.getParentFile().isDirectory() )
        {
            //noinspection ResultOfMethodCallIgnored
            mergedSummaryFile.getParentFile().mkdirs();
        }

        if ( mergedSummaryFile.exists() && inProgress )
        {
            RunResult runResult = toRunResult( mergedSummaryFile );
            mergedSummary = mergedSummary.aggregate( runResult );
        }

        fromRunResultToFile( mergedSummary, mergedSummaryFile, encoding );
    }
}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/JAXB.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/JAXB.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/JAXB.java
new file mode 100644
index 0000000..ba3fdd0
--- /dev/null
+++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/JAXB.java
@@ -0,0 +1 @@
+package org.apache.maven.plugin.failsafe.xmlsummary;

/*
 * 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 javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Mar
 shaller;
import javax.xml.bind.PropertyException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.helpers.DefaultValidationEventHandler;
import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;

import static javax.xml.bind.JAXBContext.newInstance;
import static javax.xml.bind.Marshaller.JAXB_ENCODING;
import static javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT;
import static javax.xml.bind.Marshaller.JAXB_FRAGMENT;

/**
 * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
 * @since 2.19.2
 */
public final class JAXB
{
    private JAXB()
    {
        throw new IllegalStateException( "Not instantiated constructor." );
    }

    public static <T> T unmarshal( File
  source, Class<T> rootXmlNode ) throws JAXBException
    {
        return unmarshal( source, rootXmlNode, Collections.<String, Object>emptyMap() );
    }

    public static <T> T unmarshal( File source, Class<T> rootXmlNode, Map<String, ?> props )
            throws JAXBException
    {
        Class<?>[] classesToBeBound = { rootXmlNode };
        JAXBContext ctx = newInstance( classesToBeBound );
        Unmarshaller unmarshaller = ctx.createUnmarshaller();
        properties( props, unmarshaller );
        unmarshaller.setEventHandler( new DefaultValidationEventHandler() );
        JAXBElement<T> element = unmarshaller.unmarshal( new StreamSource( source ), rootXmlNode );
        return element.getValue();
    }

    public static <T> String marshal( T bean, Charset encoding ) throws JAXBException, IOException
    {
        return marshal( bean, Collections.<String, Object>emptyMap(), encoding ).toString();
    }

    @SuppressWarnings( "unchecked" )
    public static <T> StringWr
 iter marshal( T bean, Map<String, Object> props, Charset encoding )
            throws JAXBException, IOException
    {
        return marshal( bean, (Class<T>) bean.getClass(), props, encoding );
    }

    public static <T> StringWriter marshal( T bean, Class<T> type, Map<String, Object> props, Charset encoding )
            throws JAXBException, IOException
    {
        JAXBElement<T> rootElement = buildJaxbElement( bean, type );
        return marshal( rootElement, type, props, encoding );
    }

    public static <T> StringWriter marshal( JAXBElement<T> rootElement, Class<T> type,
                                            Map<String, Object> props, Charset encoding )
            throws JAXBException, IOException
    {
        StringWriter destination = new StringWriter( 256 );
        marshal( rootElement, type, props, destination, encoding );
        destination.flush();
        return destination;
    }

    public static <T> void marshal( JAXBElement<T> rootElement, Class
 <T> type, Map<String, Object> props,
                                    Writer destination, Charset encoding ) throws JAXBException
    {
        Class<?>[] classesToBeBound = { type };
        JAXBContext context = newInstance( classesToBeBound );
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty( JAXB_ENCODING, encoding.name() );
        marshaller.setProperty( JAXB_FORMATTED_OUTPUT, true );
        marshaller.setProperty( JAXB_FRAGMENT, true );
        properties( props, marshaller );
        marshaller.marshal( rootElement, destination );
    }

    private static <T> JAXBElement<T> buildJaxbElement( T bean, Class<T> type )
    {
        XmlRootElement xmlRootElement = type.getAnnotation( XmlRootElement.class );
        if ( xmlRootElement == null )
        {
            return null;
        }
        QName root = new QName( "", xmlRootElement.name() );
        return new JAXBElement<T>( root, type, bean );
    }

    private static void
  properties( Map<String, ?> props, Unmarshaller unmarshaller ) throws PropertyException
    {
        for ( Entry<String, ?> e : props.entrySet() )
        {
            unmarshaller.setProperty( e.getKey(), e.getValue() );
        }
    }

    private static void properties( Map<String, ?> props, Marshaller marshaller ) throws PropertyException
    {
        for ( Entry<String, ?> e : props.entrySet() )
        {
            marshaller.setProperty( e.getKey(), e.getValue() );
        }
    }
}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/ObjectFactory.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/ObjectFactory.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/ObjectFactory.java
new file mode 100644
index 0000000..7e1c252
--- /dev/null
+++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/xmlsummary/ObjectFactory.java
@@ -0,0 +1 @@
+package org.apache.maven.plugin.failsafe.xmlsummary;

/*
 * 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 javax.xml.bind.annotation.XmlRegistry;


/**
 * This object contains factory methods for each
 * Java content interface and J
 ava element interface
 * generated in the org.apache.maven.surefire.suite package.
 * <p>An ObjectFactory allows you to programatically
 * construct new instances of the Java representation
 * for XML content. The Java representation of XML
 * content can consist of schema derived interfaces
 * and classes representing the binding of schema
 * type definitions, element declarations and model
 * groups.  Factory methods for each of these are
 * provided in this class.
 */
@XmlRegistry
public class ObjectFactory
{


    /**
     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package:
     * org.apache.maven.surefire.suite
     */
    public ObjectFactory()
    {
    }

    /**
     * Create an instance of {@link FailsafeSummary }
     */
    public FailsafeSummary createFailsafeSummary()
    {
        return new FailsafeSummary();
    }

}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/MarshallerUnmarshallerTest.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/MarshallerUnmarshallerTest.java b/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/MarshallerUnmarshallerTest.java
new file mode 100644
index 0000000..4386d71
--- /dev/null
+++ b/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/MarshallerUnmarshallerTest.java
@@ -0,0 +1 @@
+package org.apache.maven.plugin.failsafe;

/*
 * 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.plugin.failsafe.xmlsummary.FailsafeSummary;
import org.apache.maven.plugin.failsafe.xmlsummary.FailsafeSummaryXmlUtils;
 
import org.apache.maven.plugin.failsafe.xmlsummary.JAXB;
import org.junit.Test;

import java.io.File;
import java.io.FileWriter;
import java.util.List;

import static org.apache.maven.plugin.failsafe.xmlsummary.ErrorType.FAILURE;
import static org.fest.assertions.Assertions.assertThat;

public class MarshallerUnmarshallerTest
{
    @Test
    public void shouldUnmarshallExistingXmlFile() throws Exception
    {
        File xml = new File( "target/test-classes/org/apache/maven/plugin/failsafe/failsafe-summary.xml" );
        FailsafeSummary summary = JAXB.unmarshal( xml, FailsafeSummary.class );

        assertThat( summary.getCompleted() )
                .isEqualTo( 7 );

        assertThat( summary.getErrors() )
                .isEqualTo( 1 );

        assertThat( summary.getFailures() )
                .isEqualTo( 2 );

        assertThat( summary.getSkipped() )
                .isEqualTo( 3 );

        assertThat( summary.getFailureMessage() )
                .contains( "There 
 was an error in the forked processtest "
                                   + "subsystem#no method RuntimeException Hi There!"
                );

        assertThat( summary.getFailureMessage() )
                .contains( "There was an error in the forked processtest "
                                   + "subsystem#no method RuntimeException Hi There!"
                                   + "\n\tat org.apache.maven.plugin.surefire.booterclient.ForkStarter"
                                   + ".awaitResultsDone(ForkStarter.java:489)"
                );

        List<String> exceptionMessages = summary.extractExceptionMessageLines();

        assertThat( exceptionMessages )
                .hasSize( 1 );

        assertThat( exceptionMessages.get( 0 ) )
                .isEqualTo( "ExecutionException There was an error in the forked processtest "
                                    + "subsystem#no method RuntimeException Hi There!"
                );

        summary.setFailureMessa
 ge( null );

        assertThat( summary.extractExceptionMessageLines() )
                .isEmpty();
    }

    @Test
    public void shouldEqualTwoSameXml() throws Exception
    {
        File xml = new File( "target/test-classes/org/apache/maven/plugin/failsafe/failsafe-summary.xml" );
        FailsafeSummary summary1 = JAXB.unmarshal( xml, FailsafeSummary.class );
        FailsafeSummary summary2 = JAXB.unmarshal( xml, FailsafeSummary.class );

        assertThat( summary1 )
                .isEqualTo( summary2 );
    }

    @Test
    public void shouldMarshallAndUnmarshallSameXml() throws Exception
    {
        FailsafeSummary expected = new FailsafeSummary();
        expected.setResult( FAILURE );
        expected.setTimeout( true );
        expected.setCompleted( 7 );
        expected.setErrors( 1 );
        expected.setFailures( 2 );
        expected.setSkipped( 3 );
        expected.setFailureMessage( "There was an error in the forked processtest "
                        
                     + "subsystem#no method RuntimeException Hi There!"
                                            + "\n\tat org.apache.maven.plugin.surefire.booterclient.ForkStarter"
                                            + ".awaitResultsDone(ForkStarter.java:489)"
        );

        File xml = File.createTempFile( "failsafe-summary", ".xml" );
        String xmlText = JAXB.marshal( expected, FailsafeSummaryXmlUtils.UTF8 );
        FileWriter fileWriter = new FileWriter( xml );
        fileWriter.write( xmlText );
        fileWriter.flush();
        fileWriter.close();

        FailsafeSummary actual = JAXB.unmarshal( xml, FailsafeSummary.class );

        assertThat( actual )
                .isEqualTo( expected );

        List<String> exceptionMessages = actual.extractExceptionMessageLines();

        assertThat( exceptionMessages )
                .hasSize( 1 );

        assertThat( exceptionMessages.get( 0 ) )
                .isEqualTo( "There was an error in the forked
  processtest "
                                    + "subsystem#no method RuntimeException Hi There!"
                );
    }
}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/RunResultTest.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/RunResultTest.java b/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/RunResultTest.java
new file mode 100644
index 0000000..1ffb7d9
--- /dev/null
+++ b/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/RunResultTest.java
@@ -0,0 +1 @@
+package org.apache.maven.plugin.failsafe;

/*
 * 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.plugin.failsafe.xmlsummary.FailsafeSummaryXmlUtils;
import org.apache.maven.surefire.suite.RunResult;
import org.junit.
 Test;

import javax.xml.bind.JAXBException;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;

import static org.fest.assertions.Assertions.assertThat;

/**
 * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
 * @since 2.19.2
 */
public class RunResultTest
{

    @Test
    public void testAggregatedValues()
    {
        RunResult simple = getSimpleAggregate();

        assertThat( simple.getCompletedCount() )
                .isEqualTo( 20 );

        assertThat( simple.getErrors() )
                .isEqualTo( 3 );

        assertThat( simple.getFailures() )
                .isEqualTo( 7 );

        assertThat( simple.getSkipped() )
                .isEqualTo( 4 );

        assertThat( simple.getFlakes() )
                .isEqualTo( 2 );
    }

    @Test
    public void testSerialization()
            throws IOException, JAXBException
    {
        writeReadCheck( getSimpleAggregate() );
    }

    @Test
    public void te
 stFailures()
            throws IOException, JAXBException
    {
        writeReadCheck( new RunResult( 0, 1, 2, 3, "stacktraceHere", false ) );
    }

    @Test
    public void testSkipped()
            throws IOException, JAXBException
    {
        writeReadCheck( new RunResult( 3, 2, 1, 0, null, true ) );
    }

    @Test
    public void testAppendSerialization()
            throws IOException, JAXBException
    {
        RunResult simpleAggregate = getSimpleAggregate();
        RunResult additional = new RunResult( 2, 1, 2, 2, "msg " + ( (char) 0x0E01 ), true );

        File summary = File.createTempFile( "failsafe", "test" );
        FailsafeSummaryXmlUtils.writeSummary( simpleAggregate, summary, false, FailsafeSummaryXmlUtils.UTF8 );
        FailsafeSummaryXmlUtils.writeSummary( additional, summary, true, FailsafeSummaryXmlUtils.UTF8 );
        RunResult actual = FailsafeSummaryXmlUtils.toRunResult( summary );
        //noinspection ResultOfMethodCallIgnored
        summary.
 delete();

        RunResult expected = simpleAggregate.aggregate( additional );

        assertThat( expected.getCompletedCount() )
                .isEqualTo( 22 );

        assertThat( expected.getErrors() )
                .isEqualTo( 4 );

        assertThat( expected.getFailures() )
                .isEqualTo( 9 );

        assertThat( expected.getSkipped() )
                .isEqualTo( 6 );

        assertThat( expected.getFlakes() )
                .isEqualTo( 2 );

        assertThat( expected.getFailure() )
                .isEqualTo( "msg " + ( (char) 0x0E01 ) );

        assertThat( expected.isTimeout() )
                .isTrue();

        assertThat( actual )
                .isEqualTo( expected );
    }

    @Test
    public void shouldAcceptAliasCharset()
    {
        Charset charset1 = IntegrationTestMojo.toCharset( "UTF8" );
        assertThat( charset1.name() ).isEqualTo( "UTF-8" );

        Charset charset2 = IntegrationTestMojo.toCharset( "utf8" );
        asse
 rtThat( charset2.name() ).isEqualTo( "UTF-8" );
    }

    private void writeReadCheck( RunResult expected )
            throws IOException, JAXBException
    {
        File tmp = File.createTempFile( "test", "xml" );
        FailsafeSummaryXmlUtils.fromRunResultToFile( expected, tmp );

        RunResult actual = FailsafeSummaryXmlUtils.toRunResult( tmp );
        //noinspection ResultOfMethodCallIgnored
        tmp.delete();

        assertThat( actual )
                .isEqualTo( expected );
    }

    private RunResult getSimpleAggregate()
    {
        RunResult resultOne = new RunResult( 10, 1, 3, 2, 1 );
        RunResult resultTwo = new RunResult( 10, 2, 4, 2, 1 );
        return resultOne.aggregate( resultTwo );
    }
}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-failsafe-plugin/src/test/resources/org/apache/maven/plugin/failsafe/failsafe-summary.xml
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/test/resources/org/apache/maven/plugin/failsafe/failsafe-summary.xml b/maven-failsafe-plugin/src/test/resources/org/apache/maven/plugin/failsafe/failsafe-summary.xml
new file mode 100644
index 0000000..b1fe1f9
--- /dev/null
+++ b/maven-failsafe-plugin/src/test/resources/org/apache/maven/plugin/failsafe/failsafe-summary.xml
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<failsafe-summary result="254" timeout="false">
  <completed>7</completed>
  <errors>1</errors>
  <failures>2</failures>
  <skipped>3</skipped>
  <failureMessage>
 <![CDATA[org.apache.maven.surefire.booter.SurefireBooterForkException: ExecutionException There was an error in the forked processtest subsystem#no method RuntimeException Hi There!
	at org.apache.maven.plugin.surefire.booterclient.ForkStarter.awaitResultsDone(ForkStarter.java:489)
	at org.apache.maven.plugin.surefire.booterclient.ForkStarter.runSuitesForkOnceMultiple(ForkStarter.java:364)
	at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:288)
	at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:240)
	at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1075)
	at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:905)
	at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:783)
	at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:133)
	
 at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:108)
	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:76)
	at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
	at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:116)
	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:361)
	at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:155)
	at org.apache.maven.cli.MavenCli.execute(MavenCli.java:584)
	at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:213)
	at org.apache.maven.cli.MavenCli.main(MavenCli.java:157)
	at 
 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
	at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
	at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
	at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: java.lang.RuntimeException: There was an error in the forked processtest subsystem#no method RuntimeException Hi There!
	at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:658)
	at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:527)
	at org.apache.maven.plugin.surefire.booterclient.ForkStarter.acces
 s$500(ForkStarter.java:117)
	at org.apache.maven.plugin.surefire.booterclient.ForkStarter$1.call(ForkStarter.java:358)
	at org.apache.maven.plugin.surefire.booterclient.ForkStarter$1.call(ForkStarter.java:337)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
]]></failureMessage>
</failsafe-summary>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/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 e4b340a..bab37c7 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
@@ -165,31 +165,31 @@ public final class SurefireHelper
         return reportParameters.getFailIfNoTests() != null && reportParameters.getFailIfNoTests();
     }
 
-    private static boolean isNotFatal( Exception firstForkException )
+    private static boolean isFatal( Exception firstForkException )
     {
-        return firstForkException == null || firstForkException instanceof TestSetFailedException;
+        return firstForkException != null && !( firstForkException instanceof TestSetFailedException );
     }
 
     private static void throwException( SurefireReportParameters reportParameters, RunResult result,
                                            Exception firstForkException )
             throws MojoFailureException, MojoExecutionException
     {
-        if ( isNotFatal( firstForkException ) )
+        if ( isFatal( firstForkException ) || result.isInternalError()  )
         {
-            throw new MojoFailureException( createErrorMessage( reportParameters, result, firstForkException ),
+            throw new MojoExecutionException( createErrorMessage( reportParameters, result, firstForkException ),
                                                     firstForkException );
         }
         else
         {
-            throw new MojoExecutionException( createErrorMessage( reportParameters, result, firstForkException ),
-                                                    firstForkException );
+            throw new MojoFailureException( createErrorMessage( reportParameters, result, firstForkException ),
+                                                  firstForkException );
         }
     }
 
     private static String createErrorMessage( SurefireReportParameters reportParameters, RunResult result,
                                               Exception firstForkException )
     {
-        StringBuilder msg = new StringBuilder( 128 );
+        StringBuilder msg = new StringBuilder( 512 );
 
         if ( result.isTimeout() )
         {
@@ -199,7 +199,10 @@ public final class SurefireHelper
         {
             msg.append( "There are test failures.\n\nPlease refer to " )
                     .append( reportParameters.getReportsDirectory() )
-                    .append( " for the individual test results." );
+                    .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" );
         }
 
         if ( firstForkException != null && firstForkException.getLocalizedMessage() != null )
@@ -208,6 +211,12 @@ public final class SurefireHelper
                     .append( firstForkException.getLocalizedMessage() );
         }
 
+        if ( result.isFailure() )
+        {
+            msg.append( '\n' )
+                    .append( result.getFailure() );
+        }
+
         return msg.toString();
     }
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/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 3981c79..2d0ae38 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
@@ -30,6 +30,7 @@ import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestProvid
 import org.apache.maven.plugin.surefire.booterclient.output.ForkClient;
 import org.apache.maven.plugin.surefire.booterclient.output.NativeStdErrStreamConsumer;
 import org.apache.maven.plugin.surefire.booterclient.output.ThreadedStreamConsumer;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
 import org.apache.maven.shared.utils.cli.CommandLineCallable;
 import org.apache.maven.shared.utils.cli.CommandLineException;
@@ -44,11 +45,11 @@ import org.apache.maven.surefire.booter.StartupConfiguration;
 import org.apache.maven.surefire.booter.SurefireBooterForkException;
 import org.apache.maven.surefire.booter.SurefireExecutionException;
 import org.apache.maven.surefire.providerapi.SurefireProvider;
-import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 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;
@@ -83,20 +84,20 @@ import static org.apache.maven.plugin.surefire.AbstractSurefireMojo.createCopyAn
 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
-    .TestLessInputStreamBuilder;
+                      .TestLessInputStreamBuilder;
 import static org.apache.maven.shared.utils.cli.CommandLineUtils.executeCommandLineAsCallable;
 import static org.apache.maven.shared.utils.cli.ShutdownHookUtils.addShutDownHook;
 import static org.apache.maven.shared.utils.cli.ShutdownHookUtils.removeShutdownHook;
 import static org.apache.maven.surefire.booter.Classpath.join;
 import static org.apache.maven.surefire.booter.SystemPropertyManager.writePropertiesFile;
-import static org.apache.maven.surefire.suite.RunResult.timeout;
-import static org.apache.maven.surefire.suite.RunResult.failure;
 import static org.apache.maven.surefire.suite.RunResult.SUCCESS;
+import static org.apache.maven.surefire.suite.RunResult.failure;
+import static org.apache.maven.surefire.suite.RunResult.timeout;
 import static org.apache.maven.surefire.util.internal.ConcurrencyUtils.countDownToZero;
 import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThread;
 import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThreadFactory;
-import static org.apache.maven.surefire.util.internal.StringUtils.FORK_STREAM_CHARSET_NAME;
 import static org.apache.maven.surefire.util.internal.ObjectUtils.requireNonNull;
+import static org.apache.maven.surefire.util.internal.StringUtils.FORK_STREAM_CHARSET_NAME;
 
 /**
  * Starts the fork or runs in-process.
@@ -128,6 +129,10 @@ public class ForkStarter
 
     private static final AtomicInteger SYSTEM_PROPERTIES_FILE_COUNTER = new AtomicInteger();
 
+    private static final String DUMP_FILE_PREFIX = DumpFileUtils.newFormattedDateFileName() + "-jvmRun";
+
+    private static final AtomicInteger DUMP_FILE_POSTFIX_COUNTER = new AtomicInteger();
+
     private final ScheduledExecutorService pingThreadScheduler = createPingScheduler();
 
     private final ScheduledExecutorService timeoutCheckScheduler;
@@ -529,10 +534,12 @@ public class ForkStarter
                             AbstractForkInputStream testProvidingInputStream, boolean readTestsFromInStream )
         throws SurefireBooterForkException
     {
+        final String tempDir;
         final File surefireProperties;
         final File systPropsFile;
         try
         {
+            tempDir = forkConfiguration.getTempDirectory().getCanonicalPath();
             BooterSerializer booterSerializer = new BooterSerializer( forkConfiguration );
 
             surefireProperties = booterSerializer.serialize( providerProperties, providerConfiguration,
@@ -577,11 +584,12 @@ public class ForkStarter
             testProvidingInputStream.setFlushReceiverProvider( cli );
         }
 
-        cli.createArg().setFile( surefireProperties );
-
+        cli.createArg().setValue( tempDir );
+        cli.createArg().setValue( DUMP_FILE_PREFIX + DUMP_FILE_POSTFIX_COUNTER.incrementAndGet() );
+        cli.createArg().setValue( surefireProperties.getName() );
         if ( systPropsFile != null )
         {
-            cli.createArg().setFile( systPropsFile );
+            cli.createArg().setValue( systPropsFile.getName() );
         }
 
         final ThreadedStreamConsumer threadedStreamConsumer = new ThreadedStreamConsumer( forkClient );
@@ -640,10 +648,10 @@ public class ForkStarter
                 {
                     StackTraceWriter errorInFork = forkClient.getErrorInFork();
                     // noinspection ThrowFromFinallyBlock
-                    throw new RuntimeException( "There was an error in the forked process"
+                    throw new SurefireBooterForkException( "There was an error in the forked process"
                                                         + detail
                                                         + '\n'
-                                                        + errorInFork.writeTraceToString(), cause );
+                                                        + errorInFork.getThrowable().getLocalizedMessage(), cause );
                 }
                 if ( !forkClient.isSaidGoodBye() )
                 {
@@ -654,7 +662,7 @@ public class ForkStarter
                         testsInProgress += "\n" + test;
                     }
                     // noinspection ThrowFromFinallyBlock
-                    throw new RuntimeException(
+                    throw new SurefireBooterForkException(
                         "The forked VM terminated without properly saying goodbye. VM crash or System.exit called?"
                             + "\nCommand was " + cli.toString() + detail + errorCode + testsInProgress, cause );
                 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/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 898a165..46c747b 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
@@ -271,6 +271,7 @@ public class ForkClient
                             .warning( createConsoleMessage( remaining ) );
                     break;
                 default:
+                    LostCommandsDumpSingleton.getSingleton().dumpText( s, defaultReporterFactory );
                     log.warning( s );
             }
         }
@@ -278,15 +279,18 @@ public class ForkClient
         {
             // SUREFIRE-859
             log.warning( s );
+            LostCommandsDumpSingleton.getSingleton().dumpException( e, s, defaultReporterFactory );
         }
         catch ( NoSuchElementException e )
         {
             // SUREFIRE-859
             log.warning( s );
+            LostCommandsDumpSingleton.getSingleton().dumpException( e, s, defaultReporterFactory );
         }
         catch ( ReporterException e )
         {
-            throw new RuntimeException( e );
+            LostCommandsDumpSingleton.getSingleton().dumpException( e, s, defaultReporterFactory );
+            throw e;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/LostCommandsDumpSingleton.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/LostCommandsDumpSingleton.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/LostCommandsDumpSingleton.java
new file mode 100644
index 0000000..364d8c3
--- /dev/null
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/LostCommandsDumpSingleton.java
@@ -0,0 +1 @@
+package org.apache.maven.plugin.surefire.booterclient.output;

/*
 * 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.plugin.surefire.report.DefaultReporterFactory;
import org.apache.maven.surefire.util.internal.DumpF
 ileUtils;

import java.io.File;

/**
 * Dumps lost commands and caused exceptions in {@link ForkClient}.
 *
 * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
 * @since 2.19.2
 */
final class LostCommandsDumpSingleton
{
    private static final LostCommandsDumpSingleton SINGLETON = new LostCommandsDumpSingleton();

    private final String creationDate = DumpFileUtils.newFormattedDateFileName();

    private LostCommandsDumpSingleton()
    {
    }

    static LostCommandsDumpSingleton getSingleton()
    {
        return SINGLETON;
    }

    synchronized void dumpException( Throwable t, String msg, DefaultReporterFactory defaultReporterFactory )
    {
        File reportsDirectory = defaultReporterFactory.getReportsDirectory();
        File dumpFile = new File( reportsDirectory, creationDate + ".dumpstream" );
        DumpFileUtils.dumpException( t, msg, dumpFile );
    }

    synchronized void dumpException( Throwable t, DefaultReporterFactory defaultRepo
 rterFactory )
    {
        dumpException( t, null, defaultReporterFactory );
    }

    synchronized void dumpText( String msg, DefaultReporterFactory defaultReporterFactory )
    {
        File reportsDirectory = defaultReporterFactory.getReportsDirectory();
        File dumpFile = new File( reportsDirectory, creationDate + ".dumpstream" );
        DumpFileUtils.dumpText( msg, dumpFile );
    }
}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java
----------------------------------------------------------------------
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 24f5b3b..342e883 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
@@ -31,6 +31,7 @@ import org.apache.maven.surefire.report.RunStatistics;
 import org.apache.maven.surefire.report.StackTraceWriter;
 import org.apache.maven.surefire.suite.RunResult;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -100,6 +101,11 @@ public class DefaultReporterFactory
         return testSetRunListener;
     }
 
+    public File getReportsDirectory()
+    {
+        return reportConfiguration.getReportsDirectory();
+    }
+
     private ConsoleReporter createConsoleReporter()
     {
         return shouldReportToConsole() ? new ConsoleReporter( consoleLogger ) : NullConsoleReporter.INSTANCE;

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-surefire-plugin/src/site/apt/developing.apt.vm
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/apt/developing.apt.vm b/maven-surefire-plugin/src/site/apt/developing.apt.vm
index fcb1930..680201a 100644
--- a/maven-surefire-plugin/src/site/apt/developing.apt.vm
+++ b/maven-surefire-plugin/src/site/apt/developing.apt.vm
@@ -114,9 +114,9 @@ ForkedBooter#main
 
 * JDK Versions
 
-  The surefire booter is capable of booting all the way back to jdk1.5. Specifically
+  The surefire booter is capable of booting all the way back to jdk1.6. Specifically
   this means <<<surefire-api>>>, <<<surefire-booter>>>, <<<common-junit3>>> and <<<surefire-junit3>>> are
-  source/target 1.5. The plugin and several providers are 1.5.
+  source/target 1.6. The plugin and several providers are 1.6.
 
 * Provider Isolation
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-surefire-plugin/src/site/apt/examples/shutdown.apt.vm
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/apt/examples/shutdown.apt.vm b/maven-surefire-plugin/src/site/apt/examples/shutdown.apt.vm
index 9257c42..a546853 100644
--- a/maven-surefire-plugin/src/site/apt/examples/shutdown.apt.vm
+++ b/maven-surefire-plugin/src/site/apt/examples/shutdown.apt.vm
@@ -89,6 +89,7 @@ Shutdown of Forked JVM
 
 * Crashed forked JVM caused listing the crashed test(s)
 
-  After the JVM exited abruptly, the console lists the message <<<Crashed tests:>>> if the entire
-  test-set has not been yet completed. This happens if a test exited, killed JVM or segmentation fault crashed JVM.
+  After the JVM exited abruptly, the console lists the message <<<Crashed tests:>>> with a list of crashed tests if the
+  entire test-set has not been yet completed. This happens if a test exited, killed JVM or a segmentation fault crashed
+  JVM. In such cases you may be interested in dump files generated in reports directory, see {{{../faq.html#dumpfiles}FAQ}}.
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-surefire-plugin/src/site/apt/index.apt.vm
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/apt/index.apt.vm b/maven-surefire-plugin/src/site/apt/index.apt.vm
index 85c4d66..0ec361c 100644
--- a/maven-surefire-plugin/src/site/apt/index.apt.vm
+++ b/maven-surefire-plugin/src/site/apt/index.apt.vm
@@ -31,7 +31,7 @@
 Maven ${thisPlugin} Plugin
 
 
-  Requirements: Maven 2.2.1 or 3.x, and JDK 1.5 or higher. Due to wrong formatting of console text messages
+  Requirements: Maven 2.2.1 or 3.x, and JDK 1.6 or higher. Due to wrong formatting of console text messages
   in Maven Version prior to 3.1.0 it is highly recommended to use Maven 3.1.0 or higher.
 
 #{if}(${project.artifactId}=="maven-surefire-plugin")
@@ -81,7 +81,7 @@ mvn verify
 
   []
 
-  By default, these files are generated at <<<$\{basedir\}/target/${thisPlugin.toLowerCase()}-reports>>>.
+  By default, these files are generated in <<<$\{basedir\}/target/${thisPlugin.toLowerCase()}-reports/TEST-*.xml>>>.
 
   The schema for the ${thisPlugin} XML reports is available at
   {{{./xsd/${thisPlugin.toLowerCase()}-test-report.xsd}${thisPlugin} XML Report Schema}}.
@@ -89,6 +89,11 @@ mvn verify
   For an HTML format of the report, please see the
   {{{http://maven.apache.org/plugins/maven-surefire-report-plugin/}Maven Surefire Report Plugin}}.
 
+#{if}(${project.artifactId}=="maven-failsafe-plugin")
+  By default this plugin generates summary XML file at <<<$\{basedir\}/target/failsafe-reports/failsafe-summary.xml>>>
+  and the schema is available at {{{./xsd/failsafe-summary.xsd}Failsafe XML Summary Schema}}.
+#{end}
+
 * Goals Overview
 
 #{if}(${project.artifactId}=="maven-surefire-plugin")

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-surefire-plugin/src/site/fml/faq.fml
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/fml/faq.fml b/maven-surefire-plugin/src/site/fml/faq.fml
index de736dd..92cbb1d 100644
--- a/maven-surefire-plugin/src/site/fml/faq.fml
+++ b/maven-surefire-plugin/src/site/fml/faq.fml
@@ -108,15 +108,34 @@ under the License.
       </answer>
     </faq>
     <faq id="failsafe-jar">
-      <question>How maven-failsafe-plugin allows me to configure the jar file or classes to use</question>
+      <question>How maven-failsafe-plugin allows me to configure the jar file or classes to use?</question>
       <answer>
         <p>
-        By default maven-failsafe-plugin uses project artifact file if packaging is set to "jar" in pom.xml.
-        This can be modified and for instance set to main project classes if you use configuration parameter
+        By default maven-failsafe-plugin uses project artifact file in test classpath if packaging is set to "jar" in
+        pom.xml. This can be modified and for instance set to main project classes if you use configuration parameter
         "classesDirectory". This would mean that you set value "${project.build.outputDirectory}" for the parameter
         "classesDirectory" in the configuration of plugin.
         </p>
       </answer>
     </faq>
+    <faq id="dumpfiles">
+      <question>How to dump fatal errors and stack trace of plugin runtime if it fails?</question>
+      <answer>
+        <p>
+        By default <em>maven-failsafe-plugin</em> and <em>maven-surefire-plugin</em> dumps fatal errors in dump files
+        and these are located in <em>target/failsafe-reports</em> and <em>target/surefire-reports</em>.
+        Names of dump files are formatted as follows:
+        <br/>
+        <code>
+        <![CDATA[ [date]-jvmRun[N].dump]]><br/>
+        <![CDATA[ [date]-jvmRun[N].dumpstream]]><br/>
+        <![CDATA[ [date].dumpstream]]><br/>
+        </code>
+
+        Forked JVM process and plugin process communicate via std/out. If this channel is corrupted, for a whatever
+        reason, the dump of the corrupted stream appears in <em>*.dumpstream</em>.
+        </p>
+      </answer>
+    </faq>
   </part>
 </faqs>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-surefire-plugin/src/site/resources/xsd/bindings.xml
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/resources/xsd/bindings.xml b/maven-surefire-plugin/src/site/resources/xsd/bindings.xml
new file mode 100644
index 0000000..4e2d949
--- /dev/null
+++ b/maven-surefire-plugin/src/site/resources/xsd/bindings.xml
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
~ 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.
-->
<jxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
        version="2.0">
    <jxb:bi
 ndings schemaLocation="failsafe-summary.xsd">
        <jxb:bindings node="//xsd:simpleType[@name='errorType']/xsd:restriction/xsd:enumeration[@id='FAILURE']">
            <jxb:typesafeEnumMember name="FAILURE"/>
            <jxb:javaType name="java.lang.Integer"/>
        </jxb:bindings>
        <jxb:bindings node="//xsd:simpleType[@name='errorType']/xsd:restriction/xsd:enumeration[@id='NO_TESTS']">
            <jxb:typesafeEnumMember name="NO_TESTS"/>
            <jxb:javaType name="java.lang.Integer"/>
        </jxb:bindings>
    </jxb:bindings>
</jxb:bindings>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/maven-surefire-plugin/src/site/resources/xsd/failsafe-summary.xsd
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/resources/xsd/failsafe-summary.xsd b/maven-surefire-plugin/src/site/resources/xsd/failsafe-summary.xsd
new file mode 100644
index 0000000..dca134b
--- /dev/null
+++ b/maven-surefire-plugin/src/site/resources/xsd/failsafe-summary.xsd
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
~ 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.
-->
<xsd:schema version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="failsafe-summary">
        <xsd:complexType>
     
        <xsd:sequence>
                <xsd:element name="completed" type="xsd:int"/>
                <xsd:element name="errors" type="xsd:int"/>
                <xsd:element name="failures" type="xsd:int"/>
                <xsd:element name="skipped" type="xsd:int"/>
                <xsd:element name="failureMessage" type="xsd:string" nillable="true"/>
            </xsd:sequence>
            <xsd:attribute name="result" type="errorType" use="optional"/>
            <xsd:attribute name="timeout" type="xsd:boolean" use="required"/>
        </xsd:complexType>
    </xsd:element>
    <xsd:simpleType name="errorType">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration id="FAILURE" value="255"/>
            <xsd:enumeration id="NO_TESTS" value="254"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/303cc8ac/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java
index bdd6092..408e4a4 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java
@@ -22,9 +22,11 @@ package org.apache.maven.surefire.booter;
 import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger;
 import org.apache.maven.surefire.testset.TestSetFailedException;
+import org.apache.maven.surefire.util.internal.DumpFileUtils;
 
 import java.io.DataInputStream;
 import java.io.EOFException;
+import java.io.File;
 import java.io.IOException;
 import java.io.PrintStream;
 import java.util.Iterator;
@@ -85,6 +87,8 @@ public final class CommandReader
 
     private volatile ConsoleLogger logger = new NullConsoleLogger();
 
+    private volatile File dumpFile;
+
     private CommandReader()
     {
     }
@@ -99,6 +103,11 @@ public final class CommandReader
         return reader;
     }
 
+    public void setDumpFile( File dumpFile )
+    {
+        this.dumpFile = dumpFile;
+    }
+
     public CommandReader setShutdown( Shutdown shutdown )
     {
         this.shutdown = shutdown;
@@ -123,6 +132,7 @@ public final class CommandReader
             }
             catch ( InterruptedException e )
             {
+                DumpFileUtils.dumpException( e, dumpFile );
                 throw new TestSetFailedException( e.getLocalizedMessage() );
             }
         }
@@ -375,7 +385,9 @@ public final class CommandReader
                     Command command = decode( stdIn );
                     if ( command == null )
                     {
-                        logger.error( "[SUREFIRE] std/in stream corrupted: first sequence not recognized" );
+                        String errorMessage = "[SUREFIRE] std/in stream corrupted: first sequence not recognized";
+                        DumpFileUtils.dumpText( errorMessage, dumpFile );
+                        logger.error( errorMessage );
                         break;
                     }
                     else
@@ -411,6 +423,8 @@ public final class CommandReader
             }
             catch ( EOFException e )
             {
+                DumpFileUtils.dumpException( e, dumpFile );
+
                 CommandReader.this.state.set( TERMINATED );
                 if ( !isTestSetFinished )
                 {
@@ -420,6 +434,8 @@ public final class CommandReader
             }
             catch ( IOException e )
             {
+                DumpFileUtils.dumpException( e, dumpFile );
+
                 CommandReader.this.state.set( TERMINATED );
                 // If #stop() method is called, reader thread is interrupted and cause is InterruptedException.
                 if ( !( e.getCause() instanceof InterruptedException ) )