You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kr...@apache.org on 2012/11/11 18:53:26 UTC

[2/2] git commit: [SUREFIRE-926] Failure status incorrect with multiple providers.

[SUREFIRE-926] Failure status incorrect with multiple providers.

This fix reviews the general failure status and may fix other problems too


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

Branch: refs/heads/master
Commit: 53456de3d83447059382c5b8fa92a59094ab769e
Parents: 48a70d4
Author: Kristian Rosenvold <kr...@apache.org>
Authored: Fri Nov 9 07:51:35 2012 +0100
Committer: Kristian Rosenvold <kr...@gmail.com>
Committed: Fri Nov 9 12:18:10 2012 +0100

----------------------------------------------------------------------
 .../maven/plugin/failsafe/IntegrationTestMojo.java |   19 +-
 .../plugin/surefire/AbstractSurefireMojo.java      |  228 ++++++++-------
 .../org/apache/maven/plugin/surefire/Summary.java  |   88 ------
 .../maven/plugin/surefire/SurefireHelper.java      |   32 +-
 .../apache/maven/plugin/surefire/SummaryTest.java  |  104 -------
 .../maven/plugin/surefire/SurefirePlugin.java      |   34 +--
 .../org/apache/maven/surefire/suite/RunResult.java |   22 +--
 .../apache/maven/surefire/suite/RunResultTest.java |   37 ++-
 8 files changed, 181 insertions(+), 383 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/53456de3/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 f06fb6e..730e145 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
@@ -32,7 +32,6 @@ import java.util.List;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugin.surefire.AbstractSurefireMojo;
-import org.apache.maven.plugin.surefire.Summary;
 import org.apache.maven.plugin.surefire.booterclient.ChecksumCalculator;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
@@ -43,9 +42,10 @@ import org.apache.maven.surefire.booter.ProviderConfiguration;
 import org.apache.maven.surefire.failsafe.model.FailsafeSummary;
 import org.apache.maven.surefire.failsafe.model.io.xpp3.FailsafeSummaryXpp3Reader;
 import org.apache.maven.surefire.failsafe.model.io.xpp3.FailsafeSummaryXpp3Writer;
-import org.apache.maven.surefire.suite.RunResult;
 import org.apache.maven.shared.utils.ReaderFactory;
 
+import org.apache.maven.surefire.suite.RunResult;
+import org.apache.maven.surefire.util.NestedCheckedException;
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 
 import static org.apache.maven.shared.utils.io.IOUtil.close;
@@ -178,29 +178,28 @@ public class IntegrationTestMojo
     @Parameter( property = "encoding", defaultValue = "${project.reporting.outputEncoding}" )
     private String encoding;
 
-    protected void handleSummary( Summary summary )
+    protected void handleSummary(RunResult summary, NestedCheckedException firstForkException)
         throws MojoExecutionException, MojoFailureException
     {
-        FailsafeSummary failsafeSummary = createFailsafeSummaryFromSummary( summary );
+        FailsafeSummary failsafeSummary = createFailsafeSummaryFromSummary( summary, firstForkException );
         writeSummary( failsafeSummary );
     }
 
-    private FailsafeSummary createFailsafeSummaryFromSummary( Summary summary )
+    private FailsafeSummary createFailsafeSummaryFromSummary(RunResult summary, NestedCheckedException firstForkException)
     {
         FailsafeSummary failsafeSummary = new FailsafeSummary();
-        if ( summary.isErrorFree() )
+        if ( firstForkException == null )
         {
-            RunResult result = summary.getResultOfLastSuccessfulRun();
-            if ( result != null )
+            if ( summary != null )
             {
-                failsafeSummary.setResult( result.getForkedProcessCode() );
+                failsafeSummary.setResult( summary.getForkedProcessCode() );
             }
         }
         else
         {
             failsafeSummary.setResult( ProviderConfiguration.TESTS_FAILED_EXIT_CODE );
             //noinspection ThrowableResultOfMethodCallIgnored
-            failsafeSummary.setException( summary.getFirstException().getMessage() );
+            failsafeSummary.setException( firstForkException.getMessage() );
         }
         return failsafeSummary;
     }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/53456de3/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
index a68a735..c869801 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
@@ -64,6 +64,7 @@ import org.apache.maven.surefire.testset.RunOrderParameters;
 import org.apache.maven.surefire.testset.TestArtifactInfo;
 import org.apache.maven.surefire.testset.TestRequest;
 import org.apache.maven.surefire.util.DefaultScanResult;
