Permalink
Browse files

[SUREFIRE-751] forkMode=onceperthread

  • Loading branch information...
agudian authored and krosenvold committed Nov 6, 2012
1 parent 0b27dc2 commit 9c6ce9be423219e88d6e9c777ba69eea5e831d0c
Showing with 722 additions and 139 deletions.
  1. +35 −10 maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
  2. +6 −2 ...surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
  3. +18 −7 ...urefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
  4. +145 −27 maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
  5. +7 −0 ...n/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/FlushReceiver.java
  6. +5 −0 ...in/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/FlushReceiverProvider.java
  7. +41 −0 .../java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/ProcessAwareCommandline.java
  8. +52 −0 ...java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStream.java
  9. +17 −0 ...urefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
  10. +44 −15 ...va/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
  11. +5 −5 ...ava/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
  12. +2 −2 ...ire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
  13. +1 −1 pom.xml
  14. +3 −0 surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java
  15. +135 −0 surefire-api/src/main/java/org/apache/maven/surefire/util/LazyTestsToRun.java
  16. +1 −0 surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java
  17. +4 −1 surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
  18. +14 −1 surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
  19. +10 −2 surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java
  20. +23 −1 surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/ForkModeIT.java
  21. +10 −0 surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/fixture/SurefireLauncher.java
  22. +1 −2 ...s/src/test/java/org/apache/maven/surefire/its/jiras/Surefire907PerThreadWithoutThreadCountIT.java
  23. +1 −0 surefire-integration-tests/src/test/resources/fork-mode-testng/pom.xml
  24. +5 −0 surefire-integration-tests/src/test/resources/fork-mode-testng/src/test/java/forkMode/Test1.java
  25. +1 −0 surefire-integration-tests/src/test/resources/fork-mode/pom.xml
  26. +6 −1 surefire-integration-tests/src/test/resources/fork-mode/src/test/java/forkMode/Test1.java
  27. +11 −1 surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java
  28. +14 −4 ...fire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
  29. +11 −6 ...oviders/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
  30. +14 −9 ...roviders/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java
  31. +69 −41 ...ders/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
  32. +11 −1 ...fire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
