Added emma code coverage generation to the build file.  ant emma test emma.merge will generate emma reports for each test, then merge them.  This is a resubmit of r5781 after verifying all remoteweb tests pass.

Patch by: jlabanca
Review by: fabbott



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5798 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/build.xml b/build.xml
index 8fbc6c5..858db11 100755
--- a/build.xml
+++ b/build.xml
@@ -5,6 +5,7 @@
 
   <!-- "build" is the default when subprojects are directly targetted  -->
   <property name="target" value="build" />
+  <property name="emma.merged.out" value="${project.build}/emma-coverage" />
 
   <!-- 
      Convenience for the lateral calls we make.  Use gwt.ant to
@@ -127,6 +128,39 @@
     <call-subproject subproject="tools" subtarget="test" />
   </target>
 
+  <path id="emma.classpath.src">
+    <pathelement location="${gwt.root}/user/src" />
+    <pathelement location="${gwt.root}/dev/**/src/com/google" />
+    <pathelement location="${gwt.root}/build-tools/**/src/com/google" />
+    <pathelement location="${gwt.root}/tools/**/src/com/google" />
+  </path>
+
+  <target name="emma.merge" description="Merges coverage data for all projects" if="emma.enabled">
+    <delete dir="${emma.merged.out}" />
+    <mkdir dir="${emma.merged.out}" />
+    <emma>
+      <merge outfile="${emma.merged.out}/merged.emma" >
+        <fileset dir="${project.build}" >
+          <include name="**/*.emma" />
+          <exclude name="**/merged.emma" />
+        </fileset>
+      </merge>
+    </emma>
+    <emma enabled="${emma.enabled}">
+      <report sourcepath="${emma.classpath.src}">
+        <fileset dir="${project.build}">
+          <patternset>
+            <include name="**/metadata.emma"/>
+          </patternset>
+        </fileset>
+        <fileset file="${emma.merged.out}/merged.emma" />
+        <txt outfile="${emma.merged.out}/coverage.txt" />
+        <html outfile="${emma.merged.out}/coverage.html" />
+        <xml outfile="${emma.merged.out}/coverage.xml" />
+      </report>
+    </emma>
+  </target>
+
   <target name="clean" description="[action] Cleans the entire GWT build">
     <delete dir="${gwt.build}" />
   </target>
diff --git a/common.ant.xml b/common.ant.xml
index 37cfcce..41bac4d 100755
--- a/common.ant.xml
+++ b/common.ant.xml
@@ -49,6 +49,7 @@
   <property name="project.jni" location="${gwt.build}/${project.tail}" />
   <property name="javac.out" location="${project.build}/bin" />
   <property name="javac.junit.out" location="${project.build}/bin-test" />
+  <property name="javac.emma.out" location="${project.build}/bin-emma" />
   <property name="javac.debug" value="true" />
   <property name="javac.debuglevel" value="lines,vars,source" />
   <property name="javac.encoding" value="utf-8" />
@@ -56,6 +57,8 @@
   <property name="javac.target" value="1.5" />
   <property name="javac.nowarn" value="true" />
   <property name="junit.out" location="${project.build}/test" />
+  <property name="emma.dir" value="${gwt.tools.redist}/emma" />
+  <property name="emma.filter.exclude" value="" />
   
   <!-- Sanity check -->
   <available file="${gwt.tools}" type="dir" property="gwt.tools.exists" />
@@ -119,6 +122,14 @@
     </not>
   </condition>
 
+  <!-- Shared class paths -->
+  <path id="project.classpath.class">
+    <pathelement location="${javac.out}" />
+  </path>
+  <path id="project.classpath.src">
+    <pathelement location="${gwt.root}/${project.tail}/src" />
+  </path>
+
   <!-- Pulls in tasks defined in ant-contrib, i.e. foreach -->
   <taskdef resource="net/sf/antcontrib/antlib.xml">
     <classpath>
@@ -133,6 +144,7 @@
         <propertyref name="gwt.version" />
         <propertyref name="gwt.junit.port" />
         <propertyref name="gwt.remote.browsers" />
+        <propertyref name="emma.enabled" />
       </propertyset>
     </ant>
   </presetdef>
@@ -163,6 +175,7 @@
     <attribute name="test.args" default="" />
     <attribute name="test.out" default="" />
     <attribute name="test.reports" default="@{test.out}/reports" />
