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 2013/08/16 10:55:21 UTC

[3/3] git commit: reformat code + IT + junit.apt.vm + fork-options-and-parllel-execution.apt.vm

reformat code + IT + junit.apt.vm + fork-options-and-parllel-execution.apt.vm


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

Branch: refs/heads/master
Commit: a9d511a037f07bf9d40b908ca927b646eb96fb47
Parents: 911d374
Author: Tibor Digana <ti...@lycos.com>
Authored: Thu Aug 15 07:20:41 2013 +0200
Committer: Andreas Gudian <ag...@apache.org>
Committed: Fri Aug 16 10:34:38 2013 +0200

----------------------------------------------------------------------
 .../plugin/failsafe/IntegrationTestMojo.java    |  18 +-
 .../plugin/surefire/AbstractSurefireMojo.java   |   6 +-
 .../surefire/SurefireExecutionParameters.java   |   8 +-
 .../booterclient/ChecksumCalculator.java        |   5 +
 .../maven/plugin/surefire/SurefirePlugin.java   |  18 +-
 .../fork-options-and-parallel-execution.apt.vm  |  51 +-
 .../src/site/apt/examples/junit.apt.vm          |   4 +
 .../maven/surefire/its/JUnit47ParallelIT.java   | 495 +++++++++++++++++++
 .../surefire/its/fixture/MavenLauncher.java     |   5 +
 .../surefire/its/fixture/SurefireLauncher.java  |  68 ++-
 .../src/test/resources/junit47-parallel/pom.xml |  33 ++
 .../test/java/surefireparallel/Suite1Test.java  |  39 ++
 .../test/java/surefireparallel/Suite2Test.java  |  39 ++
 .../test/java/surefireparallel/TestClass.java   |  53 ++
 .../java/surefireparallel/Waiting1Test.java     |  50 ++
 .../java/surefireparallel/Waiting2Test.java     |  50 ++
 .../java/surefireparallel/Waiting3Test.java     |  50 ++
 .../java/surefireparallel/Waiting4Test.java     |  50 ++
 .../java/surefireparallel/Waiting5Test.java     |  50 ++
 .../java/surefireparallel/Waiting6Test.java     |  50 ++
 .../java/surefireparallel/Waiting7Test.java     |  50 ++
 .../java/surefireparallel/Waiting8Test.java     |  50 ++
 .../surefire/junitcore/JUnitCoreParameters.java |  57 ++-
 .../surefire/junitcore/JUnitCoreWrapper.java    | 167 ++-----
 .../junitcore/NonConcurrentRunListener.java     |   6 +-
 .../junitcore/ParallelComputerFactory.java      | 107 ++--
 .../pc/AbstractThreadPoolStrategy.java          |  80 +--
 .../maven/surefire/junitcore/pc/Balancer.java   |   5 +-
 .../surefire/junitcore/pc/BalancerFactory.java  |   6 +-
 .../surefire/junitcore/pc/InvokerStrategy.java  |  30 +-
 .../pc/NonSharedThreadPoolStrategy.java         |  28 +-
 .../surefire/junitcore/pc/NullBalancer.java     |   6 +-
 .../surefire/junitcore/pc/ParallelComputer.java | 117 ++++-
 .../junitcore/pc/ParallelComputerBuilder.java   | 357 ++++++++-----
 .../maven/surefire/junitcore/pc/Scheduler.java  | 299 +++++++----
 .../junitcore/pc/SchedulingStrategies.java      |  28 +-
 .../junitcore/pc/SchedulingStrategy.java        |  24 +-
 .../junitcore/pc/SharedThreadPoolStrategy.java  |  55 ++-
 .../junitcore/pc/ThreadResourcesBalancer.java   |  10 +-
 .../junitcore/ParallelComputerFactoryTest.java  | 256 ++++++++--
 .../maven/surefire/junitcore/Stopwatch.java     |  46 ++
 .../pc/ParallelComputerBuilderTest.java         | 470 ++++++++++--------
 .../surefire/junitcore/pc/RangeMatcher.java     |  12 +-
 .../junitcore/pc/SchedulingStrategiesTest.java  | 140 +++---
 .../maven/surefire/junitcore/pc/Stopwatch.java  |  45 --
 45 files changed, 2648 insertions(+), 945 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
index 41278c3..3329bcb 100644
--- a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
+++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
@@ -140,24 +140,30 @@ public class IntegrationTestMojo
 
     /**
      * Stop executing queued parallel JUnit tests after a certain number of seconds.
+     * <br/>
+     * Example values: "3.5", "4"<br/>
+     * <br/>
      * If set to 0, wait forever, never timing out.
      * Makes sense with specified <code>parallel</code> different from "none".
      *
      * @since 2.16
      */
     @Parameter( property = "failsafe.parallel.timeout" )
-    private int parallelTestsTimeoutInSeconds;
+    private double parallelTestsTimeoutInSeconds;
 
     /**
      * Stop executing queued parallel JUnit tests
      * and <em>interrupt</em> currently running tests after a certain number of seconds.
+     * <br/>
+     * Example values: "3.5", "4"<br/>
+     * <br/>
      * If set to 0, wait forever, never timing out.
      * Makes sense with specified <code>parallel</code> different from "none".
      *
      * @since 2.16
      */
     @Parameter( property = "failsafe.parallel.forcedTimeout" )
