diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java index 88b223a914..416f99fee2 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java @@ -47,6 +47,8 @@ import org.apache.maven.plugin.surefire.booterclient.ProviderDetector; import org.apache.maven.plugin.surefire.log.PluginConsoleLogger; import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; +import org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader; import org.apache.maven.plugin.surefire.util.DependencyScanner; import org.apache.maven.plugin.surefire.util.DirectoryScanner; import org.apache.maven.plugins.annotations.Component; @@ -75,7 +77,6 @@ import org.apache.maven.surefire.testset.TestRequest; import org.apache.maven.surefire.testset.TestSetFailedException; import org.apache.maven.surefire.util.DefaultScanResult; -import org.apache.maven.surefire.util.RunOrder; import org.apache.maven.surefire.util.SurefireReflectionException; import org.apache.maven.toolchain.DefaultToolchain; import org.apache.maven.toolchain.Toolchain; @@ -107,6 +108,9 @@ import static org.apache.commons.lang3.JavaVersion.JAVA_RECENT; import static org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS; import static org.apache.commons.lang3.SystemUtils.isJavaVersionAtLeast; +import static org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader.defaultRunOrder; +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.BALANCED; +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.FAILEDFIRST; import static org.apache.maven.shared.utils.StringUtils.capitalizeFirstLetter; import static org.apache.maven.shared.utils.StringUtils.isEmpty; import static org.apache.maven.shared.utils.StringUtils.isNotBlank; @@ -1530,14 +1534,15 @@ String getEffectiveForkMode() private List getRunOrders() { String runOrderString = getRunOrder(); - RunOrder[] runOrder = runOrderString == null ? RunOrder.DEFAULT : RunOrder.valueOfMulti( runOrderString ); + RunOrder[] runOrder = runOrderString == null ? defaultRunOrder() + : RunOrderLoader.runOrdersOf( runOrderString ); return Arrays.asList( runOrder ); } private boolean requiresRunHistory() { final List runOrders = getRunOrders(); - return runOrders.contains( RunOrder.BALANCED ) || runOrders.contains( RunOrder.FAILEDFIRST ); + return runOrders.contains( BALANCED ) || runOrders.contains( FAILEDFIRST ); } private boolean getEffectiveFailIfNoTests() diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java index 591e89c813..9808751ac7 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java @@ -22,8 +22,8 @@ import java.io.File; import java.io.IOException; import java.util.List; - import org.apache.maven.plugin.surefire.SurefireProperties; +import org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader; import org.apache.maven.surefire.booter.ClassLoaderConfiguration; import org.apache.maven.surefire.booter.ClasspathConfiguration; import org.apache.maven.surefire.booter.KeyValueSource; @@ -37,7 +37,6 @@ import org.apache.maven.surefire.testset.TestArtifactInfo; import org.apache.maven.surefire.testset.TestListResolver; import org.apache.maven.surefire.testset.TestRequest; -import org.apache.maven.surefire.util.RunOrder; // CHECKSTYLE_OFF: imports import static org.apache.maven.surefire.booter.BooterConstants.*; @@ -119,7 +118,7 @@ File serialize( KeyValueSource sourceProperties, ProviderConfiguration booterCon final RunOrderParameters runOrderParameters = booterConfiguration.getRunOrderParameters(); if ( runOrderParameters != null ) { - properties.setProperty( RUN_ORDER, RunOrder.asString( runOrderParameters.getRunOrder() ) ); + properties.setProperty( RUN_ORDER, RunOrderLoader.asString( runOrderParameters.getRunOrders() ) ); properties.setProperty( RUN_STATISTICS_FILE, runOrderParameters.getRunStatisticsFile() ); } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/StatisticsReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/StatisticsReporter.java index a53db0241d..2ebc019155 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/StatisticsReporter.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/StatisticsReporter.java @@ -21,9 +21,11 @@ import java.io.File; import java.io.FileNotFoundException; + +import org.apache.maven.plugin.surefire.runorder.impl.statistics.RunEntryStatisticsMap; import org.apache.maven.surefire.report.ReportEntry; -import static org.apache.maven.plugin.surefire.runorder.RunEntryStatisticsMap.fromFile; +import static org.apache.maven.plugin.surefire.runorder.impl.statistics.RunEntryStatisticsMap.fromFile; /** * @author Kristian Rosenvold diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java index 26b8be7ab1..85193f642c 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java @@ -19,19 +19,36 @@ * under the License. */ +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; import junit.framework.Assert; import junit.framework.TestCase; -import org.apache.maven.surefire.booter.*; +import org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader; +import org.apache.maven.surefire.booter.BooterDeserializer; +import org.apache.maven.surefire.booter.ClassLoaderConfiguration; +import org.apache.maven.surefire.booter.ClasspathConfiguration; +import org.apache.maven.surefire.booter.PropertiesWrapper; +import org.apache.maven.surefire.booter.ProviderConfiguration; +import org.apache.maven.surefire.booter.Shutdown; +import org.apache.maven.surefire.booter.StartupConfiguration; +import org.apache.maven.surefire.booter.TypeEncodedValue; import org.apache.maven.surefire.cli.CommandLineOption; import org.apache.maven.surefire.report.ReporterConfiguration; -import org.apache.maven.surefire.testset.*; -import org.apache.maven.surefire.util.RunOrder; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.*; - +import org.apache.maven.surefire.testset.DirectoryScannerParameters; +import org.apache.maven.surefire.testset.ResolvedTest; +import org.apache.maven.surefire.testset.RunOrderParameters; +import org.apache.maven.surefire.testset.TestArtifactInfo; +import org.apache.maven.surefire.testset.TestListResolver; +import org.apache.maven.surefire.testset.TestRequest; + +import static org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader.defaultRunOrder; +import static org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader.getRunOrderProvider; import static org.apache.maven.surefire.cli.CommandLineOption.LOGGING_LEVEL_DEBUG; import static org.apache.maven.surefire.cli.CommandLineOption.REACTOR_FAIL_FAST; import static org.apache.maven.surefire.cli.CommandLineOption.SHOW_ERRORS; @@ -199,7 +216,7 @@ private DirectoryScannerParameters getDirectoryScannerParametersWithoutSpecificT excludes.add( "xx2" ); return new DirectoryScannerParameters( aDir, includes, excludes, Collections.emptyList(), true, - RunOrder.asString( RunOrder.DEFAULT ) ); + RunOrderLoader.asString( defaultRunOrder() ) ); } private ProviderConfiguration saveAndReload( ProviderConfiguration booterConfiguration, @@ -235,7 +252,7 @@ private ProviderConfiguration getTestProviderConfiguration( DirectoryScannerPara new TestRequest( getSuiteXmlFileStrings(), getTestSourceDirectory(), new TestListResolver( aUserRequestedTest + "#aUserRequestedTestMethod" ), rerunFailingTestsCount ); - RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, null ); + RunOrderParameters runOrderParameters = new RunOrderParameters( defaultRunOrder(), null ); return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, true, reporterConfiguration, new TestArtifactInfo( "5.0", "ABC" ), testSuiteDefinition, new HashMap(), aTestTyped, readTestsFromInStream, cli, 0, Shutdown.DEFAULT, 0 ); diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java index 035add0f4a..17019fe517 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java @@ -19,13 +19,6 @@ * under the License. */ -import junit.framework.TestCase; -import org.apache.maven.surefire.booter.*; -import org.apache.maven.surefire.cli.CommandLineOption; -import org.apache.maven.surefire.report.ReporterConfiguration; -import org.apache.maven.surefire.testset.*; -import org.apache.maven.surefire.util.RunOrder; - import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -33,7 +26,24 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; +import junit.framework.TestCase; +import org.apache.maven.surefire.booter.BooterDeserializer; +import org.apache.maven.surefire.booter.ClassLoaderConfiguration; +import org.apache.maven.surefire.booter.Classpath; +import org.apache.maven.surefire.booter.ClasspathConfiguration; +import org.apache.maven.surefire.booter.PropertiesWrapper; +import org.apache.maven.surefire.booter.ProviderConfiguration; +import org.apache.maven.surefire.booter.Shutdown; +import org.apache.maven.surefire.booter.StartupConfiguration; +import org.apache.maven.surefire.cli.CommandLineOption; +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.TestListResolver; +import org.apache.maven.surefire.testset.TestRequest; +import static org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader.defaultRunOrder; import static org.apache.maven.surefire.cli.CommandLineOption.LOGGING_LEVEL_DEBUG; import static org.apache.maven.surefire.cli.CommandLineOption.REACTOR_FAIL_FAST; import static org.apache.maven.surefire.cli.CommandLineOption.SHOW_ERRORS; @@ -142,7 +152,7 @@ private ProviderConfiguration getProviderConfiguration() new TestRequest( Arrays.asList( getSuiteXmlFileStrings() ), getTestSourceDirectory(), new TestListResolver( "aUserRequestedTest#aUserRequestedTestMethod" )); - RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, null ); + RunOrderParameters runOrderParameters = new RunOrderParameters( defaultRunOrder(), null ); return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, true, reporterConfiguration, new TestArtifactInfo( "5.0", "ABC" ), testSuiteDefinition, new HashMap(), BooterDeserializerProviderConfigurationTest.aTestTyped, true, cli, 0, Shutdown.DEFAULT, 0 ); diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMapTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/RunEntryStatisticsMapTest.java similarity index 94% rename from maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMapTest.java rename to maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/RunEntryStatisticsMapTest.java index 5a171ab8bd..1c040c2a44 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMapTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/RunEntryStatisticsMapTest.java @@ -1,4 +1,4 @@ -package org.apache.maven.plugin.surefire.runorder; +package org.apache.maven.plugin.surefire.runorder.impl.statistics; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -24,6 +24,7 @@ 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; @@ -62,9 +63,9 @@ public void testPrioritizedFailureFirst() 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"; + String content = "0,17,testA(org.apache.maven.plugin.surefire.runorder.impl.statistics.RunEntryStatisticsMapTest$A)\n" + + "2,42,testB(org.apache.maven.plugin.surefire.runorder.impl.statistics.RunEntryStatisticsMapTest$B)\n" + + "1,100,testC(org.apache.maven.plugin.surefire.runorder.impl.statistics.RunEntryStatisticsMapTest$C)\n"; return new StringReader( content ); } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java index aec256dc4c..568d028ac8 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java @@ -34,7 +34,7 @@ import org.apache.maven.plugin.surefire.report.DefaultReporterFactoryTest; import org.apache.maven.plugin.surefire.report.StatelessXmlReporterTest; import org.apache.maven.plugin.surefire.report.WrappedReportEntryTest; -import org.apache.maven.plugin.surefire.runorder.RunEntryStatisticsMapTest; +import org.apache.maven.plugin.surefire.runorder.impl.statistics.RunEntryStatisticsMapTest; import org.apache.maven.plugin.surefire.util.DependenciesScannerTest; import org.apache.maven.plugin.surefire.util.DirectoryScannerTest; import org.apache.maven.plugin.surefire.util.SpecificFileFilterTest; diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/StringUtil.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/StringUtil.java new file mode 100644 index 0000000000..9a2165bd2f --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/StringUtil.java @@ -0,0 +1,93 @@ +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 org.apache.maven.plugin.surefire.runorder.api.RunOrder; + +/** + * @author Dipak Pawar + */ +public class StringUtil +{ + + public static String joins( RunOrder[] runOrders ) + { + StringJoiner stringJoiner = new StringJoiner( "," ); + + for ( RunOrder runOrder : runOrders ) + { + final String runOrderName = runOrder.getName(); + + if ( runOrderName != null ) + { + stringJoiner.add( runOrderName ); + } + } + + return stringJoiner.toString(); + } + + static class StringJoiner + { + private final String delimiter; + private StringBuilder value; + + StringJoiner( CharSequence delimiter ) + { + this.delimiter = delimiter.toString(); + } + + public String toString() + { + if ( this.value == null ) + { + return ""; + } + else + { + int initialLength = this.value.length(); + String result = this.value.toString(); + this.value.setLength( initialLength ); + return result; + } + } + + public StringJoiner add( CharSequence newElement ) + { + this.prepareBuilder().append( newElement ); + return this; + } + + private StringBuilder prepareBuilder() + { + if ( this.value != null ) + { + this.value.append( this.delimiter ); + } + else + { + this.value = new StringBuilder(); + } + + return this.value; + } + } + +} diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/api/RunOrder.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/api/RunOrder.java new file mode 100644 index 0000000000..f2f00e2452 --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/api/RunOrder.java @@ -0,0 +1,86 @@ +package org.apache.maven.plugin.surefire.runorder.api; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.surefire.testset.RunOrderParameters; + +import java.util.Collection; +import java.util.List; + +/** + * Interface to be implemented to create RunOrder. + *

