Author: krosenvold
Date: Thu Dec 22 21:55:05 2011
New Revision: 1222474

URL: http://svn.apache.org/viewvc?rev=1222474&view=rev
Log:
[SUREFIRE-799] Allow test parallelisation when forkMode=always

Patch by nkeyval, applied with review changes from me.

Added:
    
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java
   (with props)
Modified:
    
maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
    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/booterclient/ForkConfiguration.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/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
    
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java
    
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/pom.xml

Modified: 
maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java?rev=1222474&r1=1222473&r2=1222474&view=diff
==============================================================================
--- 
maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
 (original)
+++ 
maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
 Thu Dec 22 21:55:05 2011
@@ -350,8 +350,8 @@ public class IntegrationTestMojo
     private Boolean failIfNoTests;
 
     /**
-     * Option to specify the forking mode. Can be "never", "once" or "always". 
"none" and "pertest" are also accepted
-     * for backwards compatibility. "always" forks for each test-class.
+     * Option to specify the forking mode. Can be "never", "once", "always" or 
"perthread". "none" and "pertest" are also accepted
+     * for backwards compatibility. "always" forks for each test-class. 
"perthread" will create "threadCount" parallel forks.
      *
      * @parameter expression="${forkMode}" default-value="once"
      * @since 2.1
@@ -472,8 +472,9 @@ public class IntegrationTestMojo
     private String testNGArtifactName;
 
     /**
-     * (TestNG/JUnit 4.7 provider only) The attribute thread-count allows you 
to specify how many threads should be
-     * allocated for this execution. Only makes sense to use in conjunction 
with the <code>parallel</code> parameter.
+     * (forkMode=perthread or TestNG/JUnit 4.7 provider) The attribute 
thread-count allows you to specify how many threads should be
+     * allocated for this execution. Only makes sense to use in conjunction 
with the <code>parallel</code> parameter. (forkMode=perthread
+     * does not support/require the <code>parallel</code> parameter)
      *
      * @parameter expression="${threadCount}"
      * @since 2.2

Modified: maven/surefire/trunk/maven-surefire-common/pom.xml
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/pom.xml?rev=1222474&r1=1222473&r2=1222474&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/pom.xml (original)
+++ maven/surefire/trunk/maven-surefire-common/pom.xml Thu Dec 22 21:55:05 2011
@@ -97,24 +97,4 @@
       </plugin>
     </plugins>
   </build>
-
-  <profiles>
-    <!-- Force JDK 1.4 for this one, plugins can never be built on 1.3 -->
-    <profile>
-      <id>jdk1.3</id>
-      <build>
-        <pluginManagement>
-          <plugins>
-            <plugin>
-              <artifactId>maven-compiler-plugin</artifactId>
-              <configuration>
-                <fork>false</fork>
-                <compilerVersion>1.4</compilerVersion>
-              </configuration>
-            </plugin>
-          </plugins>
-        </pluginManagement>
-      </build>
-    </profile>
-  </profiles>
 </project>

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=1222474&r1=1222473&r2=1222474&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
 Thu Dec 22 21:55:05 2011
@@ -260,7 +260,8 @@ public abstract class AbstractSurefireMo
 
         if ( this.getThreadCount() > 0 )
         {
-            getProperties().setProperty( 
ProviderParameterNames.THREADCOUNT_PROP, Integer.toString( 
this.getThreadCount() ) );
+            getProperties().setProperty( 
ProviderParameterNames.THREADCOUNT_PROP,
+                                         Integer.toString( 
this.getThreadCount() ) );
         }
         if ( this.getObjectFactory() != null )
         {
@@ -317,7 +318,8 @@ public abstract class AbstractSurefireMo
         }
         if ( this.getThreadCount() > 0 )
         {
-            getProperties().setProperty( 
ProviderParameterNames.THREADCOUNT_PROP, Integer.toString( 
this.getThreadCount() ) );
+            getProperties().setProperty( 
ProviderParameterNames.THREADCOUNT_PROP,
+                                         Integer.toString( 
this.getThreadCount() ) );
         }
         getProperties().setProperty( "perCoreThreadCount", Boolean.toString( 
getPerCoreThreadCount() ) );
         getProperties().setProperty( "useUnlimitedThreads", Boolean.toString( 
getUseUnlimitedThreads() ) );
@@ -727,6 +729,15 @@ public abstract class AbstractSurefireMo
                     setEnableAssertions( false );
                 }
             }
+
+            if ( fork.getForkMode().equals( ForkConfiguration.FORK_PERTHREAD ) 
)
+            {
+                fork.setThreadCount( getThreadCount() );
+            }
+            else
+            {
+                fork.setThreadCount( 1 );
+            }
         }
         return fork;
     }

Modified: 
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java?rev=1222474&r1=1222473&r2=1222474&view=diff
==============================================================================
--- 
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
 (original)
+++ 
maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
 Thu Dec 22 21:55:05 2011
@@ -54,6 +54,10 @@ public class ForkConfiguration
 
     public static final String FORK_NEVER = "never";
 
+    public static final String FORK_PERTHREAD = "perthread";
+
+    private int threadCount;
+
     private final Classpath bootClasspathConfiguration;
 
     private final String forkMode;
@@ -96,7 +100,8 @@ public class ForkConfiguration
         {
             return FORK_NEVER;
         }
-        else if ( forkMode.equals( FORK_NEVER ) || forkMode.equals( FORK_ONCE 
) || forkMode.equals( FORK_ALWAYS ) )
+        else if ( forkMode.equals( FORK_NEVER ) || forkMode.equals( FORK_ONCE 
) ||
+            forkMode.equals( FORK_ALWAYS ) || forkMode.equals( FORK_PERTHREAD 
) )
         {
             return forkMode;
         }
@@ -302,4 +307,14 @@ public class ForkConfiguration
     {
         return tempDirectory;
     }
+
+    public int getThreadCount()
+    {
+        return threadCount;
+    }
+
+    public void setThreadCount( int threadCount )
+    {
+        this.threadCount = threadCount;
+    }
 }

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=1222474&r1=1222473&r2=1222474&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
 Thu Dec 22 21:55:05 2011
@@ -21,8 +21,16 @@ package org.apache.maven.plugin.surefire
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.Properties;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 import org.apache.maven.plugin.surefire.CommonReflector;
 import org.apache.maven.plugin.surefire.booterclient.output.ForkClient;
 import 
org.apache.maven.plugin.surefire.booterclient.output.ThreadedStreamConsumer;
@@ -72,6 +80,13 @@ public class ForkStarter
 
     private final StartupReportConfiguration startupReportConfiguration;
 
+    private final FileReporterFactory fileReporterFactory;
+
+    private static volatile int systemPropertiesFileCounter = 0;
+
+    private static final Object lock = new Object();
+
+
     public ForkStarter( ProviderConfiguration providerConfiguration, 
StartupConfiguration startupConfiguration,
                         ForkConfiguration forkConfiguration, int 
forkedProcessTimeoutInSeconds,
                         StartupReportConfiguration startupReportConfiguration )
@@ -81,28 +96,31 @@ public class ForkStarter
         this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds;
         this.startupConfiguration = startupConfiguration;
         this.startupReportConfiguration = startupReportConfiguration;
+        fileReporterFactory = new FileReporterFactory( 
startupReportConfiguration );
     }
 
     public RunResult run()
         throws SurefireBooterForkException, SurefireExecutionException
     {
         final RunResult result;
-
         final String requestedForkMode = forkConfiguration.getForkMode();
-        final FileReporterFactory fileReporterFactory = new 
FileReporterFactory( startupReportConfiguration );
         try
         {
-            final ForkClient forkClient =
-                new ForkClient( fileReporterFactory, 
startupReportConfiguration.getTestVmSystemProperties() );
-            final RunStatistics globalRunStatistics = 
fileReporterFactory.getGlobalRunStatistics();
             if ( ForkConfiguration.FORK_ONCE.equals( requestedForkMode ) )
             {
-                result = fork( null, 
providerConfiguration.getProviderProperties(), forkClient, globalRunStatistics 
);
+                final ForkClient forkClient =
+                    new ForkClient( fileReporterFactory, 
startupReportConfiguration.getTestVmSystemProperties() );
+                result = fork( null, 
providerConfiguration.getProviderProperties(), forkClient,
+                               fileReporterFactory.getGlobalRunStatistics() );
             }
             else if ( ForkConfiguration.FORK_ALWAYS.equals( requestedForkMode 
) )
             {
-                result = runSuitesForkPerTestSet( 
providerConfiguration.getProviderProperties(), forkClient,
-                                                  globalRunStatistics );
+                result = runSuitesForkPerTestSet( 
providerConfiguration.getProviderProperties(), 1 );
+            }
+            else if ( ForkConfiguration.FORK_PERTHREAD.equals( 
requestedForkMode ) )
+            {
+                result = runSuitesForkPerTestSet( 
providerConfiguration.getProviderProperties(),
+                                                  
forkConfiguration.getThreadCount() );
             }
             else
             {
@@ -116,24 +134,85 @@ public class ForkStarter
         return result;
     }
 
-    private RunResult runSuitesForkPerTestSet( Properties properties, 
ForkClient forkClient,
-                                               RunStatistics 
globalRunStatistics )
+    private RunResult runSuitesForkPerTestSet( final Properties properties, 
int forkCount )
         throws SurefireBooterForkException
     {
-        RunResult globalResult = new RunResult( 0, 0, 0, 0 );
 
-        final Iterator suites = getSuitesIterator();
+        ArrayList<Future<RunResult>> results = new 
ArrayList<Future<RunResult>>( 500 );
+        ExecutorService executorService = new ThreadPoolExecutor( forkCount, 
forkCount, 60, TimeUnit.SECONDS,
+                                                                  new 
ArrayBlockingQueue<Runnable>( 500 ) );
 
-        while ( suites.hasNext() )
+        try
         {
-            Object testSet = suites.next();
-            RunResult runResult = fork( testSet, properties, forkClient, 
globalRunStatistics );
-            globalResult = globalResult.aggregate( runResult );
+            // Ask to the executorService to run all tasks
+            RunResult globalResult = new RunResult( 0, 0, 0, 0 );
+            final Iterator suites = getSuitesIterator();
+            while ( suites.hasNext() )
+            {
+                final Object testSet = suites.next();
+                final ForkClient forkClient =
+                    new ForkClient( fileReporterFactory, 
startupReportConfiguration.getTestVmSystemProperties() );
+                Callable<RunResult> pf = new Callable<RunResult>()
+                {
+                    public RunResult call()
+                        throws Exception
+                    {
+                        return fork( testSet, properties, forkClient, 
fileReporterFactory.getGlobalRunStatistics() );
+                    }
+                };
+                results.add( executorService.submit( pf ) );
+
+            }
+
+            for ( Future<RunResult> result : results )
+            {
+                try
+                {
+                    RunResult cur = result.get();
+                    if ( cur != null )
+                    {
+                        globalResult = globalResult.aggregate( cur );
+                    }
+                    else
+                    {
+                        throw new SurefireBooterForkException( "No results for 
" + result.toString() );
+                    }
+                }
+                catch ( InterruptedException e )
+                {
+                    throw new SurefireBooterForkException( "Interrupted", e );
+                }
+                catch ( ExecutionException e )
+                {
+                    throw new SurefireBooterForkException( 
"ExecutionException", e );
+                }
+            }
+            return globalResult;
+
+        }
+        finally
+        {
+            closeExecutor( executorService );
         }
 
-        return globalResult;
     }
 
+    private void closeExecutor( ExecutorService executorService )
+        throws SurefireBooterForkException
+    {
+        executorService.shutdown();
+        try
+        {
+            // Should stop immediately, as we got all the results if we are 
here
+            executorService.awaitTermination( 60 * 60, TimeUnit.SECONDS );
+        }
+        catch ( InterruptedException e )
+        {
+            throw new SurefireBooterForkException( "Interrupted", e );
+        }
+    }
+
+
     private RunResult fork( Object testSet, Properties properties, ForkClient 
forkClient,
                             RunStatistics globalRunStatistics )
         throws SurefireBooterForkException
@@ -151,7 +230,9 @@ public class ForkStarter
             {
                 systemProperties = SystemPropertyManager.writePropertiesFile( 
forkConfiguration.getSystemProperties(),
                                                                               
forkConfiguration.getTempDirectory(),
-                                                                              
"surefire", forkConfiguration.isDebug() );
+                                                                              
"surefire_"
+                                                                               
   + systemPropertiesFileCounter++,
+                                                                              
forkConfiguration.isDebug() );
             }
         }
         catch ( IOException e )
@@ -197,7 +278,7 @@ public class ForkStarter
 
             if ( result != RunResult.SUCCESS )
             {
-                throw new SurefireBooterForkException( "Error occured in 
starting fork, check output in log" );
+                throw new SurefireBooterForkException( "Error occurred in 
starting fork, check output in log" );
             }
             threadedStreamConsumer.close();
             forkClient.close();
@@ -241,5 +322,4 @@ public class ForkStarter
         }
     }
 
-
 }

Modified: 
maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java?rev=1222474&r1=1222473&r2=1222474&view=diff
==============================================================================
--- 
maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
 (original)
+++ 
maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
 Thu Dec 22 21:55:05 2011
@@ -319,8 +319,8 @@ public class SurefirePlugin
     private Boolean failIfNoTests;
 
     /**
-     * Option to specify the forking mode. Can be "never", "once" or "always". 
"none" and "pertest" are also accepted
-     * for backwards compatibility. "always" forks for each test-class.
+     * Option to specify the forking mode. Can be "never", "once", "always" or 
"perthread". "none" and "pertest" are also accepted
+     * for backwards compatibility. "always" forks for each test-class. 
"perthread" will create "threadCount" parallel forks.
      *
      * @parameter expression="${forkMode}" default-value="once"
      * @since 2.1
@@ -442,8 +442,9 @@ public class SurefirePlugin
     private String testNGArtifactName;
 
     /**
-     * (TestNG/JUnit 4.7 provider only) The attribute thread-count allows you 
to specify how many threads should be
-     * allocated for this execution. Only makes sense to use in conjunction 
with the <code>parallel</code> parameter.
+     * (forkMode=perthread or TestNG/JUnit 4.7 provider) The attribute 
thread-count allows you to specify how many threads should be
+     * allocated for this execution. Only makes sense to use in conjunction 
with the <code>parallel</code> parameter. (forkMode=perthread
+     * does not support/require the <code>parallel</code> parameter)
      *
      * @parameter expression="${threadCount}"
      * @since 2.2

Modified: 
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java?rev=1222474&r1=1222473&r2=1222474&view=diff
==============================================================================
--- 
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java
 (original)
+++ 
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java
 Thu Dec 22 21:55:05 2011
@@ -19,19 +19,18 @@ package org.apache.maven.surefire.its;
  * under the License.
  */
 