-    private int parallelTestsTimeoutForcedInSeconds;
+    private double parallelTestsTimeoutForcedInSeconds;
     
     /**
      * A list of &lt;include> elements specifying the tests (by pattern) that should be included in testing. When not
@@ -454,19 +460,19 @@ public class IntegrationTestMojo
         this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds;
     }
 
-    public int getParallelTestsTimeoutInSeconds() {
+    public double getParallelTestsTimeoutInSeconds() {
         return parallelTestsTimeoutInSeconds;
     }
 
-    public void setParallelTestsTimeoutInSeconds( int parallelTestsTimeoutInSeconds ) {
+    public void setParallelTestsTimeoutInSeconds( double parallelTestsTimeoutInSeconds ) {
         this.parallelTestsTimeoutInSeconds = parallelTestsTimeoutInSeconds;
     }
 
-    public int getParallelTestsTimeoutForcedInSeconds() {
+    public double getParallelTestsTimeoutForcedInSeconds() {
         return parallelTestsTimeoutForcedInSeconds;
     }
 
-    public void setParallelTestsTimeoutForcedInSeconds( int parallelTestsTimeoutForcedInSeconds ) {
+    public void setParallelTestsTimeoutForcedInSeconds( double parallelTestsTimeoutForcedInSeconds ) {
         this.parallelTestsTimeoutForcedInSeconds = parallelTestsTimeoutForcedInSeconds;
     }
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
index 5975d7d..d8b9f9d 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
@@ -1143,9 +1143,9 @@ public abstract class AbstractSurefireMojo
         getProperties().setProperty( ProviderParameterNames.THREADCOUNTCLASSES_PROP, Integer.toString( getThreadCountClasses() ) );
         getProperties().setProperty( ProviderParameterNames.THREADCOUNTMETHODS_PROP, Integer.toString( getThreadCountMethods() ) );
         getProperties().setProperty( ProviderParameterNames.PARALLEL_TIMEOUT_PROP,
-                Integer.toString( getParallelTestsTimeoutInSeconds() ) );
+                Double.toString( getParallelTestsTimeoutInSeconds() ) );
         getProperties().setProperty( ProviderParameterNames.PARALLEL_TIMEOUTFORCED_PROP,
-                Integer.toString( getParallelTestsTimeoutForcedInSeconds() ) );
+                Double.toString( getParallelTestsTimeoutForcedInSeconds() ) );
 
         String message =
             "parallel='" + usedParallel + '\'' + ", perCoreThreadCount=" + getPerCoreThreadCount() + ", threadCount="
@@ -2224,7 +2224,7 @@ public abstract class AbstractSurefireMojo
             {
                 return;
             }
-            if ( junitArtifact != null && !junit47Compatible )
+            if ( junitArtifact != null )
             {
                 throw new MojoFailureException( "groups/excludedGroups are specified but JUnit version on classpath"
                                                     + " is too old to support groups. Check your dependency:tree to see if your project is picking up an old junit version" );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
index 0b5a1af..22152f0 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
@@ -101,13 +101,13 @@ public interface SurefireExecutionParameters
 
     void setForkedProcessTimeoutInSeconds( int forkedProcessTimeoutInSeconds );
 
-    int getParallelTestsTimeoutInSeconds();
+    double getParallelTestsTimeoutInSeconds();
 
-    void setParallelTestsTimeoutInSeconds( int parallelTestsTimeoutInSeconds );
+    void setParallelTestsTimeoutInSeconds( double parallelTestsTimeoutInSeconds );
 
-    int getParallelTestsTimeoutForcedInSeconds();
+    double getParallelTestsTimeoutForcedInSeconds();
 
-    void setParallelTestsTimeoutForcedInSeconds( int parallelTestsTimeoutForcedInSeconds );
+    void setParallelTestsTimeoutForcedInSeconds( double parallelTestsTimeoutForcedInSeconds );
 
     boolean isUseSystemClassLoader();
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ChecksumCalculator.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ChecksumCalculator.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ChecksumCalculator.java
index 03cbd4c..29fbf11 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ChecksumCalculator.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ChecksumCalculator.java
@@ -54,6 +54,11 @@ public class ChecksumCalculator
         checksumItems.add( value );
     }
 
+    public void add( double value )
+    {
+        checksumItems.add( value );
+    }
+
     public void add( Map<?, ?> map )
     {
         if ( map != null )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
index 189161b..1477b23 100644
--- a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
+++ b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
@@ -122,24 +122,30 @@ public class SurefirePlugin
 
     /**
      * Stop executing queued parallel JUnit tests after a certain number of seconds.
+     * <br/>
+     * Example values: "3.5", "4"<br/>
+     * <br/>
      * If set to 0, wait forever, never timing out.
      * Makes sense with specified <code>parallel</code> different from "none".
      *
      * @since 2.16
      */
     @Parameter( property = "surefire.parallel.timeout" )
-    private int parallelTestsTimeoutInSeconds;
+    private double parallelTestsTimeoutInSeconds;
 
     /**
      * Stop executing queued parallel JUnit tests
      * and <em>interrupt</em> currently running tests after a certain number of seconds.
+     * <br/>
+     * Example values: "3.5", "4"<br/>
+     * <br/>
      * If set to 0, wait forever, never timing out.
      * Makes sense with specified <code>parallel</code> different from "none".
      *
      * @since 2.16
      */
     @Parameter( property = "surefire.parallel.forcedTimeout" )