+import org.apache.maven.surefire.util.NestedCheckedException;
 import org.apache.maven.surefire.util.NestedRuntimeException;
 import org.apache.maven.surefire.util.RunOrder;
 import org.apache.maven.toolchain.Toolchain;
@@ -579,7 +580,7 @@ public abstract class AbstractSurefireMojo
                     throw new MojoFailureException(
                         "No tests were executed!  (Set -DfailIfNoTests=false to ignore this error.)" );
                 }
-                handleSummary( Summary.noTestsRun() );
+                handleSummary( RunResult.noTestsRun(), null );
                 return;
             }
             logReportsDirectory();
@@ -645,9 +646,34 @@ public abstract class AbstractSurefireMojo
         throws MojoExecutionException, MojoFailureException
     {
 
-        Summary summary = executeAllProviders( scanResult );
+        List<ProviderInfo> providers = createProviders();
+
+        RunResult current = RunResult.noTestsRun();
 
-        handleSummary( summary );
+        NestedCheckedException firstForkException = null;
+        for ( ProviderInfo provider : providers )
+        {
+            try
+            {
+                current = current.aggregate( executeProvider( provider, scanResult ) );
+            }
+            catch ( SurefireBooterForkException e )
+            {
+                if ( firstForkException == null )
+                {
+                    firstForkException = e;
+                }
+            }
+            catch ( SurefireExecutionException e )
+            {
+                if ( firstForkException == null )
+                {
+                    firstForkException = e;
+                }
+            }
+
+        }
+        handleSummary( current, firstForkException );
     }
 
 
@@ -661,27 +687,14 @@ public abstract class AbstractSurefireMojo
     protected List<ProviderInfo> createProviders()
         throws MojoFailureException, MojoExecutionException
     {
-            final Artifact junitDepArtifact = getJunitDepArtifact();
-            ProviderList wellKnownProviders =
-                new ProviderList( new DynamicProviderInfo( null ), new TestNgProviderInfo( getTestNgArtifact() ),
-                                  new JUnitCoreProviderInfo( getJunitArtifact(), junitDepArtifact ),
-                                  new JUnit4ProviderInfo( getJunitArtifact(), junitDepArtifact ),
-                                  new JUnit3ProviderInfo() );
+        final Artifact junitDepArtifact = getJunitDepArtifact();
+        ProviderList wellKnownProviders =
+            new ProviderList( new DynamicProviderInfo( null ), new TestNgProviderInfo( getTestNgArtifact() ),
+                              new JUnitCoreProviderInfo( getJunitArtifact(), junitDepArtifact ),
+                              new JUnit4ProviderInfo( getJunitArtifact(), junitDepArtifact ),
+                              new JUnit3ProviderInfo() );
 
-            return wellKnownProviders.resolve( getLog() );
-    }
-
-    private Summary executeAllProviders( DefaultScanResult scanResult )
-        throws MojoExecutionException, MojoFailureException
-    {
-        List<ProviderInfo> providers = createProviders();
-        Summary summary = new Summary();
-
-        for ( ProviderInfo provider : providers )
-        {
-            executeProvider( provider, scanResult, summary );
-        }
-        return summary;
+        return wellKnownProviders.resolve( getLog() );
     }
 
     private SurefireProperties setupProperties()
@@ -703,58 +716,46 @@ public abstract class AbstractSurefireMojo
         return result;
     }
 
