summaryrefslogtreecommitdiffstats
path: root/Source/CTest
diff options
context:
space:
mode:
authorPatrick Reynolds <patrick.reynolds@kitware.com>2013-09-27 14:42:39 (GMT)
committerBrad King <brad.king@kitware.com>2013-10-08 13:20:30 (GMT)
commitd0ec3a01a61f259768d31fc20791780807e1788e (patch)
treed5dfba622c1739ddedadfe7190eda5c7959a27f5 /Source/CTest
parent6ed8504ea5633932e5db3a5a70853a763df7af50 (diff)
downloadCMake-d0ec3a01a61f259768d31fc20791780807e1788e.zip
CMake-d0ec3a01a61f259768d31fc20791780807e1788e.tar.gz
CMake-d0ec3a01a61f259768d31fc20791780807e1788e.tar.bz2
Adding support for the Python coverage.py tool.
This assumes that coverage.py has been run in such a way to produce its standard XML output. This uses the Cobertura schema and should be somewhat generalizable.
Diffstat (limited to 'Source/CTest')
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx34
-rw-r--r--Source/CTest/cmCTestCoverageHandler.h4
-rw-r--r--Source/CTest/cmParsePythonCoverage.cxx113
-rw-r--r--Source/CTest/cmParsePythonCoverage.h48
4 files changed, 199 insertions, 0 deletions
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 20aded2..ef071b9 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -11,6 +11,7 @@
============================================================================*/
#include "cmCTestCoverageHandler.h"
#include "cmParsePHPCoverage.h"
+#include "cmParsePythonCoverage.h"
#include "cmParseGTMCoverage.h"
#include "cmParseCacheCoverage.h"
#include "cmCTest.h"
@@ -392,6 +393,13 @@ int cmCTestCoverageHandler::ProcessHandler()
{
return error;
}
+ file_count += this->HandlePythonCoverage(&cont);
+ error = cont.Error;
+ if ( file_count < 0 )
+ {
+ return error;
+ }
+
file_count += this->HandleMumpsCoverage(&cont);
error = cont.Error;
if ( file_count < 0 )
@@ -761,6 +769,32 @@ int cmCTestCoverageHandler::HandlePHPCoverage(
}
return static_cast<int>(cont->TotalCoverage.size());
}
+
+//----------------------------------------------------------------------
+int cmCTestCoverageHandler::HandlePythonCoverage(
+ cmCTestCoverageHandlerContainer* cont)
+{
+ cmParsePythonCoverage cov(*cont, this->CTest);
+
+ // Assume the coverage.xml is in the source directory
+ std::string coverageXMLFile = this->CTest->GetBinaryDir() + "/coverage.xml";
+
+ if(cmSystemTools::FileExists(coverageXMLFile.c_str()))
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Parsing coverage.py XML file: " << coverageXMLFile
+ << std::endl);
+ cov.ReadCoverageXML(coverageXMLFile.c_str());
+ }
+ else
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Cannot find coverage.py XML file: " << coverageXMLFile
+ << std::endl);
+ }
+ return static_cast<int>(cont->TotalCoverage.size());
+}
+
//----------------------------------------------------------------------
int cmCTestCoverageHandler::HandleMumpsCoverage(
cmCTestCoverageHandlerContainer* cont)
diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h
index 92b0b22..3506928 100644
--- a/Source/CTest/cmCTestCoverageHandler.h
+++ b/Source/CTest/cmCTestCoverageHandler.h
@@ -70,6 +70,10 @@ private:
//! Handle coverage using xdebug php coverage
int HandlePHPCoverage(cmCTestCoverageHandlerContainer* cont);
+
+ //! Handle coverage for Python with coverage.py
+ int HandlePythonCoverage(cmCTestCoverageHandlerContainer* cont);
+
//! Handle coverage for mumps
int HandleMumpsCoverage(cmCTestCoverageHandlerContainer* cont);
diff --git a/Source/CTest/cmParsePythonCoverage.cxx b/Source/CTest/cmParsePythonCoverage.cxx
new file mode 100644
index 0000000..a086f13
--- /dev/null
+++ b/Source/CTest/cmParsePythonCoverage.cxx
@@ -0,0 +1,113 @@
+#include "cmStandardIncludes.h"
+#include "cmSystemTools.h"
+#include "cmXMLParser.h"
+#include "cmParsePythonCoverage.h"
+#include <cmsys/Directory.hxx>
+
+
+//----------------------------------------------------------------------------
+class cmParsePythonCoverage::XMLParser: public cmXMLParser
+{
+public:
+ XMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont)
+ : CTest(ctest), Coverage(cont)
+ {
+ }
+
+ virtual ~XMLParser()
+ {
+ }
+
+protected:
+
+ virtual void StartElement(const char* name, const char** atts)
+ {
+ if(strcmp(name, "class") == 0)
+ {
+ int tagCount = 0;
+ while(true)
+ {
+ if(strcmp(atts[tagCount], "filename") == 0)
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Reading file: "
+ << atts[tagCount+1] << std::endl);
+ this->CurFileName = this->Coverage.SourceDir + "/" +
+ atts[tagCount+1];
+ FileLinesType& curFileLines =
+ this->Coverage.TotalCoverage[this->CurFileName];
+ std::ifstream fin(this->CurFileName.c_str());
+ if(!fin)
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Python Coverage: Error opening " << this->CurFileName
+ << std::endl);
+ this->Coverage.Error++;
+ break;
+ }
+
+ std::string line;
+ curFileLines.push_back(-1);
+ while(cmSystemTools::GetLineFromStream(fin, line))
+ {
+ curFileLines.push_back(-1);
+ }
+
+ break;
+ }
+ ++tagCount;
+ }
+ }
+ else if(strcmp(name, "line") == 0)
+ {
+ int tagCount = 0;
+ int curNumber = -1;
+ int curHits = -1;
+ while(true)
+ {
+ if(strcmp(atts[tagCount], "hits") == 0)
+ {
+ curHits = atoi(atts[tagCount+1]);
+ }
+ else if(strcmp(atts[tagCount], "number") == 0)
+ {
+ curNumber = atoi(atts[tagCount+1]);
+ }
+
+ if(curHits > -1 && curNumber > -1)
+ {
+ FileLinesType& curFileLines =
+ this->Coverage.TotalCoverage[this->CurFileName];
+ curFileLines[curNumber] = curHits;
+ break;
+ }
+ ++tagCount;
+ }
+ }
+ }
+
+ virtual void EndElement(const char*) {}
+
+private:
+
+ typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector
+ FileLinesType;
+ cmCTest* CTest;
+ cmCTestCoverageHandlerContainer& Coverage;
+ std::string CurFileName;
+
+};
+
+
+cmParsePythonCoverage::cmParsePythonCoverage(
+ cmCTestCoverageHandlerContainer& cont,
+ cmCTest* ctest)
+ :Coverage(cont), CTest(ctest)
+{
+}
+
+bool cmParsePythonCoverage::ReadCoverageXML(const char* xmlFile)
+{
+ cmParsePythonCoverage::XMLParser parser(this->CTest, this->Coverage);
+ parser.ParseFile(xmlFile);
+ return true;
+}
diff --git a/Source/CTest/cmParsePythonCoverage.h b/Source/CTest/cmParsePythonCoverage.h
new file mode 100644
index 0000000..668c7f9
--- /dev/null
+++ b/Source/CTest/cmParsePythonCoverage.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 cmParsePythonCoverage_h
+#define cmParsePythonCoverage_h
+
+#include "cmStandardIncludes.h"
+#include "cmCTestCoverageHandler.h"
+
+/** \class cmParsePythonCoverage
+ * \brief Parse coverage.py Python coverage information
+ *
+ * This class is used to parse the output of the coverage.py tool that
+ * is currently maintained by Ned Batchelder. That tool has a command
+ * that produces xml output in the format typically output by the common
+ * Java-based Cobertura coverage application. This helper class parses
+ * that XML file to fill the coverage-handler container.
+ */
+class cmParsePythonCoverage
+{
+public:
+
+ //! Create the coverage parser by passing in the coverage handler
+ //! container and the cmCTest object
+ cmParsePythonCoverage(cmCTestCoverageHandlerContainer& cont,
+ cmCTest* ctest);
+
+ //! Read the XML produced by running `coverage xml`
+ bool ReadCoverageXML(const char* xmlFile);
+
+private:
+
+ class XMLParser;
+ cmCTestCoverageHandlerContainer& Coverage;
+ cmCTest* CTest;
+ std::string CurFileName;
+};
+
+#endif