-    private int parallelTestsTimeoutForcedInSeconds;
+    private double parallelTestsTimeoutForcedInSeconds;
     
     /**
      * A list of &lt;include> elements specifying the tests (by pattern) that should be included in testing. When not
@@ -447,19 +453,19 @@ public class SurefirePlugin
         this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds;
     }
 
-    public int getParallelTestsTimeoutInSeconds() {
+    public double getParallelTestsTimeoutInSeconds() {
         return parallelTestsTimeoutInSeconds;
     }
 
-    public void setParallelTestsTimeoutInSeconds( int parallelTestsTimeoutInSeconds ) {
+    public void setParallelTestsTimeoutInSeconds( double parallelTestsTimeoutInSeconds ) {
         this.parallelTestsTimeoutInSeconds = parallelTestsTimeoutInSeconds;
     }
 
-    public int getParallelTestsTimeoutForcedInSeconds() {
+    public double getParallelTestsTimeoutForcedInSeconds() {
         return parallelTestsTimeoutForcedInSeconds;
     }
 
-    public void setParallelTestsTimeoutForcedInSeconds( int parallelTestsTimeoutForcedInSeconds ) {
+    public void setParallelTestsTimeoutForcedInSeconds( double parallelTestsTimeoutForcedInSeconds ) {
         this.parallelTestsTimeoutForcedInSeconds = parallelTestsTimeoutForcedInSeconds;
     }
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/maven-surefire-plugin/src/site/apt/examples/fork-options-and-parallel-execution.apt.vm
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/apt/examples/fork-options-and-parallel-execution.apt.vm b/maven-surefire-plugin/src/site/apt/examples/fork-options-and-parallel-execution.apt.vm
index 207364d..7b87379 100644
--- a/maven-surefire-plugin/src/site/apt/examples/fork-options-and-parallel-execution.apt.vm
+++ b/maven-surefire-plugin/src/site/apt/examples/fork-options-and-parallel-execution.apt.vm
@@ -42,17 +42,58 @@ Fork Options and Parallel Test Execution
 * Parallel Test Execution
 
   Basically, there are two ways in Surefire to achieve parallel test execution.
+  
   The most obvious one is by using the <<<parallel>>> parameter. The possible
   values depend on the test provider used. For JUnit 4.7 and onwards, this may
-  be <<<methods>>>, <<<classes>>>, or <<<both>>>.
+  be <<<methods>>>, <<<classes>>>, <<<both>>>, <<<suites>>>,
+  <<<suitesAndClasses>>>, <<<suitesAndMethods>>>, <<<classesAndMethods>>>,
+  <<<all>>>.
+  As of surefire 2.16, the value "both" is deprecated but it still can be
+  used and behaves same as <<<classesAndMethods>>>.
 
   See the example pages for {{{./junit.html#Running_tests_in_parallel}JUnit}}
   and {{{./testng.html#Running_tests_in_parallel}TestNG}} for details.
 
-  The <extent> of the parallelism is configured using the parameters
-  <<<threadCount>>>, and optionally <<<perCoreThreadCount>>>, or
-  <<<useUnlimitedThreads>>>.
-
+  The <extent> of the parallelism is configured using the following parameters.
+  The parameter <<<useUnlimitedThreads>>> declares the unlimited number of
+  threads. Unless <<<useUnlimitedThreads>>> is set to "true", the parameter
+  <<<threadCount>>> can be used with the optional parameter
+  <<<perCoreThreadCount>>>.
+  The parameters <<<useUnlimitedThreads>>>, <<<threadCount>>> make sense with
+  thereinbefore value specified in the parameter <<<parallel>>>.
+  
+  You can impose thread-count limitations on suites, classes or methods if you
+  configure some of the parameters <<<threadCountSuites>>>,
+  <<<threadCountClasses>>> or <<<threadCountMethods>>>.
+  If the only <<<threadCount>>> is specified, the surefire attempts to estimate
+  thread-counts for suites, classes and methods and reuse the threads in favor
+  of parallel methods (possibly increasing concurrent methods).
+  
+  As an example with unlimited number of threads, there is maximum of three
+  concurrent threads to execute suites:
+  parallel = all, useUnlimitedThreads = true, threadCountSuites = 3.
+  
+  In the second example, the number of concurrent methods is not strictly
+  limited:
+  parallel = classesAndMethods, threadCount = 8, threadCountClasses = 3.
+  Here the number of parallel methods is varying from 5 to 7.
+  Similarily with parallel = all, but the sum of <<<threadCountSuites>>> and
+  <<<threadCountClasses>>> must not excit certain <<<threadCount>>> - 1.
+  Other combinations are possible with unspecified thread-count leaf. Make sure
+  that the leaf is last from the order suites-classes-methods in <<<parallel>>>.
+  
+  In the third example the thread-counts represent a ratio, e.g. for
+  parallel = all, threadCount = 16, threadCountSuites = 2,
+  threadCountClasses = 3, threadCountMethods = 5. Thus the concurrent suites
+  will be 20%, concurrent classes 30%, and concurrent methods 50%.
+  
+  Finally, the <<<threadCount>>> and <<<useUnlimitedThreads>>> may not be
+  necessarily configured if the equivalent thread-counts are specified for the
+  value in <<<parallel>>>.
+  
+  The surefire is always trying to reuse threads, optimize the thread-counts,
+  and prefers thread fairness.
+  
   <<The important thing to remember>> with the <<<parallel>>> option is: the
   concurrency happens within the same JVM process. That is efficient in terms of
   memory and execution time, but you may be more vulnerable towards race

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/maven-surefire-plugin/src/site/apt/examples/junit.apt.vm
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/apt/examples/junit.apt.vm b/maven-surefire-plugin/src/site/apt/examples/junit.apt.vm
index 74e32cb..980779a 100644
--- a/maven-surefire-plugin/src/site/apt/examples/junit.apt.vm
+++ b/maven-surefire-plugin/src/site/apt/examples/junit.apt.vm
@@ -142,6 +142,10 @@ else
   This is particularly useful for slow tests that can have high concurrency.
 
   As of surefire 2.7, no additional dependencies are needed to use the full set of options with parallel.
+  As of surefire 2.16, new thread-count attributes are introduced, namely <<<threadCountSuites>>>, <<<threadCountClasses>>> and
+  <<<threadCountMethods>>>. Additionally new attributes, <<<parallelTestsTimeoutInSeconds>>> and
+  <<<parallelTestsTimeoutForcedInSeconds>>>, are used to shutdown the parallel execution after an elapsed timeout, and 
+  the attribute "parallel" specifies new values.
   
   See also {{{./fork-options-and-parallel-execution.html}Fork Options and Parallel Test Execution}}.
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/JUnit47ParallelIT.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/JUnit47ParallelIT.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/JUnit47ParallelIT.java
new file mode 100644
index 0000000..e236e54
--- /dev/null
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/JUnit47ParallelIT.java
@@ -0,0 +1,495 @@
+package org.apache.maven.surefire.its;
+
+/*
+ * 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.its.fixture.SurefireJUnit4IntegrationTestCase;
+import org.apache.maven.surefire.its.fixture.SurefireLauncher;
+import org.junit.Test;
+
+/**
+ * Testing JUnitCoreWrapper with ParallelComputerBuilder.
+ *
+ * @author Tibor Digana (tibor17)
+ * @since 2.16
+ */
+public class JUnit47ParallelIT
+    extends SurefireJUnit4IntegrationTestCase
+{
+
+    @Test
+    public void unknownThreadCountSuites()
+    {
+        unpack().parallelSuites().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog(
+            "Use threadCount or threadCountSuites > 0 or useUnlimitedThreads=true for parallel='suites'" );
+    }
+
+    @Test
+    public void unknownThreadCountClasses()
+    {
+        unpack().parallelClasses().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog(
+            "Use threadCount or threadCountClasses > 0 or useUnlimitedThreads=true for parallel='classes'" );
+    }
+
+    @Test
+    public void unknownThreadCountMethods()
+    {
+        unpack().parallelMethods().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog(
+            "Use threadCount or threadCountMethods > 0 or useUnlimitedThreads=true for parallel='methods'" );
+
+    }
+
+    @Test
+    public void unknownThreadCountBoth()
+    {
+        unpack().parallelBoth().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog(
+            "Use useUnlimitedThreads=true, " +
+                "or only threadCount > 0, " +
+                "or (threadCountClasses > 0 and threadCountMethods > 0), " +
+                "or (threadCount > 0 and threadCountClasses > 0 and threadCountMethods > 0), " +
+                "or (threadCount > 0 and threadCountClasses > 0 and threadCount > threadCountClasses) " +
+                "for parallel='both' or parallel='classesAndMethods'" );
+    }
+
+    @Test
+    public void unknownThreadCountAll()
+    {
+        unpack().parallelAll().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog(
+            "Use useUnlimitedThreads=true, " +
+                "or only threadCount > 0, " +
+                "or (threadCountSuites > 0 and threadCountClasses > 0 and threadCountMethods > 0), " +
+                "or every thread-count is specified, " +
+                "or (threadCount > 0 and threadCountSuites > 0 and threadCountClasses > 0 " +
+                "and threadCount > threadCountSuites + threadCountClasses) " +
+                "for parallel='all'" );
+    }
+
+    @Test
+    public void unknownThreadCountSuitesAndClasses()
+    {
+        unpack().parallelSuitesAndClasses().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog(
+            "Use useUnlimitedThreads=true, " +
+                "or only threadCount > 0, " +
+                "or (threadCountSuites > 0 and threadCountClasses > 0), " +
+                "or (threadCount > 0 and threadCountSuites > 0 and threadCountClasses > 0) " +
+                "or (threadCount > 0 and threadCountSuites > 0 and threadCount > threadCountSuites) " +
+                "for parallel='suitesAndClasses' or 'both'" );
+    }
+
+    @Test
+    public void unknownThreadCountSuitesAndMethods()
+    {
+        unpack().parallelSuitesAndMethods().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog(
+            "Use useUnlimitedThreads=true, " +
+                "or only threadCount > 0, " +
+                "or (threadCountSuites > 0 and threadCountMethods > 0), " +
+                "or (threadCount > 0 and threadCountSuites > 0 and threadCountMethods > 0), " +
+                "or (threadCount > 0 and threadCountSuites > 0 and threadCount > threadCountSuites) " +
+                "for parallel='suitesAndMethods'" );
+    }
+
+    @Test
+    public void unknownThreadCountClassesAndMethods()
+    {
+        unpack().parallelClassesAndMethods().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog(
+            "Use useUnlimitedThreads=true, " +
+                "or only threadCount > 0, " +
+                "or (threadCountClasses > 0 and threadCountMethods > 0), " +
+                "or (threadCount > 0 and threadCountClasses > 0 and threadCountMethods > 0), " +
+                "or (threadCount > 0 and threadCountClasses > 0 and threadCount > threadCountClasses) " +
+                "for parallel='both' or parallel='classesAndMethods'" );
+    }
+
+    @Test
+    public void serial()
+    {
+        // takes 7.2 sec
+        unpack().setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void useUnlimitedThreadsSuites1()
+    {
+        // takes 3.6 sec
+        unpack().parallelSuites().useUnlimitedThreads().setTestToRun( "Suite*Test" ).executeTest()
+            //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void useUnlimitedThreadsSuites2()
+    {
+        // takes 3.6 sec
+        unpack().parallelSuites().useUnlimitedThreads().threadCountSuites( 5 ).setTestToRun( "Suite*Test" )
+            .executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void useUnlimitedThreadsClasses1()
+    {
+        // takes 1.8 sec
+        unpack().parallelClasses().useUnlimitedThreads().setTestToRun( "Suite*Test" ).executeTest()
+            //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void useUnlimitedThreadsClasses2()
+    {
+        // takes 1.8 sec
+        unpack().parallelClasses().useUnlimitedThreads().threadCountClasses( 5 ).setTestToRun( "Suite*Test" )
+            .executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void useUnlimitedThreadsMethods1()
+    {
+        // takes 2.4 sec
+        unpack().parallelMethods().useUnlimitedThreads().setTestToRun( "Suite*Test" ).executeTest()
+            //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void useUnlimitedThreadsMethods2()
+    {
+        // takes 2.4 sec
+        unpack().parallelMethods().useUnlimitedThreads().threadCountMethods( 5 ).setTestToRun( "Suite*Test" )
+            .executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void unlimitedThreadsSuitesAndClasses1()
+    {
+        // takes 0.9 sec
+        unpack().parallelSuitesAndClasses().useUnlimitedThreads().setTestToRun( "Suite*Test" ).executeTest()
+        //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void unlimitedThreadsSuitesAndClasses2()
+    {
+        // takes 0.9 sec
+        // 1.8 sec with 4 parallel classes
+        unpack().parallelSuitesAndClasses().useUnlimitedThreads().threadCountSuites( 5 ).threadCountClasses( 15 )
+            .setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void unlimitedThreadsSuitesAndMethods1()
+    {
+        // takes 1.2 sec
+        unpack().parallelSuitesAndMethods().useUnlimitedThreads().setTestToRun( "Suite*Test" ).executeTest()
+            //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void unlimitedThreadsSuitesAndMethods2()
+    {
+        // takes 1.2 sec
+        unpack().parallelSuitesAndMethods().useUnlimitedThreads().threadCountSuites( 5 ).threadCountMethods( 15 )
+            .setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void unlimitedThreadsClassesAndMethods1()
+    {
+        // takes 0.6 sec
+        unpack().parallelClassesAndMethods().useUnlimitedThreads().setTestToRun( "Suite*Test" ).executeTest()
+            //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void unlimitedThreadsClassesAndMethods2()
+    {
+        // takes 0.6 sec
+        unpack().parallelClassesAndMethods().useUnlimitedThreads().threadCountClasses( 5 ).threadCountMethods( 15 )
+            .setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void unlimitedThreadsAll1()
+    {
+        // takes 0.3 sec
+        unpack().parallelAll().useUnlimitedThreads().setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void unlimitedThreadsAll2()
+    {
+        // takes 0.3 sec
+        unpack().parallelAll().useUnlimitedThreads().threadCountSuites( 5 ).threadCountClasses( 15 )
+            .threadCountMethods( 30 ).setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void threadCountSuites()
+    {
+        // takes 3.6 sec
+        unpack().parallelSuites().threadCount( 3 ).setTestToRun( "Suite*Test" ).executeTest()
+            //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void threadCountClasses()
+    {
+        // takes 3.6 sec for single core
+        // takes 1.8 sec for double core
+        unpack().parallelClasses().threadCount( 3 ).setTestToRun( "Suite*Test" ).executeTest()
+            //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void threadCountMethods()
+    {
+        // takes 2.4 sec
+        unpack().parallelMethods().threadCount( 3 ).setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void threadCountClassesAndMethodsOneCore()
+    {
+        // takes 4.8 sec
+        unpack().disablePerCoreThreadCount().parallelClassesAndMethods().threadCount( 3 ).setTestToRun( "Suite*Test" )
+            .executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void threadCountClassesAndMethods()
+    {
+        // takes 2.4 sec for double core CPU
+        unpack().parallelClassesAndMethods().threadCount( 3 ).setTestToRun( "Suite*Test" ).executeTest()
+        //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void threadCountSuitesAndMethods()
+    {
+        // usually 24 times 0.3 sec = 7.2 sec with one core CPU
+        // takes 1.8 sec for double core CPU
+        unpack().parallelSuitesAndMethods().threadCount( 3 ).setTestToRun( "Suite*Test" ).executeTest()
+            //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void threadCountSuitesAndClasses()
+    {
+        unpack().parallelSuitesAndClasses().threadCount( 3 ).setTestToRun( "Suite*Test" ).executeTest()
+            //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void threadCountAll()
+    {
+        unpack().parallelAll().threadCount( 3 ).setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void everyThreadCountSuitesAndClasses()
+    {
+        // takes 1.8 sec for double core CPU
+        unpack().parallelSuitesAndClasses().threadCount( 3 ).threadCountSuites( 34 ).threadCountClasses( 66 )
+            .setTestToRun( "Suite*Test" ).executeTest()
+            //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void everyThreadCountSuitesAndMethods()
+    {
+        // takes 1.8 sec for double core CPU
+        unpack().parallelSuitesAndMethods().threadCount( 3 ).threadCountSuites( 34 ).threadCountMethods( 66 )
+            .setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void everyThreadCountClassesAndMethods()
+    {
+        // takes 1.8 sec for double core CPU
+        unpack().parallelClassesAndMethods().threadCount( 3 ).threadCountClasses( 34 ).threadCountMethods( 66 )
+            .setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void everyThreadCountAll()
+    {
+        // takes 2.4 sec for double core CPU
+        unpack().parallelAll().threadCount( 3 ).threadCountSuites( 17 ).threadCountClasses( 34 ).threadCountMethods(
+            49 ).setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void reusableThreadCountSuitesAndClasses()
+    {
+        // 4 * cpu to 5 * cpu threads to run test classes
+        // takes cca 1.8 sec
+        unpack().parallelSuitesAndClasses().disablePerCoreThreadCount().threadCount( 6 ).threadCountSuites( 2 )
+            .setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void reusableThreadCountSuitesAndMethods()
+    {
+        // 4 * cpu to 5 * cpu threads to run test methods
+        // takes cca 1.8 sec
+        unpack().parallelSuitesAndMethods().disablePerCoreThreadCount().threadCount( 6 ).threadCountSuites( 2 )
+            .setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void reusableThreadCountClassesAndMethods()
+    {
+        // 4 * cpu to 5 * cpu threads to run test methods
+        // takes cca 1.8 sec
+        unpack().parallelClassesAndMethods().disablePerCoreThreadCount().threadCount( 6 ).threadCountClasses( 2 )
+            .setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void reusableThreadCountAll()
+    {
+        // 8 * cpu to 13 * cpu threads to run test methods
+        // takes 0.9 sec
+        unpack().parallelAll().disablePerCoreThreadCount().threadCount( 14 ).threadCountSuites( 2 ).threadCountClasses(
+            4 ).setTestToRun( "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void suites()
+    {
+        // takes 3.6 sec
+        unpack().parallelSuites().threadCountSuites( 5 ).setTestToRun( "Suite*Test" ).executeTest()
+            //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void classes()
+    {
+        // takes 1.8 sec on any CPU because the suites are running in a sequence
+        unpack().parallelClasses().threadCountClasses( 5 ).setTestToRun( "Suite*Test" ).executeTest()
+            //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void methods()
+    {
+        // takes 2.4 sec on any CPU because every class has only three methods
+        // and the suites and classes are running in a sequence
+        unpack().parallelMethods().threadCountMethods( 5 ).setTestToRun( "Suite*Test" ).executeTest()
+            //.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void suitesAndClasses()
+    {
+        // takes 0.9 sec
+        unpack().parallelSuitesAndClasses().threadCountSuites( 5 ).threadCountClasses( 15 ).setTestToRun(
+            "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void suitesAndMethods()
+    {
+        // takes 1.2 sec on any CPU
+        unpack().parallelSuitesAndMethods().threadCountSuites( 5 ).threadCountMethods( 15 ).setTestToRun(
+            "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void classesAndMethods()
+    {
+        // takes 0.6 sec on any CPU
+        unpack().parallelClassesAndMethods().threadCountClasses( 5 ).threadCountMethods( 15 ).setTestToRun(
+            "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void all()
+    {
+        // takes 0.3 sec on any CPU
+        unpack().parallelAll().threadCountSuites( 5 ).threadCountClasses( 15 ).threadCountMethods( 30 ).setTestToRun(
+            "Suite*Test" ).executeTest()//.verifyErrorFree( 24 )
+        ;
+    }
+
+    @Test
+    public void shutdown()
+    {
+        // executes for 2.5 sec until timeout has elapsed
+        unpack().parallelMethods().threadCountMethods( 2 ).parallelTestsTimeoutInSeconds( 2.5d ).setTestToRun(
+            "TestClass" ).failNever().executeTest().verifyTextInLog(
+            "The test run has finished abruptly after timeout of 2.5 seconds." );
+    }
+
+    @Test
+    public void forcedShutdown()
+    {
+        // executes for 2.5 sec until timeout has elapsed
+        unpack().parallelMethods().threadCountMethods( 2 ).parallelTestsTimeoutForcedInSeconds( 2.5d ).setTestToRun(
+            "TestClass" ).failNever().executeTest().verifyTextInLog(
+            "The test run has finished abruptly after timeout of 2.5 seconds." );
+    }
+
+    @Test
+    public void timeoutAndForcedShutdown()
+    {
+        // executes for one sec until timeout has elapsed
+        unpack().parallelMethods().threadCountMethods( 2 ).parallelTestsTimeoutInSeconds( 1 )
+            .parallelTestsTimeoutForcedInSeconds( 2.5d ).setTestToRun( "TestClass" ).failNever().executeTest()
+            .verifyTextInLog( "The test run has finished abruptly after timeout of 1.0 seconds." );
+    }
+
+    private SurefireLauncher unpack()
+    {
+        return unpack( "junit47-parallel" );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java
index e0befcc..8d4a385 100755
--- a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java
@@ -339,6 +339,11 @@ public class MavenLauncher
         return addGoal( "-D" + variable + "=" + value );
     }
 
+    public MavenLauncher sysProp( String variable, double value )
+    {
+        return addGoal( "-D" + variable + "=" + value );
+    }
+
     public MavenLauncher showExceptionMessages()
     {
         addCliOption( "-e" );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/SurefireLauncher.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/SurefireLauncher.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/SurefireLauncher.java
index 7b65783..3ac3e20 100755
--- a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/SurefireLauncher.java
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/SurefireLauncher.java
@@ -313,14 +313,18 @@ public class SurefireLauncher
         return surefireVersion;
     }
 
-    public SurefireLauncher parallel( String parallel )
+    public SurefireLauncher disablePerCoreThreadCount()
     {
+        mavenLauncher.sysProp( "perCoreThreadCount", false );
+        return this;
+    }
 
+    public SurefireLauncher parallel( String parallel )
+    {
         mavenLauncher.sysProp( "parallel", parallel );
         return this;
     }
 
-
     public SurefireLauncher parallelSuites()
     {
         return parallel( "suites" );
@@ -336,6 +340,66 @@ public class SurefireLauncher
         return parallel( "methods" );
     }
 
+    public SurefireLauncher parallelBoth()
+    {
+        return parallel( "both" );
+    }
+
+    public SurefireLauncher parallelSuitesAndClasses()
+    {
+        return parallel( "suitesAndClasses" );
+    }
+
+    public SurefireLauncher parallelSuitesAndMethods()
+    {
+        return parallel( "suitesAndMethods" );
+    }
+
+    public SurefireLauncher parallelClassesAndMethods()
+    {
+        return parallel( "classesAndMethods" );
+    }
+
+    public SurefireLauncher parallelAll()
+    {
+        return parallel( "all" );
+    }
+
+    public SurefireLauncher useUnlimitedThreads()
+    {
+        mavenLauncher.sysProp( "useUnlimitedThreads", true );
+        return this;
+    }
+
+    public SurefireLauncher threadCountSuites( int count )
+    {
+        mavenLauncher.sysProp( "threadCountSuites", count );
+        return this;
+    }
+
+    public SurefireLauncher threadCountClasses( int count )
+    {
+        mavenLauncher.sysProp( "threadCountClasses", count );
+        return this;
+    }
+
+    public SurefireLauncher threadCountMethods( int count )
+    {
+        mavenLauncher.sysProp( "threadCountMethods", count );
+        return this;
+    }
+
+    public SurefireLauncher parallelTestsTimeoutInSeconds( double timeout )
+    {
+        mavenLauncher.sysProp( "surefire.parallel.timeout", timeout );
+        return this;
+    }
+
+    public SurefireLauncher parallelTestsTimeoutForcedInSeconds( double timeout )
+    {
+        mavenLauncher.sysProp( "surefire.parallel.forcedTimeout", timeout );
+        return this;
+    }
 
     public SurefireLauncher sysProp( String variable, String value )
     {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/resources/junit47-parallel/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/junit47-parallel/pom.xml b/surefire-integration-tests/src/test/resources/junit47-parallel/pom.xml
new file mode 100644
index 0000000..d8de300
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/junit47-parallel/pom.xml
@@ -0,0 +1,33 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.maven.plugins.surefire</groupId>
+  <artifactId>junit47-parallel</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <name>junit47-parallel</name>
+  <url>http://maven.apache.org</url>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.8.1</version>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.5</source>
+          <target>1.5</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>${surefire.version}</version>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Suite1Test.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Suite1Test.java b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Suite1Test.java
new file mode 100644
index 0000000..99419fe
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Suite1Test.java
@@ -0,0 +1,39 @@
+package surefireparallel;
+
+/*
+ * 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.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * @author Tibor Digana (tibor17)
+ * @since 2.16
+ */
+@RunWith( Suite.class )
+@Suite.SuiteClasses(
+    {
+        Waiting1Test.class,
+        Waiting2Test.class,
+        Waiting3Test.class,
+        Waiting4Test.class
+    })
+public class Suite1Test
+{
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Suite2Test.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Suite2Test.java b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Suite2Test.java
new file mode 100644
index 0000000..32814ff
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Suite2Test.java
@@ -0,0 +1,39 @@
+package surefireparallel;
+
+/*
+ * 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.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * @author Tibor Digana (tibor17)
+ * @since 2.16
+ */
+@RunWith( Suite.class )
+@Suite.SuiteClasses(
+    {
+        Waiting5Test.class,
+        Waiting6Test.class,
+        Waiting7Test.class,
+        Waiting8Test.class
+    })
+public class Suite2Test
+{
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/TestClass.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/TestClass.java b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/TestClass.java
new file mode 100644
index 0000000..3b1f842
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/TestClass.java
@@ -0,0 +1,53 @@
+package surefireparallel;
+
+/*
+ * 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.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runners.BlockJUnit4ClassRunner;
+
+/**
+ * @author Tibor Digana (tibor17)
+ * @since 2.16
+ */
+public class TestClass
+{
+    @Test
+    public void a()
+        throws InterruptedException
+    {
+        Thread.sleep( 5000L );
+    }
+
+    @Test
+    public void b()
+        throws InterruptedException
+    {
+        Thread.sleep( 5000L );
+    }
+
+    @Test
+    public void c()
+        throws InterruptedException
+    {
+        Thread.sleep( 5000L );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting1Test.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting1Test.java b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting1Test.java
new file mode 100644
index 0000000..1d58841
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting1Test.java
@@ -0,0 +1,50 @@
+package surefireparallel;
+
+/*
+ * 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.junit.Test;
+
+/**
+ * @author Tibor Digana (tibor17)
+ * @since 2.16
+ */
+public class Waiting1Test
+{
+    @Test
+    public void a()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void b()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void c()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting2Test.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting2Test.java b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting2Test.java
new file mode 100644
index 0000000..55da772
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting2Test.java
@@ -0,0 +1,50 @@
+package surefireparallel;
+
+/*
+ * 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.junit.Test;
+
+/**
+ * @author Tibor Digana (tibor17)
+ * @since 2.16
+ */
+public class Waiting2Test
+{
+    @Test
+    public void a()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void b()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void c()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting3Test.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting3Test.java b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting3Test.java
new file mode 100644
index 0000000..5098fd4
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting3Test.java
@@ -0,0 +1,50 @@
+package surefireparallel;
+
+/*
+ * 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.junit.Test;
+
+/**
+ * @author Tibor Digana (tibor17)
+ * @since 2.16
+ */
+public class Waiting3Test
+{
+    @Test
+    public void a()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void b()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void c()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting4Test.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting4Test.java b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting4Test.java
new file mode 100644
index 0000000..8418448
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting4Test.java
@@ -0,0 +1,50 @@
+package surefireparallel;
+
+/*
+ * 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.junit.Test;
+
+/**
+ * @author Tibor Digana (tibor17)
+ * @since 2.16
+ */
+public class Waiting4Test
+{
+    @Test
+    public void a()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void b()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void c()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting5Test.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting5Test.java b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting5Test.java
new file mode 100644
index 0000000..2b99160
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting5Test.java
@@ -0,0 +1,50 @@
+package surefireparallel;
+
+/*
+ * 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.junit.Test;
+
+/**
+ * @author Tibor Digana (tibor17)
+ * @since 2.16
+ */
+public class Waiting5Test
+{
+    @Test
+    public void a()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void b()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void c()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting6Test.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting6Test.java b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting6Test.java
new file mode 100644
index 0000000..9ae9c01
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting6Test.java
@@ -0,0 +1,50 @@
+package surefireparallel;
+
+/*
+ * 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.junit.Test;
+
+/**
+ * @author Tibor Digana (tibor17)
+ * @since 2.16
+ */
+public class Waiting6Test
+{
+    @Test
+    public void a()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void b()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void c()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting7Test.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting7Test.java b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting7Test.java
new file mode 100644
index 0000000..ca00a6a
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting7Test.java
@@ -0,0 +1,50 @@
+package surefireparallel;
+
+/*
+ * 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.junit.Test;
+
+/**
+ * @author Tibor Digana (tibor17)
+ * @since 2.16
+ */
+public class Waiting7Test
+{
+    @Test
+    public void a()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void b()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void c()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting8Test.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting8Test.java b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting8Test.java
new file mode 100644
index 0000000..96d1c66
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/junit47-parallel/src/test/java/surefireparallel/Waiting8Test.java
@@ -0,0 +1,50 @@
+package surefireparallel;
+
+/*
+ * 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.junit.Test;
+
+/**
+ * @author Tibor Digana (tibor17)
+ * @since 2.16
+ */
+public class Waiting8Test
+{
+    @Test
+    public void a()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void b()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+
+    @Test
+    public void c()
+        throws InterruptedException
+    {
+        Thread.sleep( 300L );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/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 157ed58..8421751 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
@@ -22,6 +22,7 @@ package org.apache.maven.surefire.junitcore;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Properties;
+
 import org.apache.maven.surefire.booter.ProviderParameterNames;
 
 /**
@@ -29,24 +30,6 @@ import org.apache.maven.surefire.booter.ProviderParameterNames;
  */
 class JUnitCoreParameters
 {
-    private final String parallel;
-
-    private final Boolean perCoreThreadCount;
-
-    private final int threadCount;
-
-    private final int threadCountSuites;
-
-    private final int threadCountClasses;
-
-    private final int threadCountMethods;
-
-    private final int parallelTestsTimeoutInSeconds;
-
-    private final int parallelTestsTimeoutForcedInSeconds;
-
-    private final Boolean useUnlimitedThreads;
-
     public static final String PARALLEL_KEY = ProviderParameterNames.PARALLEL_PROP;
 
     public static final String PERCORETHREADCOUNT_KEY = "perCoreThreadCount";
@@ -65,6 +48,24 @@ class JUnitCoreParameters
 
     public static final String PARALLEL_TIMEOUTFORCED_KEY = ProviderParameterNames.PARALLEL_TIMEOUTFORCED_PROP;
 
+    private final String parallel;
+
+    private final Boolean perCoreThreadCount;
+
+    private final int threadCount;
+
+    private final int threadCountSuites;
+
+    private final int threadCountClasses;
+
+    private final int threadCountMethods;
+
+    private final double parallelTestsTimeoutInSeconds;
+
+    private final double parallelTestsTimeoutForcedInSeconds;
+
+    private final Boolean useUnlimitedThreads;
+
     public JUnitCoreParameters( Properties properties )
     {
         parallel = properties.getProperty( PARALLEL_KEY, "none" ).toLowerCase();
@@ -74,8 +75,10 @@ class JUnitCoreParameters
         threadCountClasses = Integer.valueOf( properties.getProperty( THREADCOUNTCLASSES_KEY, "0" ) );
         threadCountSuites = Integer.valueOf( properties.getProperty( THREADCOUNTSUITES_KEY, "0" ) );
         useUnlimitedThreads = Boolean.valueOf( properties.getProperty( USEUNLIMITEDTHREADS_KEY, "false" ) );
-        parallelTestsTimeoutInSeconds = Integer.valueOf( properties.getProperty( PARALLEL_TIMEOUT_KEY, "0" ) );
-        parallelTestsTimeoutForcedInSeconds = Integer.valueOf( properties.getProperty( PARALLEL_TIMEOUTFORCED_KEY, "0" ) );
+        parallelTestsTimeoutInSeconds =
+            Math.max( Double.valueOf( properties.getProperty( PARALLEL_TIMEOUT_KEY, "0" ) ), 0 );
+        parallelTestsTimeoutForcedInSeconds =
+            Math.max( Double.valueOf( properties.getProperty( PARALLEL_TIMEOUTFORCED_KEY, "0" ) ), 0 );
     }
 
     private static Collection<String> lowerCase( String... elements )
@@ -95,14 +98,14 @@ class JUnitCoreParameters
 
     public boolean isParallelMethod()
     {
-        return isAllParallel()
-                || lowerCase( "both", "methods", "suitesAndMethods", "classesAndMethods" ).contains( parallel );
+        return isAllParallel() || lowerCase( "both", "methods", "suitesAndMethods", "classesAndMethods" ).contains(
+            parallel );
     }
 
     public boolean isParallelClasses()
     {
-        return isAllParallel()
-                || lowerCase( "both", "classes", "suitesAndClasses", "classesAndMethods" ).contains( parallel );
+        return isAllParallel() || lowerCase( "both", "classes", "suitesAndClasses", "classesAndMethods" ).contains(
+            parallel );
     }
 
     public boolean isParallelSuites()
@@ -149,12 +152,12 @@ class JUnitCoreParameters
         return useUnlimitedThreads;
     }
 
-    public int getParallelTestsTimeoutInSeconds()
+    public double getParallelTestsTimeoutInSeconds()
     {
         return parallelTestsTimeoutInSeconds;
     }
 
-    public int getParallelTestsTimeoutForcedInSeconds()
+    public double getParallelTestsTimeoutForcedInSeconds()
     {
         return parallelTestsTimeoutForcedInSeconds;
     }
@@ -174,6 +177,6 @@ class JUnitCoreParameters
     {
         return "parallel='" + parallel + '\'' + ", perCoreThreadCount=" + perCoreThreadCount + ", threadCount="
             + threadCount + ", useUnlimitedThreads=" + useUnlimitedThreads + ", threadCountSuites=" + threadCountSuites
-                + ", threadCountClasses=" + threadCountClasses + ", threadCountMethods=" + threadCountMethods;
+            + ", threadCountClasses=" + threadCountClasses + ", threadCountMethods=" + threadCountMethods;
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/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 45cf34c..e124f6e 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,12 +19,7 @@ package org.apache.maven.surefire.junitcore;
  * under the License.
  */
 
-import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
-import java.util.TreeSet;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
 
 import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
 import org.apache.maven.surefire.junitcore.pc.ParallelComputer;
@@ -32,7 +27,6 @@ import org.apache.maven.surefire.testset.TestSetFailedException;
 import org.apache.maven.surefire.util.TestsToRun;
 
 import org.junit.runner.Computer;
-import org.junit.runner.Description;
 import org.junit.runner.JUnitCore;
 import org.junit.runner.Request;
 import org.junit.runner.Result;
@@ -49,51 +43,28 @@ import org.junit.runner.notification.RunListener;
 
 class JUnitCoreWrapper
 {
-    private static class FilteringRequest
-        extends Request
-    {
-        private Runner filteredRunner;
-
-        public FilteringRequest( Request req, Filter filter )
-        {
-            try
-            {
-                Runner runner = req.getRunner();
-                filter.apply( runner );
-                filteredRunner = runner;
-            }
-            catch ( NoTestsRemainException e )
-            {
-                filteredRunner = null;
-            }
-        }
-
-        @Override
-        public Runner getRunner()
-        {
-            return filteredRunner;
-        }
-    }
-
     public static void execute( TestsToRun testsToRun, JUnitCoreParameters jUnitCoreParameters,
                                 List<RunListener> listeners, Filter filter )
         throws TestSetFailedException
     {
-        ComputerWrapper computerWrapper = createComputer( jUnitCoreParameters );
+        Computer computer = createComputer( jUnitCoreParameters );
         JUnitCore junitCore = createJUnitCore( listeners );
         if ( testsToRun.allowEagerReading() )
         {
-            executeEager( testsToRun, filter, computerWrapper.getComputer(), junitCore );
+            executeEager( testsToRun, filter, computer, junitCore );
         }
         else
         {
-            exeuteLazy( testsToRun, filter, computerWrapper.getComputer(), junitCore );
+            exeuteLazy( testsToRun, filter, computer, junitCore );
         }
 
-        String timeoutMessage = computerWrapper.describeElapsedTimeout();
-        if ( timeoutMessage.length() != 0 )
+        if ( computer instanceof ParallelComputer )
         {
-            throw new TestSetFailedException( timeoutMessage );
+            String timeoutMessage = ( (ParallelComputer) computer ).describeElapsedTimeout();
+            if ( timeoutMessage.length() != 0 )
+            {
+                throw new TestSetFailedException( timeoutMessage );
+            }
         }
     }
 
@@ -107,15 +78,15 @@ class JUnitCoreWrapper
         return junitCore;
     }
 
-    private static void executeEager(TestsToRun testsToRun, Filter filter, Computer computer, JUnitCore junitCore)
-            throws TestSetFailedException 
+    private static void executeEager( TestsToRun testsToRun, Filter filter, Computer computer, JUnitCore junitCore )
+        throws TestSetFailedException
     {
         Class[] tests = testsToRun.getLocatedClasses();
         createRequestAndRun( filter, computer, junitCore, tests );
     }
 
-    private static void exeuteLazy(TestsToRun testsToRun, Filter filter, Computer computer, JUnitCore junitCore)
-            throws TestSetFailedException
+    private static void exeuteLazy( TestsToRun testsToRun, Filter filter, Computer computer, JUnitCore junitCore )
+        throws TestSetFailedException
     {
         // in order to support LazyTestsToRun, the iterator must be used
         for ( Class clazz : testsToRun )
@@ -124,8 +95,9 @@ class JUnitCoreWrapper
         }
     }
 
-    private static void createRequestAndRun( Filter filter, Computer computer, JUnitCore junitCore, Class<?>... classesToRun )
-            throws TestSetFailedException
+    private static void createRequestAndRun( Filter filter, Computer computer, JUnitCore junitCore,
+                                             Class<?>... classesToRun )
+        throws TestSetFailedException
     {
         Request req = Request.classes( computer, classesToRun );
         if ( filter != null )
@@ -142,110 +114,37 @@ class JUnitCoreWrapper
         JUnit4RunListener.rethrowAnyTestMechanismFailures( run );
     }
 
-    private static ComputerWrapper createComputer( JUnitCoreParameters parameters )
+    private static Computer createComputer( JUnitCoreParameters parameters )
         throws TestSetFailedException
     {
-        return parameters.isNoThreading() ? new ComputerWrapper( Computer.serial() ) : createParallelComputer( parameters );
+        return parameters.isNoThreading()
+            ? Computer.serial()
+            : ParallelComputerFactory.createParallelComputer( parameters );
     }
 
-    private static ComputerWrapper createParallelComputer( JUnitCoreParameters parameters )
-            throws TestSetFailedException
-    {
-        ParallelComputer pc = ParallelComputerFactory.createParallelComputer( parameters );
-
-        int timeout = parameters.getParallelTestsTimeoutInSeconds();
-
-        int timeoutForced = parameters.getParallelTestsTimeoutForcedInSeconds();
-
-        Future<Collection<Description>> testsBeforeShutdown =
-                timeout > 0 ? pc.scheduleShutdown( timeout, TimeUnit.SECONDS ) : null;
-
-        Future<Collection<Description>> testsBeforeForcedShutdown =
-                timeoutForced > 0 ? pc.scheduleForcedShutdown( timeoutForced, TimeUnit.SECONDS ) : null;
-
-        return new ComputerWrapper( pc, timeout, testsBeforeShutdown, timeoutForced, testsBeforeForcedShutdown );
-    }
-
-    private static class ComputerWrapper
+    private static class FilteringRequest
+        extends Request
     {
-        private final Computer computer;
-        private final int timeout;
-        private final int timeoutForced;
-        private final Future<Collection<Description>> testsBeforeShutdown;
-        private final Future<Collection<Description>> testsBeforeForcedShutdown;
-
-        ComputerWrapper( Computer computer )
-        {
-            this( computer, 0, null, 0, null );
-        }
-
-        ComputerWrapper( Computer computer,
-                         int timeout, Future<Collection<Description>> testsBeforeShutdown,
-                         int timeoutForced, Future<Collection<Description>> testsBeforeForcedShutdown )
-        {
-            this.computer = computer;
-            this.timeout = timeout;
-            this.testsBeforeShutdown = testsBeforeShutdown;
-            this.timeoutForced = timeoutForced;
-            this.testsBeforeForcedShutdown = testsBeforeForcedShutdown;
-        }
-
-        Computer getComputer()
-        {
-            return computer;
-        }
+        private Runner filteredRunner;
 
-        String describeElapsedTimeout() throws TestSetFailedException
+        public FilteringRequest( Request req, Filter filter )
         {
-            TreeSet<String> executedTests = new TreeSet<String>();
-            if ( timeout > 0 )
-            {
-                executedTests.addAll( printShutdownHook( testsBeforeShutdown ) );
-            }
-
-            if ( timeoutForced > 0 )
+            try
             {
-                executedTests.addAll( printShutdownHook( testsBeforeForcedShutdown ) );
+                Runner runner = req.getRunner();
+                filter.apply( runner );
+                filteredRunner = runner;
             }
-
-            StringBuilder msg = new StringBuilder();
-            if ( !executedTests.isEmpty() )
+            catch ( NoTestsRemainException e )
             {
-                msg.append( "The test run has finished abruptly after timeout of " );
-                msg.append( Math.min( timeout, timeoutForced ) );
-                msg.append( " seconds.\n" );
-                msg.append( "These tests were executed in prior of the shutdown operation:\n" );
-                for ( String executedTest : executedTests )
-                {
-                    msg.append( executedTest ).append( "\n" );
-                }
+                filteredRunner = null;
             }
-            return msg.toString();
         }
 
-        static Collection<String> printShutdownHook( Future<Collection<Description>> future )
-                throws TestSetFailedException
+        @Override
+        public Runner getRunner()
         {
-            if ( !future.isCancelled() && future.isDone() )
-            {
-                try
-                {
-                    TreeSet<String> executedTests = new TreeSet<String>();
-                    for ( Description executedTest : future.get() )
-                    {
-                        if ( executedTest != null && executedTest.getDisplayName() != null )
-                        {
-                            executedTests.add( executedTest.getDisplayName() );
-                        }
-                    }
-                    return executedTests;
-                }
-                catch ( Exception e )
-                {
-                    throw new TestSetFailedException( e );
-                }
-            }
-            return Collections.emptySet();
+            return filteredRunner;
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/a9d511a0/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/NonConcurrentRunListener.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/NonConcurrentRunListener.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/NonConcurrentRunListener.java
index dcf8615..db2ff05 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/NonConcurrentRunListener.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/NonConcurrentRunListener.java
@@ -76,11 +76,11 @@ public class NonConcurrentRunListener
     public void testStarted( Description description )
         throws Exception
     {
-        finishLastTestSetIfNeccessary( description );
+        finishLastTestSetIfNecessary( description );
         super.testStarted( description );
     }
 
-    private void finishLastTestSetIfNeccessary( Description description )
+    private void finishLastTestSetIfNecessary( Description description )
     {
         if ( describesNewTestSet( description ) )
         {
@@ -125,7 +125,7 @@ public class NonConcurrentRunListener
     public void testIgnored( Description description )
         throws Exception
     {
-        finishLastTestSetIfNeccessary( description );
+        finishLastTestSetIfNecessary( description );
 
         super.testIgnored( description );
         this.lastFinishedDescription = description;