blob: 03dea045514a7ceeb1121de8c11f5428d9514148 [file] [log] [blame]
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.api.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 + '}';
}
}