diff options
Diffstat (limited to 'Source/CTest/cmParseCoberturaCoverage.cxx')
-rw-r--r-- | Source/CTest/cmParseCoberturaCoverage.cxx | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/Source/CTest/cmParseCoberturaCoverage.cxx b/Source/CTest/cmParseCoberturaCoverage.cxx new file mode 100644 index 0000000..848a034 --- /dev/null +++ b/Source/CTest/cmParseCoberturaCoverage.cxx @@ -0,0 +1,163 @@ +#include "cmParseCoberturaCoverage.h" + +#include "cmCTest.h" +#include "cmCTestCoverageHandler.h" +#include "cmSystemTools.h" +#include "cmXMLParser.h" + +#include "cmsys/FStream.hxx" +#include <stdlib.h> +#include <string.h> + +class cmParseCoberturaCoverage::XMLParser : public cmXMLParser +{ +public: + XMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont) + : FilePaths{ cont.SourceDir, cont.BinaryDir } + , CTest(ctest) + , Coverage(cont) + { + } + +protected: + void EndElement(const std::string& name) override + { + if (name == "source") { + this->InSource = false; + } else if (name == "sources") { + this->InSources = false; + } else if (name == "class") { + this->SkipThisClass = false; + } + } + + void CharacterDataHandler(const char* data, int length) override + { + 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); + } + } + + void StartElement(const std::string& name, const char** atts) override + { + 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) { + if (strcmp(atts[tagCount], "filename") == 0) { + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "Reading file: " << atts[tagCount + 1] + << std::endl, + this->Coverage.Quiet); + std::string filename = atts[tagCount + 1]; + this->CurFileName.clear(); + + // Check if this is an absolute path that falls within our + // source or binary directories. + for (std::string const& filePath : FilePaths) { + if (filename.find(filePath) == 0) { + this->CurFileName = filename; + break; + } + } + + if (this->CurFileName.empty()) { + // Check if this is a path that is relative to our source or + // binary directories. + for (std::string const& filePath : FilePaths) { + finalpath = filePath + "/" + filename; + if (cmSystemTools::FileExists(finalpath)) { + this->CurFileName = finalpath; + break; + } + } + } + + cmsys::ifstream fin(this->CurFileName.c_str()); + if (this->CurFileName.empty() || !fin) { + this->CurFileName = + this->Coverage.BinaryDir + "/" + atts[tagCount + 1]; + fin.open(this->CurFileName.c_str()); + if (!fin) { + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "Skipping system file " << filename + << std::endl, + this->Coverage.Quiet); + + this->SkipThisClass = true; + break; + } + } + std::string line; + FileLinesType& curFileLines = + this->Coverage.TotalCoverage[this->CurFileName]; + while (cmSystemTools::GetLineFromStream(fin, line)) { + curFileLines.push_back(-1); + } + + break; + } + ++tagCount; + } + } else if (name == "line") { + int tagCount = 0; + int curNumber = -1; + int curHits = -1; + while (true) { + if (this->SkipThisClass) { + break; + } + if (strcmp(atts[tagCount], "hits") == 0) { + curHits = atoi(atts[tagCount + 1]); + } else if (strcmp(atts[tagCount], "number") == 0) { + curNumber = atoi(atts[tagCount + 1]); + } + + if (curHits > -1 && curNumber > 0) { + FileLinesType& curFileLines = + this->Coverage.TotalCoverage[this->CurFileName]; + { + curFileLines[curNumber - 1] = curHits; + } + break; + } + ++tagCount; + } + } + } + +private: + bool InSources = false; + bool InSource = false; + bool SkipThisClass = false; + std::vector<std::string> FilePaths; + typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector + FileLinesType; + cmCTest* CTest; + cmCTestCoverageHandlerContainer& Coverage; + std::string CurFileName; +}; + +cmParseCoberturaCoverage::cmParseCoberturaCoverage( + cmCTestCoverageHandlerContainer& cont, cmCTest* ctest) + : Coverage(cont) + , CTest(ctest) +{ +} + +bool cmParseCoberturaCoverage::ReadCoverageXML(const char* xmlFile) +{ + cmParseCoberturaCoverage::XMLParser parser(this->CTest, this->Coverage); + parser.ParseFile(xmlFile); + return true; +} |