| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 | #include "cmStandardIncludes.h"#include "cmSystemTools.h"#include "cmParsePHPCoverage.h"#include <cmsys/Directory.hxx>#include <cmsys/FStream.hxx>/*  To setup coverage for php.  - edit php.ini to add auto prepend and append php files from phpunit  auto_prepend_file =  auto_append_file =  - run the tests  - run this program on all the files in c:/tmp*/cmParsePHPCoverage::cmParsePHPCoverage(cmCTestCoverageHandlerContainer& cont,    cmCTest* ctest)    :Coverage(cont), CTest(ctest){}bool cmParsePHPCoverage::ReadUntil(std::istream& in, char until){  char c = 0;  while(in.get(c) && c != until)    {    }  if(c != until)    {    return false;    }  return true;}bool cmParsePHPCoverage::ReadCoverageArray(std::istream& in,                                           std::string const& fileName){  cmCTestCoverageHandlerContainer::SingleFileCoverageVector& coverageVector    = this->Coverage.TotalCoverage[fileName];  char c;  char buf[4];  in.read(buf, 3);  buf[3] = 0;  if(strcmp(buf, ";a:") != 0)    {    cmCTestLog(this->CTest, ERROR_MESSAGE,               "failed to read start of coverage array, found : "               << buf << "\n");    return false;    }  int size = 0;  if(!this->ReadInt(in, size))    {    cmCTestLog(this->CTest, ERROR_MESSAGE,               "failed to read size ");    return false;    }  if(!in.get(c) && c == '{')    {    cmCTestLog(this->CTest, ERROR_MESSAGE,               "failed to read open {\n");    return false;    }  for(int i =0; i < size; i++)    {    this->ReadUntil(in, ':');    int line = 0;    this->ReadInt(in, line);    // ok xdebug may have a bug here    // it seems to be 1 based but often times    // seems to have a 0'th line.    line--;    if(line < 0)      {      line = 0;      }    this->ReadUntil(in, ':');    int value = 0;    this->ReadInt(in, value);    // make sure the vector is the right size and is    // initialized with -1 for each line    while(coverageVector.size() <= static_cast<size_t>(line) )      {      coverageVector.push_back(-1);      }    // if value is less than 0, set it to zero    // TODO figure out the difference between    // -1 and -2 in xdebug coverage??  For now    // assume less than 0 is just not covered    // CDash expects -1 for non executable code (like comments)    // and 0 for uncovered code, and a positive value    // for number of times a line was executed    if(value < 0)      {      value = 0;      }    // if unset then set it to value    if(coverageVector[line] == -1)      {      coverageVector[line] = value;      }    // otherwise increment by value    else      {      coverageVector[line] += value;      }    }  return true;}bool cmParsePHPCoverage::ReadInt(std::istream& in, int& v){  std::string s;  char c = 0;  while(in.get(c) && c != ':' && c != ';')    {    s += c;    }  v = atoi(s.c_str());  return true;}bool cmParsePHPCoverage::ReadArraySize(std::istream& in, int& size){  char c = 0;  in.get(c);  if(c != 'a')    {    return false;    }  if(in.get(c) && c == ':')    {    if(this->ReadInt(in, size))      {      return true;      }    }  return false;}bool cmParsePHPCoverage::ReadFileInformation(std::istream& in){  char buf[4];  in.read(buf, 2);  buf[2] = 0;  if(strcmp(buf, "s:") != 0)    {    cmCTestLog(this->CTest, ERROR_MESSAGE,               "failed to read start of file info found: [" << buf << "]\n");    return false;    }  char c;  int size = 0;  if(this->ReadInt(in, size))    {    size++; // add one for null termination    char* s = new char[size+1];    // read open quote    if(in.get(c) && c != '"')      {      delete[] s;      return false;      }    // read the string data    in.read(s, size-1);    s[size-1] = 0;    std::string fileName = s;    delete [] s;    // read close quote    if(in.get(c) && c != '"')      {      cmCTestLog(this->CTest, ERROR_MESSAGE,                 "failed to read close quote\n"                 << "read [" << c << "]\n");      return false;      }    if(!this->ReadCoverageArray(in, fileName) )      {      cmCTestLog(this->CTest, ERROR_MESSAGE,                 "failed to read coverage array for file: "                 << fileName << "\n");      return false;      }    return true;    }  return false;}bool cmParsePHPCoverage::ReadPHPData(const char* file){  cmsys::ifstream in(file);  if(!in)    {    return false;    }  int size = 0;  this->ReadArraySize(in, size);  char c = 0;  in.get(c);  if(c != '{')    {    cmCTestLog(this->CTest, ERROR_MESSAGE,               "failed to read open array\n");    return false;    }  for(int i =0; i < size; i++)    {    if(!this->ReadFileInformation(in))      {      cmCTestLog(this->CTest, ERROR_MESSAGE,                 "Failed to read file #" << i << "\n");      return false;      }    in.get(c);    if(c != '}')      {      cmCTestLog(this->CTest, ERROR_MESSAGE,                 "failed to read close array\n");      return false;      }    }  return true;}bool cmParsePHPCoverage::ReadPHPCoverageDirectory(const char* d){  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(!this->ReadPHPData(path.c_str()))        {        return false;        }      }    }  return true;}
 |