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