View Javadoc
1   package org.apache.maven.plugin.surefire.report;
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 java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.Collections;
25  import java.util.List;
26  
27  import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
28  import org.apache.maven.plugin.surefire.runorder.StatisticsReporter;
29  import org.apache.maven.surefire.report.ConsoleOutputReceiver;
30  import org.apache.maven.surefire.report.ReportEntry;
31  import org.apache.maven.surefire.report.RunListener;
32  import org.apache.maven.surefire.report.TestSetReportEntry;
33  
34  import static org.apache.maven.plugin.surefire.report.ReportEntryType.ERROR;
35  import static org.apache.maven.plugin.surefire.report.ReportEntryType.FAILURE;
36  import static org.apache.maven.plugin.surefire.report.ReportEntryType.SKIPPED;
37  import static org.apache.maven.plugin.surefire.report.ReportEntryType.SUCCESS;
38  
39  /**
40   * Reports data for a single test set.
41   * <br>
42   *
43   * @author Kristian Rosenvold
44   */
45  public class TestSetRunListener
46      implements RunListener, ConsoleOutputReceiver, ConsoleLogger
47  {
48      private final TestSetStats detailsForThis;
49  
50      private List<TestMethodStats> testMethodStats;
51  
52      private Utf8RecodingDeferredFileOutputStream testStdOut = initDeferred( "stdout" );
53  
54      private Utf8RecodingDeferredFileOutputStream testStdErr = initDeferred( "stderr" );
55  
56      private Utf8RecodingDeferredFileOutputStream initDeferred( String channel )
57      {
58          return new Utf8RecodingDeferredFileOutputStream( channel );
59      }
60  
61      private final TestcycleConsoleOutputReceiver consoleOutputReceiver;
62  
63      private final boolean briefOrPlainFormat;
64  
65      private final StatelessXmlReporter simpleXMLReporter;
66  
67      private final ConsoleReporter consoleReporter;
68  
69      private final FileReporter fileReporter;
70  
71      private final StatisticsReporter statisticsReporter;
72  
73      @SuppressWarnings( "checkstyle:parameternumber" )
74      public TestSetRunListener( ConsoleReporter consoleReporter, FileReporter fileReporter,
75                                 StatelessXmlReporter simpleXMLReporter,
76                                 TestcycleConsoleOutputReceiver consoleOutputReceiver,
77                                 StatisticsReporter statisticsReporter, boolean trimStackTrace,
78                                 boolean isPlainFormat, boolean briefOrPlainFormat )
79      {
80          this.consoleReporter = consoleReporter;
81          this.fileReporter = fileReporter;
82          this.statisticsReporter = statisticsReporter;
83          this.simpleXMLReporter = simpleXMLReporter;
84          this.consoleOutputReceiver = consoleOutputReceiver;
85          this.briefOrPlainFormat = briefOrPlainFormat;
86          detailsForThis = new TestSetStats( trimStackTrace, isPlainFormat );
87          testMethodStats = new ArrayList<TestMethodStats>();
88      }
89  
90      @Override
91      public boolean isDebugEnabled()
92      {
93          return consoleReporter.getConsoleLogger().isDebugEnabled();
94      }
95  
96      @Override
97      public void debug( String message )
98      {
99          consoleReporter.getConsoleLogger().debug( trimTrailingNewLine( message ) );
100     }
101 
102     @Override
103     public boolean isInfoEnabled()
104     {
105         return consoleReporter.getConsoleLogger().isInfoEnabled();
106     }
107 
108     @Override
109     public void info( String message )
110     {
111         consoleReporter.getConsoleLogger().info( trimTrailingNewLine( message ) );
112     }
113 
114     @Override
115     public boolean isWarnEnabled()
116     {
117         return consoleReporter.getConsoleLogger().isWarnEnabled();
118     }
119 
120     @Override
121     public void warning( String message )
122     {
123         consoleReporter.getConsoleLogger().warning( trimTrailingNewLine( message ) );
124     }
125 
126     @Override
127     public boolean isErrorEnabled()
128     {
129         return consoleReporter.getConsoleLogger().isErrorEnabled();
130     }
131 
132     @Override
133     public void error( String message )
134     {
135         consoleReporter.getConsoleLogger().error( trimTrailingNewLine( message ) );
136     }
137 
138     @Override
139     public void error( String message, Throwable t )
140     {
141         consoleReporter.getConsoleLogger().error( message, t );
142     }
143 
144     @Override
145     public void error( Throwable t )
146     {
147         consoleReporter.getConsoleLogger().error( t );
148     }
149 
150     @Override
151     public void writeTestOutput( byte[] buf, int off, int len, boolean stdout )
152     {
153         try
154         {
155             if ( stdout )
156             {
157                 testStdOut.write( buf, off, len );
158             }
159             else
160             {
161                 testStdErr.write( buf, off, len );
162             }
163             consoleOutputReceiver.writeTestOutput( buf, off, len, stdout );
164         }
165         catch ( IOException e )
166         {
167             throw new RuntimeException( e );
168         }
169     }
170 
171     @Override
172     public void testSetStarting( TestSetReportEntry report )
173     {
174         detailsForThis.testSetStart();
175         consoleReporter.testSetStarting( report );
176         consoleOutputReceiver.testSetStarting( report );
177     }
178 
179     private void clearCapture()
180     {
181         testStdOut = initDeferred( "stdout" );
182         testStdErr = initDeferred( "stderr" );
183     }
184 
185     @Override
186     public void testSetCompleted( TestSetReportEntry report )
187     {
188         final WrappedReportEntry wrap = wrapTestSet( report );
189         final List<String> testResults =
190                 briefOrPlainFormat ? detailsForThis.getTestResults() : Collections.<String>emptyList();
191         fileReporter.testSetCompleted( wrap, detailsForThis, testResults );
192         simpleXMLReporter.testSetCompleted( wrap, detailsForThis );
193         statisticsReporter.testSetCompleted();
194         consoleReporter.testSetCompleted( wrap, detailsForThis, testResults );
195         consoleOutputReceiver.testSetCompleted( wrap );
196         consoleReporter.reset();
197 
198         wrap.getStdout().free();
199         wrap.getStdErr().free();
200 
201         addTestMethodStats();
202         detailsForThis.reset();
203         clearCapture();
204     }
205 
206     // ----------------------------------------------------------------------
207     // Test
208     // ----------------------------------------------------------------------
209 
210     @Override
211     public void testStarting( ReportEntry report )
212     {
213         detailsForThis.testStart();
214     }
215 
216     @Override
217     public void testSucceeded( ReportEntry reportEntry )
218     {
219         WrappedReportEntry wrapped = wrap( reportEntry, SUCCESS );
220         detailsForThis.testSucceeded( wrapped );
221         statisticsReporter.testSucceeded( reportEntry );
222         clearCapture();
223     }
224 
225     @Override
226     public void testError( ReportEntry reportEntry )
227     {
228         WrappedReportEntry wrapped = wrap( reportEntry, ERROR );
229         detailsForThis.testError( wrapped );
230         statisticsReporter.testError( reportEntry );
231         clearCapture();
232     }
233 
234     @Override
235     public void testFailed( ReportEntry reportEntry )
236     {
237         WrappedReportEntry wrapped = wrap( reportEntry, FAILURE );
238         detailsForThis.testFailure( wrapped );
239         statisticsReporter.testFailed( reportEntry );
240         clearCapture();
241     }
242 
243     // ----------------------------------------------------------------------
244     // Counters
245     // ----------------------------------------------------------------------
246 
247     @Override
248     public void testSkipped( ReportEntry reportEntry )
249     {
250         WrappedReportEntry wrapped = wrap( reportEntry, SKIPPED );
251         detailsForThis.testSkipped( wrapped );
252         statisticsReporter.testSkipped( reportEntry );
253         clearCapture();
254     }
255 
256     @Override
257     public void testExecutionSkippedByUser()
258     {
259     }
260 
261     @Override
262     public void testAssumptionFailure( ReportEntry report )
263     {
264         testSkipped( report );
265     }
266 
267     private WrappedReportEntry wrap( ReportEntry other, ReportEntryType reportEntryType )
268     {
269         int estimatedElapsed = 0;
270         if ( reportEntryType != SKIPPED )
271         {
272             Integer etime = other.getElapsed();
273             estimatedElapsed = etime == null ? detailsForThis.getElapsedSinceLastStart() : etime;
274         }
275 
276         return new WrappedReportEntry( other, reportEntryType, estimatedElapsed, testStdOut, testStdErr );
277     }
278 
279     private WrappedReportEntry wrapTestSet( TestSetReportEntry other )
280     {
281         return new WrappedReportEntry( other, null, other.getElapsed() != null
282             ? other.getElapsed()
283             : detailsForThis.getElapsedSinceTestSetStart(), testStdOut, testStdErr, other.getSystemProperties() );
284     }
285 
286     public void close()
287     {
288         consoleOutputReceiver.close();
289     }
290 
291     private void addTestMethodStats()
292     {
293         for ( WrappedReportEntry reportEntry : detailsForThis.getReportEntries() )
294         {
295             TestMethodStats methodStats =
296                 new TestMethodStats( reportEntry.getClassMethodName(), reportEntry.getReportEntryType(),
297                                      reportEntry.getStackTraceWriter() );
298             testMethodStats.add( methodStats );
299         }
300     }
301 
302     public List<TestMethodStats> getTestMethodStats()
303     {
304         return testMethodStats;
305     }
306 
307     private static String trimTrailingNewLine( final String message )
308     {
309         final int e = message == null ? 0 : lineBoundSymbolWidth( message );
310         return message != null && e != 0 ? message.substring( 0, message.length() - e ) : message;
311     }
312 
313     private static int lineBoundSymbolWidth( String message )
314     {
315         return message.endsWith( "\n" ) || message.endsWith( "\r" ) ? 1 : ( message.endsWith( "\r\n" ) ? 2 : 0 );
316     }
317 }