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.Collections;
24 import java.util.List;
25 import java.util.TreeSet;
26 import java.util.concurrent.Future;
27 import java.util.concurrent.TimeUnit;
28
29 import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
30 import org.apache.maven.surefire.junitcore.pc.ParallelComputer;
31 import org.apache.maven.surefire.testset.TestSetFailedException;
32 import org.apache.maven.surefire.util.TestsToRun;
33
34 import org.junit.runner.Computer;
35 import org.junit.runner.Description;
36 import org.junit.runner.JUnitCore;
37 import org.junit.runner.Request;
38 import org.junit.runner.Result;
39 import org.junit.runner.Runner;
40 import org.junit.runner.manipulation.Filter;
41 import org.junit.runner.manipulation.NoTestsRemainException;
42 import org.junit.runner.notification.RunListener;
43
44
45
46
47
48
49
50 class JUnitCoreWrapper
51 {
52 private static class FilteringRequest
53 extends Request
54 {
55 private Runner filteredRunner;
56
57 public FilteringRequest( Request req, Filter filter )
58 {
59 try
60 {
61 Runner runner = req.getRunner();
62 filter.apply( runner );
63 filteredRunner = runner;
64 }
65 catch ( NoTestsRemainException e )
66 {
67 filteredRunner = null;
68 }
69 }
70
71 @Override
72 public Runner getRunner()
73 {
74 return filteredRunner;
75 }
76 }
77
78 public static void execute( TestsToRun testsToRun, JUnitCoreParameters jUnitCoreParameters,
79 List<RunListener> listeners, Filter filter )
80 throws TestSetFailedException
81 {
82 ComputerWrapper computerWrapper = createComputer( jUnitCoreParameters );
83 JUnitCore junitCore = createJUnitCore( listeners );
84 if ( testsToRun.allowEagerReading() )
85 {
86 executeEager( testsToRun, filter, computerWrapper.getComputer(), junitCore );
87 }
88 else
89 {
90 exeuteLazy( testsToRun, filter, computerWrapper.getComputer(), junitCore );
91 }
92
93 String timeoutMessage = computerWrapper.describeElapsedTimeout();
94 if ( timeoutMessage.length() != 0 )
95 {
96 throw new TestSetFailedException( timeoutMessage );
97 }
98 }
99
100 private static JUnitCore createJUnitCore( List<RunListener> listeners )
101 {
102 JUnitCore junitCore = new JUnitCore();
103 for ( RunListener runListener : listeners )
104 {
105 junitCore.addListener( runListener );
106 }
107 return junitCore;
108 }
109
110 private static void executeEager(TestsToRun testsToRun, Filter filter, Computer computer, JUnitCore junitCore)
111 throws TestSetFailedException
112 {
113 Class[] tests = testsToRun.getLocatedClasses();
114 createRequestAndRun( filter, computer, junitCore, tests );
115 }
116
117 private static void exeuteLazy(TestsToRun testsToRun, Filter filter, Computer computer, JUnitCore junitCore)
118 throws TestSetFailedException
119 {
120
121 for ( Class clazz : testsToRun )
122 {
123 createRequestAndRun( filter, computer, junitCore, clazz );
124 }
125 }
126
127 private static void createRequestAndRun( Filter filter, Computer computer, JUnitCore junitCore, Class<?>... classesToRun )
128 throws TestSetFailedException
129 {
130 Request req = Request.classes( computer, classesToRun );
131 if ( filter != null )
132 {
133 req = new FilteringRequest( req, filter );
134 if ( req.getRunner() == null )
135 {
136
137 return;
138 }
139 }
140
141 final Result run = junitCore.run( req );
142 JUnit4RunListener.rethrowAnyTestMechanismFailures( run );
143 }
144
145 private static ComputerWrapper createComputer( JUnitCoreParameters parameters )
146 throws TestSetFailedException
147 {
148 return parameters.isNoThreading() ? new ComputerWrapper( Computer.serial() ) : createParallelComputer( parameters );
149 }
150
151 private static ComputerWrapper createParallelComputer( JUnitCoreParameters parameters )
152 throws TestSetFailedException
153 {
154 ParallelComputer pc = ParallelComputerFactory.createParallelComputer( parameters );
155
156 int timeout = parameters.getParallelTestsTimeoutInSeconds();
157
158 int timeoutForced = parameters.getParallelTestsTimeoutForcedInSeconds();
159
160 Future<Collection<Description>> testsBeforeShutdown =
161 timeout > 0 ? pc.scheduleShutdown( timeout, TimeUnit.SECONDS ) : null;
162
163 Future<Collection<Description>> testsBeforeForcedShutdown =
164 timeoutForced > 0 ? pc.scheduleForcedShutdown( timeoutForced, TimeUnit.SECONDS ) : null;
165
166 return new ComputerWrapper( pc, timeout, testsBeforeShutdown, timeoutForced, testsBeforeForcedShutdown );
167 }
168
169 private static class ComputerWrapper
170 {
171 private final Computer computer;
172 private final int timeout;
173 private final int timeoutForced;
174 private final Future<Collection<Description>> testsBeforeShutdown;
175 private final Future<Collection<Description>> testsBeforeForcedShutdown;
176
177 ComputerWrapper( Computer computer )
178 {
179 this( computer, 0, null, 0, null );
180 }
181
182 ComputerWrapper( Computer computer,
183 int timeout, Future<Collection<Description>> testsBeforeShutdown,
184 int timeoutForced, Future<Collection<Description>> testsBeforeForcedShutdown )
185 {
186 this.computer = computer;
187 this.timeout = timeout;
188 this.testsBeforeShutdown = testsBeforeShutdown;
189 this.timeoutForced = timeoutForced;
190 this.testsBeforeForcedShutdown = testsBeforeForcedShutdown;
191 }
192
193 Computer getComputer()
194 {
195 return computer;
196 }
197
198 String describeElapsedTimeout() throws TestSetFailedException
199 {
200 TreeSet<String> executedTests = new TreeSet<String>();
201 if ( timeout > 0 )
202 {
203 executedTests.addAll( printShutdownHook( testsBeforeShutdown ) );
204 }
205
206 if ( timeoutForced > 0 )
207 {
208 executedTests.addAll( printShutdownHook( testsBeforeForcedShutdown ) );
209 }
210
211 StringBuilder msg = new StringBuilder();
212 if ( !executedTests.isEmpty() )
213 {
214 msg.append( "The test run has finished abruptly after timeout of " );
215 msg.append( Math.min( timeout, timeoutForced ) );
216 msg.append( " seconds.\n" );
217 msg.append( "These tests were executed in prior of the shutdown operation:\n" );
218 for ( String executedTest : executedTests )
219 {
220 msg.append( executedTest ).append( "\n" );
221 }
222 }
223 return msg.toString();
224 }
225
226 static Collection<String> printShutdownHook( Future<Collection<Description>> future )
227 throws TestSetFailedException
228 {
229 if ( !future.isCancelled() && future.isDone() )
230 {
231 try
232 {
233 TreeSet<String> executedTests = new TreeSet<String>();
234 for ( Description executedTest : future.get() )
235 {
236 if ( executedTest != null && executedTest.getDisplayName() != null )
237 {
238 executedTests.add( executedTest.getDisplayName() );
239 }
240 }
241 return executedTests;
242 }
243 catch ( Exception e )
244 {
245 throw new TestSetFailedException( e );
246 }
247 }
248 return Collections.emptySet();
249 }
250 }
251 }