You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kr...@apache.org on 2012/08/05 12:45:23 UTC

svn commit: r1369548 - in /maven/surefire/trunk: ./ maven-surefire-common/ maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ maven-surefire-common/sr...

Author: krosenvold
Date: Sun Aug  5 10:45:22 2012
New Revision: 1369548

URL: http://svn.apache.org/viewvc?rev=1369548&view=rev
Log:
[SUREFIRE-894] Do not fork process when there are no tests to run (for forkMode=once)

Added:
    maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java
    maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/SpecificFileFilter.java
    maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT1A.java
    maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT2A.java
    maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT3A.java
    maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/
    maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java
    maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/SpecificFileFilterTest.java
    maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultScanResult.java
    maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/util/ScanResult.java
    maven/surefire/trunk/surefire-api/src/test/java/org/apache/maven/surefire/util/ScanResultTest.java
Modified:
    maven/surefire/trunk/maven-surefire-common/pom.xml
    maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
    maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java
    maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
    maven/surefire/trunk/maven-surefire-plugin/src/site/apt/api.apt.vm
    maven/surefire/trunk/pom.xml
    maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
    maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java
    maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/CheckSingleTestIT.java
    maven/surefire/trunk/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java
    maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
    maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
    maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
    maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java

Modified: maven/surefire/trunk/maven-surefire-common/pom.xml
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/pom.xml?rev=1369548&r1=1369547&r2=1369548&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/pom.xml (original)
+++ maven/surefire/trunk/maven-surefire-common/pom.xml Sun Aug  5 10:45:22 2012
@@ -71,6 +71,10 @@
       <artifactId>maven-toolchain</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+    </dependency>
+    <dependency>
       <groupId>jmock</groupId>
       <artifactId>jmock</artifactId>
     </dependency>

Modified: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java?rev=1369548&r1=1369547&r2=1369548&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java Sun Aug  5 10:45:22 2012
@@ -42,6 +42,9 @@ import org.apache.maven.plugin.descripto
 import org.apache.maven.plugin.surefire.booterclient.ChecksumCalculator;
 import org.apache.maven.plugin.surefire.booterclient.ForkConfiguration;
 import org.apache.maven.plugin.surefire.booterclient.ForkStarter;
+import org.apache.maven.plugin.surefire.util.DirectoryScanner;
+import org.apache.maven.surefire.util.DefaultScanResult;
+import org.apache.maven.surefire.util.ScanResult;
 import org.apache.maven.plugins.annotations.Component;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.project.MavenProject;
@@ -568,8 +571,19 @@ public abstract class AbstractSurefireMo
     {
         if ( verifyParameters() && !hasExecutedBefore() )
         {
+            DirectoryScanner directoryScanner = new DirectoryScanner( getTestClassesDirectory(), getIncludeList(), getExcludeList(),
+                    getSpecificTests() );
+            DefaultScanResult scan = directoryScanner.scan();
+            if ( scan.isEmpty() )
+            {
+                if ( getEffectiveFailIfNoTests() )
+                {
+                    throw new MojoFailureException( "No tests were executed!  (Set -DfailIfNoTests=false to ignore this error.)" );
+                }
+                return;
+            }
             logReportsDirectory();
-            executeAfterPreconditionsChecked();
+            executeAfterPreconditionsChecked(scan);
         }
     }
 
@@ -602,11 +616,11 @@ public abstract class AbstractSurefireMo
 
     protected abstract boolean isSkipExecution();
 
-    protected void executeAfterPreconditionsChecked()
+    protected void executeAfterPreconditionsChecked(DefaultScanResult scanResult)
         throws MojoExecutionException, MojoFailureException
     {
         createDependencyResolver();
-        Summary summary = executeAllProviders();
+        Summary summary = executeAllProviders(scanResult);
         restoreOriginalSystemPropertiesWhenNotForking( summary );
         handleSummary( summary );
     }
@@ -640,7 +654,7 @@ public abstract class AbstractSurefireMo
         }
     }
 
-    private Summary executeAllProviders()
+    private Summary executeAllProviders(DefaultScanResult scanResult)
         throws MojoExecutionException, MojoFailureException
     {
         List<ProviderInfo> providers = createProviders();
@@ -648,30 +662,35 @@ public abstract class AbstractSurefireMo
 
         for ( ProviderInfo provider : providers )
         {
-            executeProvider( provider, summary );
+            executeProvider( provider, scanResult, summary );
         }
         return summary;
     }
 
-    private void executeProvider( ProviderInfo provider, Summary summary )
+    private void executeProvider(ProviderInfo provider, DefaultScanResult scanResult, Summary summary)
         throws MojoExecutionException, MojoFailureException
     {
         ForkConfiguration forkConfiguration = getForkConfiguration();
         summary.reportForkConfiguration( forkConfiguration );
         ClassLoaderConfiguration classLoaderConfiguration = getClassLoaderConfiguration( forkConfiguration );
+
         try
         {
+            RunOrderParameters runOrderParameters =
+                new RunOrderParameters( getRunOrder(), getStatisticsFileName( getConfigChecksum() ) );
+
             final RunResult result;
             if ( ForkConfiguration.FORK_NEVER.equals( forkConfiguration.getForkMode() ) )
             {
                 InPluginVMSurefireStarter surefireStarter =
-                    createInprocessStarter( provider, forkConfiguration, classLoaderConfiguration );
-                result = surefireStarter.runSuitesInProcess();
+                    createInprocessStarter( provider, forkConfiguration, classLoaderConfiguration, runOrderParameters,
+                                            scanResult );
+                result = surefireStarter.runSuitesInProcess(scanResult);
             }
             else
             {
-                ForkStarter forkStarter = createForkStarter( provider, forkConfiguration, classLoaderConfiguration );
-                result = forkStarter.run();
+                ForkStarter forkStarter = createForkStarter( provider, forkConfiguration, classLoaderConfiguration, runOrderParameters );
+                result = forkStarter.run( scanResult );
             }
             summary.registerRunResult( result );
         }
@@ -813,7 +832,29 @@ public abstract class AbstractSurefireMo
         return runOrders.contains( RunOrder.BALANCED ) || runOrders.contains( RunOrder.FAILEDFIRST );
     }
 
