View Javadoc
1   package org.apache.maven.plugin.surefire;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.execution.MavenExecutionRequest;
23  import org.apache.maven.execution.MavenSession;
24  import org.apache.maven.plugin.MojoExecutionException;
25  import org.apache.maven.plugin.MojoFailureException;
26  import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
27  import org.apache.maven.surefire.cli.CommandLineOption;
28  import org.apache.maven.surefire.suite.RunResult;
29  import org.apache.maven.surefire.testset.TestSetFailedException;
30  import org.apache.maven.surefire.util.internal.DumpFileUtils;
31  
32  import java.lang.reflect.InvocationTargetException;
33  import java.lang.reflect.Method;
34  import java.util.ArrayList;
35  import java.util.Collection;
36  import java.util.List;
37  
38  import static java.util.Collections.unmodifiableList;
39  import static org.apache.maven.surefire.booter.DumpErrorSingleton.DUMPSTREAM_FILE_EXT;
40  import static org.apache.maven.surefire.booter.DumpErrorSingleton.DUMP_FILE_EXT;
41  import static org.apache.maven.surefire.cli.CommandLineOption.LOGGING_LEVEL_DEBUG;
42  import static org.apache.maven.surefire.cli.CommandLineOption.LOGGING_LEVEL_ERROR;
43  import static org.apache.maven.surefire.cli.CommandLineOption.LOGGING_LEVEL_INFO;
44  import static org.apache.maven.surefire.cli.CommandLineOption.LOGGING_LEVEL_WARN;
45  import static org.apache.maven.surefire.cli.CommandLineOption.SHOW_ERRORS;
46  
47  /**
48   * Helper class for surefire plugins
49   */
50  public final class SurefireHelper
51  {
52      private static final String DUMP_FILE_DATE = DumpFileUtils.newFormattedDateFileName();
53  
54      public static final String DUMP_FILE_PREFIX = DUMP_FILE_DATE + "-jvmRun";
55  
56      public static final String DUMPSTREAM_FILENAME_FORMATTER = DUMP_FILE_PREFIX + "%d" + DUMPSTREAM_FILE_EXT;
57  
58      private static final String[] DUMP_FILES_PRINT =
59              {
60                      "[date]-jvmRun[N]" + DUMP_FILE_EXT,
61                      "[date]" + DUMPSTREAM_FILE_EXT,
62                      "[date]-jvmRun[N]" + DUMPSTREAM_FILE_EXT
63              };
64  
65      /**
66       * Do not instantiate.
67       */
68      private SurefireHelper()
69      {
70          throw new IllegalAccessError( "Utility class" );
71      }
72  
73      public static String[] getDumpFilesToPrint()
74      {
75          return DUMP_FILES_PRINT.clone();
76      }
77  
78      public static void reportExecution( SurefireReportParameters reportParameters, RunResult result,
79                                          PluginConsoleLogger log, Exception firstForkException )
80          throws MojoFailureException, MojoExecutionException
81      {
82          if ( firstForkException == null && !result.isTimeout() && result.isErrorFree() )
83          {
84              if ( result.getCompletedCount() == 0 && failIfNoTests( reportParameters ) )
85              {
86                  throw new MojoFailureException( "No tests were executed!  "
87                                                          + "(Set -DfailIfNoTests=false to ignore this error.)" );
88              }
89              return;
90          }
91  
92          if ( reportParameters.isTestFailureIgnore() )
93          {
94              log.error( createErrorMessage( reportParameters, result, firstForkException ) );
95          }
96          else
97          {
98              throwException( reportParameters, result, firstForkException );
99          }
100     }
101 
102     public static List<CommandLineOption> commandLineOptions( MavenSession session, PluginConsoleLogger log )
103     {
104         List<CommandLineOption> cli = new ArrayList<CommandLineOption>();
105         if ( log.isErrorEnabled() )
106         {
107             cli.add( LOGGING_LEVEL_ERROR );
108         }
109 
110         if ( log.isWarnEnabled() )
111         {
112             cli.add( LOGGING_LEVEL_WARN );
113         }
114 
115         if ( log.isInfoEnabled() )
116         {
117             cli.add( LOGGING_LEVEL_INFO );
118         }
119 
120         if ( log.isDebugEnabled() )
121         {
122             cli.add( LOGGING_LEVEL_DEBUG );
123         }
124 
125         try
126         {
127             Method getRequestMethod = session.getClass().getMethod( "getRequest" );
128             MavenExecutionRequest request = (MavenExecutionRequest) getRequestMethod.invoke( session );
129 
130             if ( request.isShowErrors() )
131             {
132                 cli.add( SHOW_ERRORS );
133             }
134 
135             String f = getFailureBehavior( request );
136             if ( f != null )
137             {
138                 // compatible with enums Maven 3.0
139                 cli.add( CommandLineOption.valueOf( f.startsWith( "REACTOR_" ) ? f : "REACTOR_" + f ) );
140             }
141         }
142         catch ( Exception e )
143         {
144             // don't need to log the exception that Maven 2 does not have getRequest() method in Maven Session
145         }
146         return unmodifiableList( cli );
147     }
148 
149     public static void logDebugOrCliShowErrors( String s, PluginConsoleLogger log, Collection<CommandLineOption> cli )
150     {
151         if ( cli.contains( LOGGING_LEVEL_DEBUG ) )
152         {
153             log.debug( s );
154         }
155         else if ( cli.contains( SHOW_ERRORS ) )
156         {
157             if ( log.isDebugEnabled() )
158             {
159                 log.debug( s );
160             }
161             else
162             {
163                 log.info( s );
164             }
165         }
166     }
167 
168     private static String getFailureBehavior( MavenExecutionRequest request )
169         throws NoSuchMethodException, InvocationTargetException, IllegalAccessException
170     {
171         try
172         {
173             return request.getFailureBehavior();
174         }
175         catch ( NoSuchMethodError e )
176         {
177             return (String) request.getClass()
178                 .getMethod( "getReactorFailureBehavior" )
179                 .invoke( request );
180         }
181     }
182 
183     private static boolean failIfNoTests( SurefireReportParameters reportParameters )
184     {
185         return reportParameters.getFailIfNoTests() != null && reportParameters.getFailIfNoTests();
186     }
187 
188     private static boolean isFatal( Exception firstForkException )
189     {
190         return firstForkException != null && !( firstForkException instanceof TestSetFailedException );
191     }
192 
193     private static void throwException( SurefireReportParameters reportParameters, RunResult result,
194                                            Exception firstForkException )
195             throws MojoFailureException, MojoExecutionException
196     {
197         if ( isFatal( firstForkException ) || result.isInternalError()  )
198         {
199             throw new MojoExecutionException( createErrorMessage( reportParameters, result, firstForkException ),
200                                                     firstForkException );
201         }
202         else
203         {
204             throw new MojoFailureException( createErrorMessage( reportParameters, result, firstForkException ),
205                                                   firstForkException );
206         }
207     }
208 
209     private static String createErrorMessage( SurefireReportParameters reportParameters, RunResult result,
210                                               Exception firstForkException )
211     {
212         StringBuilder msg = new StringBuilder( 512 );
213 
214         if ( result.isTimeout() )
215         {
216             msg.append( "There was a timeout or other error in the fork" );
217         }
218         else
219         {
220             msg.append( "There are test failures.\n\nPlease refer to " )
221                     .append( reportParameters.getReportsDirectory() )
222                     .append( " for the individual test results." )
223                     .append( '\n' )
224                     .append( "Please refer to dump files (if any exist) " )
225                     .append( DUMP_FILES_PRINT[0] )
226                     .append( ", " )
227                     .append( DUMP_FILES_PRINT[1] )
228                     .append( " and " )
229                     .append( DUMP_FILES_PRINT[2] )
230                     .append( "." );
231         }
232 
233         if ( firstForkException != null && firstForkException.getLocalizedMessage() != null )
234         {
235             msg.append( '\n' )
236                     .append( firstForkException.getLocalizedMessage() );
237         }
238 
239         if ( result.isFailure() )
240         {
241             msg.append( '\n' )
242                     .append( result.getFailure() );
243         }
244 
245         return msg.toString();
246     }
247 
248 }