maven-surefire-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jvan...@apache.org
Subject svn commit: r352042 - in /maven/surefire/trunk/surefire-booter: ./ src/main/java/org/codehaus/surefire/
Date Sat, 03 Dec 2005 22:50:09 GMT
Author: jvanzyl
Date: Sat Dec  3 14:50:06 2005
New Revision: 352042

URL: http://svn.apache.org/viewcvs?rev=352042&view=rev
Log:
o adding support for forking

Added:
    maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/ForkedSurefireRunner.java
  (with props)
    maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/SurefireBooterForkException.java
  (with props)
Modified:
    maven/surefire/trunk/surefire-booter/pom.xml
    maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/SurefireBooter.java

Modified: maven/surefire/trunk/surefire-booter/pom.xml
URL: http://svn.apache.org/viewcvs/maven/surefire/trunk/surefire-booter/pom.xml?rev=352042&r1=352041&r2=352042&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-booter/pom.xml (original)
+++ maven/surefire/trunk/surefire-booter/pom.xml Sat Dec  3 14:50:06 2005
@@ -14,5 +14,23 @@
       <artifactId>surefire</artifactId>
       <version>1.5-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact</artifactId>
+      <version>2.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact-manager</artifactId>
+      <version>2.0</version>
+      <scope>test</scope>
+    </dependency>        
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>compile</scope>
+    </dependency>
   </dependencies>
-</project>
\ No newline at end of file
+</project>

Added: maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/ForkedSurefireRunner.java
URL: http://svn.apache.org/viewcvs/maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/ForkedSurefireRunner.java?rev=352042&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/ForkedSurefireRunner.java
(added)
+++ maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/ForkedSurefireRunner.java
Sat Dec  3 14:50:06 2005
@@ -0,0 +1,177 @@
+package org.codehaus.surefire;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class is executed when SurefireBooter forks surefire JUnit processes
+ *
+ * @author <a href="mailto:andyglick@acm.org">Andy Glick</a>
+ * @version $Id$
+ */
+public class ForkedSurefireRunner
+{
+    public static String FORK_ONCE = "once";
+
+    public static String FORK_PERTEST = "pertest";
+
+    static int TESTS_SUCCEEDED = 0;
+
+    static int TESTS_FAILED = 255;
+
+    static int ILLEGAL_ARGUMENT_EXCEPTION = 100;
+
+    static int OTHER_EXCEPTION = 200;
+
+    private static Class thisClass = ForkedSurefireRunner.class;
+
+    private ForkedSurefireRunner()
+    {
+        super();
+    }
+
+    /**
+     * Constructs a Map from a set of strings of the form <key>=<value>
+     *
+     * @param args an array of strings composed of name/value pairs
+     * @return Map keyed by the names with the respective values
+     */
+    private static Map getArgMap( String[] args )
+    {
+        Map argMap = new LinkedHashMap();
+
+        for ( int i = 0; i < args.length; i++ )
+        {
+            String[] mapArgs = args[i].split( "=" );
+
+            argMap.put( mapArgs[0], mapArgs[1] );
+        }
+
+        return argMap;
+    }
+
+    /**
+     * This method is invoked when Surefire is forked - this method parses and
+     * organizes the arguments passed to it and then calls the Surefire class'
+     * run method.
+     *
+     * @param args
+     * @throws Exception
+     */
+    public static void main( String[] args )
+        throws Exception
+    {
+        Map argMap = getArgMap( args );
+
+        ClassLoader surefireClassLoader = thisClass.getClassLoader();
+
+        String batteryExecutorName = (String) argMap.get( "batteryExecutorName" );
+
+        Class batteryExecutorClass = surefireClassLoader.loadClass( batteryExecutorName );
+
+        Object batteryExecutor = batteryExecutorClass.newInstance();
+
+        String reports = (String) argMap.get( "reportClassNames" );
+
+        String[] reportClasses = reports.split( "," );
+
+        List reportList = Arrays.asList( reportClasses );
+
+        String batteryConfig = (String) argMap.get( "batteryConfig" );
+
+        String[] batteryParts = batteryConfig.split( "\\|" );
+
+        String batteryClassName = batteryParts[0];
+
+        Object[] batteryParms;
+
+        String forkMode = (String) argMap.get( "forkMode" );
+
+        if ( forkMode.equals( FORK_ONCE ) )
+        {
+            batteryParms = new Object[batteryParts.length - 1];
+
+            batteryParms[0] = new File( batteryParts[1] );
+
+            String stringList = batteryParts[2];
+
+            if ( stringList.startsWith( "[" ) && stringList.endsWith( "]" ) )
+            {
+                stringList = stringList.substring( 1, stringList.length() - 1 );
+            }
+
+            ArrayList includesList = new ArrayList();
+
+            String[] stringArray = stringList.split( "," );
+
+            for ( int i = 0; i < stringArray.length; i++ )
+            {
+                includesList.add( stringArray[i].trim() );
+            }
+
+            batteryParms[1] = includesList;
+
+            stringList = batteryParts[3];
+
+            ArrayList excludesList = new ArrayList();
+
+            if ( stringList.startsWith( "[" ) && stringList.endsWith( "]" ) )
+            {
+                stringList = stringList.substring( 1, stringList.length() - 1 );
+            }
+
+            stringArray = stringList.split( "," );
+
+            for ( int i = 0; i < stringArray.length; i++ )
+            {
+                excludesList.add( stringArray[i].trim() );
+            }
+
+            batteryParms[2] = excludesList;
+        }
+        else
+        {
+            batteryParms = new Object[1];
+
+            batteryParms[0] = batteryParts[1];
+        }
+
+        List batteryHolders = new ArrayList();
+
+        batteryHolders.add( new Object[]{batteryClassName, batteryParms} );
+
+        String reportsDirectory = (String) argMap.get( "reportsDirectory" );
+
+        Method run = batteryExecutorClass.getMethod( "run", new Class[]{List.class, List.class,
String.class} );
+
+        Object[] parms = new Object[]{reportList, batteryHolders, reportsDirectory};
+
+        int returnCode = TESTS_FAILED;
+
+        try
+        {
+            boolean result = ( (Boolean) run.invoke( batteryExecutor, parms ) ).booleanValue();
+
+            if ( result )
+            {
+                returnCode = TESTS_SUCCEEDED;
+            }
+
+        }
+        catch ( IllegalArgumentException e )
+        {
+            returnCode = ILLEGAL_ARGUMENT_EXCEPTION;
+        }
+        catch ( Exception e )
+        {
+            returnCode = OTHER_EXCEPTION;
+        }
+
+        System.exit( returnCode );
+    }
+}

