package org.apache.maven.surefire.junitcore; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import org.apache.maven.surefire.util.internal.DaemonThreadFactory; import org.junit.runner.Computer; import org.junit.runner.Runner; import org.junit.runners.ParentRunner; import org.junit.runners.Suite; import org.junit.runners.model.InitializationError; import org.junit.runners.model.RunnerBuilder; import org.junit.runners.model.RunnerScheduler; /** * Since SUREFIRE 2.18 this class is deprecated. * Please use {@link org.apache.maven.surefire.junitcore.pc.ParallelComputerBuilder} instead. * * @author Kristian Rosenvold */ @Deprecated public class ConfigurableParallelComputer extends Computer { private static final ThreadFactory DAEMON_THREAD_FACTORY = DaemonThreadFactory.newDaemonThreadFactory(); private final boolean fClasses; private final boolean fMethods; private final boolean fixedPool; private final ExecutorService fService; private final List<AsynchronousRunner> nonBlockers = Collections.synchronizedList( new ArrayList<AsynchronousRunner>() ); public ConfigurableParallelComputer() { this( true, true, Executors.newCachedThreadPool( DAEMON_THREAD_FACTORY ), false ); } public ConfigurableParallelComputer( boolean fClasses, boolean fMethods ) { this( fClasses, fMethods, Executors.newCachedThreadPool( DAEMON_THREAD_FACTORY ), false ); } public ConfigurableParallelComputer( boolean fClasses, boolean fMethods, Integer numberOfThreads, boolean perCore ) { this( fClasses, fMethods, Executors.newFixedThreadPool( numberOfThreads * ( perCore ? Runtime.getRuntime().availableProcessors() : 1 ), DAEMON_THREAD_FACTORY ), true ); } private ConfigurableParallelComputer( boolean fClasses, boolean fMethods, ExecutorService executorService, boolean fixedPool ) { this.fClasses = fClasses; this.fMethods = fMethods; fService = executorService; this.fixedPool = fixedPool; } @SuppressWarnings( { "UnusedDeclaration" } ) public void close() throws ExecutionException { for ( AsynchronousRunner nonBlocker : nonBlockers ) { nonBlocker.waitForCompletion(); } fService.shutdown(); try { if ( !fService.awaitTermination( 10, java.util.concurrent.TimeUnit.SECONDS ) ) { throw new RuntimeException( "Executor did not shut down within timeout" ); } } catch ( InterruptedException e ) { throw new RuntimeException( e ); } } private Runner parallelize( Runner runner, RunnerScheduler runnerInterceptor ) { if ( runner instanceof ParentRunner<?> ) { ( (ParentRunner<?>) runner ).setScheduler( runnerInterceptor ); } return runner; } private RunnerScheduler getMethodInterceptor() { if ( fClasses && fMethods ) { final AsynchronousRunner blockingAsynchronousRunner = new AsynchronousRunner( fService ); nonBlockers.add( blockingAsynchronousRunner ); return blockingAsynchronousRunner; } return fMethods ? new AsynchronousRunner( fService ) : new SynchronousRunner(); } private RunnerScheduler getClassInterceptor() { if ( fClasses ) { return fMethods ? new SynchronousRunner() : new AsynchronousRunner( fService ); } return new SynchronousRunner(); } @Override public Runner getSuite( RunnerBuilder builder, java.lang.Class<?>[] classes ) throws InitializationError { Runner suite = super.getSuite( builder, classes ); return fClasses ? parallelize( suite, getClassInterceptor() ) : suite; } @Override protected Runner getRunner( RunnerBuilder builder, Class<?> testClass ) throws Throwable { Runner runner = super.getRunner( builder, testClass ); return fMethods && !isTestSuite( testClass ) ? parallelize( runner, getMethodInterceptor() ) : runner; } private boolean isTestSuite( Class<?> testClass ) { // Todo: Find out how/if this is enough final Suite.SuiteClasses annotation = testClass.getAnnotation( Suite.SuiteClasses.class ); return ( annotation != null ); } @Override public String toString() { return "ConfigurableParallelComputer{" + "classes=" + fClasses + ", methods=" + fMethods + ", fixedPool=" + fixedPool + '}'; } }