1 package org.apache.maven.surefire.junitcore;
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.surefire.api.booter.Command;
23 import org.apache.maven.surefire.api.provider.CommandChainReader;
24 import org.apache.maven.surefire.api.provider.CommandListener;
25 import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
26 import org.apache.maven.surefire.common.junit4.JUnitTestFailureListener;
27 import org.apache.maven.surefire.common.junit4.Notifier;
28 import org.apache.maven.surefire.common.junit48.FilterFactory;
29 import org.apache.maven.surefire.common.junit48.JUnit48Reflector;
30 import org.apache.maven.surefire.common.junit48.JUnit48TestChecker;
31 import org.apache.maven.surefire.api.provider.AbstractProvider;
32 import org.apache.maven.surefire.api.provider.ProviderParameters;
33 import org.apache.maven.surefire.api.report.ConsoleStream;
34 import org.apache.maven.surefire.api.report.ReporterFactory;
35 import org.apache.maven.surefire.api.suite.RunResult;
36 import org.apache.maven.surefire.api.testset.TestListResolver;
37 import org.apache.maven.surefire.api.testset.TestSetFailedException;
38 import org.apache.maven.surefire.api.util.RunOrderCalculator;
39 import org.apache.maven.surefire.api.util.ScanResult;
40 import org.apache.maven.surefire.api.util.ScannerFilter;
41 import org.apache.maven.surefire.api.util.TestsToRun;
42 import org.junit.runner.Description;
43 import org.junit.runner.manipulation.Filter;
44
45 import java.util.Map;
46 import java.util.Set;
47 import java.util.concurrent.ConcurrentHashMap;
48
49 import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.generateFailingTestDescriptions;
50 import static org.apache.maven.surefire.common.junit4.JUnit4RunListenerFactory.createCustomListeners;
51 import static org.apache.maven.surefire.common.junit4.Notifier.pureNotifier;
52 import static org.apache.maven.surefire.junitcore.ConcurrentRunListener.createInstance;
53 import static org.apache.maven.surefire.api.report.ConsoleOutputCapture.startCapture;
54 import static org.apache.maven.surefire.api.testset.TestListResolver.optionallyWildcardFilter;
55 import static org.apache.maven.surefire.api.util.TestsToRun.fromClass;
56
57
58
59
60 @SuppressWarnings( { "UnusedDeclaration" } )
61 public class JUnitCoreProvider
62 extends AbstractProvider
63 {
64 private final ClassLoader testClassLoader;
65
66 private final JUnitCoreParameters jUnitCoreParameters;
67
68 private final ScannerFilter scannerFilter;
69
70 private final String customRunListeners;
71
72 private final ProviderParameters providerParameters;
73
74 private final ScanResult scanResult;
75
76 private final int rerunFailingTestsCount;
77
78 private final JUnit48Reflector jUnit48Reflector;
79
80 private final RunOrderCalculator runOrderCalculator;
81
82 private final TestListResolver testResolver;
83
84 private final CommandChainReader commandsReader;
85
86 private TestsToRun testsToRun;
87
88 public JUnitCoreProvider( ProviderParameters bootParams )
89 {
90
91 commandsReader = bootParams.isInsideFork() ? bootParams.getCommandReader() : null;
92 providerParameters = bootParams;
93 testClassLoader = bootParams.getTestClassLoader();
94 scanResult = bootParams.getScanResult();
95 runOrderCalculator = bootParams.getRunOrderCalculator();
96 jUnitCoreParameters = new JUnitCoreParameters( bootParams.getProviderProperties() );
97 scannerFilter = new JUnit48TestChecker( testClassLoader );
98 testResolver = bootParams.getTestRequest().getTestListResolver();
99 rerunFailingTestsCount = bootParams.getTestRequest().getRerunFailingTestsCount();
100 customRunListeners = bootParams.getProviderProperties().get( "listener" );
101 jUnit48Reflector = new JUnit48Reflector( testClassLoader );
102 }
103
104 @Override
105 public Iterable<Class<?>> getSuites()
106 {
107 testsToRun = scanClassPath();
108 return testsToRun;
109 }
110
111 private boolean isSingleThreaded()
112 {
113 return jUnitCoreParameters.isNoThreading();
114 }
115
116 @Override
117 public RunResult invoke( Object forkTestSet )
118 throws TestSetFailedException
119 {
120 final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
121
122 final ConsoleStream consoleStream = providerParameters.getConsoleLogger();
123
124 Notifier notifier =
125 new Notifier( createRunListener( reporterFactory, consoleStream ), getSkipAfterFailureCount() );
126
127
128 Filter filter = jUnit48Reflector.isJUnit48Available() ? createJUnit48Filter() : null;
129
130 if ( testsToRun == null )
131 {
132 setTestsToRun( forkTestSet );
133 }
134
135
136 JUnitTestFailureListener testFailureListener = new JUnitTestFailureListener();
137 notifier.addListener( testFailureListener );
138
139 if ( isFailFast() && commandsReader != null )
140 {
141 registerPleaseStopJUnitListener( notifier );
142 }
143
144 final RunResult runResult;
145
146 try
147 {
148 JUnitCoreWrapper core = new JUnitCoreWrapper( notifier, jUnitCoreParameters, consoleStream );
149
150 if ( commandsReader != null )
151 {
152 registerShutdownListener( testsToRun );
153 commandsReader.awaitStarted();
154 }
155
156 notifier.asFailFast( isFailFast() );
157 core.execute( testsToRun, createCustomListeners( customRunListeners ), filter );
158 notifier.asFailFast( false );
159
160
161 if ( isRerunFailingTests() )
162 {
163 Notifier rerunNotifier = pureNotifier();
164 notifier.copyListenersTo( rerunNotifier );
165 JUnitCoreWrapper rerunCore = new JUnitCoreWrapper( rerunNotifier, jUnitCoreParameters, consoleStream );
166 for ( int i = 0; i < rerunFailingTestsCount && !testFailureListener.getAllFailures().isEmpty(); i++ )
167 {
168 Set<Description> failures = generateFailingTestDescriptions( testFailureListener.getAllFailures() );
169 testFailureListener.reset();
170 FilterFactory filterFactory = new FilterFactory( testClassLoader );
171 Filter failureDescriptionFilter = filterFactory.createMatchAnyDescriptionFilter( failures );
172 rerunCore.execute( testsToRun, failureDescriptionFilter );
173 }
174 }
175 }
176 finally
177 {
178 runResult = reporterFactory.close();
179 notifier.removeListeners();
180 }
181 return runResult;
182 }
183
184 private void setTestsToRun( Object forkTestSet )
185 throws TestSetFailedException
186 {
187 if ( forkTestSet instanceof TestsToRun )
188 {
189 testsToRun = (TestsToRun) forkTestSet;
190 }
191 else if ( forkTestSet instanceof Class )
192 {
193 Class<?> theClass = (Class<?>) forkTestSet;
194 testsToRun = fromClass( theClass );
195 }
196 else
197 {
198 testsToRun = scanClassPath();
199 }
200 }
201
202 private boolean isRerunFailingTests()
203 {
204 return rerunFailingTestsCount > 0;
205 }
206
207 private boolean isFailFast()
208 {
209 return providerParameters.getSkipAfterFailureCount() > 0;
210 }
211
212 private int getSkipAfterFailureCount()
213 {
214 return isFailFast() ? providerParameters.getSkipAfterFailureCount() : 0;
215 }
216
217 private void registerShutdownListener( final TestsToRun testsToRun )
218 {
219 commandsReader.addShutdownListener( new CommandListener()
220 {
221 @Override
222 public void update( Command command )
223 {
224 testsToRun.markTestSetFinished();
225 }
226 } );
227 }
228
229 private void registerPleaseStopJUnitListener( final Notifier stoppable )
230 {
231 commandsReader.addSkipNextTestsListener( new CommandListener()
232 {
233 @Override
234 public void update( Command command )
235 {
236 stoppable.pleaseStop();
237 }
238 } );
239 }
240
241 private JUnit4RunListener createRunListener( ReporterFactory reporterFactory, ConsoleStream consoleStream )
242 throws TestSetFailedException
243 {
244 if ( isSingleThreaded() )
245 {
246 NonConcurrentRunListener rm = new NonConcurrentRunListener( reporterFactory.createReporter() );
247 startCapture( rm );
248 return rm;
249 }
250 else
251 {
252 final Map<String, TestSet> testSetMap = new ConcurrentHashMap<>();
253
254 ConcurrentRunListener listener = createInstance( testSetMap, reporterFactory, isParallelTypes(),
255 isParallelMethodsAndTypes(), consoleStream );
256 startCapture( listener );
257
258 return new JUnitCoreRunListener( listener, testSetMap );
259 }
260 }
261
262 private boolean isParallelMethodsAndTypes()
263 {
264 return jUnitCoreParameters.isParallelMethods() && isParallelTypes();
265 }
266
267 private boolean isParallelTypes()
268 {
269 return jUnitCoreParameters.isParallelClasses() || jUnitCoreParameters.isParallelSuites();
270 }
271
272 private Filter createJUnit48Filter()
273 {
274 final FilterFactory factory = new FilterFactory( testClassLoader );
275 Map<String, String> props = providerParameters.getProviderProperties();
276 Filter groupFilter = factory.canCreateGroupFilter( props ) ? factory.createGroupFilter( props ) : null;
277 TestListResolver methodFilter = optionallyWildcardFilter( testResolver );
278 boolean onlyGroups = methodFilter.isEmpty() || methodFilter.isWildcard();
279 if ( onlyGroups )
280 {
281 return groupFilter;
282 }
283 else
284 {
285 Filter jUnitMethodFilter = factory.createMethodFilter( methodFilter );
286 return groupFilter == null ? jUnitMethodFilter : factory.and( groupFilter, jUnitMethodFilter );
287 }
288 }
289
290 private TestsToRun scanClassPath()
291 {
292 TestsToRun scanned = scanResult.applyFilter( scannerFilter, testClassLoader );
293 return runOrderCalculator.orderTestClasses( scanned );
294 }
295 }