| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 | #include "cmStandardIncludes.h"#include <stdio.h>#include <stdlib.h>#include "cmSystemTools.h"#include "cmParseCacheCoverage.h"#include <cmsys/Directory.hxx>#include <cmsys/Glob.hxx>#include <cmsys/FStream.hxx>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 futurevoid 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(cmCTestCoverageHandlerContainer::SingleFileCoverageVector::iterator i=          v.begin(); i != v.end(); ++i)      {      if(*i > 0)        {        nothing = false;        break;        }      }    if(nothing)      {      cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,                 "No coverage found in: " << ci->first                 << std::endl);      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.size() == 0)      {      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 = "";        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 = ""; // at the end of this routine        filepath = "";        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.size() == 0)      {      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;}
 |