-import org.apache.maven.it.VerificationException;
-import org.apache.maven.it.Verifier;
-import org.apache.maven.it.util.ResourceExtractor;
-import org.apache.maven.surefire.its.misc.HelperAssertions;
-
 import java.io.File;
 import java.io.IOException;
 import java.util.Calendar;
 import java.util.List;
+import org.apache.maven.it.VerificationException;
+import org.apache.maven.it.Verifier;
+import org.apache.maven.it.util.ResourceExtractor;
+import org.apache.maven.surefire.its.misc.HelperAssertions;
 
 /**
  * Verifies the runOrder setting and its effect
- * 
+ *
  * @author Kristian Rosenvold
  */
 public class RunOrderIT
@@ -45,7 +44,7 @@ public class RunOrderIT
 
     private File testDir;
 
-    private Verifier verifier;
+    protected Verifier verifier;
 
     public void setUp()
         throws IOException, VerificationException
@@ -111,10 +110,17 @@ public class RunOrderIT
         HelperAssertions.assertTestSuiteResults( 3, 0, 0, 0, testDir );
     }
 
-    private void executeTestsWithRunOrder( String runOrder )
+
+    protected String getForkMode()
+    {
+        return "once";
+    }
+
+    protected void executeTestsWithRunOrder( String runOrder )
         throws VerificationException
     {
         List<String> goals = getInitialGoals();
+        goals.add( "-DforkMode=" + getForkMode() );
         goals.add( "-DrunOrder=" + runOrder );
         goals.add( "test" );
         executeGoals( verifier, goals );
@@ -129,7 +135,8 @@ public class RunOrderIT
         }
     }
 
