[SUREFIRE] completed commit 889caca
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/866a535b Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/866a535b Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/866a535b Branch: refs/heads/master Commit: 866a535b66229e9bab3f09cbd42732d70ca9504f Parents: 889caca Author: Tibor17 <tibo...@lycos.com> Authored: Tue Mar 24 02:10:22 2015 +0100 Committer: Tibor17 <tibo...@lycos.com> Committed: Tue Mar 24 02:10:22 2015 +0100 ---------------------------------------------------------------------- .../plugin/failsafe/IntegrationTestMojo.java | 23 +- .../plugin/surefire/AbstractSurefireMojo.java | 177 +++--- .../surefire/SurefireExecutionParameters.java | 3 +- .../surefire/booterclient/BooterSerializer.java | 7 +- .../plugin/surefire/util/DependencyScanner.java | 107 +--- .../plugin/surefire/util/DirectoryScanner.java | 52 +- .../maven/plugin/surefire/util/FileScanner.java | 126 ++++ .../maven/plugin/surefire/util/ScannerUtil.java | 47 -- .../surefire/util/SpecificFileFilter.java | 1 + ...erDeserializerProviderConfigurationTest.java | 10 +- .../surefire/util/DependenciesScannerTest.java | 3 +- .../surefire/util/DirectoryScannerTest.java | 6 +- .../maven/plugin/surefire/SurefirePlugin.java | 23 +- .../apt/examples/inclusion-exclusion.apt.vm | 16 + .../src/site/apt/examples/single-test.apt.vm | 26 +- .../providerapi/ProviderParameters.java | 1 + .../surefire/testset/GenericTestPattern.java | 54 ++ .../testset/IncludedExcludedPatterns.java | 27 + .../maven/surefire/testset/ResolvedTest.java | 229 ++++--- .../maven/surefire/testset/TestFilter.java | 31 + .../surefire/testset/TestListResolver.java | 376 +++++++++--- .../surefire/testset/ResolvedTestTest.java | 49 ++ .../surefire/testset/TestListResolverTest.java | 302 ++++++++++ .../maven/surefire/booter/ForkedBooter.java | 2 +- .../maven/surefire/booter/ProviderFactory.java | 6 - surefire-integration-tests/pom.xml | 4 +- .../its/AbstractTestMultipleMethodPatterns.java | 466 +++++++++++++++ .../its/TestMultipleMethodPatternsIT.java | 160 +---- .../its/TestMultipleMethodPatternsTestNGIT.java | 64 ++ .../surefire/its/fixture/Configuration.java | 29 + .../maven/surefire/its/fixture/Settings.java | 72 +++ .../SurefireJUnit4IntegrationTestCase.java | 8 +- .../surefire/its/fixture/TestFramework.java | 29 + .../jiras/Surefire847AdditionalFailureIT.java | 2 +- .../resources/junit44-multiple-methods/pom.xml | 14 +- .../junit48-multiple-method-patterns/pom.xml | 156 ++++- .../resources/junit48-multiple-methods/pom.xml | 10 +- .../testng-multiple-method-patterns/pom.xml | 116 ++++ .../test/java/jiras/surefire745/BasicTest.java | 47 ++ .../test/java/jiras/surefire745/TestFive.java | 44 ++ .../test/java/jiras/surefire745/TestFour.java | 44 ++ .../test/java/jiras/surefire745/TestThree.java | 46 ++ .../test/java/jiras/surefire745/TestTwo.java | 38 ++ .../surefire/common/junit48/MethodFilter.java | 9 +- .../surefire/common/junit48/RequestedTest.java | 9 +- .../common/junit48/FilterFactoryTest.java | 589 +++++++++++++------ .../surefire/common/junit48/tests/ATest.java | 23 + .../surefire/common/junit48/tests/a/ATest.java | 23 + .../surefire/common/junit48/tests/pt/PT.java | 86 +++ .../maven/surefire/junit4/JUnit4Provider.java | 6 +- .../surefire/junitcore/JUnitCoreProvider.java | 33 +- .../surefire/testng/utils/MethodSelector.java | 5 +- .../testng/TestNGDirectoryTestSuite.java | 14 +- .../maven/surefire/testng/TestNGExecutor.java | 10 +- .../maven/surefire/testng/TestNGProvider.java | 23 +- 55 files changed, 3052 insertions(+), 831 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java ---------------------------------------------------------------------- diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java index 0900e81..b9daaa6 100644 --- a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java +++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java @@ -36,7 +36,6 @@ import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.shared.utils.ReaderFactory; import org.apache.maven.shared.utils.StringUtils; import org.apache.maven.surefire.suite.RunResult; -import org.apache.maven.surefire.testset.TestListResolver; import static org.apache.maven.shared.utils.io.IOUtil.close; @@ -78,8 +77,16 @@ public class IntegrationTestMojo * This parameter overrides the <code>includes/excludes</code> parameters, and the TestNG <code>suiteXmlFiles</code> * parameter. * <p/> - * since 2.7.3 You can execute a limited number of methods in the test with adding #myMethod or #my*ethod. E.g. type + * Since 2.7.3 You can execute a limited number of methods in the test with adding #myMethod or #my*ethod. E.g. type * "-Dit.test=MyTest#myMethod" <b>supported for junit 4.x and testNg</b> + * <br/> + * Since 2.19 a complex syntax is supported in one parameter (JUnit 4, JUnit 4.7+, TestNG):<br/> + * "-Dit.test=???IT, !Unstable*, pkg/**/Ci*leIT.java, *IT#test*One+testTwo?????, #fast*+slowTest"<br/> + * "-Dit.test=Basic*, !%regex[.*.Unstable.*], !%regex[.*.MyIT.class#one.*|two.*], %regex[#fast.*|slow.*]"<br/> + * <br/> + * The Parameterized JUnit runner <em>describes</em> test methods using an index in brackets, so the non-regex + * method pattern would become: <em>#testMethod[*]</em>. + * <br/> */ @Parameter( property = "it.test" ) private String test; @@ -177,6 +184,8 @@ public class IntegrationTestMojo * <p/> * Each include item may also contain a comma-separated sublist of items, which will be treated as multiple * <include> entries.<br/> + * Since 2.19 a complex syntax is supported in one parameter (JUnit 4, JUnit 4.7+, TestNG):<br/> + * <include>%regex[.*[Cat|Dog].*], !%regex[pkg.*Slow.*.class], pkg/**/*Fast*.java, Basic????, !Unstable*</include><br/> * <p/> * This parameter is ignored if the TestNG <code>suiteXmlFiles</code> parameter is specified.<br/> * <br/> @@ -261,8 +270,6 @@ public class IntegrationTestMojo @Parameter( property = "failsafe.runOrder", defaultValue = "filesystem" ) protected String runOrder; - private TestListResolver testListResolver; - protected int getRerunFailingTestsCount() { return rerunFailingTestsCount; @@ -420,13 +427,9 @@ public class IntegrationTestMojo this.reportsDirectory = reportsDirectory; } - public TestListResolver getTest() + public String getTest() { - if ( testListResolver == null && test != null ) - { - testListResolver = new TestListResolver( test ); - } - return testListResolver; + return test; } public void setTest( String test ) http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java ---------------------------------------------------------------------- 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 dfca11a..fecf74d 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 @@ -82,6 +82,7 @@ import org.apache.maven.surefire.suite.RunResult; import org.apache.maven.surefire.testset.DirectoryScannerParameters; import org.apache.maven.surefire.testset.RunOrderParameters; import org.apache.maven.surefire.testset.TestArtifactInfo; +import org.apache.maven.surefire.testset.TestListResolver; import org.apache.maven.surefire.testset.TestRequest; import org.apache.maven.surefire.testset.TestSetFailedException; import org.apache.maven.surefire.util.DefaultScanResult; @@ -210,7 +211,7 @@ public abstract class AbstractSurefireMojo /** * A file containing include patterns. Blank lines, or lines starting with # are ignored. If {@code includes} are - * also specified these patterns are appended. + * also specified, these patterns are appended. */ @Parameter protected File includesFile; @@ -226,6 +227,8 @@ public abstract class AbstractSurefireMojo * <p/> * Each exclude item may also contain a comma-separated sublist of items, which will be treated as multiple * <exclude> entries.<br/> + * Since 2.19 a complex syntax is supported in one parameter (JUnit 4, JUnit 4.7+, TestNG):<br/> + * <exclude>%regex[pkg.*Slow.*.class], Unstable*</exclude><br/> * <br/> * <em>Notice that</em> these values are relative to the directory containing generated test classes of the project * being tested. This directory is declared by the parameter <code>testClassesDirectory</code> which defaults @@ -237,7 +240,7 @@ public abstract class AbstractSurefireMojo /** * A file containing exclude patterns. Blank lines, or lines starting with # are ignored. If {@code excludes} are - * also specified these patterns are appended. + * also specified, these patterns are appended. */ @Parameter protected File excludesFile; @@ -686,14 +689,16 @@ public abstract class AbstractSurefireMojo */ public static final String FORK_NUMBER_PLACEHOLDER = "${surefire.forkNumber}"; - private static final String JAVA_EXTENSION = ".java"; - protected abstract String getPluginName(); protected abstract int getRerunFailingTestsCount(); private SurefireDependencyResolver dependencyResolver; + private TestListResolver specificTests; + + private TestListResolver includedExcludedTests; + public void execute() throws MojoExecutionException, MojoFailureException { @@ -702,10 +707,10 @@ public abstract class AbstractSurefireMojo if ( verifyParameters() && !hasExecutedBefore() ) { - DefaultScanResult scan = scanForTestClasses();//! + DefaultScanResult scan = scanForTestClasses(); if ( !isValidSuiteXmlFileConfig() && scan.isEmpty() ) { - if ( getEffectiveFailIfNoTests() )//! isSpecificTestSpecified + if ( getEffectiveFailIfNoTests() ) { throw new MojoFailureException( "No tests were executed! (Set -DfailIfNoTests=false to ignore this error.)" ); @@ -714,7 +719,7 @@ public abstract class AbstractSurefireMojo return; } logReportsDirectory(); - executeAfterPreconditionsChecked( scan );//! getTest providers + executeAfterPreconditionsChecked( scan ); } } @@ -725,17 +730,20 @@ public abstract class AbstractSurefireMojo toolchain = getToolchain(); } - private DefaultScanResult scanForTestClasses()//! execute() + private DefaultScanResult scanForTestClasses() + throws MojoFailureException { - DefaultScanResult scan = scanDirectories();//! 1 - DefaultScanResult scanDeps = scanDependencies();//! + DefaultScanResult scan = scanDirectories(); + DefaultScanResult scanDeps = scanDependencies(); return scan.append( scanDeps ); } - private DefaultScanResult scanDirectories()//! + private DefaultScanResult scanDirectories() + throws MojoFailureException { - DirectoryScanner scanner = - new DirectoryScanner( getTestClassesDirectory(), getIncludeList(), getExcludeList(), getSpecificTests() );//! + DirectoryScanner scanner = new DirectoryScanner( getTestClassesDirectory(), + getIncludedAndExcludedTests(), + getSpecificTests() ); return scanner.scan(); } @@ -749,10 +757,14 @@ public abstract class AbstractSurefireMojo { try { - // noinspection unchecked - return new DependencyScanner( DependencyScanner.filter( project.getTestArtifacts(), - Arrays.asList( getDependenciesToScan() ) ), - getIncludeList(), getExcludeList(), getSpecificTests() ).scan();//! + // @TODO noinspection unchecked, check MavenProject 3.x for Generics in surefire:3.0 + @SuppressWarnings( "unchecked" ) + List<File> dependenciesToScan = + DependencyScanner.filter( project.getTestArtifacts(), Arrays.asList( getDependenciesToScan() ) ); + DependencyScanner scanner = new DependencyScanner( dependenciesToScan, + getIncludedAndExcludedTests(), + getSpecificTests() ); + return scanner.scan(); } catch ( Exception e ) { @@ -817,7 +829,7 @@ public abstract class AbstractSurefireMojo { try { - current = current.aggregate( executeProvider( provider, scanResult ) );//! getTest + current = current.aggregate( executeProvider( provider, scanResult ) ); } catch ( SurefireBooterForkException e ) { @@ -966,7 +978,7 @@ public abstract class AbstractSurefireMojo createCopyAndReplaceForkNumPlaceholder( effectiveProperties, 1 ).copyToSystemProperties(); InPluginVMSurefireStarter surefireStarter = - createInprocessStarter( provider, classLoaderConfiguration, runOrderParameters );//! getTest + createInprocessStarter( provider, classLoaderConfiguration, runOrderParameters ); return surefireStarter.runSuitesInProcess( scanResult ); } else @@ -981,7 +993,7 @@ public abstract class AbstractSurefireMojo try { ForkStarter forkStarter = - createForkStarter( provider, forkConfiguration, classLoaderConfiguration, runOrderParameters,//! getTest + createForkStarter( provider, forkConfiguration, classLoaderConfiguration, runOrderParameters, getLog() ); return forkStarter.run( effectiveProperties, scanResult ); } @@ -1371,7 +1383,7 @@ public abstract class AbstractSurefireMojo private boolean getEffectiveFailIfNoTests() { - if ( isSpecificTestSpecified() )//! + if ( isSpecificTestSpecified() ) { if ( getFailIfNoSpecifiedTests() != null ) { @@ -1404,9 +1416,8 @@ public abstract class AbstractSurefireMojo TestArtifactInfo testNg = isTestNg ? new TestArtifactInfo( testNgArtifact.getVersion(), testNgArtifact.getClassifier() ) : null; List<File> testXml = getSuiteXmlFiles() != null ? Arrays.asList( getSuiteXmlFiles() ) : null; - TestRequest testSuiteDefinition = - new TestRequest( testXml, getTestSourceDirectory(), getTest().onlyMethodFilters(), - getRerunFailingTestsCount() );//! + TestRequest testSuiteDefinition = new TestRequest( testXml, getTestSourceDirectory(), getSpecificTests(), + getRerunFailingTestsCount() ); final boolean actualFailIfNoTests; @@ -1420,9 +1431,9 @@ public abstract class AbstractSurefireMojo } else { - if ( isSpecificTestSpecified() )//! + if ( isSpecificTestSpecified() ) { - actualFailIfNoTests = getEffectiveFailIfNoTests();//! isSpecificTestSpecified + actualFailIfNoTests = getEffectiveFailIfNoTests(); setFailIfNoTests( actualFailIfNoTests ); } else @@ -1430,9 +1441,15 @@ public abstract class AbstractSurefireMojo actualFailIfNoTests = getFailIfNoTests() != null && getFailIfNoTests(); } - List<String> actualIncludes = getIncludeList();//! - List<String> actualExcludes = getExcludeList();//! - List<String> specificTests = getSpecificTests();//! + // @todo remove these three params and use DirectoryScannerParameters to pass into DirectoryScanner only + // @todo or remove it in next major version :: 3.0 + // @todo remove deprecated methods in ProviderParameters => included|excluded|specificTests not needed here + + List<String> actualIncludes = getIncludeList(); // Collections.emptyList(); behaves same + List<String> actualExcludes = getExcludeList(); // Collections.emptyList(); behaves same + // Collections.emptyList(); behaves same + List<String> specificTests = new ArrayList<String>( getSpecificTests().getTestSpecificClasses() ); + directoryScannerParameters = new DirectoryScannerParameters( getTestClassesDirectory(), actualIncludes, actualExcludes, specificTests, actualFailIfNoTests, getRunOrder() ); @@ -1451,7 +1468,6 @@ public abstract class AbstractSurefireMojo + configurationHash; } - StartupConfiguration createStartupConfiguration( ProviderInfo provider, ClassLoaderConfiguration classLoaderConfiguration ) throws MojoExecutionException, MojoFailureException @@ -1466,7 +1482,6 @@ public abstract class AbstractSurefireMojo { providerClasspath = provider.getProviderClasspath(); ClasspathCache.setCachedClasspath( providerName, providerClasspath ); - } Artifact surefireArtifact = getCommonArtifact(); Classpath inprocClassPath = providerClasspath. @@ -1523,7 +1538,7 @@ public abstract class AbstractSurefireMojo private boolean isSpecificTestSpecified() { - return getTest() != null;//! + return getTest() != null; } private boolean isValidSuiteXmlFileConfig() @@ -1571,9 +1586,10 @@ public abstract class AbstractSurefireMojo @SuppressWarnings( "checkstyle:modifierorder" ) private @Nonnull List<String> getExcludeList() + throws MojoFailureException { List<String> actualExcludes = null; - if ( isSpecificTestSpecified() )//! + if ( isSpecificTestSpecified() ) { // Check to see if we are running a single test. The raw parameter will // come through if it has not been set. @@ -1583,21 +1599,23 @@ public abstract class AbstractSurefireMojo } else { - if ( getExcludesFile() != null )//! + if ( getExcludesFile() != null ) { - actualExcludes = readListFromFile( getExcludesFile() );//! + actualExcludes = readListFromFile( getExcludesFile() ); } // If we have excludesFile, and we have excludes, then append excludes to excludesFile content if ( actualExcludes == null ) { - actualExcludes = getExcludes();//! + actualExcludes = getExcludes(); } else { - maybeAppendList( actualExcludes, getExcludes() );//! + maybeAppendList( actualExcludes, getExcludes() ); } + checkMethodFilterInIncludesExcludes( actualExcludes ); + // defaults here, qdox doesn't like the end javadoc value // Have to wrap in an ArrayList as surefire expects an ArrayList instead of a List for some reason if ( actualExcludes == null || actualExcludes.isEmpty() ) @@ -1609,40 +1627,79 @@ public abstract class AbstractSurefireMojo } private List<String> getIncludeList() + throws MojoFailureException { List<String> includes = null; - if ( isSpecificTestSpecified() && !isMultipleExecutionBlocksDetected() )//! + if ( isSpecificTestSpecified() && !isMultipleExecutionBlocksDetected() ) { - includes = getSpecificTests();//! + includes = Arrays.asList( getTest() ); } else { - if ( getIncludesFile() != null )//! + if ( getIncludesFile() != null ) { - includes = readListFromFile( getIncludesFile() );//! + includes = readListFromFile( getIncludesFile() ); } // If we have includesFile, and we have includes, then append includes to includesFile content if ( includes == null ) { - includes = getIncludes();//! + includes = getIncludes(); } else { - maybeAppendList( includes, getIncludes() );//! + maybeAppendList( includes, getIncludes() ); } + + checkMethodFilterInIncludesExcludes( includes ); } // defaults here, qdox doesn't like the end javadoc value // Have to wrap in an ArrayList as surefire expects an ArrayList instead of a List for some reason if ( includes == null || includes.isEmpty() ) { - includes = Arrays.asList( getDefaultIncludes() );//! + includes = Arrays.asList( getDefaultIncludes() ); } return filterNulls( includes ); } + private void checkMethodFilterInIncludesExcludes( Iterable<String> patterns ) + throws MojoFailureException + { + if ( patterns != null ) + { + for ( String pattern : patterns ) + { + if ( pattern != null && pattern.contains( "#" ) ) + { + throw new MojoFailureException( "Method filter prohibited in " + + "includes|excludes|includesFile|excludesFile parameter: " + + pattern ); + } + } + } + } + + private TestListResolver getIncludedAndExcludedTests() + throws MojoFailureException + { + if ( includedExcludedTests == null ) + { + includedExcludedTests = new TestListResolver( getIncludeList(), getExcludeList() ); + } + return includedExcludedTests; + } + + public TestListResolver getSpecificTests() + { + if ( specificTests == null ) + { + specificTests = new TestListResolver( getTest() ); + } + return specificTests; + } + @SuppressWarnings( "checkstyle:modifierorder" ) private @Nonnull List<String> filterNulls( @Nonnull List<String> toFilter ) { @@ -1676,28 +1733,6 @@ public abstract class AbstractSurefireMojo return false; } - private List<String> getSpecificTests() - { - if ( isSpecificTestSpecified() )//! - { - List<String> specificTests = new ArrayList<String>(); - for ( String testRegex : getTest().getTestSpecificClasses() )//! - { - if ( testRegex.endsWith( JAVA_EXTENSION ) ) - { - testRegex = testRegex.substring( 0, testRegex.length() - JAVA_EXTENSION.length() ); - } - testRegex = testRegex.replace( '.', '/' ); - specificTests.add( "**/" + testRegex + JAVA_EXTENSION ); - } - return specificTests; - } - else - { - return Collections.emptyList(); - } - } - private Artifact getTestNgArtifact() throws MojoExecutionException { @@ -1747,7 +1782,7 @@ public abstract class AbstractSurefireMojo StartupConfiguration startupConfiguration = createStartupConfiguration( provider, classLoaderConfiguration ); String configChecksum = getConfigChecksum(); StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum ); - ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );//! getTest + ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters ); return new ForkStarter( providerConfiguration, startupConfiguration, forkConfiguration, getForkedProcessTimeoutInSeconds(), startupReportConfiguration, log ); } @@ -1760,7 +1795,7 @@ public abstract class AbstractSurefireMojo StartupConfiguration startupConfiguration = createStartupConfiguration( provider, classLoaderConfiguration ); String configChecksum = getConfigChecksum(); StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum ); - ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );//! getTest + ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters ); return new InPluginVMSurefireStarter( startupConfiguration, providerConfiguration, startupReportConfiguration ); } @@ -1917,9 +1952,9 @@ public abstract class AbstractSurefireMojo checksum.add( getAdditionalClasspathElements() ); checksum.add( getReportsDirectory() ); checksum.add( getTestSourceDirectory() ); - checksum.add( isSpecificTestSpecified() ? getTest().getPluginParameterTest() : null );//! - checksum.add( getIncludes() );//! - checksum.add( getExcludes() );//! + checksum.add( getTest() ); + checksum.add( getIncludes() ); + checksum.add( getExcludes() ); checksum.add( getLocalRepository() ); checksum.add( getSystemProperties() ); checksum.add( getSystemPropertyVariables() ); http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java ---------------------------------------------------------------------- diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java index 566c91f..48e3fd9 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java @@ -22,7 +22,6 @@ package org.apache.maven.plugin.surefire; import java.io.File; import java.util.List; import org.apache.maven.artifact.repository.ArtifactRepository; -import org.apache.maven.surefire.testset.TestListResolver; /** * This interface contains all the common parameters that have different implementations in Surefire vs IntegrationTest @@ -64,7 +63,7 @@ public interface SurefireExecutionParameters void setTestSourceDirectory( File testSourceDirectory ); - TestListResolver getTest(); + String getTest(); void setTest( String test ); http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java ---------------------------------------------------------------------- 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 bfdce4e..c8d1b3a 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 @@ -34,6 +34,7 @@ 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; @@ -93,8 +94,10 @@ class BooterSerializer { properties.setProperty( BooterConstants.SOURCE_DIRECTORY, testSuiteDefinition.getTestSourceDirectory() ); properties.addList( testSuiteDefinition.getSuiteXmlFiles(), BooterConstants.TEST_SUITE_XML_FILES ); - properties.setNullableProperty( BooterConstants.REQUESTEDTEST, - testSuiteDefinition.getTestListResolver().getPluginParameterTest() ); + TestListResolver methodFilter = testSuiteDefinition.getTestListResolver(); + String requestedTest = + methodFilter == null || methodFilter.isEmpty() ? null : methodFilter.getPluginParameterTest(); + properties.setNullableProperty( BooterConstants.REQUESTEDTEST, requestedTest ); properties.setNullableProperty( BooterConstants.RERUN_FAILING_TESTS_COUNT, String.valueOf( testSuiteDefinition.getRerunFailingTestsCount() ) ); } http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DependencyScanner.java ---------------------------------------------------------------------- diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DependencyScanner.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DependencyScanner.java index 356640e..1fb14f5 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DependencyScanner.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DependencyScanner.java @@ -20,25 +20,23 @@ package org.apache.maven.plugin.surefire.util; */ import static org.apache.maven.plugin.surefire.util.ScannerUtil.convertJarFileResourceToJavaClassName; -import static org.apache.maven.plugin.surefire.util.ScannerUtil.convertSlashToSystemFileSeparator; -import static org.apache.maven.plugin.surefire.util.ScannerUtil.processIncludesExcludes; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.shared.utils.io.MatchPatterns; +import org.apache.maven.surefire.testset.TestFilter; +import org.apache.maven.surefire.testset.TestListResolver; import org.apache.maven.surefire.util.DefaultScanResult; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - /** * Scans dependencies looking for tests. * @@ -46,77 +44,64 @@ import javax.annotation.Nullable; */ public class DependencyScanner { - private final List<File> dependenciesToScan; - protected final List<String> includes; + private final TestListResolver includedAndExcludedTests; - @SuppressWarnings( "checkstyle:modifierorder" ) - protected final @Nonnull List<String> excludes; + private final TestListResolver specificTests; - protected final List<String> specificTests; - - public DependencyScanner( List<File> dependenciesToScan, List<String> includes, @Nonnull List<String> excludes, - List<String> specificTests ) + public DependencyScanner( List<File> dependenciesToScan, + TestListResolver includedAndExcludedTests, TestListResolver specificTests ) { this.dependenciesToScan = dependenciesToScan; - this.includes = includes; - this.excludes = excludes; + this.includedAndExcludedTests = includedAndExcludedTests; this.specificTests = specificTests; } public DefaultScanResult scan() throws MojoExecutionException { - Matcher matcher = new Matcher( includes, excludes, specificTests ); - List<String> found = new ArrayList<String>(); + Set<String> classes = new LinkedHashSet<String>(); for ( File artifact : dependenciesToScan ) { try { - found.addAll( scanArtifact( artifact, matcher ) ); + scanArtifact( artifact, includedAndExcludedTests.and( specificTests ), classes ); } catch ( IOException e ) { throw new MojoExecutionException( "Could not scan dependency " + artifact.toString(), e ); } } - return new DefaultScanResult( found ); + return new DefaultScanResult( new ArrayList<String>( classes ) ); } - private List<String> scanArtifact( File artifact, Matcher matcher ) + private static void scanArtifact( File artifact, TestFilter<String, String> filter, Set<String> classes ) throws IOException { - List<String> found = new ArrayList<String>(); - - if ( artifact != null ) + if ( artifact != null && artifact.isFile() ) { - if ( artifact.isFile() ) + JarFile jar = null; + try { - JarFile jar = null; - try + jar = new JarFile( artifact ); + for ( Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements(); ) { - jar = new JarFile( artifact ); - Enumeration<JarEntry> entries = jar.entries(); - while ( entries.hasMoreElements() ) + JarEntry entry = entries.nextElement(); + if ( filter.shouldRun( entry.getName(), null ) ) { - JarEntry entry = entries.nextElement(); - if ( matcher.shouldInclude( entry.getName() ) ) - { - found.add( convertJarFileResourceToJavaClassName( entry.getName() ) ); - } + classes.add( convertJarFileResourceToJavaClassName( entry.getName() ) ); } } - finally + } + finally + { + if ( jar != null ) { - if ( jar != null ) - { - jar.close(); - } + jar.close(); } } } - return found; } public static List<File> filter( List<Artifact> artifacts, List<String> groupArtifactIds ) @@ -145,44 +130,4 @@ public class DependencyScanner } return matches; } - - private class Matcher - { - - private MatchPatterns includes; - - private MatchPatterns excludes; - - private SpecificFileFilter specificTestFilter; - - public Matcher( @Nullable List<String> includes, @Nonnull List<String> excludes, - @Nullable List<String> specificTests ) - { - String[] specific = specificTests == null ? new String[0] : processIncludesExcludes( specificTests ); - specificTestFilter = new SpecificFileFilter( specific ); - - if ( includes != null && !includes.isEmpty() ) - { - this.includes = MatchPatterns.from( processIncludesExcludes( includes ) ); - } - else - { - this.includes = MatchPatterns.from( "**" ); - } - this.excludes = MatchPatterns.from( processIncludesExcludes( excludes ) ); - } - - public boolean shouldInclude( String name ) - { - if ( !name.endsWith( ".class" ) ) - { - return false; - } - name = convertSlashToSystemFileSeparator( name ); - boolean isIncluded = includes.matches( name, false ); - boolean isExcluded = excludes.matches( name, false ); - - return isIncluded && !isExcluded && specificTestFilter.accept( name ); - } - } } http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java ---------------------------------------------------------------------- diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java index 01fcc51..8b4c434 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java @@ -19,15 +19,11 @@ package org.apache.maven.plugin.surefire.util; * under the License. */ -import static org.apache.maven.plugin.surefire.util.ScannerUtil.convertSlashToSystemFileSeparator; -import static org.apache.maven.plugin.surefire.util.ScannerUtil.convertToJavaClassName; -import static org.apache.maven.plugin.surefire.util.ScannerUtil.processIncludesExcludes; -import static org.apache.maven.plugin.surefire.util.ScannerUtil.stripBaseDir; - import java.io.File; import java.util.ArrayList; import java.util.List; +import org.apache.maven.surefire.testset.TestListResolver; import org.apache.maven.surefire.util.DefaultScanResult; /** @@ -40,54 +36,24 @@ public class DirectoryScanner { private final File basedir; - private final List<String> includes; - - private final List<String> excludes; + private final TestListResolver includedAndExcludedTests; - private final List<String> specificTests; + private final TestListResolver specificTests; - public DirectoryScanner( File basedir, List<String> includes, List<String> excludes, List<String> specificTests ) + public DirectoryScanner( File basedir, TestListResolver includedAndExcludedTests, TestListResolver specificTests ) { this.basedir = basedir; - this.includes = includes; - this.excludes = excludes; + this.includedAndExcludedTests = includedAndExcludedTests; this.specificTests = specificTests; } public DefaultScanResult scan() { - String[] specific = specificTests == null ? new String[0] : processIncludesExcludes( specificTests ); - SpecificFileFilter specificTestFilter = new SpecificFileFilter( specific ); - + FileScanner scanner = new FileScanner( basedir, "class" ); List<String> result = new ArrayList<String>(); - if ( basedir.exists() ) - { - org.apache.maven.shared.utils.io.DirectoryScanner scanner = - new org.apache.maven.shared.utils.io.DirectoryScanner(); - - scanner.setBasedir( basedir ); - - if ( includes != null ) - { - scanner.setIncludes( processIncludesExcludes( includes ) ); - } - - if ( excludes != null ) - { - scanner.setExcludes( processIncludesExcludes( excludes ) ); - } - - scanner.scan(); - for ( String test : scanner.getIncludedFiles() ) - { - if ( specificTestFilter.accept( - convertSlashToSystemFileSeparator( - stripBaseDir( basedir.getAbsolutePath(), test ) ) ) ) - { - result.add( convertToJavaClassName( test ) ); - } - } - } + TestListResolver includedExcludedClasses = includedAndExcludedTests.createClassFilters(); + TestListResolver specificClasses = specificTests.createClassFilters(); + scanner.scanTo( result, includedExcludedClasses.and( specificClasses ) ); return new DefaultScanResult( result ); } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/FileScanner.java ---------------------------------------------------------------------- diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/FileScanner.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/FileScanner.java new file mode 100644 index 0000000..02a51ab --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/FileScanner.java @@ -0,0 +1,126 @@ +package org.apache.maven.plugin.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.surefire.testset.TestFilter; + +import java.io.File; +import java.util.Collection; + +import static org.apache.maven.surefire.util.internal.StringUtils.isBlank; + +final class FileScanner +{ + private static final String CLASS_FILE_EXTENSION = ".class"; + + private final File basedir; + + private final String ext; + + FileScanner( File basedir, String ext ) + { + this.basedir = basedir; + ext = isBlank( ext ) ? null : ext.trim(); + this.ext = ext == null || ext.startsWith( "." ) ? ext : "." + ext; + } + + void scanTo( Collection<String> scannedJavaClassNames, TestFilter<String, String> filter ) + { + scan( scannedJavaClassNames, filter, basedir ); + } + + private void scan( Collection<String> scannedJavaClassNames, + TestFilter<String, String> filter, File basedir, String... subDirectories ) + { + File[] filesAndDirs = basedir.listFiles(); + if ( filesAndDirs != null ) + { + final String pAckage = toJavaPackage( subDirectories ); + final String path = toPath( subDirectories ); + final String ext = this.ext; + final boolean hasExtension = ext != null; + final int extLength = hasExtension ? ext.length() : 0; + for ( File fileOrDir : filesAndDirs ) + { + String name = fileOrDir.getName(); + if ( name.length() != 0 ) + { + if ( fileOrDir.isFile() ) + { + final int clsLength = name.length() - extLength; + if ( clsLength > 0 + && ( !hasExtension || name.regionMatches( true, clsLength, ext, 0, extLength ) ) ) + { + String simpleClassName = hasExtension ? name.substring( 0, clsLength ) : name; + if ( filter.shouldRun( toFile( path, simpleClassName ), null ) ) + { + String fullyQualifiedClassName = + pAckage.length() == 0 ? simpleClassName : pAckage + '.' + simpleClassName; + scannedJavaClassNames.add( fullyQualifiedClassName ); + } + } + } + else if ( fileOrDir.isDirectory() ) + { + String[] paths = new String[subDirectories.length + 1]; + System.arraycopy( subDirectories, 0, paths, 0, subDirectories.length ); + paths[subDirectories.length] = name; + scan( scannedJavaClassNames, filter, fileOrDir, paths ); + } + } + } + } + } + + private static String toJavaPackage( String... subDirectories ) + { + StringBuilder pkg = new StringBuilder(); + for ( int i = 0; i < subDirectories.length; i++ ) + { + if ( i > 0 && i < subDirectories.length ) + { + pkg.append( '.' ); + } + pkg.append( subDirectories[i] ); + } + return pkg.toString(); + } + + private static String toPath( String... subDirectories ) + { + StringBuilder pkg = new StringBuilder(); + for ( int i = 0; i < subDirectories.length; i++ ) + { + if ( i > 0 && i < subDirectories.length ) + { + pkg.append( '/' ); + } + pkg.append( subDirectories[i] ); + } + return pkg.toString(); + } + + private static String toFile( String path, String fileNameWithoutExtension ) + { + String pathWithoutExtension = + path.length() == 0 ? fileNameWithoutExtension : path + '/' + fileNameWithoutExtension; + return pathWithoutExtension + CLASS_FILE_EXTENSION; + } +} http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/ScannerUtil.java ---------------------------------------------------------------------- diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/ScannerUtil.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/ScannerUtil.java index e3ff45d..8452a7a 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/ScannerUtil.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/ScannerUtil.java @@ -19,12 +19,7 @@ package org.apache.maven.plugin.surefire.util; * under the License. */ -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import org.apache.commons.lang3.StringUtils; - import javax.annotation.Nonnull; final class ScannerUtil @@ -36,19 +31,9 @@ final class ScannerUtil private static final String FS = System.getProperty( "file.separator" ); - private static final String JAVA_SOURCE_FILE_EXTENSION = ".java"; - - private static final String JAVA_CLASS_FILE_EXTENSION = ".class"; - private static final boolean IS_NON_UNIX_FS = ( !FS.equals( "/" ) ); @SuppressWarnings( "checkstyle:modifierorder" ) - public static @Nonnull String convertToJavaClassName( @Nonnull String test ) - { - return StringUtils.removeEnd( test, ".class" ).replace( FS, "." ); - } - - @SuppressWarnings( "checkstyle:modifierorder" ) public static @Nonnull String convertJarFileResourceToJavaClassName( @Nonnull String test ) { return StringUtils.removeEnd( test, ".class" ).replace( "/", "." ); @@ -59,36 +44,4 @@ final class ScannerUtil { return ( IS_NON_UNIX_FS ? path.replace( "/", FS ) : path ); } - - @SuppressWarnings( "checkstyle:modifierorder" ) - public static @Nonnull String stripBaseDir( String basedir, String test ) - { - return StringUtils.removeStart( test, basedir ); - } - - @SuppressWarnings( "checkstyle:modifierorder" ) - public static @Nonnull String[] processIncludesExcludes( @Nonnull List<String> list ) - { - List<String> newList = new ArrayList<String>(); - for ( Object aList : list ) - { - String include = (String) aList; - String[] includes = include.split( "," ); - Collections.addAll( newList, includes ); - } - - String[] incs = new String[newList.size()]; - - for ( int i = 0; i < incs.length; i++ ) - { - String inc = newList.get( i ); - if ( inc.endsWith( JAVA_SOURCE_FILE_EXTENSION ) ) - { - inc = StringUtils.removeEnd( inc, JAVA_SOURCE_FILE_EXTENSION ) + JAVA_CLASS_FILE_EXTENSION; - } - incs[i] = convertSlashToSystemFileSeparator( inc ); - - } - return incs; - } } http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/SpecificFileFilter.java ---------------------------------------------------------------------- diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/SpecificFileFilter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/SpecificFileFilter.java index f168d32..912f274 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/SpecificFileFilter.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/SpecificFileFilter.java @@ -32,6 +32,7 @@ import static org.apache.maven.plugin.surefire.util.ScannerUtil.convertSlashToSy * filters file names by a given collection of class name patterns * */ +@Deprecated public class SpecificFileFilter { http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java ---------------------------------------------------------------------- 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 94d89df..1713476 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 @@ -133,12 +133,12 @@ public class BooterDeserializerProviderConfigurationTest Assert.assertNotNull( resolver ); Assert.assertFalse( resolver.isEmpty() ); Assert.assertEquals( aUserRequestedTest + "#" + aUserRequestedTestMethod, resolver.getPluginParameterTest() ); - Assert.assertFalse( resolver.getIncludedFilters().isEmpty() ); - Assert.assertTrue( resolver.getExcludedFilters().isEmpty() ); - Assert.assertEquals( 1, resolver.getIncludedFilters().size() ); - ResolvedTest filter = resolver.getIncludedFilters().iterator().next(); + Assert.assertFalse( resolver.getIncludedPatterns().isEmpty() ); + Assert.assertTrue( resolver.getExcludedPatterns().isEmpty() ); + Assert.assertEquals( 1, resolver.getIncludedPatterns().size() ); + ResolvedTest filter = resolver.getIncludedPatterns().iterator().next(); Assert.assertNotNull( filter ); - Assert.assertEquals( aUserRequestedTest + ".class", filter.getTestClassPattern() ); + Assert.assertEquals( "**/" + aUserRequestedTest, filter.getTestClassPattern() ); Assert.assertEquals( aUserRequestedTestMethod, filter.getTestMethodPattern() ); Assert.assertEquals( rerunFailingTestsCount, testSuiteDefinition.getRerunFailingTestsCount() ); } http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DependenciesScannerTest.java ---------------------------------------------------------------------- diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DependenciesScannerTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DependenciesScannerTest.java index c897e1e..3fc0976 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DependenciesScannerTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DependenciesScannerTest.java @@ -36,6 +36,7 @@ import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.surefire.testset.TestListResolver; import org.apache.maven.surefire.testset.TestSetFailedException; import org.apache.maven.surefire.util.ScanResult; @@ -65,7 +66,7 @@ public class DependenciesScannerTest DependencyScanner scanner = new DependencyScanner( DependencyScanner.filter(Arrays.asList(artifact), scanDependencies), - include, exclude, new ArrayList<String>() ); + new TestListResolver( include, exclude ), new TestListResolver( "" ) ); ScanResult classNames = scanner.scan(); assertNotNull( classNames ); http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java ---------------------------------------------------------------------- diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java index bf3d383..4c41854 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java @@ -25,6 +25,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; + +import org.apache.maven.surefire.testset.TestListResolver; import org.apache.maven.surefire.testset.TestSetFailedException; import org.apache.maven.surefire.util.ScanResult; @@ -37,7 +39,7 @@ public class DirectoryScannerTest extends TestCase { public void testLocateTestClasses() - throws IOException, TestSetFailedException + throws Exception { // use target as people can configure ide to compile in an other place than maven File baseDir = new File( new File( "target/test-classes" ).getCanonicalPath() ); @@ -46,7 +48,7 @@ public class DirectoryScannerTest List<String> exclude = new ArrayList<String>(); DirectoryScanner surefireDirectoryScanner = - new DirectoryScanner( baseDir, include, exclude, new ArrayList<String>() ); + new DirectoryScanner( baseDir, new TestListResolver( include, exclude ), new TestListResolver( "" ) ); ScanResult classNames = surefireDirectoryScanner.scan(); assertNotNull( classNames ); http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java ---------------------------------------------------------------------- diff --git a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java index 988cddc..8d45d61 100644 --- a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java +++ b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java @@ -28,7 +28,6 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.surefire.suite.RunResult; -import org.apache.maven.surefire.testset.TestListResolver; /** * Run tests using Surefire. @@ -65,7 +64,15 @@ public class SurefirePlugin * parameter. * <p/> * Since 2.7.3, you can execute a limited number of methods in the test by adding #myMethod or #my*ethod. For - * example, "-Dtest=MyTest#myMethod". This is supported for junit 4.x and testNg. + * example, "-Dtest=MyTest#myMethod". This is supported for junit 4.x and testNg.<br/> + * <br/> + * Since 2.19 a complex syntax is supported in one parameter (JUnit 4, JUnit 4.7+, TestNG):<br/> + * "-Dtest=???Test, !Unstable*, pkg/**/Ci*leTest.java, *Test#test*One+testTwo?????, #fast*+slowTest"<br/> + * "-Dtest=Basic*, !%regex[.*.Unstable.*], !%regex[.*.MyTest.class#one.*|two.*], %regex[#fast.*|slow.*]"<br/> + * <br/> + * The Parameterized JUnit runner <em>describes</em> test methods using an index in brackets, so the non-regex + * method pattern would become: <em>#testMethod[*]</em>. + * <br/> */ @Parameter( property = "test" ) private String test; @@ -158,6 +165,8 @@ public class SurefirePlugin * <p/> * Each include item may also contain a comma-separated sublist of items, which will be treated as multiple * <include> entries.<br/> + * Since 2.19 a complex syntax is supported in one parameter (JUnit 4, JUnit 4.7+, TestNG):<br/> + * <include>%regex[.*[Cat|Dog].*], !%regex[pkg.*Slow.*.class], pkg/**/*Fast*.java, Basic????, !Unstable*</include><br/> * <p/> * This parameter is ignored if the TestNG <code>suiteXmlFiles</code> parameter is specified.<br/> * <br/> @@ -236,8 +245,6 @@ public class SurefirePlugin @Parameter( property = "surefire.runOrder", defaultValue = "filesystem" ) protected String runOrder; - private TestListResolver testListResolver; - protected int getRerunFailingTestsCount() { return rerunFailingTestsCount; @@ -372,13 +379,9 @@ public class SurefirePlugin this.reportsDirectory = reportsDirectory; } - public TestListResolver getTest() + public String getTest() { - if ( testListResolver == null && test != null ) - { - testListResolver = new TestListResolver( test ); - } - return testListResolver; + return test; } public boolean isUseSystemClassLoader() http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-surefire-plugin/src/site/apt/examples/inclusion-exclusion.apt.vm ---------------------------------------------------------------------- diff --git a/maven-surefire-plugin/src/site/apt/examples/inclusion-exclusion.apt.vm b/maven-surefire-plugin/src/site/apt/examples/inclusion-exclusion.apt.vm index 6992294..515fa18 100644 --- a/maven-surefire-plugin/src/site/apt/examples/inclusion-exclusion.apt.vm +++ b/maven-surefire-plugin/src/site/apt/examples/inclusion-exclusion.apt.vm @@ -162,3 +162,19 @@ Inclusions and Exclusions of Tests Note the syntax <<<%regex[expr]>>>, where <<<expr>>> is the actual expression and the rest is just wrapping. Also note that regex matches are done over <<<*.class>>> files and not <<<*.java>>> files. + +* Multiple Formats in One + + As of ${thisPlugin} Plugin 2.19, a complex syntax is supported in one parameter (JUnit 4, JUnit 4.7+, TestNG): ++---+ + [...] + <include>%regex[.*[Cat|Dog].*], !%regex[pkg.*Slow.*.class], pkg/**/*Fast*.java, Basic????, !Unstable*</include> + [...] + <exclude>%regex[pkg.*Slow.*.class], Unstable*</exclude> + [...] ++---+ + This syntax can be used in parameters: test, includes, excludes, includesFile, excludesFile. + Exclamation mark (!) excludes tests. The syntax in excludes and excludesFile should not use (!). The character (?) + within non-regex pattern replaces one character in file name or path. The file extensions are not mandatory in + non-regex patterns, and packages with slash can be used. The regex validates fully qualified class file. + The regex supports '.class' file extension only. Note the regex comments, marked by (#) character, are unsupported. http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/maven-surefire-plugin/src/site/apt/examples/single-test.apt.vm ---------------------------------------------------------------------- diff --git a/maven-surefire-plugin/src/site/apt/examples/single-test.apt.vm b/maven-surefire-plugin/src/site/apt/examples/single-test.apt.vm index d069ab7..2ee087e 100644 --- a/maven-surefire-plugin/src/site/apt/examples/single-test.apt.vm +++ b/maven-surefire-plugin/src/site/apt/examples/single-test.apt.vm @@ -103,7 +103,7 @@ mvn -Dit.test=ITCircle#test* verify +---+ #{end} - As of Surefire 2.12.1, you can select multiple methods (JUnit 4.x only at this time; patches welcome!): + Since of ${thisPlugin} Plugin 2.19 you can select multiple methods (JUnit 4, JUnit 4.7+ and TestNG): #{if}(${project.artifactId}=="maven-surefire-plugin") +---+ @@ -114,3 +114,27 @@ mvn -Dtest=TestCircle#testOne+testTwo test mvn -Dit.test=ITCircle#testOne+testTwo verify +---+ #{end} + + Note this feature was available in JUnit 4 provider only since of ${thisPlugin} Plugin 2.12.1. + + + As of ${thisPlugin} Plugin 2.19 multiple formats are supported in one pattern (JUnit 4, JUnit 4.7+, TestNG): + +#{if}(${project.artifactId}=="maven-surefire-plugin") ++---+ +mvn "-Dtest=???Test, !Unstable*, pkg/**/Ci*leTest.java, *Test#test*One+testTwo?????, #fast*+slowTest" test +mvn "-Dtest=Basic*, !%regex[.*.Unstable.*], !%regex[.*.MyTest.class#one.*|two.*], %regex[#fast.*|slow.*]" ++---+ +#{else} ++---+ +mvn "-Dit.test=???IT, !Unstable*, pkg/**/Ci*leIT.java, *IT#test*One+testTwo?????, #fast*+slowTest" verify +mvn "-Dit.test=Basic*, !%regex[.*.Unstable.*], !%regex[.*.MyIT.class#one.*|two.*], %regex[#fast.*|slow.*]" verify ++---+ +#{end} + + The exclamation mark (!) excludes tests. The character (?) within non-regex pattern replaces one character in file + name or path. The file extensions are not mandatory in non-regex patterns, and packages with slash can be used. + The regex validates fully qualified class file, and validates test methods separately after (#) however class + is optional. The regex supports '.class' file extension only. Note the regex comments, marked by (#) + character, are unsupported. The Parameterized JUnit runner describes test methods using an index in brackets, so the + non-regex method pattern would become: <<<#testMethod[*]>>>. http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java ---------------------------------------------------------------------- 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 06048e9..cc9e91c 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 @@ -89,6 +89,7 @@ public interface ProviderParameters * @return The parameters * @deprecated Use scanresult instead, as of version 2.12.2. Will be removed in next major version. */ + @Deprecated DirectoryScannerParameters getDirectoryScannerParameters(); /** http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/surefire-api/src/main/java/org/apache/maven/surefire/testset/GenericTestPattern.java ---------------------------------------------------------------------- diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/testset/GenericTestPattern.java b/surefire-api/src/main/java/org/apache/maven/surefire/testset/GenericTestPattern.java new file mode 100644 index 0000000..585351c --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/surefire/testset/GenericTestPattern.java @@ -0,0 +1,54 @@ +package org.apache.maven.surefire.testset; + +/* + * 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.Set; + +/** + * Resolves string test patterns in object oriented patterns {@code P}. + * + * @param <T> itself + * @param <P> resolved atomic test, object oriented - not necessary to be a string + * @param <C> test class, or null if not mandatory + * @param <M> test method, or null if not mandatory + */ +public interface GenericTestPattern<T extends GenericTestPattern, P, C, M> + extends TestFilter<C, M> +{ + boolean hasIncludedMethodPatterns(); + + boolean hasExcludedMethodPatterns(); + + boolean hasMethodPatterns(); + + T createMethodFilters(); + + T createClassFilters(); + + boolean isEmpty(); + + String getPluginParameterTest(); + + Set<P> getIncludedPatterns(); + + Set<P> getExcludedPatterns(); + + Set<String> getTestSpecificClasses(); +} http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/surefire-api/src/main/java/org/apache/maven/surefire/testset/IncludedExcludedPatterns.java ---------------------------------------------------------------------- diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/testset/IncludedExcludedPatterns.java b/surefire-api/src/main/java/org/apache/maven/surefire/testset/IncludedExcludedPatterns.java new file mode 100644 index 0000000..bc5c5d4 --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/surefire/testset/IncludedExcludedPatterns.java @@ -0,0 +1,27 @@ +package org.apache.maven.surefire.testset; + +/* + * 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. + */ + +final class IncludedExcludedPatterns +{ + boolean hasExcludedMethodPatterns; + + boolean hasIncludedMethodPatterns; +} http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/surefire-api/src/main/java/org/apache/maven/surefire/testset/ResolvedTest.java ---------------------------------------------------------------------- diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/testset/ResolvedTest.java b/surefire-api/src/main/java/org/apache/maven/surefire/testset/ResolvedTest.java index 79f4174..635010e 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/testset/ResolvedTest.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/testset/ResolvedTest.java @@ -19,47 +19,91 @@ package org.apache.maven.surefire.testset; * under the License. */ +import org.apache.maven.shared.utils.StringUtils; +import org.apache.maven.shared.utils.io.MatchPatterns; import org.apache.maven.shared.utils.io.SelectorUtils; -import java.util.Map; +import java.io.File; /** * Single pattern test filter resolved from multi pattern filter -Dtest=MyTest#test,AnotherTest#otherTest. */ public final class ResolvedTest { + /** + * Type of patterns in ResolvedTest constructor. + */ + public static enum Type + { + CLASS, METHOD + } + private static final String CLASS_FILE_EXTENSION = ".class"; private static final String JAVA_FILE_EXTENSION = ".java"; + private static final String WILDCARD_PATH_PREFIX = "**/"; + + private static final String WILDCARD_FILENAME_POSTFIX = ".*"; + private final String classPattern; private final String methodPattern; - private final Map<Class<?>, String> classConversion; - private final boolean isRegexTestClassPattern; private final boolean isRegexTestMethodPattern; + private final String description; + /** * '*' means zero or more characters<br> * '?' means one and only one character - * The %ant[] expression is substituted by %regex[]. + * The pattern %regex[] prefix and suffix does not appear. The regex <code>pattern</code> is always + * unwrapped by the caller. * * @param classPattern test class file pattern * @param methodPattern test method - * @throws IllegalArgumentException if regex not finished with ']' + * @param isRegex {@code true} if regex + */ + public ResolvedTest( String classPattern, String methodPattern, boolean isRegex ) + { + classPattern = tryBlank( classPattern ); + methodPattern = tryBlank( methodPattern ); + description = description( classPattern, methodPattern, isRegex ); + + if ( isRegex && classPattern != null ) + { + classPattern = wrapRegex( classPattern ); + } + + if ( isRegex && methodPattern != null ) + { + methodPattern = wrapRegex( methodPattern ); + } + + this.classPattern = reformatClassPattern( classPattern, isRegex ); + this.methodPattern = methodPattern; + isRegexTestClassPattern = isRegex; + isRegexTestMethodPattern = isRegex; + } + + /** + * The regex <code>pattern</code> is always unwrapped. */ - ResolvedTest( String classPattern, String methodPattern, Map<Class<?>, String> classConversion ) + public ResolvedTest( Type type, String pattern, boolean isRegex ) { - this.classPattern = reformatPattern( classPattern, true ); - this.methodPattern = reformatPattern( methodPattern, false ); - this.classConversion = classConversion; - isRegexTestClassPattern = - this.classPattern != null && this.classPattern.startsWith( SelectorUtils.REGEX_HANDLER_PREFIX ); - isRegexTestMethodPattern = - this.methodPattern != null && this.methodPattern.startsWith( SelectorUtils.REGEX_HANDLER_PREFIX ); + pattern = tryBlank( pattern ); + final boolean isClass = type == Type.CLASS; + description = description( isClass ? pattern : null, !isClass ? pattern : null, isRegex ); + if ( isRegex && pattern != null ) + { + pattern = wrapRegex( pattern ); + } + classPattern = isClass ? reformatClassPattern( pattern, isRegex ) : null; + methodPattern = !isClass ? pattern : null; + isRegexTestClassPattern = isRegex && isClass; + isRegexTestMethodPattern = isRegex && !isClass; } /** @@ -74,6 +118,11 @@ public final class ResolvedTest return classPattern; } + public boolean hasTestClassPattern() + { + return classPattern != null; + } + /** * Test method, e.g. "realTestMethod".<br/> * Other examples: test* or testSomethin? or %regex[testOne|testTwo] or %ant[testOne|testTwo]<br/> @@ -86,6 +135,11 @@ public final class ResolvedTest return methodPattern; } + public boolean hasTestMethodPattern() + { + return methodPattern != null; + } + public boolean isRegexTestClassPattern() { return isRegexTestClassPattern; @@ -101,42 +155,34 @@ public final class ResolvedTest return classPattern == null && methodPattern == null; } - public boolean shouldRun( Class<?> realTestClass, String methodName ) + public boolean shouldRun( String testClassFile, String methodName ) { - if ( methodPattern != null ) + if ( isEmpty() ) + { + return true; + } + + boolean matchedMethodPattern = false; + + if ( methodPattern != null && methodName != null ) { - if ( methodName != null && !SelectorUtils.matchPath( methodPattern, methodName ) ) + if ( SelectorUtils.matchPath( methodPattern, methodName ) ) + { + matchedMethodPattern = true; + } + else { return false; } } - if ( classPattern == null ) + if ( classPattern != null ) { - return methodName != null; + return isRegexTestClassPattern ? matchClassRegexPatter( testClassFile ) : matchClassPatter( testClassFile ); } else { - String classFile = classFile( realTestClass ); - if ( isRegexTestClassPattern() ) - { - String pattern = classPattern.indexOf( '$' ) == -1 ? classPattern : classPattern.replace( "$", "\\$" ); - return SelectorUtils.matchPath( pattern, classFile ); - } - else - { - if ( SelectorUtils.matchPath( classPattern, classFile ) ) - { - // match class pattern with package - return true; - } - else - { - int indexOfSimpleName = classFile.lastIndexOf( '/' ); - return indexOfSimpleName != -1 - && SelectorUtils.matchPath( classPattern, classFile.substring( 1 + indexOfSimpleName ) ); - } - } + return matchedMethodPattern; } } @@ -156,7 +202,6 @@ public final class ResolvedTest return ( classPattern == null ? that.classPattern == null : classPattern.equals( that.classPattern ) ) && ( methodPattern == null ? that.methodPattern == null : methodPattern.equals( that.methodPattern ) ); - } @Override @@ -170,27 +215,59 @@ public final class ResolvedTest @Override public String toString() { - return "ResolvedTest{classPattern='" + classPattern + "', methodPattern='" + methodPattern + "'}"; + return isEmpty() ? null : description; + } + + private static String description( String clazz, String method, boolean isRegex ) + { + String description; + if ( clazz == null && method == null ) + { + description = null; + } + else if ( clazz == null ) + { + description = "#" + method; + } + else if ( method == null ) + { + description = clazz; + } + else + { + description = clazz + "#" + method; + } + return isRegex && description != null ? wrapRegex( description ) : description; } - private String classFile( Class<?> realTestClass ) + private boolean matchClassPatter( String testClassFile ) { - String classFile = classConversion.get( realTestClass ); - if ( classFile == null ) + //@todo We have to use File.separator only because the MatchPatterns is using it internally - cannot override. + String classPattern = this.classPattern; + if ( File.separatorChar != '/' ) { - classFile = realTestClass.getName().replace( '.', '/' ) + CLASS_FILE_EXTENSION; - classConversion.put( realTestClass, classFile ); + testClassFile = testClassFile.replace( '/', File.separatorChar ); + classPattern = classPattern.replace( '/', File.separatorChar ); + } + + if ( classPattern.endsWith( WILDCARD_FILENAME_POSTFIX ) || classPattern.endsWith( CLASS_FILE_EXTENSION ) ) + { + return MatchPatterns.from( classPattern ).matches( testClassFile, true ); + } + else + { + String[] classPatterns = { classPattern + CLASS_FILE_EXTENSION, classPattern }; + return MatchPatterns.from( classPatterns ).matches( testClassFile, true ); } - return classFile; } - /** - * {@link Class#getSimpleName()} does not return this format with nested classes FirstClass$NestedTest. - */ - private static String simpleClassFileName( String classFile ) + private boolean matchClassRegexPatter( String testClassFile ) { - int indexOfSimpleName = classFile.lastIndexOf( '/' ); - return indexOfSimpleName == -1 ? classFile : classFile.substring( 1 + indexOfSimpleName ); + if ( File.separatorChar != '/' ) + { + testClassFile = testClassFile.replace( '/', File.separatorChar ); + } + return MatchPatterns.from( classPattern ).matches( testClassFile, true ); } private static String tryBlank( String s ) @@ -202,60 +279,42 @@ public final class ResolvedTest else { s = s.trim(); - return s.length() == 0 ? null : s; + return StringUtils.isEmpty( s ) ? null : s; } } - private static String reformatPattern( String s, boolean isTestClass ) + private static String reformatClassPattern( String s, boolean isRegex ) { - s = tryBlank( s ); - if ( s == null ) + if ( s != null && !isRegex ) { - return null; - } - else if ( s.startsWith( SelectorUtils.REGEX_HANDLER_PREFIX ) ) - { - if ( !s.endsWith( SelectorUtils.PATTERN_HANDLER_SUFFIX ) ) - { - throw new IllegalArgumentException( s + " enclosed regex does not finish with ']'" ); - } - } - else if ( s.startsWith( SelectorUtils.ANT_HANDLER_PREFIX ) ) - { - if ( s.endsWith( SelectorUtils.PATTERN_HANDLER_SUFFIX ) ) - { - s = SelectorUtils.REGEX_HANDLER_PREFIX + s.substring( SelectorUtils.ANT_HANDLER_PREFIX.length() ); - } - else + s = convertToPath( s ); + if ( s != null && !s.startsWith( WILDCARD_PATH_PREFIX ) ) { - throw new IllegalArgumentException( s + " enclosed regex does not finish with ']'" ); + s = WILDCARD_PATH_PREFIX + s; } } - else if ( isTestClass ) - { - s = convertToPath( s ); - } return s; } private static String convertToPath( String className ) { - if ( className == null || className.trim().length() == 0 ) + if ( StringUtils.isBlank( className ) ) { - return className; + return null; } else { if ( className.endsWith( JAVA_FILE_EXTENSION ) ) { className = className.substring( 0, className.length() - JAVA_FILE_EXTENSION.length() ); + className += CLASS_FILE_EXTENSION; } - else if ( className.endsWith( CLASS_FILE_EXTENSION ) ) - { - className = className.substring( 0, className.length() - CLASS_FILE_EXTENSION.length() ); - } - className = className.replace( '.', '/' ); - return className + CLASS_FILE_EXTENSION; + return className; } } + + static String wrapRegex( String unwrapped ) + { + return SelectorUtils.REGEX_HANDLER_PREFIX + unwrapped + SelectorUtils.PATTERN_HANDLER_SUFFIX; + } } http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/866a535b/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestFilter.java ---------------------------------------------------------------------- diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestFilter.java b/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestFilter.java new file mode 100644 index 0000000..d0155cb --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestFilter.java @@ -0,0 +1,31 @@ +package org.apache.maven.surefire.testset; + +/* + * 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. + */ + +/** + * Generic interface of test filter. + * + * @param <C> test class, or null if not mandatory + * @param <M> test method, or null if not mandatory + */ +public interface TestFilter<C, M> +{ + boolean shouldRun( C testClass, M methodName ); +}