From eb3ca0151f7a030e4f9f4c01e3c482155da7b73b Mon Sep 17 00:00:00 2001 From: amamiya_yuuko <1913250675@qq.com> Date: Wed, 27 Jul 2022 16:23:24 +0800 Subject: [PATCH 1/6] Definition of config --- .../api/testset/RunOrderParameters.java | 39 ++++++++++++++++++- .../maven/surefire/api/util/RunOrder.java | 5 ++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/testset/RunOrderParameters.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/testset/RunOrderParameters.java index d7f55a6523..c799b04281 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/api/testset/RunOrderParameters.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/testset/RunOrderParameters.java @@ -18,9 +18,11 @@ * specific language governing permissions and limitations * under the License. */ +import org.apache.maven.surefire.api.util.RunOrder; import java.io.File; -import org.apache.maven.surefire.api.util.RunOrder; +import java.util.ArrayList; +import java.util.List; import static org.apache.maven.surefire.api.util.RunOrder.ALPHABETICAL; import static org.apache.maven.surefire.api.util.RunOrder.DEFAULT; @@ -36,6 +38,8 @@ public final class RunOrderParameters private final Long runOrderRandomSeed; + private final String specifiedRunOrder; + public RunOrderParameters( RunOrder[] runOrder, File runStatisticsFile ) { this( runOrder, runStatisticsFile, null ); @@ -48,14 +52,28 @@ public RunOrderParameters( String runOrder, File runStatisticsFile ) public RunOrderParameters( String runOrder, File runStatisticsFile, Long runOrderRandomSeed ) { - this( runOrder == null ? DEFAULT : RunOrder.valueOfMulti( runOrder ), runStatisticsFile, runOrderRandomSeed ); + this( runOrder, runStatisticsFile, runOrderRandomSeed, null ); } public RunOrderParameters( RunOrder[] runOrder, File runStatisticsFile, Long runOrderRandomSeed ) + { + this( runOrder, runStatisticsFile, runOrderRandomSeed, null ); + } + + public RunOrderParameters( RunOrder[] runOrder, File runStatisticsFile, Long runOrderRandomSeed, + String specifiedRunOrder ) { this.runOrder = runOrder; this.runStatisticsFile = runStatisticsFile; this.runOrderRandomSeed = runOrderRandomSeed; + this.specifiedRunOrder = specifiedRunOrder; + } + + public RunOrderParameters( String runOrder, File runStatisticsFile, Long runOrderRandomSeed, + String specifiedRunOrder ) + { + this( runOrder == null ? DEFAULT : RunOrder.valueOfMulti( runOrder ), runStatisticsFile, runOrderRandomSeed, + specifiedRunOrder ); } public static RunOrderParameters alphabetical() @@ -77,4 +95,21 @@ public File getRunStatisticsFile() { return runStatisticsFile; } + + public List resolvedSpecifiedRunOrder() + { + if ( specifiedRunOrder != null ) + { + return new ArrayList<>( new TestListResolver( specifiedRunOrder ).getIncludedPatterns() ); + } + else + { + return null; + } + } + + public String getSpecifiedRunOrder() + { + return specifiedRunOrder; + } } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/util/RunOrder.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/util/RunOrder.java index b0d938266a..2d979a9513 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/api/util/RunOrder.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/util/RunOrder.java @@ -44,6 +44,8 @@ public class RunOrder public static final RunOrder FAILEDFIRST = new RunOrder( "failedfirst" ); + public static final RunOrder TESTORDER = new RunOrder( "testorder" ); + public static final RunOrder[] DEFAULT = new RunOrder[]{ FILESYSTEM }; /** @@ -108,7 +110,8 @@ private static String createMessageForMissingRunOrder( String name ) private static RunOrder[] values() { - return new RunOrder[]{ ALPHABETICAL, FILESYSTEM, HOURLY, RANDOM, REVERSE_ALPHABETICAL, BALANCED, FAILEDFIRST }; + return new RunOrder[]{ ALPHABETICAL, FILESYSTEM, HOURLY, RANDOM, REVERSE_ALPHABETICAL, BALANCED, FAILEDFIRST, + TESTORDER }; } public static String asString( RunOrder[] runOrder ) From 06ee583c01556d38eed42bdfba2ab7b1c43eb1db Mon Sep 17 00:00:00 2001 From: amamiya_yuuko <1913250675@qq.com> Date: Wed, 27 Jul 2022 16:24:30 +0800 Subject: [PATCH 2/6] Serialize/Deserialize the config --- .../plugin/surefire/AbstractSurefireMojo.java | 3 ++- .../surefire/booterclient/BooterSerializer.java | 2 ++ ...ooterDeserializerProviderConfigurationTest.java | 14 +++++++++++++- ...BooterDeserializerStartupConfigurationTest.java | 3 ++- .../maven/surefire/booter/BooterConstants.java | 1 + .../maven/surefire/booter/BooterDeserializer.java | 3 ++- 6 files changed, 22 insertions(+), 4 deletions(-) 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 257e64b2a3..7ab35e383c 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 @@ -1296,7 +1296,8 @@ private RunResult executeProvider( @Nonnull ProviderInfo provider, @Nonnull Defa ClassLoaderConfiguration classLoaderConfiguration = getClassLoaderConfiguration(); provider.addProviderProperties(); RunOrderParameters runOrderParameters = - new RunOrderParameters( getRunOrder(), getStatisticsFile( getConfigChecksum() ), getRunOrderRandomSeed() ); + new RunOrderParameters( getRunOrder(), getStatisticsFile( getConfigChecksum() ), getRunOrderRandomSeed(), + getTest() ); if ( isNotForking() ) { 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 1385bd44d6..63bf8ccb42 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 @@ -65,6 +65,7 @@ import static org.apache.maven.surefire.booter.BooterConstants.SHUTDOWN; import static org.apache.maven.surefire.booter.BooterConstants.SOURCE_DIRECTORY; import static org.apache.maven.surefire.booter.BooterConstants.SPECIFIC_TEST_PROPERTY_PREFIX; +import static org.apache.maven.surefire.booter.BooterConstants.SPECIFIED_RUN_ORDER; import static org.apache.maven.surefire.booter.BooterConstants.SYSTEM_EXIT_TIMEOUT; import static org.apache.maven.surefire.booter.BooterConstants.TEST_CLASSES_DIRECTORY; import static org.apache.maven.surefire.booter.BooterConstants.TEST_SUITE_XML_FILES; @@ -162,6 +163,7 @@ File serialize( KeyValueSource sourceProperties, ProviderConfiguration providerC properties.setProperty( RUN_ORDER, RunOrder.asString( runOrderParameters.getRunOrder() ) ); properties.setProperty( RUN_STATISTICS_FILE, runOrderParameters.getRunStatisticsFile() ); properties.setProperty( RUN_ORDER_RANDOM_SEED, runOrderParameters.getRunOrderRandomSeed() ); + properties.setProperty( SPECIFIED_RUN_ORDER, runOrderParameters.getSpecifiedRunOrder() ); } ReporterConfiguration reporterConfiguration = providerConfiguration.getReporterConfiguration(); 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 55f63f358d..af81d4793a 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 @@ -152,6 +152,17 @@ public void testTestArtifact() assertEquals( cli, reloaded.getMainCliOptions() ); } + public void testRunOrderParameter() + throws IOException + { + ProviderConfiguration reloaded = getReloadedProviderConfiguration(); + + Assert.assertEquals( RunOrder.DEFAULT[0], reloaded.getRunOrderParameters().getRunOrder()[0] ); + Assert.assertNull( reloaded.getRunOrderParameters().getRunStatisticsFile() ); + Assert.assertEquals( "c1#m2,c2#m1", reloaded.getRunOrderParameters().getSpecifiedRunOrder() ); + Assert.assertEquals( new Long( "65" ), reloaded.getRunOrderParameters().getRunOrderRandomSeed() ); + } + public void testTestRequest() throws IOException { @@ -275,7 +286,8 @@ private ProviderConfiguration getTestProviderConfiguration( DirectoryScannerPara new TestRequest( getSuiteXmlFileStrings(), getTestSourceDirectory(), new TestListResolver( USER_REQUESTED_TEST + "#aUserRequestedTestMethod" ), RERUN_FAILING_TEST_COUNT ); - RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, null ); + RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, null, new Long( "65" ), + "c1#m2,c2#m1" ); return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, reporterConfiguration, new TestArtifactInfo( "5.0", "ABC" ), testSuiteDefinition, new HashMap(), TEST_TYPED, 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 9baf914af7..262cad3764 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 @@ -197,7 +197,8 @@ private ProviderConfiguration getProviderConfiguration() new TestRequest( Arrays.asList( getSuiteXmlFileStrings() ), getTestSourceDirectory(), new TestListResolver( "aUserRequestedTest#aUserRequestedTestMethod" ) ); - RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, null ); + RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, null, + new Long( "65" ), "c1#m2,c2#m1" ); return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, reporterConfiguration, new TestArtifactInfo( "5.0", "ABC" ), testSuiteDefinition, new HashMap(), BooterDeserializerProviderConfigurationTest.TEST_TYPED, true, cli, 0, Shutdown.DEFAULT, 0 ); diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java index dcf73615da..9e2f8804f9 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java @@ -60,4 +60,5 @@ private BooterConstants() public static final String PROCESS_CHECKER = "processChecker"; public static final String FORK_NODE_CONNECTION_STRING = "forkNodeConnectionString"; public static final String FORK_NUMBER = "forkNumber"; + public static final String SPECIFIED_RUN_ORDER = "specifiedRunOrder"; } diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java index 2b365ad89a..228dd633cd 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java @@ -109,6 +109,7 @@ public ProviderConfiguration deserialize() final String runOrder = properties.getProperty( RUN_ORDER ); final Long runOrderRandomSeed = properties.getLongProperty( RUN_ORDER_RANDOM_SEED ); final String runStatisticsFile = properties.getProperty( RUN_STATISTICS_FILE ); + final String specifiedRunOrder = properties.getProperty( SPECIFIED_RUN_ORDER ); final int rerunFailingTestsCount = properties.getIntProperty( RERUN_FAILING_TESTS_COUNT ); @@ -117,7 +118,7 @@ public ProviderConfiguration deserialize() RunOrderParameters runOrderParameters = new RunOrderParameters( runOrder, runStatisticsFile == null ? null : new File( runStatisticsFile ), - runOrderRandomSeed ); + runOrderRandomSeed, specifiedRunOrder ); TestArtifactInfo testNg = new TestArtifactInfo( testNgVersion, testArtifactClassifier ); TestRequest testSuiteDefinition = From 1c72d113cdd02adab067532c0b820f8661bcded2 Mon Sep 17 00:00:00 2001 From: amamiya_yuuko <1913250675@qq.com> Date: Wed, 27 Jul 2022 16:25:05 +0800 Subject: [PATCH 3/6] Run order calculator --- .../api/util/DefaultRunOrderCalculator.java | 86 ++++++++++++- .../surefire/api/util/RunOrderCalculator.java | 4 + .../api/util/RunOrderCalculatorTest.java | 116 ++++++++++++++++++ 3 files changed, 205 insertions(+), 1 deletion(-) diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/util/DefaultRunOrderCalculator.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/util/DefaultRunOrderCalculator.java index 79a4618291..93a8361521 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/api/util/DefaultRunOrderCalculator.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/util/DefaultRunOrderCalculator.java @@ -20,6 +20,7 @@ */ import org.apache.maven.surefire.api.runorder.RunEntryStatisticsMap; +import org.apache.maven.surefire.api.testset.ResolvedTest; import org.apache.maven.surefire.api.testset.RunOrderParameters; import java.util.ArrayList; @@ -30,6 +31,8 @@ import java.util.List; import java.util.Random; +import static org.apache.maven.surefire.api.testset.TestListResolver.toClassFileName; + /** * Applies the final runorder of the tests * @@ -48,11 +51,14 @@ public class DefaultRunOrderCalculator private final Random random; + private final List specifiedRunOrder; + public DefaultRunOrderCalculator( RunOrderParameters runOrderParameters, int threadCount ) { this.runOrderParameters = runOrderParameters; this.threadCount = threadCount; this.runOrder = runOrderParameters.getRunOrder(); + this.specifiedRunOrder = runOrderParameters.resolvedSpecifiedRunOrder(); this.sortOrder = this.runOrder.length > 0 ? getSortOrderComparator( this.runOrder[0] ) : null; Long runOrderRandomSeed = runOrderParameters.getRunOrderRandomSeed(); random = new Random( runOrderRandomSeed == null ? System.nanoTime() : runOrderRandomSeed ); @@ -73,9 +79,49 @@ public TestsToRun orderTestClasses( TestsToRun scannedClasses ) return new TestsToRun( new LinkedHashSet<>( result ) ); } + @Override + public Comparator comparatorForTestMethods() + { + if ( RunOrder.TESTORDER.equals( runOrder[0] ) && specifiedRunOrder != null ) + { + return new Comparator() + { + @Override + public int compare( String o1, String o2 ) + { + String[] classAndMethod1 = getClassAndMethod( o1 ); + String className1 = classAndMethod1[0]; + String methodName1 = classAndMethod1[1]; + String[] classAndMethod2 = getClassAndMethod( o2 ); + String className2 = classAndMethod2[0]; + String methodName2 = classAndMethod2[1]; + return testOrderComparator( className1, className2, methodName1, methodName2 ); + } + }; + } + else + { + return null; + } + } + private void orderTestClasses( List> testClasses, RunOrder runOrder ) { - if ( RunOrder.RANDOM.equals( runOrder ) ) + if ( RunOrder.TESTORDER.equals( runOrder ) ) + { + if ( specifiedRunOrder != null ) + { + Collections.sort( testClasses, new Comparator>() + { + @Override + public int compare( Class o1, Class o2 ) + { + return testOrderComparator( o1.getName(), o2.getName(), null, null ); + } + } ); + } + } + else if ( RunOrder.RANDOM.equals( runOrder ) ) { Collections.shuffle( testClasses, random ); } @@ -131,4 +177,42 @@ private static Comparator> getAlphabeticalComparator() { return Comparator.comparing( Class::getName ); } + + public int testOrderComparator( String className1, String className2, String methodName1, String methodName2 ) + { + String classFileName1 = toClassFileName( className1 ); + String classFileName2 = toClassFileName( className2 ); + int index1 = -1; + int index2 = -1; + if ( specifiedRunOrder != null ) + { + for ( ResolvedTest filter : specifiedRunOrder ) + { + if ( filter.matchAsInclusive( classFileName1, methodName1 ) ) + { + index1 = specifiedRunOrder.indexOf( filter ); + } + } + for ( ResolvedTest filter : specifiedRunOrder ) + { + if ( filter.matchAsInclusive( classFileName2, methodName2 ) ) + { + index2 = specifiedRunOrder.indexOf( filter ); + } + } + } + return index1 - index2; + } + + public String[] getClassAndMethod( String request ) + { + String[] classAndMethod = { request, request }; + if ( request.contains( "(" ) ) + { + String[] nameSplit1 = request.split( "\\(" ); + classAndMethod[0] = nameSplit1[1].substring( 0, nameSplit1[1].length() - 1 ); + classAndMethod[1] = nameSplit1[0]; + } + return classAndMethod; + } } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/util/RunOrderCalculator.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/util/RunOrderCalculator.java index a9f99939ed..2c58002089 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/api/util/RunOrderCalculator.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/util/RunOrderCalculator.java @@ -19,10 +19,14 @@ * under the License. */ +import java.util.Comparator; + /** * @author Kristian Rosenvold */ public interface RunOrderCalculator { TestsToRun orderTestClasses( TestsToRun scannedClasses ); + + Comparator comparatorForTestMethods(); } diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/api/util/RunOrderCalculatorTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/api/util/RunOrderCalculatorTest.java index 63768cf03d..3546dd99bd 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/api/util/RunOrderCalculatorTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/api/util/RunOrderCalculatorTest.java @@ -19,7 +19,10 @@ * under the License. */ +import java.util.Arrays; +import java.util.Comparator; import java.util.LinkedHashSet; +import java.util.List; import java.util.Set; import org.apache.maven.surefire.api.testset.RunOrderParameters; @@ -59,4 +62,117 @@ static class B { } + public void testOrderTestMethods() + { + System.setProperty( "test", "TestClass#a2d,TestClass#aBc,TestClass#abc,TestClass#a1b" ); + RunOrderParameters runOrderParameters = new RunOrderParameters( "testorder" , null, + null, System.getProperty( "test" ) ); + DefaultRunOrderCalculator runOrderCalculator = new DefaultRunOrderCalculator( runOrderParameters, 1 ); + Comparator testOrderRunOrderComparator = runOrderCalculator.comparatorForTestMethods(); + String[] strArray = { "abc(TestClass)", "a1b(TestClass)", "a2d(TestClass)", "aBc(TestClass)" }; + List actual = Arrays.asList( strArray ); + actual.sort( testOrderRunOrderComparator ); + String[] strArray2 = { "a2d(TestClass)", "aBc(TestClass)", "abc(TestClass)", "a1b(TestClass)" }; + List expected = Arrays.asList( strArray2 ); + assertEquals( actual, expected ); + } + + public void testOrderTestClassesAndMethods() + { + System.setProperty( "test", "TestClass1#a2d,TestClass2#aBc,TestClass2#abc,TestClass2#a1b" ); + RunOrderParameters runOrderParameters = new RunOrderParameters( "testorder" , null, + null, System.getProperty( "test" ) ); + DefaultRunOrderCalculator runOrderCalculator = new DefaultRunOrderCalculator( runOrderParameters, 1 ); + Comparator testOrderRunOrderComparator = runOrderCalculator.comparatorForTestMethods(); + String[] strArray = { "abc(TestClass2)", "a1b(TestClass2)", "a2d(TestClass1)", "aBc(TestClass2)" }; + List actual = Arrays.asList( strArray ); + actual.sort( testOrderRunOrderComparator ); + String[] strArray2 = { "a2d(TestClass1)", "aBc(TestClass2)", "abc(TestClass2)", "a1b(TestClass2)" }; + List expected = Arrays.asList( strArray2 ); + assertEquals( actual, expected ); + } + + public void testOrderTestRegexClassesAndMethods() + { + System.setProperty( "test", "Amber*Test#a?c,My???Test#test*" ); + RunOrderParameters runOrderParameters = new RunOrderParameters( "testorder" , null, + null, System.getProperty( "test" ) ); + DefaultRunOrderCalculator runOrderCalculator = new DefaultRunOrderCalculator( runOrderParameters, 1 ); + Comparator testOrderRunOrderComparator = runOrderCalculator.comparatorForTestMethods(); + String[] strArray = { "abc(AmberGoodTest)", + "testabc(MyabcTest)", + "a2c(AmberBadTest)", + "testefg(MyefgTest)", + "aBc(AmberGoodTest)" }; + List actual = Arrays.asList( strArray ); + actual.sort( testOrderRunOrderComparator ); + assertEquals( runOrderCalculator.getClassAndMethod( actual.get( 0 ) )[0].substring( 0, 5 ), "Amber" ); + assertEquals( runOrderCalculator.getClassAndMethod( actual.get( 1 ) )[0].substring( 0, 5 ), "Amber" ); + assertEquals( runOrderCalculator.getClassAndMethod( actual.get( 2 ) )[0].substring( 0, 5 ), "Amber" ); + assertEquals( runOrderCalculator.getClassAndMethod( actual.get( 3 ) )[0].substring( 0, 2 ), "My" ); + assertEquals( runOrderCalculator.getClassAndMethod( actual.get( 4 ) )[0].substring( 0, 2 ), "My" ); + } + + public void testOrderComparatorTest() + { + StringBuilder sb = new StringBuilder(); + sb.append( "TestClass1#testa2d," ); + sb.append( "TestClass1#testabc," ); + sb.append( "TestClass1#testa1b," ); + sb.append( "TestClass2#testa1b," ); + sb.append( "TestClass2#testaBc" ); + RunOrderParameters runOrderParameters = new RunOrderParameters( "testorder" , null, + null, sb.toString() ); + DefaultRunOrderCalculator roc = new DefaultRunOrderCalculator( runOrderParameters, 1 ); + String className = "TestClass1"; + String className2 = "TestClass2"; + assertTrue( ( int ) roc.testOrderComparator( className, className, "testa2d", "testa1b" ) < 0 ); + assertTrue( ( int ) roc.testOrderComparator( className, className, "testa2d", "testabc" ) < 0 ); + assertTrue( ( int ) roc.testOrderComparator( className, className, "testa1b", "testabc" ) > 0 ); + assertTrue( ( int ) roc.testOrderComparator( className, className, "testa2d", "testaBc" ) > 0 ); + assertTrue( ( int ) roc.testOrderComparator( className, className, "testa3d", "testa1b" ) < 0 ); + assertTrue( ( int ) roc.testOrderComparator( className, className2, "testa2d", "testa1b" ) < 0 ); + assertTrue( ( int ) roc.testOrderComparator( className2, className, "testaBc", "testa1b" ) > 0 ); + assertTrue( ( int ) roc.testOrderComparator( className, className2, "testa3d", "testa1b" ) < 0 ); + assertTrue( ( int ) roc.testOrderComparator( className, className2, "testa2d", "testabc" ) > 0 ); + assertTrue( ( int ) roc.testOrderComparator( className, className, "testa2d", "testa2d" ) == 0 ); + } + + public void testRegexMethodOrderComparator() + { + StringBuilder orderParamList = new StringBuilder(); + orderParamList.append( "TestClass1#testa?c," ); + orderParamList.append( "TestClass1#testa?b," ); + orderParamList.append( "TestClass2#test?1*," ); + orderParamList.append( "!TestClass1#testa4b," ); + orderParamList.append( "!TestClass2#test11MyTest" ); + RunOrderParameters runOrderParameters = new RunOrderParameters( "testorder" , null, + null, orderParamList.toString() ); + DefaultRunOrderCalculator roc = new DefaultRunOrderCalculator( runOrderParameters, 1 ); + String className = "TestClass1"; + String className2 = "TestClass2"; + assertTrue( ( int ) roc.testOrderComparator( className, className, "testabc", "testa1b" ) < 0 ); + assertTrue( ( int ) roc.testOrderComparator( className, className, "testaBc", "testa2b" ) < 0 ); + assertTrue( ( int ) roc.testOrderComparator( className, className, "testa1b", "testa3c" ) > 0 ); + assertTrue( ( int ) roc.testOrderComparator( className, className2, "testa1b", "test1123" ) < 0 ); + assertTrue( ( int ) roc.testOrderComparator( className2, className, "testa1b", "testa1b" ) > 0 ); + assertTrue( ( int ) roc.testOrderComparator( className2, className2, "testa1b", "test1123" ) == 0 ); + assertTrue( ( int ) roc.testOrderComparator( className, className, "testa1c", "testa1c" ) == 0 ); + } + + public void testRegexClassOrderComparator() + { + StringBuilder orderParamList = new StringBuilder(); + orderParamList.append( "My2*Test.java," ); + orderParamList.append( "???My1*Test," ); + orderParamList.append( "!abcMy1PeaceTest" ); + RunOrderParameters runOrderParameters = new RunOrderParameters( "testorder" , null, + null, orderParamList.toString() ); + DefaultRunOrderCalculator roc = new DefaultRunOrderCalculator( runOrderParameters, 1 ); + String className = "My2ConnectTest"; + String className2 = "456My1ConnectTest"; + assertTrue( ( int ) roc.testOrderComparator( className, className2, null, null ) < 0 ); + assertTrue( ( int ) roc.testOrderComparator( className2, className, null, null ) > 0 ); + assertTrue( ( int ) roc.testOrderComparator( className, className, null, null ) == 0 ); + } } From 3eb118f184d1e64752cd993bafe7bff85d03f065 Mon Sep 17 00:00:00 2001 From: amamiya_yuuko <1913250675@qq.com> Date: Wed, 27 Jul 2022 16:25:51 +0800 Subject: [PATCH 4/6] Modify provider --- .../maven/surefire/junit4/JUnit4Provider.java | 14 +++++++++++--- .../surefire/junitcore/JUnitCoreProvider.java | 5 +++-- .../maven/surefire/junitcore/JUnitCoreWrapper.java | 12 +++++++++++- .../maven/surefire/junitcore/Surefire746Test.java | 6 +++++- 4 files changed, 30 insertions(+), 7 deletions(-) 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 5c38caa70d..dbe5f3658c 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 @@ -51,6 +51,7 @@ import org.junit.runner.notification.StoppedByUserException; import java.util.Collection; +import java.util.Comparator; import java.util.Set; import static java.lang.reflect.Modifier.isAbstract; @@ -281,7 +282,8 @@ private void executeWithRerun( Class clazz, Notifier notifier, RunModeSetter try { notifier.asFailFast( isFailFast() ); - execute( clazz, notifier, hasMethodFilter ? createMethodFilter() : null ); + execute( clazz, notifier, hasMethodFilter ? createMethodFilter() : null, + runOrderCalculator.comparatorForTestMethods() ); } finally { @@ -299,7 +301,8 @@ private void executeWithRerun( Class clazz, Notifier notifier, RunModeSetter Set failures = generateFailingTestDescriptions( failureListener.getAllFailures() ); failureListener.reset(); Filter failureDescriptionFilter = createMatchAnyDescriptionFilter( failures ); - execute( clazz, rerunNotifier, failureDescriptionFilter ); + execute( clazz, rerunNotifier, failureDescriptionFilter, + runOrderCalculator.comparatorForTestMethods() ); } } } @@ -361,7 +364,8 @@ private static boolean isJUnit4UpgradeCheck() return System.getProperty( "surefire.junit4.upgradecheck" ) != null; } - private static void execute( Class testClass, Notifier notifier, Filter filter ) + private static void execute( Class testClass, Notifier notifier, Filter filter, + Comparator runOrderComparator ) { final int classModifiers = testClass.getModifiers(); if ( !isAbstract( classModifiers ) && !isInterface( classModifiers ) ) @@ -371,6 +375,10 @@ private static void execute( Class testClass, Notifier notifier, Filter filte { request = request.filterWith( filter ); } + if ( runOrderComparator != null ) + { + request = request.sortWith( ( o1, o2 ) -> runOrderComparator.compare( o1.toString(), o2.toString() ) ); + } Runner runner = request.getRunner(); if ( countTestsInRunner( runner.getDescription() ) != 0 ) { 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 7ed483426f..68f14695cb 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 @@ -146,7 +146,7 @@ public RunResult invoke( Object forkTestSet ) try { - JUnitCoreWrapper core = new JUnitCoreWrapper( notifier, jUnitCoreParameters, logger ); + JUnitCoreWrapper core = new JUnitCoreWrapper( notifier, jUnitCoreParameters, logger, runOrderCalculator ); if ( commandsReader != null ) { @@ -164,7 +164,8 @@ public RunResult invoke( Object forkTestSet ) listener.setRunMode( RERUN_TEST_AFTER_FAILURE ); Notifier rerunNotifier = pureNotifier(); notifier.copyListenersTo( rerunNotifier ); - JUnitCoreWrapper rerunCore = new JUnitCoreWrapper( rerunNotifier, jUnitCoreParameters, logger ); + JUnitCoreWrapper rerunCore = new JUnitCoreWrapper( rerunNotifier, jUnitCoreParameters, logger, + runOrderCalculator ); for ( int i = 0; i < rerunFailingTestsCount && !testFailureListener.getAllFailures().isEmpty(); i++ ) { Set failures = generateFailingTestDescriptions( testFailureListener.getAllFailures() ); diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java index 3ae0b48e1f..da7c1dd23c 100644 --- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java +++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreWrapper.java @@ -21,6 +21,7 @@ import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; import org.apache.maven.surefire.api.testset.TestSetFailedException; +import org.apache.maven.surefire.api.util.RunOrderCalculator; import org.apache.maven.surefire.api.util.TestsToRun; import org.apache.maven.surefire.common.junit4.Notifier; import org.apache.maven.surefire.junitcore.pc.ParallelComputer; @@ -36,6 +37,7 @@ import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.Iterator; import java.util.Queue; @@ -55,12 +57,15 @@ final class JUnitCoreWrapper private final Notifier notifier; private final JUnitCoreParameters jUnitCoreParameters; private final ConsoleLogger consoleStream; + private final RunOrderCalculator runOrderCalculator; - JUnitCoreWrapper( Notifier notifier, JUnitCoreParameters jUnitCoreParameters, ConsoleLogger consoleStream ) + JUnitCoreWrapper( Notifier notifier, JUnitCoreParameters jUnitCoreParameters, ConsoleLogger consoleStream, + RunOrderCalculator runOrderCalculator ) { this.notifier = notifier; this.jUnitCoreParameters = jUnitCoreParameters; this.consoleStream = consoleStream; + this.runOrderCalculator = runOrderCalculator; } void execute( TestsToRun testsToRun, Filter filter ) @@ -133,6 +138,11 @@ private void createRequestAndRun( Filter filter, Computer computer, JUnitCore ju return; } } + final Comparator testOrderComparator = runOrderCalculator.comparatorForTestMethods(); + if ( testOrderComparator != null ) + { + req = req.sortWith( ( o1, o2 ) -> testOrderComparator.compare( o1.toString(), o2.toString() ) ); + } Result run = junitCore.run( req.getRunner() ); rethrowAnyTestMechanismFailures( run ); diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java index fab0367b68..538c36ab64 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java @@ -50,7 +50,9 @@ import org.apache.maven.surefire.api.report.ReporterConfiguration; import org.apache.maven.surefire.api.report.ReporterFactory; import org.apache.maven.surefire.api.suite.RunResult; +import org.apache.maven.surefire.api.testset.RunOrderParameters; import org.apache.maven.surefire.api.testset.TestSetFailedException; +import org.apache.maven.surefire.api.util.DefaultRunOrderCalculator; import org.apache.maven.surefire.api.util.TestsToRun; import org.apache.maven.surefire.common.junit4.JUnit4RunListener; import org.apache.maven.surefire.common.junit4.Notifier; @@ -135,7 +137,9 @@ public void surefireIsConfused_ByMultipleIgnore_OnClassLevel() throws Exception // and rethrows a failure which happened in listener exception.expect( TestSetFailedException.class ); JUnit4RunListener dummy = new JUnit4RunListener( new MockReporter() ); - new JUnitCoreWrapper( new Notifier( dummy, 0 ), jUnitCoreParameters, mock( ConsoleLogger.class ) ) + new JUnitCoreWrapper( new Notifier( dummy, 0 ), jUnitCoreParameters, + mock( ConsoleLogger.class ), + new DefaultRunOrderCalculator( RunOrderParameters.alphabetical(), 1 ) ) .execute( testsToRun, customRunListeners, null ); } finally From d2234d0db052dfa5a27a359a29ac6090966cd55b Mon Sep 17 00:00:00 2001 From: amamiya_yuuko <1913250675@qq.com> Date: Wed, 27 Jul 2022 16:26:32 +0800 Subject: [PATCH 5/6] Integration test --- .../apache/maven/surefire/its/RunOrderIT.java | 21 +++++++++++ .../src/test/java/junit/runOrder/TestD.java | 37 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 surefire-its/src/test/resources/runOrder/src/test/java/junit/runOrder/TestD.java diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java index a3f167bc6c..b2224363a7 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java @@ -40,6 +40,8 @@ public class RunOrderIT private static final String[] TESTS_IN_REVERSE_ALPHABETICAL_ORDER = { "TC", "TB", "TA" }; + private static final String[] TEST_IN_SPECIFIED_ORDER = { "TD#2", "TD#1", "TB" }; + // testing random is left as an exercise to the reader. Patches welcome @Test @@ -185,6 +187,25 @@ public void testNonExistingRunOrderJUnit5() .verifyTextInLog( "There's no RunOrder with the name nonExistingRunOrder." ); } + @Test + public void testSpecifiedTestOrderJUnit4() + throws Exception + { + OutputValidator validator = executeWithTestOrder( "junit4" ); + assertTestnamesAppearInSpecificOrder( validator, TEST_IN_SPECIFIED_ORDER ); + } + + private OutputValidator executeWithTestOrder( String profile ) + { + return unpack() + .activateProfile( profile ) + .forkMode( getForkMode() ) + .setTestToRun( "junit.runOrder.TestD#testTwo,junit.runOrder.TestD#testOne,junit.runOrder.TestB" ) + .runOrder( "testorder" ) + .executeTest() + .verifyErrorFree( 3 ); + } + private OutputValidator executeWithRunOrder( String runOrder, String profile ) { return unpack() diff --git a/surefire-its/src/test/resources/runOrder/src/test/java/junit/runOrder/TestD.java b/surefire-its/src/test/resources/runOrder/src/test/java/junit/runOrder/TestD.java new file mode 100644 index 0000000000..4597b2f5e5 --- /dev/null +++ b/surefire-its/src/test/resources/runOrder/src/test/java/junit/runOrder/TestD.java @@ -0,0 +1,37 @@ +package junit.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 junit.framework.TestCase; + +public class TestD + extends TestCase +{ + public void testOne() + { + System.out.println( "TD#1" ); + } + + public void testTwo() + { + System.out.println( "TD#2" ); + } + +} From bc5a063c2b9a5670295b2a445ab52c94e9684450 Mon Sep 17 00:00:00 2001 From: amamiya_yuuko <73588409+amamiya-yuuko-1225@users.noreply.github.com> Date: Sun, 31 Jul 2022 21:29:55 +0800 Subject: [PATCH 6/6] Fix checkstyle problem --- .../apache/maven/surefire/api/testset/RunOrderParameters.java | 1 + 1 file changed, 1 insertion(+) diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/testset/RunOrderParameters.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/testset/RunOrderParameters.java index c799b04281..404fab2d70 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/api/testset/RunOrderParameters.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/testset/RunOrderParameters.java @@ -18,6 +18,7 @@ * specific language governing permissions and limitations * under the License. */ + import org.apache.maven.surefire.api.util.RunOrder; import java.io.File;