cmake/Source/CTest/cmParseCoberturaCoverage.cxx

166 lines
4.8 KiB
C++
Raw Normal View History

2016-07-09 11:21:54 +02:00
#include "cmParseCoberturaCoverage.h"
2020-02-01 23:06:01 +01:00
#include <cstdlib>
#include <cstring>
#include "cmsys/FStream.hxx"
2016-10-30 18:24:19 +01:00
#include "cmCTest.h"
#include "cmCTestCoverageHandler.h"
2020-02-01 23:06:01 +01:00
#include "cmStringAlgorithms.h"
2015-04-27 22:25:09 +02:00
#include "cmSystemTools.h"
#include "cmXMLParser.h"
2016-10-30 18:24:19 +01:00
2016-07-09 11:21:54 +02:00
class cmParseCoberturaCoverage::XMLParser : public cmXMLParser
2015-04-27 22:25:09 +02:00
{
public:
XMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont)
2019-11-11 23:01:05 +01:00
: FilePaths{ cont.SourceDir, cont.BinaryDir }
, CTest(ctest)
2016-07-09 11:21:54 +02:00
, Coverage(cont)
2015-04-27 22:25:09 +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
{
2016-07-09 11:21:54 +02:00
if (name == "source") {
this->InSource = false;
} else if (name == "sources") {
this->InSources = false;
} else if (name == "class") {
2015-04-27 22:25:09 +02:00
this->SkipThisClass = false;
2016-07-09 11:21:54 +02:00
}
2015-04-27 22:25:09 +02:00
}
2018-01-26 17:06:56 +01:00
void CharacterDataHandler(const char* data, int length) override
2015-04-27 22:25:09 +02:00
{
2016-07-09 11:21:54 +02:00
std::string tmp;
tmp.insert(0, data, length);
if (this->InSources && this->InSource) {
this->FilePaths.push_back(tmp);
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Adding Source: " << tmp << std::endl,
this->Coverage.Quiet);
}
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
2015-04-27 22:25:09 +02:00
{
std::string FoundSource;
2017-04-14 19:02:05 +02:00
std::string finalpath;
2016-07-09 11:21:54 +02:00
if (name == "source") {
2015-04-27 22:25:09 +02:00
this->InSource = true;
2016-07-09 11:21:54 +02:00
} else if (name == "sources") {
2015-04-27 22:25:09 +02:00
this->InSources = true;
2016-07-09 11:21:54 +02:00
} else if (name == "class") {
2015-04-27 22:25:09 +02:00
int tagCount = 0;
2016-07-09 11:21:54 +02:00
while (true) {
if (strcmp(atts[tagCount], "filename") == 0) {
2015-08-17 11:37:30 +02:00
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
2016-07-09 11:21:54 +02:00
"Reading file: " << atts[tagCount + 1]
<< std::endl,
this->Coverage.Quiet);
std::string filename = atts[tagCount + 1];
2018-01-26 17:06:56 +01:00
this->CurFileName.clear();
2015-04-27 22:25:09 +02:00
// Check if this is an absolute path that falls within our
// source or binary directories.
2021-09-14 00:13:48 +02:00
for (std::string const& filePath : this->FilePaths) {
2020-08-30 11:54:41 +02:00
if (cmHasPrefix(filename, filePath)) {
2015-04-27 22:25:09 +02:00
this->CurFileName = filename;
break;
}
2016-07-09 11:21:54 +02:00
}
2015-04-27 22:25:09 +02:00
2018-01-26 17:06:56 +01:00
if (this->CurFileName.empty()) {
2015-04-27 22:25:09 +02:00
// Check if this is a path that is relative to our source or
// binary directories.
2021-09-14 00:13:48 +02:00
for (std::string const& filePath : this->FilePaths) {
2020-02-01 23:06:01 +01:00
finalpath = cmStrCat(filePath, "/", filename);
2018-04-23 21:13:27 +02:00
if (cmSystemTools::FileExists(finalpath)) {
2015-04-27 22:25:09 +02:00
this->CurFileName = finalpath;
break;
}
}
2016-07-09 11:21:54 +02:00
}
2015-04-27 22:25:09 +02:00
cmsys::ifstream fin(this->CurFileName.c_str());
2018-01-26 17:06:56 +01:00
if (this->CurFileName.empty() || !fin) {
2016-07-09 11:21:54 +02:00
this->CurFileName =
2020-02-01 23:06:01 +01:00
cmStrCat(this->Coverage.BinaryDir, "/", atts[tagCount + 1]);
2015-04-27 22:25:09 +02:00
fin.open(this->CurFileName.c_str());
2016-07-09 11:21:54 +02:00
if (!fin) {
2015-08-17 11:37:30 +02:00
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
2016-07-09 11:21:54 +02:00
"Skipping system file " << filename
<< std::endl,
this->Coverage.Quiet);
2015-04-27 22:25:09 +02:00
this->SkipThisClass = true;
break;
}
}
std::string line;
FileLinesType& curFileLines =
this->Coverage.TotalCoverage[this->CurFileName];
2016-07-09 11:21:54 +02:00
while (cmSystemTools::GetLineFromStream(fin, line)) {
2015-04-27 22:25:09 +02:00
curFileLines.push_back(-1);
}
break;
}
++tagCount;
}
2016-07-09 11:21:54 +02:00
} else if (name == "line") {
2015-04-27 22:25:09 +02:00
int tagCount = 0;
int curNumber = -1;
int curHits = -1;
2016-07-09 11:21:54 +02:00
while (true) {
if (this->SkipThisClass) {
2015-04-27 22:25:09 +02:00
break;
}
2016-07-09 11:21:54 +02:00
if (strcmp(atts[tagCount], "hits") == 0) {
curHits = atoi(atts[tagCount + 1]);
} else if (strcmp(atts[tagCount], "number") == 0) {
curNumber = atoi(atts[tagCount + 1]);
2015-04-27 22:25:09 +02:00
}
2016-07-09 11:21:54 +02:00
if (curHits > -1 && curNumber > 0) {
2015-04-27 22:25:09 +02:00
FileLinesType& curFileLines =
this->Coverage.TotalCoverage[this->CurFileName];
2016-07-09 11:21:54 +02:00
{
curFileLines[curNumber - 1] = curHits;
}
2015-04-27 22:25:09 +02:00
break;
}
++tagCount;
}
}
}
private:
2019-11-11 23:01:05 +01:00
bool InSources = false;
bool InSource = false;
bool SkipThisClass = false;
2015-04-27 22:25:09 +02:00
std::vector<std::string> FilePaths;
2020-02-01 23:06:01 +01:00
using FileLinesType =
cmCTestCoverageHandlerContainer::SingleFileCoverageVector;
2015-04-27 22:25:09 +02:00
cmCTest* CTest;
cmCTestCoverageHandlerContainer& Coverage;
std::string CurFileName;
};
cmParseCoberturaCoverage::cmParseCoberturaCoverage(
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 cmParseCoberturaCoverage::ReadCoverageXML(const char* xmlFile)
{
cmParseCoberturaCoverage::XMLParser parser(this->CTest, this->Coverage);
parser.ParseFile(xmlFile);
return true;
}