Author: krosenvold
Date: Thu Dec 22 21:55:05 2011
New Revision: 1222474
URL: http://svn.apache.org/viewvc?rev=1222474&view=rev
Log:
[SUREFIRE-799] Allow test parallelisation when forkMode=always
Patch by nkeyval, applied with review changes from me.
Added:
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java
(with props)
Modified:
maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
maven/surefire/trunk/maven-surefire-common/pom.xml
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/pom.xml
Modified:
maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
URL:
http://svn.apache.org/viewvc/maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java?rev=1222474&r1=1222473&r2=1222474&view=diff
==============================================================================
---
maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
(original)
+++
maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
Thu Dec 22 21:55:05 2011
@@ -350,8 +350,8 @@ public class IntegrationTestMojo
private Boolean failIfNoTests;
/**
- * Option to specify the forking mode. Can be "never", "once" or "always".
"none" and "pertest" are also accepted
- * for backwards compatibility. "always" forks for each test-class.
+ * Option to specify the forking mode. Can be "never", "once", "always" or
"perthread". "none" and "pertest" are also accepted
+ * for backwards compatibility. "always" forks for each test-class.
"perthread" will create "threadCount" parallel forks.
*
* @parameter expression="${forkMode}" default-value="once"
* @since 2.1
@@ -472,8 +472,9 @@ public class IntegrationTestMojo
private String testNGArtifactName;
/**
- * (TestNG/JUnit 4.7 provider only) The attribute thread-count allows you
to specify how many threads should be
- * allocated for this execution. Only makes sense to use in conjunction
with the <code>parallel</code> parameter.
+ * (forkMode=perthread or TestNG/JUnit 4.7 provider) The attribute
thread-count allows you to specify how many threads should be
+ * allocated for this execution. Only makes sense to use in conjunction
with the <code>parallel</code> parameter. (forkMode=perthread
+ * does not support/require the <code>parallel</code> parameter)
*
* @parameter expression="${threadCount}"
* @since 2.2
Modified: maven/surefire/trunk/maven-surefire-common/pom.xml
URL:
http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/pom.xml?rev=1222474&r1=1222473&r2=1222474&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/pom.xml (original)
+++ maven/surefire/trunk/maven-surefire-common/pom.xml Thu Dec 22 21:55:05 2011
@@ -97,24 +97,4 @@
</plugin>
</plugins>
</build>
-
- <profiles>
- <!-- Force JDK 1.4 for this one, plugins can never be built on 1.3 -->
- <profile>
- <id>jdk1.3</id>
- <build>
- <pluginManagement>
- <plugins>
- <plugin>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <fork>false</fork>
- <compilerVersion>1.4</compilerVersion>
- </configuration>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
- </profile>
- </profiles>
</project>
Modified:
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
URL:
http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java?rev=1222474&r1=1222473&r2=1222474&view=diff
==============================================================================
---
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
(original)
+++
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
Thu Dec 22 21:55:05 2011
@@ -260,7 +260,8 @@ public abstract class AbstractSurefireMo
if ( this.getThreadCount() > 0 )
{
- getProperties().setProperty(
ProviderParameterNames.THREADCOUNT_PROP, Integer.toString(
this.getThreadCount() ) );
+ getProperties().setProperty(
ProviderParameterNames.THREADCOUNT_PROP,
+ Integer.toString(
this.getThreadCount() ) );
}
if ( this.getObjectFactory() != null )
{
@@ -317,7 +318,8 @@ public abstract class AbstractSurefireMo
}
if ( this.getThreadCount() > 0 )
{
- getProperties().setProperty(
ProviderParameterNames.THREADCOUNT_PROP, Integer.toString(
this.getThreadCount() ) );
+ getProperties().setProperty(
ProviderParameterNames.THREADCOUNT_PROP,
+ Integer.toString(
this.getThreadCount() ) );
}
getProperties().setProperty( "perCoreThreadCount", Boolean.toString(
getPerCoreThreadCount() ) );
getProperties().setProperty( "useUnlimitedThreads", Boolean.toString(
getUseUnlimitedThreads() ) );
@@ -727,6 +729,15 @@ public abstract class AbstractSurefireMo
setEnableAssertions( false );
}
}
+
+ if ( fork.getForkMode().equals( ForkConfiguration.FORK_PERTHREAD )
)
+ {
+ fork.setThreadCount( getThreadCount() );
+ }
+ else
+ {
+ fork.setThreadCount( 1 );
+ }
}
return fork;
}
Modified:
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
URL:
http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java?rev=1222474&r1=1222473&r2=1222474&view=diff
==============================================================================
---
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
(original)
+++
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
Thu Dec 22 21:55:05 2011
@@ -54,6 +54,10 @@ public class ForkConfiguration
public static final String FORK_NEVER = "never";
+ public static final String FORK_PERTHREAD = "perthread";
+
+ private int threadCount;
+
private final Classpath bootClasspathConfiguration;
private final String forkMode;
@@ -96,7 +100,8 @@ public class ForkConfiguration
{
return FORK_NEVER;
}
- else if ( forkMode.equals( FORK_NEVER ) || forkMode.equals( FORK_ONCE
) || forkMode.equals( FORK_ALWAYS ) )
+ else if ( forkMode.equals( FORK_NEVER ) || forkMode.equals( FORK_ONCE
) ||
+ forkMode.equals( FORK_ALWAYS ) || forkMode.equals( FORK_PERTHREAD
) )
{
return forkMode;
}
@@ -302,4 +307,14 @@ public class ForkConfiguration
{
return tempDirectory;
}
+
+ public int getThreadCount()
+ {
+ return threadCount;
+ }
+
+ public void setThreadCount( int threadCount )
+ {
+ this.threadCount = threadCount;
+ }
}
Modified:
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
URL:
http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java?rev=1222474&r1=1222473&r2=1222474&view=diff
==============================================================================
---
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
(original)
+++
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
Thu Dec 22 21:55:05 2011
@@ -21,8 +21,16 @@ package org.apache.maven.plugin.surefire
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.Properties;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
import org.apache.maven.plugin.surefire.CommonReflector;
import org.apache.maven.plugin.surefire.booterclient.output.ForkClient;
import
org.apache.maven.plugin.surefire.booterclient.output.ThreadedStreamConsumer;
@@ -72,6 +80,13 @@ public class ForkStarter
private final StartupReportConfiguration startupReportConfiguration;
+ private final FileReporterFactory fileReporterFactory;
+
+ private static volatile int systemPropertiesFileCounter = 0;
+
+ private static final Object lock = new Object();
+
+
public ForkStarter( ProviderConfiguration providerConfiguration,
StartupConfiguration startupConfiguration,
ForkConfiguration forkConfiguration, int
forkedProcessTimeoutInSeconds,
StartupReportConfiguration startupReportConfiguration )
@@ -81,28 +96,31 @@ public class ForkStarter
this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds;
this.startupConfiguration = startupConfiguration;
this.startupReportConfiguration = startupReportConfiguration;
+ fileReporterFactory = new FileReporterFactory(
startupReportConfiguration );
}
public RunResult run()
throws SurefireBooterForkException, SurefireExecutionException
{
final RunResult result;
-
final String requestedForkMode = forkConfiguration.getForkMode();
- final FileReporterFactory fileReporterFactory = new
FileReporterFactory( startupReportConfiguration );
try
{
- final ForkClient forkClient =
- new ForkClient( fileReporterFactory,
startupReportConfiguration.getTestVmSystemProperties() );
- final RunStatistics globalRunStatistics =
fileReporterFactory.getGlobalRunStatistics();
if ( ForkConfiguration.FORK_ONCE.equals( requestedForkMode ) )
{
- result = fork( null,
providerConfiguration.getProviderProperties(), forkClient, globalRunStatistics
);
+ final ForkClient forkClient =
+ new ForkClient( fileReporterFactory,
startupReportConfiguration.getTestVmSystemProperties() );
+ result = fork( null,
providerConfiguration.getProviderProperties(), forkClient,
+ fileReporterFactory.getGlobalRunStatistics() );
}
else if ( ForkConfiguration.FORK_ALWAYS.equals( requestedForkMode
) )
{
- result = runSuitesForkPerTestSet(
providerConfiguration.getProviderProperties(), forkClient,
- globalRunStatistics );
+ result = runSuitesForkPerTestSet(
providerConfiguration.getProviderProperties(), 1 );
+ }
+ else if ( ForkConfiguration.FORK_PERTHREAD.equals(
requestedForkMode ) )
+ {
+ result = runSuitesForkPerTestSet(
providerConfiguration.getProviderProperties(),
+
forkConfiguration.getThreadCount() );
}
else
{
@@ -116,24 +134,85 @@ public class ForkStarter
return result;
}
- private RunResult runSuitesForkPerTestSet( Properties properties,
ForkClient forkClient,
- RunStatistics
globalRunStatistics )
+ private RunResult runSuitesForkPerTestSet( final Properties properties,
int forkCount )
throws SurefireBooterForkException
{
- RunResult globalResult = new RunResult( 0, 0, 0, 0 );
- final Iterator suites = getSuitesIterator();
+ ArrayList<Future<RunResult>> results = new
ArrayList<Future<RunResult>>( 500 );
+ ExecutorService executorService = new ThreadPoolExecutor( forkCount,
forkCount, 60, TimeUnit.SECONDS,
+ new
ArrayBlockingQueue<Runnable>( 500 ) );
- while ( suites.hasNext() )
+ try
{
- Object testSet = suites.next();
- RunResult runResult = fork( testSet, properties, forkClient,
globalRunStatistics );
- globalResult = globalResult.aggregate( runResult );
+ // Ask to the executorService to run all tasks
+ RunResult globalResult = new RunResult( 0, 0, 0, 0 );
+ final Iterator suites = getSuitesIterator();
+ while ( suites.hasNext() )
+ {
+ final Object testSet = suites.next();
+ final ForkClient forkClient =
+ new ForkClient( fileReporterFactory,
startupReportConfiguration.getTestVmSystemProperties() );
+ Callable<RunResult> pf = new Callable<RunResult>()
+ {
+ public RunResult call()
+ throws Exception
+ {
+ return fork( testSet, properties, forkClient,
fileReporterFactory.getGlobalRunStatistics() );
+ }
+ };
+ results.add( executorService.submit( pf ) );
+
+ }
+
+ for ( Future<RunResult> result : results )
+ {
+ try
+ {
+ RunResult cur = result.get();
+ if ( cur != null )
+ {
+ globalResult = globalResult.aggregate( cur );
+ }
+ else
+ {
+ throw new SurefireBooterForkException( "No results for
" + result.toString() );
+ }
+ }
+ catch ( InterruptedException e )
+ {
+ throw new SurefireBooterForkException( "Interrupted", e );
+ }
+ catch ( ExecutionException e )
+ {
+ throw new SurefireBooterForkException(
"ExecutionException", e );
+ }
+ }
+ return globalResult;
+
+ }
+ finally
+ {
+ closeExecutor( executorService );
}
- return globalResult;
}
+ private void closeExecutor( ExecutorService executorService )
+ throws SurefireBooterForkException
+ {
+ executorService.shutdown();
+ try
+ {
+ // Should stop immediately, as we got all the results if we are
here
+ executorService.awaitTermination( 60 * 60, TimeUnit.SECONDS );
+ }
+ catch ( InterruptedException e )
+ {
+ throw new SurefireBooterForkException( "Interrupted", e );
+ }
+ }
+
+
private RunResult fork( Object testSet, Properties properties, ForkClient
forkClient,
RunStatistics globalRunStatistics )
throws SurefireBooterForkException
@@ -151,7 +230,9 @@ public class ForkStarter
{
systemProperties = SystemPropertyManager.writePropertiesFile(
forkConfiguration.getSystemProperties(),
forkConfiguration.getTempDirectory(),
-
"surefire", forkConfiguration.isDebug() );
+
"surefire_"
+
+ systemPropertiesFileCounter++,
+
forkConfiguration.isDebug() );
}
}
catch ( IOException e )
@@ -197,7 +278,7 @@ public class ForkStarter
if ( result != RunResult.SUCCESS )
{
- throw new SurefireBooterForkException( "Error occured in
starting fork, check output in log" );
+ throw new SurefireBooterForkException( "Error occurred in
starting fork, check output in log" );
}
threadedStreamConsumer.close();
forkClient.close();
@@ -241,5 +322,4 @@ public class ForkStarter
}
}
-
}
Modified:
maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
URL:
http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java?rev=1222474&r1=1222473&r2=1222474&view=diff
==============================================================================
---
maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
(original)
+++
maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
Thu Dec 22 21:55:05 2011
@@ -319,8 +319,8 @@ public class SurefirePlugin
private Boolean failIfNoTests;
/**
- * Option to specify the forking mode. Can be "never", "once" or "always".
"none" and "pertest" are also accepted
- * for backwards compatibility. "always" forks for each test-class.
+ * Option to specify the forking mode. Can be "never", "once", "always" or
"perthread". "none" and "pertest" are also accepted
+ * for backwards compatibility. "always" forks for each test-class.
"perthread" will create "threadCount" parallel forks.
*
* @parameter expression="${forkMode}" default-value="once"
* @since 2.1
@@ -442,8 +442,9 @@ public class SurefirePlugin
private String testNGArtifactName;
/**
- * (TestNG/JUnit 4.7 provider only) The attribute thread-count allows you
to specify how many threads should be
- * allocated for this execution. Only makes sense to use in conjunction
with the <code>parallel</code> parameter.
+ * (forkMode=perthread or TestNG/JUnit 4.7 provider) The attribute
thread-count allows you to specify how many threads should be
+ * allocated for this execution. Only makes sense to use in conjunction
with the <code>parallel</code> parameter. (forkMode=perthread
+ * does not support/require the <code>parallel</code> parameter)
*
* @parameter expression="${threadCount}"
* @since 2.2
Modified:
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java
URL:
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java?rev=1222474&r1=1222473&r2=1222474&view=diff
==============================================================================
---
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java
(original)
+++
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java
Thu Dec 22 21:55:05 2011
@@ -19,19 +19,18 @@ package org.apache.maven.surefire.its;
* under the License.
*/
-import org.apache.maven.it.VerificationException;
-import org.apache.maven.it.Verifier;
-import org.apache.maven.it.util.ResourceExtractor;
-import org.apache.maven.surefire.its.misc.HelperAssertions;
-
import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.List;
+import org.apache.maven.it.VerificationException;
+import org.apache.maven.it.Verifier;
+import org.apache.maven.it.util.ResourceExtractor;
+import org.apache.maven.surefire.its.misc.HelperAssertions;
/**
* Verifies the runOrder setting and its effect
- *
+ *
* @author Kristian Rosenvold
*/
public class RunOrderIT
@@ -45,7 +44,7 @@ public class RunOrderIT
private File testDir;
- private Verifier verifier;
+ protected Verifier verifier;
public void setUp()
throws IOException, VerificationException
@@ -111,10 +110,17 @@ public class RunOrderIT
HelperAssertions.assertTestSuiteResults( 3, 0, 0, 0, testDir );
}
- private void executeTestsWithRunOrder( String runOrder )
+
+ protected String getForkMode()
+ {
+ return "once";
+ }
+
+ protected void executeTestsWithRunOrder( String runOrder )
throws VerificationException
{
List<String> goals = getInitialGoals();
+ goals.add( "-DforkMode=" + getForkMode() );
goals.add( "-DrunOrder=" + runOrder );
goals.add( "test" );
executeGoals( verifier, goals );
@@ -129,7 +135,8 @@ public class RunOrderIT
}
}
- private boolean testnamesAppearInSpecificOrder( String[] testnames )
throws VerificationException
+ private boolean testnamesAppearInSpecificOrder( String[] testnames )
+ throws VerificationException
{
int i = 0;
for ( String line : getLog() )
Added:
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java
URL:
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java?rev=1222474&view=auto
==============================================================================
---
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java
(added)
+++
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java
Thu Dec 22 21:55:05 2011
@@ -0,0 +1,31 @@
+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.
+ */
+
+public class RunOrderParallelForksIT
+ extends RunOrderIT
+{
+
+ @Override
+ protected String getForkMode()
+ {
+ return "perthread";
+ }
+}
Propchange:
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/pom.xml
URL:
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/pom.xml?rev=1222474&r1=1222473&r2=1222474&view=diff
==============================================================================
---
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/pom.xml
(original)
+++
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/pom.xml
Thu Dec 22 21:55:05 2011
@@ -11,7 +11,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
- <version>4.8.1</version>
+ <version>4.10</version>
</dependency>
</dependencies>
@@ -34,7 +34,6 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<configuration>
- <forkMode>once</forkMode>
<runOrder>${runOrder}</runOrder>
<threadCount>2</threadCount>
<perCoreThreadCount>false</perCoreThreadCount>