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;
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   * Since SUREFIRE 2.18 this class is deprecated.
40   * Please use {@link org.apache.maven.surefire.junitcore.pc.ParallelComputerBuilder} instead.
41   *
42   * @author Kristian Rosenvold
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         // Todo: Find out how/if this is enough
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 }