[SUREFIRE-1287] Improve logging to understand why test run failed and report the right failed category
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/e0ce6cb0 Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/e0ce6cb0 Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/e0ce6cb0 Branch: refs/heads/junit5 Commit: e0ce6cb021d42d021704f77a689e3b663aebf084 Parents: 4b43807 Author: Tibor17 <tibo...@lycos.com> Authored: Tue Oct 4 01:06:18 2016 +0200 Committer: Tibor17 <tibo...@lycos.com> Committed: Tue Oct 4 01:06:18 2016 +0200 ---------------------------------------------------------------------- .../surefire/booterclient/ForkStarter.java | 33 +++++++++---- .../booterclient/output/ForkClient.java | 1 + .../maven/surefire/booter/ForkedBooter.java | 6 +-- .../booter/SurefireBooterForkException.java | 51 ++++++++++++++++++++ 4 files changed, 79 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/e0ce6cb0/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 57c31b6..2eb8259 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 @@ -567,7 +567,7 @@ public class ForkStarter log.debug( "Forking command line: " + cli ); RunResult runResult = null; - + SurefireBooterForkException booterForkException = null; try { CommandLineCallable future = @@ -585,13 +585,17 @@ public class ForkStarter } else if ( result != SUCCESS ) { - throw new SurefireBooterForkException( "Error occurred in starting fork, check output in log" ); + booterForkException = + new SurefireBooterForkException( "Error occurred in starting fork, check output in log" ); } } catch ( CommandLineException e ) { runResult = failure( forkClient.getDefaultReporterFactory().getGlobalRunStatistics().getRunResult(), e ); - throw new SurefireBooterForkException( "Error while executing forked tests.", e.getCause() ); + String cliErr = e.getLocalizedMessage(); + Throwable cause = e.getCause(); + booterForkException = + new SurefireBooterForkException( "Error while executing forked tests.", cliErr, cause, runResult ); } finally { @@ -600,25 +604,36 @@ public class ForkStarter { runResult = forkClient.getDefaultReporterFactory().getGlobalRunStatistics().getRunResult(); } + forkClient.close( runResult.isTimeout() ); if ( !runResult.isTimeout() ) { - StackTraceWriter errorInFork = forkClient.getErrorInFork(); - if ( errorInFork != null ) + Throwable cause = booterForkException == null ? null : booterForkException.getCause(); + String detail = booterForkException == null ? "" : "\n" + booterForkException.getMessage(); + + if ( forkClient.isErrorInFork() ) { + StackTraceWriter errorInFork = forkClient.getErrorInFork(); // noinspection ThrowFromFinallyBlock - throw new RuntimeException( - "There was an error in the forked process\n" + errorInFork.writeTraceToString() ); + throw new RuntimeException( "There was an error in the forked process" + + detail + + '\n' + + errorInFork.writeTraceToString(), cause ); } if ( !forkClient.isSaidGoodBye() ) { // noinspection ThrowFromFinallyBlock throw new RuntimeException( "The forked VM terminated without properly saying goodbye. VM crash or System.exit called?" - + "\nCommand was " + cli.toString() ); + + "\nCommand was " + cli.toString() + detail, cause ); } } - forkClient.close( runResult.isTimeout() ); + + if ( booterForkException != null ) + { + // noinspection ThrowFromFinallyBlock + throw booterForkException; + } } return runResult; http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/e0ce6cb0/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 d59fdd0..e6e5a6e 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 @@ -394,6 +394,7 @@ public class ForkClient public void close( boolean hadTimeout ) { + // no op } public final boolean isSaidGoodBye() http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/e0ce6cb0/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java ---------------------------------------------------------------------- diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java index bc8f487..98040db 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java @@ -131,15 +131,15 @@ public final class ForkedBooter } catch ( InvocationTargetException t ) { - LegacyPojoStackTraceWriter stackTraceWriter = - new LegacyPojoStackTraceWriter( "test subystem", "no method", t.getTargetException() ); + StackTraceWriter stackTraceWriter = + new LegacyPojoStackTraceWriter( "test subsystem", "no method", t.getTargetException() ); StringBuilder stringBuilder = new StringBuilder(); encode( stringBuilder, stackTraceWriter, false ); encodeAndWriteToOutput( ( (char) BOOTERCODE_ERROR ) + ",0," + stringBuilder + "\n" , originalOut ); } catch ( Throwable t ) { - StackTraceWriter stackTraceWriter = new LegacyPojoStackTraceWriter( "test subystem", "no method", t ); + StackTraceWriter stackTraceWriter = new LegacyPojoStackTraceWriter( "test subsystem", "no method", t ); StringBuilder stringBuilder = new StringBuilder(); encode( stringBuilder, stackTraceWriter, false ); encodeAndWriteToOutput( ( (char) BOOTERCODE_ERROR ) + ",0," + stringBuilder + "\n", originalOut ); http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/e0ce6cb0/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooterForkException.java ---------------------------------------------------------------------- diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooterForkException.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooterForkException.java index 9571c92..5f78ef5 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooterForkException.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooterForkException.java @@ -20,12 +20,26 @@ package org.apache.maven.surefire.booter; */ +import org.apache.maven.surefire.suite.RunResult; + +import static org.apache.maven.surefire.util.internal.StringUtils.isNotBlank; + /** * Encapsulates exceptions thrown during Surefire forking. */ public class SurefireBooterForkException extends Exception { + public SurefireBooterForkException( String message, RunResult runResult ) + { + this( message, null, null, runResult ); + } + + public SurefireBooterForkException( String message, String rethrownMessage, Throwable rethrownCause, + RunResult runResult ) + { + super( toString( message, rethrownMessage, rethrownCause, runResult ), rethrownCause ); + } public SurefireBooterForkException( String message, Throwable cause ) { @@ -36,4 +50,41 @@ public class SurefireBooterForkException { super( msg ); } + + private static String toString( String message, String rethrownMessage, Throwable rethrownCause, + RunResult runResult ) + { + return toNewLines( message, + rethrownMessage, + rethrownCause == null ? null : rethrownCause.getLocalizedMessage(), + runResult == null ? null : runResult.getFailure(), + runResult == null ? null : toString( runResult ) ); + } + + private static String toString( RunResult runResult ) + { + return "Fatal Tests run: " + runResult.getCompletedCount() + + ", Failures: " + runResult.getFailures() + + ", Errors: " + runResult.getErrors() + + ", Skipped: " + runResult.getSkipped() + + ", Flakes: " + runResult.getFlakes() + + ", Elapsed timeout: " + runResult.isTimeout(); + } + + private static String toNewLines( String... messages ) + { + StringBuilder result = new StringBuilder(); + for ( String message : messages ) + { + if ( isNotBlank( message ) ) + { + if ( result.length() == 0 ) + { + result.append( '\n' ); + } + result.append( message ); + } + } + return result.toString(); + } }