CTest: Add Jacoco Coverage functionality
Add the ability to parse the XML output of the Jacoco tool. Jacoco (www.eclemma.org/jacoco) is a Java coverage tool. Add and integrate a class for the parser and include a test which utilizes the new parser.
This commit is contained in:
parent
47cde18849
commit
558c2190e8
|
@ -518,6 +518,7 @@ set(CTEST_SRCS cmCTest.cxx
|
|||
CTest/cmParseMumpsCoverage.cxx
|
||||
CTest/cmParseCacheCoverage.cxx
|
||||
CTest/cmParseGTMCoverage.cxx
|
||||
CTest/cmParseJacocoCoverage.cxx
|
||||
CTest/cmParsePHPCoverage.cxx
|
||||
CTest/cmParseCoberturaCoverage.cxx
|
||||
CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "cmParseCoberturaCoverage.h"
|
||||
#include "cmParseGTMCoverage.h"
|
||||
#include "cmParseCacheCoverage.h"
|
||||
#include "cmParseJacocoCoverage.h"
|
||||
#include "cmCTest.h"
|
||||
#include "cmake.h"
|
||||
#include "cmMakefile.h"
|
||||
|
@ -415,6 +416,13 @@ int cmCTestCoverageHandler::ProcessHandler()
|
|||
return error;
|
||||
}
|
||||
|
||||
file_count += this->HandleJacocoCoverage(&cont);
|
||||
error = cont.Error;
|
||||
if ( file_count < 0 )
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
std::set<std::string> uncovered = this->FindUncoveredFiles(&cont);
|
||||
|
||||
if ( file_count == 0 )
|
||||
|
@ -871,6 +879,38 @@ struct cmCTestCoverageHandlerLocale
|
|||
std::string lc_all;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int cmCTestCoverageHandler::HandleJacocoCoverage(
|
||||
cmCTestCoverageHandlerContainer* cont)
|
||||
{
|
||||
cmParseJacocoCoverage cov =
|
||||
cmParseJacocoCoverage(*cont, this->CTest);
|
||||
cmsys::Glob g;
|
||||
std::vector<std::string> files;
|
||||
g.SetRecurse(true);
|
||||
|
||||
std::string SourceDir
|
||||
= this->CTest->GetCTestConfiguration("SourceDirectory");
|
||||
std::string coverageFile = SourceDir+ "/*jacoco.xml";
|
||||
|
||||
g.FindFiles(coverageFile);
|
||||
files=g.GetFiles();
|
||||
if (files.size() > 0)
|
||||
{
|
||||
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
|
||||
"Found Jacoco Files, Performing Coverage" << std::endl);
|
||||
cov.LoadCoverageData(files);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
|
||||
" Cannot find Jacoco coverage files: " << coverageFile
|
||||
<< std::endl);
|
||||
}
|
||||
return static_cast<int>(cont->TotalCoverage.size());
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int cmCTestCoverageHandler::HandleGCovCoverage(
|
||||
cmCTestCoverageHandlerContainer* cont)
|
||||
|
|
|
@ -81,6 +81,9 @@ private:
|
|||
//! Handle coverage for mumps
|
||||
int HandleMumpsCoverage(cmCTestCoverageHandlerContainer* cont);
|
||||
|
||||
//! Handle coverage for Jacoco
|
||||
int HandleJacocoCoverage(cmCTestCoverageHandlerContainer* cont);
|
||||
|
||||
//! Handle coverage using Bullseye
|
||||
int HandleBullseyeCoverage(cmCTestCoverageHandlerContainer* cont);
|
||||
int RunBullseyeSourceSummary(cmCTestCoverageHandlerContainer* cont);
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
#include "cmStandardIncludes.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmXMLParser.h"
|
||||
#include "cmParseJacocoCoverage.h"
|
||||
#include <cmsys/Directory.hxx>
|
||||
#include <cmsys/Glob.hxx>
|
||||
#include <cmsys/FStream.hxx>
|
||||
|
||||
|
||||
class cmParseJacocoCoverage::XMLParser: public cmXMLParser
|
||||
{
|
||||
public:
|
||||
XMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont)
|
||||
: CTest(ctest), Coverage(cont)
|
||||
{
|
||||
this->PackageName = "";
|
||||
this->ModuleName = "";
|
||||
this->FileName = "";
|
||||
this->CurFileName = "";
|
||||
this->FilePaths.push_back(this->Coverage.SourceDir);
|
||||
}
|
||||
|
||||
virtual ~XMLParser()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void EndElement(const std::string&)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void StartElement(const std::string& name,
|
||||
const char** atts)
|
||||
{
|
||||
if(name == "package")
|
||||
{
|
||||
this->PackageName = atts[1];
|
||||
std::string FilePath = this->Coverage.SourceDir +
|
||||
"/" + this->ModuleName + "/src/main/java/" +
|
||||
this->PackageName;
|
||||
this->FilePaths.push_back(FilePath);
|
||||
}
|
||||
else if(name == "sourcefile")
|
||||
{
|
||||
this->FileName = atts[1];
|
||||
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Reading file: "
|
||||
<< this->FileName << std::endl);
|
||||
for(size_t i=0;i < FilePaths.size();i++)
|
||||
{
|
||||
std::string finalpath = FilePaths[i] + "/" + this->FileName;
|
||||
if(cmSystemTools::FileExists(finalpath.c_str()))
|
||||
{
|
||||
this->CurFileName = finalpath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cmsys::ifstream fin(this->CurFileName.c_str());
|
||||
if(this->CurFileName == "" || !fin )
|
||||
{
|
||||
this->CurFileName = this->Coverage.BinaryDir + "/" +
|
||||
this->FileName;
|
||||
fin.open(this->CurFileName.c_str());
|
||||
if (!fin)
|
||||
{
|
||||
cmCTestLog(this->CTest, ERROR_MESSAGE,
|
||||
"Jacoco Coverage: Error opening " << this->CurFileName
|
||||
<< std::endl);
|
||||
this->Coverage.Error++;
|
||||
}
|
||||
}
|
||||
std::string line;
|
||||
FileLinesType& curFileLines =
|
||||
this->Coverage.TotalCoverage[this->CurFileName];
|
||||
curFileLines.push_back(-1);
|
||||
while(cmSystemTools::GetLineFromStream(fin, line))
|
||||
{
|
||||
curFileLines.push_back(-1);
|
||||
}
|
||||
}
|
||||
else if(name == "report")
|
||||
{
|
||||
this->ModuleName=atts[1];
|
||||
}
|
||||
else if(name == "line")
|
||||
{
|
||||
int tagCount = 0;
|
||||
int nr = -1;
|
||||
int ci = -1;
|
||||
while(true)
|
||||
{
|
||||
if(strcmp(atts[tagCount],"ci") == 0)
|
||||
{
|
||||
ci = atoi(atts[tagCount+1]);
|
||||
}
|
||||
else if (strcmp(atts[tagCount],"nr") == 0)
|
||||
{
|
||||
nr = atoi(atts[tagCount+1]);
|
||||
}
|
||||
if (ci > -1 && nr > 0)
|
||||
{
|
||||
FileLinesType& curFileLines=
|
||||
this->Coverage.TotalCoverage[this->CurFileName];
|
||||
if(curFileLines.size() > 0)
|
||||
{
|
||||
curFileLines[nr-1] = ci;
|
||||
}
|
||||
break;
|
||||
}
|
||||
++tagCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string PackageName;
|
||||
std::string FileName;
|
||||
std::string ModuleName;
|
||||
std::string CurFileName;
|
||||
std::vector<std::string> FilePaths;
|
||||
typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector
|
||||
FileLinesType;
|
||||
cmCTest* CTest;
|
||||
cmCTestCoverageHandlerContainer& Coverage;
|
||||
};
|
||||
|
||||
cmParseJacocoCoverage::cmParseJacocoCoverage(
|
||||
cmCTestCoverageHandlerContainer& cont,
|
||||
cmCTest* ctest)
|
||||
:Coverage(cont), CTest(ctest)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmParseJacocoCoverage::LoadCoverageData(
|
||||
const std::vector<std::string> files)
|
||||
{
|
||||
// load all the jacoco.xml files in the source directory
|
||||
cmsys::Directory dir;
|
||||
size_t i;
|
||||
std::string path;
|
||||
size_t numf = files.size();
|
||||
for (i = 0; i < numf; i++)
|
||||
{
|
||||
path = files[i];
|
||||
|
||||
cmCTestLog(this->CTest,HANDLER_VERBOSE_OUTPUT,
|
||||
"Reading XML File " << path << std::endl);
|
||||
if(cmSystemTools::GetFilenameLastExtension(path) == ".xml")
|
||||
{
|
||||
if(!this->ReadJacocoXML(path.c_str()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmParseJacocoCoverage::ReadJacocoXML(const char* file)
|
||||
{
|
||||
cmParseJacocoCoverage::XMLParser
|
||||
parser(this->CTest, this->Coverage);
|
||||
parser.ParseFile(file);
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*============================================================================
|
||||
CMake - Cross Platform Makefile Generator
|
||||
Copyright 2000-2009 Kitware, Inc.
|
||||
|
||||
Distributed under the OSI-approved BSD License (the "License");
|
||||
see accompanying file Copyright.txt for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the License for more information.
|
||||
============================================================================*/
|
||||
|
||||
#ifndef cmParseJacocoCoverage_h
|
||||
#define cmParseJacocoCoverage_h
|
||||
|
||||
#include "cmStandardIncludes.h"
|
||||
#include "cmCTestCoverageHandler.h"
|
||||
|
||||
|
||||
/** \class cmParseJacocoCoverage
|
||||
* \brief Parse JaCoCO coverage information
|
||||
*
|
||||
* This class is used to parse coverage information for
|
||||
* java using the JaCoCo tool:
|
||||
*
|
||||
* http://www.eclemma.org/jacoco/trunk/index.html
|
||||
*/
|
||||
class cmParseJacocoCoverage
|
||||
{
|
||||
public:
|
||||
cmParseJacocoCoverage(cmCTestCoverageHandlerContainer& cont,
|
||||
cmCTest* ctest);
|
||||
bool LoadCoverageData(const std::vector<std::string> files);
|
||||
|
||||
std::string PackageName;
|
||||
std::string FileName;
|
||||
std::string ModuleName;
|
||||
std::string CurFileName;
|
||||
private:
|
||||
// implement virtual from parent
|
||||
// remove files with no coverage
|
||||
void RemoveUnCoveredFiles();
|
||||
// Read a single mcov file
|
||||
bool ReadJacocoXML(const char* f);
|
||||
// split a string based on ,
|
||||
bool SplitString(std::vector<std::string>& args,
|
||||
std::string const& line);
|
||||
bool FindJavaFile(std::string const& routine,
|
||||
std::string& filepath);
|
||||
void InitializeJavaFile(std::string& file);
|
||||
bool LoadSource(std::string d);
|
||||
|
||||
class XMLParser;
|
||||
std::map<std::string, std::string> RoutineToDirectory;
|
||||
cmCTestCoverageHandlerContainer& Coverage;
|
||||
cmCTest* CTest;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -2202,6 +2202,22 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
|
|||
"Process file.*CoverageTest.java.*Total LOC:.*18.*Percentage Coverage: 72.22.*"
|
||||
ENVIRONMENT COVFILE=)
|
||||
|
||||
|
||||
# Adding a test case for JaCoCo Coverage
|
||||
configure_file(
|
||||
"${CMake_SOURCE_DIR}/Tests/JacocoCoverage/DartConfiguration.tcl.in"
|
||||
"${CMake_BINARY_DIR}/Testing/JacocoCoverage/DartConfiguration.tcl")
|
||||
file(COPY "${CMake_SOURCE_DIR}/Tests/JacocoCoverage/Coverage"
|
||||
DESTINATION "${CMake_BINARY_DIR}/Testing/JacocoCoverage")
|
||||
add_test(NAME CTestJacocoCoverage
|
||||
COMMAND cmake -E chdir
|
||||
${CMake_BINARY_DIR}/Testing/JacocoCoverage
|
||||
$<TARGET_FILE:ctest> -T Coverage --debug)
|
||||
set_tests_properties(CTestJacocoCoverage PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION
|
||||
"Process file.*CoverageTest.java.*Total LOC:.*17.*Percentage Coverage: 76.47*"
|
||||
ENVIRONMENT COVFILE=)
|
||||
|
||||
function(add_config_tests cfg)
|
||||
set(base "${CMake_BINARY_DIR}/Tests/CTestConfig")
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><!DOCTYPE report PUBLIC "-//JACOCO//DTD Report 1.0//EN" "report.dtd"><report name="Coverage"><sessioninfo id="vagrant-ubuntu-precise-32-f1c264e9" start="1402427058670" dump="1402427059269"/><package name="org/cmake"><class name="org/cmake/Coverage/CoverageTest"><method name="<init>" desc="()V" line="8"><counter type="INSTRUCTION" missed="7" covered="0"/><counter type="LINE" missed="2" covered="0"/><counter type="COMPLEXITY" missed="1" covered="0"/><counter type="METHOD" missed="1" covered="0"/></method><method name="equalsVarOne" desc="(Ljava/lang/String;)Ljava/lang/Boolean;" line="16"><counter type="INSTRUCTION" missed="3" covered="7"/><counter type="BRANCH" missed="1" covered="1"/><counter type="LINE" missed="1" covered="2"/><counter type="COMPLEXITY" missed="1" covered="1"/><counter type="METHOD" missed="0" covered="1"/></method><method name="equalsVarTwo" desc="(Ljava/lang/String;)Z" line="26"><counter type="INSTRUCTION" missed="0" covered="8"/><counter type="BRANCH" missed="0" covered="2"/><counter type="LINE" missed="0" covered="3"/><counter type="COMPLEXITY" missed="0" covered="2"/><counter type="METHOD" missed="0" covered="1"/></method><method name="timesIntOne" desc="(Ljava/lang/Integer;)Ljava/lang/Integer;" line="36"><counter type="INSTRUCTION" missed="8" covered="0"/><counter type="LINE" missed="1" covered="0"/><counter type="COMPLEXITY" missed="1" covered="0"/><counter type="METHOD" missed="1" covered="0"/></method><method name="whileLoop" desc="(Ljava/lang/Integer;)Z" line="41"><counter type="INSTRUCTION" missed="0" covered="24"/><counter type="BRANCH" missed="0" covered="4"/><counter type="LINE" missed="0" covered="6"/><counter type="COMPLEXITY" missed="0" covered="3"/><counter type="METHOD" missed="0" covered="1"/></method><method name="<clinit>" desc="()V" line="10"><counter type="INSTRUCTION" missed="0" covered="5"/><counter type="LINE" missed="0" covered="2"/><counter type="COMPLEXITY" missed="0" covered="1"/><counter type="METHOD" missed="0" covered="1"/></method><counter type="INSTRUCTION" missed="18" covered="44"/><counter type="BRANCH" missed="1" covered="7"/><counter type="LINE" missed="4" covered="13"/><counter type="COMPLEXITY" missed="3" covered="7"/><counter type="METHOD" missed="2" covered="4"/><counter type="CLASS" missed="0" covered="1"/></class><sourcefile name="CoverageTest.java"><line nr="8" mi="2" ci="0" mb="0" cb="0"/><line nr="10" mi="0" ci="2" mb="0" cb="0"/><line nr="11" mi="0" ci="3" mb="0" cb="0"/><line nr="12" mi="5" ci="0" mb="0" cb="0"/><line nr="16" mi="0" ci="4" mb="1" cb="1"/><line nr="17" mi="0" ci="3" mb="0" cb="0"/><line nr="20" mi="3" ci="0" mb="0" cb="0"/><line nr="26" mi="0" ci="4" mb="0" cb="2"/><line nr="27" mi="0" ci="2" mb="0" cb="0"/><line nr="30" mi="0" ci="2" mb="0" cb="0"/><line nr="36" mi="8" ci="0" mb="0" cb="0"/><line nr="41" mi="0" ci="3" mb="0" cb="0"/><line nr="42" mi="0" ci="5" mb="0" cb="2"/><line nr="43" mi="0" ci="7" mb="0" cb="0"/><line nr="45" mi="0" ci="5" mb="0" cb="2"/><line nr="46" mi="0" ci="2" mb="0" cb="0"/><line nr="49" mi="0" ci="2" mb="0" cb="0"/><counter type="INSTRUCTION" missed="18" covered="44"/><counter type="BRANCH" missed="1" covered="7"/><counter type="LINE" missed="4" covered="13"/><counter type="COMPLEXITY" missed="3" covered="7"/><counter type="METHOD" missed="2" covered="4"/><counter type="CLASS" missed="0" covered="1"/></sourcefile><counter type="INSTRUCTION" missed="18" covered="44"/><counter type="BRANCH" missed="1" covered="7"/><counter type="LINE" missed="4" covered="13"/><counter type="COMPLEXITY" missed="3" covered="7"/><counter type="METHOD" missed="2" covered="4"/><counter type="CLASS" missed="0" covered="1"/></package><counter type="INSTRUCTION" missed="18" covered="44"/><counter type="BRANCH" missed="1" covered="7"/><counter type="LINE" missed="4" covered="13"/><counter type="COMPLEXITY" missed="3" covered="7"/><counter type="METHOD" missed="2" covered="4"/><counter type="CLASS" missed="0" covered="1"/></report>
|
|
@ -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_BINARY_DIR}/Testing/JacocoCoverage
|
||||
BuildDirectory: ${CMake_BINARY_DIR}/Testing/JacocoCoverage
|
Loading…
Reference in New Issue