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