You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by kr...@apache.org on 2012/06/21 13:45:44 UTC

svn commit: r1352502 - in /db/derby/code/trunk: build.xml java/testing/org/apache/derbyTesting/junit/BaseTestCase.java

Author: kristwaa
Date: Thu Jun 21 11:45:44 2012
New Revision: 1352502

URL: http://svn.apache.org/viewvc?rev=1352502&view=rev
Log:
DERBY-5817: Add support for the JaCoCo code coverage tool

Adds initial support for the JaCoCo code coverage tool.
Top-level ant targets:
 o jacoco-complete: runs derbyall, suites.All, junit-lowmem and junit-pptesting
 o jacoco-junit: runs suite.All
 o jacoco-junit-single: runs test specified by the property

The report currently ends up under 'junit_{timestamp}/coverage-report'.
You need to install 'jacocoant.jar' and 'jacocoagent.jar' in 'tools/java/'

Refactored the ant target 'getsvnversion' (now also loads the version into the
property 'changenumber' and runs only if that property isn't already set).

Patch file: derby-5817-1c-jacoco_support.diff

Modified:
    db/derby/code/trunk/build.xml
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java

Modified: db/derby/code/trunk/build.xml
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/build.xml?rev=1352502&r1=1352501&r2=1352502&view=diff
==============================================================================
--- db/derby/code/trunk/build.xml (original)
+++ db/derby/code/trunk/build.xml Thu Jun 21 11:45:44 2012
@@ -16,7 +16,7 @@
   limitations under the License.
 -->
 
-<project default="buildsource" basedir=".">
+<project default="buildsource" basedir="." xmlns:jacoco="antlib:org.jacoco.ant">
 
 <!-- Set Properties -->
 
@@ -1420,19 +1420,6 @@
     <property name="derby.jar.topdir" value="${jarsdist.dir}"/>
     <mkdir dir="${derby.jar.dir}"/>
     <mkdir dir="${derby.jar.dir}/lists"/>
-    <loadfile srcFile="${out.base}/changenumber.properties"
-               failonerror="false"
-               property="changenumber">
-      <filterchain>
-        <striplinebreaks/>
-      </filterchain>
-    </loadfile>    
-    <condition property="changenumber" value="???">
-      <not>
-        <isset property="changenumber"/>
-      </not>
-    </condition>
-    <echo level="info" message="Revision number set to ${changenumber}."/>
   </target>
 
 
@@ -1942,13 +1929,26 @@
   </target>
 
 
-   <target name="getsvnversion">
+   <target name="getsvnversion" unless="changenumber">
      <exec executable="svnversion"
            failifexecutionfails="no"
            output="${out.base}/changenumber.properties">
        <arg value="${basedir}"/>
        <arg value="-n"/>
      </exec>
+     <loadfile srcFile="${out.base}/changenumber.properties"
+               failonerror="false"
+               property="changenumber">
+       <filterchain>
+         <striplinebreaks/>
+       </filterchain>
+     </loadfile>    
+     <condition property="changenumber" value="???">
+       <not>
+         <isset property="changenumber"/>
+       </not>
+     </condition>
+     <echo level="info" message="Revision number set to ${changenumber}."/>
    </target>
 
   <target name="cleanjars" depends="setsanityname">
@@ -2099,14 +2099,7 @@
 
      <property file="${properties.dir}/release.properties"/>
 
-      <antcall target="getsvnversion"/>
-      <loadfile srcFile="${out.base}/changenumber.properties"
-               failonerror="false"
-               property="changenumber">
-        <filterchain>
-          <striplinebreaks/>
-        </filterchain>
-      </loadfile>    
+     <antcall target="getsvnversion"/>
 
      <ant dir="${docs.root}" target="clobber"/>
 
@@ -2254,6 +2247,15 @@
     <property name="derby.junit.jvm" value="java"/>
     <property name="derby.junit.timestamp" value="${derby.junit.DSTAMP}_${derby.junit.TSTAMP}"/>
     <mkdir dir="junit_${derby.junit.timestamp}/testout"/>
+
+    <!-- Set a dummy value for the JaCoCo agent option when running without
+         JaCoCo for code coverage. Required because ant doesn't (yet) handle
+         empty variables passed to jvmarg. See also target jacoco-enable. -->
+    <condition property="derby.tests.jacoco.agent" value="-Dderby.dummy.prop=X">
+      <not>
+        <isset property="derby.tests.jacoco.agent"/>            
+      </not>
+    </condition>
   </target>
 
   <target name="junit-init" depends="junit-init-nocp">
@@ -2378,6 +2380,8 @@
            tempdir="junit_${derby.junit.timestamp}"
   	 	   errorproperty="tests.failed"
   	       failureproperty="tests.failed">
+      <jvmarg value="${derby.tests.jacoco.agent}"/>
+      <sysproperty key="derby.tests.jacoco.agent" value="${derby.tests.jacoco.agent}"/>
       <sysproperty key="derbyTesting.oldReleasePath" value="${derbyTesting.oldReleasePath}"/>
       <!-- This property is needed to keep EMMA silent when measuring codecoverage -->
       <sysproperty key="emma.verbosity.level" value="silent"/>
@@ -2438,6 +2442,8 @@
                tempdir="junit_${derby.junit.timestamp}"
                errorproperty="tests.failed"
                failureproperty="tests.failed">
+          <jvmarg value="${derby.tests.jacoco.agent}"/>
+          <sysproperty key="derby.tests.jacoco.agent" value="${derby.tests.jacoco.agent}"/>
           <formatter type="xml"/>
 
     <test name="org.apache.derbyTesting.system.oe.test.OETest"
@@ -2466,6 +2472,8 @@
            tempdir="junit_${derby.junit.timestamp}"
   	 	   errorproperty="tests.failed"
   	       failureproperty="tests.failed">
+      <jvmarg value="${derby.tests.jacoco.agent}"/>
+      <sysproperty key="derby.tests.jacoco.agent" value="${derby.tests.jacoco.agent}"/>
       <formatter type="xml"/>
   	 	
       <test name="org.apache.derbyTesting.functionTests.tests.jdbc4._Suite"
@@ -2478,7 +2486,6 @@
       </junit>	
   </target>
 
-	  
   <!-- low memory suite runs with 16MB heap  -->
   <target name="junit-lowmem"  depends="checkVMLevel,junit-init" if="vmLevelIsAtLeast1.5">
   	 <junit printsummary="on"
@@ -2489,6 +2496,8 @@
            tempdir="junit_${derby.junit.timestamp}"
   	 	   errorproperty="tests.failed"
   	       failureproperty="tests.failed">
+      <jvmarg value="${derby.tests.jacoco.agent}"/>
+      <sysproperty key="derby.tests.jacoco.agent" value="${derby.tests.jacoco.agent}"/>
       <formatter type="xml"/>
   	 	
       <test name="org.apache.derbyTesting.functionTests.tests.memory._Suite"
@@ -2510,6 +2519,8 @@
             tempdir="junit_${derby.junit.timestamp}"
             errorproperty="tests.failed"
             failureproperty="tests.failed">
+        <jvmarg value="${derby.tests.jacoco.agent}"/>
+        <sysproperty key="derby.tests.jacoco.agent" value="${derby.tests.jacoco.agent}"/>
         <formatter type="xml"/>
 
         <test name="org.apache.derbyTesting.functionTests.tests.management._Suite"
@@ -2532,6 +2543,8 @@
             tempdir="junit_${derby.junit.timestamp}"
             errorproperty="tests.failed"
             failureproperty="tests.failed">
+        <jvmarg value="${derby.tests.jacoco.agent}"/>
+        <sysproperty key="derby.tests.jacoco.agent" value="${derby.tests.jacoco.agent}"/>
         <formatter type="xml"/>
 
         <test name="org.apache.derby.PackagePrivateTestSuite"
@@ -2561,6 +2574,8 @@
            tempdir="junit_${derby.junit.timestamp}"
            errorproperty="tests.failed"
            failureproperty="tests.failed">
+      <jvmarg value="${derby.tests.jacoco.agent}"/>
+      <sysproperty key="derby.tests.jacoco.agent" value="${derby.tests.jacoco.agent}"/>
       <!-- This property is needed to keep EMMA silent when measuring codecoverage -->
       <sysproperty key="emma.verbosity.level" value="silent"/>
       <formatter type="xml"/>
@@ -2578,7 +2593,7 @@
    
   <target
       name="junit-all"
-      depends="junit-core,junit-jdbc4,junit-jmx,junit-lowmem"
+      depends="junit-pptesting,junit-core,junit-jdbc4,junit-jmx,junit-lowmem"
       description="Run the JUnit tests."
   />
  
@@ -2650,7 +2665,31 @@
 	        value="${derby.jar.base}/derbyTesting.jar:${derby.jar.base}/derbynet.jar:${derby.jar.base}/derbytools.jar:${derby.jar.base}/derbyclient.jar"/>
 	</target>
 	
-	
+<!-- =================================================================== -->
+<!--                        Old harness test targets                     -->
+<!-- =================================================================== -->
+<!-- The old harness tests are being phased out, so just borrow some     -->
+<!-- functionality from the JUnit setup.                                 -->
+
+  <target name="test-derbyall" depends="junit-init">
+    <path id="derbyall.classpath">
+      <fileset dir="${derby.junit.test.jars}" includes="*.jar"/>
+   	  <pathelement path="${derby.junit.classpath}"/>
+      <pathelement location="${javatools.dir}/junit.jar"/>
+      <pathelement location="${javatools.dir}/jakarta-oro-2.0.8.jar"/>
+    </path>
+    <echo message="Classpath used for derbyall: ${toString:derbyall.classpath}"/>
+    <mkdir dir="junit_${derby.junit.timestamp}/derbyall"/>
+    <java classname="org.apache.derbyTesting.functionTests.harness.RunSuite"
+        fork="yes" dir="junit_${derby.junit.timestamp}/derbyall">
+      <jvmarg value="${derby.tests.jacoco.agent}"/>
+      <sysproperty key="jvmflags" value="${derby.tests.jacoco.agent}"/>
+      <!-- Note the duplicate specification, don't know why it's needed. -->
+      <sysproperty key="testSpecialProps" value="noSecurityManager=true^noSecurityManager=true"/>
+      <arg value="derbyall"/>
+      <env key="CLASSPATH" value="${toString:derbyall.classpath}"/>
+    </java>
+  </target>
 
 <!-- =================================================================== -->
 <!--                         EMMA utility targets                        -->
@@ -2748,6 +2787,97 @@ you should not have to do this.
     </target>
 
 <!-- ==================================================================== -->
+<!--                   JaCoCo code coverage targets -->
+<!-- ==================================================================== -->
+
+    <target name="jacoco-complete"
+            depends="clobber,sane,all,buildjars,jacoco-enable,test-derbyall,junit-all,jacoco-report"
+            description="Runs all the Derby tests with JaCoCo to obtain code coverage">
+    </target>
+
+    <target name="jacoco-derbyall"
+            depends="jacoco-enable,test-derbyall,jacoco-report"
+            description="Runs the derbyall test with JaCoCo to obtain code coverage">
+    </target>
+
+    <target name="jacoco-junit"
+            depends="jacoco-enable,junit-all,jacoco-report"
+            description="Runs all the Derby JUnit tests with JaCoCo to obtain code coverage">
+    </target>
+
+    <target name="jacoco-junit-single"
+            depends="jacoco-enable,junit-single,jacoco-report"
+            description="Runs the specified Derby JUnit test with JaCoCo to obtain code coverage">
+    </target>
+
+<!-- The below JaCoCo targets are helper targets and have not been written to
+     be invoked directly. -->
+
+    <target name="jacoco-report" depends="getsvnversion">
+      <jacoco:merge destfile="junit_${derby.junit.timestamp}/merged.exec">
+        <fileset dir="junit_${derby.junit.timestamp}" includes="**/jacoco.exec*"/>
+      </jacoco:merge>
+
+      <jacoco:report>
+        <executiondata>
+          <file file="junit_${derby.junit.timestamp}/merged.exec"/>
+        </executiondata>
+
+        <structure name="Apache Derby Code Coverage (revision ${changenumber}, JRE ${java.specification.version})">
+          <classfiles>
+            <fileset dir="classes">
+              <include name="org/apache/derby/**/*.class"/>
+                <!-- Ignore testing classes for now.
+                     Maybe in a separate report? -->
+                <!-- <include name="org/apache/derbyTesting/**/*.class"/> -->
+            </fileset>
+          </classfiles>
+          <sourcefiles encoding="UTF-8">
+            <fileset dir="java/client"/>
+            <fileset dir="java/drda"/>
+            <fileset dir="java/engine"/>
+            <fileset dir="java/shared"/>
+            <fileset dir="java/testing"/>
+            <fileset dir="java/tools"/>
+            <fileset dir="generated/java"/>
+          </sourcefiles>
+        </structure>
+
+        <html destdir="junit_${derby.junit.timestamp}/coverage-report"/>
+        <!-- Alternative report formats that are available.
+        <csv destfile="junit_${derby.junit.timestamp}/coverage-jacoco.csv"/>
+        <html destfile="junit_${derby.junit.timestamp}/coverage-jacoco.html.zip"/>
+        <xml destfile="junit_${derby.junit.timestamp}/coverage-jacoco.xml"/>
+        -->
+
+      </jacoco:report>
+    </target>
+
+    <target name="jacoco-enable">
+      <!-- Make sure we have the required JaCoCo files. -->
+      <fail message="missing jacocoant.jar and/or jacocoagent.jar in tools/java">
+        <condition>
+          <not>
+            <and>
+              <available file="${basedir}/tools/java/jacocoant.jar"/>
+              <available file="${basedir}/tools/java/jacocoagent.jar"/>
+            </and>
+          </not>
+        </condition>
+      </fail>
+      <!-- Add the JaCoCo targets/tasks. -->
+      <taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
+        <classpath path="${basedir}/tools/java/jacocoant.jar"/> 
+      </taskdef>
+      <!-- Generate the property required to enable JaCoCo.
+           Exclude invalid class file loaded in DatabaseClassLoadingTest.
+      -->
+      <jacoco:agent property="derby.tests.jacoco.agent"
+        sessionid="derby-ant"
+        excludes="*/emc:org/apache/derby/exe/*"/>
+    </target>
+
+<!-- ==================================================================== -->
 <!--                         Release Candidates  -->
 <!-- ==================================================================== -->
 
@@ -2974,14 +3104,6 @@ you should not have to do this.
       <antcall target="updatesvnclients"/>
       <antcall target="getsvnversion"/>
 
-      <loadfile srcFile="${out.base}/changenumber.properties"
-               failonerror="false"
-               property="changenumber">
-        <filterchain>
-          <striplinebreaks/>
-        </filterchain>
-      </loadfile>    
-
       <property file="${properties.dir}/release.properties"/>
 
       <antcall target="prompttocontinue">

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java?rev=1352502&r1=1352501&r2=1352502&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java Thu Jun 21 11:45:44 2012
@@ -52,6 +52,8 @@ import java.util.ArrayList;
 public abstract class BaseTestCase
     extends TestCase {
 
+    private static final String JACOCO_AGENT_PROP = "derby.tests.jacoco.agent";
+
     protected final static String ERRORSTACKTRACEFILE = "error-stacktrace.out";
     protected final static String DEFAULT_DB_DIR      = "system";
     protected final static String DERBY_LOG           = "derby.log";
@@ -581,6 +583,14 @@ public abstract class BaseTestCase
             }
         }
 
