From f851b0fad57cd9459ff63132d68ce269a93cd116 Mon Sep 17 00:00:00 2001
From: boli <boli@localhost>
Date: Tue, 21 Nov 2006 17:18:11 +0000
Subject: [PATCH] Adds a tool to show svn diff output annotated with EMMA coverage information. To use the tool, just pipe the unified diff output from 'svn diff' to build-tools/bin/coveragediff.

---
 opends/build.xml                                                |    4 
 opends/build-tools/bin/coveragediff                             |   61 ++++++
 opends/build-tools/src/org/opends/build/tools/CoverageDiff.java |  439 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 504 insertions(+), 0 deletions(-)

diff --git a/opends/build-tools/bin/coveragediff b/opends/build-tools/bin/coveragediff
new file mode 100755
index 0000000..40a56c9
--- /dev/null
+++ b/opends/build-tools/bin/coveragediff
@@ -0,0 +1,61 @@
+#!/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License").  You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at
+# trunk/opends/resource/legal-notices/OpenDS.LICENSE
+# or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at
+# trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+# add the following below this CDDL HEADER, with the fields enclosed
+# by brackets "[]" replaced with your own identifying * information:
+#      Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+#      Portions Copyright 2006 Sun Microsystems, Inc.
+
+
+# Capture this script's directory
+ROOT_DIR=`dirname $0`/../../
+
+# See if JAVA_HOME is set.  If not, then see if there is a java executable in
+# the path and try to figure it out.
+if test -z "${JAVA_BIN}"
+then
+  if test -z "${JAVA_HOME}"
+  then
+    JAVA_BIN=`which java 2> /dev/null`
+    if test ${?} -eq 0
+    then
+      export JAVA_BIN
+    else
+      echo "Please set JAVA_HOME to the root of a Java 5.0 installation."
+      exit 1
+    fi
+  else
+    JAVA_BIN=${JAVA_HOME}/bin/java
+    export JAVA_BIN
+  fi
+fi
+
+CLASSPATH=${ROOT_DIR}/ext/build-tools.jar:${ROOT_DIR}/ext/emma/lib/emma.jar
+export CLASSPATH
+
+EMMADATAPATH=${ROOT_DIR}/build/coverage/gathereddata/
+
+cd `pwd`
+echo ${CLASSPATH}
+# Launch the setup process.
+"${JAVA_BIN}" ${JAVA_ARGS} org.opends.build.tools.CoverageDiff ${EMMADATAPATH}
+
diff --git a/opends/build-tools/src/org/opends/build/tools/CoverageDiff.java b/opends/build-tools/src/org/opends/build/tools/CoverageDiff.java
new file mode 100644
index 0000000..274e425
--- /dev/null
+++ b/opends/build-tools/src/org/opends/build/tools/CoverageDiff.java
@@ -0,0 +1,439 @@
+package org.opends.build.tools;
+
+import com.vladium.emma.*;
+import com.vladium.emma.report.*;
+import com.vladium.emma.data.*;
+import com.vladium.util.IntObjectMap;
+
+import java.io.*;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+public class CoverageDiff {
+
+
+  private static boolean verbose = false;
+
+  public static void main(String[] args) {
+
+    if(args.length < 1 || args[0] == null)
+    {
+      System.out.println("Please specify emma data location");
+      return;
+    }
+    IReportDataView emmaDataView = null;
+    try
+    {
+      emmaDataView = loadEmmaData(new File(args[0].trim()));
+
+    }
+    catch(IOException ie)
+    {
+      System.out.println("An error occured while loading EMMA data: " + ie.toString());
+    }
+
+    if(emmaDataView == null)
+    {
+      System.out.println(System.in);
+    }
+    else
+    {
+      try
+      {
+        processDiffOutput(new BufferedReader(new InputStreamReader(System.in)), emmaDataView);
+      }
+      catch(IOException ie)
+      {
+        System.out.println("An error occured while processing diff output: " + ie.toString());
+      }
+    }
+  }
+
+
+  private static IReportDataView loadEmmaData(File emmaCoverageDataDir) throws IOException {
+    File[] emmaCoverageDataFiles = emmaCoverageDataDir.listFiles();
+    int emmaCoverageDataFileCount = 0;
+    IReportDataView m_view = null;
+    IMetaData mdata = null;
+    ICoverageData cdata = null;
+
+    if(emmaCoverageDataFiles == null || emmaCoverageDataFiles.length <= 0)
+    {
+      throw new IOException("No EMMA data files found");
+    }
+
+    if (verbose) System.out.println("processing input files ...");
+
+    final long start = verbose ? System.currentTimeMillis() : 0;
+
+    // merge all data files:
+
+    for (int f = 0; f < emmaCoverageDataFiles.length; ++f) {
+      final File dataFile = emmaCoverageDataFiles[f];
+      if (verbose)
+        System.out.println("processing input file [" + dataFile.getAbsolutePath() + "] ...");
+
+      final IMergeable[] fileData = DataFactory.load(dataFile);
+
+      final IMetaData _mdata = (IMetaData) fileData[DataFactory.TYPE_METADATA];
+      if (_mdata != null) {
+        if (verbose)
+          System.out.println("  loaded " + _mdata.size() + " metadata entries");
+
+        if (mdata == null)
+          mdata = _mdata;
+        else
+          mdata = (IMetaData) mdata.merge(_mdata); // note: later datapath entries override earlier ones
+      }
+
+      final ICoverageData _cdata = (ICoverageData) fileData[DataFactory.TYPE_COVERAGEDATA];
+      if (_cdata != null) {
+        if (verbose)
+          System.out.println("  loaded " + _cdata.size() + " coverage data entries");
+
+        if (cdata == null)
+          cdata = _cdata;
+        else
+          cdata = (ICoverageData) cdata.merge(_cdata); // note: later datapath entries override earlier ones
+      }
+
+      ++emmaCoverageDataFileCount;
+    }
+
+    if (verbose) {
+      final long end = System.currentTimeMillis();
+
+      System.out.println(emmaCoverageDataFileCount + " file(s) read and merged in " + (end - start) + " ms");
+    }
+
+    if ((mdata == null) || mdata.isEmpty()) {
+      System.out.println("nothing to do: no metadata found in any of the data files");
+      return null;
+    }
+
+    if (cdata == null) {
+      System.out.println("nothing to do: no runtime coverage data found in any of the data files");
+      return null;
+    }
+
+    if (cdata.isEmpty()) {
+      System.out.println("no collected coverage data found in any of the data files [Diff output will not include coverage data]");
+      return null;
+    }
+    if (!mdata.hasLineNumberData() || !mdata.hasSrcFileData()) {
+      System.out.println("no collected line coverage data found in any of the data files [Diff output will not include coverage data]");
+      return null;
+    }
+
+    final IReportDataModel model = IReportDataModel.Factory.create (mdata, cdata);
+    m_view = model.getView (IReportDataView.HIER_SRC_VIEW);
+
+    if (verbose) {
+      if (mdata != null) {
+        System.out.println("  merged metadata contains " + mdata.size() + " entries");
+      }
+
+      if (cdata != null) {
+        System.out.println("  merged coverage data contains " + cdata.size() + " entries");
+      }
+    }
+
+    return m_view;
+  }
+
+  private static BufferedReader getDiffOutputReader() throws IOException {
+
+    Process child = Runtime.getRuntime().exec("svn diff");
+    InputStream diffOutputStream = child.getInputStream();
+    BufferedReader diffOutput = new BufferedReader(
+        new InputStreamReader(diffOutputStream));
+    return diffOutput;
+
+  }
+
+  private static void processDiffOutput(BufferedReader diffOutput,
+                                        IReportDataView emmaDataView)
+      throws IOException {
+
+    String line = diffOutput.readLine();
+    ArrayList<String> diffOutputFile = new ArrayList<String>();
+
+    while(line != null)
+    {
+      //Diffed file
+      if(line.length() >6 && line.substring(0, 6).equals("Index:"))
+      {
+        processDiffOutputFile(diffOutputFile, emmaDataView);
+        diffOutputFile = new ArrayList<String>();
+        diffOutputFile.add(line);
+      }
+      else
+      {
+        diffOutputFile.add(line);
+      }
+
+      line = diffOutput.readLine();
+    }
+    processDiffOutputFile(diffOutputFile, emmaDataView);
+  }
+
+  private static void processDiffOutputFile(ArrayList<String> diffFile,
+                                            IReportDataView emmaDataView)
+      throws IOException
+  {
+    if(diffFile.size() <= 0)
+    {
+      return;
+    }
+    
+    String fileHeader = diffFile.get(0);
+
+    File srcFilePath = new File(fileHeader.substring(7));
+    FileInputStream srcFile = new FileInputStream(srcFilePath);
+    String srcFilePackage = parseJavaPackage(srcFile);
+    SrcFileItem emmaSourceItem = getEmmaSrcItem(emmaDataView.getRoot(),
+                  srcFilePackage, srcFilePath.getName());
+
+    if(emmaSourceItem == null)
+    {
+      System.out.println(fileHeader);
+      System.out.println("Coverage: Not Available");
+      for(int i = 1; i < diffFile.size(); i++)
+      {
+        System.out.println(diffFile.get(i));
+      }
+    }
+    else
+    {
+      System.out.println(fileHeader);
+
+      System.out.print("Coverage: ");
+      String name;
+      StringBuffer buf = new StringBuffer();
+      for(int i = 1; i <= 4; i++)
+      {
+        buf.setLength(0);
+        emmaSourceItem.getAttribute(i, 0).format(emmaSourceItem, buf);
+        name = emmaSourceItem.getAttribute(i, 0).getName();
+        System.out.print(name);
+        for(int j = 0; j < buf.length() - name.length() + 1; j++)
+        {
+          System.out.print(" ");
+        }
+      }
+      System.out.print("\n          ");
+      for(int i = 1; i <= 4; i++)
+      {
+        buf.setLength(0);
+        emmaSourceItem.getAttribute(i, 0).format(emmaSourceItem, buf);
+        System.out.print(buf + " ");
+      }
+      System.out.println("");
+
+      System.out.println(diffFile.get(1));
+
+      //Figure out the flag for the working copy.
+      String workingCopyFlag = null;
+      String otherCopyFlag = null;
+
+      String firstFileLine = diffFile.get(2);
+      String secondFileLine = diffFile.get(3);
+      System.out.println(firstFileLine);
+      System.out.println(secondFileLine);
+
+      if(firstFileLine.endsWith("(working copy)"))
+      {
+        workingCopyFlag = firstFileLine.substring(0, 1);
+      }
+      else
+      {
+        otherCopyFlag = firstFileLine.substring(0, 1);
+      }
+
+      if(secondFileLine.endsWith("(working copy)"))
+      {
+        workingCopyFlag = secondFileLine.substring(0, 1);
+      }
+      else
+      {
+        otherCopyFlag = secondFileLine.substring(0, 1);
+      }
+
+      if(firstFileLine.endsWith("(revision 0)") &&
+          secondFileLine.endsWith("(revision 0)"))
+      {
+        workingCopyFlag = "+";
+        otherCopyFlag = "-";
+      }
+
+      if(workingCopyFlag == null || otherCopyFlag == null ||
+          srcFilePackage == null)
+      {
+        for(int i = 4; i < diffFile.size(); i++)
+        {
+          System.out.println(diffFile.get(i));
+        }
+      }
+      else
+      {
+
+        ArrayList<String> diffOutputChunk = new ArrayList<String>();
+
+        for(int i = 4; i < diffFile.size(); i++)
+        {
+          //Found a chunk indicator.
+          if(diffFile.get(i).startsWith("@@"))
+          {
+            processDiffOutputFileChunk(diffOutputChunk, workingCopyFlag,
+                otherCopyFlag, emmaSourceItem);
+            diffOutputChunk = new ArrayList<String>();
+            diffOutputChunk.add(diffFile.get(i));
+          }
+          //Not any of the above so this line must be diffed text
+          else
+          {
+            diffOutputChunk.add(diffFile.get(i));
+          }
+        }
+
+        //Finishing process whatever we have queued up
+        processDiffOutputFileChunk(diffOutputChunk, workingCopyFlag,
+            otherCopyFlag, emmaSourceItem);
+      }
+    }
+
+  }
+
+  private static void processDiffOutputFileChunk(ArrayList<String> diffChunk,
+                                                 String workingCopyFlag,
+                                                 String otherCopyFlag,
+                                                 SrcFileItem emmaSrcItem)
+  {
+
+    if(diffChunk.size() <= 0)
+    {
+      return;
+    }
+
+    int workingCopyBegin;
+    int workingCopyRange;
+    int otherCopyBegin;
+    int otherCopyRange;
+
+    IntObjectMap lineCoverageMap = null;
+    if(emmaSrcItem != null)
+    {
+      lineCoverageMap = emmaSrcItem.getLineCoverage ();
+    }
+
+    String chunkHeader = diffChunk.get(0);
+    System.out.println(chunkHeader);
+
+    int workingCopyBeginIdx = chunkHeader.indexOf(workingCopyFlag);
+    int workingCopyCommaIdx = chunkHeader.indexOf(",", workingCopyBeginIdx);
+    int workingCopyEndIdx = chunkHeader.indexOf(" ", workingCopyCommaIdx);
+    int otherCopyBeginIdx = chunkHeader.indexOf(otherCopyFlag);
+    int otherCopyCommaIdx = chunkHeader.indexOf(",", otherCopyBeginIdx);
+    int otherCopyEndIdx = chunkHeader.indexOf(" ", otherCopyCommaIdx);
+    workingCopyBegin = Integer.parseInt(
+        chunkHeader.substring(workingCopyBeginIdx + 1, workingCopyCommaIdx));
+    workingCopyRange = Integer.parseInt(
+        chunkHeader.substring(workingCopyCommaIdx + 1, workingCopyEndIdx));
+    otherCopyBegin = Integer.parseInt(
+        chunkHeader.substring(otherCopyBeginIdx + 1, otherCopyCommaIdx));
+    otherCopyRange = Integer.parseInt(
+        chunkHeader.substring(otherCopyCommaIdx + 1, otherCopyEndIdx));
+
+    String chunkLine;
+    SrcFileItem.LineCoverageData lCoverageData = null;
+    int workingCopyLineIncrement = 0;
+    int otherCopyLineIncrement = 0;
+    for(int i = 1; i < diffChunk.size(); i++)
+    {
+      chunkLine = diffChunk.get(i);
+      //System.out.print(workingCopyBegin + workingCopyLineIncrement + " ");
+      if(lineCoverageMap != null)
+      {
+        lCoverageData = (SrcFileItem.LineCoverageData) lineCoverageMap.get (workingCopyBegin + workingCopyLineIncrement);
+      }
+
+      if(!chunkLine.startsWith(otherCopyFlag) && lCoverageData != null)
+      {
+
+        switch(lCoverageData.m_coverageStatus)
+        {
+          case SrcFileItem.LineCoverageData.LINE_COVERAGE_ZERO:
+            System.out.println(chunkLine.charAt(0) + "N" + chunkLine.substring(1));
+            break;
+          case SrcFileItem.LineCoverageData.LINE_COVERAGE_PARTIAL:
+            System.out.println(chunkLine.charAt(0) + "P" + chunkLine.substring(1));
+            break;
+          case SrcFileItem.LineCoverageData.LINE_COVERAGE_COMPLETE:
+            System.out.println(chunkLine.charAt(0) + "C" + chunkLine.substring(1));
+            break;
+          default:
+            System.out.println(chunkLine.charAt(0) + "U" + chunkLine.substring(1));
+        }
+      }
+      else
+      {
+        System.out.println(chunkLine.charAt(0) + " " + chunkLine.substring(1));
+      }
+
+      if(!chunkLine.startsWith(otherCopyFlag))
+      {
+        workingCopyLineIncrement++;
+      }
+      if(!chunkLine.startsWith(workingCopyFlag))
+      {
+        otherCopyLineIncrement++;
+      }
+    }
+  }
+
+  private static String parseJavaPackage(FileInputStream srcFile)
+      throws IOException {
+
+    BufferedReader srcFileReader = new BufferedReader(
+        new InputStreamReader(srcFile));
+
+    String line = srcFileReader.readLine();
+    while(line != null)
+    {
+      int beginIdx = line.indexOf("package");
+      if(beginIdx > -1)
+      {
+        int endIdx = line.indexOf(";", beginIdx);
+        if(endIdx > -1)
+        {
+          return  line.substring(beginIdx + 7, endIdx).trim();
+        }
+      }
+      line = srcFileReader.readLine();
+    }
+
+    return null;
+  }
+
+  private static SrcFileItem getEmmaSrcItem(IItem rootItem,
+                                      String srcPackageName,
+                                      String srcFileName)
+  {
+    for(Iterator packages = rootItem.getChildren(); packages.hasNext();)
+    {
+      IItem packageItem = (IItem)packages.next();
+      if(packageItem.getName().equals(srcPackageName))
+      {
+        for(Iterator sources = packageItem.getChildren(); sources.hasNext();)
+        {
+          SrcFileItem sourceItem = (SrcFileItem)sources.next();
+          if(sourceItem.getName().equals(srcFileName))
+          {
+            return sourceItem;
+          }
+        }
+      }
+    }
+    return null;
+  }
+}
diff --git a/opends/build.xml b/opends/build.xml
index a51f497..1ddf08d 100644
--- a/opends/build.xml
+++ b/opends/build.xml
@@ -854,6 +854,10 @@
         <fileset dir="${ant.lib.dir}">
           <include name="*.jar" />
         </fileset>
+
+        <fileset dir="${emma.dir}">
+          <include name="*.jar" />
+        </fileset>
         <path refid="run.classpath" />
       </classpath>
     </javac>

--
Gitblit v1.10.0