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 java.util.Collection;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Set;
26 import java.util.concurrent.ConcurrentHashMap;
27
28 import org.apache.maven.surefire.booter.Command;
29 import org.apache.maven.surefire.booter.MasterProcessListener;
30 import org.apache.maven.surefire.booter.MasterProcessReader;
31 import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
32 import org.apache.maven.surefire.common.junit4.JUnitTestFailureListener;
33 import org.apache.maven.surefire.common.junit4.Notifier;
34 import org.apache.maven.surefire.common.junit48.FilterFactory;
35 import org.apache.maven.surefire.common.junit48.JUnit48Reflector;
36 import org.apache.maven.surefire.common.junit48.JUnit48TestChecker;
37 import org.apache.maven.surefire.providerapi.AbstractProvider;
38 import org.apache.maven.surefire.providerapi.ProviderParameters;
39 import org.apache.maven.surefire.report.ConsoleLogger;
40 import org.apache.maven.surefire.report.ConsoleOutputCapture;
41 import org.apache.maven.surefire.report.ReporterFactory;
42 import org.apache.maven.surefire.suite.RunResult;
43 import org.apache.maven.surefire.testset.TestListResolver;
44 import org.apache.maven.surefire.testset.TestSetFailedException;
45 import org.apache.maven.surefire.util.RunOrderCalculator;
46 import org.apache.maven.surefire.util.ScanResult;
47 import org.apache.maven.surefire.util.ScannerFilter;
48 import org.apache.maven.surefire.util.TestsToRun;
49 import org.junit.runner.manipulation.Filter;
50 import org.junit.runner.notification.Failure;
51 import org.junit.runner.notification.RunListener;
52
53 import static org.apache.maven.surefire.junitcore.ConcurrentRunListener.createInstance;
54 import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.generateFailingTests;
55 import static org.apache.maven.surefire.common.junit4.JUnit4RunListenerFactory.createCustomListeners;
56 import static java.util.Collections.unmodifiableCollection;
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 Collection<RunListener> 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 MasterProcessReader commandsReader;
86
87 private TestsToRun testsToRun;
88
89 public JUnitCoreProvider( ProviderParameters providerParameters )
90 {
91 commandsReader = providerParameters.isInsideFork()
92 ? MasterProcessReader.getReader().setShutdown( providerParameters.getShutdown() )
93 : null;
94 this.providerParameters = providerParameters;
95 testClassLoader = providerParameters.getTestClassLoader();
96 scanResult = providerParameters.getScanResult();
97 runOrderCalculator = providerParameters.getRunOrderCalculator();
98 jUnitCoreParameters = new JUnitCoreParameters( providerParameters.getProviderProperties() );
99 scannerFilter = new JUnit48TestChecker( testClassLoader );
100 testResolver = providerParameters.getTestRequest().getTestListResolver();
101 rerunFailingTestsCount = providerParameters.getTestRequest().getRerunFailingTestsCount();
102 String listeners = providerParameters.getProviderProperties().get( "listener" );
103 customRunListeners = unmodifiableCollection( createCustomListeners( listeners ) );
104 jUnit48Reflector = new JUnit48Reflector( testClassLoader );
105 }
106
107 public Iterable<Class<?>> getSuites()
108 {
109 testsToRun = scanClassPath();
110 return testsToRun;
111 }
112
113 private boolean isSingleThreaded()
114 {
115 return jUnitCoreParameters.isNoThreading();
116 }
117
118 public RunResult invoke( Object forkTestSet )
119 throws TestSetFailedException
120 {
121 if ( isRerunFailingTests() && isFailFast() )
122 {
123 throw new TestSetFailedException( "don't enable parameters rerunFailingTestsCount, skipAfterFailureCount" );
124 }
125
126 final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
127
128 final ConsoleLogger consoleLogger = providerParameters.getConsoleLogger();
129
130 Filter filter = jUnit48Reflector.isJUnit48Available() ? createJUnit48Filter() : null;
131
132 if ( testsToRun == null )
133 {
134 if ( forkTestSet instanceof TestsToRun )
135 {
136 testsToRun = (TestsToRun) forkTestSet;
137 }
138 else if ( forkTestSet instanceof Class )
139 {
140 Class<?> theClass = (Class<?>) forkTestSet;
141 testsToRun = TestsToRun.fromClass( theClass );
142 }
143 else
144 {
145 testsToRun = scanClassPath();
146 }
147 }
148
149 Notifier notifier =
150 new Notifier( createRunListener( reporterFactory, consoleLogger ), getSkipAfterFailureCount() );
151
152
153 JUnitTestFailureListener testFailureListener = new JUnitTestFailureListener();
154 notifier.addListener( testFailureListener );
155
156 if ( isFailFast() && commandsReader != null )
157 {
158 registerPleaseStopJunitListener( notifier );
159 }
160
161 try
162 {
163 JUnitCoreWrapper core = new JUnitCoreWrapper( notifier, jUnitCoreParameters, consoleLogger, isFailFast() );
164
165 if ( commandsReader != null )
166 {
167 commandsReader.addShutdownListener( new MasterProcessListener()
168 {
169 public void update( Command command )
170 {
171 testsToRun.markTestSetFinished();
172 }
173 } );
174 commandsReader.awaitStarted();
175 }
176
177 core.execute( testsToRun, customRunListeners, filter );
178
179
180 if ( isRerunFailingTests() )
181 {
182 for ( int i = 0; i < rerunFailingTestsCount && !testFailureListener.getAllFailures().isEmpty(); i++ )
183 {
184 List<Failure> failures = testFailureListener.getAllFailures();
185 Map<Class<?>, Set<String>> failingTests = generateFailingTests( failures, testClassLoader );
186 testFailureListener.reset();
187 final FilterFactory filterFactory = new FilterFactory( testClassLoader );
188 Filter failingMethodsFilter = filterFactory.createFailingMethodFilter( failingTests );
189 core.execute( testsToRun, failingMethodsFilter );
190 }
191 }
192 return reporterFactory.close();
193 }
194 finally
195 {
196 notifier.removeListeners();
197 closeCommandsReader();
198 }
199 }
200
201 private boolean isRerunFailingTests()
202 {
203 return rerunFailingTestsCount > 0;
204 }
205
206 private boolean isFailFast()
207 {
208 return providerParameters.getSkipAfterFailureCount() > 0;
209 }
210
211 private int getSkipAfterFailureCount()
212 {
213 return isFailFast() && !isRerunFailingTests() ? providerParameters.getSkipAfterFailureCount() : 0;
214 }
215
216 private void closeCommandsReader()
217 {
218 if ( commandsReader != null )
219 {
220 commandsReader.stop();
221 }
222 }
223
224 private MasterProcessListener registerPleaseStopJunitListener( final Notifier stoppable )
225 {
226 MasterProcessListener listener = new MasterProcessListener()
227 {
228 public void update( Command command )
229 {
230 stoppable.pleaseStop();
231 }
232 };
233 commandsReader.addSkipNextListener( listener );
234 return listener;
235 }
236
237 private JUnit4RunListener createRunListener( ReporterFactory reporterFactory, ConsoleLogger consoleLogger )
238 throws TestSetFailedException
239 {
240 if ( isSingleThreaded() )
241 {
242 NonConcurrentRunListener rm = new NonConcurrentRunListener( reporterFactory.createReporter() );
243 ConsoleOutputCapture.startCapture( rm );
244 return rm;
245 }
246 else
247 {
248 final Map<String, TestSet> testSetMap = new ConcurrentHashMap<String, TestSet>();
249
250 ConcurrentRunListener listener = createInstance( testSetMap, reporterFactory, isParallelTypes(),
251 isParallelMethodsAndTypes(), consoleLogger );
252 ConsoleOutputCapture.startCapture( listener );
253
254 return new JUnitCoreRunListener( listener, testSetMap );
255 }
256 }
257
258 private boolean isParallelMethodsAndTypes()
259 {
260 return jUnitCoreParameters.isParallelMethods() && isParallelTypes();
261 }
262
263 private boolean isParallelTypes()
264 {
265 return jUnitCoreParameters.isParallelClasses() || jUnitCoreParameters.isParallelSuites();
266 }
267
268 private Filter createJUnit48Filter()
269 {
270 final FilterFactory factory = new FilterFactory( testClassLoader );
271 Filter groupFilter = factory.createGroupFilter( providerParameters.getProviderProperties() );
272 TestListResolver methodFilter = createMethodFilter();
273 boolean onlyGroups = methodFilter == null || methodFilter.isEmpty();
274 return onlyGroups ? groupFilter : factory.and( groupFilter, factory.createMethodFilter( methodFilter ) );
275 }
276
277 private TestsToRun scanClassPath()
278 {
279 TestsToRun scanned = scanResult.applyFilter( scannerFilter, testClassLoader );
280 return runOrderCalculator.orderTestClasses( scanned );
281 }
282
283 private TestListResolver createMethodFilter()
284 {
285 return testResolver == null ? null : testResolver.createMethodFilters();
286 }
287 }