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