Propchange: maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/ForkedSurefireRunner.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/ForkedSurefireRunner.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Modified: maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/SurefireBooter.java
URL: http://svn.apache.org/viewcvs/maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/SurefireBooter.java?rev=352042&r1=352041&r2=352042&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/SurefireBooter.java
(original)
+++ maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/SurefireBooter.java
Sat Dec  3 14:50:06 2005
@@ -16,17 +16,31 @@
  * limitations under the License.
  */
 
+import org.codehaus.plexus.util.cli.CommandLineException;
+import org.codehaus.plexus.util.cli.CommandLineUtils;
+import org.codehaus.plexus.util.cli.Commandline;
+import org.codehaus.plexus.util.cli.StreamConsumer;
+import org.codehaus.plexus.util.cli.WriterStreamConsumer;
+
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileReader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-import java.util.StringTokenizer;
 
+/**
+ * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
+ * @author <a href="mail-to:emmanuel@venisse.net">Emmanuel Venisse</a>
+ * @version $Id$
+ */
 public class SurefireBooter
 {
+    private static String RUNNER = "org.codehaus.surefire.ForkedSurefireRunner";
+
     private List batteries = new ArrayList();
 
     private List reports = new ArrayList();
@@ -35,6 +49,10 @@
 
     private String reportsDirectory;
 
+    private String forkMode;
+
+    private String basedir;
+
     public SurefireBooter()
     {
     }
@@ -44,14 +62,19 @@
         this.reportsDirectory = reportsDirectory;
     }
 
+    public String getReportsDirectory()
+    {
+        return this.reportsDirectory;
+    }
+
     public void addBattery( String battery, Object[] params )
     {
-        batteries.add( new Object[]{ battery, params } );
+        batteries.add( new Object[]{battery, params} );
     }
 
     public void addBattery( String battery )
     {
-        batteries.add( new Object[]{ battery, null } );
+        batteries.add( new Object[]{battery, null} );
     }
 
     public void addReport( String report )
@@ -72,12 +95,36 @@
         this.classpathUrls = classpathUrls;
     }
 