+    <attribute name="test.emma.coverage" default="@{test.out}/emma-coverage" />
     <attribute name="test.cases" default="" />
     <element name="extraclasspaths" optional="true" />
     <sequential>
@@ -177,20 +190,28 @@
       <echo message="Writing test results to @{test.reports} for @{test.cases}" />
       <mkdir dir="@{test.reports}" />
 
+      <antcall target="-create.emma.coverage">
+    	  <param name="test.emma.coverage" value="@{test.emma.coverage}"/>
+      </antcall>
+
       <echo message="${javac.out} ${javac.junit.out}" />
       <junit dir="@{test.out}" fork="yes" printsummary="yes"
              failureproperty="junit.failure" tempdir="@{test.out}" >
         <jvmarg line="${junit.platform.args}" />
         <jvmarg line="-Xmx768m" />
+        <jvmarg value="-Demma.coverage.out.file=@{test.emma.coverage}/coverage.emma" />
+        <jvmarg value="-Demma.coverage.out.merge=true" />
         <sysproperty key="gwt.args" value="${junit.notheadless.arg} @{test.args}" />
         <sysproperty key="java.awt.headless" value="${junit.headless}" />
         <sysproperty key="gwt.devjar" value="${gwt.dev.staging.jar}" />
         <classpath>
-          <pathelement location="${gwt.root}/${project.tail}/src" />
+          <path refid="project.classpath.src" />
           <pathelement location="${gwt.root}/${project.tail}/super" />
           <pathelement location="${gwt.root}/${project.tail}/test" />
           <pathelement location="${javac.junit.out}" />
-          <pathelement location="${javac.out}" />
+          <pathelement location="${javac.emma.out}" />
+          <path refid="project.classpath.class" />
+          <path refid="emma.lib" />
           <pathelement location="${gwt.dev.staging.jar}" />
           <pathelement location="${gwt.tools.lib}/junit/junit-3.8.1.jar" />
           <pathelement location="${gwt.tools.lib}/selenium/selenium-java-client-driver.jar" />
@@ -206,6 +227,19 @@
           <fileset refid="@{test.cases}" />
         </batchtest>
       </junit>
+
+      <emma enabled="${emma.enabled}">
+        <report sourcepath="${project.classpath.src}">
+          <fileset file="${javac.emma.out}/metadata.emma" />
+          <fileset dir="@{test.emma.coverage}">
+            <include name="*.emma" />
+          </fileset>
+          <txt outfile="@{test.emma.coverage}/coverage.txt" />
+          <html outfile="@{test.emma.coverage}/coverage.html" />
+          <xml outfile="@{test.emma.coverage}/coverage.xml" />
+        </report>
+      </emma>
+
       <fail message="One or more junit tests failed" if="junit.failure" />
     </sequential>
   </macrodef>
@@ -303,6 +337,43 @@
     </sequential>
   </macrodef>
 
+  <!-- Targets for emma support.  To run tests with emma enabled, use 
+       ant emma <test-target>. -->
+  <path id="emma.lib">
+    <pathelement location="${emma.dir}/emma-2.0.5312-patched.jar" />
+    <pathelement location="${emma.dir}/emma_ant-2.0.5312.jar" />
+  </path>
+
+  <taskdef resource="emma_ant.properties" classpathref="emma.lib" />
+
+  <target name="emma" description="Enables on EMMA instrumentation/reporting" >
+    <property name="emma.enabled" value="true" />
+  </target>
+
+  <target name="compile.emma" description="Instruments emma classes" unless="emma.compiled">
+    <delete dir="${javac.emma.out}" />
+    <property name="emma.compiled" value="true" />
+    <antcall target="-compile.emma.if.enabled" />
+  </target>
+
+  <target name="-compile.emma.if.enabled" description="Instruments emma classes" if="emma.enabled">
+    <mkdir dir="${javac.emma.out}" />
+    <path id="emma.classpath">
+      <pathelement location="${javac.out}" />
+    </path>
+    <emma enabled="${emma.enabled}" >
+      <instr instrpathref="emma.classpath" destdir="${javac.emma.out}" metadatafile="${javac.emma.out}/metadata.emma" merge="false">
+        <filter includes="com.google.*" />
+        <filter excludes="${emma.filter.exclude}" />
+      </instr>
+    </emma>
+  </target>
+
+  <target name="-create.emma.coverage" description="Create the emma coverage directory" if="emma.enabled">
+    <delete dir="${test.emma.coverage}" />
+    <mkdir dir="${test.emma.coverage}" />
+  </target>
+	
   <!-- Default implementations of the required targets; projects should
   override the ones that matter -->
   <target name="all" depends="verify" />
