1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.surefire.junitcore;
20
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.List;
24 import java.util.concurrent.ExecutionException;
25 import java.util.concurrent.ExecutorService;
26 import java.util.concurrent.Executors;
27 import java.util.concurrent.ThreadFactory;
28
29 import org.apache.maven.surefire.api.util.internal.DaemonThreadFactory;
30 import org.junit.runner.Computer;
31 import org.junit.runner.Runner;
32 import org.junit.runners.ParentRunner;
33 import org.junit.runners.Suite;
34 import org.junit.runners.model.InitializationError;
35 import org.junit.runners.model.RunnerBuilder;
36 import org.junit.runners.model.RunnerScheduler;
37
38
39
40
41
42
43
44 @Deprecated
45 public class ConfigurableParallelComputer extends Computer {
46 private static final ThreadFactory DAEMON_THREAD_FACTORY = DaemonThreadFactory.newDaemonThreadFactory();
47
48 private final boolean fClasses;
49
50 private final boolean fMethods;
51
52 private final boolean fixedPool;
53
54 private final ExecutorService fService;
55
56 private final List<AsynchronousRunner> nonBlockers =
57 Collections.synchronizedList(new ArrayList<AsynchronousRunner>());
58
59 public ConfigurableParallelComputer() {
60 this(true, true, Executors.newCachedThreadPool(DAEMON_THREAD_FACTORY), false);
61 }
62
63 public ConfigurableParallelComputer(boolean fClasses, boolean fMethods) {
64 this(fClasses, fMethods, Executors.newCachedThreadPool(DAEMON_THREAD_FACTORY), false);
65 }
66
67 public ConfigurableParallelComputer(boolean fClasses, boolean fMethods, Integer numberOfThreads, boolean perCore) {
68 this(
69 fClasses,
70 fMethods,
71 Executors.newFixedThreadPool(
72 numberOfThreads * (perCore ? Runtime.getRuntime().availableProcessors() : 1),
73 DAEMON_THREAD_FACTORY),
74 true);
75 }
76
77 private ConfigurableParallelComputer(
78 boolean fClasses, boolean fMethods, ExecutorService executorService, boolean fixedPool) {
79 this.fClasses = fClasses;
80 this.fMethods = fMethods;
81 fService = executorService;
82 this.fixedPool = fixedPool;
83 }
84
85 @SuppressWarnings({"UnusedDeclaration"})
86 public void close() throws ExecutionException {
87 for (AsynchronousRunner nonBlocker : nonBlockers) {
88 nonBlocker.waitForCompletion();
89 }
90
91 fService.shutdown();
92 try {
93 if (!fService.awaitTermination(10, java.util.concurrent.TimeUnit.SECONDS)) {
94 throw new RuntimeException("Executor did not shut down within timeout");
95 }
96 } catch (InterruptedException e) {
97 throw new RuntimeException(e);
98 }
99 }
100
101 private Runner parallelize(Runner runner, RunnerScheduler runnerInterceptor) {
102 if (runner instanceof ParentRunner<?>) {
103 ((ParentRunner<?>) runner).setScheduler(runnerInterceptor);
104 }
105 return runner;
106 }
107
108 private RunnerScheduler getMethodInterceptor() {
109 if (fClasses && fMethods) {
110 final AsynchronousRunner blockingAsynchronousRunner = new AsynchronousRunner(fService);
111 nonBlockers.add(blockingAsynchronousRunner);
112 return blockingAsynchronousRunner;
113 }
114 return fMethods ? new AsynchronousRunner(fService) : new SynchronousRunner();
115 }
116
117 private RunnerScheduler getClassInterceptor() {
118 if (fClasses) {
119 return fMethods ? new SynchronousRunner() : new AsynchronousRunner(fService);
120 }
121 return new SynchronousRunner();
122 }
123
124 @Override
125 public Runner getSuite(RunnerBuilder builder, java.lang.Class<?>[] classes) throws InitializationError {
126 Runner suite = super.getSuite(builder, classes);
127 return fClasses ? parallelize(suite, getClassInterceptor()) : suite;
128 }
129
130 @Override
131 protected Runner getRunner(RunnerBuilder builder, Class<?> testClass) throws Throwable {
132 Runner runner = super.getRunner(builder, testClass);
133 return fMethods && !isTestSuite(testClass) ? parallelize(runner, getMethodInterceptor()) : runner;
134 }
135
136 private boolean isTestSuite(Class<?> testClass) {
137
138 final Suite.SuiteClasses annotation = testClass.getAnnotation(Suite.SuiteClasses.class);
139 return (annotation != null);
140 }
141
142 @Override
143 public String toString() {
144 return "ConfigurableParallelComputer{" + "classes=" + fClasses + ", methods=" + fMethods + ", fixedPool="
145 + fixedPool + '}';
146 }
147 }