Enable parallel unit tests for 8.0.x

git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc8.0.x/trunk@1696308 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/BUILDING.txt b/BUILDING.txt
index 06a97b3..26afdec 100644
--- a/BUILDING.txt
+++ b/BUILDING.txt
@@ -64,9 +64,10 @@
     into which you installed the JDK release.
 
 
-(2) Install Apache Ant version 1.8.2 or later on your computer
+(2) Install Apache Ant version 1.9.5 or later on your computer.
 
- 1. If Apache Ant version 1.8.2 or later is already installed on your computer, skip to (3).
+ 1. If Apache Ant version 1.9.5 or later is already installed on your computer,
+    skip to (3).
 
  2. Download a binary distribution of Ant from:
 
diff --git a/build.properties.default b/build.properties.default
index 6edc681..6c04bf1 100644
--- a/build.properties.default
+++ b/build.properties.default
@@ -42,6 +42,12 @@
 # Activate AccessLog during testing
 test.accesslog=false
 
+# Number of parallel threads to use for testing. The recommended value is one
+# thread per core.
+# Note: Cobertura code coverage currently requires this to be set to 1. Setting
+#       a value above one will disable code coverage if enabled.
+test.threads=1
+
 # Note the Cobertura code coverage tool is GPLv2 licensed
 test.cobertura=false
 
diff --git a/build.xml b/build.xml
index ef3a3be..f8cbfc0 100644
--- a/build.xml
+++ b/build.xml
@@ -1419,7 +1419,8 @@
       <junit printsummary="yes" fork="yes" dir="." showoutput="yes"
         errorproperty="test.result.error"
         failureproperty="test.result.failure"
-        haltonfailure="${test.haltonfailure}" >
+        haltonfailure="${test.haltonfailure}"
+        threads="${test.threads}" >
 
         <jvmarg value="${test.jvmarg.egd}"/>
         <jvmarg value="-Djava.library.path=${test.apr.loc}"/>
@@ -1468,15 +1469,39 @@
     </sequential>
   </macrodef>
 
-  <target name="cobertura-disabled" unless="${test.cobertura}">
+  <target name="cobertura-init">
+    <condition property="cobertura.enabled" value="true">
+      <and>
+        <istrue value="${test.cobertura}"/>
+        <equals arg1="1" arg2="${test.threads}"/>
+      </and>
+    </condition>
+    <condition property="cobertura.disabled" value="true">
+        <and>
+          <istrue value="${test.cobertura}"/>
+          <not>
+            <equals arg1="1" arg2="${test.threads}"/>
+          </not>
+        </and>
+    </condition>
+  </target>
+
+  <target name="cobertura-disabled" unless="${cobertura.enabled}"
+          depends="cobertura-init">
     <!-- Define classpath used to run tests when Cobertura is turned off. -->
     <path id="tomcat.test.run.classpath">
       <path refid="tomcat.test.classpath" />
     </path>
   </target>
 
-  <target name="cobertura-instrument" depends="compile,download-cobertura,cobertura-disabled"
-          if="${test.cobertura}"
+  <target name="cobertura-disabled-log" if="${cobertura.disabled}"
+          depends="cobertura-init">
+    <echo message="Code coverage disabled because test.threads is greater than 1"/>
+  </target>
+
+  <target name="cobertura-instrument"
+          depends="compile,download-cobertura,cobertura-disabled,cobertura-disabled-log"
+          if="${cobertura.enabled}"
           description="Adds Cobertura instrumentation to the compiled bytecode">
 
     <path id="cobertura.classpath">
@@ -1518,7 +1543,7 @@
     </path>
   </target>
 
-  <target name="cobertura-report" if="${test.cobertura}"
+  <target name="cobertura-report" if="${cobertura.enabled}"
           depends="test-bio,test-nio,test-nio2,test-apr"
           description="Creates report from gathered Cobertura results">
 
diff --git a/test/org/apache/catalina/startup/LoggingBaseTest.java b/test/org/apache/catalina/startup/LoggingBaseTest.java
index 21aa44e..09d57e2 100644
--- a/test/org/apache/catalina/startup/LoggingBaseTest.java
+++ b/test/org/apache/catalina/startup/LoggingBaseTest.java
@@ -17,8 +17,12 @@
 package org.apache.catalina.startup;
 
 import java.io.File;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.logging.LogManager;
 
 import static org.junit.Assert.fail;
 
@@ -27,6 +31,7 @@
 import org.junit.Rule;
 import org.junit.rules.TestName;
 
+import org.apache.juli.ClassLoaderLogManager;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 
@@ -97,10 +102,12 @@
     @Before
     public void setUp() throws Exception {
         // Create catalina.base directory
-        tempDir = new File(System.getProperty("tomcat.test.temp", "output/tmp"));
-        if (!tempDir.mkdirs() && !tempDir.isDirectory()) {
-            fail("Unable to create temporary directory for test");
+        File tempBase = new File(System.getProperty("tomcat.test.temp", "output/tmp"));
+        if (!tempBase.mkdirs() && !tempBase.isDirectory()) {
+            fail("Unable to create base temporary directory for tests");
         }
+        Path tempBasePath = FileSystems.getDefault().getPath(tempBase.getAbsolutePath());
+        tempDir = Files.createTempDirectory(tempBasePath, "test").toFile();
 
         System.setProperty("catalina.base", tempDir.getAbsolutePath());
 
@@ -121,5 +128,13 @@
             ExpandWar.delete(file);
         }
         deleteOnTearDown.clear();
+
+        LogManager logManager = LogManager.getLogManager();
+        if (logManager instanceof ClassLoaderLogManager) {
+            ((ClassLoaderLogManager) logManager).shutdown();
+        } else {
+            logManager.reset();
+        }
+        ExpandWar.deleteDir(tempDir);
     }
 }
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index d2f2faf..9cc36a5 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -275,6 +275,11 @@
         Update package renamed Apache Commons DBCP to Commons DBCP 2.1.1.
         (markt)
       </update>
+      <add>
+        Support the use of the <code>threads</code> attribute on Ant&apos;s
+        junit task. Note that using this with a value of greater than one will
+        disbale Cobertura code coverage. (markt)
+      </add>
     </changelog>
   </subsection>
 </section>