diff --git a/dev/core/build.xml b/dev/core/build.xml
index e868ed4..11ee628 100755
--- a/dev/core/build.xml
+++ b/dev/core/build.xml
@@ -9,7 +9,7 @@
     <include name="**/com/google/**/*Test.class" />
   </fileset>
 
-  <target name="compile.tests" depends="build" description="Compiles the test code for this project">
+  <target name="compile.tests" depends="build, compile.emma" description="Compiles the test code for this project">
     <mkdir dir="${javac.junit.out}" />
     <gwt.javac srcdir="test" destdir="${javac.junit.out}">
       <classpath>
@@ -166,38 +166,14 @@
   </target>
 
   <target name="test" depends="build, compile.tests" description="Run unit tests for this project.">
-    <!-- TODO: refactor gwt.junit so it can be reused here -->
-    <taskdef name="junit" classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask">
-      <classpath>
-        <pathelement location="${gwt.tools.lib}/junit/junit-3.8.1.jar" />
-        <pathelement location="${gwt.tools.antlib}/ant-junit-1.6.5.jar" />
-      </classpath>
-    </taskdef>
-  
-    <echo message="Writing test results to ${junit.out}/reports for ${test.cases}" />
-    <mkdir dir="${junit.out}/reports" />
-  
-    <echo message="${javac.out} ${javac.junit.out}" />
-    <junit dir="${junit.out}" fork="yes" printsummary="yes" haltonfailure="true">
-      <classpath>
-        <pathelement location="test" />
-        <pathelement location="${javac.junit.out}" />
-        <pathelement location="${javac.out}" />
+    <gwt.junit test.out="${junit.out}" test.cases="default.tests" >
+      <extraclasspaths>
         <pathelement location="${alldeps.jar}" />
-        <pathelement location="${gwt.tools.lib}/junit/junit-3.8.1.jar" />
         <!-- Pull in gwt-dev and gwt-user sources for .gwt.xml files -->
         <pathelement location="${gwt.root}/user/src/" />
         <pathelement location="${gwt.root}/user/super/" />
-        <pathelement location="${gwt.root}/dev/core/super" />
-      </classpath>
-  
-      <formatter type="plain" />
-      <formatter type="xml" />
-  
-      <batchtest todir="${junit.out}/reports">
-        <fileset refid="default.tests" />
-      </batchtest>
-    </junit>
+      </extraclasspaths>
+    </gwt.junit>
   </target>
 
   <target name="clean" description="Cleans this project's intermediate and output files">
diff --git a/tools/api-checker/build.xml b/tools/api-checker/build.xml
index 5ee734f..da23606 100755
--- a/tools/api-checker/build.xml
+++ b/tools/api-checker/build.xml
@@ -10,6 +10,10 @@
   <property.ensure name="gwt.dev.jar" location="${gwt.build.lib}/gwt-dev-${build.host.platform}.jar" />
   <property.ensure name="gwt.user.jar" location="${gwt.build.lib}/gwt-user.jar" />
 
+  <fileset id="default.tests" dir="${javac.junit.out}">
+    <include name="**/*Test.class" />
+  </fileset>
+
   <target name="compile" description="Compile all class files">
     <mkdir dir="${javac.out}" />
     <gwt.javac>
@@ -20,7 +24,7 @@
     </gwt.javac>
   </target>
 
-  <target name="compile.tests" description="Compiles the test code for this project">
+  <target name="compile.tests" depends="compile.emma" description="Compiles the test code for this project">
     <mkdir dir="${javac.junit.out}" />
     <gwt.javac srcdir="test" destdir="${javac.junit.out}">
       <classpath>
@@ -42,33 +46,12 @@
   </target>
 
   <target name="test" depends="build, compile.tests" description="Run unit tests for this project.">
