summaryrefslogtreecommitdiffstats
path: root/Source/CTest/cmParseDelphiCoverage.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CTest/cmParseDelphiCoverage.cxx')
-rw-r--r--Source/CTest/cmParseDelphiCoverage.cxx253
1 files changed, 253 insertions, 0 deletions
diff --git a/Source/CTest/cmParseDelphiCoverage.cxx b/Source/CTest/cmParseDelphiCoverage.cxx
new file mode 100644
index 0000000..ad71c85
--- /dev/null
+++ b/Source/CTest/cmParseDelphiCoverage.cxx
@@ -0,0 +1,253 @@
+#include "cmStandardIncludes.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "cmSystemTools.h"
+#include "cmXMLParser.h"
+#include "cmParseDelphiCoverage.h"
+#include <cmsys/Directory.hxx>
+#include <cmsys/Glob.hxx>
+#include <cmsys/FStream.hxx>
+
+
+class cmParseDelphiCoverage::HTMLParser
+{
+public:
+ typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector
+ FileLinesType;
+ HTMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont)
+ : CTest(ctest), Coverage(cont)
+ {
+ }
+
+ virtual ~HTMLParser()
+ {
+ }
+
+ bool initializeDelphiFile(const std::string filename,
+ cmParseDelphiCoverage::HTMLParser::FileLinesType &coverageVector)
+ {
+ std::string line;
+ size_t comPos;
+ size_t semiPos;
+ bool blockComFlag= false;
+ bool lineComFlag= false;
+ std::vector<std::string> beginSet;
+ cmsys::ifstream in(filename.c_str());
+ if(!in)
+ {
+ return false;
+ }
+ while(cmSystemTools::GetLineFromStream(in, line))
+ {
+ lineComFlag=false;
+ // Unique cases found in lines.
+ size_t beginPos = line.find("begin");
+
+ //Check that the begin is the first non-space string on the line
+ if( (beginPos == line.find_first_not_of(' ')) && beginPos != line.npos )
+ {
+ beginSet.push_back("begin");
+ coverageVector.push_back(-1);
+ continue;
+ }
+ else if(line.find('{') != line.npos)
+ {
+ blockComFlag=true;
+ }
+ else if(line.find('}') != line.npos)
+ {
+ blockComFlag=false;
+ coverageVector.push_back(-1);
+ continue;
+ }
+ else if((line.find("end;") != line.npos)
+ && (beginSet.size() > 0))
+ {
+ beginSet.pop_back();
+ coverageVector.push_back(-1);
+ continue;
+ }
+
+ // This checks for comments after lines of code, finding the
+ // comment symbol after the ending semicolon.
+ comPos = line.find("//");
+ if(comPos != line.npos)
+ {
+ semiPos= line.find(';');
+ if(comPos < semiPos)
+ {
+ lineComFlag=true;
+ }
+ }
+ //Based up what was found, add a line to the coverageVector
+ if((beginSet.size() > 0) && line != "" && !blockComFlag
+ && !lineComFlag)
+ {
+ coverageVector.push_back(0);
+ }
+ else
+ {
+ coverageVector.push_back(-1);
+ }
+ }
+ return true;
+ }
+ bool ParseFile(const char* file)
+ {
+ std::string line=file;
+ std::string lineresult;
+ std::string lastroutine;
+ std::string filename;
+ std::string filelineoffset;
+ size_t afterLineNum = 0;
+ size_t lastoffset = 0;
+ size_t endcovpos = 0;
+ size_t endnamepos = 0;
+ size_t pos = 0;
+
+ /*
+ * This first 'while' section goes through the found HTML
+ * file name and attempts to capture the source file name
+ * which is set as part of the HTML file name: the name of
+ * the file is found in parenthesis '()'
+ *
+ * See test HTML file name: UTCovTest(UTCovTest.pas).html.
+ *
+ * Find the text inside each pair of parenthesis and check
+ * to see if it ends in '.pas'. If it can't be found,
+ * exit the function.
+ */
+ while(true)
+ {
+ lastoffset = line.find('(',pos);
+ if(lastoffset==line.npos)
+ {
+ cmCTestLog(this->CTest,HANDLER_VERBOSE_OUTPUT,
+ endnamepos << "File not found " << lastoffset << std::endl);
+ return false;
+ }
+ endnamepos = line.find(')',lastoffset);
+ filename = line.substr(lastoffset+1,
+ (endnamepos-1)-lastoffset);
+ if(filename.find(".pas") != filename.npos)
+ {
+ cmCTestLog(this->CTest,HANDLER_VERBOSE_OUTPUT,
+ "Coverage found for file: " << filename << std::endl);
+ break;
+ }
+ pos = lastoffset+1;
+ endnamepos = 0;
+ lastoffset =0;
+ }
+ /*
+ * Glob through the source directory for the
+ * file found above
+ */
+ cmsys::Glob gl;
+ gl.RecurseOn();
+ gl.RecurseThroughSymlinksOff();
+ std::string glob = Coverage.SourceDir + "*/" + filename;
+ gl.FindFiles(glob);
+ std::vector<std::string> const& files = gl.GetFiles();
+ if(files.size() == 0)
+ {
+ /*
+ * If that doesn't find any matching files
+ * return a failure.
+ */
+ cmCTestLog(this->CTest,HANDLER_VERBOSE_OUTPUT,
+ "Unable to find file matching" << glob << std::endl);
+ return false;
+ }
+ FileLinesType& coverageVector =
+ this->Coverage.TotalCoverage[files[0]];
+
+ /*
+ * Initialize the file to have all code between 'begin' and
+ * 'end' tags marked as executable
+ */
+
+ this->initializeDelphiFile(files[0],coverageVector);
+
+ cmsys::ifstream in(file);
+ if(!in)
+ {
+ return false;
+ }
+
+ /*
+ * Now read the HTML file, looking for the lines that have an
+ * "inline" in it. Then parse out the "class" value of that
+ * line to determine if the line is executed or not.
+ *
+ * Sample HTML line:
+ *
+ * <tr class="covered"><td>47</td><td><pre style="display:inline;">
+ * &nbsp;CheckEquals(1,2-1);</pre></td></tr>
+ *
+ */
+
+ while( cmSystemTools::GetLineFromStream(in, line))
+ {
+ if(line.find("inline") == line.npos)
+ {
+ continue;
+ }
+
+ lastoffset = line.find("class=");
+ endcovpos = line.find(">",lastoffset);
+ lineresult = line.substr(lastoffset+7,(endcovpos-8)-lastoffset);
+
+ if(lineresult == "covered")
+ {
+ afterLineNum = line.find('<',endcovpos+5);
+ filelineoffset= line.substr(endcovpos+5,
+ afterLineNum-(endcovpos+5));
+ coverageVector[atoi(filelineoffset.c_str())-1] = 1;
+ }
+ }
+ return true;
+ }
+
+
+ private:
+ cmCTest* CTest;
+ cmCTestCoverageHandlerContainer& Coverage;
+};
+
+cmParseDelphiCoverage::cmParseDelphiCoverage(
+ cmCTestCoverageHandlerContainer& cont, cmCTest* ctest)
+ :Coverage(cont), CTest(ctest)
+ {
+ }
+
+bool cmParseDelphiCoverage::LoadCoverageData(
+ const std::vector<std::string> files)
+ {
+ size_t i;
+ std::string path;
+ size_t numf = files.size();
+ for (i = 0; i < numf; i++)
+ {
+ path = files[i];
+
+ cmCTestLog(this->CTest,HANDLER_VERBOSE_OUTPUT,
+ "Reading HTML File " << path << std::endl);
+ if(cmSystemTools::GetFilenameLastExtension(path) == ".html")
+ {
+ if(!this->ReadDelphiHTML(path.c_str()))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ };
+
+bool cmParseDelphiCoverage::ReadDelphiHTML(const char* file)
+ {
+ cmParseDelphiCoverage::HTMLParser
+ parser(this->CTest, this->Coverage);
+ parser.ParseFile(file);
+ return true;
+ };