cmake/Source/CTest/cmParseJacocoCoverage.cxx

179 lines
5.1 KiB
C++
Raw Normal View History

2016-07-09 11:21:54 +02:00
#include "cmParseJacocoCoverage.h"
2020-02-01 23:06:01 +01:00
#include <cstdlib>
#include <cstring>
2016-10-30 18:24:19 +01:00
2017-07-20 19:35:53 +02:00
#include "cmsys/Directory.hxx"
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
2020-02-01 23:06:01 +01:00
#include "cmCTest.h"
#include "cmCTestCoverageHandler.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
2015-04-27 22:25:09 +02:00
2016-07-09 11:21:54 +02:00
class cmParseJacocoCoverage::XMLParser : public cmXMLParser
2015-04-27 22:25:09 +02:00
{
2016-07-09 11:21:54 +02:00
public:
XMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont)
: CTest(ctest)
, Coverage(cont)
{
}
2015-04-27 22:25:09 +02:00
2016-07-09 11:21:54 +02:00
protected:
2018-01-26 17:06:56 +01:00
void EndElement(const std::string& /*name*/) override {}
2015-04-27 22:25:09 +02:00
2018-01-26 17:06:56 +01:00
void StartElement(const std::string& name, const char** atts) override
2016-07-09 11:21:54 +02:00
{
if (name == "package") {
this->PackageName = atts[1];
2018-01-26 17:06:56 +01:00
this->PackagePath.clear();
2016-07-09 11:21:54 +02:00
} else if (name == "sourcefile") {
2019-11-11 23:01:05 +01:00
this->FilePath.clear();
2016-07-09 11:21:54 +02:00
std::string fileName = atts[1];
2018-01-26 17:06:56 +01:00
if (this->PackagePath.empty()) {
2016-07-09 11:21:54 +02:00
if (!this->FindPackagePath(fileName)) {
2018-08-09 18:06:22 +02:00
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Cannot find file: " << this->PackageName << "/"
<< fileName << std::endl);
2016-07-09 11:21:54 +02:00
this->Coverage.Error++;
return;
}
2015-04-27 22:25:09 +02:00
}
2016-07-09 11:21:54 +02:00
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Reading file: " << fileName << std::endl,
this->Coverage.Quiet);
2015-11-17 17:22:37 +01:00
2016-07-09 11:21:54 +02:00
this->FilePath = this->PackagePath + "/" + fileName;
cmsys::ifstream fin(this->FilePath.c_str());
if (!fin) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Jacoco Coverage: Error opening " << this->FilePath
<< std::endl);
}
std::string line;
FileLinesType& curFileLines =
this->Coverage.TotalCoverage[this->FilePath];
if (fin) {
curFileLines.push_back(-1);
}
while (cmSystemTools::GetLineFromStream(fin, line)) {
curFileLines.push_back(-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]);
2015-04-27 22:25:09 +02:00
}
2016-07-09 11:21:54 +02:00
if (ci > -1 && nr > 0) {
FileLinesType& curFileLines =
this->Coverage.TotalCoverage[this->FilePath];
if (!curFileLines.empty()) {
curFileLines[nr - 1] = ci;
2015-04-27 22:25:09 +02:00
}
2016-07-09 11:21:54 +02:00
break;
2015-04-27 22:25:09 +02:00
}
2016-07-09 11:21:54 +02:00
++tagCount;
2015-04-27 22:25:09 +02:00
}
2016-07-09 11:21:54 +02:00
}
}
2015-04-27 22:25:09 +02:00
2016-07-09 11:21:54 +02:00
virtual bool FindPackagePath(std::string const& fileName)
{
// Search for the source file in the source directory.
if (this->PackagePathFound(fileName, this->Coverage.SourceDir)) {
return true;
}
2015-11-17 17:22:37 +01:00
2016-07-09 11:21:54 +02:00
// If not found there, check the binary directory.
if (this->PackagePathFound(fileName, this->Coverage.BinaryDir)) {
return true;
}
return false;
}
2015-11-17 17:22:37 +01:00
2016-07-09 11:21:54 +02:00
virtual bool PackagePathFound(std::string const& fileName,
std::string const& baseDir)
{
// Search for the file in the baseDir and its subdirectories.
2020-02-01 23:06:01 +01:00
std::string packageGlob = cmStrCat(baseDir, '/', fileName);
2016-07-09 11:21:54 +02:00
cmsys::Glob gl;
gl.RecurseOn();
gl.RecurseThroughSymlinksOn();
gl.FindFiles(packageGlob);
std::vector<std::string> const& files = gl.GetFiles();
2016-10-30 18:24:19 +01:00
if (files.empty()) {
2015-11-17 17:22:37 +01:00
return false;
2016-07-09 11:21:54 +02:00
}
// Check if any of the locations found match our package.
2018-01-26 17:06:56 +01:00
for (std::string const& f : files) {
std::string dir = cmsys::SystemTools::GetParentDirectory(f);
2020-02-01 23:06:01 +01:00
if (cmHasSuffix(dir, this->PackageName)) {
2016-07-09 11:21:54 +02:00
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Found package directory for " << fileName << ": "
<< dir << std::endl,
this->Coverage.Quiet);
this->PackagePath = dir;
return true;
2015-11-17 17:22:37 +01:00
}
2016-07-09 11:21:54 +02:00
}
return false;
}
2015-11-17 17:22:37 +01:00
2016-07-09 11:21:54 +02:00
private:
std::string FilePath;
std::string PackagePath;
std::string PackageName;
2020-02-01 23:06:01 +01:00
using FileLinesType =
cmCTestCoverageHandlerContainer::SingleFileCoverageVector;
2016-07-09 11:21:54 +02:00
cmCTest* CTest;
cmCTestCoverageHandlerContainer& Coverage;
2015-04-27 22:25:09 +02:00
};
cmParseJacocoCoverage::cmParseJacocoCoverage(
2016-07-09 11:21:54 +02:00
cmCTestCoverageHandlerContainer& cont, cmCTest* ctest)
: Coverage(cont)
, CTest(ctest)
{
}
2015-04-27 22:25:09 +02:00
bool cmParseJacocoCoverage::LoadCoverageData(
2016-07-09 11:21:54 +02:00
std::vector<std::string> const& files)
2015-04-27 22:25:09 +02:00
{
// load all the jacoco.xml files in the source directory
cmsys::Directory dir;
size_t i;
std::string path;
size_t numf = files.size();
2016-07-09 11:21:54 +02:00
for (i = 0; i < numf; i++) {
2015-04-27 22:25:09 +02:00
path = files[i];
2016-07-09 11:21:54 +02:00
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Reading XML File " << path << std::endl,
this->Coverage.Quiet);
if (cmSystemTools::GetFilenameLastExtension(path) == ".xml") {
if (!this->ReadJacocoXML(path.c_str())) {
2015-04-27 22:25:09 +02:00
return false;
}
}
2016-07-09 11:21:54 +02:00
}
2015-04-27 22:25:09 +02:00
return true;
}
bool cmParseJacocoCoverage::ReadJacocoXML(const char* file)
{
2016-07-09 11:21:54 +02:00
cmParseJacocoCoverage::XMLParser parser(this->CTest, this->Coverage);
2015-04-27 22:25:09 +02:00
parser.ParseFile(file);
return true;
}