View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.surefire.junitcore.pc;
20  
21  import java.util.Collections;
22  import java.util.HashMap;
23  import java.util.Map;
24  import java.util.concurrent.TimeUnit;
25  
26  import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
27  import org.apache.maven.surefire.api.testset.TestSetFailedException;
28  import org.apache.maven.surefire.junitcore.JUnitCoreParameters;
29  import org.junit.AfterClass;
30  import org.junit.Before;
31  import org.junit.BeforeClass;
32  import org.junit.Rule;
33  import org.junit.Test;
34  import org.junit.experimental.theories.DataPoint;
35  import org.junit.experimental.theories.Theories;
36  import org.junit.experimental.theories.Theory;
37  import org.junit.rules.ExpectedException;
38  import org.junit.runner.JUnitCore;
39  import org.junit.runner.Result;
40  import org.junit.runner.RunWith;
41  
42  import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.PARALLEL_KEY;
43  import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.PARALLEL_TIMEOUTFORCED_KEY;
44  import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.PARALLEL_TIMEOUT_KEY;
45  import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNTCLASSES_KEY;
46  import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNTMETHODS_KEY;
47  import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNTSUITES_KEY;
48  import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNT_KEY;
49  import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.USEUNLIMITEDTHREADS_KEY;
50  import static org.apache.maven.surefire.junitcore.pc.ParallelComputerUtil.resolveConcurrency;
51  import static org.hamcrest.core.Is.is;
52  import static org.junit.Assert.assertEquals;
53  import static org.junit.Assert.assertFalse;
54  import static org.junit.Assert.assertThat;
55  import static org.junit.Assert.assertTrue;
56  import static org.mockito.Mockito.mock;
57  
58  /**
59   * Testing an algorithm in {@link ParallelComputerUtil} which configures allocated thread resources in ParallelComputer
60   * by given {@link org.apache.maven.surefire.junitcore.JUnitCoreParameters}.
61   *
62   * @author Tibor Digana (tibor17)
63   * @see ParallelComputerUtil
64   * @since 2.16
65   */
66  @RunWith(Theories.class)
67  @SuppressWarnings("checkstyle:magicnumber")
68  public final class ParallelComputerUtilTest {
69      private static final ConsoleLogger LOGGER = mock(ConsoleLogger.class);
70  
71      @DataPoint
72      public static final int CPU_1 = 1;
73  
74      @DataPoint
75      public static final int CPU_4 = 4;
76  
77      @Rule
78      public final ExpectedException exception = ExpectedException.none();
79  
80      @BeforeClass
81      public static void beforeClass() {
82          ParallelComputerUtil.overrideAvailableProcessors(1);
83      }
84  
85      @AfterClass
86      public static void afterClass() {
87          ParallelComputerUtil.setDefaultAvailableProcessors();
88      }
89  
90      @Before
91      public void beforeTest() throws InterruptedException {
92          System.gc();
93          Thread.sleep(50L);
94          assertFalse(Thread.currentThread().isInterrupted());
95      }
96  
97      private static Map<String, String> parallel(String parallel) {
98          return Collections.singletonMap(PARALLEL_KEY, parallel);
99      }
100 
101     @Test
102     public void unknownParallel() throws TestSetFailedException {
103         Map<String, String> properties = new HashMap<>();
104         exception.expect(TestSetFailedException.class);
105         resolveConcurrency(new JUnitCoreParameters(properties), null);
106     }
107 
108     @Test
109     public void unknownThreadCountSuites() throws TestSetFailedException {
110         JUnitCoreParameters params = new JUnitCoreParameters(parallel("suites"));
111         assertTrue(params.isParallelSuites());
112         assertFalse(params.isParallelClasses());
113         assertFalse(params.isParallelMethods());
114         exception.expect(TestSetFailedException.class);
115         resolveConcurrency(params, null);
116     }
117 
118     @Test
119     public void unknownThreadCountClasses() throws TestSetFailedException {
120         JUnitCoreParameters params = new JUnitCoreParameters(parallel("classes"));
121         assertFalse(params.isParallelSuites());
122         assertTrue(params.isParallelClasses());
123         assertFalse(params.isParallelMethods());
124         exception.expect(TestSetFailedException.class);
125         resolveConcurrency(params, null);
126     }
127 
128     @Test
129     public void unknownThreadCountMethods() throws TestSetFailedException {
130         JUnitCoreParameters params = new JUnitCoreParameters(parallel("methods"));
131         assertFalse(params.isParallelSuites());
132         assertFalse(params.isParallelClasses());
133         assertTrue(params.isParallelMethods());
134         exception.expect(TestSetFailedException.class);
135         resolveConcurrency(params, null);
136     }
137 
138     @Test
139     public void unknownThreadCountBoth() throws TestSetFailedException {
140         JUnitCoreParameters params = new JUnitCoreParameters(parallel("both"));
141         assertFalse(params.isParallelSuites());
142         assertTrue(params.isParallelClasses());
143         assertTrue(params.isParallelMethods());
144         exception.expect(TestSetFailedException.class);
145         resolveConcurrency(params, null);
146     }
147 
148     @Test
149     public void unknownThreadCountAll() throws TestSetFailedException {
150         JUnitCoreParameters params = new JUnitCoreParameters(parallel("all"));
151         assertTrue(params.isParallelSuites());
152         assertTrue(params.isParallelClasses());
153         assertTrue(params.isParallelMethods());
154         exception.expect(TestSetFailedException.class);
155         resolveConcurrency(params, null);
156     }
157 
158     @Test
159     public void unknownThreadCountSuitesAndClasses() throws TestSetFailedException {
160         JUnitCoreParameters params = new JUnitCoreParameters(parallel("suitesAndClasses"));
161         assertTrue(params.isParallelSuites());
162         assertTrue(params.isParallelClasses());
163         assertFalse(params.isParallelMethods());
164         exception.expect(TestSetFailedException.class);
165         resolveConcurrency(params, null);
166     }
167 
168     @Test
169     public void unknownThreadCountSuitesAndMethods() throws TestSetFailedException {
170         JUnitCoreParameters params = new JUnitCoreParameters(parallel("suitesAndMethods"));
171         assertTrue(params.isParallelSuites());
172         assertFalse(params.isParallelClasses());
173         assertTrue(params.isParallelMethods());
174         exception.expect(TestSetFailedException.class);
175         resolveConcurrency(params, null);
176     }
177 
178     @Test
179     public void unknownThreadCountClassesAndMethods() throws TestSetFailedException {
180         JUnitCoreParameters params = new JUnitCoreParameters(parallel("classesAndMethods"));
181         assertFalse(params.isParallelSuites());
182         assertTrue(params.isParallelClasses());
183         assertTrue(params.isParallelMethods());
184         exception.expect(TestSetFailedException.class);
185         resolveConcurrency(params, null);
186     }
187 
188     @Theory
189     public void useUnlimitedThreadsSuites(int cpu) throws TestSetFailedException {
190         ParallelComputerUtil.overrideAvailableProcessors(cpu);
191         Map<String, String> properties = new HashMap<>();
192         properties.put(PARALLEL_KEY, "suites");
193         properties.put(USEUNLIMITEDTHREADS_KEY, "true");
194         JUnitCoreParameters params = new JUnitCoreParameters(properties);
195         Concurrency concurrency = resolveConcurrency(params, null);
196         assertTrue(params.isParallelSuites());
197         assertFalse(params.isParallelClasses());
198         assertFalse(params.isParallelMethods());
199         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
200         assertThat(concurrency.suites, is(Integer.MAX_VALUE));
201         assertThat(concurrency.classes, is(0));
202         assertThat(concurrency.methods, is(0));
203 
204         properties.put(THREADCOUNTSUITES_KEY, "5");
205         params = new JUnitCoreParameters(properties);
206         concurrency = resolveConcurrency(params, null);
207         assertTrue(params.isParallelSuites());
208         assertFalse(params.isParallelClasses());
209         assertFalse(params.isParallelMethods());
210         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
211         assertThat(concurrency.suites, is(5 * cpu));
212         assertThat(concurrency.classes, is(0));
213         assertThat(concurrency.methods, is(0));
214     }
215 
216     @Theory
217     public void useUnlimitedThreadsClasses(int cpu) throws TestSetFailedException {
218         ParallelComputerUtil.overrideAvailableProcessors(cpu);
219         Map<String, String> properties = new HashMap<>();
220         properties.put(PARALLEL_KEY, "classes");
221         properties.put(USEUNLIMITEDTHREADS_KEY, "true");
222         JUnitCoreParameters params = new JUnitCoreParameters(properties);
223         Concurrency concurrency = resolveConcurrency(params, null);
224         assertFalse(params.isParallelSuites());
225         assertTrue(params.isParallelClasses());
226         assertFalse(params.isParallelMethods());
227         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
228         assertThat(concurrency.suites, is(0));
229         assertThat(concurrency.classes, is(Integer.MAX_VALUE));
230         assertThat(concurrency.methods, is(0));
231 
232         properties.put(THREADCOUNTCLASSES_KEY, "5");
233         params = new JUnitCoreParameters(properties);
234         concurrency = resolveConcurrency(params, null);
235         assertFalse(params.isParallelSuites());
236         assertTrue(params.isParallelClasses());
237         assertFalse(params.isParallelMethods());
238         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
239         assertThat(concurrency.suites, is(0));
240         assertThat(concurrency.classes, is(5 * cpu));
241         assertThat(concurrency.methods, is(0));
242     }
243 
244     @Theory
245     public void unlimitedThreadsMethods(int cpu) throws TestSetFailedException {
246         ParallelComputerUtil.overrideAvailableProcessors(cpu);
247         Map<String, String> properties = new HashMap<>();
248         properties.put(PARALLEL_KEY, "methods");
249         properties.put(USEUNLIMITEDTHREADS_KEY, "true");
250         JUnitCoreParameters params = new JUnitCoreParameters(properties);
251         Concurrency concurrency = resolveConcurrency(params, null);
252         assertFalse(params.isParallelSuites());
253         assertFalse(params.isParallelClasses());
254         assertTrue(params.isParallelMethods());
255         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
256         assertThat(concurrency.suites, is(0));
257         assertThat(concurrency.classes, is(0));
258         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
259 
260         properties.put(THREADCOUNTMETHODS_KEY, "5");
261         params = new JUnitCoreParameters(properties);
262         concurrency = resolveConcurrency(params, null);
263         assertFalse(params.isParallelSuites());
264         assertFalse(params.isParallelClasses());
265         assertTrue(params.isParallelMethods());
266         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
267         assertThat(concurrency.suites, is(0));
268         assertThat(concurrency.classes, is(0));
269         assertThat(concurrency.methods, is(5 * cpu));
270     }
271 
272     @Theory
273     public void unlimitedThreadsSuitesAndClasses(int cpu) throws TestSetFailedException {
274         ParallelComputerUtil.overrideAvailableProcessors(cpu);
275         Map<String, String> properties = new HashMap<>();
276         properties.put(PARALLEL_KEY, "suitesAndClasses");
277         properties.put(USEUNLIMITEDTHREADS_KEY, "true");
278         JUnitCoreParameters params = new JUnitCoreParameters(properties);
279         Concurrency concurrency = resolveConcurrency(params, null);
280         assertTrue(params.isParallelSuites());
281         assertTrue(params.isParallelClasses());
282         assertFalse(params.isParallelMethods());
283         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
284         assertThat(concurrency.suites, is(Integer.MAX_VALUE));
285         assertThat(concurrency.classes, is(Integer.MAX_VALUE));
286         assertThat(concurrency.methods, is(0));
287 
288         properties.put(THREADCOUNTSUITES_KEY, "5");
289         properties.put(THREADCOUNTCLASSES_KEY, "15");
290         params = new JUnitCoreParameters(properties);
291         concurrency = resolveConcurrency(params, null);
292         assertTrue(params.isParallelSuites());
293         assertTrue(params.isParallelClasses());
294         assertFalse(params.isParallelMethods());
295         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
296         assertThat(concurrency.suites, is(5 * cpu));
297         assertThat(concurrency.classes, is(15 * cpu));
298         assertThat(concurrency.methods, is(0));
299     }
300 
301     @Theory
302     public void unlimitedThreadsSuitesAndMethods(int cpu) throws TestSetFailedException {
303         ParallelComputerUtil.overrideAvailableProcessors(cpu);
304         Map<String, String> properties = new HashMap<>();
305         properties.put(PARALLEL_KEY, "suitesAndMethods");
306         properties.put(USEUNLIMITEDTHREADS_KEY, "true");
307         JUnitCoreParameters params = new JUnitCoreParameters(properties);
308         Concurrency concurrency = resolveConcurrency(params, null);
309         assertTrue(params.isParallelSuites());
310         assertFalse(params.isParallelClasses());
311         assertTrue(params.isParallelMethods());
312         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
313         assertThat(concurrency.suites, is(Integer.MAX_VALUE));
314         assertThat(concurrency.classes, is(0));
315         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
316 
317         properties.put(THREADCOUNTSUITES_KEY, "5");
318         properties.put(THREADCOUNTMETHODS_KEY, "15");
319         params = new JUnitCoreParameters(properties);
320         concurrency = resolveConcurrency(params, null);
321         assertTrue(params.isParallelSuites());
322         assertFalse(params.isParallelClasses());
323         assertTrue(params.isParallelMethods());
324         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
325         assertThat(concurrency.suites, is(5 * cpu));
326         assertThat(concurrency.classes, is(0));
327         assertThat(concurrency.methods, is(15 * cpu));
328     }
329 
330     @Theory
331     public void unlimitedThreadsClassesAndMethods(int cpu) throws TestSetFailedException {
332         ParallelComputerUtil.overrideAvailableProcessors(cpu);
333         Map<String, String> properties = new HashMap<>();
334         properties.put(PARALLEL_KEY, "classesAndMethods");
335         properties.put(USEUNLIMITEDTHREADS_KEY, "true");
336         JUnitCoreParameters params = new JUnitCoreParameters(properties);
337         Concurrency concurrency = resolveConcurrency(params, null);
338         assertFalse(params.isParallelSuites());
339         assertTrue(params.isParallelClasses());
340         assertTrue(params.isParallelMethods());
341         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
342         assertThat(concurrency.suites, is(0));
343         assertThat(concurrency.classes, is(Integer.MAX_VALUE));
344         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
345 
346         properties.put(THREADCOUNTCLASSES_KEY, "5");
347         properties.put(THREADCOUNTMETHODS_KEY, "15");
348         params = new JUnitCoreParameters(properties);
349         concurrency = resolveConcurrency(params, null);
350         assertFalse(params.isParallelSuites());
351         assertTrue(params.isParallelClasses());
352         assertTrue(params.isParallelMethods());
353         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
354         assertThat(concurrency.suites, is(0));
355         assertThat(concurrency.classes, is(5 * cpu));
356         assertThat(concurrency.methods, is(15 * cpu));
357     }
358 
359     @Theory
360     public void unlimitedThreadsAll(int cpu) throws TestSetFailedException {
361         ParallelComputerUtil.overrideAvailableProcessors(cpu);
362         Map<String, String> properties = new HashMap<>();
363         properties.put(PARALLEL_KEY, "all");
364         properties.put(USEUNLIMITEDTHREADS_KEY, "true");
365         JUnitCoreParameters params = new JUnitCoreParameters(properties);
366         Concurrency concurrency = resolveConcurrency(params, null);
367         assertTrue(params.isParallelSuites());
368         assertTrue(params.isParallelClasses());
369         assertTrue(params.isParallelMethods());
370         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
371         assertThat(concurrency.suites, is(Integer.MAX_VALUE));
372         assertThat(concurrency.classes, is(Integer.MAX_VALUE));
373         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
374 
375         properties.put(THREADCOUNTSUITES_KEY, "5");
376         properties.put(THREADCOUNTCLASSES_KEY, "15");
377         properties.put(THREADCOUNTMETHODS_KEY, "30");
378         params = new JUnitCoreParameters(properties);
379         concurrency = resolveConcurrency(params, null);
380         assertTrue(params.isParallelSuites());
381         assertTrue(params.isParallelClasses());
382         assertTrue(params.isParallelMethods());
383         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
384         assertThat(concurrency.suites, is(5 * cpu));
385         assertThat(concurrency.classes, is(15 * cpu));
386         assertThat(concurrency.methods, is(30 * cpu));
387     }
388 
389     @Theory
390     public void threadCountSuites(int cpu) throws TestSetFailedException {
391         ParallelComputerUtil.overrideAvailableProcessors(cpu);
392         Map<String, String> properties = new HashMap<>();
393         properties.put(PARALLEL_KEY, "suites");
394         properties.put(THREADCOUNT_KEY, "3");
395         JUnitCoreParameters params = new JUnitCoreParameters(properties);
396         Concurrency concurrency = resolveConcurrency(params, null);
397         assertTrue(params.isParallelSuites());
398         assertFalse(params.isParallelClasses());
399         assertFalse(params.isParallelMethods());
400         assertThat(concurrency.capacity, is(0));
401         assertThat(concurrency.suites, is(3 * cpu));
402         assertThat(concurrency.classes, is(0));
403         assertThat(concurrency.methods, is(0));
404     }
405 
406     @Theory
407     public void threadCountClasses(int cpu) throws TestSetFailedException {
408         ParallelComputerUtil.overrideAvailableProcessors(cpu);
409         Map<String, String> properties = new HashMap<>();
410         properties.put(PARALLEL_KEY, "classes");
411         properties.put(THREADCOUNT_KEY, "3");
412         JUnitCoreParameters params = new JUnitCoreParameters(properties);
413         Concurrency concurrency = resolveConcurrency(params, null);
414         assertFalse(params.isParallelSuites());
415         assertTrue(params.isParallelClasses());
416         assertFalse(params.isParallelMethods());
417         assertThat(concurrency.capacity, is(0));
418         assertThat(concurrency.suites, is(0));
419         assertThat(concurrency.classes, is(3 * cpu));
420         assertThat(concurrency.methods, is(0));
421     }
422 
423     @Theory
424     public void threadCountMethods(int cpu) throws TestSetFailedException {
425         ParallelComputerUtil.overrideAvailableProcessors(cpu);
426         Map<String, String> properties = new HashMap<>();
427         properties.put(PARALLEL_KEY, "methods");
428         properties.put(THREADCOUNT_KEY, "3");
429         JUnitCoreParameters params = new JUnitCoreParameters(properties);
430         Concurrency concurrency = resolveConcurrency(params, null);
431         assertFalse(params.isParallelSuites());
432         assertFalse(params.isParallelClasses());
433         assertTrue(params.isParallelMethods());
434         assertThat(concurrency.capacity, is(0));
435         assertThat(concurrency.suites, is(0));
436         assertThat(concurrency.classes, is(0));
437         assertThat(concurrency.methods, is(3 * cpu));
438     }
439 
440     @Theory
441     public void threadCountBoth(int cpu) throws TestSetFailedException {
442         ParallelComputerUtil.overrideAvailableProcessors(cpu);
443         Map<String, String> properties = new HashMap<>();
444         properties.put(PARALLEL_KEY, "both");
445         properties.put(THREADCOUNT_KEY, "3");
446         JUnitCoreParameters params = new JUnitCoreParameters(properties);
447         Concurrency concurrency = resolveConcurrency(params, null);
448         assertFalse(params.isParallelSuites());
449         assertTrue(params.isParallelClasses());
450         assertTrue(params.isParallelMethods());
451         assertThat(concurrency.capacity, is(3 * cpu));
452         assertThat(concurrency.suites, is(0));
453         assertThat(concurrency.classes, is((int) ((3d / 2) * cpu)));
454         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
455     }
456 
457     @Theory
458     public void threadCountClassesAndMethods(int cpu) throws TestSetFailedException {
459         ParallelComputerUtil.overrideAvailableProcessors(cpu);
460         Map<String, String> properties = new HashMap<>();
461         properties.put(PARALLEL_KEY, "classesAndMethods");
462         properties.put(THREADCOUNT_KEY, "3");
463         JUnitCoreParameters params = new JUnitCoreParameters(properties);
464         Concurrency concurrency = resolveConcurrency(params, null);
465         assertFalse(params.isParallelSuites());
466         assertTrue(params.isParallelClasses());
467         assertTrue(params.isParallelMethods());
468         assertThat(concurrency.capacity, is(3 * cpu));
469         assertThat(concurrency.suites, is(0));
470         assertThat(concurrency.classes, is((int) ((3d / 2) * cpu)));
471         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
472     }
473 
474     @Theory
475     public void threadCountSuitesAndMethods(int cpu) throws TestSetFailedException {
476         ParallelComputerUtil.overrideAvailableProcessors(cpu);
477         Map<String, String> properties = new HashMap<>();
478         properties.put(PARALLEL_KEY, "suitesAndMethods");
479         properties.put(THREADCOUNT_KEY, "3");
480         JUnitCoreParameters params = new JUnitCoreParameters(properties);
481         Concurrency concurrency = resolveConcurrency(params, null);
482         assertTrue(params.isParallelSuites());
483         assertFalse(params.isParallelClasses());
484         assertTrue(params.isParallelMethods());
485         assertThat(concurrency.capacity, is(3 * cpu));
486         assertThat(concurrency.suites, is((int) ((3d / 2) * cpu)));
487         assertThat(concurrency.classes, is(0));
488         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
489     }
490 
491     @Theory
492     public void threadCountSuitesAndClasses(int cpu) throws TestSetFailedException {
493         ParallelComputerUtil.overrideAvailableProcessors(cpu);
494         Map<String, String> properties = new HashMap<>();
495         properties.put(PARALLEL_KEY, "suitesAndClasses");
496         properties.put(THREADCOUNT_KEY, "3");
497         JUnitCoreParameters params = new JUnitCoreParameters(properties);
498         Concurrency concurrency = resolveConcurrency(params, null);
499         assertTrue(params.isParallelSuites());
500         assertTrue(params.isParallelClasses());
501         assertFalse(params.isParallelMethods());
502         assertThat(concurrency.capacity, is(3 * cpu));
503         assertThat(concurrency.suites, is((int) ((3d / 2) * cpu)));
504         assertThat(concurrency.classes, is(Integer.MAX_VALUE));
505         assertThat(concurrency.methods, is(0));
506     }
507 
508     @Theory
509     public void threadCountAll(int cpu) throws TestSetFailedException {
510         ParallelComputerUtil.overrideAvailableProcessors(cpu);
511         Map<String, String> properties = new HashMap<>();
512         properties.put(PARALLEL_KEY, "all");
513         properties.put(THREADCOUNT_KEY, "3");
514         JUnitCoreParameters params = new JUnitCoreParameters(properties);
515         Concurrency concurrency = resolveConcurrency(params, null);
516         assertTrue(params.isParallelSuites());
517         assertTrue(params.isParallelClasses());
518         assertTrue(params.isParallelMethods());
519         assertThat(concurrency.capacity, is(3 * cpu));
520         assertThat(concurrency.suites, is(cpu));
521         assertThat(concurrency.classes, is(cpu));
522         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
523     }
524 
525     @Theory
526     public void everyThreadCountSuitesAndClasses(int cpu) throws TestSetFailedException {
527         ParallelComputerUtil.overrideAvailableProcessors(cpu);
528         Map<String, String> properties = new HashMap<>();
529         properties.put(PARALLEL_KEY, "suitesAndClasses");
530         properties.put(THREADCOUNT_KEY, "3");
531         // % percentage ratio
532         properties.put(THREADCOUNTSUITES_KEY, "34");
533         properties.put(THREADCOUNTCLASSES_KEY, "66");
534         JUnitCoreParameters params = new JUnitCoreParameters(properties);
535         Concurrency concurrency = resolveConcurrency(params, null);
536         assertTrue(params.isParallelSuites());
537         assertTrue(params.isParallelClasses());
538         assertFalse(params.isParallelMethods());
539         assertThat(concurrency.capacity, is(3 * cpu));
540         int concurrentSuites = (int) (0.34d * concurrency.capacity);
541         assertThat(concurrency.suites, is(concurrentSuites));
542         assertThat(concurrency.classes, is(concurrency.capacity - concurrentSuites));
543         assertThat(concurrency.methods, is(0));
544     }
545 
546     @Theory
547     public void everyThreadCountSuitesAndMethods(int cpu) throws TestSetFailedException {
548         ParallelComputerUtil.overrideAvailableProcessors(cpu);
549         Map<String, String> properties = new HashMap<>();
550         properties.put(PARALLEL_KEY, "suitesAndMethods");
551         properties.put(THREADCOUNT_KEY, "3");
552         // % percentage ratio
553         properties.put(THREADCOUNTSUITES_KEY, "34");
554         properties.put(THREADCOUNTMETHODS_KEY, "66");
555         JUnitCoreParameters params = new JUnitCoreParameters(properties);
556         Concurrency concurrency = resolveConcurrency(params, null);
557         assertTrue(params.isParallelSuites());
558         assertFalse(params.isParallelClasses());
559         assertTrue(params.isParallelMethods());
560         assertThat(concurrency.capacity, is(3 * cpu));
561         int concurrentSuites = (int) (0.34d * concurrency.capacity);
562         assertThat(concurrency.suites, is(concurrentSuites));
563         assertThat(concurrency.classes, is(0));
564         assertThat(concurrency.methods, is(concurrency.capacity - concurrentSuites));
565     }
566 
567     @Theory
568     public void everyThreadCountClassesAndMethods(int cpu) throws TestSetFailedException {
569         ParallelComputerUtil.overrideAvailableProcessors(cpu);
570         Map<String, String> properties = new HashMap<>();
571         properties.put(PARALLEL_KEY, "classesAndMethods");
572         properties.put(THREADCOUNT_KEY, "3");
573         // % percentage ratio
574         properties.put(THREADCOUNTCLASSES_KEY, "34");
575         properties.put(THREADCOUNTMETHODS_KEY, "66");
576         JUnitCoreParameters params = new JUnitCoreParameters(properties);
577         Concurrency concurrency = resolveConcurrency(params, null);
578         assertFalse(params.isParallelSuites());
579         assertTrue(params.isParallelClasses());
580         assertTrue(params.isParallelMethods());
581         assertThat(concurrency.capacity, is(3 * cpu));
582         assertThat(concurrency.suites, is(0));
583         int concurrentClasses = (int) (0.34d * concurrency.capacity);
584         assertThat(concurrency.classes, is(concurrentClasses));
585         assertThat(concurrency.methods, is(concurrency.capacity - concurrentClasses));
586     }
587 
588     @Theory
589     public void everyThreadCountAll(int cpu) throws TestSetFailedException {
590         ParallelComputerUtil.overrideAvailableProcessors(cpu);
591         Map<String, String> properties = new HashMap<>();
592         properties.put(PARALLEL_KEY, "all");
593         properties.put(THREADCOUNT_KEY, "3");
594         // % percentage ratio
595         properties.put(THREADCOUNTSUITES_KEY, "17");
596         properties.put(THREADCOUNTCLASSES_KEY, "34");
597         properties.put(THREADCOUNTMETHODS_KEY, "49");
598         JUnitCoreParameters params = new JUnitCoreParameters(properties);
599         Concurrency concurrency = resolveConcurrency(params, null);
600         assertTrue(params.isParallelSuites());
601         assertTrue(params.isParallelClasses());
602         assertTrue(params.isParallelMethods());
603         assertThat(concurrency.capacity, is(3 * cpu));
604         int concurrentSuites = (int) (0.17d * concurrency.capacity);
605         int concurrentClasses = (int) (0.34d * concurrency.capacity);
606         assertThat(concurrency.suites, is(concurrentSuites));
607         assertThat(concurrency.classes, is(concurrentClasses));
608         assertThat(concurrency.methods, is(concurrency.capacity - concurrentSuites - concurrentClasses));
609     }
610 
611     @Theory
612     public void reusableThreadCountSuitesAndClasses(int cpu) throws TestSetFailedException {
613         // 4 * cpu to 5 * cpu threads to run test classes
614         ParallelComputerUtil.overrideAvailableProcessors(cpu);
615         Map<String, String> properties = new HashMap<>();
616         properties.put(PARALLEL_KEY, "suitesAndClasses");
617         properties.put(THREADCOUNT_KEY, "6");
618         properties.put(THREADCOUNTSUITES_KEY, "2");
619         JUnitCoreParameters params = new JUnitCoreParameters(properties);
620         Concurrency concurrency = resolveConcurrency(params, null);
621         assertTrue(params.isParallelSuites());
622         assertTrue(params.isParallelClasses());
623         assertFalse(params.isParallelMethods());
624         assertThat(concurrency.capacity, is(6 * cpu));
625         assertThat(concurrency.suites, is(2 * cpu));
626         assertThat(concurrency.classes, is(Integer.MAX_VALUE));
627         assertThat(concurrency.methods, is(0));
628     }
629 
630     @Theory
631     public void reusableThreadCountSuitesAndMethods(int cpu) throws TestSetFailedException {
632         // 4 * cpu to 5 * cpu threads to run test methods
633         ParallelComputerUtil.overrideAvailableProcessors(cpu);
634         Map<String, String> properties = new HashMap<>();
635         properties.put(PARALLEL_KEY, "suitesAndMethods");
636         properties.put(THREADCOUNT_KEY, "6");
637         properties.put(THREADCOUNTSUITES_KEY, "2");
638         JUnitCoreParameters params = new JUnitCoreParameters(properties);
639         Concurrency concurrency = resolveConcurrency(params, null);
640         assertTrue(params.isParallelSuites());
641         assertFalse(params.isParallelClasses());
642         assertTrue(params.isParallelMethods());
643         assertThat(concurrency.capacity, is(6 * cpu));
644         assertThat(concurrency.suites, is(2 * cpu));
645         assertThat(concurrency.classes, is(0));
646         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
647     }
648 
649     @Theory
650     public void reusableThreadCountClassesAndMethods(int cpu) throws TestSetFailedException {
651         // 4 * cpu to 5 * cpu threads to run test methods
652         ParallelComputerUtil.overrideAvailableProcessors(cpu);
653         Map<String, String> properties = new HashMap<>();
654         properties.put(PARALLEL_KEY, "classesAndMethods");
655         properties.put(THREADCOUNT_KEY, "6");
656         properties.put(THREADCOUNTCLASSES_KEY, "2");
657         JUnitCoreParameters params = new JUnitCoreParameters(properties);
658         Concurrency concurrency = resolveConcurrency(params, null);
659         assertFalse(params.isParallelSuites());
660         assertTrue(params.isParallelClasses());
661         assertTrue(params.isParallelMethods());
662         assertThat(concurrency.capacity, is(6 * cpu));
663         assertThat(concurrency.suites, is(0));
664         assertThat(concurrency.classes, is(2 * cpu));
665         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
666     }
667 
668     @Theory
669     public void reusableThreadCountAll(int cpu) throws TestSetFailedException {
670         // 8 * cpu to 13 * cpu threads to run test methods
671         ParallelComputerUtil.overrideAvailableProcessors(cpu);
672         Map<String, String> properties = new HashMap<>();
673         properties.put(PARALLEL_KEY, "all");
674         properties.put(THREADCOUNT_KEY, "14");
675         properties.put(THREADCOUNTSUITES_KEY, "2");
676         properties.put(THREADCOUNTCLASSES_KEY, "4");
677         JUnitCoreParameters params = new JUnitCoreParameters(properties);
678         Concurrency concurrency = resolveConcurrency(params, null);
679         assertTrue(params.isParallelSuites());
680         assertTrue(params.isParallelClasses());
681         assertTrue(params.isParallelMethods());
682         assertThat(concurrency.capacity, is(14 * cpu));
683         assertThat(concurrency.suites, is(2 * cpu));
684         assertThat(concurrency.classes, is(4 * cpu));
685         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
686     }
687 
688     @Theory
689     public void suites(int cpu) throws TestSetFailedException {
690         ParallelComputerUtil.overrideAvailableProcessors(cpu);
691         Map<String, String> properties = new HashMap<>();
692         properties.put(PARALLEL_KEY, "suites");
693         properties.put(THREADCOUNTSUITES_KEY, "5");
694         JUnitCoreParameters params = new JUnitCoreParameters(properties);
695         Concurrency concurrency = resolveConcurrency(params, null);
696         assertTrue(params.isParallelSuites());
697         assertFalse(params.isParallelClasses());
698         assertFalse(params.isParallelMethods());
699         assertThat(concurrency.capacity, is(5 * cpu));
700         assertThat(concurrency.suites, is(5 * cpu));
701         assertThat(concurrency.classes, is(0));
702         assertThat(concurrency.methods, is(0));
703     }
704 
705     @Theory
706     public void classes(int cpu) throws TestSetFailedException {
707         ParallelComputerUtil.overrideAvailableProcessors(cpu);
708         Map<String, String> properties = new HashMap<>();
709         properties.put(PARALLEL_KEY, "classes");
710         properties.put(THREADCOUNTCLASSES_KEY, "5");
711         JUnitCoreParameters params = new JUnitCoreParameters(properties);
712         Concurrency concurrency = resolveConcurrency(params, null);
713         assertFalse(params.isParallelSuites());
714         assertTrue(params.isParallelClasses());
715         assertFalse(params.isParallelMethods());
716         assertThat(concurrency.capacity, is(5 * cpu));
717         assertThat(concurrency.suites, is(0));
718         assertThat(concurrency.classes, is(5 * cpu));
719         assertThat(concurrency.methods, is(0));
720     }
721 
722     @Theory
723     public void methods(int cpu) throws TestSetFailedException {
724         ParallelComputerUtil.overrideAvailableProcessors(cpu);
725         Map<String, String> properties = new HashMap<>();
726         properties.put(PARALLEL_KEY, "methods");
727         properties.put(THREADCOUNTMETHODS_KEY, "5");
728         JUnitCoreParameters params = new JUnitCoreParameters(properties);
729         Concurrency concurrency = resolveConcurrency(params, null);
730         assertFalse(params.isParallelSuites());
731         assertFalse(params.isParallelClasses());
732         assertTrue(params.isParallelMethods());
733         assertThat(concurrency.capacity, is(5 * cpu));
734         assertThat(concurrency.suites, is(0));
735         assertThat(concurrency.classes, is(0));
736         assertThat(concurrency.methods, is(5 * cpu));
737     }
738 
739     @Theory
740     public void suitesAndClasses(int cpu) throws TestSetFailedException {
741         ParallelComputerUtil.overrideAvailableProcessors(cpu);
742         Map<String, String> properties = new HashMap<>();
743 
744         properties.put(PARALLEL_KEY, "suitesAndClasses");
745         properties.put(THREADCOUNTSUITES_KEY, "5");
746         properties.put(THREADCOUNTCLASSES_KEY, "15");
747         JUnitCoreParameters params = new JUnitCoreParameters(properties);
748         Concurrency concurrency = resolveConcurrency(params, null);
749         assertTrue(params.isParallelSuites());
750         assertTrue(params.isParallelClasses());
751         assertFalse(params.isParallelMethods());
752         assertThat(concurrency.capacity, is(20 * cpu));
753         assertThat(concurrency.suites, is(5 * cpu));
754         assertThat(concurrency.classes, is(15 * cpu));
755         assertThat(concurrency.methods, is(0));
756 
757         // Warning: this case works but is not enabled in AbstractSurefireMojo
758         // Instead use the 'useUnlimitedThreads' parameter.
759         properties = new HashMap<>();
760         properties.put(PARALLEL_KEY, "suitesAndClasses");
761         properties.put(THREADCOUNTSUITES_KEY, "5");
762         params = new JUnitCoreParameters(properties);
763         concurrency = resolveConcurrency(params, null);
764         assertTrue(params.isParallelSuites());
765         assertTrue(params.isParallelClasses());
766         assertFalse(params.isParallelMethods());
767         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
768         assertThat(concurrency.suites, is(5 * cpu));
769         assertThat(concurrency.classes, is(Integer.MAX_VALUE));
770         assertThat(concurrency.methods, is(0));
771     }
772 
773     @Theory
774     public void suitesAndMethods(int cpu) throws TestSetFailedException {
775         ParallelComputerUtil.overrideAvailableProcessors(cpu);
776         Map<String, String> properties = new HashMap<>();
777 
778         properties.put(PARALLEL_KEY, "suitesAndMethods");
779         properties.put(THREADCOUNTSUITES_KEY, "5");
780         properties.put(THREADCOUNTMETHODS_KEY, "15");
781         JUnitCoreParameters params = new JUnitCoreParameters(properties);
782         Concurrency concurrency = resolveConcurrency(params, null);
783         assertTrue(params.isParallelSuites());
784         assertFalse(params.isParallelClasses());
785         assertTrue(params.isParallelMethods());
786         assertThat(concurrency.capacity, is(20 * cpu));
787         assertThat(concurrency.suites, is(5 * cpu));
788         assertThat(concurrency.classes, is(0));
789         assertThat(concurrency.methods, is(15 * cpu));
790 
791         // Warning: this case works but is not enabled in AbstractSurefireMojo
792         // Instead use the 'useUnlimitedThreads' parameter.
793         properties = new HashMap<>();
794         properties.put(PARALLEL_KEY, "suitesAndMethods");
795         properties.put(THREADCOUNTSUITES_KEY, "5");
796         params = new JUnitCoreParameters(properties);
797         concurrency = resolveConcurrency(params, null);
798         assertTrue(params.isParallelSuites());
799         assertFalse(params.isParallelClasses());
800         assertTrue(params.isParallelMethods());
801         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
802         assertThat(concurrency.suites, is(5 * cpu));
803         assertThat(concurrency.classes, is(0));
804         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
805     }
806 
807     @Theory
808     public void classesAndMethods(int cpu) throws TestSetFailedException {
809         ParallelComputerUtil.overrideAvailableProcessors(cpu);
810         Map<String, String> properties = new HashMap<>();
811 
812         properties.put(PARALLEL_KEY, "classesAndMethods");
813         properties.put(THREADCOUNTCLASSES_KEY, "5");
814         properties.put(THREADCOUNTMETHODS_KEY, "15");
815         JUnitCoreParameters params = new JUnitCoreParameters(properties);
816         Concurrency concurrency = resolveConcurrency(params, null);
817         assertFalse(params.isParallelSuites());
818         assertTrue(params.isParallelClasses());
819         assertTrue(params.isParallelMethods());
820         assertThat(concurrency.capacity, is(20 * cpu));
821         assertThat(concurrency.suites, is(0));
822         assertThat(concurrency.classes, is(5 * cpu));
823         assertThat(concurrency.methods, is(15 * cpu));
824 
825         // Warning: this case works but is not enabled in AbstractSurefireMojo
826         // Instead use the 'useUnlimitedThreads' parameter.
827         properties = new HashMap<>();
828         properties.put(PARALLEL_KEY, "classesAndMethods");
829         properties.put(THREADCOUNTCLASSES_KEY, "5");
830         params = new JUnitCoreParameters(properties);
831         concurrency = resolveConcurrency(params, null);
832         assertFalse(params.isParallelSuites());
833         assertTrue(params.isParallelClasses());
834         assertTrue(params.isParallelMethods());
835         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
836         assertThat(concurrency.suites, is(0));
837         assertThat(concurrency.classes, is(5 * cpu));
838         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
839     }
840 
841     @Theory
842     public void all(int cpu) throws TestSetFailedException {
843         ParallelComputerUtil.overrideAvailableProcessors(cpu);
844         Map<String, String> properties = new HashMap<>();
845 
846         properties.put(PARALLEL_KEY, "all");
847         properties.put(THREADCOUNTSUITES_KEY, "5");
848         properties.put(THREADCOUNTCLASSES_KEY, "15");
849         properties.put(THREADCOUNTMETHODS_KEY, "30");
850         JUnitCoreParameters params = new JUnitCoreParameters(properties);
851         Concurrency concurrency = resolveConcurrency(params, null);
852         assertTrue(params.isParallelSuites());
853         assertTrue(params.isParallelClasses());
854         assertTrue(params.isParallelMethods());
855         assertThat(concurrency.capacity, is(50 * cpu));
856         assertThat(concurrency.suites, is(5 * cpu));
857         assertThat(concurrency.classes, is(15 * cpu));
858         assertThat(concurrency.methods, is(30 * cpu));
859 
860         // Warning: these cases work but they are not enabled in AbstractSurefireMojo
861         // Instead use the 'useUnlimitedThreads' parameter.
862         properties = new HashMap<>();
863         properties.put(PARALLEL_KEY, "all");
864         properties.put(THREADCOUNTSUITES_KEY, "5");
865         properties.put(THREADCOUNTCLASSES_KEY, "15");
866         params = new JUnitCoreParameters(properties);
867         concurrency = resolveConcurrency(params, null);
868         assertTrue(params.isParallelSuites());
869         assertTrue(params.isParallelClasses());
870         assertTrue(params.isParallelMethods());
871         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
872         assertThat(concurrency.suites, is(5 * cpu));
873         assertThat(concurrency.classes, is(15 * cpu));
874         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
875 
876         properties = new HashMap<>();
877         properties.put(PARALLEL_KEY, "all");
878         properties.put(THREADCOUNTCLASSES_KEY, "15");
879         params = new JUnitCoreParameters(properties);
880         concurrency = resolveConcurrency(params, null);
881         assertTrue(params.isParallelSuites());
882         assertTrue(params.isParallelClasses());
883         assertTrue(params.isParallelMethods());
884         assertThat(concurrency.capacity, is(Integer.MAX_VALUE));
885         assertThat(concurrency.suites, is(Integer.MAX_VALUE));
886         assertThat(concurrency.classes, is(15 * cpu));
887         assertThat(concurrency.methods, is(Integer.MAX_VALUE));
888     }
889 
890     @Test
891     public void withoutShutdown() {
892         Map<String, String> properties = new HashMap<>();
893         properties.put(PARALLEL_KEY, "methods");
894         properties.put(THREADCOUNTMETHODS_KEY, "2");
895         JUnitCoreParameters params = new JUnitCoreParameters(properties);
896         ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder(LOGGER, params);
897         ParallelComputer pc = pcBuilder.buildComputer();
898         final JUnitCore core = new JUnitCore();
899         final long t1 = systemMillis();
900         final Result result = core.run(pc, TestClass.class);
901         final long t2 = systemMillis();
902         long timeSpent = t2 - t1;
903         final long deltaTime = 500L;
904 
905         assertTrue(result.wasSuccessful());
906         assertThat(result.getRunCount(), is(3));
907         assertThat(result.getFailureCount(), is(0));
908         assertThat(result.getIgnoreCount(), is(0));
909         // assertThat( timeSpent, between (timeSpent - deltaTime, timeSpent + deltaTime + 2000L ) );
910         assertEquals(10000L, timeSpent, deltaTime);
911     }
912 
913     @Test
914     public void shutdown() throws TestSetFailedException {
915         // The JUnitCore returns after 2.5s.
916         // The test-methods in TestClass are NOT interrupted, and return normally after 5s.
917         Map<String, String> properties = new HashMap<>();
918         properties.put(PARALLEL_KEY, "methods");
919         properties.put(THREADCOUNTMETHODS_KEY, "2");
920         properties.put(PARALLEL_TIMEOUT_KEY, Double.toString(2.5d));
921         JUnitCoreParameters params = new JUnitCoreParameters(properties);
922         ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder(LOGGER, params);
923         ParallelComputer pc = pcBuilder.buildComputer();
924         final JUnitCore core = new JUnitCore();
925         final long t1 = systemMillis();
926         core.run(pc, TestClass.class);
927         final long t2 = systemMillis();
928         final long timeSpent = t2 - t1;
929         final long deltaTime = 500L;
930 
931         assertEquals(5000L, timeSpent, deltaTime);
932         String description = pc.describeElapsedTimeout();
933         assertTrue(description.contains("The test run has finished abruptly after timeout of 2.5 seconds."));
934         assertTrue(description.contains(
935                 "These tests were executed in prior to the shutdown operation:\n" + TestClass.class.getName()));
936     }
937 
938     @Test
939     public void forcedShutdown() throws TestSetFailedException {
940         // The JUnitCore returns after 2.5s, and the test-methods in TestClass are interrupted.
941         Map<String, String> properties = new HashMap<>();
942         properties.put(PARALLEL_KEY, "methods");
943         properties.put(THREADCOUNTMETHODS_KEY, "2");
944         properties.put(PARALLEL_TIMEOUTFORCED_KEY, Double.toString(2.5d));
945         JUnitCoreParameters params = new JUnitCoreParameters(properties);
946         ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder(LOGGER, params);
947         ParallelComputer pc = pcBuilder.buildComputer();
948         final JUnitCore core = new JUnitCore();
949         final long t1 = systemMillis();
950         core.run(pc, TestClass.class);
951         final long t2 = systemMillis();
952         final long timeSpent = t2 - t1;
953         final long deltaTime = 500L;
954 
955         assertEquals(2500L, timeSpent, deltaTime);
956         String description = pc.describeElapsedTimeout();
957         assertTrue(description.contains("The test run has finished abruptly after timeout of 2.5 seconds."));
958         assertTrue(description.contains(
959                 "These tests were executed in prior to the shutdown operation:\n" + TestClass.class.getName()));
960     }
961 
962     @Test
963     public void timeoutAndForcedShutdown() throws TestSetFailedException {
964         // The JUnitCore returns after 3.5s and the test-methods in TestClass are timed out after 2.5s.
965         // No new test methods are scheduled for execution after 2.5s.
966         // Interruption of test methods after 3.5s.
967         Map<String, String> properties = new HashMap<>();
968         properties.put(PARALLEL_KEY, "methods");
969         properties.put(THREADCOUNTMETHODS_KEY, "2");
970         properties.put(PARALLEL_TIMEOUT_KEY, Double.toString(2.5d));
971         properties.put(PARALLEL_TIMEOUTFORCED_KEY, Double.toString(3.5d));
972         JUnitCoreParameters params = new JUnitCoreParameters(properties);
973         ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder(LOGGER, params);
974         ParallelComputer pc = pcBuilder.buildComputer();
975         final JUnitCore core = new JUnitCore();
976         final long t1 = systemMillis();
977         core.run(pc, TestClass.class);
978         final long t2 = systemMillis();
979         final long timeSpent = t2 - t1;
980         final long deltaTime = 500L;
981 
982         assertEquals(3500L, timeSpent, deltaTime);
983         String description = pc.describeElapsedTimeout();
984         assertTrue(description.contains("The test run has finished abruptly after timeout of 2.5 seconds."));
985         assertTrue(description.contains(
986                 "These tests were executed in prior to the shutdown operation:\n" + TestClass.class.getName()));
987     }
988 
989     @Test
990     public void forcedTimeoutAndShutdown() throws Exception {
991         // The JUnitCore returns after 3.5s and the test-methods in TestClass are interrupted after 3.5s.
992         Map<String, String> properties = new HashMap<>();
993         properties.put(PARALLEL_KEY, "methods");
994         properties.put(THREADCOUNTMETHODS_KEY, "2");
995         properties.put(PARALLEL_TIMEOUTFORCED_KEY, Double.toString(3.5d));
996         properties.put(PARALLEL_TIMEOUT_KEY, Double.toString(4.0d));
997         JUnitCoreParameters params = new JUnitCoreParameters(properties);
998         ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder(LOGGER, params);
999         ParallelComputer pc = pcBuilder.buildComputer();
1000         final JUnitCore core = new JUnitCore();
1001         final long t1 = systemMillis();
1002         core.run(pc, TestClass.class);
1003         final long t2 = systemMillis();
1004         final long timeSpent = t2 - t1;
1005         final long deltaTime = 500L;
1006 
1007         assertEquals(3500L, timeSpent, deltaTime);
1008         String description = pc.describeElapsedTimeout();
1009         assertTrue(description.contains("The test run has finished abruptly after timeout of 3.5 seconds."));
1010         assertTrue(description.contains(
1011                 "These tests were executed in prior to the shutdown operation:\n" + TestClass.class.getName()));
1012     }
1013 
1014     /**
1015      *
1016      */
1017     public static class TestClass {
1018         @Test
1019         public void a() throws InterruptedException {
1020             long t1 = systemMillis();
1021             try {
1022                 Thread.sleep(5000L);
1023             } finally {
1024                 System.out.println(getClass().getSimpleName() + "#a() spent " + (systemMillis() - t1));
1025             }
1026         }
1027 
1028         @Test
1029         public void b() throws InterruptedException {
1030             long t1 = systemMillis();
1031             try {
1032                 Thread.sleep(5000L);
1033             } finally {
1034                 System.out.println(getClass().getSimpleName() + "#b() spent " + (systemMillis() - t1));
1035             }
1036         }
1037 
1038         @Test
1039         public void c() throws InterruptedException {
1040             long t1 = systemMillis();
1041             try {
1042                 Thread.sleep(5000L);
1043             } finally {
1044                 System.out.println(getClass().getSimpleName() + "#c() spent " + (systemMillis() - t1));
1045             }
1046         }
1047     }
1048 
1049     private static long systemMillis() {
1050         return TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
1051     }
1052 }