| #include "cmStandardIncludes.h" |
| #include "cmSystemTools.h" |
| #include "cmXMLParser.h" |
| #include "cmParseCoberturaCoverage.h" |
| #include <cmsys/Directory.hxx> |
| #include <cmsys/FStream.hxx> |
| |
| //---------------------------------------------------------------------------- |
| class cmParseCoberturaCoverage::XMLParser: public cmXMLParser |
| { |
| public: |
| XMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont) |
| : CTest(ctest), Coverage(cont) |
| { |
| this->InSources = false; |
| this->InSource = false; |
| this->SkipThisClass = false; |
| this->FilePaths.push_back(this->Coverage.SourceDir); |
| this->FilePaths.push_back(this->Coverage.BinaryDir); |
| this->CurFileName = ""; |
| } |
| |
| virtual ~XMLParser() |
| { |
| } |
| |
| protected: |
| |
| |
| virtual void EndElement(const std::string& name) |
| { |
| if(name == "source") |
| { |
| this->InSource=false; |
| } |
| else if (name == "sources") |
| { |
| this->InSources=false; |
| } |
| else if(name == "class") |
| { |
| this->SkipThisClass = 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); |
| cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, |
| "Adding Source: " << tmp << std::endl, this->Coverage.Quiet); |
| } |
| } |
| |
| virtual void StartElement(const std::string& name, const char** atts) |
| { |
| 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 = ""; |
| |
| // Check if this is an absolute path that falls within our |
| // source or binary directories. |
| for(size_t i=0;i < FilePaths.size();i++) |
| { |
| if (filename.find(FilePaths[i]) == 0) |
| { |
| this->CurFileName = filename; |
| break; |
| } |
| } |
| |
| if (this->CurFileName == "") |
| { |
| // Check if this is a path that is relative to our source or |
| // binary directories. |
| 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(this->CurFileName == "" || !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]; |
| curFileLines.push_back(-1); |
| 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; |
| bool InSource; |
| bool SkipThisClass; |
| 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; |
| } |