-    private void executeProvider( ProviderInfo provider, DefaultScanResult scanResult, Summary summary )
-        throws MojoExecutionException, MojoFailureException
+    private RunResult executeProvider( ProviderInfo provider, DefaultScanResult scanResult )
+        throws MojoExecutionException, MojoFailureException, SurefireExecutionException, SurefireBooterForkException
     {
         SurefireProperties effectiveProperties = setupProperties();
-        summary.reportForkConfiguration( isForking() );
         ClassLoaderConfiguration classLoaderConfiguration = getClassLoaderConfiguration( isForking() );
 
-        try
+        RunOrderParameters runOrderParameters =
+            new RunOrderParameters( getRunOrder(), getStatisticsFileName( getConfigChecksum() ) );
+
+        final RunResult result;
+        if ( isForkModeNever() )
         {
-            RunOrderParameters runOrderParameters =
-                new RunOrderParameters( getRunOrder(), getStatisticsFileName( getConfigChecksum() ) );
+            effectiveProperties.copyToSystemProperties();
+            InPluginVMSurefireStarter surefireStarter =
+                createInprocessStarter( provider, classLoaderConfiguration, runOrderParameters );
+            result = surefireStarter.runSuitesInProcess( scanResult );
+        }
+        else
+        {
+            ForkConfiguration forkConfiguration = getForkConfiguration();
+            if ( getLog().isDebugEnabled() )
+            {
+                showMap( getEnvironmentVariables(), "environment variable" );
+            }
 
-            final RunResult result;
-            if ( isForkModeNever() )
+            Properties originalSystemProperties = (Properties) System.getProperties().clone();
+            try
             {
-                effectiveProperties.copyToSystemProperties();
-                InPluginVMSurefireStarter surefireStarter =
-                    createInprocessStarter( provider, classLoaderConfiguration, runOrderParameters );
-                result = surefireStarter.runSuitesInProcess( scanResult );
+                ForkStarter forkStarter =
+                    createForkStarter( provider, forkConfiguration, classLoaderConfiguration, runOrderParameters,
+                                       effectiveProperties );
+                result = forkStarter.run( effectiveProperties, scanResult, getEffectiveForkMode() );
             }
-            else
+            finally
             {
-                ForkConfiguration forkConfiguration = getForkConfiguration();
-                if ( getLog().isDebugEnabled() )
-                {
-                    showMap( getEnvironmentVariables(), "environment variable" );
-                }
-
-                Properties originalSystemProperties = (Properties) System.getProperties().clone();
-                try
-                {
-                    ForkStarter forkStarter =
-                        createForkStarter( provider, forkConfiguration, classLoaderConfiguration, runOrderParameters,
-                                           effectiveProperties );
-                    result = forkStarter.run( effectiveProperties, scanResult, getEffectiveForkMode() );
-                }
-                finally
-                {
-                    System.setProperties( originalSystemProperties );
-                    cleanupForkConfiguration( forkConfiguration );
-                }
+                System.setProperties( originalSystemProperties );
+                cleanupForkConfiguration( forkConfiguration );
             }
-            summary.registerRunResult( result );
-        }
-        catch ( SurefireBooterForkException e )
-        {
-            summary.registerException( e );
-        }
-        catch ( SurefireExecutionException e )
-        {
-            summary.registerException( e );
         }
+        return result;
     }
 
     protected void cleanupForkConfiguration( ForkConfiguration forkConfiguration )
@@ -773,7 +774,7 @@ public abstract class AbstractSurefireMojo
         }
     }
 
-    protected abstract void handleSummary( Summary summary )
+    protected abstract void handleSummary( RunResult summary, NestedCheckedException firstForkException )
         throws MojoExecutionException, MojoFailureException;
 
     protected void logReportsDirectory()
@@ -880,7 +881,7 @@ public abstract class AbstractSurefireMojo
         return isForkModeNever( getEffectiveForkMode() );
     }
 
-    static boolean isForkModeNever(String forkMode)
+    static boolean isForkModeNever( String forkMode )
     {
         return ForkConfiguration.FORK_NEVER.equals( forkMode );
     }
