You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ag...@apache.org on 2014/03/09 20:42:08 UTC

[04/11] git commit: PC optimization refactoring (Only unit tests. Missing IT tests refactoring.)

PC optimization refactoring (Only unit tests. Missing IT tests refactoring.)


Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/01c39b01
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/01c39b01
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/01c39b01

Branch: refs/heads/master
Commit: 01c39b013e4d2fcc53e39a422890a3b78bce0f54
Parents: c85e6e8
Author: Tibor Digana <ti...@lycos.com>
Authored: Mon Mar 3 23:29:50 2014 +0100
Committer: Andreas Gudian <ag...@apache.org>
Committed: Sun Mar 9 19:46:40 2014 +0100

----------------------------------------------------------------------
 .../surefire/junitcore/JUnitCoreParameters.java |    8 +-
 .../surefire/junitcore/JUnitCoreWrapper.java    |    8 +-
 .../junitcore/ParallelComputerFactory.java      |  450 --------
 .../surefire/junitcore/pc/Concurrency.java      |   29 +
 .../surefire/junitcore/pc/ParallelComputer.java |   19 +-
 .../junitcore/pc/ParallelComputerBuilder.java   |  145 ++-
 .../junitcore/pc/ParallelComputerUtil.java      |  355 ++++++
 .../surefire/junitcore/pc/RunnerCounter.java    |   10 +-
 .../maven/surefire/junitcore/pc/Type.java       |   31 +
 .../surefire/junitcore/JUnit4SuiteTest.java     |    8 +-
 .../junitcore/JUnitCoreParametersTest.java      |  167 ++-
 .../OptimizedParallelComputerTest.java          |  323 ------
 .../junitcore/ParallelComputerFactoryTest.java  | 1063 ------------------
 .../maven/surefire/junitcore/Stopwatch.java     |   46 -
 .../pc/OptimizedParallelComputerTest.java       |  323 ++++++
 .../pc/ParallelComputerBuilderTest.java         |   43 +-
 .../junitcore/pc/ParallelComputerUtilTest.java  | 1063 ++++++++++++++++++
 .../maven/surefire/junitcore/pc/Stopwatch.java  |   46 +
 18 files changed, 2115 insertions(+), 2022 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/01c39b01/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreParameters.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreParameters.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreParameters.java
index 4c042a0..04031c6 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreParameters.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreParameters.java
@@ -48,7 +48,7 @@ public final class JUnitCoreParameters
 
     public static final String PARALLEL_TIMEOUTFORCED_KEY = ProviderParameterNames.PARALLEL_TIMEOUTFORCED_PROP;
 
-    public static final String PARALLEL_OPTIMIZE = ProviderParameterNames.PARALLEL_OPTIMIZE_PROP;
+    public static final String PARALLEL_OPTIMIZE_KEY = ProviderParameterNames.PARALLEL_OPTIMIZE_PROP;
 
     private final String parallel;
 
@@ -83,7 +83,7 @@ public final class JUnitCoreParameters
             Math.max( Double.valueOf( properties.getProperty( PARALLEL_TIMEOUT_KEY, "0" ) ), 0 );
         parallelTestsTimeoutForcedInSeconds =
             Math.max( Double.valueOf( properties.getProperty( PARALLEL_TIMEOUTFORCED_KEY, "0" ) ), 0 );
-        parallelOptimization = Boolean.valueOf( properties.getProperty( PARALLEL_OPTIMIZE, "true" ) );
+        parallelOptimization = Boolean.valueOf( properties.getProperty( PARALLEL_OPTIMIZE_KEY, "true" ) );
     }
 
     private static Collection<String> lowerCase( String... elements )
@@ -169,10 +169,10 @@ public final class JUnitCoreParameters
 
     public boolean isNoThreading()
     {
-        return !isAnyParallelitySelected();
+        return !isParallelismSelected();
     }
 
-    public boolean isAnyParallelitySelected()
+    public boolean isParallelismSelected()
     {
         return isParallelSuites() || isParallelClasses() || isParallelMethods();
     }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/01c39b01/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
index 7bf7a89..14fd77c 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
@@ -19,13 +19,11 @@ package org.apache.maven.surefire.junitcore;
  * under the License.
  */
 
-import java.util.List;
-
 import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
 import org.apache.maven.surefire.junitcore.pc.ParallelComputer;
+import org.apache.maven.surefire.junitcore.pc.ParallelComputerBuilder;
 import org.apache.maven.surefire.testset.TestSetFailedException;
 import org.apache.maven.surefire.util.TestsToRun;
-
 import org.junit.runner.Computer;
 import org.junit.runner.JUnitCore;
 import org.junit.runner.Request;
@@ -35,6 +33,8 @@ import org.junit.runner.manipulation.Filter;
 import org.junit.runner.manipulation.NoTestsRemainException;
 import org.junit.runner.notification.RunListener;
 
