summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2014-06-05 14:55:29 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2014-06-05 14:55:29 (GMT)
commit994f4b71fcc5f4487862bd610eab7114a616d643 (patch)
tree9279d53e05aa47df526433f0d15d845fb9ebb50a
parent5d360f23fa5616004ffa813914336e5810d1f42b (diff)
parent50daf239b001ddda61449044e75bb98651e99d21 (diff)
downloadCMake-994f4b71fcc5f4487862bd610eab7114a616d643.zip
CMake-994f4b71fcc5f4487862bd610eab7114a616d643.tar.gz
CMake-994f4b71fcc5f4487862bd610eab7114a616d643.tar.bz2
Merge topic 'expand_cobertura_coverage'
50daf239 CTest: Generalize Cobertura coverage format handling a2822d30 CTest: Rename coverage implementation for "Python" to "Cobertura"
-rw-r--r--Help/variable/CTEST_COVERAGE_COMMAND.rst55
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx12
-rw-r--r--Source/CTest/cmCTestCoverageHandler.h2
-rw-r--r--Source/CTest/cmParseCoberturaCoverage.cxx (renamed from Source/CTest/cmParsePythonCoverage.cxx)77
-rw-r--r--Source/CTest/cmParseCoberturaCoverage.h (renamed from Source/CTest/cmParsePythonCoverage.h)11
-rw-r--r--Tests/CMakeLists.txt18
-rw-r--r--Tests/CoberturaCoverage/DartConfiguration.tcl.in8
-rw-r--r--Tests/CoberturaCoverage/coverage.xml.in112
-rw-r--r--Tests/CoberturaCoverage/src/main/java/org/cmake/CoverageTest.java52
10 files changed, 323 insertions, 26 deletions
diff --git a/Help/variable/CTEST_COVERAGE_COMMAND.rst b/Help/variable/CTEST_COVERAGE_COMMAND.rst
index 1a8e499..a669dd7 100644
--- a/Help/variable/CTEST_COVERAGE_COMMAND.rst
+++ b/Help/variable/CTEST_COVERAGE_COMMAND.rst
@@ -3,3 +3,58 @@ CTEST_COVERAGE_COMMAND
Specify the CTest ``CoverageCommand`` setting
in a :manual:`ctest(1)` dashboard client script.
+
+Cobertura
+'''''''''
+
+Using `Cobertura`_ as the coverage generation within your multi-module
+Java project can generate a series of XML files.
+
+The Cobertura Coverage parser expects to read the coverage data from a
+single XML file which contains the coverage data for all modules.
+Cobertura has a program with the ability to merge given cobertura.ser files
+and then another program to generate a combined XML file from the previous
+merged file. For command line testing, this can be done by hand prior to
+CTest looking for the coverage files. For script builds,
+set the ``CTEST_COVERAGE_COMMAND`` variable to point to a file which will
+perform these same steps, such as a .sh or .bat file.
+
+.. code-block:: cmake
+
+ set(CTEST_COVERAGE_COMMAND .../run-coverage-and-consolidate.sh)
+
+where the ``run-coverage-and-consolidate.sh`` script is perhaps created by
+the :command:`configure_file` command and might contain the following code:
+
+.. code-block:: bash
+
+ #!/usr/bin/env bash
+ CoberturaFiles="$(find "/path/to/source" -name "cobertura.ser")"
+ SourceDirs="$(find "/path/to/source" -name "java" -type d)"
+ cobertura-merge --datafile coberturamerge.ser $CoberturaFiles
+ cobertura-report --datafile coberturamerge.ser --destination . \
+ --format xml $SourceDirs
+
+The script uses ``find`` to capture the paths to all of the cobertura.ser files
+found below the project's source directory. It keeps the list of files and
+supplies it as an argument to the ``cobertura-merge`` program. The ``--datafile``
+argument signifies where the result of the merge will be kept.
+
+The combined ``coberturamerge.ser`` file is then used to generate the XML report
+using the ``cobertura-report`` program. The call to the cobertura-report program
+requires some named arguments.
+
+``--datafila``
+ path to the merged .ser file
+
+``--destination``
+ path to put the output files(s)
+
+``--format``
+ file format to write output in: xml or html
+
+The rest of the supplied arguments consist of the full paths to the
+/src/main/java directories of each module within the souce tree. These
+directories are needed and should not be forgotten.
+
+.. _`Cobertura`: http://cobertura.github.io/cobertura/
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 8ecf83c..fe6cc1b 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -519,7 +519,7 @@ set(CTEST_SRCS cmCTest.cxx
CTest/cmParseCacheCoverage.cxx
CTest/cmParseGTMCoverage.cxx
CTest/cmParsePHPCoverage.cxx
- CTest/cmParsePythonCoverage.cxx
+ CTest/cmParseCoberturaCoverage.cxx
CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
CTest/cmCTestGenericHandler.cxx
CTest/cmCTestHandlerCommand.cxx
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index cb6e56e..da27c8c 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -11,7 +11,7 @@
============================================================================*/
#include "cmCTestCoverageHandler.h"
#include "cmParsePHPCoverage.h"
-#include "cmParsePythonCoverage.h"
+#include "cmParseCoberturaCoverage.h"
#include "cmParseGTMCoverage.h"
#include "cmParseCacheCoverage.h"
#include "cmCTest.h"
@@ -401,7 +401,7 @@ int cmCTestCoverageHandler::ProcessHandler()
{
return error;
}
- file_count += this->HandlePythonCoverage(&cont);
+ file_count += this->HandleCoberturaCoverage(&cont);
error = cont.Error;
if ( file_count < 0 )
{
@@ -779,10 +779,10 @@ int cmCTestCoverageHandler::HandlePHPCoverage(
}
//----------------------------------------------------------------------
-int cmCTestCoverageHandler::HandlePythonCoverage(
+int cmCTestCoverageHandler::HandleCoberturaCoverage(
cmCTestCoverageHandlerContainer* cont)
{
- cmParsePythonCoverage cov(*cont, this->CTest);
+ cmParseCoberturaCoverage cov(*cont, this->CTest);
// Assume the coverage.xml is in the source directory
std::string coverageXMLFile = this->CTest->GetBinaryDir() + "/coverage.xml";
@@ -790,14 +790,14 @@ int cmCTestCoverageHandler::HandlePythonCoverage(
if(cmSystemTools::FileExists(coverageXMLFile.c_str()))
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Parsing coverage.py XML file: " << coverageXMLFile
+ "Parsing Cobertura XML file: " << coverageXMLFile
<< std::endl);
cov.ReadCoverageXML(coverageXMLFile.c_str());
}
else
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Cannot find coverage.py XML file: " << coverageXMLFile
+ "Cannot find Cobertura XML file: " << coverageXMLFile
<< std::endl);
}
return static_cast<int>(cont->TotalCoverage.size());
diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h
index 0a0fe81..38a3353 100644
--- a/Source/CTest/cmCTestCoverageHandler.h
+++ b/Source/CTest/cmCTestCoverageHandler.h
@@ -76,7 +76,7 @@ private:
int HandlePHPCoverage(cmCTestCoverageHandlerContainer* cont);
//! Handle coverage for Python with coverage.py
- int HandlePythonCoverage(cmCTestCoverageHandlerContainer* cont);
+ int HandleCoberturaCoverage(cmCTestCoverageHandlerContainer* cont);
//! Handle coverage for mumps
int HandleMumpsCoverage(cmCTestCoverageHandlerContainer* cont);
diff --git a/Source/CTest/cmParsePythonCoverage.cxx b/Source/CTest/cmParseCoberturaCoverage.cxx
index 817b8dc..6b98056 100644
--- a/Source/CTest/cmParsePythonCoverage.cxx
+++ b/Source/CTest/cmParseCoberturaCoverage.cxx
@@ -1,17 +1,21 @@
#include "cmStandardIncludes.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
-#include "cmParsePythonCoverage.h"
+#include "cmParseCoberturaCoverage.h"
#include <cmsys/Directory.hxx>
#include <cmsys/FStream.hxx>
//----------------------------------------------------------------------------
-class cmParsePythonCoverage::XMLParser: public cmXMLParser
+class cmParseCoberturaCoverage::XMLParser: public cmXMLParser
{
public:
XMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont)
: CTest(ctest), Coverage(cont)
{
+ this->InSources = false;
+ this->InSource = false;
+ this->FilePaths.push_back(this->Coverage.SourceDir);
+ this->CurFileName = "";
}
virtual ~XMLParser()
@@ -20,9 +24,44 @@ public:
protected:
+
+ virtual void EndElement(const std::string& name)
+ {
+ if(name == "source")
+ {
+ this->InSource=false;
+ }
+ else if (name == "sources")
+ {
+ this->InSources=false;
+ }
+ }
+
+ virtual void CharacterDataHandler(const char* data, int length)
+ {
+ std::string tmp;
+ tmp.insert(0,data,length);
+ if (this->InSources && this->InSource)
+ {
+ this->FilePaths.push_back(tmp);
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Adding Source: "
+ << tmp << std::endl);
+ }
+ }
+
virtual void StartElement(const std::string& name, const char** atts)
{
- if(name == "class")
+ std::string FoundSource;
+ std::string finalpath = "";
+ if(name == "source")
+ {
+ this->InSource = true;
+ }
+ else if(name == "sources")
+ {
+ this->InSources = true;
+ }
+ else if(name == "class")
{
int tagCount = 0;
while(true)
@@ -30,11 +69,19 @@ protected:
if(strcmp(atts[tagCount], "filename") == 0)
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Reading file: "
- << atts[tagCount+1] << std::endl);
- this->CurFileName = this->Coverage.SourceDir + "/" +
- atts[tagCount+1];
+ << atts[tagCount+1]<< std::endl);
+ std::string filename = atts[tagCount+1];
+ for(size_t i=0;i < FilePaths.size();i++)
+ {
+ finalpath = FilePaths[i] + "/" + filename;
+ if(cmSystemTools::FileExists(finalpath.c_str()))
+ {
+ this->CurFileName = finalpath;
+ break;
+ }
+ }
cmsys::ifstream fin(this->CurFileName.c_str());
- if(!fin)
+ if(this->CurFileName == "" || !fin )
{
this->CurFileName = this->Coverage.BinaryDir + "/" +
atts[tagCount+1];
@@ -48,7 +95,6 @@ protected:
break;
}
}
-
std::string line;
FileLinesType& curFileLines =
this->Coverage.TotalCoverage[this->CurFileName];
@@ -83,7 +129,9 @@ protected:
{
FileLinesType& curFileLines =
this->Coverage.TotalCoverage[this->CurFileName];
- curFileLines[curNumber-1] = curHits;
+ {
+ curFileLines[curNumber-1] = curHits;
+ }
break;
}
++tagCount;
@@ -91,10 +139,11 @@ protected:
}
}
- virtual void EndElement(const std::string&) {}
-
private:
+ bool InSources;
+ bool InSource;
+ std::vector<std::string> FilePaths;
typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector
FileLinesType;
cmCTest* CTest;
@@ -104,16 +153,16 @@ private:
};
-cmParsePythonCoverage::cmParsePythonCoverage(
+cmParseCoberturaCoverage::cmParseCoberturaCoverage(
cmCTestCoverageHandlerContainer& cont,
cmCTest* ctest)
:Coverage(cont), CTest(ctest)
{
}
-bool cmParsePythonCoverage::ReadCoverageXML(const char* xmlFile)
+bool cmParseCoberturaCoverage::ReadCoverageXML(const char* xmlFile)
{
- cmParsePythonCoverage::XMLParser parser(this->CTest, this->Coverage);
+ cmParseCoberturaCoverage::XMLParser parser(this->CTest, this->Coverage);
parser.ParseFile(xmlFile);
return true;
}
diff --git a/Source/CTest/cmParsePythonCoverage.h b/Source/CTest/cmParseCoberturaCoverage.h
index 668c7f9..ff5954d 100644
--- a/Source/CTest/cmParsePythonCoverage.h
+++ b/Source/CTest/cmParseCoberturaCoverage.h
@@ -10,8 +10,8 @@
See the License for more information.
============================================================================*/
-#ifndef cmParsePythonCoverage_h
-#define cmParsePythonCoverage_h
+#ifndef cmParseCoberturaCoverage_h
+#define cmParseCoberturaCoverage_h
#include "cmStandardIncludes.h"
#include "cmCTestCoverageHandler.h"
@@ -25,15 +25,18 @@
* Java-based Cobertura coverage application. This helper class parses
* that XML file to fill the coverage-handler container.
*/
-class cmParsePythonCoverage
+class cmParseCoberturaCoverage
{
public:
//! Create the coverage parser by passing in the coverage handler
//! container and the cmCTest object
- cmParsePythonCoverage(cmCTestCoverageHandlerContainer& cont,
+ cmParseCoberturaCoverage(cmCTestCoverageHandlerContainer& cont,
cmCTest* ctest);
+ bool inSources;
+ bool inSource;
+ std::vector<std::string> filepaths;
//! Read the XML produced by running `coverage xml`
bool ReadCoverageXML(const char* xmlFile);
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 8d2b7fc..05442a1 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -2184,6 +2184,24 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
"Process file.*foo.py.*Total LOC:.*13.*Percentage Coverage: 84.62.*"
ENVIRONMENT COVFILE=)
+ # Adding a test case for non-python Cobertura Coverage
+ configure_file(
+ "${CMake_SOURCE_DIR}/Tests/CoberturaCoverage/DartConfiguration.tcl.in"
+ "${CMake_BINARY_DIR}/Testing/CoberturaCoverage/DartConfiguration.tcl")
+ configure_file(
+ "${CMake_SOURCE_DIR}/Tests/CoberturaCoverage/coverage.xml.in"
+ "${CMake_BINARY_DIR}/Testing/CoberturaCoverage/coverage.xml")
+ file(COPY "${CMake_SOURCE_DIR}/Tests/CoberturaCoverage/src"
+ DESTINATION "${CMake_BINARY_DIR}/Testing/CoberturaCoverage")
+ add_test(NAME CTestCoberturaCoverage
+ COMMAND cmake -E chdir
+ ${CMake_BINARY_DIR}/Testing/CoberturaCoverage
+ $<TARGET_FILE:ctest> -T Coverage --debug)
+ set_tests_properties(CTestCoberturaCoverage PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "Process file.*CoverageTest.java.*Total LOC:.*18.*Percentage Coverage: 72.22.*"
+ ENVIRONMENT COVFILE=)
+
function(add_config_tests cfg)
set(base "${CMake_BINARY_DIR}/Tests/CTestConfig")
diff --git a/Tests/CoberturaCoverage/DartConfiguration.tcl.in b/Tests/CoberturaCoverage/DartConfiguration.tcl.in
new file mode 100644
index 0000000..954f59a
--- /dev/null
+++ b/Tests/CoberturaCoverage/DartConfiguration.tcl.in
@@ -0,0 +1,8 @@
+# This file is configured by CMake automatically as DartConfiguration.tcl
+# If you choose not to use CMake, this file may be hand configured, by
+# filling in the required variables.
+
+
+# Configuration directories and files
+SourceDirectory: ${CMake_SOURCE_DIR}/Testing/CoberturaCoverage
+BuildDirectory: ${CMake_BINARY_DIR}/Testing/CoberturaCoverage
diff --git a/Tests/CoberturaCoverage/coverage.xml.in b/Tests/CoberturaCoverage/coverage.xml.in
new file mode 100644
index 0000000..b3f6691
--- /dev/null
+++ b/Tests/CoberturaCoverage/coverage.xml.in
@@ -0,0 +1,112 @@
+<?xml version="1.0"?>
+<!DOCTYPE coverage SYSTEM "http://cobertura.sourceforge.net/xml/coverage-04.dtd">
+
+<coverage line-rate="0.7222222222222222" branch-rate="0.875" lines-covered="13" lines-valid="18" branches-covered="7" branches-valid="8" complexity="0.0" version="1.9.4.1" timestamp="1401890139281">
+ <sources>
+ <source>${CMake_BINARY_DIR}/Testing/CoberturaCoverage/src/main/java/</source>
+ </sources>
+ <packages>
+ <package name="org.cmake.Coverage" line-rate="0.7222222222222222" branch-rate="0.875" complexity="0.0">
+ <classes>
+ <class name="org.cmake.Coverage.CoverageTest" filename="org/cmake/CoverageTest.java" line-rate="0.7222222222222222" branch-rate="0.875" complexity="0.0">
+ <methods>
+ <method name="&lt;clinit&gt;" signature="()V" line-rate="1.0" branch-rate="1.0">
+ <lines>
+ <line number="10" hits="2" branch="false"/>
+ <line number="11" hits="2" branch="false"/>
+ </lines>
+ </method>
+ <method name="&lt;init&gt;" signature="()V" line-rate="0.0" branch-rate="1.0">
+ <lines>
+ <line number="8" hits="0" branch="false"/>
+ <line number="12" hits="0" branch="false"/>
+ </lines>
+ </method>
+ <method name="equalsVarOne" signature="(Ljava/lang/String;)Ljava/lang/Boolean;" line-rate="0.6666666666666666" branch-rate="0.5">
+ <lines>
+ <line number="16" hits="2" branch="true" condition-coverage="50% (1/2)">
+ <conditions>
+ <condition number="0" type="jump" coverage="50%"/>
+ </conditions>
+ </line>
+ <line number="17" hits="2" branch="false"/>
+ <line number="20" hits="0" branch="false"/>
+ </lines>
+ </method>
+ <method name="equalsVarTwo" signature="(Ljava/lang/String;)Z" line-rate="1.0" branch-rate="1.0">
+ <lines>
+ <line number="26" hits="4" branch="true" condition-coverage="100% (2/2)">
+ <conditions>
+ <condition number="0" type="jump" coverage="100%"/>
+ </conditions>
+ </line>
+ <line number="27" hits="2" branch="false"/>
+ <line number="30" hits="2" branch="false"/>
+ </lines>
+ </method>
+ <method name="timesIntOne" signature="(Ljava/lang/Integer;)Ljava/lang/Integer;" line-rate="0.0" branch-rate="1.0">
+ <lines>
+ <line number="35" hits="0" branch="false"/>
+ <line number="36" hits="0" branch="false"/>
+ </lines>
+ </method>
+ <method name="whileLoop" signature="(Ljava/lang/Integer;)Z" line-rate="1.0" branch-rate="1.0">
+ <lines>
+ <line number="41" hits="2" branch="false"/>
+ <line number="42" hits="10" branch="true" condition-coverage="100% (2/2)">
+ <conditions>
+ <condition number="0" type="jump" coverage="100%"/>
+ </conditions>
+ </line>
+ <line number="43" hits="8" branch="false"/>
+ <line number="45" hits="2" branch="true" condition-coverage="100% (2/2)">
+ <conditions>
+ <condition number="0" type="jump" coverage="100%"/>
+ </conditions>
+ </line>
+ <line number="46" hits="1" branch="false"/>
+ <line number="49" hits="1" branch="false"/>
+ </lines>
+ </method>
+ </methods>
+ <lines>
+ <line number="8" hits="0" branch="false"/>
+ <line number="10" hits="2" branch="false"/>
+ <line number="11" hits="2" branch="false"/>
+ <line number="12" hits="0" branch="false"/>
+ <line number="16" hits="2" branch="true" condition-coverage="50% (1/2)">
+ <conditions>
+ <condition number="0" type="jump" coverage="50%"/>
+ </conditions>
+ </line>
+ <line number="17" hits="2" branch="false"/>
+ <line number="20" hits="0" branch="false"/>
+ <line number="26" hits="4" branch="true" condition-coverage="100% (2/2)">
+ <conditions>
+ <condition number="0" type="jump" coverage="100%"/>
+ </conditions>
+ </line>
+ <line number="27" hits="2" branch="false"/>
+ <line number="30" hits="2" branch="false"/>
+ <line number="35" hits="0" branch="false"/>
+ <line number="36" hits="0" branch="false"/>
+ <line number="41" hits="2" branch="false"/>
+ <line number="42" hits="10" branch="true" condition-coverage="100% (2/2)">
+ <conditions>
+ <condition number="0" type="jump" coverage="100%"/>
+ </conditions>
+ </line>
+ <line number="43" hits="8" branch="false"/>
+ <line number="45" hits="2" branch="true" condition-coverage="100% (2/2)">
+ <conditions>
+ <condition number="0" type="jump" coverage="100%"/>
+ </conditions>
+ </line>
+ <line number="46" hits="1" branch="false"/>
+ <line number="49" hits="1" branch="false"/>
+ </lines>
+ </class>
+ </classes>
+ </package>
+ </packages>
+</coverage>
diff --git a/Tests/CoberturaCoverage/src/main/java/org/cmake/CoverageTest.java b/Tests/CoberturaCoverage/src/main/java/org/cmake/CoverageTest.java
new file mode 100644
index 0000000..4fb43c6
--- /dev/null
+++ b/Tests/CoberturaCoverage/src/main/java/org/cmake/CoverageTest.java
@@ -0,0 +1,52 @@
+package org.cmake.Coverage;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.List;
+import java.awt.*;
+
+public class CoverageTest {
+
+ public static String VarOne = "test1";
+ public static String VarTwo = "test2";
+ private Integer IntOne = 4;
+
+ public static Boolean equalsVarOne(String inString) {
+
+ if(VarOne.equals(inString)){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ public static boolean equalsVarTwo(String inString){
+
+ if(VarTwo.equals(inString)){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ private Integer timesIntOne(Integer inVal){
+
+ return inVal * IntOne;
+ }
+
+ public static boolean whileLoop(Integer StopInt){
+
+ Integer i = 0;
+ while(i < StopInt){
+ i=i+1;
+ }
+ if (i.equals(5)){
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+}