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 = Collections.synchronizedList(new ArrayList<>());
57
58 public ConfigurableParallelComputer() {
59 this(true, true, Executors.newCachedThreadPool(DAEMON_THREAD_FACTORY), false);
60 }
61
62 public ConfigurableParallelComputer(boolean fClasses, boolean fMethods) {
63 this(fClasses, fMethods, Executors.newCachedThreadPool(DAEMON_THREAD_FACTORY), false);
64 }
65
66 public ConfigurableParallelComputer(boolean fClasses, boolean fMethods, Integer numberOfThreads, boolean perCore) {
67 this(
68 fClasses,
69 fMethods,
70 Executors.newFixedThreadPool(
71 numberOfThreads * (perCore ? Runtime.getRuntime().availableProcessors() : 1),
72 DAEMON_THREAD_FACTORY),
73 true);
74 }
75
76 private ConfigurableParallelComputer(
77 boolean fClasses, boolean fMethods, ExecutorService executorService, boolean fixedPool) {
78 this.fClasses = fClasses;
79 this.fMethods = fMethods;
80 fService = executorService;
81 this.fixedPool = fixedPool;
82 }
83
84 @SuppressWarnings({"UnusedDeclaration"})
85 public void close() throws ExecutionException {
86 for (AsynchronousRunner nonBlocker : nonBlockers) {
87 nonBlocker.waitForCompletion();
88 }
89
90 fService.shutdown();
91 try {
92 if (!fService.awaitTermination(10, java.util.concurrent.TimeUnit.SECONDS)) {
93 throw new RuntimeException("Executor did not shut down within timeout");
94 }
95 } catch (InterruptedException e) {
96 throw new RuntimeException(e);
97 }
98 }
99
100 private Runner parallelize(Runner runner, RunnerScheduler runnerInterceptor) {
101 if (runner instanceof ParentRunner<?>) {
102 ((ParentRunner<?>) runner).setScheduler(runnerInterceptor);
103 }
104 return runner;
105 }
106
107 private RunnerScheduler getMethodInterceptor() {
108 if (fClasses && fMethods) {
109 final AsynchronousRunner blockingAsynchronousRunner = new AsynchronousRunner(fService);
110 nonBlockers.add(blockingAsynchronousRunner);
111 return blockingAsynchronousRunner;
112 }
113 return fMethods ? new AsynchronousRunner(fService) : new SynchronousRunner();
114 }
115
116 private RunnerScheduler getClassInterceptor() {
117 if (fClasses) {
118 return fMethods ? new SynchronousRunner() : new AsynchronousRunner(fService);
119 }
120 return new SynchronousRunner();
121 }
122
123 @Override
124 public Runner getSuite(RunnerBuilder builder, java.lang.Class<?>[] classes) throws InitializationError {
125 Runner suite = super.getSuite(builder, classes);
126 return fClasses ? parallelize(suite, getClassInterceptor()) : suite;
127 }
128
129 @Override
130 protected Runner getRunner(RunnerBuilder builder, Class<?> testClass) throws Throwable {
131 Runner runner = super.getRunner(builder, testClass);
132 return fMethods && !isTestSuite(testClass) ? parallelize(runner, getMethodInterceptor()) : runner;
133 }
134
135 private boolean isTestSuite(Class<?> testClass) {
136
137 final Suite.SuiteClasses annotation = testClass.getAnnotation(Suite.SuiteClasses.class);
138 return (annotation != null);
139 }
140
141 @Override
142 public String toString() {
143 return "ConfigurableParallelComputer{" + "classes=" + fClasses + ", methods=" + fMethods + ", fixedPool="
144 + fixedPool + '}';
145 }
146 }