+        if (runsWithJaCoCo()) {
+            // Property (http://www.eclemma.org/jacoco/trunk/doc/agent.html):
+            // -javaagent:[yourpath/]jacocoagent.jar=[opt1]=[val1],[opt2]=[val2]
+            String agent = getSystemProperty(JACOCO_AGENT_PROP);
+            cmdlist.add(agent + (agent.endsWith("=") ? "": ",") +
+                    "destfile=" + getJaCoCoOutFile());
+        }
+
 	    cmdlist.add("-classpath");
         cmdlist.add(cp == null ? getSystemProperty("java.class.path") : cp);
 
@@ -747,10 +757,31 @@ public abstract class BaseTestCase
         return getSystemProperty("java.class.path").indexOf("emma.jar") != -1;
     }
 
+    public static boolean runsWithJaCoCo() {
+        String agentProp = getSystemProperty(JACOCO_AGENT_PROP);
+        // Additional logic due to the use of a dummy property in build.xml
+        return agentProp != null && agentProp.startsWith("-javaagent");
+    }
+
     /**
-     * Counter used by {@link #getEmmaOutFile()} to produce unique file names.
+     * Counter used to produce unique file names based on process count.
+     *
+     * @see #getEmmaOutFile()
+     * @see #getJaCoCoOutFile()
      */
-    private static int emmaCount = 0;
+    private static int spawnedCount = 0;
+
+    /**
+     * Get a unique file object that can be used by sub-processes to store
+     * JaCoCo code coverage data. Each separate sub-process should have its
+     * own file in order to prevent corruption of the coverage data.
+     *
+     * @return a file to which a sub-process can write code coverage data
+     */
+    private static synchronized File getJaCoCoOutFile() {
+        return new File(currentDirectory(),
+                "jacoco.exec." + (++spawnedCount));
+    }
 
     /**
      * Get a unique file object that can be used by sub-processes to store
@@ -761,7 +792,7 @@ public abstract class BaseTestCase
      */
     private static synchronized File getEmmaOutFile() {
         return new File(currentDirectory(),
-                "coverage-" + (++emmaCount) + ".ec");
+                "coverage-" + (++spawnedCount) + ".ec");
     }
 
     /**