+import java.util.List;
+
 /**
  * Encapsulates access to JUnitCore
  *
@@ -119,7 +119,7 @@ class JUnitCoreWrapper
     {
         return parameters.isNoThreading()
             ? Computer.serial()
-            : ParallelComputerFactory.createParallelComputer( parameters, parameters.isParallelOptimization() ? null : null );//todo resolve
+            : new ParallelComputerBuilder( parameters ).buildComputer();
     }
 
     private static class FilteringRequest

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/01c39b01/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ParallelComputerFactory.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ParallelComputerFactory.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ParallelComputerFactory.java
deleted file mode 100644
index 70d4a64..0000000
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ParallelComputerFactory.java
+++ /dev/null
@@ -1,450 +0,0 @@
-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 org.apache.maven.surefire.junitcore.pc.ParallelComputer;
-import org.apache.maven.surefire.junitcore.pc.ParallelComputerBuilder;
-import org.apache.maven.surefire.junitcore.pc.RunnerCounter;
-import org.apache.maven.surefire.testset.TestSetFailedException;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * An algorithm which configures {@link ParallelComputer} with allocated thread resources by given
- * {@link JUnitCoreParameters}.
- * The <code>AbstractSurefireMojo</code> has to provide correct combinations of thread-counts and <em>parallel</em>.
- *
- * @author Tibor Digana (tibor17)
- * @see org.apache.maven.surefire.junitcore.pc.ParallelComputerBuilder
- * @since 2.16
- */
-final class ParallelComputerFactory
-{
-    private static int availableProcessors = Runtime.getRuntime().availableProcessors();
-
-    private ParallelComputerFactory()
-    {
-        throw new IllegalStateException( "Suppresses calling constructor, ensuring non-instantiability." );
-    }
-
-    /*
-    * For testing purposes.
-    */
-    static void overrideAvailableProcessors( int availableProcessors )
-    {
-        ParallelComputerFactory.availableProcessors = availableProcessors;
-    }
-
-    /*
-    * For testing purposes.
-    */
-    static void setDefaultAvailableProcessors()
-    {
-        ParallelComputerFactory.availableProcessors = Runtime.getRuntime().availableProcessors();
-    }
-
-    static ParallelComputer createParallelComputer( JUnitCoreParameters params, RunnerCounter counts )
-        throws TestSetFailedException
-    {
-        Concurrency concurrency = resolveConcurrency( params, counts );
-        ParallelComputerBuilder builder = new ParallelComputerBuilder();
-
-        if ( params.isParallelSuites() )
-        {
-            resolveSuitesConcurrency( builder, concurrency.suites );
-        }
-
-        if ( params.isParallelClasses() )
-        {
-            resolveClassesConcurrency( builder, concurrency.classes );
-        }
-
-        if ( params.isParallelMethods() )
-        {
-            resolveMethodsConcurrency( builder, concurrency.methods );
-        }
-
-        long timeout = secondsToNanos( params.getParallelTestsTimeoutInSeconds() );
-        long timeoutForced = secondsToNanos( params.getParallelTestsTimeoutForcedInSeconds() );
-        resolveCapacity( builder, concurrency.capacity );
-        return builder.buildComputer( timeout, timeoutForced, TimeUnit.NANOSECONDS );
-    }
-
-    static Concurrency resolveConcurrency( JUnitCoreParameters params, RunnerCounter counts )
-        throws TestSetFailedException
-    {
-        if ( !params.isAnyParallelitySelected() )
-        {
-            throw new TestSetFailedException( "Unspecified parameter '" + JUnitCoreParameters.PARALLEL_KEY + "'." );
-        }
-
-        if ( !params.isUseUnlimitedThreads() && !hasThreadCount( params ) && !hasThreadCounts( params ) )
-        {
-            throw new TestSetFailedException( "Unspecified thread-count(s). " +
-                                                  "See the parameters " + JUnitCoreParameters.USEUNLIMITEDTHREADS_KEY
-                                                  + ", " + JUnitCoreParameters.THREADCOUNT_KEY + ", "
-                                                  + JUnitCoreParameters.THREADCOUNTSUITES_KEY + ", "
-                                                  + JUnitCoreParameters.THREADCOUNTCLASSES_KEY + ", "
-                                                  + JUnitCoreParameters.THREADCOUNTMETHODS_KEY + "." );
-        }
-
-        if ( params.isUseUnlimitedThreads() )
-        {
-            return concurrencyForUnlimitedThreads( params );
-        }
-        else if ( hasThreadCount( params ) )
-        {
-            if ( hasThreadCounts( params ) )
-            {
-                return isLeafUnspecified( params )
-                    ? concurrencyFromAllThreadCountsButUnspecifiedLeafCount( params, counts )
-                    : concurrencyFromAllThreadCounts( params );
-            }
-            else
-            {
-                return estimateConcurrency( params, counts );
-            }
-        }
-        else
-        {
-            return concurrencyFromThreadCounts( params );
-        }
-    }
-
-    private static long secondsToNanos( double seconds )
-    {
-        double nanos = seconds > 0 ? seconds * 1E9 : 0;
-        return Double.isInfinite( nanos ) || nanos >= Long.MAX_VALUE ? 0 : (long) nanos;
-    }
-
-    private static void resolveSuitesConcurrency( ParallelComputerBuilder builder, int concurrency )
-    {
-        if ( concurrency > 0 )
-        {
-            if ( concurrency == Integer.MAX_VALUE )
-            {
-                builder.parallelSuites();
-            }
-            else
-            {
-                builder.parallelSuites( concurrency );
-            }
-        }
-    }
-
-    private static void resolveClassesConcurrency( ParallelComputerBuilder builder, int concurrency )
-    {
-        if ( concurrency > 0 )
-        {
-            if ( concurrency == Integer.MAX_VALUE )
-            {
-                builder.parallelClasses();
-            }
-            else
-            {
-                builder.parallelClasses( concurrency );
-            }
-        }
-    }
-
-    private static void resolveMethodsConcurrency( ParallelComputerBuilder builder, int concurrency )
-    {
-        if ( concurrency > 0 )
-        {
-            if ( concurrency == Integer.MAX_VALUE )
-            {
-                builder.parallelMethods();
-            }
-            else
-            {
-                builder.parallelMethods( concurrency );
-            }
-        }
-    }
-
-    private static void resolveCapacity( ParallelComputerBuilder builder, int capacity )
-    {
-        if ( capacity > 0 )
-        {
-            builder.useOnePool( capacity );
-        }
-    }
-
-    private static Concurrency concurrencyForUnlimitedThreads( JUnitCoreParameters params )
-    {
-        Concurrency concurrency = new Concurrency();
-        concurrency.suites = params.isParallelSuites() ? threadCountSuites( params ) : 0;
-        concurrency.classes = params.isParallelClasses() ? threadCountClasses( params ) : 0;
-        concurrency.methods = params.isParallelMethods() ? threadCountMethods( params ) : 0;
-        concurrency.capacity = Integer.MAX_VALUE;
-        return concurrency;
-    }
-
-    private static Concurrency estimateConcurrency( JUnitCoreParameters params, RunnerCounter counts )
-    {
-        final Concurrency concurrency = new Concurrency();
-        final int parallelEntities = countParallelEntities( params );
-        concurrency.capacity = multiplyByCoreCount( params, params.getThreadCount() );
-        if ( parallelEntities == 1 || counts == null || counts.classes == 0 )
-        {
-            // Estimate parallel thread counts.
-            double ratio = 1d / parallelEntities;
-            int threads = multiplyByCoreCount( params, ratio * params.getThreadCount() );
-            concurrency.suites = params.isParallelSuites() ? minSuites( threads, counts ) : 0;
-            concurrency.classes = params.isParallelClasses() ? minClasses( threads, counts ) : 0;
-            concurrency.methods = params.isParallelMethods() ? minMethods( threads, counts ) : 0;
-            if ( parallelEntities == 1 )
-            {
-                concurrency.capacity = 0;
-            }
-            else
-            {
-                adjustLeaf( params, concurrency );
-            }
-        }
-        else
-        {
-            // Try to allocate suites+classes+methods within threadCount,
-            concurrency.suites = params.isParallelSuites() ? toNonNegative( counts.suites ) : 0;
-            concurrency.classes = params.isParallelClasses() ? toNonNegative( counts.classes ) : 0;
-            concurrency.methods =
-                params.isParallelMethods() ? toNonNegative( Math.ceil( counts.methods / (double) counts.classes ) ) : 0;
-            double sum = toNonNegative( concurrency.suites + concurrency.classes + concurrency.methods );
-            if ( concurrency.capacity < sum && sum != 0 )
-            {
-                // otherwise allocate them using the weighting factor < 1.
-                double weight = concurrency.capacity / sum;
-                concurrency.suites *= weight;
-                concurrency.classes *= weight;
-                concurrency.methods *= weight;
-            }
-            adjustLeaf( params, concurrency );
-        }
-        return concurrency;
-    }
-
-    private static Concurrency concurrencyFromAllThreadCountsButUnspecifiedLeafCount( JUnitCoreParameters params,
-                                                                                      RunnerCounter counts )
-    {
-        Concurrency concurrency = new Concurrency();
-        concurrency.suites = params.isParallelSuites() ? params.getThreadCountSuites() : 0;
-        concurrency.suites = params.isParallelSuites() ? multiplyByCoreCount( params, concurrency.suites ) : 0;
-        concurrency.classes = params.isParallelClasses() ? params.getThreadCountClasses() : 0;
-        concurrency.classes = params.isParallelClasses() ? multiplyByCoreCount( params, concurrency.classes ) : 0;
-        concurrency.methods = params.isParallelMethods() ? params.getThreadCountMethods() : 0;
-        concurrency.methods = params.isParallelMethods() ? multiplyByCoreCount( params, concurrency.methods ) : 0;
-        concurrency.capacity = multiplyByCoreCount( params, params.getThreadCount() );
-
-        if ( counts != null )
-        {
-            concurrency.suites = toNonNegative( Math.min( concurrency.suites, counts.suites ) );
-            concurrency.classes = toNonNegative( Math.min( concurrency.classes, counts.classes ) );
-        }
-
-        setLeafInfinite( params, concurrency );
-
-        return concurrency;
-    }
-
-    private static Concurrency concurrencyFromAllThreadCounts( JUnitCoreParameters params )
-    {
-        Concurrency concurrency = new Concurrency();
-        concurrency.suites = params.isParallelSuites() ? params.getThreadCountSuites() : 0;
-        concurrency.classes = params.isParallelClasses() ? params.getThreadCountClasses() : 0;
-        concurrency.methods = params.isParallelMethods() ? params.getThreadCountMethods() : 0;
-        concurrency.capacity = params.getThreadCount();
-        double all = sumThreadCounts( concurrency );
-
-        concurrency.suites = params.isParallelSuites() ? multiplyByCoreCount( params, concurrency.capacity * (
-            concurrency.suites / all ) ) : 0;
-
-        concurrency.classes = params.isParallelClasses() ? multiplyByCoreCount( params, concurrency.capacity * (
-            concurrency.classes / all ) ) : 0;
-
-        concurrency.methods = params.isParallelMethods() ? multiplyByCoreCount( params, concurrency.capacity * (
-            concurrency.methods / all ) ) : 0;
-
-        concurrency.capacity = multiplyByCoreCount( params, concurrency.capacity );
-        adjustPrecisionInLeaf( params, concurrency );
-        return concurrency;
-    }
-
-    private static Concurrency concurrencyFromThreadCounts( JUnitCoreParameters params )
-    {
-        Concurrency concurrency = new Concurrency();
-        concurrency.suites = params.isParallelSuites() ? threadCountSuites( params ) : 0;
-        concurrency.classes = params.isParallelClasses() ? threadCountClasses( params ) : 0;
-        concurrency.methods = params.isParallelMethods() ? threadCountMethods( params ) : 0;
-        concurrency.capacity = toNonNegative( sumThreadCounts( concurrency ) );
-        return concurrency;
-    }
-
-    private static int countParallelEntities( JUnitCoreParameters params )
-    {
-        int count = 0;
-        if ( params.isParallelSuites() )
-        {
-            count++;
-        }
-
-        if ( params.isParallelClasses() )
-        {
-            count++;
-        }
-
-        if ( params.isParallelMethods() )
-        {
-            count++;
-        }
-        return count;
-    }
-
-    private static void adjustPrecisionInLeaf( JUnitCoreParameters params, Concurrency concurrency )
-    {
-        if ( params.isParallelMethods() )
-        {
-            concurrency.methods = concurrency.capacity - concurrency.suites - concurrency.classes;
-        }
-        else if ( params.isParallelClasses() )
-        {
-            concurrency.classes = concurrency.capacity - concurrency.suites;
-        }
-    }
-
-    private static void adjustLeaf( JUnitCoreParameters params, Concurrency concurrency )
-    {
-        if ( params.isParallelMethods() )
-        {
-            concurrency.methods = Integer.MAX_VALUE;
-        }
-        else if ( params.isParallelClasses() )
-        {
-            concurrency.classes = Integer.MAX_VALUE;
-        }
-    }
-
-    private static void setLeafInfinite( JUnitCoreParameters params, Concurrency concurrency )
-    {
-        if ( params.isParallelMethods() )
-        {
-            concurrency.methods = Integer.MAX_VALUE;
-        }
-        else if ( params.isParallelClasses() )
-        {
-            concurrency.classes = Integer.MAX_VALUE;
-        }
-        else if ( params.isParallelSuites() )
-        {
-            concurrency.suites = Integer.MAX_VALUE;
-        }
-    }
-
-    private static boolean isLeafUnspecified( JUnitCoreParameters params )
-    {
-        int maskOfParallel = params.isParallelSuites() ? 4 : 0;
-        maskOfParallel |= params.isParallelClasses() ? 2 : 0;
-        maskOfParallel |= params.isParallelMethods() ? 1 : 0;
-
-        int maskOfConcurrency = params.getThreadCountSuites() > 0 ? 4 : 0;
-        maskOfConcurrency |= params.getThreadCountClasses() > 0 ? 2 : 0;
-        maskOfConcurrency |= params.getThreadCountMethods() > 0 ? 1 : 0;
-
-        maskOfConcurrency &= maskOfParallel;
-
-        int leaf = Integer.lowestOneBit( maskOfParallel );
-        return maskOfConcurrency == maskOfParallel - leaf;
-    }
-
-    private static double sumThreadCounts( Concurrency concurrency )
-    {
-        double sum = concurrency.suites;
-        sum += concurrency.classes;
-        sum += concurrency.methods;
-        return sum;
-    }
-
-    private static boolean hasThreadCounts( JUnitCoreParameters jUnitCoreParameters )
-    {
-        return jUnitCoreParameters.isParallelSuites() && jUnitCoreParameters.getThreadCountSuites() > 0 ||
-            jUnitCoreParameters.isParallelClasses() && jUnitCoreParameters.getThreadCountClasses() > 0 ||
-            jUnitCoreParameters.isParallelMethods() && jUnitCoreParameters.getThreadCountMethods() > 0;
-    }
-
-    private static boolean hasThreadCount( JUnitCoreParameters jUnitCoreParameters )
-    {
-        return jUnitCoreParameters.getThreadCount() > 0;
-    }
-
-    private static int threadCountMethods( JUnitCoreParameters jUnitCoreParameters )
-    {
-        return multiplyByCoreCount( jUnitCoreParameters, jUnitCoreParameters.getThreadCountMethods() );
-    }
-
-    private static int threadCountClasses( JUnitCoreParameters jUnitCoreParameters )
-    {
-        return multiplyByCoreCount( jUnitCoreParameters, jUnitCoreParameters.getThreadCountClasses() );
-    }
-
-    private static int threadCountSuites( JUnitCoreParameters jUnitCoreParameters )
-    {
-        return multiplyByCoreCount( jUnitCoreParameters, jUnitCoreParameters.getThreadCountSuites() );
-    }
-
-    private static int multiplyByCoreCount( JUnitCoreParameters jUnitCoreParameters, double threadsPerCore )
-    {
-        double numberOfThreads =
-            jUnitCoreParameters.isPerCoreThreadCount() ? threadsPerCore * (double) availableProcessors : threadsPerCore;
-
-        return numberOfThreads > 0 ? toNonNegative( numberOfThreads ) : Integer.MAX_VALUE;
-    }
-
-    private static int minSuites( int threads, RunnerCounter counts )
-    {
-        long count = counts == null ? Integer.MAX_VALUE : counts.suites;
-        return Math.min( threads, toNonNegative( count ) );
-    }
-
-    private static int minClasses( int threads, RunnerCounter counts )
-    {
-        long count = counts == null ? Integer.MAX_VALUE : counts.classes;
-        return Math.min( threads, toNonNegative( count ) );
-    }
-
-    private static int minMethods( int threads, RunnerCounter counts )
-    {
-        long count = counts == null ? Integer.MAX_VALUE : counts.methods;
-        return Math.min( threads, toNonNegative( count ) );
-    }
-
-    private static int toNonNegative( long num )
-    {
-        return (int) Math.min( num > 0 ? num : 0, Integer.MAX_VALUE );
-    }
-
-    private static int toNonNegative( double num )
-    {
-        return (int) Math.min( num > 0 ? num : 0, Integer.MAX_VALUE );
-    }
-
-    static class Concurrency
-    {
-        int suites, classes, methods, capacity;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/01c39b01/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/Concurrency.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/Concurrency.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/Concurrency.java
new file mode 100644
index 0000000..c05af7f
--- /dev/null
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/Concurrency.java
@@ -0,0 +1,29 @@
+package org.apache.maven.surefire.junitcore.pc;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author tibor17 (Tibor Digana)
+ * @since 2.17
+ */
+final class Concurrency
+{
+    int suites, classes, methods, capacity;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/01c39b01/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputer.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputer.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputer.java
index 242df2e..79ca87a 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputer.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputer.java
@@ -30,7 +30,8 @@ import java.util.concurrent.Callable;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
+
+import static java.util.concurrent.TimeUnit.*;
 
 /**
  * ParallelComputer extends JUnit {@link Computer} and has a shutdown functionality.
@@ -52,10 +53,16 @@ public abstract class ParallelComputer
 
     private Future<Collection<Description>> testsBeforeForcedShutdown;
 
-    public ParallelComputer( long timeout, long timeoutForced, TimeUnit timeoutUnit )
+    public ParallelComputer( double timeoutInSeconds, double timeoutForcedInSeconds  )
+    {
+        this.timeoutNanos = secondsToNanos( timeoutInSeconds );
+        this.timeoutForcedNanos = secondsToNanos( timeoutForcedInSeconds );
+    }
+
+    private static long secondsToNanos( double seconds )
     {
-        this.timeoutNanos = timeoutUnit.toNanos( timeout );
-        this.timeoutForcedNanos = timeoutUnit.toNanos( timeoutForced );
+        double nanos = seconds > 0 ? seconds * 1E9 : 0;
+        return Double.isInfinite( nanos ) || nanos >= Long.MAX_VALUE ? 0 : (long) nanos;
     }
 
     private static long minTimeout( long timeout1, long timeout2 )
@@ -146,12 +153,12 @@ public abstract class ParallelComputer
 
     private Future<Collection<Description>> scheduleShutdown()
     {
-        return getShutdownScheduler().schedule( createShutdownTask( false ), timeoutNanos, TimeUnit.NANOSECONDS );
+        return getShutdownScheduler().schedule( createShutdownTask( false ), timeoutNanos, NANOSECONDS );
     }
 
     private Future<Collection<Description>> scheduleForcedShutdown()
     {
-        return getShutdownScheduler().schedule( createShutdownTask( true ), timeoutForcedNanos, TimeUnit.NANOSECONDS );
+        return getShutdownScheduler().schedule( createShutdownTask( true ), timeoutForcedNanos, NANOSECONDS );
     }
 
     private ScheduledExecutorService getShutdownScheduler()

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/01c39b01/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilder.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilder.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilder.java
index ca49561..04813ad 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilder.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilder.java
@@ -20,6 +20,7 @@ package org.apache.maven.surefire.junitcore.pc;
  */
 
 import org.apache.maven.surefire.junitcore.JUnitCoreParameters;
+import org.apache.maven.surefire.testset.TestSetFailedException;
 import org.junit.internal.runners.ErrorReportingRunner;
 import org.junit.runner.Description;
 import org.junit.runner.Runner;
@@ -40,13 +41,16 @@ import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
+
+import static org.apache.maven.surefire.junitcore.pc.ParallelComputerUtil.*;
+import static org.apache.maven.surefire.junitcore.pc.Type.*;
 
 /**
  * Executing suites, classes and methods with defined concurrency. In this example the threads which completed
  * the suites and classes can be reused in parallel methods.
  * <pre>
- * ParallelComputerBuilder builder = new ParallelComputerBuilder();
+ * JUnitCoreParameters parameters = ...;
+ * ParallelComputerBuilder builder = new ParallelComputerBuilder(parameters);
  * builder.useOnePool(8).parallelSuites(2).parallelClasses(4).parallelMethods();
  * ParallelComputerBuilder.ParallelComputer computer = builder.buildComputer();
  * Class<?>[] tests = {...};
@@ -79,31 +83,42 @@ public final class ParallelComputerBuilder
 
     private boolean optimize;
 
+    private boolean runningInTests;
+
     /**
      * Calling {@link #useSeparatePools()}.
+     * Can be used only in unit tests.
+     * Do NOT call this constructor in production.
      */
-    public ParallelComputerBuilder()
+    ParallelComputerBuilder()
     {
+        runningInTests = true;
         useSeparatePools();
-        parallelGroups.put( Type.SUITES, 0 );
-        parallelGroups.put( Type.CLASSES, 0 );
-        parallelGroups.put( Type.METHODS, 0 );
+        parallelGroups.put( SUITES, 0 );
+        parallelGroups.put( CLASSES, 0 );
+        parallelGroups.put( METHODS, 0 );
     }
 
     public ParallelComputerBuilder( JUnitCoreParameters parameters )
     {
         this();
+        runningInTests = false;
         this.parameters = parameters;
     }
 
-    public ParallelComputerBuilder useSeparatePools()
+    public ParallelComputer buildComputer()
+    {
+        return new PC();
+    }
+
+    ParallelComputerBuilder useSeparatePools()
     {
         totalPoolSize = TOTAL_POOL_SIZE_UNDEFINED;
         useSeparatePools = true;
         return this;
     }
 
-    public ParallelComputerBuilder useOnePool()
+    ParallelComputerBuilder useOnePool()
     {
         totalPoolSize = TOTAL_POOL_SIZE_UNDEFINED;
         useSeparatePools = false;
@@ -116,7 +131,7 @@ public final class ParallelComputerBuilder
      *                      limited.
      * @throws IllegalArgumentException If <tt>totalPoolSize</tt> is &lt; 1.
      */
-    public ParallelComputerBuilder useOnePool( int totalPoolSize )
+    ParallelComputerBuilder useOnePool( int totalPoolSize )
     {
         if ( totalPoolSize < 1 )
         {
@@ -127,40 +142,45 @@ public final class ParallelComputerBuilder
         return this;
     }
 
-    public ParallelComputerBuilder optimize( boolean optimize )
+    boolean isOptimized()
+    {
+        return optimize;
+    }
+
+    ParallelComputerBuilder optimize( boolean optimize )
     {
         this.optimize = optimize;
         return this;
     }
 
-    public ParallelComputerBuilder parallelSuites()
+    ParallelComputerBuilder parallelSuites()
     {
-        return parallel( Type.SUITES );
+        return parallel( SUITES );
     }
 
-    public ParallelComputerBuilder parallelSuites( int nThreads )
+    ParallelComputerBuilder parallelSuites( int nThreads )
     {
-        return parallel( nThreads, Type.SUITES );
+        return parallel( nThreads, SUITES );
     }
 
-    public ParallelComputerBuilder parallelClasses()
+    ParallelComputerBuilder parallelClasses()
     {
-        return parallel( Type.CLASSES );
+        return parallel( CLASSES );
     }
 
-    public ParallelComputerBuilder parallelClasses( int nThreads )
+    ParallelComputerBuilder parallelClasses( int nThreads )
     {
-        return parallel( nThreads, Type.CLASSES );
+        return parallel( nThreads, CLASSES );
     }
 
-    public ParallelComputerBuilder parallelMethods()
+    ParallelComputerBuilder parallelMethods()
     {
-        return parallel( Type.METHODS );
+        return parallel( METHODS );
     }
 
-    public ParallelComputerBuilder parallelMethods( int nThreads )
+    ParallelComputerBuilder parallelMethods( int nThreads )
     {
-        return parallel( nThreads, Type.METHODS );
+        return parallel( nThreads, METHODS );
     }
 
     private ParallelComputerBuilder parallel( int nThreads, Type parallelType )
@@ -184,21 +204,14 @@ public final class ParallelComputerBuilder
         return parallel( Integer.MAX_VALUE, parallelType );
     }
 
-    public ParallelComputer buildComputer()
-    {
-        return buildComputer( 0, 0, TimeUnit.NANOSECONDS );
-    }
-
-    public ParallelComputer buildComputer( long timeout, long timeoutForced, TimeUnit timeUnit )
+    private double parallelTestsTimeoutInSeconds()
     {
-        return new PC( timeout, timeoutForced, timeUnit );
+        return parameters == null ? 0d : parameters.getParallelTestsTimeoutInSeconds();
     }
 
-    private static enum Type
+    private double parallelTestsTimeoutForcedInSeconds()
     {
-        SUITES,
-        CLASSES,
-        METHODS
+        return parameters == null ? 0d : parameters.getParallelTestsTimeoutForcedInSeconds();
     }
 
     final class PC
@@ -214,9 +227,9 @@ public final class ParallelComputerBuilder
 
         final Collection<Runner> unscheduledRunners = new LinkedHashSet<Runner>();
 
-        final int poolCapacity;
+        int poolCapacity;
 
-        final boolean splitPool;
+        boolean splitPool;
 
         private final Map<Type, Integer> allGroups;
 
@@ -224,9 +237,9 @@ public final class ParallelComputerBuilder
 
         private volatile Scheduler master;
 
-        private PC( long timeout, long timeoutForced, TimeUnit timeoutUnit )
+        private PC()
         {
-            super( timeout, timeoutForced, timeoutUnit );
+            super( parallelTestsTimeoutInSeconds(), parallelTestsTimeoutForcedInSeconds() );
             allGroups = new EnumMap<Type, Integer>( ParallelComputerBuilder.this.parallelGroups );
             poolCapacity = ParallelComputerBuilder.this.totalPoolSize;
             splitPool = ParallelComputerBuilder.this.useSeparatePools;
@@ -243,18 +256,28 @@ public final class ParallelComputerBuilder
         public Runner getSuite( RunnerBuilder builder, Class<?>[] cls )
             throws InitializationError
         {
-            super.getSuite( builder, cls );
-            populateChildrenFromSuites();
+            try
+            {
+                super.getSuite( builder, cls );
+                populateChildrenFromSuites();
 
-            WrappedRunners suiteSuites = wrapRunners( suites );
-            WrappedRunners suiteClasses = wrapRunners( classes );
+                WrappedRunners suiteSuites = wrapRunners( suites );
+                WrappedRunners suiteClasses = wrapRunners( classes );
 
-            long suitesCount = suites.size();
-            long classesCount = classes.size() + nestedClasses.size();
-            long methodsCount = suiteClasses.embeddedChildrenCount + nestedClassesChildren;
-            tryOptimize( suitesCount, classesCount, methodsCount );
+                long suitesCount = suites.size();
+                long classesCount = classes.size() + nestedClasses.size();
+                long methodsCount = suiteClasses.embeddedChildrenCount + nestedClassesChildren;
+                if (!ParallelComputerBuilder.this.runningInTests)
+                {
+                    determineThreadCounts( suitesCount, classesCount, methodsCount );
+                }
 
-            return setSchedulers( suiteSuites.wrappingSuite, suiteClasses.wrappingSuite );
+                return setSchedulers( suiteSuites.wrappingSuite, suiteClasses.wrappingSuite );
+            }
+            catch ( TestSetFailedException e )
+            {
+                throw new InitializationError( e );
+            }
         }
 
         @Override
@@ -280,19 +303,24 @@ public final class ParallelComputerBuilder
             return runner;
         }
 
-        private void tryOptimize( long suites, long classes, long methods )
+        private void determineThreadCounts( long suites, long classes, long methods )
+            throws TestSetFailedException
         {
-            //todo remove statement, we will rely on single non-default constructor. Final class.
             final JUnitCoreParameters parameters = ParallelComputerBuilder.this.parameters;
-            if ( ParallelComputerBuilder.this.optimize && parameters != null )
-            {
-                ;//todo
-            }
+            final boolean optimize = ParallelComputerBuilder.this.optimize;
+            RunnerCounter counts = new RunnerCounter( suites, classes, methods );
+            Concurrency concurrency = resolveConcurrency( parameters, optimize ? counts : null );
+            allGroups.put( SUITES, concurrency.suites );
+            allGroups.put( CLASSES, concurrency.classes );
+            allGroups.put( METHODS, concurrency.methods );
+            poolCapacity = concurrency.capacity;
+            splitPool &= concurrency.capacity <= 0;//fault if negative; should not happen
         }
 
         private <T extends Runner> WrappedRunners wrapRunners( Collection<T> runners )
             throws InitializationError
         {
+            // Do NOT use allGroups here.
             long childrenCounter = 0;
             ArrayList<Runner> runs = new ArrayList<Runner>();
             for ( T runner : runners )
@@ -346,12 +374,13 @@ public final class ParallelComputerBuilder
 
         private boolean areSuitesAndClassesParallel()
         {
-            return !suites.isEmpty() && allGroups.get( Type.SUITES ) > 0 && !classes.isEmpty()
-                && allGroups.get( Type.CLASSES ) > 0;
+            return !suites.isEmpty() && allGroups.get( SUITES ) > 0 && !classes.isEmpty()
+                && allGroups.get( CLASSES ) > 0;
         }
 
         private void populateChildrenFromSuites()
         {
+            // Do NOT use allGroups here.
             Filter filter = new SuiteFilter();
             for ( Iterator<ParentRunner> it = suites.iterator(); it.hasNext(); )
             {
@@ -392,9 +421,9 @@ public final class ParallelComputerBuilder
         private Runner setSchedulers( ParentRunner suiteSuites, ParentRunner suiteClasses )
             throws InitializationError
         {
-            int parallelSuites = allGroups.get( Type.SUITES );
-            int parallelClasses = allGroups.get( Type.CLASSES );
-            int parallelMethods = allGroups.get( Type.METHODS );
+            int parallelSuites = allGroups.get( SUITES );
+            int parallelClasses = allGroups.get( CLASSES );
+            int parallelMethods = allGroups.get( METHODS );
             int poolSize = totalPoolSize();
             ExecutorService commonPool = splitPool || poolSize == 0 ? null : createPool( poolSize );
             master = createMaster( commonPool, poolSize );
@@ -533,6 +562,8 @@ public final class ParallelComputerBuilder
         private class SuiteFilter
             extends Filter
         {
+            // Do NOT use allGroups in SuiteFilter.
+
             @Override
             public boolean shouldRun( Description description )
             {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/01c39b01/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerUtil.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerUtil.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerUtil.java
new file mode 100644
index 0000000..f93e9b6
--- /dev/null
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerUtil.java
@@ -0,0 +1,355 @@
+package org.apache.maven.surefire.junitcore.pc;
+
+/*
+ * 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 org.apache.maven.surefire.junitcore.JUnitCoreParameters;
+import org.apache.maven.surefire.testset.TestSetFailedException;
+
+/**
+ * An algorithm which configures {@link ParallelComputer} with allocated thread resources by given
+ * {@link org.apache.maven.surefire.junitcore.JUnitCoreParameters}.
+ * The <code>AbstractSurefireMojo</code> has to provide correct combinations of thread-counts and <em>parallel</em>.
+ *
+ * @author Tibor Digana (tibor17)
+ * @see org.apache.maven.surefire.junitcore.pc.ParallelComputerBuilder
+ * @since 2.16
+ */
+final class ParallelComputerUtil
+{
+    private static int availableProcessors = Runtime.getRuntime().availableProcessors();
+
+    private ParallelComputerUtil()
+    {
+        throw new IllegalStateException( "Suppresses calling constructor, ensuring non-instantiability." );
+    }
+
+    /*
+    * For testing purposes.
+    */
+    static void overrideAvailableProcessors( int availableProcessors )
+    {
+        ParallelComputerUtil.availableProcessors = availableProcessors;
+    }
+
+    /*
+    * For testing purposes.
+    */
+    static void setDefaultAvailableProcessors()
+    {
+        ParallelComputerUtil.availableProcessors = Runtime.getRuntime().availableProcessors();
+    }
+
+    static Concurrency resolveConcurrency( JUnitCoreParameters params, RunnerCounter counts )
+        throws TestSetFailedException
+    {
+        if ( !params.isParallelismSelected() )
+        {
+            throw new TestSetFailedException( "Unspecified parameter '" + JUnitCoreParameters.PARALLEL_KEY + "'." );
+        }
+
+        if ( !params.isUseUnlimitedThreads() && !hasThreadCount( params ) && !hasThreadCounts( params ) )
+        {
+            throw new TestSetFailedException( "Unspecified thread-count(s). " +
+                                                  "See the parameters " + JUnitCoreParameters.USEUNLIMITEDTHREADS_KEY
+                                                  + ", " + JUnitCoreParameters.THREADCOUNT_KEY + ", "
+                                                  + JUnitCoreParameters.THREADCOUNTSUITES_KEY + ", "
+                                                  + JUnitCoreParameters.THREADCOUNTCLASSES_KEY + ", "
+                                                  + JUnitCoreParameters.THREADCOUNTMETHODS_KEY + "." );
+        }
+
+        if ( params.isUseUnlimitedThreads() )
+        {
+            return concurrencyForUnlimitedThreads( params );
+        }
+        else if ( hasThreadCount( params ) )
+        {
+            if ( hasThreadCounts( params ) )
+            {
+                return isLeafUnspecified( params )
+                    ? concurrencyFromAllThreadCountsButUnspecifiedLeafCount( params, counts )
+                    : concurrencyFromAllThreadCounts( params );
+            }
+            else
+            {
+                return estimateConcurrency( params, counts );
+            }
+        }
+        else
+        {
+            return concurrencyFromThreadCounts( params );
+        }
+    }
+
+    private static Concurrency concurrencyForUnlimitedThreads( JUnitCoreParameters params )
+    {
+        Concurrency concurrency = new Concurrency();
+        concurrency.suites = params.isParallelSuites() ? threadCountSuites( params ) : 0;
+        concurrency.classes = params.isParallelClasses() ? threadCountClasses( params ) : 0;
+        concurrency.methods = params.isParallelMethods() ? threadCountMethods( params ) : 0;
+        concurrency.capacity = Integer.MAX_VALUE;
+        return concurrency;
+    }
+
+    private static Concurrency estimateConcurrency( JUnitCoreParameters params, RunnerCounter counts )
+    {
+        final Concurrency concurrency = new Concurrency();
+        final int parallelEntities = countParallelEntities( params );
+        concurrency.capacity = multiplyByCoreCount( params, params.getThreadCount() );
+        if ( parallelEntities == 1 || counts == null || counts.classes == 0 )
+        {
+            // Estimate parallel thread counts.
+            double ratio = 1d / parallelEntities;
+            int threads = multiplyByCoreCount( params, ratio * params.getThreadCount() );
+            concurrency.suites = params.isParallelSuites() ? minSuites( threads, counts ) : 0;
+            concurrency.classes = params.isParallelClasses() ? minClasses( threads, counts ) : 0;
+            concurrency.methods = params.isParallelMethods() ? minMethods( threads, counts ) : 0;
+            if ( parallelEntities == 1 )
+            {
+                concurrency.capacity = 0;
+            }
+            else
+            {
+                adjustLeaf( params, concurrency );
+            }
+        }
+        else
+        {
+            // Try to allocate suites+classes+methods within threadCount,
+            concurrency.suites = params.isParallelSuites() ? toNonNegative( counts.suites ) : 0;
+            concurrency.classes = params.isParallelClasses() ? toNonNegative( counts.classes ) : 0;
+            concurrency.methods =
+                params.isParallelMethods() ? toNonNegative( Math.ceil( counts.methods / (double) counts.classes ) ) : 0;
+            double sum = toNonNegative( concurrency.suites + concurrency.classes + concurrency.methods );
+            if ( concurrency.capacity < sum && sum != 0 )
+            {
+                // otherwise allocate them using the weighting factor < 1.
+                double weight = concurrency.capacity / sum;
+                concurrency.suites *= weight;
+                concurrency.classes *= weight;
+                concurrency.methods *= weight;
+            }
+            adjustLeaf( params, concurrency );
+        }
+        return concurrency;
+    }
+
+    private static Concurrency concurrencyFromAllThreadCountsButUnspecifiedLeafCount( JUnitCoreParameters params,
+                                                                                      RunnerCounter counts )
+    {
+        Concurrency concurrency = new Concurrency();
+        concurrency.suites = params.isParallelSuites() ? params.getThreadCountSuites() : 0;
+        concurrency.suites = params.isParallelSuites() ? multiplyByCoreCount( params, concurrency.suites ) : 0;
+        concurrency.classes = params.isParallelClasses() ? params.getThreadCountClasses() : 0;
+        concurrency.classes = params.isParallelClasses() ? multiplyByCoreCount( params, concurrency.classes ) : 0;
+        concurrency.methods = params.isParallelMethods() ? params.getThreadCountMethods() : 0;
+        concurrency.methods = params.isParallelMethods() ? multiplyByCoreCount( params, concurrency.methods ) : 0;
+        concurrency.capacity = multiplyByCoreCount( params, params.getThreadCount() );
+
+        if ( counts != null )
+        {
+            concurrency.suites = toNonNegative( Math.min( concurrency.suites, counts.suites ) );
+            concurrency.classes = toNonNegative( Math.min( concurrency.classes, counts.classes ) );
+        }
+
+        setLeafInfinite( params, concurrency );
+
+        return concurrency;
+    }
+
+    private static Concurrency concurrencyFromAllThreadCounts( JUnitCoreParameters params )
+    {
+        Concurrency concurrency = new Concurrency();
+        concurrency.suites = params.isParallelSuites() ? params.getThreadCountSuites() : 0;
+        concurrency.classes = params.isParallelClasses() ? params.getThreadCountClasses() : 0;
+        concurrency.methods = params.isParallelMethods() ? params.getThreadCountMethods() : 0;
+        concurrency.capacity = params.getThreadCount();
+        double all = sumThreadCounts( concurrency );
+
+        concurrency.suites = params.isParallelSuites() ? multiplyByCoreCount( params, concurrency.capacity * (
+            concurrency.suites / all ) ) : 0;
+
+        concurrency.classes = params.isParallelClasses() ? multiplyByCoreCount( params, concurrency.capacity * (
+            concurrency.classes / all ) ) : 0;
+
+        concurrency.methods = params.isParallelMethods() ? multiplyByCoreCount( params, concurrency.capacity * (
+            concurrency.methods / all ) ) : 0;
+
+        concurrency.capacity = multiplyByCoreCount( params, concurrency.capacity );
+        adjustPrecisionInLeaf( params, concurrency );
+        return concurrency;
+    }
+
+    private static Concurrency concurrencyFromThreadCounts( JUnitCoreParameters params )
+    {
+        Concurrency concurrency = new Concurrency();
+        concurrency.suites = params.isParallelSuites() ? threadCountSuites( params ) : 0;
+        concurrency.classes = params.isParallelClasses() ? threadCountClasses( params ) : 0;
+        concurrency.methods = params.isParallelMethods() ? threadCountMethods( params ) : 0;
+        concurrency.capacity = toNonNegative( sumThreadCounts( concurrency ) );
+        return concurrency;
+    }
+
+    private static int countParallelEntities( JUnitCoreParameters params )
+    {
+        int count = 0;
+        if ( params.isParallelSuites() )
+        {
+            count++;
+        }
+
+        if ( params.isParallelClasses() )
+        {
+            count++;
+        }
+
+        if ( params.isParallelMethods() )
+        {
+            count++;
+        }
+        return count;
+    }
+
+    private static void adjustPrecisionInLeaf( JUnitCoreParameters params, Concurrency concurrency )
+    {
+        if ( params.isParallelMethods() )
+        {
+            concurrency.methods = concurrency.capacity - concurrency.suites - concurrency.classes;
+        }
+        else if ( params.isParallelClasses() )
+        {
+            concurrency.classes = concurrency.capacity - concurrency.suites;
+        }
+    }
+
+    private static void adjustLeaf( JUnitCoreParameters params, Concurrency concurrency )
+    {
+        if ( params.isParallelMethods() )
+        {
+            concurrency.methods = Integer.MAX_VALUE;
+        }
+        else if ( params.isParallelClasses() )
+        {
+            concurrency.classes = Integer.MAX_VALUE;
+        }
+    }
+
+    private static void setLeafInfinite( JUnitCoreParameters params, Concurrency concurrency )
+    {
+        if ( params.isParallelMethods() )
+        {
+            concurrency.methods = Integer.MAX_VALUE;
+        }
+        else if ( params.isParallelClasses() )
+        {
+            concurrency.classes = Integer.MAX_VALUE;
+        }
+        else if ( params.isParallelSuites() )
+        {
+            concurrency.suites = Integer.MAX_VALUE;
+        }
+    }
+
+    private static boolean isLeafUnspecified( JUnitCoreParameters params )
+    {
+        int maskOfParallel = params.isParallelSuites() ? 4 : 0;
+        maskOfParallel |= params.isParallelClasses() ? 2 : 0;
+        maskOfParallel |= params.isParallelMethods() ? 1 : 0;
+
+        int maskOfConcurrency = params.getThreadCountSuites() > 0 ? 4 : 0;
+        maskOfConcurrency |= params.getThreadCountClasses() > 0 ? 2 : 0;
+        maskOfConcurrency |= params.getThreadCountMethods() > 0 ? 1 : 0;
+
+        maskOfConcurrency &= maskOfParallel;
+
+        int leaf = Integer.lowestOneBit( maskOfParallel );
+        return maskOfConcurrency == maskOfParallel - leaf;
+    }
+
+    private static double sumThreadCounts( Concurrency concurrency )
+    {
+        double sum = concurrency.suites;
+        sum += concurrency.classes;
+        sum += concurrency.methods;
+        return sum;
+    }
+
+    private static boolean hasThreadCounts( JUnitCoreParameters jUnitCoreParameters )
+    {
+        return jUnitCoreParameters.isParallelSuites() && jUnitCoreParameters.getThreadCountSuites() > 0 ||
+            jUnitCoreParameters.isParallelClasses() && jUnitCoreParameters.getThreadCountClasses() > 0 ||
+            jUnitCoreParameters.isParallelMethods() && jUnitCoreParameters.getThreadCountMethods() > 0;
+    }
+
+    private static boolean hasThreadCount( JUnitCoreParameters jUnitCoreParameters )
+    {
+        return jUnitCoreParameters.getThreadCount() > 0;
+    }
+
+    private static int threadCountMethods( JUnitCoreParameters jUnitCoreParameters )
+    {
+        return multiplyByCoreCount( jUnitCoreParameters, jUnitCoreParameters.getThreadCountMethods() );
+    }
+
+    private static int threadCountClasses( JUnitCoreParameters jUnitCoreParameters )
+    {
+        return multiplyByCoreCount( jUnitCoreParameters, jUnitCoreParameters.getThreadCountClasses() );
+    }
+
+    private static int threadCountSuites( JUnitCoreParameters jUnitCoreParameters )
+    {
+        return multiplyByCoreCount( jUnitCoreParameters, jUnitCoreParameters.getThreadCountSuites() );
+    }
+
+    private static int multiplyByCoreCount( JUnitCoreParameters jUnitCoreParameters, double threadsPerCore )
+    {
+        double numberOfThreads =
+            jUnitCoreParameters.isPerCoreThreadCount() ? threadsPerCore * (double) availableProcessors : threadsPerCore;
+
+        return numberOfThreads > 0 ? toNonNegative( numberOfThreads ) : Integer.MAX_VALUE;
+    }
+
+    private static int minSuites( int threads, RunnerCounter counts )
+    {
+        long count = counts == null ? Integer.MAX_VALUE : counts.suites;
+        return Math.min( threads, toNonNegative( count ) );
+    }
+
+    private static int minClasses( int threads, RunnerCounter counts )
+    {
+        long count = counts == null ? Integer.MAX_VALUE : counts.classes;
+        return Math.min( threads, toNonNegative( count ) );
+    }
+
+    private static int minMethods( int threads, RunnerCounter counts )
+    {
+        long count = counts == null ? Integer.MAX_VALUE : counts.methods;
+        return Math.min( threads, toNonNegative( count ) );
+    }
+
+    private static int toNonNegative( long num )
+    {
+        return (int) Math.min( num > 0 ? num : 0, Integer.MAX_VALUE );
+    }
+
+    private static int toNonNegative( double num )
+    {
+        return (int) Math.min( num > 0 ? num : 0, Integer.MAX_VALUE );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/01c39b01/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/RunnerCounter.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/RunnerCounter.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/RunnerCounter.java
index ec0e80d..26f5fa0 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/RunnerCounter.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/RunnerCounter.java
@@ -26,15 +26,15 @@ package org.apache.maven.surefire.junitcore.pc;
  * @see ParallelComputerBuilder
  * @since 2.17
  */
-final public class RunnerCounter//todo needs refactoring, remove public
+final class RunnerCounter
 {
-    public final long suites;
+    final long suites;
 
-    public final long classes;
+    final long classes;
 
-    public final long methods;
+    final long methods;
 
-    public RunnerCounter( long suites, long classes, long methods )
+    RunnerCounter( long suites, long classes, long methods )
     {
         this.suites = suites;
         this.classes = classes;

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/01c39b01/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/Type.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/Type.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/Type.java
new file mode 100644
index 0000000..3f9685f
--- /dev/null
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/pc/Type.java
@@ -0,0 +1,31 @@
+package org.apache.maven.surefire.junitcore.pc;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author tibor17 (Tibor Digana)
+ * @since 2.17
+ */
+enum Type
+{
+    SUITES,
+    CLASSES,
+    METHODS
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/01c39b01/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit4SuiteTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit4SuiteTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit4SuiteTest.java
index 455f280..6bb58e1 100644
--- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit4SuiteTest.java
+++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit4SuiteTest.java
@@ -21,7 +21,9 @@ package org.apache.maven.surefire.junitcore;
 
 import junit.framework.JUnit4TestAdapter;
 import junit.framework.Test;
+import org.apache.maven.surefire.junitcore.pc.OptimizedParallelComputerTest;
 import org.apache.maven.surefire.junitcore.pc.ParallelComputerBuilderTest;
+import org.apache.maven.surefire.junitcore.pc.ParallelComputerUtilTest;
 import org.apache.maven.surefire.junitcore.pc.SchedulingStrategiesTest;
 import org.junit.runner.RunWith;
 import org.junit.runners.Suite;
@@ -35,9 +37,11 @@ import org.junit.runners.Suite;
 @Suite.SuiteClasses( {
         Surefire746Test.class,
         Surefire813IncorrectResultTest.class,
-        ParallelComputerFactoryTest.class,
+        ParallelComputerUtilTest.class,
         ParallelComputerBuilderTest.class,
-        SchedulingStrategiesTest.class
+        SchedulingStrategiesTest.class,
+        JUnitCoreParametersTest.class,
+        OptimizedParallelComputerTest.class
 } )
 @RunWith( Suite.class )
 public class JUnit4SuiteTest

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/01c39b01/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreParametersTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreParametersTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreParametersTest.java
index c73fa01..acfe429 100644
--- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreParametersTest.java
+++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreParametersTest.java
@@ -21,87 +21,116 @@ package org.apache.maven.surefire.junitcore;
 
 import java.util.Properties;
 
-import junit.framework.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+import static org.hamcrest.core.Is.is;
 
 /*
  * @author Kristian Rosenvold, kristian.rosenvold@gmail com
  */
 public class JUnitCoreParametersTest
-    extends TestCase
 {
-    public void testIsParallelMethod()
-        throws Exception
+    @Test
+    public void defaultParameters()
+    {
+        assertFalse( newTestSetDefault().isParallelismSelected() );
+        assertTrue( newTestSetDefault().isPerCoreThreadCount() );
+        assertThat( newTestSetDefault().getThreadCount(), is( 0 ) );
+        assertThat( newTestSetDefault().getThreadCountMethods(), is( 0 ) );
+        assertThat( newTestSetDefault().getThreadCountClasses(), is( 0 ) );
+        assertThat( newTestSetDefault().getThreadCountSuites(), is( 0 ) );
+        assertFalse( newTestSetDefault().isUseUnlimitedThreads() );
+        assertThat( newTestSetDefault().getParallelTestsTimeoutInSeconds(), is( 0d ) );
+        assertThat( newTestSetDefault().getParallelTestsTimeoutForcedInSeconds(), is( 0d ) );
+        assertTrue( newTestSetDefault().isParallelOptimization() );
+    }
+
+    @Test
+    public void optimizationParameter()
+    {
+        assertFalse( newTestSetOptimization( false ).isParallelOptimization() );
+    }
+
+    @Test
+    public void timeoutParameters()
     {
-        assertFalse( getTestSetClasses().isParallelMethods() );
-        assertTrue( getTestSetMethods().isParallelMethods() );
-        assertTrue( getTestSetBoth().isParallelMethods() );
+        JUnitCoreParameters parameters = newTestSetTimeouts( 5.5d, 11.1d );
+        assertThat( parameters.getParallelTestsTimeoutInSeconds(), is( 5.5d ) );
+        assertThat( parameters.getParallelTestsTimeoutForcedInSeconds(), is( 11.1d ) );
     }
 
-    public void testIsParallelClasses()
-        throws Exception
+    @Test
+    public void isParallelMethod()
     {
-        assertTrue( getTestSetClasses().isParallelClasses() );
-        assertFalse( getTestSetMethods().isParallelClasses() );
-        assertTrue( getTestSetBoth().isParallelClasses() );
+        assertFalse( newTestSetClasses().isParallelMethods() );
+        assertTrue( newTestSetMethods().isParallelMethods() );
+        assertTrue( newTestSetBoth().isParallelMethods() );
     }
 
-    public void testIsParallelBoth()
-        throws Exception
+    @Test
+    public void isParallelClasses()
     {
-        assertFalse( isParallelMethodsAndClasses( getTestSetClasses() ) );
-        assertFalse( isParallelMethodsAndClasses( getTestSetMethods() ) );
-        assertTrue( isParallelMethodsAndClasses( getTestSetBoth() ) );
+        assertTrue( newTestSetClasses().isParallelClasses() );
+        assertFalse( newTestSetMethods().isParallelClasses() );
+        assertTrue( newTestSetBoth().isParallelClasses() );
     }
 
-    public void testIsPerCoreThreadCount()
-        throws Exception
+    @Test
+    public void isParallelBoth()
     {
-        assertFalse( getTestSetClasses().isPerCoreThreadCount() );
-        assertFalse( getTestSetMethods().isPerCoreThreadCount() );
-        assertTrue( getTestSetBoth().isPerCoreThreadCount() );
+        assertFalse( isParallelMethodsAndClasses( newTestSetClasses() ) );
+        assertFalse( isParallelMethodsAndClasses( newTestSetMethods() ) );
+        assertTrue( isParallelMethodsAndClasses( newTestSetBoth() ) );
     }
 
-    public void testGetThreadCount()
-        throws Exception
+    @Test
+    public void isPerCoreThreadCount()
     {
-        assertFalse( getTestSetClasses().isPerCoreThreadCount() );
-        assertFalse( getTestSetMethods().isPerCoreThreadCount() );
-        assertTrue( getTestSetBoth().isPerCoreThreadCount() );
+        assertFalse( newTestSetClasses().isPerCoreThreadCount() );
+        assertFalse( newTestSetMethods().isPerCoreThreadCount() );
+        assertTrue( newTestSetBoth().isPerCoreThreadCount() );
     }
 
-    public void testIsUseUnlimitedThreads()
-        throws Exception
+    @Test
+    public void getThreadCount()
     {
-        assertFalse( getTestSetClasses().isUseUnlimitedThreads() );
-        assertTrue( getTestSetMethods().isUseUnlimitedThreads() );
-        assertFalse( getTestSetBoth().isUseUnlimitedThreads() );
+        assertFalse( newTestSetClasses().isPerCoreThreadCount() );
+        assertFalse( newTestSetMethods().isPerCoreThreadCount() );
+        assertTrue( newTestSetBoth().isPerCoreThreadCount() );
     }
 
-    public void testIsNoThreading()
-        throws Exception
+    @Test
+    public void isUseUnlimitedThreads()
     {
-        assertFalse( getTestSetClasses().isNoThreading() );
-        assertFalse( getTestSetMethods().isNoThreading() );
-        assertFalse( getTestSetBoth().isNoThreading() );
+        assertFalse( newTestSetClasses().isUseUnlimitedThreads() );
+        assertTrue( newTestSetMethods().isUseUnlimitedThreads() );
+        assertFalse( newTestSetBoth().isUseUnlimitedThreads() );
     }
 
-    public void testIsAnyParallelitySelected()
-        throws Exception
+    @Test
+    public void isNoThreading()
     {
-        assertTrue( getTestSetClasses().isAnyParallelitySelected() );
-        assertTrue( getTestSetMethods().isAnyParallelitySelected() );
-        assertTrue( getTestSetBoth().isAnyParallelitySelected() );
+        assertFalse( newTestSetClasses().isNoThreading() );
+        assertFalse( newTestSetMethods().isNoThreading() );
+        assertFalse( newTestSetBoth().isNoThreading() );
     }
 
+    @Test
+    public void isAnyParallelismSelected()
+    {
+        assertTrue( newTestSetClasses().isParallelismSelected() );
+        assertTrue( newTestSetMethods().isParallelismSelected() );
+        assertTrue( newTestSetBoth().isParallelismSelected() );
+    }
 
-    public void testToString()
-        throws Exception
+    private Properties newDefaultProperties()
     {
-        assertNotNull( getTestSetBoth().toString() );
+        return new Properties();
     }
 
 
-    public Properties getPropsetClasses()
+    private Properties newPropertiesClasses()
     {
         Properties props = new Properties();
         props.setProperty( JUnitCoreParameters.PARALLEL_KEY, "classes" );
@@ -111,7 +140,7 @@ public class JUnitCoreParametersTest
         return props;
     }
 
-    public Properties getPropsetMethods()
+    private Properties newPropertiesMethods()
     {
         Properties props = new Properties();
         props.setProperty( JUnitCoreParameters.PARALLEL_KEY, "methods" );
@@ -121,7 +150,7 @@ public class JUnitCoreParametersTest
         return props;
     }
 
-    public Properties getPropsetBoth()
+    private Properties newPropertiesBoth()
     {
         Properties props = new Properties();
         props.setProperty( JUnitCoreParameters.PARALLEL_KEY, "both" );
@@ -131,19 +160,49 @@ public class JUnitCoreParametersTest
         return props;
     }
 
-    private JUnitCoreParameters getTestSetBoth()
+    private Properties newPropertiesTimeouts( double timeout, double forcedTimeout )
+    {
+        Properties props = new Properties();
+        props.setProperty( JUnitCoreParameters.PARALLEL_TIMEOUT_KEY, Double.toString( timeout ) );
+        props.setProperty( JUnitCoreParameters.PARALLEL_TIMEOUTFORCED_KEY, Double.toString( forcedTimeout ) );
+        return props;
+    }
+
+    private Properties newPropertiesOptimization( boolean optimize )
+    {
+        Properties props = new Properties();
+        props.setProperty( JUnitCoreParameters.PARALLEL_OPTIMIZE_KEY, Boolean.toString( optimize ) );
+        return props;
+    }
+
+    private JUnitCoreParameters newTestSetDefault()
+    {
+        return new JUnitCoreParameters( newDefaultProperties() );
+    }
+
+    private JUnitCoreParameters newTestSetBoth()
+    {
+        return new JUnitCoreParameters( newPropertiesBoth() );
+    }
+
+    private JUnitCoreParameters newTestSetClasses()
+    {
+        return new JUnitCoreParameters( newPropertiesClasses() );
+    }
+
+    private JUnitCoreParameters newTestSetMethods()
     {
-        return new JUnitCoreParameters( getPropsetBoth() );
+        return new JUnitCoreParameters( newPropertiesMethods() );
     }
 
-    private JUnitCoreParameters getTestSetClasses()
+    private JUnitCoreParameters newTestSetOptimization( boolean optimize )
     {
-        return new JUnitCoreParameters( getPropsetClasses() );
+        return new JUnitCoreParameters( newPropertiesOptimization( optimize ) );
     }
 
-    private JUnitCoreParameters getTestSetMethods()
+    private JUnitCoreParameters newTestSetTimeouts( double timeout, double forcedTimeout )
     {
-        return new JUnitCoreParameters( getPropsetMethods() );
+        return new JUnitCoreParameters( newPropertiesTimeouts( timeout, forcedTimeout ) );
     }
 
     private boolean isParallelMethodsAndClasses( JUnitCoreParameters jUnitCoreParameters )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/01c39b01/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/OptimizedParallelComputerTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/OptimizedParallelComputerTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/OptimizedParallelComputerTest.java
deleted file mode 100644
index c1ac0b4..0000000
--- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/OptimizedParallelComputerTest.java
+++ /dev/null
@@ -1,323 +0,0 @@
-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 org.apache.maven.surefire.junitcore.pc.RunnerCounter;
-import org.apache.maven.surefire.testset.TestSetFailedException;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.experimental.theories.DataPoint;
-import org.junit.experimental.theories.Theories;
-import org.junit.experimental.theories.Theory;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-
-import java.util.Properties;
-
-import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.*;
-import static org.apache.maven.surefire.junitcore.ParallelComputerFactory.resolveConcurrency;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.*;
-
-/**
- * Testing an algorithm in {@link ParallelComputerFactory} which configures
- * optimized thread resources in ParallelComputer by given {@link JUnitCoreParameters}.
- *
- * @author Tibor Digana (tibor17)
- * @see org.apache.maven.surefire.junitcore.ParallelComputerFactory
- * @since 2.17
- */
-@RunWith( Theories.class )
-public final class OptimizedParallelComputerTest
-{
-    @DataPoint
-    public static final int CPU_1 = 1;
-
-    @DataPoint
-    public static final int CPU_4 = 4;
-
-    @Rule
-    public final ExpectedException exception = ExpectedException.none();
-
-    @Rule
-    public final Stopwatch runtime = new Stopwatch();
-
-    @BeforeClass
-    public static void beforeClass()
-    {
-        ParallelComputerFactory.overrideAvailableProcessors( 1 );
-    }
-
-    @AfterClass
-    public static void afterClass()
-    {
-        ParallelComputerFactory.setDefaultAvailableProcessors();
-    }
-
-    @Theory
-    public void threadCountSuites( int cpu )
-        throws TestSetFailedException
-    {
-        ParallelComputerFactory.overrideAvailableProcessors( cpu );
-        Properties properties = new Properties();
-        properties.setProperty( PARALLEL_KEY, "suites" );
-        properties.setProperty( THREADCOUNT_KEY, "3" );
-        JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        RunnerCounter counter = new RunnerCounter( 5, 10, 20 );
-        ParallelComputerFactory.Concurrency concurrency = resolveConcurrency( params, counter );
-        assertTrue( params.isParallelSuites() );
-        assertFalse( params.isParallelClasses() );
-        assertFalse( params.isParallelMethods() );
-        assertThat( concurrency.capacity, is( 0 ) );
-        assertThat( concurrency.suites, is( (int) Math.min( 3 * cpu, counter.suites ) ) );
-        assertThat( concurrency.classes, is( 0 ) );
-        assertThat( concurrency.methods, is( 0 ) );
-    }
-
-    @Theory
-    public void threadCountClasses( int cpu )
-        throws TestSetFailedException
-    {
-        ParallelComputerFactory.overrideAvailableProcessors( cpu );
-        Properties properties = new Properties();
-        properties.setProperty( PARALLEL_KEY, "classes" );
-        properties.setProperty( THREADCOUNT_KEY, "3" );
-        JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        RunnerCounter counter = new RunnerCounter( 1, 5, 10 );
-        ParallelComputerFactory.Concurrency concurrency = resolveConcurrency( params, counter );
-        assertFalse( params.isParallelSuites() );
-        assertTrue( params.isParallelClasses() );
-        assertFalse( params.isParallelMethods() );
-        assertThat( concurrency.capacity, is( 0 ) );
-        assertThat( concurrency.suites, is( 0 ) );
-        assertThat( concurrency.classes, is( (int) Math.min( 3 * cpu, counter.classes ) ) );
-        assertThat( concurrency.methods, is( 0 ) );
-    }
-
-    @Theory
-    public void threadCountMethods( int cpu )
-        throws TestSetFailedException
-    {
-        ParallelComputerFactory.overrideAvailableProcessors( cpu );
-        Properties properties = new Properties();
-        properties.setProperty( PARALLEL_KEY, "methods" );
-        properties.setProperty( THREADCOUNT_KEY, "3" );
-        JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        RunnerCounter counter = new RunnerCounter( 1, 2, 5 );
-        ParallelComputerFactory.Concurrency concurrency = resolveConcurrency( params, counter );
-        assertFalse( params.isParallelSuites() );
-        assertFalse( params.isParallelClasses() );
-        assertTrue( params.isParallelMethods() );
-        assertThat( concurrency.capacity, is( 0 ) );
-        assertThat( concurrency.suites, is( 0 ) );
-        assertThat( concurrency.classes, is( 0 ) );
-        assertThat( concurrency.methods, is( (int) Math.min( 3 * cpu, counter.methods ) ) );
-    }
-
-    @Theory
-    public void threadCountBoth( int cpu )
-        throws TestSetFailedException
-    {
-        ParallelComputerFactory.overrideAvailableProcessors( cpu );
-        Properties properties = new Properties();
-        properties.setProperty( PARALLEL_KEY, "both" );
-        properties.setProperty( THREADCOUNT_KEY, "3" );
-        JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        RunnerCounter counter = new RunnerCounter( 1, 2, 5 );
-        ParallelComputerFactory.Concurrency concurrency = resolveConcurrency( params, counter );
-        assertFalse( params.isParallelSuites() );
-        assertTrue( params.isParallelClasses() );
-        assertTrue( params.isParallelMethods() );
-        assertThat( concurrency.capacity, is( 3 * cpu ) );
-        assertThat( concurrency.suites, is( 0 ) );
-        assertThat( concurrency.classes, is( (int) Math.min( ( 3d / 2 ) * cpu, 2 ) ) );
-        assertThat( concurrency.methods, is( Integer.MAX_VALUE ) );
-    }
-
-    @Theory
-    public void threadCountClassesAndMethods( int cpu )
-        throws TestSetFailedException
-    {
-        ParallelComputerFactory.overrideAvailableProcessors( cpu );
-        Properties properties = new Properties();
-        properties.setProperty( PARALLEL_KEY, "classesAndMethods" );
-        properties.setProperty( THREADCOUNT_KEY, "3" );
-        JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        RunnerCounter counter = new RunnerCounter( 1, 2, 5 );
-        ParallelComputerFactory.Concurrency concurrency = resolveConcurrency( params, counter );
-        assertFalse( params.isParallelSuites() );
-        assertTrue( params.isParallelClasses() );
-        assertTrue( params.isParallelMethods() );
-        assertThat( concurrency.capacity, is( 3 * cpu ) );
-        assertThat( concurrency.suites, is( 0 ) );
-        assertThat( concurrency.classes, is( (int) Math.min( ( 3d / 2 ) * cpu, 2 ) ) );
-        assertThat( concurrency.methods, is( Integer.MAX_VALUE ) );
-    }
-
-    @Theory
-    public void threadCountSuitesAndMethods( int cpu )
-        throws TestSetFailedException
-    {
-        ParallelComputerFactory.overrideAvailableProcessors( cpu );
-        Properties properties = new Properties();
-        properties.setProperty( PARALLEL_KEY, "suitesAndMethods" );
-        properties.setProperty( THREADCOUNT_KEY, "3" );
-        JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        RunnerCounter counter = new RunnerCounter( 2, 3, 5 );
-        ParallelComputerFactory.Concurrency concurrency = resolveConcurrency( params, counter );
-        assertTrue( params.isParallelSuites() );
-        assertFalse( params.isParallelClasses() );
-        assertTrue( params.isParallelMethods() );
-        assertThat( concurrency.capacity, is( 3 * cpu ) );
-        assertThat( concurrency.suites, is( (int) Math.min( ( 3d / 2 ) * cpu, 2 ) ) );
-        assertThat( concurrency.classes, is( 0 ) );
-        assertThat( concurrency.methods, is( Integer.MAX_VALUE ) );
-    }
-
-    @Theory
-    public void threadCountSuitesAndClasses( int cpu )
-        throws TestSetFailedException
-    {
-        ParallelComputerFactory.overrideAvailableProcessors( cpu );
-        Properties properties = new Properties();
-        properties.setProperty( PARALLEL_KEY, "suitesAndClasses" );
-        properties.setProperty( THREADCOUNT_KEY, "3" );
-        JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        RunnerCounter counter = new RunnerCounter( 2, 5, 20 );
-        ParallelComputerFactory.Concurrency concurrency = resolveConcurrency( params, counter );
-        assertTrue( params.isParallelSuites() );
-        assertTrue( params.isParallelClasses() );
-        assertFalse( params.isParallelMethods() );
-        assertThat( concurrency.capacity, is( 3 * cpu ) );
-        assertThat( concurrency.suites, is( (int) Math.min( ( 2d * 3 / 7 ) * cpu, 2 ) ) );
-        assertThat( concurrency.classes, is( Integer.MAX_VALUE ) );
-        assertThat( concurrency.methods, is( 0 ) );
-    }
-
-    @Theory
-    public void threadCountAll( int cpu )
-        throws TestSetFailedException
-    {
-        ParallelComputerFactory.overrideAvailableProcessors( cpu );
-        Properties properties = new Properties();
-        properties.setProperty( PARALLEL_KEY, "all" );
-        properties.setProperty( THREADCOUNT_KEY, "3" );
-        JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        RunnerCounter counter = new RunnerCounter( 2, 5, 20 );
-        ParallelComputerFactory.Concurrency concurrency = resolveConcurrency( params, counter );
-        assertTrue( params.isParallelSuites() );
-        assertTrue( params.isParallelClasses() );
-        assertTrue( params.isParallelMethods() );
-        assertThat( concurrency.capacity, is( 3 * cpu ) );
-        assertThat( concurrency.suites, is( (int) Math.min( ( 2d * 3 / 11 ) * cpu, 2 ) ) );
-        assertThat( concurrency.classes, is( (int) Math.min( ( 5d * 3 / 11 ) * cpu, 5 ) ) );
-        assertThat( concurrency.methods, is( Integer.MAX_VALUE ) );
-    }
-
-    @Theory
-    public void reusableThreadCountSuitesAndClasses( int cpu )
-        throws TestSetFailedException
-    {
-        // 4 * cpu to 5 * cpu threads to run test classes
-        ParallelComputerFactory.overrideAvailableProcessors( cpu );
-        Properties properties = new Properties();
-        properties.setProperty( PARALLEL_KEY, "suitesAndClasses" );
-        properties.setProperty( THREADCOUNT_KEY, "6" );
-        properties.setProperty( THREADCOUNTSUITES_KEY, "2" );
-        JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        RunnerCounter counter = new RunnerCounter( 3, 5, 20 );
-        ParallelComputerFactory.Concurrency concurrency = resolveConcurrency( params, counter );
-        assertTrue( params.isParallelSuites() );
-        assertTrue( params.isParallelClasses() );
-        assertFalse( params.isParallelMethods() );
-        assertThat( concurrency.capacity, is( 6 * cpu ) );
-        assertThat( concurrency.suites, is( Math.min( 2 * cpu, 3 ) ) );
-        assertThat( concurrency.classes, is( Integer.MAX_VALUE ) );
-        assertThat( concurrency.methods, is( 0 ) );
-    }
-
-    @Theory
-    public void reusableThreadCountSuitesAndMethods( int cpu )
-        throws TestSetFailedException
-    {
-        // 4 * cpu to 5 * cpu threads to run test methods
-        ParallelComputerFactory.overrideAvailableProcessors( cpu );
-        Properties properties = new Properties();
-        properties.setProperty( PARALLEL_KEY, "suitesAndMethods" );
-        properties.setProperty( THREADCOUNT_KEY, "6" );
-        properties.setProperty( THREADCOUNTSUITES_KEY, "2" );
-        JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        RunnerCounter counter = new RunnerCounter( 3, 5, 20 );
-        ParallelComputerFactory.Concurrency concurrency = resolveConcurrency( params, counter );
-        assertTrue( params.isParallelSuites() );
-        assertFalse( params.isParallelClasses() );
-        assertTrue( params.isParallelMethods() );
-        assertThat( concurrency.capacity, is( 6 * cpu ) );
-        assertThat( concurrency.suites, is( Math.min( 2 * cpu, 3 ) ) );
-        assertThat( concurrency.classes, is( 0 ) );
-        assertThat( concurrency.methods, is( Integer.MAX_VALUE ) );
-    }
-
-    @Theory
-    public void reusableThreadCountClassesAndMethods( int cpu )
-        throws TestSetFailedException
-    {
-        // 4 * cpu to 5 * cpu threads to run test methods
-        ParallelComputerFactory.overrideAvailableProcessors( cpu );
-        Properties properties = new Properties();
-        properties.setProperty( PARALLEL_KEY, "classesAndMethods" );
-        properties.setProperty( THREADCOUNT_KEY, "6" );
-        properties.setProperty( THREADCOUNTCLASSES_KEY, "2" );
-        JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        RunnerCounter counter = new RunnerCounter( 3, 5, 20 );
-        ParallelComputerFactory.Concurrency concurrency = resolveConcurrency( params, counter );
-        assertFalse( params.isParallelSuites() );
-        assertTrue( params.isParallelClasses() );
-        assertTrue( params.isParallelMethods() );
-        assertThat( concurrency.capacity, is( 6 * cpu ) );
-        assertThat( concurrency.suites, is( 0 ) );
-        assertThat( concurrency.classes, is( Math.min( 2 * cpu, 5 ) ) );
-        assertThat( concurrency.methods, is( Integer.MAX_VALUE ) );
-    }
-
-    @Theory
-    public void reusableThreadCountAll( int cpu )
-        throws TestSetFailedException
-    {
-        // 8 * cpu to 13 * cpu threads to run test methods
-        ParallelComputerFactory.overrideAvailableProcessors( cpu );
-        Properties properties = new Properties();
-        properties.setProperty( PARALLEL_KEY, "all" );
-        properties.setProperty( THREADCOUNT_KEY, "14" );
-        properties.setProperty( THREADCOUNTSUITES_KEY, "2" );
-        properties.setProperty( THREADCOUNTCLASSES_KEY, "4" );
-        JUnitCoreParameters params = new JUnitCoreParameters( properties );
-        RunnerCounter counter = new RunnerCounter( 3, 5, 20 );
-        ParallelComputerFactory.Concurrency concurrency = resolveConcurrency( params, counter );
-        assertTrue( params.isParallelSuites() );
-        assertTrue( params.isParallelClasses() );
-        assertTrue( params.isParallelMethods() );
-        assertThat( concurrency.capacity, is( 14 * cpu ) );
-        assertThat( concurrency.suites, is( Math.min( 2 * cpu, 3 ) ) );
-        assertThat( concurrency.classes, is( Math.min( 4 * cpu, 5 ) ) );
-        assertThat( concurrency.methods, is( Integer.MAX_VALUE ) );
-    }
-}
\ No newline at end of file