summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Hoffman <bill.hoffman@kitware.com>2010-05-25 13:23:25 (GMT)
committerBill Hoffman <bill.hoffman@kitware.com>2010-05-25 13:23:25 (GMT)
commit1d4e121d9cdb0b250c49a9d0d8d5f726ed7c69d4 (patch)
treed0e540c8b2cce79c91b3684e173a9d85c9bd2014
parent3d784cc7528672b68e07e65c7287d4db1a12b79f (diff)
downloadCMake-1d4e121d9cdb0b250c49a9d0d8d5f726ed7c69d4.zip
CMake-1d4e121d9cdb0b250c49a9d0d8d5f726ed7c69d4.tar.gz
CMake-1d4e121d9cdb0b250c49a9d0d8d5f726ed7c69d4.tar.bz2
Add php coverage to ctest.
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx34
-rw-r--r--Source/CTest/cmCTestCoverageHandler.h60
-rw-r--r--Source/CTest/cmParsePHPCoverage.cxx252
-rw-r--r--Source/CTest/cmParsePHPCoverage.h48
5 files changed, 334 insertions, 62 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 49cbda7..dc73cec 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -366,6 +366,7 @@ SET(CTEST_SRCS cmCTest.cxx
CTest/cmCTestConfigureHandler.cxx
CTest/cmCTestCoverageCommand.cxx
CTest/cmCTestCoverageHandler.cxx
+ CTest/cmParsePHPCoverage.cxx
CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
CTest/cmCTestGenericHandler.cxx
CTest/cmCTestHandlerCommand.cxx
@@ -502,4 +503,3 @@ IF(APPLE)
ENDIF(APPLE)
INSTALL_FILES(${CMAKE_DATA_DIR}/include cmCPluginAPI.h)
-
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index da5aed0..3235bfd 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -10,6 +10,7 @@
See the License for more information.
============================================================================*/
#include "cmCTestCoverageHandler.h"
+#include "cmParsePHPCoverage.h"
#include "cmCTest.h"
#include "cmake.h"
#include "cmMakefile.h"
@@ -126,20 +127,6 @@ private:
//----------------------------------------------------------------------
-//**********************************************************************
-class cmCTestCoverageHandlerContainer
-{
-public:
- int Error;
- std::string SourceDir;
- std::string BinaryDir;
- typedef std::vector<int> SingleFileCoverageVector;
- typedef std::map<std::string, SingleFileCoverageVector> TotalCoverageMap;
- TotalCoverageMap TotalCoverage;
- std::ostream* OFS;
-};
-//**********************************************************************
-//----------------------------------------------------------------------
//----------------------------------------------------------------------
cmCTestCoverageHandler::cmCTestCoverageHandler()
@@ -395,6 +382,11 @@ int cmCTestCoverageHandler::ProcessHandler()
{
return error;
}
+ file_count += this->HandlePHPCoverage(&cont);
+ if ( file_count < 0 )
+ {
+ return error;
+ }
error = cont.Error;
std::set<std::string> uncovered = this->FindUncoveredFiles(&cont);
@@ -524,7 +516,7 @@ int cmCTestCoverageHandler::ProcessHandler()
{
cmOStringStream ostr;
ostr << "Problem reading source file: " << fullFileName.c_str()
- << " line:" << cc;
+ << " line:" << cc << " out total: " << fcov.size()-1;
errorsWhileAccumulating.push_back(ostr.str());
error ++;
break;
@@ -748,6 +740,18 @@ bool IsFileInDir(const std::string &infile, const std::string &indir)
}
//----------------------------------------------------------------------
+int cmCTestCoverageHandler::HandlePHPCoverage(
+ cmCTestCoverageHandlerContainer* cont)
+{
+ cmParsePHPCoverage cov(*cont, this->CTest);
+ std::string coverageDir = this->CTest->GetBinaryDir() + "/xdebugCoverage";
+ if(cmSystemTools::FileIsDirectory(coverageDir.c_str()))
+ {
+ cov.ReadPHPCoverageDirectory(coverageDir.c_str());
+ }
+ return static_cast<int>(cont->TotalCoverage.size());
+}
+//----------------------------------------------------------------------
int cmCTestCoverageHandler::HandleGCovCoverage(
cmCTestCoverageHandlerContainer* cont)
{
diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h
index f0564e8..d3e8503 100644
--- a/Source/CTest/cmCTestCoverageHandler.h
+++ b/Source/CTest/cmCTestCoverageHandler.h
@@ -20,8 +20,17 @@
#include <cmsys/RegularExpression.hxx>
class cmGeneratedFileStream;
-class cmCTestCoverageHandlerContainer;
-
+class cmCTestCoverageHandlerContainer
+{
+public:
+ int Error;
+ std::string SourceDir;
+ std::string BinaryDir;
+ typedef std::vector<int> SingleFileCoverageVector;
+ typedef std::map<std::string, SingleFileCoverageVector> TotalCoverageMap;
+ TotalCoverageMap TotalCoverage;
+ std::ostream* OFS;
+};
/** \class cmCTestCoverageHandler
* \brief A class that handles coverage computaiton for ctest
*
@@ -59,6 +68,9 @@ private:
int HandleGCovCoverage(cmCTestCoverageHandlerContainer* cont);
void FindGCovFiles(std::vector<std::string>& files);
+ //! Handle coverage using xdebug php coverage
+ int HandlePHPCoverage(cmCTestCoverageHandlerContainer* cont);
+
//! Handle coverage using Bullseye
int HandleBullseyeCoverage(cmCTestCoverageHandlerContainer* cont);
int RunBullseyeSourceSummary(cmCTestCoverageHandlerContainer* cont);
@@ -94,54 +106,10 @@ private:
std::set<std::string> FindUncoveredFiles(
cmCTestCoverageHandlerContainer* cont);
-
- struct cmCTestCoverage
- {
- cmCTestCoverage()
- {
- this->AbsolutePath = "";
- this->FullPath = "";
- this->Covered = false;
- this->Tested = 0;
- this->UnTested = 0;
- this->Lines.clear();
- this->Show = false;
- }
- cmCTestCoverage(const cmCTestCoverage& rhs) :
- AbsolutePath(rhs.AbsolutePath),
- FullPath(rhs.FullPath),
- Covered(rhs.Covered),
- Tested(rhs.Tested),
- UnTested(rhs.UnTested),
- Lines(rhs.Lines),
- Show(rhs.Show)
- {
- }
- cmCTestCoverage& operator=(const cmCTestCoverage& rhs)
- {
- this->AbsolutePath = rhs.AbsolutePath;
- this->FullPath = rhs.FullPath;
- this->Covered = rhs.Covered;
- this->Tested = rhs.Tested;
- this->UnTested = rhs.UnTested;
- this->Lines = rhs.Lines;
- this->Show = rhs.Show;
- return *this;
- }
- std::string AbsolutePath;
- std::string FullPath;
- bool Covered;
- int Tested;
- int UnTested;
- std::vector<int> Lines;
- bool Show;
- };
-
std::vector<cmStdString> CustomCoverageExclude;
std::vector<cmsys::RegularExpression> CustomCoverageExcludeRegex;
std::vector<cmStdString> ExtraCoverageGlobs;
- typedef std::map<std::string, cmCTestCoverage> CoverageMap;
// Map from source file to label ids.
class LabelSet: public std::set<int> {};
diff --git a/Source/CTest/cmParsePHPCoverage.cxx b/Source/CTest/cmParsePHPCoverage.cxx
new file mode 100644
index 0000000..32c1ec1
--- /dev/null
+++ b/Source/CTest/cmParsePHPCoverage.cxx
@@ -0,0 +1,252 @@
+#include "cmStandardIncludes.h"
+#include "cmSystemTools.h"
+#include "cmParsePHPCoverage.h"
+#include <cmsys/Directory.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::ifstream& in, char until)
+{
+ char c = 0;
+ while(in.get(c) && c != until)
+ {
+ }
+ if(c != until)
+ {
+ return false;
+ }
+ return true;
+}
+bool cmParsePHPCoverage::ReadCoverageArray(std::ifstream& in,
+ cmStdString 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::ifstream& 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::ifstream& 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::ifstream& 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 != '"')
+ {
+ return false;
+ }
+ // read the string data
+ in.read(s, size-1);
+ s[size-1] = 0;
+ cmStdString 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)
+{
+ std::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.c_str()))
+ {
+ std::string path = d;
+ path += "/";
+ path += file;
+ if(!this->ReadPHPData(path.c_str()))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
diff --git a/Source/CTest/cmParsePHPCoverage.h b/Source/CTest/cmParsePHPCoverage.h
new file mode 100644
index 0000000..ce5741d
--- /dev/null
+++ b/Source/CTest/cmParsePHPCoverage.h
@@ -0,0 +1,48 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2009 Kitware, Inc.
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+
+#ifndef cmParsePHPCoverage_h
+#define cmParsePHPCoverage_h
+
+#include "cmStandardIncludes.h"
+#include "cmCTestCoverageHandler.h"
+
+/** \class cmParsePHPCoverage
+ * \brief Parse xdebug PHP coverage information
+ *
+ * This class is used to parse php coverage information produced
+ * by xdebug. The data is stored as a php dump of the array
+ * return by xdebug coverage. It is an array of arrays.
+ */
+class cmParsePHPCoverage
+{
+public:
+ cmParsePHPCoverage(cmCTestCoverageHandlerContainer& cont,
+ cmCTest* ctest);
+ bool ReadPHPCoverageDirectory(const char* dir);
+ void PrintCoverage();
+private:
+ bool ReadPHPData(const char* file);
+ bool ReadArraySize(std::ifstream& in, int& size);
+ bool ReadFileInformation(std::ifstream& in);
+ bool ReadInt(std::ifstream& in, int& v);
+ bool ReadCoverageArray(std::ifstream& in, cmStdString const&);
+ bool ReadUntil(std::ifstream& in, char until);
+ typedef std::map<int, int> FileLineCoverage;
+ std::map<cmStdString, FileLineCoverage> FileToCoverage;
+ std::map<int, int> FileCoverage;
+ cmCTestCoverageHandlerContainer& Coverage;
+ cmCTest* CTest;
+};
+
+
+#endif