123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- #include "cmParseCacheCoverage.h"
- #include "cmCTest.h"
- #include "cmCTestCoverageHandler.h"
- #include "cmSystemTools.h"
- #include "cmsys/Directory.hxx"
- #include "cmsys/FStream.hxx"
- #include <map>
- #include <stdio.h>
- #include <stdlib.h>
- #include <utility>
- cmParseCacheCoverage::cmParseCacheCoverage(
- cmCTestCoverageHandlerContainer& cont, cmCTest* ctest)
- : cmParseMumpsCoverage(cont, ctest)
- {
- }
- bool cmParseCacheCoverage::LoadCoverageData(const char* d)
- {
- // load all the .mcov files in the specified directory
- cmsys::Directory dir;
- if (!dir.Load(d)) {
- return false;
- }
- size_t numf;
- unsigned int i;
- numf = dir.GetNumberOfFiles();
- for (i = 0; i < numf; i++) {
- std::string file = dir.GetFile(i);
- if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
- std::string path = d;
- path += "/";
- path += file;
- if (cmSystemTools::GetFilenameLastExtension(path) == ".cmcov") {
- if (!this->ReadCMCovFile(path.c_str())) {
- return false;
- }
- }
- }
- }
- return true;
- }
- // not currently used, but leave it in case we want it in the future
- void cmParseCacheCoverage::RemoveUnCoveredFiles()
- {
- // loop over the coverage data computed and remove all files
- // that only have -1 or 0 for the lines.
- cmCTestCoverageHandlerContainer::TotalCoverageMap::iterator ci =
- this->Coverage.TotalCoverage.begin();
- while (ci != this->Coverage.TotalCoverage.end()) {
- cmCTestCoverageHandlerContainer::SingleFileCoverageVector& v = ci->second;
- bool nothing = true;
- for (int i : v) {
- if (i > 0) {
- nothing = false;
- break;
- }
- }
- if (nothing) {
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "No coverage found in: " << ci->first << std::endl,
- this->Coverage.Quiet);
- this->Coverage.TotalCoverage.erase(ci++);
- } else {
- ++ci;
- }
- }
- }
- bool cmParseCacheCoverage::SplitString(std::vector<std::string>& args,
- std::string const& line)
- {
- std::string::size_type pos1 = 0;
- std::string::size_type pos2 = line.find(',', 0);
- if (pos2 == std::string::npos) {
- return false;
- }
- std::string arg;
- while (pos2 != std::string::npos) {
- arg = line.substr(pos1, pos2 - pos1);
- args.push_back(arg);
- pos1 = pos2 + 1;
- pos2 = line.find(',', pos1);
- }
- arg = line.substr(pos1);
- args.push_back(arg);
- return true;
- }
- bool cmParseCacheCoverage::ReadCMCovFile(const char* file)
- {
- cmsys::ifstream in(file);
- if (!in) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Can not open : " << file << "\n");
- return false;
- }
- std::string line;
- std::vector<std::string> separateLine;
- if (!cmSystemTools::GetLineFromStream(in, line)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Empty file : "
- << file << " referenced in this line of cmcov data:\n"
- "["
- << line << "]\n");
- return false;
- }
- separateLine.clear();
- this->SplitString(separateLine, line);
- if (separateLine.size() != 4 || separateLine[0] != "Routine" ||
- separateLine[1] != "Line" || separateLine[2] != "RtnLine" ||
- separateLine[3] != "Code") {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Bad first line of cmcov file : " << file << " line:\n"
- "["
- << line << "]\n");
- }
- std::string routine;
- std::string filepath;
- while (cmSystemTools::GetLineFromStream(in, line)) {
- // clear out line argument vector
- separateLine.clear();
- // parse the comma separated line
- this->SplitString(separateLine, line);
- // might have more because code could have a quoted , in it
- // but we only care about the first 3 args anyway
- if (separateLine.size() < 4) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Bad line of cmcov file expected at least 4 found: "
- << separateLine.size() << " " << file << " line:\n"
- "["
- << line << "]\n");
- for (std::string::size_type i = 0; i < separateLine.size(); ++i) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "" << separateLine[1] << " ");
- }
- cmCTestLog(this->CTest, ERROR_MESSAGE, "\n");
- return false;
- }
- // if we do not have a routine yet, then it should be
- // the first argument in the vector
- if (routine.empty()) {
- routine = separateLine[0];
- // Find the full path to the file
- if (!this->FindMumpsFile(routine, filepath)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Could not find mumps file for routine: " << routine
- << "\n");
- filepath.clear();
- continue; // move to next line
- }
- }
- // if we have a routine name, check for end of routine
- else {
- // Totals in arg 0 marks the end of a routine
- if (separateLine[0].substr(0, 6) == "Totals") {
- routine.clear(); // at the end of this routine
- filepath.clear();
- continue; // move to next line
- }
- }
- // if the file path was not found for the routine
- // move to next line. We should have already warned
- // after the call to FindMumpsFile that we did not find
- // it, so don't report again to cut down on output
- if (filepath.empty()) {
- continue;
- }
- // now we are ready to set the coverage from the line of data
- cmCTestCoverageHandlerContainer::SingleFileCoverageVector& coverageVector =
- this->Coverage.TotalCoverage[filepath];
- std::string::size_type linenumber = atoi(separateLine[1].c_str()) - 1;
- int count = atoi(separateLine[2].c_str());
- if (linenumber > coverageVector.size()) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Parse error line is greater than number of lines in file: "
- << linenumber << " " << filepath << "\n");
- continue; // skip setting count to avoid crash
- }
- // now add to count for linenumber
- // for some reason the cache coverage adds extra lines to the
- // end of the file in some cases. Since they do not exist, we will
- // mark them as non executable
- while (linenumber >= coverageVector.size()) {
- coverageVector.push_back(-1);
- }
- // Accounts for lines that were previously marked
- // as non-executable code (-1). if the parser comes back with
- // a non-zero count, increase the count by 1 to push the line
- // into the executable code set in addition to the count found.
- if (coverageVector[linenumber] == -1 && count > 0) {
- coverageVector[linenumber] += count + 1;
- } else {
- coverageVector[linenumber] += count;
- }
- }
- return true;
- }
|