1 package org.apache.maven.surefire.common.junit4;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
23 import org.apache.maven.surefire.api.report.OutputReportEntry;
24 import org.apache.maven.surefire.api.report.ReportEntry;
25 import org.apache.maven.surefire.api.report.RunMode;
26 import org.apache.maven.surefire.api.report.SimpleReportEntry;
27 import org.apache.maven.surefire.api.report.StackTraceWriter;
28 import org.apache.maven.surefire.api.report.TestOutputReceiver;
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.testset.TestSetFailedException;
32 import org.apache.maven.surefire.api.util.internal.ClassMethod;
33 import org.apache.maven.surefire.report.ClassMethodIndexer;
34 import org.apache.maven.surefire.report.RunModeSetter;
35 import org.junit.runner.Description;
36 import org.junit.runner.Result;
37 import org.junit.runner.notification.Failure;
38 import org.junit.runner.notification.RunListener;
39
40 import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.isFailureInsideJUnitItself;
41 import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.toClassMethod;
42 import static org.apache.maven.surefire.common.junit4.JUnit4Reflector.getAnnotatedIgnoreValue;
43 import static org.apache.maven.surefire.api.report.SimpleReportEntry.assumption;
44 import static org.apache.maven.surefire.api.report.SimpleReportEntry.ignored;
45 import static org.apache.maven.surefire.api.report.SimpleReportEntry.withException;
46
47
48
49
50
51 public class JUnit4RunListener
52 extends RunListener
53 implements TestOutputReceiver<OutputReportEntry>, RunModeSetter
54 {
55 protected final ClassMethodIndexer classMethodIndexer = new ClassMethodIndexer();
56 protected final TestReportListener<TestOutputReportEntry> reporter;
57 private volatile RunMode runMode;
58
59
60
61
62
63
64
65
66 private final ThreadLocal<Boolean> failureFlag = new InheritableThreadLocal<>();
67
68
69
70
71
72
73 public JUnit4RunListener( TestReportListener<TestOutputReportEntry> reporter )
74 {
75 this.reporter = reporter;
76 }
77
78 public final ConsoleLogger getConsoleLogger()
79 {
80 return reporter;
81 }
82
83 @Override
84 public void setRunMode( RunMode runMode )
85 {
86 this.runMode = runMode;
87 }
88
89 protected final RunMode getRunMode()
90 {
91 return runMode;
92 }
93
94
95
96
97
98
99
100
101 @Override
102 public void testIgnored( Description description )
103 throws Exception
104 {
105 String reason = getAnnotatedIgnoreValue( description );
106 ClassMethod classMethod = toClassMethod( description );
107 long testRunId = classMethodIndexer.indexClassMethod( classMethod.getClazz(), classMethod.getMethod() );
108 reporter.testSkipped( ignored( runMode, testRunId, classMethod.getClazz(), null,
109 classMethod.getMethod(), null, reason ) );
110 }
111
112
113
114
115
116
117 @Override
118 public void testStarted( Description description )
119 throws Exception
120 {
121 try
122 {
123 reporter.testStarting( createReportEntry( description ) );
124 }
125 finally
126 {
127 failureFlag.remove();
128 }
129 }
130
131
132
133
134
135
136 @Override
137 @SuppressWarnings( { "ThrowableResultOfMethodCallIgnored" } )
138 public void testFailure( Failure failure )
139 throws Exception
140 {
141 try
142 {
143 StackTraceWriter stackTrace = createStackTraceWriter( failure );
144 ClassMethod classMethod = toClassMethod( failure.getDescription() );
145 long testRunId = classMethodIndexer.indexClassMethod( classMethod.getClazz(), classMethod.getMethod() );
146 ReportEntry report = withException( runMode, testRunId, classMethod.getClazz(), null,
147 classMethod.getMethod(), null, stackTrace );
148
149 if ( failure.getException() instanceof AssertionError )
150 {
151 reporter.testFailed( report );
152 }
153 else
154 {
155 reporter.testError( report );
156 }
157 }
158 finally
159 {
160 failureFlag.set( true );
161 }
162 }
163
164 public void testAssumptionFailure( Failure failure )
165 {
166 try
167 {
168 Description desc = failure.getDescription();
169 ClassMethod classMethod = toClassMethod( desc );
170 long testRunId = classMethodIndexer.indexClassMethod( classMethod.getClazz(), classMethod.getMethod() );
171 ReportEntry report = assumption( runMode, testRunId, classMethod.getClazz(), null,
172 classMethod.getMethod(), null, failure.getMessage() );
173 reporter.testAssumptionFailure( report );
174 }
175 finally
176 {
177 failureFlag.set( true );
178 }
179 }
180
181
182
183
184
185
186 @Override
187 public void testFinished( Description description )
188 throws Exception
189 {
190 Boolean failure = failureFlag.get();
191 if ( failure == null )
192 {
193 reporter.testSucceeded( createReportEntry( description ) );
194 }
195 }
196
197
198
199
200 public void testExecutionSkippedByUser()
201 {
202 reporter.testExecutionSkippedByUser();
203 }
204
205 protected StackTraceWriter createStackTraceWriter( Failure failure )
206 {
207 return new JUnit4StackTraceWriter( failure );
208 }
209
210 protected SimpleReportEntry createReportEntry( Description description )
211 {
212 ClassMethod classMethod = toClassMethod( description );
213 long testRunId = classMethodIndexer.indexClassMethod( classMethod.getClazz(), classMethod.getMethod() );
214 return new SimpleReportEntry( runMode, testRunId, classMethod.getClazz(), null,
215 classMethod.getMethod(), null );
216 }
217
218 public static void rethrowAnyTestMechanismFailures( Result run )
219 throws TestSetFailedException
220 {
221 for ( Failure failure : run.getFailures() )
222 {
223 if ( isFailureInsideJUnitItself( failure.getDescription() ) )
224 {
225 throw new TestSetFailedException( failure.getTestHeader() + " :: " + failure.getMessage(),
226 failure.getException() );
227 }
228 }
229 }
230
231 @Override
232 public void writeTestOutput( OutputReportEntry reportEntry )
233 {
234 Long testRunId = classMethodIndexer.getLocalIndex();
235 reporter.writeTestOutput( new TestOutputReportEntry( reportEntry, runMode, testRunId ) );
236 }
237 }