You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kr...@apache.org on 2011/11/22 22:43:28 UTC
svn commit: r1205186 [1/2] - in /maven/surefire/trunk: ./
maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/
maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/
maven-surefire-common/src/main/java/org/apache/maven/p...
Author: krosenvold
Date: Tue Nov 22 21:43:19 2011
New Revision: 1205186
URL: http://svn.apache.org/viewvc?rev=1205186&view=rev
Log:
[SUREFIRE-795] Added support for balancing tests across threads
Added:
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/StatisticsReporter.java (with props)
maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
- copied, changed from r1204953, maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/
maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMapTest.java (with props)
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/PrioritizedTest.java
- copied, changed from r1204953, maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/Priority.java (with props)
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatistics.java (with props)
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java (with props)
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionScheduler.java (with props)
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/RunOrderParametersAware.java (contents, props changed)
- copied, changed from r1204953, maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/testset/RunOrderParameters.java (with props)
maven/surefire/trunk/surefire-api/src/test/java/org/apache/maven/plugin/
maven/surefire/trunk/surefire-api/src/test/java/org/apache/maven/plugin/surefire/
maven/surefire/trunk/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/
maven/surefire/trunk/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionSchedulerTest.java (with props)
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/pom.xml (with props)
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/src/
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/src/test/
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/src/test/java/
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/src/test/java/runorder/
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/src/test/java/runorder/parallel/
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/src/test/java/runorder/parallel/Test1.java (with props)
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/src/test/java/runorder/parallel/Test2.java (with props)
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/src/test/java/runorder/parallel/Test3.java (with props)
Removed:
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java
Modified:
maven/surefire/trunk/.gitignore
maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
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/CommonReflector.java
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/FileReporterFactory.java
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/surefire/booter/StartupReportConfiguration.java
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/TestSetRunListener.java
maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/testset/DirectoryScannerParameters.java
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultRunOrderCalculator.java
maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/util/RunOrder.java
maven/surefire/trunk/surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderCalculatorTest.java
maven/surefire/trunk/surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderTest.java
maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java
maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java
maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
maven/surefire/trunk/surefire-booter/src/test/java/org/apache/maven/surefire/booter/Foo.java
maven/surefire/trunk/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java
maven/surefire/trunk/surefire-integration-tests/pom.xml
maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestMethod.java
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
Modified: maven/surefire/trunk/.gitignore
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/.gitignore?rev=1205186&r1=1205185&r2=1205186&view=diff
==============================================================================
--- maven/surefire/trunk/.gitignore (original)
+++ maven/surefire/trunk/.gitignore Tue Nov 22 21:43:19 2011
@@ -9,4 +9,4 @@ build
.project
.settings
.idea
-
+.surefire-*
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=1205186&r1=1205185&r2=1205186&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 Tue Nov 22 21:43:19 2011
@@ -29,7 +29,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
-
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
@@ -629,11 +628,21 @@ public class IntegrationTestMojo
/**
* Defines the order the tests will be run in. Supported values are "alphabetical", "reversealphabetical", "random",
- * "hourly" (alphabetical on even hours, reverse alphabetical on odd hours) and "filesystem".
+ * "hourly" (alphabetical on even hours, reverse alphabetical on odd hours), "failedfirst", "balanced" and "filesystem".
* <p/>
* <p/>
* Odd/Even for hourly is determined at the time the of scanning the classpath, meaning it could change during a
* multi-module build.
+ * <p/>
+ * Failed first will run tests that failed on previous run first, as well as new tests.
+ * <p/>
+ * Balanced is only relevant with parallel=classes, and will try to optimize the run-order of the tests to
+ * make all tests complete at the same time, reducing the overall execution time.
+ * <p/>
+ * Note that the statistics are stored in a file named .surefire-XXXXXXXXX beside pom.xml, and should not
+ * be checked into version control. The "XXXXX" is the SHA1 checksum of the entire surefire configuration,
+ * so different configurations will have different statistics files, meaning if you change any config
+ * settings you will re-run once before new statistics data can be established.
*
* @parameter default-value="filesystem"
* @since 2.7
@@ -722,7 +731,7 @@ public class IntegrationTestMojo
protected String[] getDefaultIncludes()
{
- return new String[]{"**/IT*.java", "**/*IT.java", "**/*ITCase.java"};
+ return new String[]{ "**/IT*.java", "**/*IT.java", "**/*ITCase.java" };
}
public boolean isSkipTests()
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=1205186&r1=1205185&r2=1205186&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 Tue Nov 22 21:43:19 2011
@@ -61,6 +61,7 @@ import org.apache.maven.surefire.booter.
import org.apache.maven.surefire.report.ReporterConfiguration;
import org.apache.maven.surefire.suite.RunResult;
import org.apache.maven.surefire.testset.DirectoryScannerParameters;
+import org.apache.maven.surefire.testset.RunOrderParameters;
import org.apache.maven.surefire.testset.TestArtifactInfo;
import org.apache.maven.surefire.testset.TestRequest;
import org.apache.maven.surefire.util.NestedRuntimeException;
@@ -151,9 +152,9 @@ public abstract class AbstractSurefireMo
{
final Artifact junitDepArtifact = getJunitDepArtifact();
ProviderList wellKnownProviders = new ProviderList(
- new ProviderInfo[]{new TestNgProviderInfo( getTestNgArtifact() ),
+ new ProviderInfo[]{ new TestNgProviderInfo( getTestNgArtifact() ),
new JUnitCoreProviderInfo( getJunitArtifact(), junitDepArtifact ),
- new JUnit4ProviderInfo( getJunitArtifact(), junitDepArtifact ), new JUnit3ProviderInfo()},
+ new JUnit4ProviderInfo( getJunitArtifact(), junitDepArtifact ), new JUnit3ProviderInfo() },
new DynamicProviderInfo( null ) );
return wellKnownProviders.resolve( getLog() );
@@ -331,7 +332,20 @@ public abstract class AbstractSurefireMo
return ForkConfiguration.FORK_NEVER.equals( getForkMode() );
}
- protected ProviderConfiguration createProviderConfiguration()
+ private java.util.List getRunOrders()
+ {
+ String runOrderString = getRunOrder();
+ RunOrder[] runOrder = runOrderString == null ? RunOrder.DEFAULT : RunOrder.valueOfMulti( runOrderString );
+ return Arrays.asList( runOrder );
+ }
+
+ private boolean requiresRunHistory()
+ {
+ final List runOrders = getRunOrders();
+ return runOrders.contains( RunOrder.BALANCED ) || runOrders.contains( RunOrder.FAILEDFIRST );
+ }
+
+ protected ProviderConfiguration createProviderConfiguration( String configurationHash )
throws MojoExecutionException, MojoFailureException
{
ReporterConfiguration reporterConfiguration =
@@ -377,7 +391,7 @@ public abstract class AbstractSurefireMo
List excludes = getExcludeList();
directoryScannerParameters = new DirectoryScannerParameters( getTestClassesDirectory(), includes, excludes,
Boolean.valueOf( failIfNoTests ),
- getRunOrderObject() );
+ getRunOrder() );
}
Properties providerProperties = getProperties();
@@ -386,10 +400,26 @@ public abstract class AbstractSurefireMo
providerProperties = new Properties();
}
- return new ProviderConfiguration( directoryScannerParameters, failIfNoTests, reporterConfiguration, testNg,
- testSuiteDefinition, providerProperties, null );
+ RunOrderParameters runOrderParameters =
+ new RunOrderParameters( getRunOrder(), getStatisticsFileName( configurationHash ) );
+
+ return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, failIfNoTests,
+ reporterConfiguration, testNg, testSuiteDefinition, providerProperties,
+ null );
+ }
+
+ public File getStatisticsFile( String configurationHash )
+ {
+ return new File( getStatisticsFileName( configurationHash ) );
}
+ public String getStatisticsFileName( String configurationHash )
+ {
+ return getReportsDirectory().getParentFile().getParentFile() + File.separator + ".surefire-"
+ + configurationHash;
+ }
+
+
StartupConfiguration createStartupConfiguration( ForkConfiguration forkConfiguration, ProviderInfo provider,
ClassLoaderConfiguration classLoaderConfiguration )
throws MojoExecutionException, MojoFailureException
@@ -435,11 +465,12 @@ public abstract class AbstractSurefireMo
return (Artifact) getPluginArtifactMap().get( "org.apache.maven.surefire:maven-surefire-common" );
}
- private StartupReportConfiguration getStartupReportConfiguration()
+ private StartupReportConfiguration getStartupReportConfiguration( String configChecksum )
{
return new StartupReportConfiguration( isUseFile(), isPrintSummary(), getReportFormat(),
isRedirectTestOutputToFile(), isDisableXmlReport(),
- getReportsDirectory(), isTrimStackTrace(), getReportNameSuffix() );
+ getReportsDirectory(), isTrimStackTrace(), getReportNameSuffix(),
+ configChecksum, requiresRunHistory() );
}
void logClasspath( Classpath classpath, String descriptor )
@@ -490,7 +521,7 @@ public abstract class AbstractSurefireMo
// Have to wrap in an ArrayList as surefire expects an ArrayList instead of a List for some reason
if ( excludes == null || excludes.size() == 0 )
{
- excludes = new ArrayList( Arrays.asList( new String[]{"**/*$*"} ) );
+ excludes = new ArrayList( Arrays.asList( new String[]{ "**/*$*" } ) );
}
}
return excludes;
@@ -548,8 +579,8 @@ public abstract class AbstractSurefireMo
if ( !range.containsVersion( new DefaultArtifactVersion( artifact.getVersion() ) ) )
{
throw new MojoFailureException(
- "TestNG support requires version 4.7 or above. You have declared version " +
- artifact.getVersion() );
+ "TestNG support requires version 4.7 or above. You have declared version "
+ + artifact.getVersion() );
}
}
return artifact;
@@ -572,20 +603,23 @@ public abstract class AbstractSurefireMo
{
StartupConfiguration startupConfiguration =
createStartupConfiguration( forkConfiguration, provider, classLoaderConfiguration );
- StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration();
- ProviderConfiguration providerConfiguration = createProviderConfiguration();
+ String configChecksum = getConfigChecksum();
+ StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum );
+ ProviderConfiguration providerConfiguration = createProviderConfiguration( configChecksum );
return new ForkStarter( providerConfiguration, startupConfiguration, forkConfiguration,
getForkedProcessTimeoutInSeconds(), startupReportConfiguration );
}
- protected InPluginVMSurefireStarter createInprocessStarter( ProviderInfo provider, ForkConfiguration forkConfiguration,
- ClassLoaderConfiguration classLoaderConfiguration )
+ protected InPluginVMSurefireStarter createInprocessStarter( ProviderInfo provider,
+ ForkConfiguration forkConfiguration,
+ ClassLoaderConfiguration classLoaderConfiguration )
throws MojoExecutionException, MojoFailureException
{
StartupConfiguration startupConfiguration =
createStartupConfiguration( forkConfiguration, provider, classLoaderConfiguration );
- StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration();
- ProviderConfiguration providerConfiguration = createProviderConfiguration();
+ String configChecksum = getConfigChecksum();
+ StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum );
+ ProviderConfiguration providerConfiguration = createProviderConfiguration( configChecksum );
return new InPluginVMSurefireStarter( startupConfiguration, providerConfiguration, startupReportConfiguration );
}
@@ -655,8 +689,7 @@ public abstract class AbstractSurefireMo
fork.setDebugLine( getDebugForkedProcess() );
-
- if ( (getJvm() == null || "".equals( getJvm() )))
+ if ( ( getJvm() == null || "".equals( getJvm() ) ) )
{
// use the same JVM as the one used to run Maven (the "java.home" one)
setJvm( System.getProperty( "java.home" ) + File.separator + "bin" + File.separator + "java" );
@@ -802,7 +835,8 @@ public abstract class AbstractSurefireMo
protected ClassLoaderConfiguration getClassLoaderConfiguration( ForkConfiguration fork )
{
- return fork.isForking() ? new ClassLoaderConfiguration( isUseSystemClassLoader(), isUseManifestOnlyJar() )
+ return fork.isForking()
+ ? new ClassLoaderConfiguration( isUseSystemClassLoader(), isUseManifestOnlyJar() )
: new ClassLoaderConfiguration( false, false );
}
@@ -1078,8 +1112,8 @@ public abstract class AbstractSurefireMo
}
catch ( Exception e )
{
- String msg = "Build uses Maven 2.0.x, cannot propagate system properties" +
- " from command line to tests (cf. SUREFIRE-121)";
+ String msg = "Build uses Maven 2.0.x, cannot propagate system properties"
+ + " from command line to tests (cf. SUREFIRE-121)";
if ( getLog().isDebugEnabled() )
{
getLog().warn( msg, e );
@@ -1137,11 +1171,6 @@ public abstract class AbstractSurefireMo
}
}
- private RunOrder getRunOrderObject() {
- RunOrder runOrder = RunOrder.valueOf( getRunOrder() );
- return runOrder == null ? RunOrder.FILESYSTEM : runOrder;
- }
-
class TestNgProviderInfo
implements ProviderInfo
{
Modified: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java?rev=1205186&r1=1205185&r2=1205186&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java Tue Nov 22 21:43:19 2011
@@ -51,12 +51,11 @@ public class CommonReflector
public Object createReportingReporterFactory( StartupReportConfiguration startupReportConfiguration )
{
- Class[] args =
- new Class[]{ this.startupReportConfiguration };
+ Class[] args = new Class[]{ this.startupReportConfiguration };
Object src = createStartupReportConfiguration( startupReportConfiguration );
Object[] params = new Object[]{ src };
- return ReflectionUtils.instantiateObject( FileReporterFactory.class.getName(), args,
- params, surefireClassLoader );
+ return ReflectionUtils.instantiateObject( FileReporterFactory.class.getName(), args, params,
+ surefireClassLoader );
}
@@ -65,16 +64,17 @@ public class CommonReflector
Constructor constructor = ReflectionUtils.getConstructor( this.startupReportConfiguration,
new Class[]{ boolean.class, boolean.class,
String.class, boolean.class, boolean.class,
- File.class, boolean.class, String.class } );
+ File.class, boolean.class, String.class,
+ String.class, boolean.class } );
//noinspection BooleanConstructorCall
final Object[] params =
{ new Boolean( reporterConfiguration.isUseFile() ), new Boolean( reporterConfiguration.isPrintSummary() ),
reporterConfiguration.getReportFormat(),
new Boolean( reporterConfiguration.isRedirectTestOutputToFile() ),
- new Boolean( reporterConfiguration.isDisableXmlReport() ),
- reporterConfiguration.getReportsDirectory(),
- new Boolean( reporterConfiguration.isTrimStackTrace()),
- reporterConfiguration.getReportNameSuffix()};
+ new Boolean( reporterConfiguration.isDisableXmlReport() ), reporterConfiguration.getReportsDirectory(),
+ new Boolean( reporterConfiguration.isTrimStackTrace() ), reporterConfiguration.getReportNameSuffix(),
+ reporterConfiguration.getConfigurationHash(),
+ Boolean.valueOf( reporterConfiguration.isRequiresRunHistory() ) };
return ReflectionUtils.newInstance( constructor, params );
}
Modified: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java?rev=1205186&r1=1205185&r2=1205186&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java Tue Nov 22 21:43:19 2011
@@ -30,8 +30,10 @@ import org.apache.maven.surefire.booter.
import org.apache.maven.surefire.booter.SystemPropertyManager;
import org.apache.maven.surefire.report.ReporterConfiguration;
import org.apache.maven.surefire.testset.DirectoryScannerParameters;
+import org.apache.maven.surefire.testset.RunOrderParameters;
import org.apache.maven.surefire.testset.TestArtifactInfo;
import org.apache.maven.surefire.testset.TestRequest;
+import org.apache.maven.surefire.util.RunOrder;
/**
* Knows how to serialize and deserialize the booter configuration.
@@ -94,7 +96,13 @@ class BooterSerializer
properties.addList( directoryScannerParameters.getExcludes(), BooterConstants.EXCLUDES_PROPERTY_PREFIX );
properties.setProperty( BooterConstants.TEST_CLASSES_DIRECTORY,
directoryScannerParameters.getTestClassesDirectory() );
- properties.setProperty( BooterConstants.RUN_ORDER, directoryScannerParameters.getRunOrder().name() );
+ }
+
+ final RunOrderParameters runOrderParameters = booterConfiguration.getRunOrderParameters();
+ if ( runOrderParameters != null )
+ {
+ properties.setProperty( BooterConstants.RUN_ORDER, RunOrder.asString( runOrderParameters.getRunOrder() ) );
+ properties.setProperty( BooterConstants.RUN_STATISTICS_FILE, runOrderParameters.getRunStatisticsFile() );
}
ReporterConfiguration reporterConfiguration = booterConfiguration.getReporterConfiguration();
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=1205186&r1=1205185&r2=1205186&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 Tue Nov 22 21:43:19 2011
@@ -37,7 +37,6 @@ import org.apache.maven.surefire.booter.
import org.apache.maven.surefire.booter.SurefireExecutionException;
import org.apache.maven.surefire.booter.SystemPropertyManager;
import org.apache.maven.surefire.providerapi.SurefireProvider;
-import org.apache.maven.surefire.report.ReporterFactory;
import org.apache.maven.surefire.report.RunStatistics;
import org.apache.maven.surefire.suite.RunResult;
import org.codehaus.plexus.util.cli.CommandLineException;
@@ -93,13 +92,17 @@ public class ForkStarter
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(), fileReporterFactory );
+ result = fork( null, providerConfiguration.getProviderProperties(), forkClient, globalRunStatistics );
}
else if ( ForkConfiguration.FORK_ALWAYS.equals( requestedForkMode ) )
{
- result = runSuitesForkPerTestSet( fileReporterFactory, providerConfiguration.getProviderProperties() );
+ result = runSuitesForkPerTestSet( providerConfiguration.getProviderProperties(), forkClient,
+ globalRunStatistics );
}
else
{
@@ -113,7 +116,8 @@ public class ForkStarter
return result;
}
- private RunResult runSuitesForkPerTestSet( FileReporterFactory fileReporterFactory, Properties properties )
+ private RunResult runSuitesForkPerTestSet( Properties properties, ForkClient forkClient,
+ RunStatistics globalRunStatistics )
throws SurefireBooterForkException
{
RunResult globalResult = new RunResult( 0, 0, 0, 0 );
@@ -123,14 +127,15 @@ public class ForkStarter
while ( suites.hasNext() )
{
Object testSet = suites.next();
- RunResult runResult = fork( testSet, properties, fileReporterFactory );
+ RunResult runResult = fork( testSet, properties, forkClient, globalRunStatistics );
globalResult = globalResult.aggregate( runResult );
}
return globalResult;
}
- private RunResult fork( Object testSet, Properties properties, ReporterFactory testSetReporterFactory )
+ private RunResult fork( Object testSet, Properties properties, ForkClient forkClient,
+ RunStatistics globalRunStatistics )
throws SurefireBooterForkException
{
File surefireProperties;
@@ -172,9 +177,7 @@ public class ForkStarter
cli.createArg().setFile( systemProperties );
}
- ForkClient out =
- new ForkClient( testSetReporterFactory, startupReportConfiguration.getTestVmSystemProperties() );
- ThreadedStreamConsumer threadedStreamConsumer2 = new ThreadedStreamConsumer( out );
+ ThreadedStreamConsumer threadedStreamConsumer2 = new ThreadedStreamConsumer( forkClient );
if ( forkConfiguration.isDebug() )
{
@@ -189,13 +192,12 @@ public class ForkStarter
final int result =
CommandLineUtils.executeCommandLine( cli, threadedStreamConsumer2, threadedStreamConsumer2, timeout );
- if (result != RunResult.SUCCESS){
- throw new SurefireBooterForkException("Error occured in starting fork, check output in log");
+ if ( result != RunResult.SUCCESS )
+ {
+ throw new SurefireBooterForkException( "Error occured in starting fork, check output in log" );
}
threadedStreamConsumer2.close();
- out.close();
-
- final RunStatistics globalRunStatistics = testSetReporterFactory.getGlobalRunStatistics();
+ forkClient.close();
runResult = globalRunStatistics.getRunResult();
}
@@ -218,7 +220,8 @@ public class ForkStarter
{
final ClasspathConfiguration classpathConfiguration = startupConfiguration.getClasspathConfiguration();
ClassLoader testsClassLoader = classpathConfiguration.createTestClassLoader( false );
- ClassLoader surefireClassLoader = classpathConfiguration.createInprocSurefireClassLoader( testsClassLoader );
+ ClassLoader surefireClassLoader =
+ classpathConfiguration.createInprocSurefireClassLoader( testsClassLoader );
CommonReflector commonReflector = new CommonReflector( surefireClassLoader );
Object reporterFactory = commonReflector.createReportingReporterFactory( startupReportConfiguration );
@@ -226,7 +229,7 @@ public class ForkStarter
final ProviderFactory providerFactory =
new ProviderFactory( startupConfiguration, providerConfiguration, surefireClassLoader, testsClassLoader,
reporterFactory );
- SurefireProvider surefireProvider = providerFactory.createProvider(false);
+ SurefireProvider surefireProvider = providerFactory.createProvider( false );
return surefireProvider.getSuites();
}
catch ( SurefireExecutionException e )
@@ -236,5 +239,4 @@ public class ForkStarter
}
-
}
Modified: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/FileReporterFactory.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/FileReporterFactory.java?rev=1205186&r1=1205185&r2=1205186&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/FileReporterFactory.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/FileReporterFactory.java Tue Nov 22 21:43:19 2011
@@ -19,12 +19,12 @@ package org.apache.maven.plugin.surefire
* under the License.
*/
+import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import org.apache.maven.plugin.surefire.runorder.StatisticsReporter;
import org.apache.maven.surefire.booter.StartupReportConfiguration;
-import org.apache.maven.surefire.report.AbstractConsoleReporter;
-import org.apache.maven.surefire.report.AbstractFileReporter;
import org.apache.maven.surefire.report.ConsoleLogger;
import org.apache.maven.surefire.report.DefaultDirectConsoleReporter;
import org.apache.maven.surefire.report.MulticastingReporter;
@@ -34,7 +34,6 @@ import org.apache.maven.surefire.report.
import org.apache.maven.surefire.report.RunListener;
import org.apache.maven.surefire.report.RunStatistics;
import org.apache.maven.surefire.report.TestSetRunListener;
-import org.apache.maven.surefire.report.XMLReporter;
import org.apache.maven.surefire.suite.RunResult;
/**
@@ -56,11 +55,14 @@ public class FileReporterFactory
private final StartupReportConfiguration reportConfiguration;
+ private final StatisticsReporter statisticsReporter;
+
public FileReporterFactory( StartupReportConfiguration reportConfiguration )
{
this.reportConfiguration = reportConfiguration;
this.reporterConfiguration = getReporterConfiguration();
multicastingReporter = new MulticastingReporter( instantiateReports() );
+ this.statisticsReporter = reportConfiguration.instantiateStatisticsReporter();
runStarting();
}
@@ -73,38 +75,23 @@ public class FileReporterFactory
public RunListener createReporter()
{
- return new TestSetRunListener( instantiateConsoleReporter(), instantiateFileReporter(),
- instantiateXmlReporter(), instantiateConsoleOutputFileReporter(), globalStats );
- }
-
- private AbstractConsoleReporter instantiateConsoleReporter()
- {
- return reportConfiguration.instantiateConsoleReporter();
- }
-
- private AbstractFileReporter instantiateFileReporter()
- {
- return reportConfiguration.instantiateFileReporter();
- }
-
- private XMLReporter instantiateXmlReporter()
- {
- return reportConfiguration.instantiateXmlReporter();
- }
-
- private Reporter instantiateConsoleOutputFileReporter()
- {
- return reportConfiguration.instantiateConsoleOutputFileReporterName(
- reporterConfiguration.getOriginalSystemOut() );
+ final PrintStream sout = reporterConfiguration.getOriginalSystemOut();
+ return new TestSetRunListener( reportConfiguration.instantiateConsoleReporter(),
+ reportConfiguration.instantiateFileReporter(),
+ reportConfiguration.instantiateXmlReporter(),
+ reportConfiguration.instantiateConsoleOutputFileReporter( sout ),
+ statisticsReporter, globalStats );
}
private List instantiateReports()
{
+ final PrintStream sout = reporterConfiguration.getOriginalSystemOut();
List result = new ArrayList();
- addIfNotNull( result, instantiateConsoleReporter() );
- addIfNotNull( result, instantiateFileReporter() );
- addIfNotNull( result, instantiateXmlReporter() );
- addIfNotNull( result, instantiateConsoleOutputFileReporter() );
+ addIfNotNull( result, reportConfiguration.instantiateConsoleReporter() );
+ addIfNotNull( result, reportConfiguration.instantiateFileReporter() );
+ addIfNotNull( result, reportConfiguration.instantiateXmlReporter() );
+ addIfNotNull( result, reportConfiguration.instantiateConsoleOutputFileReporter( sout ) );
+ addIfNotNull( result, statisticsReporter );
return result;
}
Added: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/StatisticsReporter.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/StatisticsReporter.java?rev=1205186&view=auto
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/StatisticsReporter.java (added)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/StatisticsReporter.java Tue Nov 22 21:43:19 2011
@@ -0,0 +1,98 @@
+package org.apache.maven.plugin.surefire.runorder;
+
+/*
+ * 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 java.io.File;
+import java.io.FileNotFoundException;
+import org.apache.maven.surefire.report.ReportEntry;
+import org.apache.maven.surefire.report.Reporter;
+import org.apache.maven.surefire.util.NestedRuntimeException;
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class StatisticsReporter
+ implements Reporter
+{
+ private final RunEntryStatisticsMap existing;
+
+ private final RunEntryStatisticsMap newResults;
+
+ private final File dataFile;
+
+ public StatisticsReporter( File dataFile )
+ {
+ this.dataFile = dataFile;
+ this.existing = RunEntryStatisticsMap.fromFile( this.dataFile );
+ this.newResults = new RunEntryStatisticsMap();
+ }
+
+ public void testSetStarting( ReportEntry report )
+ {
+ }
+
+ public void testSetCompleted( ReportEntry report )
+ {
+ try
+ {
+ newResults.serialize( dataFile );
+ }
+ catch ( FileNotFoundException e )
+ {
+ throw new NestedRuntimeException( e );
+ }
+ }
+
+ public void testStarting( ReportEntry report )
+ {
+ }
+
+ public void testSucceeded( ReportEntry report )
+ {
+ newResults.add( existing.createNextGeneration( report ) );
+ }
+
+ public void testSkipped( ReportEntry report )
+ {
+ newResults.add( existing.createNextGeneration( report ) );
+ }
+
+ public void testError( ReportEntry report, String stdOut, String stdErr )
+ {
+ newResults.add( existing.createNextGenerationFailure( report ) );
+ }
+
+ public void testFailed( ReportEntry report, String stdOut, String stdErr )
+ {
+ newResults.add( existing.createNextGenerationFailure( report ) );
+ }
+
+ public void writeMessage( String message )
+ {
+ }
+
+ public void writeMessage( byte[] b, int off, int len )
+ {
+ }
+
+ public void reset()
+ {
+ }
+}
Propchange: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/StatisticsReporter.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/surefire/booter/StartupReportConfiguration.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/surefire/booter/StartupReportConfiguration.java?rev=1205186&r1=1205185&r2=1205186&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/surefire/booter/StartupReportConfiguration.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/surefire/booter/StartupReportConfiguration.java Tue Nov 22 21:43:19 2011
@@ -24,6 +24,7 @@ import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
+import org.apache.maven.plugin.surefire.runorder.StatisticsReporter;
import org.apache.maven.surefire.report.AbstractConsoleReporter;
import org.apache.maven.surefire.report.AbstractFileReporter;
import org.apache.maven.surefire.report.BriefConsoleReporter;
@@ -39,7 +40,6 @@ import org.apache.maven.surefire.report.
/**
* All the parameters used to construct reporters
* <p/>
- * TODO: Move out of API module
*
* @author Kristian Rosenvold
*/
@@ -53,6 +53,10 @@ public class StartupReportConfiguration
private final String reportNameSuffix;
+ private final String configurationHash;
+
+ private final boolean requiresRunHistory;
+
private final boolean redirectTestOutputToFile;
private final boolean disableXmlReport;
@@ -61,7 +65,7 @@ public class StartupReportConfiguration
private final boolean trimStackTrace;
- private final Properties testVmSystemProperties = new Properties( );
+ private final Properties testVmSystemProperties = new Properties();
public static final String BRIEF_REPORT_FORMAT = "brief";
@@ -69,16 +73,8 @@ public class StartupReportConfiguration
public StartupReportConfiguration( boolean useFile, boolean printSummary, String reportFormat,
boolean redirectTestOutputToFile, boolean disableXmlReport,
- File reportsDirectory, boolean trimStackTrace )
- {
- this( useFile, printSummary, reportFormat, redirectTestOutputToFile,
- disableXmlReport, reportsDirectory, trimStackTrace, null );
- }
-
- public StartupReportConfiguration( boolean useFile, boolean printSummary, String reportFormat,
- boolean redirectTestOutputToFile, boolean disableXmlReport,
- File reportsDirectory, boolean trimStackTrace,
- String reportNameSuffix )
+ File reportsDirectory, boolean trimStackTrace, String reportNameSuffix,
+ String configurationHash, boolean requiresRunHistory )
{
this.useFile = useFile;
this.printSummary = printSummary;
@@ -88,18 +84,22 @@ public class StartupReportConfiguration
this.reportsDirectory = reportsDirectory;
this.trimStackTrace = trimStackTrace;
this.reportNameSuffix = reportNameSuffix;
+ this.configurationHash = configurationHash;
+ this.requiresRunHistory = requiresRunHistory;
}
public static StartupReportConfiguration defaultValue()
{
File target = new File( "./target" );
- return new StartupReportConfiguration( true, true, "PLAIN", false, false, target, false );
+ return new StartupReportConfiguration( true, true, "PLAIN", false, false, target, false, null, "TESTHASH",
+ false );
}
public static StartupReportConfiguration defaultNoXml()
{
File target = new File( "./target" );
- return new StartupReportConfiguration( true, true, "PLAIN", false, true, target, false );
+ return new StartupReportConfiguration( true, true, "PLAIN", false, true, target, false, null, "TESTHASHxXML",
+ false );
}
public boolean isUseFile()
@@ -150,7 +150,7 @@ public class StartupReportConfiguration
{
if ( !isDisableXmlReport() )
{
- return new XMLReporter(trimStackTrace, reportsDirectory, reportNameSuffix);
+ return new XMLReporter( trimStackTrace, reportsDirectory, reportNameSuffix );
}
return null;
}
@@ -177,11 +177,11 @@ public class StartupReportConfiguration
{
if ( BRIEF_REPORT_FORMAT.equals( getReportFormat() ) )
{
- return new BriefFileReporter(trimStackTrace, reportsDirectory, getReportNameSuffix());
+ return new BriefFileReporter( trimStackTrace, reportsDirectory, getReportNameSuffix() );
}
else if ( PLAIN_REPORT_FORMAT.equals( getReportFormat() ) )
{
- return new FileReporter(trimStackTrace, reportsDirectory, getReportNameSuffix());
+ return new FileReporter( trimStackTrace, reportsDirectory, getReportNameSuffix() );
}
}
return null;
@@ -214,15 +214,15 @@ public class StartupReportConfiguration
{
if ( isUseFile() )
{
- return isPrintSummary() ? new ConsoleReporter(trimStackTrace) : null;
+ return isPrintSummary() ? new ConsoleReporter( trimStackTrace ) : null;
}
else if ( isRedirectTestOutputToFile() || BRIEF_REPORT_FORMAT.equals( getReportFormat() ) )
{
- return new BriefConsoleReporter(trimStackTrace);
+ return new BriefConsoleReporter( trimStackTrace );
}
else if ( PLAIN_REPORT_FORMAT.equals( getReportFormat() ) )
{
- return new DetailedConsoleReporter(trimStackTrace );
+ return new DetailedConsoleReporter( trimStackTrace );
}
return null;
}
@@ -239,16 +239,31 @@ public class StartupReportConfiguration
}
}
- public Reporter instantiateConsoleOutputFileReporterName(PrintStream originalSystemOut)
+ public Reporter instantiateConsoleOutputFileReporter( PrintStream originalSystemOut )
{
if ( isRedirectTestOutputToFile() )
{
- return new ConsoleOutputFileReporter(reportsDirectory, getReportNameSuffix());
+ return new ConsoleOutputFileReporter( reportsDirectory, getReportNameSuffix() );
}
else
{
- return new ConsoleOutputDirectReporter(originalSystemOut);
+ return new ConsoleOutputDirectReporter( originalSystemOut );
+ }
+ }
+
+ public StatisticsReporter instantiateStatisticsReporter()
+ {
+ if ( requiresRunHistory )
+ {
+ final File target = getStatisticsFile();
+ return new StatisticsReporter( target );
}
+ return null;
+ }
+
+ public File getStatisticsFile()
+ {
+ return new File( reportsDirectory.getParentFile().getParentFile(), ".surefire-" + this.configurationHash );
}
@@ -286,4 +301,14 @@ public class StartupReportConfiguration
{
return trimStackTrace;
}
+
+ public String getConfigurationHash()
+ {
+ return configurationHash;
+ }
+
+ public boolean isRequiresRunHistory()
+ {
+ return requiresRunHistory;
+ }
}
Modified: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/TestSetRunListener.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/TestSetRunListener.java?rev=1205186&r1=1205185&r2=1205186&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/TestSetRunListener.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/TestSetRunListener.java Tue Nov 22 21:43:19 2011
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import org.apache.maven.plugin.surefire.runorder.StatisticsReporter;
import org.apache.maven.surefire.util.internal.ByteBuffer;
/**
@@ -45,7 +46,8 @@ public class TestSetRunListener
public TestSetRunListener( AbstractConsoleReporter consoleReporter, AbstractFileReporter fileReporter,
- XMLReporter xmlReporter, Reporter reporter, RunStatistics globalStats )
+ XMLReporter xmlReporter, Reporter reporter, StatisticsReporter statisticsReporter,
+ RunStatistics globalStats )
{
ArrayList reportes = new ArrayList();
@@ -65,6 +67,10 @@ public class TestSetRunListener
{
reportes.add( reporter );
}
+ if ( statisticsReporter != null )
+ {
+ reportes.add( statisticsReporter );
+ }
multicastingReporter = new MulticastingReporter( reportes );
this.testSetStatistics = new TestSetStatistics();
this.globalStatistics = globalStats;
@@ -77,7 +83,7 @@ public class TestSetRunListener
public void writeMessage( String message )
{
- info( message );
+ info( message );
}
public void writeMessage( byte[] b, int off, int len )
Modified: maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java?rev=1205186&r1=1205185&r2=1205186&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java Tue Nov 22 21:43:19 2011
@@ -35,6 +35,7 @@ import org.apache.maven.surefire.booter.
import org.apache.maven.surefire.booter.TypeEncodedValue;
import org.apache.maven.surefire.report.ReporterConfiguration;
import org.apache.maven.surefire.testset.DirectoryScannerParameters;
+import org.apache.maven.surefire.testset.RunOrderParameters;
import org.apache.maven.surefire.testset.TestArtifactInfo;
import org.apache.maven.surefire.testset.TestRequest;
import org.apache.maven.surefire.util.RunOrder;
@@ -160,7 +161,8 @@ public class BooterDeserializerProviderC
excludes.add( "xx1" );
excludes.add( "xx2" );
- return new DirectoryScannerParameters( aDir, includes, excludes, Boolean.TRUE, RunOrder.FILESYSTEM );
+ return new DirectoryScannerParameters( aDir, includes, excludes, Boolean.TRUE,
+ RunOrder.asString( RunOrder.DEFAULT ) );
}
private ProviderConfiguration saveAndReload( ProviderConfiguration booterConfiguration,
@@ -187,7 +189,8 @@ public class BooterDeserializerProviderC
TestRequest testSuiteDefinition =
new TestRequest( getSuiteXmlFileStrings(), getTestSourceDirectory(), aUserRequestedTest,
aUserRequestedTestMethod );
- return new ProviderConfiguration( directoryScannerParameters, true, reporterConfiguration,
+ RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, null );
+ return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, true, reporterConfiguration,
new TestArtifactInfo( "5.0", "ABC" ), testSuiteDefinition, new Properties(),
aTestTyped );
}
Modified: maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java?rev=1205186&r1=1205185&r2=1205186&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java Tue Nov 22 21:43:19 2011
@@ -35,8 +35,10 @@ import org.apache.maven.surefire.booter.
import org.apache.maven.surefire.booter.SystemPropertyManager;
import org.apache.maven.surefire.report.ReporterConfiguration;
import org.apache.maven.surefire.testset.DirectoryScannerParameters;
+import org.apache.maven.surefire.testset.RunOrderParameters;
import org.apache.maven.surefire.testset.TestArtifactInfo;
import org.apache.maven.surefire.testset.TestRequest;
+import org.apache.maven.surefire.util.RunOrder;
import junit.framework.TestCase;
@@ -100,7 +102,7 @@ public class BooterDeserializerStartupCo
{
Classpath testClassPath = new Classpath( Arrays.asList( new String[]{ "CP1", "CP2" } ) );
Classpath providerClasspath = new Classpath( Arrays.asList( new String[]{ "SP1", "SP2" } ) );
- return new ClasspathConfiguration( testClassPath, providerClasspath, new Classpath( ), true, true );
+ return new ClasspathConfiguration( testClassPath, providerClasspath, new Classpath(), true, true );
}
public static ClassLoaderConfiguration getSystemClassLoaderConfiguration()
@@ -147,7 +149,9 @@ public class BooterDeserializerStartupCo
TestRequest testSuiteDefinition =
new TestRequest( Arrays.asList( getSuiteXmlFileStrings() ), getTestSourceDirectory(), aUserRequestedTest,
aUserRequestedTestMethod );
- return new ProviderConfiguration( directoryScannerParameters, true, reporterConfiguration,
+
+ RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, null );
+ return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, true, reporterConfiguration,
new TestArtifactInfo( "5.0", "ABC" ), testSuiteDefinition, new Properties(),
BooterDeserializerProviderConfigurationTest.aTestTyped );
}
Copied: maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java (from r1204953, maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java)
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java?p2=maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java&p1=maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java&r1=1204953&r2=1205186&rev=1205186&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java Tue Nov 22 21:43:19 2011
@@ -21,8 +21,8 @@ package org.apache.maven.plugin.surefire
import org.apache.maven.plugin.surefire.report.FileReporterFactory;
import org.apache.maven.surefire.booter.StartupReportConfiguration;
-import org.apache.maven.surefire.report.DefaultConsoleReporter;
import org.apache.maven.surefire.report.ConsoleLogger;
+import org.apache.maven.surefire.report.DefaultConsoleReporter;
import org.apache.maven.surefire.report.RunListener;
/**
Added: maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMapTest.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMapTest.java?rev=1205186&view=auto
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMapTest.java (added)
+++ maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMapTest.java Tue Nov 22 21:43:19 2011
@@ -0,0 +1,109 @@
+package org.apache.maven.plugin.surefire.runorder;
+
+/*
+ * 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 java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Arrays;
+import java.util.List;
+import org.apache.maven.surefire.report.ReportEntry;
+import org.apache.maven.surefire.report.SimpleReportEntry;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class RunEntryStatisticsMapTest
+ extends TestCase
+{
+ public void testPrioritizedClassRuntime()
+ throws IOException
+ {
+ final RunEntryStatisticsMap runEntryStatisticsMap = RunEntryStatisticsMap.fromReader( getStatisticsFile() );
+ final List list = Arrays.asList( new Class[]{ A.class, B.class, C.class } );
+ final List prioritizedTestsClassRunTime = runEntryStatisticsMap.getPrioritizedTestsClassRunTime( list, 2 );
+ assertEquals( C.class, prioritizedTestsClassRunTime.get( 0 ) );
+ assertEquals( B.class, prioritizedTestsClassRunTime.get( 1 ) );
+ assertEquals( A.class, prioritizedTestsClassRunTime.get( 2 ) );
+ }
+
+ public void testPrioritizedFailureFirst()
+ throws IOException
+ {
+ final RunEntryStatisticsMap runEntryStatisticsMap = RunEntryStatisticsMap.fromReader( getStatisticsFile() );
+ final List list = Arrays.asList( new Class[]{ A.class, B.class, C.class } );
+ final List prioritizedTestsClassRunTime = runEntryStatisticsMap.getPrioritizedTestsByFailureFirst( list);
+ assertEquals( A.class, prioritizedTestsClassRunTime.get( 0 ) );
+ assertEquals( C.class, prioritizedTestsClassRunTime.get( 1 ) );
+ assertEquals( B.class, prioritizedTestsClassRunTime.get( 2 ) );
+ }
+
+ private StringReader getStatisticsFile()
+ {
+ String content = "0,17,testA(org.apache.maven.plugin.surefire.runorder.RunEntryStatisticsMapTest$A)\n" +
+ "2,42,testB(org.apache.maven.plugin.surefire.runorder.RunEntryStatisticsMapTest$B)\n" +
+ "1,100,testC(org.apache.maven.plugin.surefire.runorder.RunEntryStatisticsMapTest$C)\n";
+ return new StringReader( content );
+ }
+
+ public void testSerialize()
+ throws Exception
+ {
+ File data = File.createTempFile( "surefire-unit", "test" );
+ RunEntryStatisticsMap existingEntries = RunEntryStatisticsMap.fromFile( data );
+ RunEntryStatisticsMap newResults = new RunEntryStatisticsMap();
+
+ ReportEntry reportEntry1 = new SimpleReportEntry( "abc", "method1", new Integer( 42 ) );
+ ReportEntry reportEntry2 = new SimpleReportEntry( "abc", "willFail", new Integer( 17 ) );
+ ReportEntry reportEntry3 = new SimpleReportEntry( "abc", "method3", new Integer( 100 ) );
+
+ newResults.add( existingEntries.createNextGeneration( reportEntry1 ) );
+ newResults.add( existingEntries.createNextGeneration( reportEntry2 ) );
+ newResults.add( existingEntries.createNextGeneration( reportEntry3 ) );
+
+ newResults.serialize( data );
+
+ RunEntryStatisticsMap nextRun = RunEntryStatisticsMap.fromFile( data );
+ newResults = new RunEntryStatisticsMap();
+
+ newResults.add( existingEntries.createNextGeneration( reportEntry1 ) );
+ newResults.add( existingEntries.createNextGenerationFailure( reportEntry2 ) );
+ newResults.add( existingEntries.createNextGeneration( reportEntry3 ) );
+
+ newResults.serialize( data );
+ }
+
+
+
+ class A
+ {
+ }
+
+ class B
+ {
+ }
+
+ class C
+ {
+ }
+
+}
Propchange: maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMapTest.java
------------------------------------------------------------------------------
svn:eol-style = native
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=1205186&r1=1205185&r2=1205186&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 Tue Nov 22 21:43:19 2011
@@ -24,7 +24,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
-
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
@@ -591,11 +590,21 @@ public class SurefirePlugin
/**
* Defines the order the tests will be run in. Supported values are "alphabetical", "reversealphabetical", "random",
- * "hourly" (alphabetical on even hours, reverse alphabetical on odd hours) and "filesystem".
+ * "hourly" (alphabetical on even hours, reverse alphabetical on odd hours), "failedfirst", "balanced" and "filesystem".
* <p/>
* <p/>
* Odd/Even for hourly is determined at the time the of scanning the classpath, meaning it could change during a
* multi-module build.
+ * <p/>
+ * Failed first will run tests that failed on previous run first, as well as new tests.
+ * <p/>
+ * Balanced is only relevant with parallel=classes, and will try to optimize the run-order of the tests to
+ * make all tests complete at the same time, reducing the overall execution time.
+ * <p/>
+ * Note that the statistics are stored in a file named .surefire-XXXXXXXXX beside pom.xml, and should not
+ * be checked into version control. The "XXXXX" is the SHA1 checksum of the entire surefire configuration,
+ * so different configurations will have different statistics files, meaning if you change any config
+ * settings you will re-run once before new statistics data can be established.
*
* @parameter default-value="filesystem"
* @since 2.7
@@ -653,7 +662,7 @@ public class SurefirePlugin
protected String[] getDefaultIncludes()
{
- return new String[]{"**/Test*.java", "**/*Test.java", "**/*TestCase.java"};
+ return new String[]{ "**/Test*.java", "**/*Test.java", "**/*TestCase.java" };
}
// now for the implementation of the field accessors
Copied: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/PrioritizedTest.java (from r1204953, maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java)
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/PrioritizedTest.java?p2=maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/PrioritizedTest.java&p1=maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java&r1=1204953&r2=1205186&rev=1205186&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java (original)
+++ maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/PrioritizedTest.java Tue Nov 22 21:43:19 2011
@@ -1,4 +1,4 @@
-package org.apache.maven.plugin.surefire.booterclient;
+package org.apache.maven.plugin.surefire.runorder;
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,30 +19,33 @@ package org.apache.maven.plugin.surefire
* under the License.
*/
-import org.apache.maven.plugin.surefire.report.FileReporterFactory;
-import org.apache.maven.surefire.booter.StartupReportConfiguration;
-import org.apache.maven.surefire.report.DefaultConsoleReporter;
-import org.apache.maven.surefire.report.ConsoleLogger;
-import org.apache.maven.surefire.report.RunListener;
-
/**
* @author Kristian Rosenvold
*/
-public class TestSetMockReporterFactory
- extends FileReporterFactory
+public class PrioritizedTest
{
- public TestSetMockReporterFactory()
+ private final Class clazz;
+ private final Priority priority;
+
+ public PrioritizedTest( Class clazz, Priority pri )
+ {
+ this.clazz = clazz;
+ this.priority = pri;
+ }
+
+ public int getPriority()
{
- super( StartupReportConfiguration.defaultValue() );
+ return priority.getPriority();
}
- public ConsoleLogger createConsoleLogger()
+
+ public int getTotalRuntime()
{
- return new DefaultConsoleReporter( System.out );
+ return priority.getTotalRuntime();
}
- public RunListener createReporter()
+ public Class getClazz()
{
- return new MockReporter();
+ return clazz;
}
}
Added: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/Priority.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/Priority.java?rev=1205186&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/Priority.java (added)
+++ maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/Priority.java Tue Nov 22 21:43:19 2011
@@ -0,0 +1,74 @@
+package org.apache.maven.plugin.surefire.runorder;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class Priority
+{
+ private final String className;
+ int priority;
+ int totalRuntime = 0;
+ int minSuccessRate = Integer.MAX_VALUE;
+
+ public Priority( String className )
+ {
+ this.className = className;
+ }
+
+ public static Priority lowest(String className){
+ Priority priority1 = new Priority( className );
+ priority1.setPriority( Integer.MAX_VALUE );
+ priority1.minSuccessRate = 0;
+ return priority1;
+ }
+
+ public void addItem( RunEntryStatistics itemStat )
+ {
+ totalRuntime += itemStat.getRunTime();
+ minSuccessRate = Math.min( minSuccessRate, itemStat.getSuccessfulBuilds());
+ }
+
+ public int getTotalRuntime()
+ {
+ return totalRuntime;
+ }
+
+ public int getMinSuccessRate()
+ {
+ return minSuccessRate;
+ }
+
+ public String getClassName()
+ {
+ return className;
+ }
+
+ public int getPriority()
+ {
+ return priority;
+ }
+
+ public void setPriority( int priority )
+ {
+ this.priority = priority;
+ }
+}
Propchange: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/Priority.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatistics.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatistics.java?rev=1205186&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatistics.java (added)
+++ maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatistics.java Tue Nov 22 21:43:19 2011
@@ -0,0 +1,99 @@
+package org.apache.maven.plugin.surefire.runorder;
+/*
+ * 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 java.util.StringTokenizer;
+import org.apache.maven.surefire.report.ReportEntry;
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class RunEntryStatistics
+{
+ private final int runTime;
+
+ private final int successfulBuilds;
+
+ private final String testName;
+
+ private RunEntryStatistics( int runTime, int successfulBuilds, String testName )
+ {
+ this.runTime = runTime;
+ this.successfulBuilds = successfulBuilds;
+ this.testName = testName;
+ }
+
+ public static RunEntryStatistics fromReportEntry( ReportEntry previous )
+ {
+ final Integer elapsed = previous.getElapsed();
+ return new RunEntryStatistics( elapsed != null ? elapsed.intValue() : 0, 0, previous.getName() );
+ }
+
+ public static RunEntryStatistics fromValues( int runTime, int successfulBuilds, Class clazz, String testName )
+ {
+ return new RunEntryStatistics( runTime, successfulBuilds, testName + "(" + clazz.getName() + ")" );
+ }
+
+ public RunEntryStatistics nextGeneration( int runTime )
+ {
+ return new RunEntryStatistics( runTime, this.successfulBuilds + 1, this.testName );
+ }
+
+ public RunEntryStatistics nextGenerationFailure( int runTime )
+ {
+ return new RunEntryStatistics( runTime, 0, this.testName );
+ }
+
+ public String getTestName()
+ {
+ return testName;
+ }
+
+ public int getRunTime()
+ {
+ return runTime;
+ }
+
+
+ public int getSuccessfulBuilds()
+ {
+ return successfulBuilds;
+ }
+
+ public static RunEntryStatistics fromString( String line )
+ {
+ StringTokenizer tok = new StringTokenizer( line, "," );
+ int successfulBuilds = Integer.parseInt( tok.nextToken() );
+ int runTime = Integer.parseInt( tok.nextToken() );
+ String className = tok.nextToken();
+ return new RunEntryStatistics( runTime, successfulBuilds, className );
+ }
+
+ public String getAsString()
+ {
+ StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer.append( successfulBuilds );
+ stringBuffer.append( "," );
+ stringBuffer.append( runTime );
+ stringBuffer.append( "," );
+ stringBuffer.append( testName );
+ return stringBuffer.toString();
+ }
+
+}
Propchange: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatistics.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java?rev=1205186&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java (added)
+++ maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java Tue Nov 22 21:43:19 2011
@@ -0,0 +1,289 @@
+package org.apache.maven.plugin.surefire.runorder;
+
+/*
+ * 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 java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.maven.surefire.report.ReportEntry;
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class RunEntryStatisticsMap
+{
+ private final Map runEntryStatistics;
+
+ public RunEntryStatisticsMap( Map runEntryStatistics )
+ {
+ this.runEntryStatistics = Collections.synchronizedMap( runEntryStatistics );
+ }
+
+ public RunEntryStatisticsMap()
+ {
+ this( new HashMap() );
+ }
+
+ public static RunEntryStatisticsMap fromFile( File file )
+ {
+ if ( file.exists() )
+ {
+ try
+ {
+ FileReader fileReader = new FileReader( file );
+ return fromReader( fileReader );
+ }
+ catch ( FileNotFoundException e )
+ {
+ throw new RuntimeException( e );
+ }
+ catch ( IOException e1 )
+ {
+ throw new RuntimeException( e1 );
+ }
+
+ }
+ return new RunEntryStatisticsMap();
+ }
+
+ static RunEntryStatisticsMap fromReader( Reader fileReader )
+ throws IOException
+ {
+ Map result = new HashMap();
+ BufferedReader bufferedReader = new BufferedReader( fileReader );
+ String line = bufferedReader.readLine();
+ while ( line != null )
+ {
+ if ( !line.startsWith( "#" ) )
+ {
+ final RunEntryStatistics stats = RunEntryStatistics.fromString( line );
+ result.put( stats.getTestName(), stats );
+ }
+ line = bufferedReader.readLine();
+ }
+ return new RunEntryStatisticsMap( result );
+ }
+
+ public void serialize( File file )
+ throws FileNotFoundException
+ {
+ FileOutputStream fos = new FileOutputStream( file );
+ PrintWriter printWriter = new PrintWriter( fos );
+ List items = new ArrayList( runEntryStatistics.values() );
+ Collections.sort( items, new RunCountComparator() );
+ RunEntryStatistics item;
+ for ( Iterator iter = items.iterator(); iter.hasNext(); )
+ {
+ item = (RunEntryStatistics) iter.next();
+ printWriter.println( item.getAsString() );
+ }
+ printWriter.close();
+ }
+
+
+ public RunEntryStatistics findOrCreate( ReportEntry reportEntry )
+ {
+ final RunEntryStatistics item = (RunEntryStatistics) runEntryStatistics.get( reportEntry.getName() );
+ return item != null ? item : RunEntryStatistics.fromReportEntry( reportEntry );
+ }
+
+ public RunEntryStatistics createNextGeneration( ReportEntry reportEntry )
+ {
+ final RunEntryStatistics newItem = findOrCreate( reportEntry );
+ final Integer elapsed = reportEntry.getElapsed();
+ return newItem.nextGeneration( elapsed != null ? elapsed.intValue() : 0 );
+ }
+
+ public RunEntryStatistics createNextGenerationFailure( ReportEntry reportEntry )
+ {
+ final RunEntryStatistics newItem = findOrCreate( reportEntry );
+ final Integer elapsed = reportEntry.getElapsed();
+ return newItem.nextGenerationFailure( elapsed != null ? elapsed.intValue() : 0 );
+ }
+
+ public void add( RunEntryStatistics item )
+ {
+ runEntryStatistics.put( item.getTestName(), item );
+ }
+
+ class RunCountComparator
+ implements Comparator
+ {
+ public int compare( Object o, Object o1 )
+ {
+ RunEntryStatistics re = (RunEntryStatistics) o;
+ RunEntryStatistics re1 = (RunEntryStatistics) o1;
+ int runtime = re.getSuccessfulBuilds() - re1.getSuccessfulBuilds();
+ if ( runtime == 0 )
+ {
+ return re.getRunTime() - re1.getRunTime();
+ }
+ return runtime;
+ }
+ }
+
+ public List getPrioritizedTestsClassRunTime( List testsToRun, int threadCount )
+ {
+ final List prioritizedTests = getPrioritizedTests( testsToRun, new TestRuntimeComparator() );
+ ThreadedExecutionScheduler threadedExecutionScheduler = new ThreadedExecutionScheduler( threadCount );
+ for ( Iterator prioritizedTest = prioritizedTests.iterator(); prioritizedTest.hasNext(); )
+ {
+ threadedExecutionScheduler.addTest( (PrioritizedTest) prioritizedTest.next() );
+ }
+
+ return threadedExecutionScheduler.getResult();
+
+ }
+
+ public List getPrioritizedTestsByFailureFirst( List testsToRun )
+ {
+ final List prioritizedTests = getPrioritizedTests( testsToRun, new LeastFailureComparator() );
+ return transformToClasses( prioritizedTests );
+ }
+
+
+ private List getPrioritizedTests( List testsToRun, Comparator priorityComparator )
+ {
+ Map classPriorities = getPriorities( priorityComparator );
+
+ List tests = new ArrayList();
+ for ( Iterator iter = testsToRun.iterator(); iter.hasNext(); )
+ {
+ Class clazz = (Class) iter.next();
+ Priority pri = (Priority) classPriorities.get( clazz.getName() );
+ if ( pri == null )
+ {
+ pri = Priority.lowest( clazz.getName() );
+ }
+ PrioritizedTest prioritizedTest = new PrioritizedTest( clazz, pri );
+ tests.add( prioritizedTest );
+ }
+ Collections.sort( tests, new PrioritizedTestComparator() );
+ return tests;
+
+ }
+
+ private List transformToClasses( List tests )
+ {
+ List result = new ArrayList();
+ for ( int i = 0; i < tests.size(); i++ )
+ {
+ result.add( ( (PrioritizedTest) tests.get( i ) ).getClazz() );
+ }
+ return result;
+ }
+
+ public Map getPriorities( Comparator priorityComparator )
+ {
+ Map priorities = new HashMap();
+ for ( Iterator iter = runEntryStatistics.keySet().iterator(); iter.hasNext(); )
+ {
+ String testNames = (String) iter.next();
+ String clazzName = extractClassName( testNames );
+ Priority priority = (Priority) priorities.get( clazzName );
+ if ( priority == null )
+ {
+ priority = new Priority( clazzName );
+ priorities.put( clazzName, priority );
+ }
+
+ RunEntryStatistics itemStat = (RunEntryStatistics) runEntryStatistics.get( testNames );
+ priority.addItem( itemStat );
+ }
+
+ List items = new ArrayList( priorities.values() );
+ Collections.sort( items, priorityComparator );
+ Map result = new HashMap();
+ int i = 0;
+ for ( Iterator iter = items.iterator(); iter.hasNext(); )
+ {
+ Priority pri = (Priority) iter.next();
+ pri.setPriority( i++ );
+ result.put( pri.getClassName(), pri );
+ }
+ return result;
+ }
+
+ class PrioritizedTestComparator
+ implements Comparator
+ {
+ public int compare( Object o, Object o1 )
+ {
+ PrioritizedTest re = (PrioritizedTest) o;
+ PrioritizedTest re1 = (PrioritizedTest) o1;
+ return re.getPriority() - re1.getPriority();
+ }
+ }
+
+ class TestRuntimeComparator
+ implements Comparator
+ {
+ public int compare( Object o, Object o1 )
+ {
+ Priority re = (Priority) o;
+ Priority re1 = (Priority) o1;
+ return re1.getTotalRuntime() - re.getTotalRuntime();
+ }
+ }
+
+ class LeastFailureComparator
+ implements Comparator
+ {
+ public int compare( Object o, Object o1 )
+ {
+ Priority re = (Priority) o;
+ Priority re1 = (Priority) o1;
+ return re.getMinSuccessRate() - re1.getMinSuccessRate();
+ }
+ }
+
+
+ private static final Pattern PARENS = Pattern.compile( "^" + "[^\\(\\)]+" //non-parens
+ + "\\((" // then an open-paren (start matching a group)
+ + "[^\\\\(\\\\)]+" //non-parens
+ + ")\\)" + "$" ); // then a close-paren (end group match)
+
+ String extractClassName( String displayName )
+ {
+ Matcher m = PARENS.matcher( displayName );
+ if ( !m.find() )
+ {
+ return displayName;
+ }
+ return m.group( 1 );
+ }
+
+
+}
Propchange: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionScheduler.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionScheduler.java?rev=1205186&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionScheduler.java (added)
+++ maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionScheduler.java Tue Nov 22 21:43:19 2011
@@ -0,0 +1,90 @@
+package org.apache.maven.plugin.surefire.runorder;
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class ThreadedExecutionScheduler
+{
+ private final int numThreads;
+
+ private final int runTime[];
+
+ private final List[] lists;
+
+ public ThreadedExecutionScheduler( int numThreads )
+ {
+ this.numThreads = numThreads;
+ runTime = new int[numThreads];
+ lists = new List[numThreads];
+ for ( int i = 0; i < numThreads; i++ )
+ {
+ lists[i] = new ArrayList();
+ }
+ }
+
+ public void addTest( PrioritizedTest prioritizedTest )
+ {
+ final int leastBusySlot = findLeastBusySlot();
+ runTime[leastBusySlot] += prioritizedTest.getTotalRuntime();
+ lists[leastBusySlot].add( prioritizedTest.getClazz() );
+ }
+
+ public List getResult()
+ {
+ List result = new ArrayList();
+ int index = 0;
+ boolean added = false;
+ do
+ {
+ added = false;
+ for ( int i = 0; i < numThreads; i++ )
+ {
+ if ( lists[i].size() > index )
+ {
+ result.add( lists[i].get( index ) );
+ added = true;
+ }
+ }
+ index++;
+ }
+ while ( added );
+ return result;
+ }
+
+ private int findLeastBusySlot()
+ {
+ int leastBusy = 0;
+ int minRuntime = runTime[0];
+ for ( int i = 1; i < numThreads; i++ )
+ {
+ if ( runTime[i] < minRuntime )
+ {
+ leastBusy = i;
+ minRuntime = runTime[i];
+ }
+ }
+ return leastBusy;
+ }
+}