+    public void setForkMode( String forkMode )
+    {
+        this.forkMode = forkMode;
+    }
+
     public boolean run()
         throws Exception
     {
-        ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
+        boolean result = false;
+
+        if ( "once".equals( forkMode ) )
+        {
+            result = runTestsForkOnce();
+        }
+        else if ( "none".equals( forkMode ) )
+        {
+            result = runTestsInProcess();
+        }
+        else if ( "pertest".equals( forkMode ) )
+        {
+            result = runTestsForkEach();
+        }
 
-        IsolatedClassLoader surefireClassLoader = new IsolatedClassLoader( systemLoader );
+        return result;
+    }
+
+    private IsolatedClassLoader createClassLoader()
+        throws Exception
+    {
+        IsolatedClassLoader surefireClassLoader = new IsolatedClassLoader( ClassLoader.getSystemClassLoader()
);
 
         for ( Iterator i = classpathUrls.iterator(); i.hasNext(); )
         {
@@ -93,142 +140,278 @@
             surefireClassLoader.addURL( f.toURL() );
         }
 
+        return surefireClassLoader;
+    }
+
+    private boolean runTestsInProcess()
+        throws Exception
+    {
+        IsolatedClassLoader surefireClassLoader = createClassLoader();
+
         Class batteryExecutorClass = surefireClassLoader.loadClass( "org.codehaus.surefire.Surefire"
);
 
         Object batteryExecutor = batteryExecutorClass.newInstance();
 
-        Method run = batteryExecutorClass.getMethod( "run", new Class[] { List.class, List.class,
ClassLoader.class, String.class } );
+        Method run = batteryExecutorClass.getMethod( "run", new Class[]{List.class, List.class,
ClassLoader.class, String.class} );
 
-        ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
+        ClassLoader oldContextClassLoader = Thread.currentThread() .getContextClassLoader();
 
         Thread.currentThread().setContextClassLoader( surefireClassLoader );
 
-        Boolean result = (Boolean) run.invoke( batteryExecutor, new Object[]{ reports, batteries,
surefireClassLoader, reportsDirectory } );
+        Boolean result = (Boolean) run.invoke( batteryExecutor, new Object[]{reports, batteries,
surefireClassLoader, reportsDirectory} );
 
         Thread.currentThread().setContextClassLoader( oldContextClassLoader );
 
         return result.booleanValue();
     }
 