-    private boolean testnamesAppearInSpecificOrder( String[] testnames ) 
throws VerificationException
+    private boolean testnamesAppearInSpecificOrder( String[] testnames )
+        throws VerificationException
     {
         int i = 0;
         for ( String line : getLog() )

Added: 
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java?rev=1222474&view=auto
==============================================================================
--- 
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java
 (added)
+++ 
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java
 Thu Dec 22 21:55:05 2011
@@ -0,0 +1,31 @@
+package org.apache.maven.surefire.its;
+
+/*
+ * 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.
+ */
+
+public class RunOrderParallelForksIT
+    extends RunOrderIT
+{
+
+    @Override
+    protected String getForkMode()
+    {
+        return "perthread";
+    }
+}

Propchange: 
maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/pom.xml
URL: 
http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/pom.xml?rev=1222474&r1=1222473&r2=1222474&view=diff
==============================================================================
--- 
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/pom.xml
 (original)
+++ 
maven/surefire/trunk/surefire-integration-tests/src/test/resources/runorder-parallel/pom.xml
 Thu Dec 22 21:55:05 2011
@@ -11,7 +11,7 @@
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>4.8.1</version>
+      <version>4.10</version>
     </dependency>
   </dependencies>
 
@@ -34,7 +34,6 @@
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${surefire.version}</version>
            <configuration>
-             <forkMode>once</forkMode>
              <runOrder>${runOrder}</runOrder>
              <threadCount>2</threadCount>
              <perCoreThreadCount>false</perCoreThreadCount>


Reply via email to