-    <taskdef name="junit" classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask">
-      <classpath>
-        <pathelement location="${gwt.tools.lib}/junit/junit-3.8.1.jar" />
-        <pathelement location="${gwt.tools.antlib}/ant-junit-1.6.5.jar" />
-      </classpath>
-    </taskdef>
-  
-    <echo message="Writing test results to ${junit.out}/reports" />
-    <mkdir dir="${junit.out}/reports" />
-  
-    <junit dir="${junit.out}" fork="yes" printsummary="yes" haltonfailure="true">
-      <sysproperty key="gwt.devjar" value="${gwt.dev.staging.jar}" />
-      <classpath>
-        <pathelement location="test" />
-        <pathelement location="${javac.junit.out}" />
+    <gwt.junit test.out="${junit.out}" test.cases="default.tests" >
+      <extraclasspaths>
         <pathelement location="${gwt.build.out}/tools/api-checker/bin"/>
         <pathelement location="${gwt.dev.jar}" />
-        <pathelement location="${gwt.tools.lib}/junit/junit-3.8.1.jar" />
-      </classpath>
-  
-      <formatter type="plain" />
-      <formatter type="xml" />
-      <batchtest todir="${junit.out}/reports">
-                          <fileset dir="${javac.junit.out}"
-                            includes="**/*Test.class"/> 
-      </batchtest>
-    </junit>
+      </extraclasspaths>
+    </gwt.junit>
   </target>
 
   <target name="checkstyle" description="Static analysis of source">
diff --git a/user/build.xml b/user/build.xml
index 7c68dbd..7cc0064 100755
--- a/user/build.xml
+++ b/user/build.xml
@@ -3,10 +3,14 @@
   <property name="project.tail" value="user" />
   <property name="test.args" value="" />
 
+  <!-- BrowserManagerServer_Stub compiled using rmic, which doesn't generate full source code -->
+  <property name="emma.filter.exclude" value="*BrowserManagerServer_Stub*" />
+
   <import file="${gwt.root}/common.ant.xml" />
 
   <property name="gwt.junit.emmatestcase.includes" value="**/*Suite.class,com/google/gwt/dev/jjs/test/*Test.class"/>
   <property name="test.timeout" value="3" />
+  <property name="emma.merged.out" value="${junit.out}/emma-coverage" />
 
   <!-- 
     Whether I18NSuite should test e.g. Foo$InnerMsgs_fr.properties (if the
@@ -75,7 +79,7 @@
     <gwt.ant dir="../dev/core" target="compile.tests" />
   </target>
 
-  <target name="compile.tests" depends="compile.dev.core.tests" description="Compiles the test code for this project">
+  <target name="compile.tests" depends="compile.dev.core.tests, compile.emma" description="Compiles the test code for this project">
     <mkdir dir="${javac.junit.out}" />
     <gwt.javac srcdir="test" excludes="com/google/gwt/langtest/**" destdir="${javac.junit.out}">
       <classpath>
@@ -186,6 +190,7 @@
 
   <target name="test" depends="compile, compile.tests" description="Run hosted-mode, web-mode, remoteweb, and selenium tests for this project.">
     <property.ensure name="distro.built" location="${gwt.dev.staging.jar}" message="GWT must be built before performing any tests.  This can be fixed by running ant in the ${gwt.root} directory." />
+    <property name="emma.compiled" value="true" />
 
     <!--
       Run hosted and web mode tests for the platform on which this build
@@ -207,6 +212,28 @@
     </limit>
   </target>
 
+  <target name="emma.merge" description="Merges coverage data for the entire project" if="emma.enabled">
+    <delete dir="${emma.merged.out}" />
+    <mkdir dir="${emma.merged.out}" />
+    <emma>
+      <merge outfile="${emma.merged.out}/merged.emma" >
+        <fileset dir="${junit.out}" >
+          <include name="**/*.emma" />
+          <exclude name="${emma.merged.out}/merged.emma" />
+        </fileset>
+      </merge>
+    </emma>
+    <emma enabled="${emma.enabled}">
+      <report sourcepath="${project.classpath.src}">
+        <fileset file="${javac.emma.out}/metadata.emma" />
+        <fileset file="${emma.merged.out}/merged.emma" />
+        <txt outfile="${emma.merged.out}/coverage.txt" />
+        <html outfile="${emma.merged.out}/coverage.html" />
+        <xml outfile="${emma.merged.out}/coverage.xml" />
+      </report>
+    </emma>
+  </target>
+
   <target name="clean" description="Cleans this project's intermediate and output files">
     <delete dir="${project.build}" />
     <delete file="${project.lib}" />