cmParseCoberturaCoverage.cxx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #include "cmParseCoberturaCoverage.h"
  2. #include "cmCTest.h"
  3. #include "cmCTestCoverageHandler.h"
  4. #include "cmSystemTools.h"
  5. #include "cmXMLParser.h"
  6. #include "cmsys/FStream.hxx"
  7. #include <stdlib.h>
  8. #include <string.h>
  9. class cmParseCoberturaCoverage::XMLParser : public cmXMLParser
  10. {
  11. public:
  12. XMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont)
  13. : CTest(ctest)
  14. , Coverage(cont)
  15. {
  16. this->InSources = false;
  17. this->InSource = false;
  18. this->SkipThisClass = false;
  19. this->FilePaths.push_back(this->Coverage.SourceDir);
  20. this->FilePaths.push_back(this->Coverage.BinaryDir);
  21. this->CurFileName.clear();
  22. }
  23. ~XMLParser() override {}
  24. protected:
  25. void EndElement(const std::string& name) override
  26. {
  27. if (name == "source") {
  28. this->InSource = false;
  29. } else if (name == "sources") {
  30. this->InSources = false;
  31. } else if (name == "class") {
  32. this->SkipThisClass = false;
  33. }
  34. }
  35. void CharacterDataHandler(const char* data, int length) override
  36. {
  37. std::string tmp;
  38. tmp.insert(0, data, length);
  39. if (this->InSources && this->InSource) {
  40. this->FilePaths.push_back(tmp);
  41. cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
  42. "Adding Source: " << tmp << std::endl,
  43. this->Coverage.Quiet);
  44. }
  45. }
  46. void StartElement(const std::string& name, const char** atts) override
  47. {
  48. std::string FoundSource;
  49. std::string finalpath;
  50. if (name == "source") {
  51. this->InSource = true;
  52. } else if (name == "sources") {
  53. this->InSources = true;
  54. } else if (name == "class") {
  55. int tagCount = 0;
  56. while (true) {
  57. if (strcmp(atts[tagCount], "filename") == 0) {
  58. cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
  59. "Reading file: " << atts[tagCount + 1]
  60. << std::endl,
  61. this->Coverage.Quiet);
  62. std::string filename = atts[tagCount + 1];
  63. this->CurFileName.clear();
  64. // Check if this is an absolute path that falls within our
  65. // source or binary directories.
  66. for (std::string const& filePath : FilePaths) {
  67. if (filename.find(filePath) == 0) {
  68. this->CurFileName = filename;
  69. break;
  70. }
  71. }
  72. if (this->CurFileName.empty()) {
  73. // Check if this is a path that is relative to our source or
  74. // binary directories.
  75. for (std::string const& filePath : FilePaths) {
  76. finalpath = filePath + "/" + filename;
  77. if (cmSystemTools::FileExists(finalpath)) {
  78. this->CurFileName = finalpath;
  79. break;
  80. }
  81. }
  82. }
  83. cmsys::ifstream fin(this->CurFileName.c_str());
  84. if (this->CurFileName.empty() || !fin) {
  85. this->CurFileName =
  86. this->Coverage.BinaryDir + "/" + atts[tagCount + 1];
  87. fin.open(this->CurFileName.c_str());
  88. if (!fin) {
  89. cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
  90. "Skipping system file " << filename
  91. << std::endl,
  92. this->Coverage.Quiet);
  93. this->SkipThisClass = true;
  94. break;
  95. }
  96. }
  97. std::string line;
  98. FileLinesType& curFileLines =
  99. this->Coverage.TotalCoverage[this->CurFileName];
  100. while (cmSystemTools::GetLineFromStream(fin, line)) {
  101. curFileLines.push_back(-1);
  102. }
  103. break;
  104. }
  105. ++tagCount;
  106. }
  107. } else if (name == "line") {
  108. int tagCount = 0;
  109. int curNumber = -1;
  110. int curHits = -1;
  111. while (true) {
  112. if (this->SkipThisClass) {
  113. break;
  114. }
  115. if (strcmp(atts[tagCount], "hits") == 0) {
  116. curHits = atoi(atts[tagCount + 1]);
  117. } else if (strcmp(atts[tagCount], "number") == 0) {
  118. curNumber = atoi(atts[tagCount + 1]);
  119. }
  120. if (curHits > -1 && curNumber > 0) {
  121. FileLinesType& curFileLines =
  122. this->Coverage.TotalCoverage[this->CurFileName];
  123. {
  124. curFileLines[curNumber - 1] = curHits;
  125. }
  126. break;
  127. }
  128. ++tagCount;
  129. }
  130. }
  131. }
  132. private:
  133. bool InSources;
  134. bool InSource;
  135. bool SkipThisClass;
  136. std::vector<std::string> FilePaths;
  137. typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector
  138. FileLinesType;
  139. cmCTest* CTest;
  140. cmCTestCoverageHandlerContainer& Coverage;
  141. std::string CurFileName;
  142. };
  143. cmParseCoberturaCoverage::cmParseCoberturaCoverage(
  144. cmCTestCoverageHandlerContainer& cont, cmCTest* ctest)
  145. : Coverage(cont)
  146. , CTest(ctest)
  147. {
  148. }
  149. bool cmParseCoberturaCoverage::ReadCoverageXML(const char* xmlFile)
  150. {
  151. cmParseCoberturaCoverage::XMLParser parser(this->CTest, this->Coverage);
  152. parser.ParseFile(xmlFile);
  153. return true;
  154. }