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