@@ -29,6 +29,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
@@ -327,8 +328,11 @@
protected Boolean failIfNoTests;
/**
- * 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.
+ * Option to specify the forking mode. Can be "never", "once", "always", "perthread" or "onceperthread". "none" and "pertest" are also accepted
+ * for backwards compatibility. "always" forks for each test-class. "perthread" will create "threadCount" parallel forks, each executing one test-class.
+ * "onceperthread" will fork "threadCount" processes that each execute a 1/"threadCount" of all test-classes.<br/>
+ * The system properties and the "argLine" of the forked processes may contain the place holder string <code>${surefire.threadNumber}</code>,
+ * which is replaced with a fixed number for each thread, ranging from 1 to "threadCount".
*
* @since 2.1
*/
@@ -429,9 +433,9 @@
protected String testNGArtifactName;
/**
- * (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)
+ * (forkMode=perthread, forkmode=onceperthread 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 or with forkMode=perthread
+ * or forkmode=onceperthread.
*
* @since 2.2
*/
@@ -572,6 +576,12 @@
private Artifact surefireBooterArtifact;
private Toolchain toolchain;
+
+ /**
+ * The placeholder that is replaced by the executing thread's running number. The thread number
+ * range starts with 1
+ */
+ public static final String THREAD_NUMBER_PLACEHOLDER = "${surefire.threadNumber}";
protected abstract String getPluginName();
@@ -741,7 +751,8 @@ private RunResult executeProvider( ProviderInfo provider, DefaultScanResult scan
final RunResult result;
if ( isForkModeNever() )
{
- effectiveProperties.copyToSystemProperties();
+ createCopyAndReplaceThreadNumPlaceholder(effectiveProperties, 1).copyToSystemProperties();
+
InPluginVMSurefireStarter surefireStarter =
createInprocessStarter( provider, classLoaderConfiguration, runOrderParameters );
result = surefireStarter.runSuitesInProcess( scanResult );
@@ -771,6 +782,18 @@ private RunResult executeProvider( ProviderInfo provider, DefaultScanResult scan
return result;
}
+
+ public static SurefireProperties createCopyAndReplaceThreadNumPlaceholder(SurefireProperties effectiveSystemProperties, int threadNumber) {
+ SurefireProperties filteredProperties = new SurefireProperties(effectiveSystemProperties);
+ String threadNumberString = String.valueOf(threadNumber);
+ for (Entry<Object,Object> entry : effectiveSystemProperties.entrySet()) {
+ if (entry.getValue() instanceof String) {
+ filteredProperties.put(entry.getKey(), ((String)entry.getValue()).replace(THREAD_NUMBER_PLACEHOLDER, threadNumberString));
+ }
+ }
+ return filteredProperties;
+ }
+
protected void cleanupForkConfiguration( ForkConfiguration forkConfiguration )
{
if ( !getLog().isDebugEnabled() && forkConfiguration != null )
@@ -1002,7 +1025,7 @@ private ProviderConfiguration createProviderConfiguration( RunOrderParameters ru
return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, failIfNoTests,
reporterConfiguration, testNg, testSuiteDefinition, providerProperties,
- null );
+ null, false );
}
public String getStatisticsFileName( String configurationHash )
@@ -1344,7 +1367,8 @@ protected ForkConfiguration getForkConfiguration()
private int getEffectiveForkCount()
{
- return ( ForkConfiguration.FORK_PERTHREAD.equals( getEffectiveForkMode() ) ) ? getThreadCount() : 1;
+ return ( ForkConfiguration.FORK_PERTHREAD.equals( getEffectiveForkMode() ) ||
+ ForkConfiguration.FORK_ONCE_PERTHREAD.equals( getEffectiveForkMode() ) ) ? getThreadCount() : 1;
}
private String getEffectiveDebugForkedProcess()
@@ -1728,9 +1752,10 @@ void ensureParallelRunningCompatibility()
void ensureThreadCountWithPerThread()
throws MojoFailureException
{
- if ( ForkConfiguration.FORK_PERTHREAD.equals( getEffectiveForkMode() ) && getThreadCount() < 1 )
+ if ( ( ForkConfiguration.FORK_PERTHREAD.equals( getEffectiveForkMode() ) ||
+ ForkConfiguration.FORK_ONCE_PERTHREAD.equals( getEffectiveForkMode() )) && getThreadCount() < 1 )
{
- throw new MojoFailureException( "Fork mode perthread requires a thread count" );
+ throw new MojoFailureException( "Fork modes perthread and onceperthread require a thread count" );
}
}
@@ -21,7 +21,9 @@
import java.io.File;
import java.io.IOException;
+import java.util.List;
import java.util.Properties;
+
import org.apache.maven.surefire.booter.BooterConstants;
import org.apache.maven.surefire.booter.ClassLoaderConfiguration;
import org.apache.maven.surefire.booter.KeyValueSource;
@@ -66,7 +68,7 @@ public BooterSerializer( ForkConfiguration forkConfiguration )
DOes not modify sourceProperties
*/
public File serialize(KeyValueSource sourceProperties, ProviderConfiguration booterConfiguration, StartupConfiguration providerConfiguration,
- Object testSet)
+ Object testSet, boolean readTestsFromInStream)
throws IOException
{
@@ -82,7 +84,9 @@ public File serialize(KeyValueSource sourceProperties, ProviderConfiguration boo
properties.setProperty( BooterConstants.TESTARTIFACT_CLASSIFIER, testNg.getClassifier() );
}
- properties.setProperty( BooterConstants.FORKTESTSET, getTypeEncoded( testSet ) );
+ properties.setProperty( BooterConstants.FORKTESTSET_PREFER_TESTS_FROM_IN_STREAM, Boolean.valueOf( readTestsFromInStream ) );
+ properties.setProperty( BooterConstants.FORKTESTSET, getTypeEncoded( testSet ) );
+
TestRequest testSuiteDefinition = booterConfiguration.getTestSuiteDefinition();
if ( testSuiteDefinition != null )
{
@@ -27,6 +27,9 @@
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
+
+import org.apache.maven.plugin.surefire.AbstractSurefireMojo;
+import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.ProcessAwareCommandline;
import org.apache.maven.plugin.surefire.util.Relocator;
import org.apache.maven.shared.utils.StringUtils;
import org.apache.maven.shared.utils.cli.Commandline;
@@ -52,6 +55,8 @@
public static final String FORK_NEVER = "never";
public static final String FORK_PERTHREAD = "perthread";
+
+ public static final String FORK_ONCE_PERTHREAD = "onceperthread";
private final int forkCount;
@@ -102,7 +107,8 @@ else if ( "none".equalsIgnoreCase( forkMode ) )
return FORK_NEVER;
}
else if ( forkMode.equals( FORK_NEVER ) || forkMode.equals( FORK_ONCE ) ||
- forkMode.equals( FORK_ALWAYS ) || forkMode.equals( FORK_PERTHREAD ) )
+ forkMode.equals( FORK_ALWAYS ) || forkMode.equals( FORK_PERTHREAD ) ||
+ forkMode.equals( FORK_ONCE_PERTHREAD ))
{
return forkMode;
}
@@ -117,27 +123,28 @@ else if ( forkMode.equals( FORK_NEVER ) || forkMode.equals( FORK_ONCE ) ||
* @param classPath cla the classpath arguments
* @param classpathConfiguration the classpath configuration
* @param shadefire true if running shadefire
+ * @param threadNumber the thread number, to be the replacement in the argLine
* @return A commandline
* @throws org.apache.maven.surefire.booter.SurefireBooterForkException
* when unable to perform the fork
*/
- public Commandline createCommandLine( List<String> classPath, ClassLoaderConfiguration classpathConfiguration,
- boolean shadefire )
+ public ProcessAwareCommandline createCommandLine( List<String> classPath, ClassLoaderConfiguration classpathConfiguration,
+ boolean shadefire, int threadNumber )
throws SurefireBooterForkException
{
- return createCommandLine( classPath, classpathConfiguration.isManifestOnlyJarRequestedAndUsable(), shadefire );
+ return createCommandLine( classPath, classpathConfiguration.isManifestOnlyJarRequestedAndUsable(), shadefire, threadNumber );
}
- public Commandline createCommandLine( List<String> classPath, boolean useJar, boolean shadefire )
+ public ProcessAwareCommandline createCommandLine( List<String> classPath, boolean useJar, boolean shadefire, int threadNumber )
throws SurefireBooterForkException
{
- Commandline cli = new Commandline();
+ ProcessAwareCommandline cli = new ProcessAwareCommandline();
cli.setExecutable( jvmExecutable );
if ( argLine != null )
{
- cli.createArg().setLine( stripNewLines( argLine ) );
+ cli.createArg().setLine( replaceThreadNumberPlaceholder(stripNewLines( argLine ), threadNumber) );
}
if ( environmentVariables != null )
@@ -186,6 +193,10 @@ public Commandline createCommandLine( List<String> classPath, boolean useJar, bo
return cli;
}
+ private String replaceThreadNumberPlaceholder(String argLine, int threadNumber) {
+ return argLine.replace(AbstractSurefireMojo.THREAD_NUMBER_PLACEHOLDER, String.valueOf(threadNumber));
+ }
+
/**
* Create a jar with just a manifest containing a Main-Class entry for BooterConfiguration and a Class-Path entry
* for all classpath elements.
Oops, something went wrong.

0 comments on commit 9c6ce9b

Please sign in to comment.