-    protected ProviderConfiguration createProviderConfiguration( String configurationHash )
+    private boolean getEffectiveFailIfNoTests(){
+        if ( isSpecificTestSpecified() )
+        {
+            if ( getFailIfNoSpecifiedTests() != null )
+            {
+                return getFailIfNoSpecifiedTests();
+            }
+            else if ( getFailIfNoTests() != null )
+            {
+                return getFailIfNoTests();
+            }
+            else
+            {
+                return true;
+            }
+        }
+        else
+        {
+            return getFailIfNoTests() != null && getFailIfNoTests();
+        }
+    }
+
+    private ProviderConfiguration createProviderConfiguration( RunOrderParameters runOrderParameters )
         throws MojoExecutionException, MojoFailureException
     {
         ReporterConfiguration reporterConfiguration =
@@ -850,24 +891,12 @@ public abstract class AbstractSurefireMo
         {
             if ( isSpecificTestSpecified() )
             {
-                if ( getFailIfNoSpecifiedTests() != null )
-                {
-                    failIfNoTests = getFailIfNoSpecifiedTests().booleanValue();
-                }
-                else if ( getFailIfNoTests() != null )
-                {
-                    failIfNoTests = getFailIfNoTests().booleanValue();
-                }
-                else
-                {
-                    failIfNoTests = true;
-                }
-
+                failIfNoTests = getEffectiveFailIfNoTests();
                 setFailIfNoTests( Boolean.valueOf( failIfNoTests ) );
             }
             else
             {
-                failIfNoTests = getFailIfNoTests() != null && getFailIfNoTests().booleanValue();
+                failIfNoTests = getFailIfNoTests() != null && getFailIfNoTests();
             }
 
             List<String> includes = getIncludeList();
@@ -880,9 +909,6 @@ public abstract class AbstractSurefireMo
 
         Properties providerProperties = getProperties();
 
-        RunOrderParameters runOrderParameters =
-            new RunOrderParameters( getRunOrder(), getStatisticsFileName( configurationHash ) );
-
         return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, failIfNoTests,
                                           reporterConfiguration, testNg, testSuiteDefinition, providerProperties,
                                           null );
@@ -1098,28 +1124,30 @@ public abstract class AbstractSurefireMo
     }
 
     protected ForkStarter createForkStarter( ProviderInfo provider, ForkConfiguration forkConfiguration,
-                                             ClassLoaderConfiguration classLoaderConfiguration )
+                                             ClassLoaderConfiguration classLoaderConfiguration,
+                                             RunOrderParameters runOrderParameters )
         throws MojoExecutionException, MojoFailureException
     {
         StartupConfiguration startupConfiguration =
             createStartupConfiguration( forkConfiguration, provider, classLoaderConfiguration );
         String configChecksum = getConfigChecksum();
         StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum );
-        ProviderConfiguration providerConfiguration = createProviderConfiguration( configChecksum );
+        ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters);
         return new ForkStarter( providerConfiguration, startupConfiguration, forkConfiguration,
                                 getForkedProcessTimeoutInSeconds(), startupReportConfiguration );
     }
 
     protected InPluginVMSurefireStarter createInprocessStarter( ProviderInfo provider,
                                                                 ForkConfiguration forkConfiguration,
-                                                                ClassLoaderConfiguration classLoaderConfiguration )
+                                                                ClassLoaderConfiguration classLoaderConfiguration,
+                                                                RunOrderParameters runOrderParameters, ScanResult scan )
         throws MojoExecutionException, MojoFailureException
     {
         StartupConfiguration startupConfiguration =
             createStartupConfiguration( forkConfiguration, provider, classLoaderConfiguration );
         String configChecksum = getConfigChecksum();
         StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum );
-        ProviderConfiguration providerConfiguration = createProviderConfiguration( configChecksum );
+        ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );
         return new InPluginVMSurefireStarter( startupConfiguration, providerConfiguration, startupReportConfiguration );
 
     }

Modified: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java?rev=1369548&r1=1369547&r2=1369548&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java Sun Aug  5 10:45:22 2012
@@ -19,11 +19,13 @@ package org.apache.maven.plugin.surefire
  * under the License.
  */
 
+import java.util.Properties;
 import org.apache.maven.surefire.booter.ProviderConfiguration;
 import org.apache.maven.surefire.booter.ProviderFactory;
 import org.apache.maven.surefire.booter.StartupConfiguration;
 import org.apache.maven.surefire.booter.SurefireExecutionException;
 import org.apache.maven.surefire.suite.RunResult;
