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