-    public void reset()
-    {
-        batteries.clear();
+    protected static final String EOL = System.getProperty( "line.separator" );
 
-        reports.clear();
+    protected static final String PS = System.getProperty( "path.separator" );
 
-        classpathUrls.clear();
+    private boolean runTestsForkOnce()
+        throws Exception
+    {
+        return fork( getForkOnceArgs() );
     }
 
-    // ----------------------------------------------------------------------
-    // Main
-    // ----------------------------------------------------------------------
+    private boolean runTestsForkEach()
+        throws Exception
+    {
+        boolean noFailures = true;
+
+        List testClasses = getTestClasses();
+
+        for ( Iterator i = testClasses.iterator(); i.hasNext(); )
+        {
+            String testClass = (String) i.next();
+
+            boolean result = fork( getForkPerTestArgs( testClass ) );
 
-    public static void main( String[] args )
+            if ( !result )
+            {
+                noFailures = false;
+            }
+        }
+
+        return noFailures;
+    }
+
+    private boolean fork( String[] args )
         throws Exception
     {
-        // 0: basedir
-        String basedir = args[0];
+        String executable = "java";
 
-        System.setProperty( "basedir", basedir );
+        File workingDirectory = new File( "." );
 
-        // 1; testClassesDirectory
-        String testClassesDirectory = args[1];
+        Commandline cli = new Commandline();
 
-        // 2; includes
+        basedir = workingDirectory.getAbsolutePath();
 
-        // 3: excludes
+        cli.setWorkingDirectory( basedir );
 
+        cli.setExecutable( executable );
 
-        String mavenRepoLocal = args[1];
+        cli.addArguments( args );
 
-        File dependenciesFile = new File( args[2] );
+        Writer stringWriter = new StringWriter();
 
-        List dependencies = new ArrayList();
+        StreamConsumer out = new WriterStreamConsumer( stringWriter );
 
-        BufferedReader buf = new BufferedReader( new FileReader( dependenciesFile ) );
+        StreamConsumer err = new WriterStreamConsumer( stringWriter );
 
-        String line;
+        int returnCode;
 
-        while ( ( line = buf.readLine() ) != null )
+        try
         {
-            dependencies.add( line );
+            returnCode = CommandLineUtils.executeCommandLine( cli, out, err );
+        }
+        catch ( CommandLineException e )
+        {
+            throw new Exception( "Error while executing forked tests.", e );
+        }
+        catch ( Exception e )
+        {
+            throw new SurefireBooterForkException( "Error while executing forked tests.",
e );
         }
 
-        buf.close();
+        String string = stringWriter.toString();
 
-        File includesFile = new File( args[3] );
+        if ( string != null && string.length() > 0 )
+        {
+            StringReader sr = new StringReader( string );
 
-        List includes = new ArrayList();
+            BufferedReader br = new BufferedReader( sr );
 
-        buf = new BufferedReader( new FileReader( includesFile ) );
+            while ( ( string = br.readLine() ) != null )
+            {
+                System.out.println( string );
+            }
+        }
 
-        line = buf.readLine();
+        if ( returnCode != 0 )
+        {
+            return false;
+        }
 
-        String includesStr = line.substring( line.indexOf( "@" ) + 1 );
+        return true;
+    }
+
+    private List getTestClasses()
+        throws Exception
+    {
 
-        StringTokenizer st = new StringTokenizer( includesStr, "," );
+        IsolatedClassLoader classLoader = createClassLoader();
 
-        while ( st.hasMoreTokens() )
+        List instantiatedBatteries = Surefire.instantiateBatteries( batteries, classLoader
);
+
+        List testClasses = new ArrayList();
+
+        for ( Iterator i = instantiatedBatteries.iterator(); i.hasNext(); )
         {
-            String inc = st.nextToken().trim();
+            Object o = i.next();
+
+            Method m = o.getClass().getMethod( "getSubBatteryClassNames", new Class[]{} );
 
-            includes.add( inc );
+            List tests = (List) m.invoke( o, new Object[]{} );
+
+            // This class comes from a different classloader then the isolated classloader.
+            // This is the battery class that is from a different loader.
+
+            testClasses.addAll( tests );
         }
 
-        buf.close();
+        return testClasses;
+    }
 
-        File excludesFile = new File( args[4] );
+    private String[] getForkOnceArgs()
+        throws Exception
+    {
+        // List reports
+        // List batteryHolders
+        // List classpathUrls
+        // String reportsDirectory
+        // String forkMode
 
-        List excludes = new ArrayList();
+        String pathSeparator = System.getProperty( "path.separator" );
 
-        buf = new BufferedReader( new FileReader( excludesFile ) );
+        String classpathEntries = getListOfStringsAsString( classpathUrls, pathSeparator
);
 
-        line = buf.readLine();
+        String reportClassNames = getListOfStringsAsString( reports, "," );
 
-        String excludesStr = line.substring( line.indexOf( "@" ) + 1 );
+        String[] batteryConfig = getStringArrayFromBatteries();
 
-        st = new StringTokenizer( excludesStr, "," );
+        String[] argArray =
+            {
+                "-classpath",
+                classpathEntries,
+                RUNNER,
+                "reportClassNames=" + reportClassNames,
+                "reportsDirectory=" + reportsDirectory,
+                "batteryExecutorName=" + "org.codehaus.surefire.Surefire",
+                "forkMode=" + forkMode,
+                "batteryConfig=" + batteryConfig[0]
+            };
 
-        while ( st.hasMoreTokens() )
-        {
-            excludes.add( st.nextToken().trim() );
-        }
+        return argArray;
+    }
 
-        buf.close();
+    private String[] getForkPerTestArgs( String testClass )
+        throws Exception
+    {
+        // List reports
+        // List batteryHolders
+        // List classpathUrls
+        // String reportsDirectory
+        // String forkMode
 
-        SurefireBooter surefireBooter = new SurefireBooter();
+        String pathSeparator = System.getProperty( "path.separator" );
 
-        System.out.println( "testClassesDirectory = " + testClassesDirectory );
+        String classpathEntries = getListOfStringsAsString( classpathUrls, pathSeparator
);
 
-        System.out.println( "includes = " + includes );
+        String reportClassNames = getListOfStringsAsString( reports, "," );
 
-        System.out.println( "excludes = " + excludes );
+        String batteryConfig = "org.codehaus.surefire.battery.SingleTestBattery|" + testClass;
 
-        surefireBooter.addBattery( "org.codehaus.surefire.battery.DirectoryBattery", new
Object[]{ testClassesDirectory, includes, excludes } );
+        String[] argArray =
+            {
+                "-classpath",
+                classpathEntries,
+                RUNNER,
+                "reportClassNames=" + reportClassNames,
+                "reportsDirectory=" + reportsDirectory,
+                "batteryExecutorName=" + "org.codehaus.surefire.Surefire",
+                "forkMode=" + forkMode,
+                "batteryConfig=" + batteryConfig
+            };
 
-        surefireBooter.addClassPathUrl( new File( mavenRepoLocal, "junit/jars/junit-3.8.1.jar"
).getPath() );
+        return argArray;
+    }
 
-        surefireBooter.addClassPathUrl( new File( mavenRepoLocal, "surefire/jars/surefire-1.3-SNAPSHOT.jar"
).getPath() );
+    public void reset()
+    {
+        batteries.clear();
 
-        surefireBooter.addClassPathUrl( new File( testClassesDirectory, "target/classes/"
).getPath() );
+        reports.clear();
 
-        surefireBooter.addClassPathUrl( new File( testClassesDirectory, "target/test-classes/"
).getPath() );
+        classpathUrls.clear();
+    }
 
-        processDependencies( dependencies, surefireBooter );
+    private String getListOfStringsAsString( List listOfStrings,
+                                             String delimiterParm )
+    {
+        StringBuffer stringBuffer = new StringBuffer();
 
-        surefireBooter.addReport( "org.codehaus.surefire.report.ConsoleReport" );
+        Iterator listOfStringsIterator = listOfStrings.iterator();
+
+        String delimiter = "";
+
+        while ( listOfStringsIterator.hasNext() )
+        {
+            String string = (String) listOfStringsIterator.next();
 
-        surefireBooter.run();
+            stringBuffer.append( delimiter );
+
+            stringBuffer.append( string );
+
+            delimiter = delimiterParm;
+        }
+
+        return new String( stringBuffer );
     }
 
-    private static void processDependencies( List dependencies, SurefireBooter sureFire )
-        throws Exception
+    private String[] getStringArrayFromBatteries()
     {
-        for ( Iterator i = dependencies.iterator(); i.hasNext(); )
+        String[] batteryConfig = new String[batteries.size()];
+
+        StringBuffer batteryBuffer = new StringBuffer();
+
+        String delimiter = "";
+
+        int batteryCounter = 0;
+
+        for ( Iterator j = batteries.iterator(); j.hasNext(); )
         {
-            String dep = (String) i.next();
-         
-            sureFire.addClassPathUrl( new File( dep ).getPath() );
+            Object[] batteryArray = (Object[]) j.next();
+
+            batteryBuffer.append( (String) batteryArray[0] );
+
+            if ( batteryArray[1] != null )
+            {
+                Object[] batteryParms = (Object[]) batteryArray[1];
+
+                for ( int i = 0; i < 3; i++ )
+                {
+                    batteryBuffer.append( "|" );
+
+                    batteryBuffer.append( batteryParms[i] );
+                }
+            }
+
+            batteryConfig[batteryCounter++] = new String( batteryBuffer );
         }
+
+        return batteryConfig;
     }
 }
+

Added: maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/SurefireBooterForkException.java
URL: http://svn.apache.org/viewcvs/maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/SurefireBooterForkException.java?rev=352042&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/SurefireBooterForkException.java
(added)
+++ maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/SurefireBooterForkException.java
Sat Dec  3 14:50:06 2005
@@ -0,0 +1,35 @@
+package org.codehaus.surefire;
+
+/*
+ * Copyright 2001-2005 The Codehaus.
+ *
+ * Licensed 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.
+ */
+
+public class SurefireBooterForkException extends Exception
+{
+  public SurefireBooterForkException(String message)
+  {
+    super(message);
+  }
+
+  public SurefireBooterForkException(Throwable cause)
+  {
+    super(cause);
+  }
+
+  public SurefireBooterForkException(String message, Throwable cause)
+  {
+    super(message, cause);
+  }
+}

Propchange: maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/SurefireBooterForkException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/surefire/trunk/surefire-booter/src/main/java/org/codehaus/surefire/SurefireBooterForkException.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"



Mime
View raw message