@@ -894,7 +895,7 @@ public abstract class AbstractSurefireMojo
     {
         String forkMode1 = getForkMode();
 
-        if ( toolchain != null && isForkModeNever(forkMode1) )
+        if ( toolchain != null && isForkModeNever( forkMode1 ) )
         {
             return ForkConfiguration.FORK_ONCE;
         }
@@ -1061,7 +1062,7 @@ public abstract class AbstractSurefireMojo
     void logClasspath( Classpath classpath, String descriptor )
     {
         getLog().debug( descriptor + " classpath:" );
-        @SuppressWarnings("unchecked") final List<String> classPath = classpath.getClassPath();
+        @SuppressWarnings( "unchecked" ) final List<String> classPath = classpath.getClassPath();
         for ( String classpathElement : classPath )
         {
             if ( classpathElement == null )
@@ -1144,7 +1145,7 @@ public abstract class AbstractSurefireMojo
 
             if ( plugin != null )
             {
-                @SuppressWarnings("rawtypes") List executions = plugin.getExecutions();
+                @SuppressWarnings( "rawtypes" ) List executions = plugin.getExecutions();
                 return executions != null && executions.size() > 1;
             }
         }
@@ -1392,7 +1393,7 @@ public abstract class AbstractSurefireMojo
     {
         // A tribute to Linus Torvalds
         String configChecksum = getConfigChecksum();
-        @SuppressWarnings("unchecked") Map<String, String> pluginContext = getPluginContext();
+        @SuppressWarnings( "unchecked" ) Map<String, String> pluginContext = getPluginContext();
         if ( pluginContext.containsKey( configChecksum ) )
         {
             getLog().info( "Skipping execution of surefire because it has already been run for this configuration" );
@@ -1432,7 +1433,7 @@ public abstract class AbstractSurefireMojo
 
         classpath.add( getClassesDirectory().getAbsolutePath() );
 
-        @SuppressWarnings("unchecked") Set<Artifact> classpathArtifacts = getProject().getArtifacts();
+        @SuppressWarnings( "unchecked" ) Set<Artifact> classpathArtifacts = getProject().getArtifacts();
 
         if ( getClasspathDependencyScopeExclude() != null && !getClasspathDependencyScopeExclude().equals( "" ) )
         {
@@ -1667,24 +1668,29 @@ public abstract class AbstractSurefireMojo
     void warnIfDefunctGroupsCombinations()
         throws MojoFailureException, MojoExecutionException
     {
-        if (isAnyGroupsSelected()){
-            if (getTestNgArtifact() != null){
+        if ( isAnyGroupsSelected() )
+        {
+            if ( getTestNgArtifact() != null )
+            {
                 return;
             }
             Artifact junitArtifact = getJunitArtifact();
             boolean junit47Compatible = isJunit47Compatible( junitArtifact );
-            if (junit47Compatible )
+            if ( junit47Compatible )
             {
                 return;
             }
-            if (junitArtifact != null && !junit47Compatible ){
-                throw new MojoFailureException("groups/excludedGroups are specified but JUnit version on classpath"
-                                                   + " is too old to support groups. Check your dependency:tree to see if your project is picking up an old junit version");
+            if ( junitArtifact != null && !junit47Compatible )
+            {
+                throw new MojoFailureException( "groups/excludedGroups are specified but JUnit version on classpath"
+                                                    + " is too old to support groups. Check your dependency:tree to see if your project is picking up an old junit version" );
             }
-            throw new MojoFailureException("groups/excludedGroups require TestNG or JUnit48+ on project test classpath");
+            throw new MojoFailureException(
+                "groups/excludedGroups require TestNG or JUnit48+ on project test classpath" );
 
         }
     }
+
     class TestNgProviderInfo
         implements ProviderInfo
     {
@@ -1912,7 +1918,7 @@ public abstract class AbstractSurefireMojo
         return systemProperties;
     }
 
-    @SuppressWarnings({ "UnusedDeclaration", "deprecation" })
+    @SuppressWarnings( { "UnusedDeclaration", "deprecation" } )
     public void setSystemProperties( Properties systemProperties )
     {
         this.systemProperties = systemProperties;
@@ -1923,7 +1929,7 @@ public abstract class AbstractSurefireMojo
         return systemPropertyVariables;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setSystemPropertyVariables( Map<String, String> systemPropertyVariables )
     {
         this.systemPropertyVariables = systemPropertyVariables;
@@ -1934,7 +1940,7 @@ public abstract class AbstractSurefireMojo
         return systemPropertiesFile;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setSystemPropertiesFile( File systemPropertiesFile )
     {
         this.systemPropertiesFile = systemPropertiesFile;
@@ -1955,7 +1961,7 @@ public abstract class AbstractSurefireMojo
         return pluginArtifactMap;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setPluginArtifactMap( Map<String, Artifact> pluginArtifactMap )
     {
         this.pluginArtifactMap = pluginArtifactMap;
@@ -1966,7 +1972,7 @@ public abstract class AbstractSurefireMojo
         return projectArtifactMap;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setProjectArtifactMap( Map<String, Artifact> projectArtifactMap )
     {
         this.projectArtifactMap = projectArtifactMap;
@@ -1978,7 +1984,7 @@ public abstract class AbstractSurefireMojo
         return reportNameSuffix;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setReportNameSuffix( String reportNameSuffix )
     {
         this.reportNameSuffix = reportNameSuffix;
@@ -1990,7 +1996,7 @@ public abstract class AbstractSurefireMojo
         return redirectTestOutputToFile;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setRedirectTestOutputToFile( boolean redirectTestOutputToFile )
     {
         this.redirectTestOutputToFile = redirectTestOutputToFile;
@@ -2012,7 +2018,7 @@ public abstract class AbstractSurefireMojo
         return forkMode;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setForkMode( String forkMode )
     {
         this.forkMode = forkMode;
@@ -2028,7 +2034,7 @@ public abstract class AbstractSurefireMojo
         return argLine;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setArgLine( String argLine )
     {
         this.argLine = argLine;
@@ -2040,7 +2046,7 @@ public abstract class AbstractSurefireMojo
         return environmentVariables;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setEnvironmentVariables( Map<String, String> environmentVariables )
     {
         this.environmentVariables = environmentVariables;
@@ -2051,7 +2057,7 @@ public abstract class AbstractSurefireMojo
         return workingDirectory;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setWorkingDirectory( File workingDirectory )
     {
         this.workingDirectory = workingDirectory;
@@ -2062,7 +2068,7 @@ public abstract class AbstractSurefireMojo
         return childDelegation;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setChildDelegation( boolean childDelegation )
     {
         this.childDelegation = childDelegation;
@@ -2073,7 +2079,7 @@ public abstract class AbstractSurefireMojo
         return groups;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setGroups( String groups )
     {
         this.groups = groups;
@@ -2084,7 +2090,7 @@ public abstract class AbstractSurefireMojo
         return excludedGroups;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setExcludedGroups( String excludedGroups )
     {
         this.excludedGroups = excludedGroups;
@@ -2095,7 +2101,7 @@ public abstract class AbstractSurefireMojo
         return suiteXmlFiles;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setSuiteXmlFiles( File[] suiteXmlFiles )
     {
         this.suiteXmlFiles = suiteXmlFiles;
@@ -2106,7 +2112,7 @@ public abstract class AbstractSurefireMojo
         return junitArtifactName;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setJunitArtifactName( String junitArtifactName )
     {
         this.junitArtifactName = junitArtifactName;
@@ -2117,7 +2123,7 @@ public abstract class AbstractSurefireMojo
         return testNGArtifactName;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setTestNGArtifactName( String testNGArtifactName )
     {
         this.testNGArtifactName = testNGArtifactName;
@@ -2128,7 +2134,7 @@ public abstract class AbstractSurefireMojo
         return threadCount;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setThreadCount( int threadCount )
     {
         this.threadCount = threadCount;
@@ -2139,7 +2145,7 @@ public abstract class AbstractSurefireMojo
         return perCoreThreadCount;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setPerCoreThreadCount( boolean perCoreThreadCount )
     {
         this.perCoreThreadCount = perCoreThreadCount;
@@ -2150,7 +2156,7 @@ public abstract class AbstractSurefireMojo
         return useUnlimitedThreads;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setUseUnlimitedThreads( boolean useUnlimitedThreads )
     {
         this.useUnlimitedThreads = useUnlimitedThreads;
@@ -2161,7 +2167,7 @@ public abstract class AbstractSurefireMojo
         return parallel;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setParallel( String parallel )
     {
         this.parallel = parallel;
@@ -2172,7 +2178,7 @@ public abstract class AbstractSurefireMojo
         return trimStackTrace;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setTrimStackTrace( boolean trimStackTrace )
     {
         this.trimStackTrace = trimStackTrace;
@@ -2183,7 +2189,7 @@ public abstract class AbstractSurefireMojo
         return artifactResolver;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setArtifactResolver( ArtifactResolver artifactResolver )
     {
         this.artifactResolver = artifactResolver;
@@ -2194,7 +2200,7 @@ public abstract class AbstractSurefireMojo
         return artifactFactory;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setArtifactFactory( ArtifactFactory artifactFactory )
     {
         this.artifactFactory = artifactFactory;
@@ -2205,7 +2211,7 @@ public abstract class AbstractSurefireMojo
         return remoteRepositories;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setRemoteRepositories( List<ArtifactRepository> remoteRepositories )
     {
         this.remoteRepositories = remoteRepositories;
@@ -2216,7 +2222,7 @@ public abstract class AbstractSurefireMojo
         return metadataSource;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setMetadataSource( ArtifactMetadataSource metadataSource )
     {
         this.metadataSource = metadataSource;
@@ -2228,7 +2234,7 @@ public abstract class AbstractSurefireMojo
         return disableXmlReport;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setDisableXmlReport( boolean disableXmlReport )
     {
         this.disableXmlReport = disableXmlReport;
@@ -2253,7 +2259,7 @@ public abstract class AbstractSurefireMojo
         return isEnableAssertions();
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setEnableAssertions( boolean enableAssertions )
     {
         this.enableAssertions = enableAssertions;
@@ -2264,7 +2270,7 @@ public abstract class AbstractSurefireMojo
         return session;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setSession( MavenSession session )
     {
         this.session = session;
@@ -2275,7 +2281,7 @@ public abstract class AbstractSurefireMojo
         return objectFactory;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setObjectFactory( String objectFactory )
     {
         this.objectFactory = objectFactory;
@@ -2286,7 +2292,7 @@ public abstract class AbstractSurefireMojo
         return toolchainManager;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setToolchainManager( ToolchainManager toolchainManager )
     {
         this.toolchainManager = toolchainManager;
@@ -2302,7 +2308,7 @@ public abstract class AbstractSurefireMojo
         return runOrder;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setRunOrder( String runOrder )
     {
         this.runOrder = runOrder;
@@ -2318,7 +2324,7 @@ public abstract class AbstractSurefireMojo
         return project;
     }
 
-    @SuppressWarnings("UnusedDeclaration")
+    @SuppressWarnings( "UnusedDeclaration" )
     public void setProject( MavenProject project )
     {
         this.project = project;

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/53456de3/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/Summary.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/Summary.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/Summary.java
deleted file mode 100644
index b758e75..0000000
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/Summary.java
+++ /dev/null
@@ -1,88 +0,0 @@
-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.apache.maven.surefire.suite.RunResult;
-
-public class Summary
-{
-    private boolean forking = false;
-
-    private RunResult runResult;
-
-    private Exception exception;
-
-    public Summary()
-    {
-    }
-
-    public Summary( RunResult runResult )
-    {
-        this.runResult = runResult;
-    }
-
-    public void reportForkConfiguration( boolean isForking )
-    {
-        forking = isForking;
-    }
-
-    public void registerException( Exception exception )
-    {
-        if ( this.exception == null )
-        {
-            this.exception = exception;
-        }
-    }
-
-    public void registerRunResult( RunResult result )
-    {
-        runResult = result;
-    }
-
-    public boolean isErrorFree()
-    {
-        return exception == null;
-    }
-
-    public boolean isFailureOrTimeout()
-    {
-        return runResult != null && runResult.isFailureOrTimeout();
-    }
-
-    public boolean isForking()
-    {
-        return forking;
-    }
-
-    public Exception getFirstException()
-    {
-        return exception;
-    }
-
-    public RunResult getResultOfLastSuccessfulRun()
-    {
-        return runResult;
-    }
-
-    public static Summary noTestsRun(){
-        return new Summary(RunResult.noTestsRun());
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/53456de3/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 7f6a71c..c431f0c 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
@@ -19,6 +19,7 @@ package org.apache.maven.plugin.surefire;
  * under the License.
  */
 
+import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.surefire.booter.ProviderConfiguration;
@@ -41,10 +42,9 @@ public final class SurefireHelper
     // Todo: Fix the duplication, probably by making failsafe relate to a "RunResult" too.
 
     public static void reportExecution( SurefireReportParameters reportParameters, RunResult result, Log log )
-        throws MojoFailureException
+        throws MojoFailureException, MojoExecutionException
     {
 
-        String msg;
 
         if ( result.getCompletedCount() == 0 )
         {
@@ -52,27 +52,20 @@ public final class SurefireHelper
             {
                 return;
             }
-            // TODO: i18n
             throw new MojoFailureException(
                 "No tests were executed!  (Set -DfailIfNoTests=false to ignore this error.)" );
         }
 
-        if ( result.isErrorFree() )
+        boolean timeoutOrOtherFailure = result.isFailureOrTimeout();
+        if ( !timeoutOrOtherFailure && result.isErrorFree() )
         {
             return;
         }
 
-        if ( result.isFailureOrTimeout() )
-        {
-            msg = "There was a timeout or other error in the fork";
-        }
-        else
-        {
-            // TODO: i18n
-            msg = "There are test failures.\n\nPlease refer to " + reportParameters.getReportsDirectory()
-                + " for the individual test results.";
-
-        }
+        String msg = timeoutOrOtherFailure ?
+                "There was a timeout or other error in the fork" :
+                "There are test failures.\n\nPlease refer to " + reportParameters.getReportsDirectory()
+                        + " for the individual test results.";
 
         if ( reportParameters.isTestFailureIgnore() )
         {
@@ -80,7 +73,14 @@ public final class SurefireHelper
         }
         else
         {
-            throw new MojoFailureException( msg );
+            if (result.isFailure())
+            {
+                throw new MojoExecutionException(msg );
+            }
+            else
+            {
+                throw new MojoFailureException( msg );
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/53456de3/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SummaryTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SummaryTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SummaryTest.java
deleted file mode 100644
index 74c6881..0000000
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SummaryTest.java
+++ /dev/null
@@ -1,104 +0,0 @@
-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.apache.maven.plugin.surefire.booterclient.ForkConfiguration;
-import org.apache.maven.surefire.suite.RunResult;
-
-import junit.framework.TestCase;
-
-public class SummaryTest
-    extends TestCase
-{
-    Summary summary = new Summary();
-
-    public void testEmptySummaryShouldBeErrorFree()
-    {
-        assertTrue( summary.isErrorFree() );
-    }
-
-    public void testSummaryShouldBeErrorFreeAfterAddingAnException()
-    {
-        summary.registerException( new RuntimeException() );
-        assertFalse( summary.isErrorFree() );
-    }
-
-    public void testEmptySummaryShouldHaveNoFailureOrTimeOut()
-    {
-        assertFalse( summary.isFailureOrTimeout() );
-    }
-
-    public void testSummaryReturnsFailureOrTimeOutStateOfLastRun()
-    {
-        RunResult resultWithoutFailure = new RunResult( 0, 0, 0, 0, false, false );
-        RunResult resultWithFailure = new RunResult( 0, 0, 0, 0, true, true );
-        summary.registerRunResult( resultWithoutFailure );
-        summary.registerRunResult( resultWithFailure );
-        assertTrue( summary.isFailureOrTimeout() );
-    }
-
-    public void testEmptySummaryHasNoFirstException()
-    {
-        assertNull( summary.getFirstException() );
-    }
-
-    public void testSummaryReturnsTheFirstOfTwoExceptions()
-    {
-        Exception exceptionOne = new RuntimeException();
-        Exception exceptionTwo = new RuntimeException();
-        summary.registerException( exceptionOne );
-        summary.registerException( exceptionTwo );
-        assertEquals( "Wrong exception.", exceptionOne, summary.getFirstException() );
-    }
-
-    public void testEmptySummaryHasNoResultOfLastSuccessfulRun()
-    {
-        assertNull( summary.getResultOfLastSuccessfulRun() );
-    }
-
-    public void testSummaryReturnsTheSecondOfTwoResult()
-    {
-        RunResult resultOne = new RunResult( 0, 0, 0, 0 );
-        RunResult resultTwo = new RunResult( 0, 0, 0, 0 );
-        summary.registerRunResult( resultOne );
-        summary.registerRunResult( resultTwo );
-        assertEquals( "Wrong exception.", resultTwo, summary.getResultOfLastSuccessfulRun() );
-    }
-
-    public void testEmptySummaryIsNotForking()
-    {
-        assertFalse( summary.isForking() );
-    }
-
-    public void testSummaryIsForkingIfTheLastConfigurationIsForking()
-    {
-        summary.reportForkConfiguration(false);
-        summary.reportForkConfiguration(true);
-        assertTrue( summary.isForking() );
-    }
-
-    public void testSummaryIsNotForkingIfTheLastConfigurationIsNotForking()
-    {
-        summary.reportForkConfiguration(true);
-        summary.reportForkConfiguration(false);
-        assertFalse( summary.isForking() );
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/53456de3/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
index 9f90b52..5adcdcf 100644
--- a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
+++ b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
@@ -28,6 +28,7 @@ import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.surefire.suite.RunResult;
+import org.apache.maven.surefire.util.NestedCheckedException;
 import org.apache.maven.surefire.util.internal.StringUtils;
 
 /**
@@ -143,38 +144,31 @@ public class SurefirePlugin
     @Parameter( property = "surefire.useManifestOnlyJar", defaultValue = "true" )
     private boolean useManifestOnlyJar;
 
-    protected void handleSummary( Summary summary )
+    protected void handleSummary(RunResult summary, NestedCheckedException firstForkException)
         throws MojoExecutionException, MojoFailureException
     {
-        assertNoException( summary );
-        assertNoFailureOrTimeout( summary );
-        writeSummary( summary );
-    }
+        assertNoException( firstForkException );
+        assertNoFailureOrTimeout( firstForkException );  // todo: These seem identical ??
 
-    private void assertNoException( Summary summary )
-        throws MojoExecutionException
-    {
-        if ( !summary.isErrorFree() )
-        {
-            Exception cause = summary.getFirstException();
-            throw new MojoExecutionException( cause.getMessage(), cause );
-        }
+        SurefireHelper.reportExecution(this, summary, getLog() );
     }
 
-    private void assertNoFailureOrTimeout( Summary summary )
-        throws MojoExecutionException
+    private void assertNoException( NestedCheckedException firstForkException )
+        throws MojoFailureException
     {
-        if ( summary.isFailureOrTimeout() )
+        if ( firstForkException != null )
         {
-            throw new MojoExecutionException( "Failure or timeout" );
+            throw new MojoFailureException( firstForkException.getMessage(), firstForkException );
         }
     }
 
-    private void writeSummary( Summary summary )
+    private void assertNoFailureOrTimeout( NestedCheckedException summary )
         throws MojoFailureException
     {
-        RunResult result = summary.getResultOfLastSuccessfulRun();
-        SurefireHelper.reportExecution( this, result, getLog() );
+        if ( summary != null )
+        {
+            throw new MojoFailureException( "Failure or timeout" );
+        }
     }
 
     protected boolean isSkipExecution()

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/53456de3/surefire-api/src/main/java/org/apache/maven/surefire/suite/RunResult.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/suite/RunResult.java b/surefire-api/src/main/java/org/apache/maven/surefire/suite/RunResult.java
index 5f38436..d6291d8 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/suite/RunResult.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/suite/RunResult.java
@@ -19,8 +19,6 @@ package org.apache.maven.surefire.suite;
  * under the License.
  */
 
-import java.util.StringTokenizer;
-
 /**
  * Represents a test-run-result; this may be from a single test run or an aggregated result.
  *
@@ -90,29 +88,13 @@ public class RunResult
         return completedCount == 0 ? NO_TESTS : isErrorFree() ? SUCCESS : FAILURE;
     }
 
+    /* Indicates if the tests are error free */
     public boolean isErrorFree()
     {
         return getFailures() == 0 && getErrors() == 0;
     }
 
-    public String getAsString()
-    {
-        return getCompletedCount() + "," + getErrors() + "," + getFailures() + "," + getSkipped() + "," + isFailure()
-            + "," + isTimeout();
-    }
-
-    public static RunResult fromString( String string )
-    {
-        StringTokenizer strTok = new StringTokenizer( string, "," );
-        int completed = Integer.parseInt( strTok.nextToken() );
-        int errors = Integer.parseInt( strTok.nextToken() );
-        int failures = Integer.parseInt( strTok.nextToken() );
-        int skipped = Integer.parseInt( strTok.nextToken() );
-        boolean isFailure = Boolean.parseBoolean( strTok.nextToken() );
-        boolean isTimeout = Boolean.parseBoolean( strTok.nextToken() );
-        return new RunResult( completed, errors, failures, skipped, isFailure, isTimeout );
-    }
-
+    /* Indicates test timeout or technical failure */
     public boolean isFailureOrTimeout()
     {
         return this.timeout || this.failure;

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/53456de3/surefire-api/src/test/java/org/apache/maven/surefire/suite/RunResultTest.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/suite/RunResultTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/suite/RunResultTest.java
index 1c94a18..32fe232 100644
--- a/surefire-api/src/test/java/org/apache/maven/surefire/suite/RunResultTest.java
+++ b/surefire-api/src/test/java/org/apache/maven/surefire/suite/RunResultTest.java
@@ -27,30 +27,39 @@ import junit.framework.TestCase;
 public class RunResultTest
     extends TestCase
 {
-    public void testGetAsString()
-        throws Exception
+
+    public void testEmptySummaryShouldBeErrorFree()
     {
+        RunResult summary = RunResult.noTestsRun();
+        assertTrue( summary.isErrorFree() );
+    }
 
+    public void testFailuresInFirstRun()
+    {
+        RunResult resultOne = new RunResult( 10, 1, 3, 2 );
+        RunResult resultTwo = new RunResult( 20, 0, 0, 0 );
+        assertFalse( resultOne.aggregate( resultTwo ).isErrorFree() );
     }
 
-    public void testFromString()
-        throws Exception
+
+    public void testAggregatedValues()
     {
-        RunResult original = new RunResult( 4, 3, 2, 1, true, false );
-        final String asString = original.getAsString();
-        final RunResult runResult = RunResult.fromString( asString );
-        verifySame( original, runResult );
+        RunResult simple = getSimpleAggregate();
+        assertEquals( 20, simple.getCompletedCount() );
+        assertEquals( 3, simple.getErrors() );
+        assertEquals( 7, simple.getFailures() );
+        assertEquals( 4, simple.getSkipped() );
+
     }
 
-    public void testFromString2()
-        throws Exception
+    private RunResult getSimpleAggregate()
     {
-        RunResult original = new RunResult( 5, 6, 7, 8, false, true );
-        final String asString = original.getAsString();
-        final RunResult runResult = RunResult.fromString( asString );
-        verifySame( original, runResult );
+        RunResult resultOne = new RunResult( 10, 1, 3, 2 );
+        RunResult resultTwo = new RunResult( 10, 2, 4, 2 );
+        return resultOne.aggregate( resultTwo );
     }
 
+
     private void verifySame( RunResult original, RunResult runResult )
     {
         assertEquals( original.getCompletedCount(), runResult.getCompletedCount() );