Coverage Report - org.apache.maven.surefire.junitcore.ConfigurableParallelComputer
 
Classes in this File Line Coverage Branch Coverage Complexity
ConfigurableParallelComputer
84%
33/39
75%
18/24
2,25
 
 1  
 package org.apache.maven.surefire.junitcore;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *     http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.util.ArrayList;
 23  
 import java.util.Collections;
 24  
 import java.util.List;
 25  
 import java.util.concurrent.ExecutionException;
 26  
 import java.util.concurrent.ExecutorService;
 27  
 import java.util.concurrent.Executors;
 28  
 import org.apache.maven.surefire.util.NestedRuntimeException;
 29  
 
 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  
  * @author Kristian Rosenvold
 40  
  */
 41  
 public class ConfigurableParallelComputer
 42  
     extends Computer
 43  
 {
 44  
     private final boolean fClasses;
 45  
 
 46  
     private final boolean fMethods;
 47  
 
 48  
     private final boolean fixedPool;
 49  
 
 50  
     private final ExecutorService fService;
 51  
 
 52  11
     private final List<AsynchronousRunner> nonBlockers =
 53  
         Collections.synchronizedList( new ArrayList<AsynchronousRunner>() );
 54  
 
 55  
 
 56  
     public ConfigurableParallelComputer()
 57  
     {
 58  0
         this( true, true, Executors.newCachedThreadPool(), false );
 59  0
     }
 60  
 
 61  
     public ConfigurableParallelComputer( boolean fClasses, boolean fMethods )
 62  
     {
 63  5
         this( fClasses, fMethods, Executors.newCachedThreadPool(), false );
 64  5
     }
 65  
 
 66  
     public ConfigurableParallelComputer( boolean fClasses, boolean fMethods, Integer numberOfThreads, boolean perCore )
 67  
     {
 68  6
         this( fClasses, fMethods, Executors.newFixedThreadPool(
 69  
             numberOfThreads * ( perCore ? Runtime.getRuntime().availableProcessors() : 1 ) ), true );
 70  6
     }
 71  
 
 72  
     private ConfigurableParallelComputer( boolean fClasses, boolean fMethods, ExecutorService executorService,
 73  
                                           boolean fixedPool )
 74  11
     {
 75  11
         this.fClasses = fClasses;
 76  11
         this.fMethods = fMethods;
 77  11
         fService = executorService;
 78  11
         this.fixedPool = fixedPool;
 79  11
     }
 80  
 
 81  
     @SuppressWarnings( { "UnusedDeclaration" } )
 82  
     public void close()
 83  
         throws ExecutionException
 84  
     {
 85  11
         for ( AsynchronousRunner nonBlocker : nonBlockers )
 86  
         {
 87  3000
             nonBlocker.waitForCompletion();
 88  
         }
 89  
 
 90  11
         fService.shutdown();
 91  
         try
 92  
         {
 93  11
             fService.awaitTermination( 10, java.util.concurrent.TimeUnit.SECONDS );
 94  
         }
 95  0
         catch ( InterruptedException e )
 96  
         {
 97  0
             throw new NestedRuntimeException( e );
 98  11
         }
 99  11
     }
 100  
 
 101  
     private Runner parallelize( Runner runner, RunnerScheduler runnerInterceptor )
 102  
     {
 103  6014
         if ( runner instanceof ParentRunner<?> )
 104  
         {
 105  6014
             ( (ParentRunner<?>) runner ).setScheduler( runnerInterceptor );
 106  
         }
 107  6014
         return runner;
 108  
     }
 109  
 
 110  
     private RunnerScheduler getMethodInterceptor()
 111  
     {
 112  6008
         if ( fClasses && fMethods )
 113  
         {
 114  3000
             final AsynchronousRunner blockingAsynchronousRunner = new AsynchronousRunner( fService );
 115  3000
             nonBlockers.add( blockingAsynchronousRunner );
 116  3000
             return blockingAsynchronousRunner;
 117  
         }
 118  3008
         return fMethods ? new AsynchronousRunner( fService ) : new SynchronousRunner();
 119  
     }
 120  
 
 121  
     private RunnerScheduler getClassInterceptor()
 122  
     {
 123  6
         if ( fClasses )
 124  
         {
 125  6
             return fMethods ? new SynchronousRunner() : new AsynchronousRunner( fService );
 126  
         }
 127  0
         return new SynchronousRunner();
 128  
     }
 129  
 
 130  
     @Override
 131  
     public Runner getSuite( RunnerBuilder builder, java.lang.Class<?>[] classes )
 132  
         throws InitializationError
 133  
     {
 134  11
         Runner suite = super.getSuite( builder, classes );
 135  11
         return fClasses ? parallelize( suite, getClassInterceptor() ) : suite;
 136  
     }
 137  
 
 138  
     @Override
 139  
     protected Runner getRunner( RunnerBuilder builder, Class<?> testClass )
 140  
         throws Throwable
 141  
     {
 142  8010
         Runner runner = super.getRunner( builder, testClass );
 143  8010
         return fMethods && !isTestSuite( testClass ) ? parallelize( runner, getMethodInterceptor() ) : runner;
 144  
     }
 145  
 
 146  
     private boolean isTestSuite( Class<?> testClass )
 147  
     {
 148  
         // Todo: Find out how/if this is enough
 149  6008
         final Suite.SuiteClasses annotation = testClass.getAnnotation( Suite.SuiteClasses.class );
 150  6008
         return ( annotation != null );
 151  
     }
 152  
 
 153  
     @Override
 154  
     public String toString()
 155  
     {
 156  0
         return "ConfigurableParallelComputer{" + "classes=" + fClasses + ", methods=" + fMethods + ", fixedPool="
 157  
             + fixedPool + '}';
 158  
     }
 159  
 
 160  
 }