+ * How to create your RunOrder? + *

+ * {@code
+ * public class YourRunOrder implements RunOrder
+ * {
+ *
+ *  @Override
+ *  public String getName()
+ *  {
+ *   return "runOrderName";
+ *  }
+ *
+ *  @Override
+ *  public List<Class<?>> orderTestClasses( Collection<Class<?>> classes,
+ *  RunOrderParameters runOrderParameters, int threadCount )
+ *  {
+ *   return new ArrayList<Class<?>>( classes ); // Add your logic for ordering test classes
+ *  }
+ * }
+ * }
+ * 
+ * + *

+ * How to load it during surefire execution? + *

+ * In your implementation of RunOrderProvider, add your instance of RunOrder to the list of RunOrder instances + * using {@link org.apache.maven.plugin.surefire.runorder.spi.RunOrderProvider#getRunOrders()}. + * + * @author Dipak Pawar + */ +public interface RunOrder +{ + + /** + * Gives name of RunOrder. + *
+ * Used to get respective instance of RunOrder from available RunOrder instances by + * comparing name of RunOrder. + * + * @return String + */ + String getName(); + + /** + * Orders testClasses as per runOrder. + * + * @param testClasses + * Collection of all test classes which are passed to given surefire run. + * @param runOrderParameters instance of RunOrderParameters containing runOrders, + * runStatisticsFile and map containing properties if any. + * + * @param threadCount number of threads to allocate for this execution. + * @return List of Test Classes + */ + List> orderTestClasses( Collection> testClasses, RunOrderParameters runOrderParameters, + int threadCount ); +} diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/RunOrderCalculator.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/api/RunOrderCalculator.java similarity index 89% rename from surefire-api/src/main/java/org/apache/maven/surefire/util/RunOrderCalculator.java rename to surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/api/RunOrderCalculator.java index bdbc48b790..4f45cde185 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/util/RunOrderCalculator.java +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/api/RunOrderCalculator.java @@ -1,4 +1,4 @@ -package org.apache.maven.surefire.util; +package org.apache.maven.plugin.surefire.runorder.api; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -19,6 +19,8 @@ * under the License. */ +import org.apache.maven.surefire.util.TestsToRun; + /** * @author Kristian Rosenvold */ diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/DefaultRunOrderCalculator.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/DefaultRunOrderCalculator.java new file mode 100644 index 0000000000..05ee4aca00 --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/DefaultRunOrderCalculator.java @@ -0,0 +1,73 @@ +package org.apache.maven.plugin.surefire.runorder.impl; + +/* + * 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.Collection; +import java.util.LinkedHashSet; +import java.util.List; +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; +import org.apache.maven.plugin.surefire.runorder.api.RunOrderCalculator; +import org.apache.maven.surefire.testset.RunOrderParameters; +import org.apache.maven.surefire.util.TestsToRun; + +/** + * Applies the final runorder of the tests + * + * @author Kristian Rosenvold + */ +public class DefaultRunOrderCalculator + implements RunOrderCalculator +{ + private final RunOrder[] runOrders; + + private final RunOrderParameters runOrderParameters; + + private final int threadCount; + + public DefaultRunOrderCalculator( RunOrderParameters runOrderParameters, int threadCount ) + { + this.runOrderParameters = runOrderParameters; + this.runOrders = runOrderParameters.getRunOrders(); + this.threadCount = threadCount; + } + + @Override + @SuppressWarnings( "checkstyle:magicnumber" ) + public TestsToRun orderTestClasses( TestsToRun scannedClasses ) + { + if ( runOrders == null || runOrders.length == 0 ) + { + return scannedClasses; + } + + List> testClasses = new ArrayList>( 512 ); + + for ( Class scannedClass : scannedClasses ) + { + testClasses.add( scannedClass ); + } + + final Collection> classes = runOrders[0].orderTestClasses( testClasses, runOrderParameters, + threadCount ); + + return new TestsToRun( new LinkedHashSet>( classes ) ); + } +} diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/DefaultRunOrderProvider.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/DefaultRunOrderProvider.java new file mode 100644 index 0000000000..dab49019e2 --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/DefaultRunOrderProvider.java @@ -0,0 +1,71 @@ +package org.apache.maven.plugin.surefire.runorder.impl; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; +import org.apache.maven.plugin.surefire.runorder.api.RunOrderCalculator; +import org.apache.maven.plugin.surefire.runorder.spi.RunOrderProvider; +import org.apache.maven.surefire.testset.RunOrderParameters; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.ALPHABETICAL; +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.BALANCED; +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.FAILEDFIRST; +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.FILESYSTEM; +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.HOURLY; +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.RANDOM; +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.REVERSE_ALPHABETICAL; + +/** + * Provides Default implementation of RunOrderProvider for Surefire. + * + * @author Dipak Pawar + */ +public class DefaultRunOrderProvider implements RunOrderProvider +{ + + @Override + public Collection getRunOrders() + { + return Arrays.asList( ALPHABETICAL, FILESYSTEM, HOURLY, + RANDOM, REVERSE_ALPHABETICAL, BALANCED, FAILEDFIRST ); + } + + @Override + public Integer priority() + { + return 0; + } + + @Override + public RunOrderCalculator createRunOrderCalculator( RunOrderParameters runOrderParameters, int threadCount ) + { + return new DefaultRunOrderCalculator( runOrderParameters, threadCount ); + } + + @Override + public Collection defaultRunOrder() + { + return Collections.singletonList( FILESYSTEM ); + } +} diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/PriorityComparator.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/PriorityComparator.java new file mode 100644 index 0000000000..f567779ff4 --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/PriorityComparator.java @@ -0,0 +1,39 @@ +package org.apache.maven.plugin.surefire.runorder.impl; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.surefire.runorder.spi.RunOrderProvider; + +import java.util.Comparator; + +class PriorityComparator +{ + static Comparator byPriority() + { + return new Comparator() + { + @Override + public int compare( RunOrderProvider runOrderProvider1, RunOrderProvider runOrderProvider2 ) + { + return runOrderProvider1.priority().compareTo( runOrderProvider2.priority() ); + } + }; + } +} diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/RunOrderLoader.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/RunOrderLoader.java new file mode 100644 index 0000000000..2c77b2e2fd --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/RunOrderLoader.java @@ -0,0 +1,155 @@ +package org.apache.maven.plugin.surefire.runorder.impl; + +/* + * 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.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.ServiceLoader; +import java.util.Set; + +import org.apache.maven.plugin.surefire.runorder.StringUtil; +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; +import org.apache.maven.plugin.surefire.runorder.spi.RunOrderProvider; + +import static java.lang.Thread.currentThread; +import static org.apache.maven.plugin.surefire.runorder.impl.PriorityComparator.byPriority; + +/** + * RunOrderLoader gives you instances of RunOrder provided by implementation of + * RunOrderProvider found on classpath which is used to order test classes. + * + * @author Dipak Pawar + */ +public class RunOrderLoader +{ + + private static RunOrderProvider runOrderProvider; + + /** + * Returns the specified RunOrders + * + * @param values the runorder names in comma separated format + * @return the instances of RunOrder implementation, never null + */ + public static RunOrder[] runOrdersOf( String values ) + { + List result = new ArrayList(); + if ( values != null ) + { + final RunOrder[] runOrders = values(); + final String[] runOrderValues = values.split( "\\s*,\\s*" ); + for ( String runOrder : runOrderValues ) + { + result.add( valueOf( runOrder, runOrders ) ); + } + } + return result.toArray( new RunOrder[result.size()] ); + } + + /** + * Scans classpath for implementation of RunOrderProvider with higher priority + * If not found, default RunOrderProvider {@link DefaultRunOrderProvider} is used. + * + * @return An implementation of RunOrderProvider + */ + public static RunOrderProvider getRunOrderProvider() + { + if ( runOrderProvider == null ) + { + final ServiceLoader runOrderProviderLoader = + ServiceLoader.load( RunOrderProvider.class, currentThread().getContextClassLoader() ); + + final Set implementations = new HashSet(); + + for ( RunOrderProvider providerLoader : runOrderProviderLoader ) + { + implementations.add( providerLoader ); + } + + if ( implementations.isEmpty() ) + { + RunOrderLoader.runOrderProvider = new DefaultRunOrderProvider(); + } + else + { + RunOrderLoader.runOrderProvider = Collections.max( implementations, byPriority() ); + } + } + + return runOrderProvider; + } + + public static RunOrder[] asArray( Collection runOrders ) + { + return runOrders.toArray( new RunOrder[runOrders.size()] ); + } + + public static RunOrder[] defaultRunOrder() + { + return asArray( getRunOrderProvider().defaultRunOrder() ); + } + + public static String asString( RunOrder[] runOrders ) + { + return StringUtil.joins( runOrders ); + } + + public static String asString( Collection runOrders ) + { + return asString( runOrders.toArray( new RunOrder[runOrders.size()] ) ); + } + + private static RunOrder valueOf( String name, RunOrder[] runOrders ) + { + if ( name == null ) + { + return null; + } + + for ( RunOrder runOrder : runOrders ) + { + if ( name.equalsIgnoreCase( runOrder.getName() ) ) + { + return runOrder; + } + } + + String errorMessage = createMessageForMissingRunOrder( name ); + throw new IllegalArgumentException( errorMessage ); + } + + private static String createMessageForMissingRunOrder( String name ) + { + return "There's no RunOrder with the name " + + name + + ". Please use one of the following RunOrders: " + + StringUtil.joins( values() ) + '.'; + } + + private static RunOrder[] values() + { + final Collection runOrders = getRunOrderProvider().getRunOrders(); + + return runOrders.toArray( new RunOrder[runOrders.size()] ); + } +} diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/PrioritizedTest.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/PrioritizedTest.java similarity index 93% rename from surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/PrioritizedTest.java rename to surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/PrioritizedTest.java index 280d71060e..00603c015c 100644 --- a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/PrioritizedTest.java +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/PrioritizedTest.java @@ -1,4 +1,4 @@ -package org.apache.maven.plugin.surefire.runorder; +package org.apache.maven.plugin.surefire.runorder.impl.statistics; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -22,7 +22,7 @@ /** * @author Kristian Rosenvold */ -public class PrioritizedTest +class PrioritizedTest { private final Class clazz; diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/Priority.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/Priority.java similarity index 96% rename from surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/Priority.java rename to surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/Priority.java index 93784fa1f4..dcde315136 100644 --- a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/Priority.java +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/Priority.java @@ -1,4 +1,4 @@ -package org.apache.maven.plugin.surefire.runorder; +package org.apache.maven.plugin.surefire.runorder.impl.statistics; /* * Licensed to the Apache Software Foundation (ASF) under one diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatistics.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/RunEntryStatistics.java similarity index 97% rename from surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatistics.java rename to surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/RunEntryStatistics.java index 7c794dc7fa..544e5febe3 100644 --- a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatistics.java +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/RunEntryStatistics.java @@ -1,4 +1,4 @@ -package org.apache.maven.plugin.surefire.runorder; +package org.apache.maven.plugin.surefire.runorder.impl.statistics; /* * Licensed to the Apache Software Foundation (ASF) under one diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/RunEntryStatisticsMap.java similarity index 97% rename from surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java rename to surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/RunEntryStatisticsMap.java index dc871a569e..71d6c13bfe 100644 --- a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/RunEntryStatisticsMap.java @@ -1,4 +1,4 @@ -package org.apache.maven.plugin.surefire.runorder; +package org.apache.maven.plugin.surefire.runorder.impl.statistics; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -40,8 +40,8 @@ import java.util.regex.Pattern; import static java.util.Collections.sort; -import static org.apache.maven.plugin.surefire.runorder.RunEntryStatistics.fromReportEntry; -import static org.apache.maven.plugin.surefire.runorder.RunEntryStatistics.fromString; +import static org.apache.maven.plugin.surefire.runorder.impl.statistics.RunEntryStatistics.fromReportEntry; +import static org.apache.maven.plugin.surefire.runorder.impl.statistics.RunEntryStatistics.fromString; /** * @author Kristian Rosenvold diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionScheduler.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/ThreadedExecutionScheduler.java similarity index 97% rename from surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionScheduler.java rename to surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/ThreadedExecutionScheduler.java index 09ea1221d7..3ed17e5df8 100644 --- a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionScheduler.java +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/ThreadedExecutionScheduler.java @@ -1,4 +1,4 @@ -package org.apache.maven.plugin.surefire.runorder; +package org.apache.maven.plugin.surefire.runorder.impl.statistics; /* * Licensed to the Apache Software Foundation (ASF) under one diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/AlphabeticalRunOrder.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/AlphabeticalRunOrder.java new file mode 100644 index 0000000000..6ad9be8281 --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/AlphabeticalRunOrder.java @@ -0,0 +1,71 @@ +package org.apache.maven.plugin.surefire.runorder.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; +import org.apache.maven.surefire.testset.RunOrderParameters; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * @author Dipak Pawar + */ +public class AlphabeticalRunOrder implements RunOrder +{ + + @Override + public String getName() + { + return "alphabetical"; + } + + @Override + public List> orderTestClasses( Collection> scannedClasses, + RunOrderParameters runOrderParameters, int threadCount ) + { + final RunOrder[] runOrders = runOrderParameters.getRunOrders(); + final List> testClasses = new ArrayList>( scannedClasses ); + + if ( runOrders.length == 0 ) + { + return testClasses; + } + + Collections.sort( testClasses, alphabetically() ); + + return testClasses; + } + + public Comparator alphabetically() + { + return new Comparator() + { + @Override + public int compare( Class class1, Class class2 ) + { + return class1.getName().compareTo( class2.getName() ); + } + }; + } +} diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/BalancedRunOrder.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/BalancedRunOrder.java new file mode 100644 index 0000000000..54520a3177 --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/BalancedRunOrder.java @@ -0,0 +1,56 @@ +package org.apache.maven.plugin.surefire.runorder.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.surefire.runorder.impl.statistics.RunEntryStatisticsMap; +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; +import org.apache.maven.surefire.testset.RunOrderParameters; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author Dipak Pawar + */ +public class BalancedRunOrder implements RunOrder +{ + + @Override + public String getName() + { + return "balanced"; + } + + @Override + public List> orderTestClasses( Collection> scannedClasses, + RunOrderParameters runOrderParameters, int threadCount ) + { + final List> testClasses = new ArrayList>( scannedClasses ); + + RunEntryStatisticsMap stat = RunEntryStatisticsMap.fromFile( runOrderParameters.getRunStatisticsFile() ); + List> prioritized = stat.getPrioritizedTestsClassRunTime( testClasses, + threadCount ); + testClasses.clear(); + testClasses.addAll( prioritized ); + + return testClasses; + } +} diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/FailedFirstRunOrder.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/FailedFirstRunOrder.java new file mode 100644 index 0000000000..670dc1d197 --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/FailedFirstRunOrder.java @@ -0,0 +1,55 @@ +package org.apache.maven.plugin.surefire.runorder.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.surefire.runorder.impl.statistics.RunEntryStatisticsMap; +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; +import org.apache.maven.surefire.testset.RunOrderParameters; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author Dipak Pawar + */ +public class FailedFirstRunOrder implements RunOrder +{ + + @Override + public String getName() + { + return "failedfirst"; + } + + @Override + public List> orderTestClasses( Collection> scannedClasses, + RunOrderParameters runOrderParameters, int threadCount ) + { + final List> testClasses = new ArrayList>( scannedClasses ); + + RunEntryStatisticsMap stat = RunEntryStatisticsMap.fromFile( runOrderParameters.getRunStatisticsFile() ); + List> prioritized = stat.getPrioritizedTestsByFailureFirst( testClasses ); + testClasses.clear(); + testClasses.addAll( prioritized ); + + return testClasses; + } +} diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/FileSystemRunOrder.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/FileSystemRunOrder.java new file mode 100644 index 0000000000..fb4eb27296 --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/FileSystemRunOrder.java @@ -0,0 +1,48 @@ +package org.apache.maven.plugin.surefire.runorder.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; +import org.apache.maven.surefire.testset.RunOrderParameters; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author Dipak Pawar + */ +public class FileSystemRunOrder implements RunOrder +{ + + @Override + public String getName() + { + return "filesystem"; + } + + @Override + public List> orderTestClasses( Collection> classes, + RunOrderParameters runOrderParameters, int threadCount ) + { + return new ArrayList>( classes ); + } + +} diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/HourlyRunOrder.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/HourlyRunOrder.java new file mode 100644 index 0000000000..3e662f5216 --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/HourlyRunOrder.java @@ -0,0 +1,62 @@ +package org.apache.maven.plugin.surefire.runorder.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; +import org.apache.maven.surefire.testset.RunOrderParameters; + +import java.util.Calendar; +import java.util.Collection; +import java.util.List; + +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.ALPHABETICAL; +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.REVERSE_ALPHABETICAL; + + +/** + * RunOrder to order test classes alphabetical on even hours, + * reverse alphabetical on odd hours. + * + * @author Dipak Pawar + */ +public class HourlyRunOrder implements RunOrder +{ + + @Override + public String getName() + { + return "hourly"; + } + + @Override + public List> orderTestClasses( Collection> scannedClasses, + RunOrderParameters runOrderParameters, int threadCount ) + { + final int hour = Calendar.getInstance().get( Calendar.HOUR_OF_DAY ); + if ( hour % 2 == 0 ) + { + return ALPHABETICAL.orderTestClasses( scannedClasses, runOrderParameters, threadCount ); + } + else + { + return REVERSE_ALPHABETICAL.orderTestClasses( scannedClasses, runOrderParameters, threadCount ); + } + } +} diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/RandomRunOrder.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/RandomRunOrder.java new file mode 100644 index 0000000000..c78e4af548 --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/RandomRunOrder.java @@ -0,0 +1,52 @@ +package org.apache.maven.plugin.surefire.runorder.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; +import org.apache.maven.surefire.testset.RunOrderParameters; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * @author Dipak Pawar + */ +public class RandomRunOrder implements RunOrder +{ + + @Override + public String getName() + { + return "random"; + } + + @Override + public List> orderTestClasses( Collection> scannedClasses, + RunOrderParameters runOrderParameters, int threadCount ) + { + final List> testClasses = new ArrayList>( scannedClasses ); + + Collections.shuffle( testClasses ); + + return testClasses; + } +} diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/ReverseAlphabeticalRunOrder.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/ReverseAlphabeticalRunOrder.java new file mode 100644 index 0000000000..411df8e583 --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/ReverseAlphabeticalRunOrder.java @@ -0,0 +1,68 @@ +package org.apache.maven.plugin.surefire.runorder.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; +import org.apache.maven.surefire.testset.RunOrderParameters; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.ALPHABETICAL; + +/** + * @author Dipak Pawar + */ +public class ReverseAlphabeticalRunOrder implements RunOrder +{ + + @Override + public String getName() + { + return "reversealphabetical"; + } + + @Override + public List> orderTestClasses( Collection> scannedClasses, + RunOrderParameters runOrderParameters, int threadCount ) + { + final RunOrder[] runOrders = runOrderParameters.getRunOrders(); + final List> testClasses = new ArrayList>( scannedClasses ); + + if ( runOrders.length == 0 ) + { + return testClasses; + } + + Collections.sort( testClasses, reverseAlphabetically() ); + + return testClasses; + } + + private Comparator reverseAlphabetically() + { + final AlphabeticalRunOrder runOrder = (AlphabeticalRunOrder) ALPHABETICAL; + + return Collections.reverseOrder( runOrder.alphabetically() ); + } +} diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/RunOrderFactory.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/RunOrderFactory.java new file mode 100644 index 0000000000..8a5ebf123b --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/model/RunOrderFactory.java @@ -0,0 +1,43 @@ +package org.apache.maven.plugin.surefire.runorder.model; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; + + +/** + * @author Dipak Pawar + */ +public class RunOrderFactory +{ + public static final RunOrder ALPHABETICAL = new AlphabeticalRunOrder(); + + public static final RunOrder BALANCED = new BalancedRunOrder(); + + public static final RunOrder FAILEDFIRST = new FailedFirstRunOrder(); + + public static final RunOrder FILESYSTEM = new FileSystemRunOrder(); + + public static final RunOrder HOURLY = new HourlyRunOrder(); + + public static final RunOrder RANDOM = new RandomRunOrder(); + + public static final RunOrder REVERSE_ALPHABETICAL = new ReverseAlphabeticalRunOrder(); +} diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/spi/RunOrderProvider.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/spi/RunOrderProvider.java new file mode 100644 index 0000000000..8f4b72460c --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/spi/RunOrderProvider.java @@ -0,0 +1,101 @@ +package org.apache.maven.plugin.surefire.runorder.spi; + +/* + * 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.Collection; +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; +import org.apache.maven.plugin.surefire.runorder.api.RunOrderCalculator; +import org.apache.maven.surefire.testset.RunOrderParameters; + +/** + * This is the service provider interface (SPI) to override default runOrders provided by surefire. + *

+ * Packaging of RunOrderProvider Implementations + *

+ * Implementations of these run order provider are packaged using the Java Extension Mechanism as installed extensions. + * A provider identifies itself with a provider-configuration file in the resource directory META-INF/services, + * using the fully qualified provider interface class name as the file name. + *

+ * For example, an implementation of the RunOrderProvider class should take the form of a jar file which contains + * the file: + *

+ * META-INF/services/org.apache.maven.plugin.surefire.runorder.spi.RunOrderProvider + *

+ * And the file org.apache.maven.plugin.surefire.runorder.spi.RunOrderProvider should have a line such as: + *

+ com.surefire.YourRunOrderProviderImpl + *

+ * which is the fully qualified class name of the class implementing RunOrderProvider + *

+ * Loading RunOrder Providers + *

+ * RunOrder providers are loaded using + * {@link org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader#getRunOrderProvider()} when needed. + * + * If a more than one implementation of provider is present on classpath, implementation with greater priority is used + * others are ignored. + * + * If no implementation of provider is on classpath, default implementation of RunOrderProvider is used. + * + * see {@link org.apache.maven.plugin.surefire.runorder.impl.DefaultRunOrderProvider }). + * + * + * @author Dipak Pawar + */ +public interface RunOrderProvider +{ + + /** + * Gives all supported RunOrder Implementations to use. + * + * @return A list of RunOrder Implementation. + * + * see {@link RunOrder} + */ + Collection getRunOrders(); + + /** + * Provides priority for RunOrderProvider + * + * @return An integer + */ + Integer priority(); + + /** + * Creates RunOrderCalculator instance for ordering testClasses. + * + * @param runOrderParameters instance of RunOrderParameters containing runOrders, + * runStatisticsFile and map containing properties if any. + * @param threadCount number of threads to allocate for this execution. + * + * @return An instance of RunOrderCalculator. + */ + RunOrderCalculator createRunOrderCalculator( RunOrderParameters runOrderParameters, int threadCount ); + + /** + * Gives RunOrder Implementations to use by default if no runOrder is specified in surefire configuration. + * + * All RunOrder Implementations using as default should be already provided using + * {@link RunOrderProvider#getRunOrders()} + * + * @return A list of RunOrder Implementation. + */ + Collection defaultRunOrder(); +} diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java index 2b329ee5db..7a98734ad6 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java @@ -19,6 +19,11 @@ * under the License. */ +import java.io.PrintStream; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import org.apache.maven.plugin.surefire.runorder.api.RunOrderCalculator; import org.apache.maven.surefire.cli.CommandLineOption; import org.apache.maven.surefire.providerapi.ProviderParameters; import org.apache.maven.surefire.report.ConsoleStream; @@ -30,18 +35,12 @@ import org.apache.maven.surefire.testset.TestArtifactInfo; import org.apache.maven.surefire.testset.TestRequest; import org.apache.maven.surefire.util.DefaultDirectoryScanner; -import org.apache.maven.surefire.util.DefaultRunOrderCalculator; import org.apache.maven.surefire.util.DefaultScanResult; import org.apache.maven.surefire.util.DirectoryScanner; -import org.apache.maven.surefire.util.RunOrderCalculator; import org.apache.maven.surefire.util.ScanResult; -import java.io.PrintStream; -import java.util.Collections; -import java.util.List; -import java.util.Map; - import static java.util.Collections.emptyList; +import static org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader.getRunOrderProvider; /** * @author Kristian Rosenvold @@ -111,8 +110,14 @@ private int getThreadCount() @Override public RunOrderCalculator getRunOrderCalculator() { - return directoryScannerParameters == null - ? null : new DefaultRunOrderCalculator( runOrderParameters, getThreadCount() ); + if ( directoryScannerParameters == null ) + { + return null; + } + else + { + return getRunOrderProvider().createRunOrderCalculator( runOrderParameters, getThreadCount() ); + } } @Override @@ -204,6 +209,7 @@ public void setTestArtifactInfo( TestArtifactInfo testArtifactInfo ) @Override public void setRunOrderParameters( RunOrderParameters runOrderParameters ) { + runOrderParameters.setLogger( getConsoleLogger() ); this.runOrderParameters = runOrderParameters; } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java index 097a3fa7a4..fb3c26a031 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java @@ -27,9 +27,10 @@ import java.util.Collection; import java.util.List; import java.util.Map; - +import javax.annotation.Nonnull; import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; import org.apache.maven.plugin.surefire.log.api.ConsoleLoggerDecorator; +import org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader; import org.apache.maven.surefire.cli.CommandLineOption; import org.apache.maven.surefire.providerapi.ProviderParameters; import org.apache.maven.surefire.report.ReporterConfiguration; @@ -40,20 +41,16 @@ import org.apache.maven.surefire.testset.TestArtifactInfo; import org.apache.maven.surefire.testset.TestListResolver; import org.apache.maven.surefire.testset.TestRequest; -import org.apache.maven.surefire.util.RunOrder; import org.apache.maven.surefire.util.SurefireReflectionException; -import javax.annotation.Nonnull; - import static java.util.Collections.checkedList; - import static org.apache.maven.surefire.util.ReflectionUtils.getConstructor; import static org.apache.maven.surefire.util.ReflectionUtils.getMethod; +import static org.apache.maven.surefire.util.ReflectionUtils.instantiateOneArg; +import static org.apache.maven.surefire.util.ReflectionUtils.instantiateTwoArgs; import static org.apache.maven.surefire.util.ReflectionUtils.invokeGetter; import static org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray; -import static org.apache.maven.surefire.util.ReflectionUtils.instantiateOneArg; import static org.apache.maven.surefire.util.ReflectionUtils.invokeSetter; -import static org.apache.maven.surefire.util.ReflectionUtils.instantiateTwoArgs; import static org.apache.maven.surefire.util.ReflectionUtils.newInstance; /** @@ -221,7 +218,7 @@ Object createDirectoryScannerParameters( DirectoryScannerParameters directorySca directoryScannerParameters.getExcludes(), directoryScannerParameters.getSpecificTests(), directoryScannerParameters.isFailIfNoTests(), - RunOrder.asString( directoryScannerParameters.getRunOrder() ) ); + RunOrderLoader.asString( directoryScannerParameters.getRunOrders() ) ); } @@ -235,7 +232,8 @@ Object createRunOrderParameters( RunOrderParameters runOrderParameters ) Class[] arguments = { String.class, File.class }; Constructor constructor = getConstructor( this.runOrderParameters, arguments ); File runStatisticsFile = runOrderParameters.getRunStatisticsFile(); - return newInstance( constructor, RunOrder.asString( runOrderParameters.getRunOrder() ), runStatisticsFile ); + return newInstance( constructor, RunOrderLoader.asString( runOrderParameters.getRunOrders() ), + runStatisticsFile ); } Object createTestArtifactInfo( TestArtifactInfo testArtifactInfo ) diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java b/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java index b487f06589..b061b51c93 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java @@ -28,7 +28,7 @@ import org.apache.maven.surefire.testset.TestArtifactInfo; import org.apache.maven.surefire.testset.TestRequest; import org.apache.maven.surefire.util.DirectoryScanner; -import org.apache.maven.surefire.util.RunOrderCalculator; +import org.apache.maven.plugin.surefire.runorder.api.RunOrderCalculator; import org.apache.maven.surefire.util.ScanResult; import java.util.List; diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/testset/DirectoryScannerParameters.java b/surefire-api/src/main/java/org/apache/maven/surefire/testset/DirectoryScannerParameters.java index 36f4b2e7c0..caa02a65df 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/testset/DirectoryScannerParameters.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/testset/DirectoryScannerParameters.java @@ -21,7 +21,10 @@ import java.io.File; import java.util.List; -import org.apache.maven.surefire.util.RunOrder; +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; +import org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader; + +import static org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader.defaultRunOrder; /** * @author Kristian Rosenvold @@ -41,17 +44,17 @@ public class DirectoryScannerParameters private final boolean failIfNoTests; - private final RunOrder[] runOrder; + private final RunOrder[] runOrders; private DirectoryScannerParameters( File testClassesDirectory, List includes, List excludes, - List specificTests, boolean failIfNoTests, RunOrder[] runOrder ) + List specificTests, boolean failIfNoTests, RunOrder[] runOrders ) { this.testClassesDirectory = testClassesDirectory; this.includes = includes; this.excludes = excludes; this.specificTests = specificTests; this.failIfNoTests = failIfNoTests; - this.runOrder = runOrder; + this.runOrders = runOrders; } public DirectoryScannerParameters( File testClassesDirectory, @Deprecated List includes, @@ -59,7 +62,7 @@ public DirectoryScannerParameters( File testClassesDirectory, @Deprecated List runOrderProperties; - private File runStatisticsFile; + public RunOrderParameters( RunOrder[] runOrders, File runStatisticsFile ) + { + this.runOrders = runOrders; + this.runStatisticsFile = runStatisticsFile; + } - public RunOrderParameters( RunOrder[] runOrder, File runStatisticsFile ) + public RunOrderParameters( Collection runOrders, File runStatisticsFile ) { - this.runOrder = runOrder; + this.runOrders = asArray( runOrders ); this.runStatisticsFile = runStatisticsFile; } - public RunOrderParameters( String runOrder, File runStatisticsFile ) + public RunOrderParameters( String runOrders, File runStatisticsFile ) { - this.runOrder = runOrder == null ? RunOrder.DEFAULT : RunOrder.valueOfMulti( runOrder ); + this.runOrders = runOrders == null ? defaultRunOrder() : RunOrderLoader.runOrdersOf( runOrders ); this.runStatisticsFile = runStatisticsFile; } public static RunOrderParameters alphabetical() { - return new RunOrderParameters( new RunOrder[]{ RunOrder.ALPHABETICAL }, null ); + return new RunOrderParameters( new RunOrder[]{ ALPHABETICAL }, null ); } - public RunOrder[] getRunOrder() + public RunOrder[] getRunOrders() { - return runOrder; + return runOrders; } public File getRunStatisticsFile() @@ -58,4 +77,23 @@ public File getRunStatisticsFile() return runStatisticsFile; } + public void setRunOrderProperties( Map runOrderProperties ) + { + this.runOrderProperties = runOrderProperties; + } + + public Map getRunOrderProperties() + { + return runOrderProperties; + } + + public ConsoleStream getLogger() + { + return logger; + } + + public void setLogger( ConsoleStream logger ) + { + this.logger = logger; + } } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultRunOrderCalculator.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultRunOrderCalculator.java deleted file mode 100644 index dea10a69a5..0000000000 --- a/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultRunOrderCalculator.java +++ /dev/null @@ -1,143 +0,0 @@ -package org.apache.maven.surefire.util; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import org.apache.maven.plugin.surefire.runorder.RunEntryStatisticsMap; -import org.apache.maven.surefire.testset.RunOrderParameters; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedHashSet; -import java.util.List; - -/** - * Applies the final runorder of the tests - * - * @author Kristian Rosenvold - */ -public class DefaultRunOrderCalculator - implements RunOrderCalculator -{ - private final Comparator sortOrder; - - private final RunOrder[] runOrder; - - private final RunOrderParameters runOrderParameters; - - private final int threadCount; - - public DefaultRunOrderCalculator( RunOrderParameters runOrderParameters, int threadCount ) - { - this.runOrderParameters = runOrderParameters; - this.threadCount = threadCount; - this.runOrder = runOrderParameters.getRunOrder(); - this.sortOrder = this.runOrder.length > 0 ? getSortOrderComparator( this.runOrder[0] ) : null; - } - - @Override - @SuppressWarnings( "checkstyle:magicnumber" ) - public TestsToRun orderTestClasses( TestsToRun scannedClasses ) - { - List> result = new ArrayList>( 512 ); - - for ( Class scannedClass : scannedClasses ) - { - result.add( scannedClass ); - } - - orderTestClasses( result, runOrder.length != 0 ? runOrder[0] : null ); - return new TestsToRun( new LinkedHashSet>( result ) ); - } - - private void orderTestClasses( List> testClasses, RunOrder runOrder ) - { - if ( RunOrder.RANDOM.equals( runOrder ) ) - { - Collections.shuffle( testClasses ); - } - else if ( RunOrder.FAILEDFIRST.equals( runOrder ) ) - { - RunEntryStatisticsMap stat = RunEntryStatisticsMap.fromFile( runOrderParameters.getRunStatisticsFile() ); - List> prioritized = stat.getPrioritizedTestsByFailureFirst( testClasses ); - testClasses.clear(); - testClasses.addAll( prioritized ); - - } - else if ( RunOrder.BALANCED.equals( runOrder ) ) - { - RunEntryStatisticsMap stat = RunEntryStatisticsMap.fromFile( runOrderParameters.getRunStatisticsFile() ); - List> prioritized = stat.getPrioritizedTestsClassRunTime( testClasses, threadCount ); - testClasses.clear(); - testClasses.addAll( prioritized ); - - } - else if ( sortOrder != null ) - { - Collections.sort( testClasses, sortOrder ); - } - } - - private Comparator getSortOrderComparator( RunOrder runOrder ) - { - if ( RunOrder.ALPHABETICAL.equals( runOrder ) ) - { - return getAlphabeticalComparator(); - } - else if ( RunOrder.REVERSE_ALPHABETICAL.equals( runOrder ) ) - { - return getReverseAlphabeticalComparator(); - } - else if ( RunOrder.HOURLY.equals( runOrder ) ) - { - final int hour = Calendar.getInstance().get( Calendar.HOUR_OF_DAY ); - return ( ( hour % 2 ) == 0 ) ? getAlphabeticalComparator() : getReverseAlphabeticalComparator(); - } - else - { - return null; - } - } - - private Comparator getReverseAlphabeticalComparator() - { - return new Comparator() - { - @Override - public int compare( Class o1, Class o2 ) - { - return o2.getName().compareTo( o1.getName() ); - } - }; - } - - private Comparator getAlphabeticalComparator() - { - return new Comparator() - { - @Override - public int compare( Class o1, Class o2 ) - { - return o1.getName().compareTo( o2.getName() ); - } - }; - } -} diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/RunOrder.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/RunOrder.java deleted file mode 100644 index 79c52357f2..0000000000 --- a/surefire-api/src/main/java/org/apache/maven/surefire/util/RunOrder.java +++ /dev/null @@ -1,151 +0,0 @@ -package org.apache.maven.surefire.util; - -/* - * 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; -import java.util.StringTokenizer; - -/** - * A RunOrder specifies the order in which the tests will be run. - * - * @author Stefan Birkner - */ -public class RunOrder -{ - public static final RunOrder ALPHABETICAL = new RunOrder( "alphabetical" ); - - public static final RunOrder FILESYSTEM = new RunOrder( "filesystem" ); - - public static final RunOrder HOURLY = new RunOrder( "hourly" ); - - public static final RunOrder RANDOM = new RunOrder( "random" ); - - public static final RunOrder REVERSE_ALPHABETICAL = new RunOrder( "reversealphabetical" ); - - public static final RunOrder BALANCED = new RunOrder( "balanced" ); - - public static final RunOrder FAILEDFIRST = new RunOrder( "failedfirst" ); - - public static final RunOrder[] DEFAULT = new RunOrder[]{ FILESYSTEM }; - - /** - * Returns the specified RunOrder - * - * @param values The runorder string value - * @return An array of RunOrder objects, never null - */ - public static RunOrder[] valueOfMulti( String values ) - { - List result = new ArrayList(); - if ( values != null ) - { - StringTokenizer stringTokenizer = new StringTokenizer( values, "," ); - while ( stringTokenizer.hasMoreTokens() ) - { - result.add( valueOf( stringTokenizer.nextToken() ) ); - } - } - return result.toArray( new RunOrder[result.size()] ); - } - - public static RunOrder valueOf( String name ) - { - if ( name == null ) - { - return null; - } - else - { - RunOrder[] runOrders = values(); - for ( RunOrder runOrder : runOrders ) - { - if ( runOrder.matches( name ) ) - { - return runOrder; - } - } - - String errorMessage = createMessageForMissingRunOrder( name ); - throw new IllegalArgumentException( errorMessage ); - } - } - - private static String createMessageForMissingRunOrder( String name ) - { - RunOrder[] runOrders = values(); - StringBuilder message = new StringBuilder( "There's no RunOrder with the name " ); - message.append( name ); - message.append( ". Please use one of the following RunOrders: " ); - for ( int i = 0; i < runOrders.length; i++ ) - { - if ( i != 0 ) - { - message.append( ", " ); - } - message.append( runOrders[i] ); - } - message.append( '.' ); - return message.toString(); - } - - private static RunOrder[] values() - { - return new RunOrder[]{ ALPHABETICAL, FILESYSTEM, HOURLY, RANDOM, REVERSE_ALPHABETICAL, BALANCED, FAILEDFIRST }; - } - - public static String asString( RunOrder[] runOrder ) - { - StringBuilder stringBuffer = new StringBuilder(); - for ( int i = 0; i < runOrder.length; i++ ) - { - stringBuffer.append( runOrder[i].name ); - if ( i < ( runOrder.length - 1 ) ) - { - stringBuffer.append( "," ); - } - } - return stringBuffer.toString(); - - } - - private final String name; - - private RunOrder( String name ) - { - this.name = name; - } - - private boolean matches( String anotherName ) - { - return name.equalsIgnoreCase( anotherName ); - } - - public String name() - { - return name; - } - - @Override - public String toString() - { - return name; - } -} \ No newline at end of file diff --git a/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java b/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java index 66cca64b82..4d4483a33e 100644 --- a/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java +++ b/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java @@ -21,7 +21,7 @@ import junit.framework.JUnit4TestAdapter; import junit.framework.Test; -import org.apache.maven.plugin.surefire.runorder.ThreadedExecutionSchedulerTest; +import org.apache.maven.plugin.surefire.runorder.impl.statistics.ThreadedExecutionSchedulerTest; import org.apache.maven.surefire.SpecificTestClassFilterTest; import org.apache.maven.surefire.booter.ForkingRunListenerTest; import org.apache.maven.surefire.booter.MasterProcessCommandTest; @@ -33,8 +33,8 @@ import org.apache.maven.surefire.testset.TestListResolverTest; import org.apache.maven.surefire.util.DefaultDirectoryScannerTest; import org.apache.maven.surefire.util.ReflectionUtilsTest; -import org.apache.maven.surefire.util.RunOrderCalculatorTest; -import org.apache.maven.surefire.util.RunOrderTest; +import org.apache.maven.plugin.surefire.runorder.api.RunOrderCalculatorTest; +import org.apache.maven.plugin.surefire.runorder.api.RunOrderTest; import org.apache.maven.surefire.util.ScanResultTest; import org.apache.maven.surefire.util.TestsToRunTest; import org.apache.maven.surefire.util.UrlUtilsTest; diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderCalculatorTest.java b/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/api/RunOrderCalculatorTest.java similarity index 90% rename from surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderCalculatorTest.java rename to surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/api/RunOrderCalculatorTest.java index 30a7560e53..82ab2ea684 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderCalculatorTest.java +++ b/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/api/RunOrderCalculatorTest.java @@ -1,4 +1,4 @@ -package org.apache.maven.surefire.util; +package org.apache.maven.plugin.surefire.runorder.api; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -21,9 +21,11 @@ import java.util.LinkedHashSet; import java.util.Set; +import org.apache.maven.plugin.surefire.runorder.impl.DefaultRunOrderCalculator; import org.apache.maven.surefire.testset.RunOrderParameters; import junit.framework.TestCase; +import org.apache.maven.surefire.util.TestsToRun; /** * @author Kristian Rosenvold diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderTest.java b/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/api/RunOrderTest.java similarity index 56% rename from surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderTest.java rename to surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/api/RunOrderTest.java index 13e5a43824..6807561cdf 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderTest.java +++ b/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/api/RunOrderTest.java @@ -1,4 +1,4 @@ -package org.apache.maven.surefire.util; +package org.apache.maven.plugin.surefire.runorder.api; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -20,43 +20,49 @@ */ import junit.framework.TestCase; +import org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader; + +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.ALPHABETICAL; +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.BALANCED; +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.FAILEDFIRST; +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.HOURLY; public class RunOrderTest extends TestCase { public void testShouldReturnRunOrderForLowerCaseName() { - assertEquals( RunOrder.HOURLY, RunOrder.valueOfMulti( "hourly" )[0] ); + assertEquals( HOURLY, RunOrderLoader.runOrdersOf( "hourly" )[0] ); } public void testMultiValue() { - final RunOrder[] hourlies = RunOrder.valueOfMulti( "failedfirst,balanced" ); - assertEquals( RunOrder.FAILEDFIRST, hourlies[0] ); - assertEquals( RunOrder.BALANCED, hourlies[1] ); + final RunOrder[] hourlies = RunOrderLoader.runOrdersOf( "failedfirst,balanced" ); + assertEquals( FAILEDFIRST, hourlies[0] ); + assertEquals( BALANCED, hourlies[1] ); } public void testAsString() { - RunOrder[] orders = new RunOrder[]{ RunOrder.FAILEDFIRST, RunOrder.ALPHABETICAL }; - assertEquals( "failedfirst,alphabetical", RunOrder.asString( orders ) ); + RunOrder[] orders = new RunOrder[]{ FAILEDFIRST, ALPHABETICAL }; + assertEquals( "failedfirst,alphabetical", RunOrderLoader.asString( orders ) ); } public void testShouldReturnRunOrderForUpperCaseName() { - assertEquals( RunOrder.HOURLY, RunOrder.valueOfMulti( "HOURLY" )[0] ); + assertEquals( HOURLY, RunOrderLoader.runOrdersOf( "HOURLY" )[0] ); } public void testShouldReturnNullForNullName() { - assertTrue( RunOrder.valueOfMulti( null ).length == 0 ); + assertTrue( RunOrderLoader.runOrdersOf( null ).length == 0 ); } public void testShouldThrowExceptionForInvalidName() { try { - RunOrder.valueOfMulti( "arbitraryName" ); + RunOrderLoader.runOrdersOf( "arbitraryName" ); fail( "IllegalArgumentException not thrown." ); } catch ( IllegalArgumentException expected ) diff --git a/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/impl/DefaultRunOrderProviderTest.java b/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/impl/DefaultRunOrderProviderTest.java new file mode 100644 index 0000000000..ce6c082a72 --- /dev/null +++ b/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/impl/DefaultRunOrderProviderTest.java @@ -0,0 +1,49 @@ +package org.apache.maven.plugin.surefire.runorder.impl; +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.surefire.runorder.api.RunOrder; +import org.apache.maven.plugin.surefire.runorder.spi.RunOrderProvider; +import org.junit.Test; + +import java.util.Collection; + +import static org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader.asArray; +import static org.apache.maven.plugin.surefire.runorder.model.RunOrderFactory.*; +import static org.junit.Assert.assertArrayEquals; + +public class DefaultRunOrderProviderTest { + + @Test + public void shouldLoadAllDefaultRunOrders() { + final RunOrderProvider runOrderLoader = RunOrderLoader.getRunOrderProvider(); + + final Collection runOrders = runOrderLoader.getRunOrders(); + + assertArrayEquals(asArray(runOrders), new RunOrder[] {ALPHABETICAL, FILESYSTEM, HOURLY, + RANDOM, REVERSE_ALPHABETICAL, BALANCED, FAILEDFIRST}); + } + + @Test + public void shouldLoadFileSystemAsDefaultRunOrder() { + final RunOrder[] defaultRunOrder = RunOrderLoader.defaultRunOrder(); + + assertArrayEquals(defaultRunOrder, new RunOrder[] {FILESYSTEM}); + } +} \ No newline at end of file diff --git a/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionSchedulerTest.java b/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/ThreadedExecutionSchedulerTest.java similarity index 98% rename from surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionSchedulerTest.java rename to surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/ThreadedExecutionSchedulerTest.java index 15963d776e..34b75650e0 100644 --- a/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionSchedulerTest.java +++ b/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/impl/statistics/ThreadedExecutionSchedulerTest.java @@ -1,4 +1,4 @@ -package org.apache.maven.plugin.surefire.runorder; +package org.apache.maven.plugin.surefire.runorder.impl.statistics; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -18,10 +18,10 @@ * under the License. */ -import java.util.List; - import junit.framework.TestCase; +import java.util.List; + /** * @author Kristian Rosenvold */ diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java index dd2f271278..a102d7b2cc 100644 --- a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java +++ b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java @@ -25,15 +25,16 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import junit.framework.TestCase; +import org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader; 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.TestListResolver; import org.apache.maven.surefire.testset.TestRequest; -import org.apache.maven.surefire.util.RunOrder; -import junit.framework.TestCase; +import static org.apache.maven.plugin.surefire.runorder.impl.RunOrderLoader.getRunOrderProvider; /** * @author Kristian Rosenvold @@ -61,7 +62,7 @@ public void testRunOrderParameters() SurefireReflector surefireReflector = getReflector(); Object foo = getFoo(); - RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, new File( "." ) ); + RunOrderParameters runOrderParameters = new RunOrderParameters( getRunOrderProvider().defaultRunOrder(), new File( "." ) ); surefireReflector.setRunOrderParameters( foo, runOrderParameters ); assertTrue( isCalled( foo ) ); diff --git a/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java b/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java index b8c83e1f8f..78647826ab 100644 --- a/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java +++ b/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java @@ -31,7 +31,7 @@ import org.apache.maven.surefire.suite.RunResult; import org.apache.maven.surefire.testset.TestSetFailedException; import org.apache.maven.surefire.util.ReflectionUtils; -import org.apache.maven.surefire.util.RunOrderCalculator; +import org.apache.maven.plugin.surefire.runorder.api.RunOrderCalculator; import org.apache.maven.surefire.util.ScanResult; import org.apache.maven.surefire.util.TestsToRun; diff --git a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java index ad29224e59..e40db9ee23 100644 --- a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java +++ b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java @@ -38,7 +38,7 @@ import org.apache.maven.surefire.testset.TestListResolver; import org.apache.maven.surefire.testset.TestRequest; import org.apache.maven.surefire.testset.TestSetFailedException; -import org.apache.maven.surefire.util.RunOrderCalculator; +import org.apache.maven.plugin.surefire.runorder.api.RunOrderCalculator; import org.apache.maven.surefire.util.ScanResult; import org.apache.maven.surefire.util.TestsToRun; import org.junit.runner.Description; diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java index a4c061e81d..48465fb9e1 100644 --- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java +++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java @@ -35,7 +35,7 @@ import org.apache.maven.surefire.suite.RunResult; import org.apache.maven.surefire.testset.TestListResolver; import org.apache.maven.surefire.testset.TestSetFailedException; -import org.apache.maven.surefire.util.RunOrderCalculator; +import org.apache.maven.plugin.surefire.runorder.api.RunOrderCalculator; import org.apache.maven.surefire.util.ScanResult; import org.apache.maven.surefire.util.ScannerFilter; import org.apache.maven.surefire.util.TestsToRun; diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java index 14e103a189..e28bb166eb 100644 --- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java +++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java @@ -34,7 +34,7 @@ import org.apache.maven.surefire.testset.TestListResolver; import org.apache.maven.surefire.testset.TestRequest; import org.apache.maven.surefire.testset.TestSetFailedException; -import org.apache.maven.surefire.util.RunOrderCalculator; +import org.apache.maven.plugin.surefire.runorder.api.RunOrderCalculator; import org.apache.maven.surefire.util.ScanResult; import org.apache.maven.surefire.util.TestsToRun;