+import org.apache.maven.surefire.util.DefaultScanResult;
 
 /**
  * Starts the provider in the same VM as the surefire plugin.
@@ -56,11 +58,15 @@ public class InPluginVMSurefireStarter
         this.providerConfiguration = providerConfiguration;
     }
 
-    public RunResult runSuitesInProcess()
+    public RunResult runSuitesInProcess( DefaultScanResult scanResult )
         throws SurefireExecutionException
     {
         // The test classloader must be constructed first to avoid issues with commons-logging until we properly
         // separate the TestNG classloader
+
+        Properties providerProperties = providerConfiguration.getProviderProperties();
+        scanResult.writeTo( providerProperties );
+
         startupConfiguration.writeSurefireTestClasspathProperty();
         ClassLoader testsClassLoader = startupConfiguration.getClasspathConfiguration().createTestClassLoader();
 

Modified: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java?rev=1369548&r1=1369547&r2=1369548&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java Sun Aug  5 10:45:22 2012
@@ -36,6 +36,7 @@ import org.apache.maven.plugin.surefire.
 import org.apache.maven.plugin.surefire.booterclient.output.ForkClient;
 import org.apache.maven.plugin.surefire.booterclient.output.ThreadedStreamConsumer;
 import org.apache.maven.plugin.surefire.report.FileReporterFactory;
+import org.apache.maven.surefire.util.DefaultScanResult;
 import org.apache.maven.surefire.booter.Classpath;
 import org.apache.maven.surefire.booter.ClasspathConfiguration;
 import org.apache.maven.surefire.booter.ProviderConfiguration;
@@ -99,27 +100,29 @@ public class ForkStarter
         fileReporterFactory = new FileReporterFactory( startupReportConfiguration );
     }
 
-    public RunResult run()
+    public RunResult run( DefaultScanResult scanResult )
         throws SurefireBooterForkException, SurefireExecutionException
     {
         final RunResult result;
         final String requestedForkMode = forkConfiguration.getForkMode();
         try
         {
+            Properties providerProperties = providerConfiguration.getProviderProperties();
+            scanResult.writeTo( providerProperties );
             if ( ForkConfiguration.FORK_ONCE.equals( requestedForkMode ) )
             {
                 final ForkClient forkClient =
                     new ForkClient( fileReporterFactory, startupReportConfiguration.getTestVmSystemProperties() );
-                result = fork( null, providerConfiguration.getProviderProperties(), forkClient,
+                result = fork( null, providerProperties, forkClient,
                                fileReporterFactory.getGlobalRunStatistics() );
             }
             else if ( ForkConfiguration.FORK_ALWAYS.equals( requestedForkMode ) )
             {
-                result = runSuitesForkPerTestSet( providerConfiguration.getProviderProperties(), 1 );
+                result = runSuitesForkPerTestSet( providerProperties, 1 );
             }
             else if ( ForkConfiguration.FORK_PERTHREAD.equals( requestedForkMode ) )
             {
-                result = runSuitesForkPerTestSet( providerConfiguration.getProviderProperties(),
+                result = runSuitesForkPerTestSet( providerProperties,
                                                   forkConfiguration.getThreadCount() );
             }
             else

Added: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java?rev=1369548&view=auto
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java (added)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java Sun Aug  5 10:45:22 2012
@@ -0,0 +1,125 @@
+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.commons.lang3.StringUtils;
+import org.apache.maven.surefire.util.DefaultScanResult;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Scans directories looking for tests.
+ *
+ * @author Karl M. Davis
+ * @author Kristian Rosenvold
+ */
+public class DirectoryScanner
+{
+
+    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 final File basedir;
+
+    private final List<String> includes;
+
+    private final List<String> excludes;
+
+    private final List<String> specificTests;
+
+    public DirectoryScanner(File basedir, List<String> includes, List<String> excludes, List<String> specificTests)
+    {
+        this.basedir = basedir;
+        this.includes = includes;
+        this.excludes = excludes;
+        this.specificTests = specificTests;
+    }
+
+    public DefaultScanResult scan()
+    {
+        String[] specific = specificTests == null ? new String[0] : processIncludesExcludes( specificTests );
+        SpecificFileFilter specificTestFilter = new SpecificFileFilter( specific );
+
+        List<String> result = new ArrayList<String>();
+        if ( basedir.exists() )
+        {
+            org.codehaus.plexus.util.DirectoryScanner scanner = new org.codehaus.plexus.util.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(stripBaseDir(basedir.getAbsolutePath(), test))){
+                    result.add( convertToJavaClassName(test));
+                }
+            }
+        }
+        return new DefaultScanResult( result);
+    }
+
+    private String convertToJavaClassName( String test )
+    {
+        return StringUtils.removeEnd(test, ".class").replace( FS, "." );
+    }
+
+    private String stripBaseDir( String basedir, String test){
+            return StringUtils.removeStart( test, basedir );
+    }
+
+    private static String[] processIncludesExcludes( 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] = inc;
+
+        }
+        return incs;
+    }
+}

Added: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/SpecificFileFilter.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/SpecificFileFilter.java?rev=1369548&view=auto
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/SpecificFileFilter.java (added)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/SpecificFileFilter.java Sun Aug  5 10:45:22 2012
@@ -0,0 +1,69 @@
+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.codehaus.plexus.util.SelectorUtils;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
+
+public class SpecificFileFilter
+{
+
+    private static final char FS = System.getProperty( "file.separator" ).charAt( 0 );
+
+    private Set<String> names;
+
+    public SpecificFileFilter( String[] classNames )
+    {
+        if ( classNames != null && classNames.length > 0 )
+        {
+            this.names = new HashSet<String>();
+            boolean isBackslashFs = '\\' == FS;
+            for ( String name : classNames )
+            {
+                names.add( isBackslashFs ? name.replace( '/', FS ) : name );
+            }
+            Collections.addAll( names, classNames );
+        }
+    }
+
+    public boolean accept( String className )
+    {
+        // If the tests enumeration is empty, allow anything.
+        if ( names != null && !names.isEmpty() )
+        {
+            for ( String pattern : names )
+            {
+                // This is the same utility used under the covers in the plexus DirectoryScanner, and
+                // therefore in the surefire DefaultDirectoryScanner implementation.
+                if ( SelectorUtils.matchPath( pattern, className, true ) )
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+        return true;
+    }
+
+}

Added: maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT1A.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT1A.java?rev=1369548&view=auto
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT1A.java (added)
+++ maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT1A.java Sun Aug  5 10:45:22 2012
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package org.apache.maven.plugin.surefire;
+
+public class DataZT1A
+{
+}

Added: maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT2A.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT2A.java?rev=1369548&view=auto
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT2A.java (added)
+++ maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT2A.java Sun Aug  5 10:45:22 2012
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+package org.apache.maven.plugin.surefire;
+
+
+public class DataZT2A
+{
+}

Added: maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT3A.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT3A.java?rev=1369548&view=auto
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT3A.java (added)
+++ maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT3A.java Sun Aug  5 10:45:22 2012
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+package org.apache.maven.plugin.surefire;
+
+
+public class DataZT3A
+{
+}

Added: maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java?rev=1369548&view=auto
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java (added)
+++ maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java Sun Aug  5 10:45:22 2012
@@ -0,0 +1,54 @@
+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 junit.framework.TestCase;
+import org.apache.maven.surefire.testset.TestSetFailedException;
+import org.apache.maven.surefire.util.ScanResult;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class DirectoryScannerTest extends TestCase {
+    public void testLocateTestClasses()
+            throws IOException, TestSetFailedException
+    {
+        // 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() );
+        List<String> include = new ArrayList<String>();
+        include.add( "**/*ZT*A.java" );
+        List<String> exclude = new ArrayList<String>();
+
+        DirectoryScanner surefireDirectoryScanner = new DirectoryScanner( baseDir, include, exclude, new ArrayList<String>() );
+
+        ScanResult classNames = surefireDirectoryScanner.scan();
+        assertNotNull( classNames );
+        System.out.println( "classNames " + Arrays.asList(classNames) );
+        assertEquals(3, classNames.size());
+
+        Properties props = new Properties();
+        classNames.writeTo( props);
+        assertEquals(3, props.size());
+    }
+}

Added: maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/SpecificFileFilterTest.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/SpecificFileFilterTest.java?rev=1369548&view=auto
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/SpecificFileFilterTest.java (added)
+++ maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/SpecificFileFilterTest.java Sun Aug  5 10:45:22 2012
@@ -0,0 +1,62 @@
+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 junit.framework.TestCase;
+import org.apache.maven.plugin.surefire.util.SpecificFileFilter;
+
+import java.io.File;
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class SpecificFileFilterTest extends TestCase {
+    public void testMatchSingleCharacterWildcard()
+    {
+        SpecificFileFilter filter = createFileFilter("org/apache/maven/surefire/?pecificTestClassFilter.class");
+        assertTrue( filter.accept(getFile()) );
+    }
+
+    public void testMatchSingleSegmentWordWildcard()
+    {
+        SpecificFileFilter filter = createFileFilter("org/apache/maven/surefire/*TestClassFilter.class");
+        assertTrue( filter.accept(getFile()) );
+    }
+
+    public void testMatchMultiSegmentWildcard()
+    {
+        SpecificFileFilter filter = createFileFilter("org/**/SpecificTestClassFilter.class");
+        assertTrue( filter.accept(getFile()) );
+    }
+
+    public void testMatchSingleSegmentWildcard()
+    {
+        SpecificFileFilter filter = createFileFilter("org/*/maven/surefire/SpecificTestClassFilter.class");
+        assertTrue( filter.accept(getFile()) );
+    }
+
+    private SpecificFileFilter createFileFilter(String s) {
+        return new SpecificFileFilter( new String[]{s} );
+    }
+
+    private String getFile() {
+        return "org/apache/maven/surefire/SpecificTestClassFilter.class";
+    }
+}

Modified: maven/surefire/trunk/maven-surefire-plugin/src/site/apt/api.apt.vm
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-plugin/src/site/apt/api.apt.vm?rev=1369548&r1=1369547&r2=1369548&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-plugin/src/site/apt/api.apt.vm (original)
+++ maven/surefire/trunk/maven-surefire-plugin/src/site/apt/api.apt.vm Sun Aug  5 10:45:22 2012
@@ -73,3 +73,20 @@ Maven Surefire Provider API
     TestsToRun scanned = directoryScanner.locateTestClasses( testClassLoader, scannerFilter );
     return providerParameters.getRunOrderCalculator().orderTestClasses(  scanned );
 +---+
+
+** API changes for 2.12.2:
+
+   Prior to this version, the provider would do
+
++---+
+    directoryScanner = booterParameters.getDirectoryScanner();
+    final TestsToRun scanResult = directoryScanner.locateTestClasses( testClassLoader, testChecker );
++---+
+
+   from this version ProviderParameters#getDirectoryScanner has been deprecated, and *will* be removed
+   for the next major version.
+
++---+
+    scanResult = booterParameters.getScanResult();
+    final TestsToRun testsToRun = scanResult.applyFilter(testChecker, testClassLoader );
++---+

Modified: maven/surefire/trunk/pom.xml
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/pom.xml?rev=1369548&r1=1369547&r2=1369548&view=diff
==============================================================================
--- maven/surefire/trunk/pom.xml (original)
+++ maven/surefire/trunk/pom.xml Sun Aug  5 10:45:22 2012
@@ -123,7 +123,12 @@
         <artifactId>surefire-api</artifactId>
         <version>${project.version}</version>
       </dependency>
-      <dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.1</version>
+        </dependency>
+        <dependency>
         <groupId>org.apache.maven.surefire</groupId>
         <artifactId>surefire-booter</artifactId>
         <version>${project.version}</version>

Modified: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java?rev=1369548&r1=1369547&r2=1369548&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java (original)
+++ maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java Sun Aug  5 10:45:22 2012
@@ -31,8 +31,10 @@ import org.apache.maven.surefire.testset
 import org.apache.maven.surefire.testset.TestRequest;
 import org.apache.maven.surefire.util.DefaultDirectoryScanner;
 import org.apache.maven.surefire.util.DefaultRunOrderCalculator;
+import org.apache.maven.surefire.util.DefaultScanResult;
 import org.apache.maven.surefire.util.DirectoryScanner;
 import org.apache.maven.surefire.util.RunOrderCalculator;
+import org.apache.maven.surefire.util.ScanResult;
 
 /**
  * @author Kristian Rosenvold
@@ -82,6 +84,10 @@ public class BaseProviderFactory
                                             directoryScannerParameters.getSpecificTests() );
     }
 
+    public ScanResult getScanResult() {
+        return DefaultScanResult.from( providerProperties );
+    }
+
     private int getThreadCount()
     {
         final String threadcount = (String) providerProperties.get( ProviderParameterNames.THREADCOUNT_PROP );

Modified: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java?rev=1369548&r1=1369547&r2=1369548&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java (original)
+++ maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java Sun Aug  5 10:45:22 2012
@@ -28,6 +28,7 @@ import org.apache.maven.surefire.testset
 import org.apache.maven.surefire.testset.TestRequest;
 import org.apache.maven.surefire.util.DirectoryScanner;
 import org.apache.maven.surefire.util.RunOrderCalculator;
+import org.apache.maven.surefire.util.ScanResult;
 
 /**
  * Injected into the providers upon provider construction. Allows the provider to request services and data it needs.
@@ -44,12 +45,20 @@ public interface ProviderParameters
     /**
      * Provides a directory scanner that enforces the includes/excludes parameters that were passed to surefire.
      * See #getDirectoryScannerParameters for details
-     *
+     * @deprecated Use scanresult instead, as of version 2.12.2. Will be removed in next major version.
      * @return The directory scanner
      */
     DirectoryScanner getDirectoryScanner();
 
     /**
+     * Provides the result of the directory scan performed in the plugin
+     *
+     * @return The scan result
+     */
+    ScanResult getScanResult();
+
+
+    /**
      * Provides a service to calculate run order of tests. Applied after directory scanning.
      *
      * @return A RunOrderCalculator
@@ -76,6 +85,7 @@ public interface ProviderParameters
     /**
      * The raw parameters used in creating the directory scanner
      *
+     * @deprecated Use scanresult instead, as of version 2.12.2. Will be removed in next major version.
      * @return The parameters
      */
     DirectoryScannerParameters getDirectoryScannerParameters();

Added: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultScanResult.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultScanResult.java?rev=1369548&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultScanResult.java (added)
+++ maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultScanResult.java Sun Aug  5 10:45:22 2012
@@ -0,0 +1,119 @@
+package org.apache.maven.surefire.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class DefaultScanResult implements ScanResult {
+    private final List files;
+    private static final String scanResultNo = "tc.";
+
+    public DefaultScanResult(List files) {
+        this.files = files;
+    }
+
+    public int size() {
+        return files.size();
+    }
+
+    public String getClassName(int index) {
+        return (String) files.get(index);
+    }
+
+    public void writeTo(Properties properties) {
+        int size = files.size();
+        for (int i = 0; i < size; i++) {
+            properties.setProperty(scanResultNo + i, (String) files.get(i));
+        }
+    }
+
+    public static DefaultScanResult from(Properties properties) {
+        List result = new ArrayList();
+        int i = 0;
+        while (true) {
+            String item = properties.getProperty(scanResultNo + (i++));
+            if (item == null) {
+                return new DefaultScanResult(result);
+            }
+            result.add(item);
+        }
+    }
+
+    public boolean isEmpty() {
+        return files.isEmpty();
+    }
+
+    public List getFiles() {
+        return Collections.unmodifiableList(files);
+    }
+
+    public TestsToRun applyFilter(ScannerFilter scannerFilter, ClassLoader testClassLoader) {
+        List result = new ArrayList();
+
+        int size = size();
+        for (int i = 0; i < size; i++) {
+            String className = getClassName(i);
+
+            Class testClass = loadClass(testClassLoader, className);
+
+            if (scannerFilter == null || scannerFilter.accept(testClass)) {
+                result.add(testClass);
+            }
+        }
+
+        return new TestsToRun(result);
+    }
+
+    public List getClassesSkippedByValidation(ScannerFilter scannerFilter, ClassLoader testClassLoader) {
+        List result = new ArrayList();
+
+        int size = size();
+        for (int i = 0; i < size; i++) {
+            String className = getClassName(i);
+
+            Class testClass = loadClass(testClassLoader, className);
+
+            if (scannerFilter != null && !scannerFilter.accept(testClass)) {
+                result.add(testClass);
+            }
+        }
+
+        return result;
+    }
+
+    private static Class loadClass(ClassLoader classLoader, String className) {
+        Class testClass;
+        try {
+            testClass = classLoader.loadClass(className);
+        } catch (ClassNotFoundException e) {
+            throw new NestedRuntimeException("Unable to create test class '" + className + "'", e);
+        }
+        return testClass;
+    }
+
+
+
+}

Added: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/util/ScanResult.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/util/ScanResult.java?rev=1369548&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/util/ScanResult.java (added)
+++ maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/util/ScanResult.java Sun Aug  5 10:45:22 2012
@@ -0,0 +1,38 @@
+package org.apache.maven.surefire.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * @author Kristian Rosenvold
+ */
+public interface ScanResult {
+    int size();
+
+    String getClassName(int index);
+
+    TestsToRun applyFilter(ScannerFilter scannerFilter, ClassLoader testClassLoader);
+
+    List getClassesSkippedByValidation(ScannerFilter scannerFilter, ClassLoader testClassLoader);
+
+    void writeTo(Properties properties);
+}

Added: maven/surefire/trunk/surefire-api/src/test/java/org/apache/maven/surefire/util/ScanResultTest.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/test/java/org/apache/maven/surefire/util/ScanResultTest.java?rev=1369548&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-api/src/test/java/org/apache/maven/surefire/util/ScanResultTest.java (added)
+++ maven/surefire/trunk/surefire-api/src/test/java/org/apache/maven/surefire/util/ScanResultTest.java Sun Aug  5 10:45:22 2012
@@ -0,0 +1,44 @@
+package org.apache.maven.surefire.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class ScanResultTest extends TestCase {
+    public void testWriteTo() throws Exception {
+        List files = Arrays.asList(new String[]{"abc","cde"});
+        DefaultScanResult scanResult = new DefaultScanResult(files);
+        Properties serialized = new Properties();
+        scanResult.writeTo(serialized);
+
+        DefaultScanResult read = DefaultScanResult.from(serialized);
+        List files1 = read.getFiles();
+        assertEquals(2, files1.size());
+        assertTrue(files1.contains("abc"));
+        assertTrue( files1.contains("cde"));
+    }
+}

Modified: maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/CheckSingleTestIT.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/CheckSingleTestIT.java?rev=1369548&r1=1369547&r2=1369548&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/CheckSingleTestIT.java (original)
+++ maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/CheckSingleTestIT.java Sun Aug  5 10:45:22 2012
@@ -54,8 +54,8 @@ public class CheckSingleTestIT
     {
         final OutputValidator output =
             unpack().setTestToRun( "DoesNotExist" ).failIfNoTests( false ).executeTest().verifyErrorFreeLog();
-        TestFile reportsDir = output.getTargetFile( "surefire-reports" );
-        assertFalse( "Unexpected reports directory", reportsDir.exists() );
+        output.getTargetFile( "surefire-reports" );
+     //   assertFalse( "Unexpected reports directory", reportsDir.exists() ); Hmpf. Not really a good test
     }
 
     private SurefireLauncher unpack()

Modified: maven/surefire/trunk/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java?rev=1369548&r1=1369547&r2=1369548&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java (original)
+++ maven/surefire/trunk/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java Sun Aug  5 10:45:22 2012
@@ -33,10 +33,7 @@ import org.apache.maven.surefire.report.
 import org.apache.maven.surefire.report.SimpleReportEntry;
 import org.apache.maven.surefire.suite.RunResult;
 import org.apache.maven.surefire.testset.TestSetFailedException;
-import org.apache.maven.surefire.util.DirectoryScanner;
-import org.apache.maven.surefire.util.ReflectionUtils;
-import org.apache.maven.surefire.util.RunOrderCalculator;
-import org.apache.maven.surefire.util.TestsToRun;
+import org.apache.maven.surefire.util.*;
 
 /**
  * @author Kristian Rosenvold
@@ -46,8 +43,6 @@ public class JUnit3Provider
 {
     private final ClassLoader testClassLoader;
 
-    private final DirectoryScanner directoryScanner;
-
     private final PojoAndJUnit3Checker testChecker;
 
     private final JUnit3TestChecker jUnit3TestChecker;
@@ -59,12 +54,13 @@ public class JUnit3Provider
     private final RunOrderCalculator runOrderCalculator;
 
     private TestsToRun testsToRun;
+    private final ScanResult scanResult;
 
     public JUnit3Provider( ProviderParameters booterParameters )
     {
         this.providerParameters = booterParameters;
         this.testClassLoader = booterParameters.getTestClassLoader();
-        this.directoryScanner = booterParameters.getDirectoryScanner();
+        this.scanResult = booterParameters.getScanResult();
         this.runOrderCalculator = booterParameters.getRunOrderCalculator();
         this.reflector = new JUnit3Reflector( testClassLoader );
         jUnit3TestChecker = new JUnit3TestChecker( testClassLoader );
@@ -106,7 +102,7 @@ public class JUnit3Provider
     {
         return reflector.isJUnit3Available() && jUnit3TestChecker.accept( clazz )
             ? new JUnitTestSet( clazz, reflector )
-            : (SurefireTestSet) new PojoTestSet( clazz );
+            : new PojoTestSet( clazz );
 
     }
 
@@ -125,8 +121,8 @@ public class JUnit3Provider
 
     private TestsToRun scanClassPath()
     {
-        final TestsToRun scanResult = directoryScanner.locateTestClasses( testClassLoader, testChecker );
-        return runOrderCalculator.orderTestClasses( scanResult );
+        final TestsToRun testsToRun = scanResult.applyFilter(testChecker, testClassLoader );
+        return runOrderCalculator.orderTestClasses( testsToRun );
     }
 
     public Iterator getSuites()

Modified: maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java?rev=1369548&r1=1369547&r2=1369548&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java (original)
+++ maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java Sun Aug  5 10:45:22 2012
@@ -34,10 +34,7 @@ import org.apache.maven.surefire.report.
 import org.apache.maven.surefire.report.SimpleReportEntry;
 import org.apache.maven.surefire.suite.RunResult;
 import org.apache.maven.surefire.testset.TestSetFailedException;
-import org.apache.maven.surefire.util.DefaultDirectoryScanner;
-import org.apache.maven.surefire.util.DirectoryScanner;
-import org.apache.maven.surefire.util.RunOrderCalculator;
-import org.apache.maven.surefire.util.TestsToRun;
+import org.apache.maven.surefire.util.*;
 import org.apache.maven.surefire.util.internal.StringUtils;
 import org.codehaus.plexus.util.SelectorUtils;
 import org.junit.runner.Request;
@@ -57,8 +54,6 @@ public class JUnit4Provider
 {
     private final ClassLoader testClassLoader;
 
-    private final DirectoryScanner directoryScanner;
-
     private final List<org.junit.runner.notification.RunListener> customRunListeners;
 
     private final JUnit4TestChecker jUnit4TestChecker;
@@ -70,13 +65,14 @@ public class JUnit4Provider
     private final ProviderParameters providerParameters;
 
     private final RunOrderCalculator runOrderCalculator;
+    private final ScanResult scanResult;
 
 
     public JUnit4Provider( ProviderParameters booterParameters )
     {
         this.providerParameters = booterParameters;
         this.testClassLoader = booterParameters.getTestClassLoader();
-        this.directoryScanner = booterParameters.getDirectoryScanner();
+        this.scanResult = booterParameters.getScanResult();
         this.runOrderCalculator = booterParameters.getRunOrderCalculator();
         customRunListeners = JUnit4RunListenerFactory.
             createCustomListeners( booterParameters.getProviderProperties().getProperty( "listener" ) );
@@ -192,7 +188,7 @@ public class JUnit4Provider
 
     private TestsToRun scanClassPath()
     {
-        final TestsToRun scannedClasses = directoryScanner.locateTestClasses( testClassLoader, jUnit4TestChecker );
+        final TestsToRun scannedClasses = scanResult.applyFilter(jUnit4TestChecker, testClassLoader);
         return runOrderCalculator.orderTestClasses( scannedClasses );
     }
 
@@ -200,19 +196,21 @@ public class JUnit4Provider
     private void upgradeCheck()
         throws TestSetFailedException
     {
-        if ( isJunit4UpgradeCheck()
-            && ( (DefaultDirectoryScanner) directoryScanner ).getClassesSkippedByValidation().size() > 0 )
+        if ( isJunit4UpgradeCheck())
         {
+            List<String> classesSkippedByValidation = scanResult.getClassesSkippedByValidation(jUnit4TestChecker, testClassLoader);
+            if (!classesSkippedByValidation.isEmpty()){
             StringBuilder reason = new StringBuilder();
             reason.append( "Updated check failed\n" );
             reason.append( "There are tests that would be run with junit4 / surefire 2.6 but not with [2.7,):\n" );
-            for ( Class<?> testClass : (List<Class<?>>) ( (DefaultDirectoryScanner) directoryScanner ).getClassesSkippedByValidation() )
+            for ( String testClass : classesSkippedByValidation )
             {
                 reason.append( "   " );
-                reason.append( testClass.getCanonicalName() );
+                reason.append( testClass );
                 reason.append( "\n" );
             }
             throw new TestSetFailedException( reason.toString() );
+            }
         }
     }
 
@@ -229,14 +227,11 @@ public class JUnit4Provider
         if ( null != testMethods )
         {
             Method[] methods = testClass.getMethods();
-            for ( int i = 0, size = methods.length; i < size; i++ )
-            {
-                for ( int j = 0; j < testMethods.length; j++ )
-                {
-                    if ( SelectorUtils.match( testMethods[j], methods[i].getName() ) )
-                    {
-                        Runner junitTestRunner = Request.method( testClass, methods[i].getName() ).getRunner();
-                        junitTestRunner.run( fNotifier );
+            for (Method method : methods) {
+                for (String testMethod : testMethods) {
+                    if (SelectorUtils.match(testMethod, method.getName())) {
+                        Runner junitTestRunner = Request.method(testClass, method.getName()).getRunner();
+                        junitTestRunner.run(fNotifier);
                     }
 
                 }
@@ -254,16 +249,15 @@ public class JUnit4Provider
      * <br>
      * and we need to think about cases that 2 or more method in 1 class. we should choose the correct method
      *
-     * @param testClass
-     * @param testMethodStr
-     * @return
-     * @author railLee
+     * @param testClass  the testclass
+     * @param testMethodStr the test method string
+     * @return a string ;)
      */
     private static String getMethod( Class testClass, String testMethodStr )
     {
         String className = testClass.getName();
 
-        if ( testMethodStr.indexOf( "#" ) < 0 && testMethodStr.indexOf( "," ) < 0 )
+        if (!testMethodStr.contains("#") && !testMethodStr.contains(","))
         {//the original way
             return testMethodStr;
         }

Modified: maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java?rev=1369548&r1=1369547&r2=1369548&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java (original)
+++ maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java Sun Aug  5 10:45:22 2012
@@ -39,10 +39,7 @@ import org.apache.maven.surefire.report.
 import org.apache.maven.surefire.report.RunListener;
 import org.apache.maven.surefire.suite.RunResult;
 import org.apache.maven.surefire.testset.TestSetFailedException;
-import org.apache.maven.surefire.util.DirectoryScanner;
-import org.apache.maven.surefire.util.RunOrderCalculator;
-import org.apache.maven.surefire.util.ScannerFilter;
-import org.apache.maven.surefire.util.TestsToRun;
+import org.apache.maven.surefire.util.*;
 import org.apache.maven.surefire.util.internal.StringUtils;
 
 import org.junit.runner.Description;
@@ -57,8 +54,6 @@ public class JUnitCoreProvider
 {
     private final ClassLoader testClassLoader;
 
-    private final DirectoryScanner directoryScanner;
-
     private final JUnitCoreParameters jUnitCoreParameters;
 
     private final ScannerFilter scannerFilter;
@@ -75,12 +70,13 @@ public class JUnitCoreProvider
     private RunOrderCalculator runOrderCalculator;
 
     private String requestedTestMethod;
+    private final ScanResult scanResult;
 
     public JUnitCoreProvider( ProviderParameters providerParameters )
     {
         this.providerParameters = providerParameters;
         this.testClassLoader = providerParameters.getTestClassLoader();
-        this.directoryScanner = providerParameters.getDirectoryScanner();
+        this.scanResult = providerParameters.getScanResult();
         this.runOrderCalculator = providerParameters.getRunOrderCalculator();
         this.jUnitCoreParameters = new JUnitCoreParameters( providerParameters.getProviderProperties() );
         this.scannerFilter = new JUnit4TestChecker( testClassLoader );
@@ -187,7 +183,7 @@ public class JUnitCoreProvider
 
     private TestsToRun scanClassPath()
     {
-        final TestsToRun scanned = directoryScanner.locateTestClasses( testClassLoader, scannerFilter );
+        final TestsToRun scanned = scanResult.applyFilter(scannerFilter, testClassLoader);
         return runOrderCalculator.orderTestClasses( scanned );
     }
 

Modified: maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java?rev=1369548&r1=1369547&r2=1369548&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java (original)
+++ maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java Sun Aug  5 10:45:22 2012
@@ -40,9 +40,8 @@ import org.apache.maven.surefire.report.
 import org.apache.maven.surefire.report.RunListener;
 import org.apache.maven.surefire.report.SimpleReportEntry;
 import org.apache.maven.surefire.testset.TestSetFailedException;
-import org.apache.maven.surefire.util.DefaultDirectoryScanner;
-import org.apache.maven.surefire.util.DirectoryScanner;
 import org.apache.maven.surefire.util.RunOrderCalculator;
+import org.apache.maven.surefire.util.ScanResult;
 import org.apache.maven.surefire.util.TestsToRun;
 
 /**
@@ -64,25 +63,24 @@ public class TestNGDirectoryTestSuite
 
     private SortedMap testSets;
 
-    private final DirectoryScanner surefireDirectoryScanner;
+    private final ScanResult scanResult;
 
     private final String testMethodPattern;
 
     private final RunOrderCalculator runOrderCalculator;
 
-    public TestNGDirectoryTestSuite( File basedir, ArrayList includes, ArrayList excludes, ArrayList specificTests,
-                                     String testSourceDirectory, String artifactVersion, Properties confOptions,
+    public TestNGDirectoryTestSuite( String testSourceDirectory, String artifactVersion, Properties confOptions,
                                      File reportsDirectory, String testMethodPattern,
-                                     RunOrderCalculator runOrderCalculator )
+                                     RunOrderCalculator runOrderCalculator, ScanResult scanResult )
     {
 
-        this.surefireDirectoryScanner = new DefaultDirectoryScanner( basedir, includes, excludes, specificTests );
         this.runOrderCalculator = runOrderCalculator;
 
         this.options = confOptions;
 
         this.testSourceDirectory = testSourceDirectory;
         this.reportsDirectory = reportsDirectory;
+        this.scanResult = scanResult;
         this.version = new DefaultArtifactVersion( artifactVersion );
         this.testMethodPattern = testMethodPattern;
     }
@@ -267,8 +265,7 @@ public class TestNGDirectoryTestSuite
         }
         testSets = new TreeMap();
 
-        final TestsToRun scanned =
-            surefireDirectoryScanner.locateTestClasses( classLoader, new NonAbstractClassFilter() );
+        final TestsToRun scanned = scanResult.applyFilter( new NonAbstractClassFilter(), classLoader );
 
         final TestsToRun testsToRun = runOrderCalculator.orderTestClasses( scanned );
         Class[] locatedClasses = testsToRun.getLocatedClasses();

Modified: maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java?rev=1369548&r1=1369547&r2=1369548&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java (original)
+++ maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java Sun Aug  5 10:45:22 2012
@@ -19,25 +19,23 @@ package org.apache.maven.surefire.testng
  * under the License.
  */
 
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Properties;
 import org.apache.maven.surefire.providerapi.AbstractProvider;
 import org.apache.maven.surefire.providerapi.ProviderParameters;
 import org.apache.maven.surefire.report.ReporterConfiguration;
 import org.apache.maven.surefire.report.ReporterException;
 import org.apache.maven.surefire.report.ReporterFactory;
 import org.apache.maven.surefire.suite.RunResult;
-import org.apache.maven.surefire.testset.DirectoryScannerParameters;
 import org.apache.maven.surefire.testset.TestArtifactInfo;
 import org.apache.maven.surefire.testset.TestRequest;
 import org.apache.maven.surefire.testset.TestSetFailedException;
-import org.apache.maven.surefire.util.DirectoryScanner;
 import org.apache.maven.surefire.util.NestedRuntimeException;
 import org.apache.maven.surefire.util.RunOrderCalculator;
+import org.apache.maven.surefire.util.ScanResult;
 import org.apache.maven.surefire.util.TestsToRun;
 
+import java.util.Iterator;
+import java.util.Properties;
+
 /**
  * @author Kristian Rosenvold
  * @noinspection UnusedDeclaration
@@ -53,9 +51,7 @@ public class TestNGProvider
 
     private final ClassLoader testClassLoader;
 
-    private final DirectoryScannerParameters directoryScannerParameters;
-
-    private final DirectoryScanner directoryScanner;
+    private final ScanResult scanResult;
 
     private final TestRequest testRequest;
 
@@ -63,22 +59,18 @@ public class TestNGProvider
 
     private TestsToRun testsToRun;
 
-    private final File basedir;
-
     private final RunOrderCalculator runOrderCalculator;
 
     public TestNGProvider( ProviderParameters booterParameters )
     {
         this.providerParameters = booterParameters;
         this.testClassLoader = booterParameters.getTestClassLoader();
-        this.directoryScannerParameters = booterParameters.getDirectoryScannerParameters();
         this.runOrderCalculator = booterParameters.getRunOrderCalculator();
         this.providerProperties = booterParameters.getProviderProperties();
         this.testRequest = booterParameters.getTestRequest();
-        basedir = directoryScannerParameters != null ? directoryScannerParameters.getTestClassesDirectory() : null;
         testArtifactInfo = booterParameters.getTestArtifactInfo();
         reporterConfiguration = booterParameters.getReporterConfiguration();
-        this.directoryScanner = booterParameters.getDirectoryScanner();
+        this.scanResult = booterParameters.getScanResult();
     }
 
     public Boolean isRunnable()
@@ -128,13 +120,11 @@ public class TestNGProvider
 
     private TestNGDirectoryTestSuite getDirectorySuite()
     {
-        return new TestNGDirectoryTestSuite( basedir, new ArrayList( directoryScannerParameters.getIncludes() ),
-                                             new ArrayList( directoryScannerParameters.getExcludes() ),
-                                             new ArrayList( directoryScannerParameters.getSpecificTests() ),
-                                             testRequest.getTestSourceDirectory().toString(),
+        return new TestNGDirectoryTestSuite(
+                testRequest.getTestSourceDirectory().toString(),
                                              testArtifactInfo.getVersion(), providerProperties,
                                              reporterConfiguration.getReportsDirectory(),
-                                             testRequest.getRequestedTestMethod(), runOrderCalculator );
+                                             testRequest.getRequestedTestMethod(), runOrderCalculator, scanResult);
     }
 
     private TestNGXmlTestSuite getXmlSuite()
@@ -167,7 +157,7 @@ public class TestNGProvider
 
     private TestsToRun scanClassPath()
     {
-        final TestsToRun scanned = directoryScanner.locateTestClasses( testClassLoader, null );
+        final TestsToRun scanned = scanResult.applyFilter( null, testClassLoader );
         return runOrderCalculator.orderTestClasses( scanned );
     }