[cmake-commits] andy committed cmCTestCoverageHandler.cxx 1.37 1.38 cmCTestCoverageHandler.h 1.13 1.14

cmake-commits at cmake.org cmake-commits at cmake.org
Thu Apr 26 23:20:14 EDT 2007


Update of /cvsroot/CMake/CMake/Source/CTest
In directory public:/mounts/ram/cvs-serv6452

Modified Files:
	cmCTestCoverageHandler.cxx cmCTestCoverageHandler.h 
Log Message:
ENH: Initial attempt to do python coverage. Hopefully will not break coverage on GCov


Index: cmCTestCoverageHandler.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/CTest/cmCTestCoverageHandler.cxx,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -d -r1.37 -r1.38
--- cmCTestCoverageHandler.cxx	25 Oct 2006 12:56:56 -0000	1.37
+++ cmCTestCoverageHandler.cxx	27 Apr 2007 03:20:12 -0000	1.38
@@ -33,6 +33,22 @@
 #define SAFEDIV(x,y) (((y)!=0)?((x)/(y)):(0))
 
 //----------------------------------------------------------------------
+//**********************************************************************
+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()
 {
 }
@@ -186,12 +202,12 @@
     return error;
     }
   
+  std::string coverage_start_time = this->CTest->CurrentTime();
+
   std::string sourceDir
     = this->CTest->GetCTestConfiguration("SourceDirectory");
   std::string binaryDir
     = this->CTest->GetCTestConfiguration("BuildDirectory");
-  std::string gcovCommand
-    = this->CTest->GetCTestConfiguration("CoverageCommand");
 
   cmGeneratedFileStream ofs;
   double elapsed_time_start = cmSystemTools::GetTime();
@@ -209,6 +225,298 @@
   std::string asfGlob = sourceDir + "/*";
   std::string abfGlob = binaryDir + "/*";
 
+  cmCTestLog(this->CTest, HANDLER_OUTPUT, "Performing coverage" << std::endl);
+
+  cmCTestCoverageHandlerContainer cont;
+  cont.Error = error;
+  cont.SourceDir = sourceDir;
+  cont.BinaryDir = binaryDir;
+  cont.OFS = &ofs;
+
+  int file_count = 0;
+
+  file_count += this->HandleGCovCoverage(&cont);
+  if ( file_count < 0 )
+    {
+    return error;
+    }
+  file_count += this->HandleTracePyCoverage(&cont);
+  if ( file_count < 0 )
+    {
+    return error;
+    }
+  error = cont.Error;
+
+
+  if ( file_count == 0 )
+    {
+    cmCTestLog(this->CTest, WARNING,
+      " Cannot find any coverage files. Ignoring Coverage request."
+      << std::endl);
+    return error;
+    }
+  cmGeneratedFileStream covSumFile;
+  cmGeneratedFileStream covLogFile;
+
+  if (!this->StartResultingXML("Coverage", covSumFile))
+    {
+    cmCTestLog(this->CTest, ERROR_MESSAGE,
+      "Cannot open coverage summary file." << std::endl);
+    return -1;
+    }
+
+  this->CTest->StartXML(covSumFile);
+  // Produce output xml files
+
+  covSumFile << "<Coverage>" << std::endl
+    << "\t<StartDateTime>" << coverage_start_time << "</StartDateTime>"
+    << std::endl;
+  int logFileCount = 0;
+  if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
+    {
+    return -1;
+    }
+  cmCTestCoverageHandlerContainer::TotalCoverageMap::iterator fileIterator;
+  int cnt = 0;
+  long total_tested = 0;
+  long total_untested = 0;
+  //std::string fullSourceDir = sourceDir + "/";
+  //std::string fullBinaryDir = binaryDir + "/";
+  cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
+  cmCTestLog(this->CTest, HANDLER_OUTPUT,
+    "   Acumulating results (each . represents one file):" << std::endl);
+  cmCTestLog(this->CTest, HANDLER_OUTPUT, "    ");
+
+  std::vector<std::string> errorsWhileAccumulating;
+
+  file_count = 0;
+  for ( fileIterator = cont.TotalCoverage.begin();
+    fileIterator != cont.TotalCoverage.end();
+    ++fileIterator )
+    {
+    cmCTestLog(this->CTest, HANDLER_OUTPUT, "." << std::flush);
+    file_count ++;
+    if ( file_count % 50 == 0 )
+      {
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, " processed: " << file_count
+        << " out of "
+        << cont.TotalCoverage.size() << std::endl);
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, "    ");
+      }
+    if ( cnt % 100 == 0 )
+      {
+      this->EndCoverageLogFile(covLogFile, logFileCount);
+      logFileCount ++;
+      if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
+        {
+        return -1;
+        }
+      }
+    const std::string fullFileName = fileIterator->first;
+    const std::string fileName
+      = cmSystemTools::GetFilenameName(fullFileName.c_str());
+    std::string fullFilePath
+      = cmSystemTools::GetFilenamePath(fullFileName.c_str());
+    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+      "Process file: " << fullFileName << std::endl);
+
+    cmSystemTools::ConvertToUnixSlashes(fullFilePath);
+
+    if ( !cmSystemTools::FileExists(fullFileName.c_str()) )
+      {
+      cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot find file: "
+        << fullFileName.c_str() << std::endl);
+      continue;
+      }
+
+    bool shouldIDoCoverage
+      = this->ShouldIDoCoverage(fullFileName.c_str(),
+        sourceDir.c_str(), binaryDir.c_str());
+    if ( !shouldIDoCoverage )
+      {
+      cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+        ".NoDartCoverage found, so skip coverage check for: "
+        << fullFileName.c_str()
+        << std::endl);
+      continue;
+      }
+
+    const cmCTestCoverageHandlerContainer::SingleFileCoverageVector& fcov
+      = fileIterator->second;
+    covLogFile << "\t<File Name=\""
+      << this->CTest->MakeXMLSafe(fileName.c_str())
+      << "\" FullPath=\"" << this->CTest->MakeXMLSafe(
+        this->CTest->GetShortPathToFile(
+          fileIterator->first.c_str())) << "\">" << std::endl
+      << "\t\t<Report>" << std::endl;
+
+    std::ifstream ifs(fullFileName.c_str());
+    if ( !ifs)
+      {
+      cmOStringStream ostr;
+      ostr <<  "Cannot open source file: " << fullFileName.c_str();
+      errorsWhileAccumulating.push_back(ostr.str());
+      error ++;
+      continue;
+      }
+
+    int tested = 0;
+    int untested = 0;
+
+    cmCTestCoverageHandlerContainer::SingleFileCoverageVector::size_type cc;
+    std::string line;
+    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+      "Actually perfoming coverage for: " << fullFileName << std::endl);
+    for ( cc= 0; cc < fcov.size(); cc ++ )
+      {
+      if ( !cmSystemTools::GetLineFromStream(ifs, line) &&
+        cc != fcov.size() -1 )
+        {
+        cmOStringStream ostr;
+        ostr << "Problem reading source file: " << fullFileName.c_str()
+          << " line:" << cc;
+        errorsWhileAccumulating.push_back(ostr.str());
+        error ++;
+        break;
+        }
+      covLogFile << "\t\t<Line Number=\"" << cc << "\" Count=\"" << fcov[cc]
+        << "\">"
+        << this->CTest->MakeXMLSafe(line.c_str()) << "</Line>" << std::endl;
+      if ( fcov[cc] == 0 )
+        {
+        untested ++;
+        }
+      else if ( fcov[cc] > 0 )
+        {
+        tested ++;
+        }
+      }
+    if ( cmSystemTools::GetLineFromStream(ifs, line) )
+      {
+      cmOStringStream ostr;
+      ostr <<  "Looks like there are more lines in the file: " << line;
+      errorsWhileAccumulating.push_back(ostr.str());
+      }
+    float cper = 0;
+    float cmet = 0;
+    if ( tested + untested > 0 )
+      {
+      cper = (100 * SAFEDIV(static_cast<float>(tested),
+          static_cast<float>(tested + untested)));
+      cmet = ( SAFEDIV(static_cast<float>(tested + 10),
+          static_cast<float>(tested + untested + 10)));
+      }
+    total_tested += tested;
+    total_untested += untested;
+    covLogFile << "\t\t</Report>" << std::endl
+      << "\t</File>" << std::endl;
+    covSumFile << "\t<File Name=\"" << this->CTest->MakeXMLSafe(fileName)
+      << "\" FullPath=\"" << this->CTest->MakeXMLSafe(
+        this->CTest->GetShortPathToFile(fullFileName.c_str()))
+      << "\" Covered=\"" << (cmet>0?"true":"false") << "\">\n"
+      << "\t\t<LOCTested>" << tested << "</LOCTested>\n"
+      << "\t\t<LOCUnTested>" << untested << "</LOCUnTested>\n"
+      << "\t\t<PercentCoverage>";
+    covSumFile.setf(std::ios::fixed, std::ios::floatfield);
+    covSumFile.precision(2);
+    covSumFile << (cper) << "</PercentCoverage>\n"
+      << "\t\t<CoverageMetric>";
+    covSumFile.setf(std::ios::fixed, std::ios::floatfield);
+    covSumFile.precision(2);
+    covSumFile << (cmet) << "</CoverageMetric>\n"
+      << "\t</File>" << std::endl;
+    cnt ++;
+    }
+  this->EndCoverageLogFile(covLogFile, logFileCount);
+
+  if ( errorsWhileAccumulating.size() > 0 )
+    {
+    cmCTestLog(this->CTest, ERROR_MESSAGE, std::endl);
+    cmCTestLog(this->CTest, ERROR_MESSAGE,
+      "Error(s) while acumulating results:" << std::endl);
+    std::vector<std::string>::iterator erIt;
+    for ( erIt = errorsWhileAccumulating.begin();
+      erIt != errorsWhileAccumulating.end();
+      ++ erIt )
+      {
+      cmCTestLog(this->CTest, ERROR_MESSAGE,
+        "  " << erIt->c_str() << std::endl);
+      }
+    }
+
+  int total_lines = total_tested + total_untested;
+  float percent_coverage = 100 * SAFEDIV(static_cast<float>(total_tested),
+    static_cast<float>(total_lines));
+  if ( total_lines == 0 )
+    {
+    percent_coverage = 0;
+    }
+
+  std::string end_time = this->CTest->CurrentTime();
+
+  covSumFile << "\t<LOCTested>" << total_tested << "</LOCTested>\n"
+    << "\t<LOCUntested>" << total_untested << "</LOCUntested>\n"
+    << "\t<LOC>" << total_lines << "</LOC>\n"
+    << "\t<PercentCoverage>";
+  covSumFile.setf(std::ios::fixed, std::ios::floatfield);
+  covSumFile.precision(2);
+  covSumFile << (percent_coverage)<< "</PercentCoverage>\n"
+    << "\t<EndDateTime>" << end_time << "</EndDateTime>\n";
+  covSumFile << "<ElapsedMinutes>" <<
+    static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
+    << "</ElapsedMinutes>"
+    << "</Coverage>" << std::endl;
+  this->CTest->EndXML(covSumFile);
+
+  cmCTestLog(this->CTest, HANDLER_OUTPUT, "" << std::endl
+    << "\tCovered LOC:         "
+    << total_tested << std::endl
+    << "\tNot covered LOC:     " << total_untested << std::endl
+    << "\tTotal LOC:           " << total_lines << std::endl
+    << "\tPercentage Coverage: "
+    << std::setiosflags(std::ios::fixed)
+    << std::setprecision(2)
+    << (percent_coverage) << "%" << std::endl);
+
+  ofs << "\tCovered LOC:         " << total_tested << std::endl
+    << "\tNot covered LOC:     " << total_untested << std::endl
+    << "\tTotal LOC:           " << total_lines << std::endl
+    << "\tPercentage Coverage: "
+    << std::setiosflags(std::ios::fixed)
+    << std::setprecision(2)
+    << (percent_coverage) << "%" << std::endl;
+
+
+  if ( error )
+    {
+    return -1;
+    }
+  return 0;
+}
+
+//----------------------------------------------------------------------
+void cmCTestCoverageHandler::PopulateCustomVectors(cmMakefile *mf)
+{
+  cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+    " Add coverage exclude regular expressions." << std::endl);
+  this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_COVERAGE_EXCLUDE",
+                                this->CustomCoverageExclude);
+  std::vector<cmStdString>::iterator it;
+  for ( it = this->CustomCoverageExclude.begin();
+    it != this->CustomCoverageExclude.end();
+    ++ it )
+    {
+    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Add coverage exclude: "
+      << it->c_str() << std::endl);
+    }
+}
+
+//----------------------------------------------------------------------
+int cmCTestCoverageHandler::HandleGCovCoverage(
+  cmCTestCoverageHandlerContainer* cont)
+{
+  std::string gcovCommand
+    = this->CTest->GetCTestConfiguration("CoverageCommand");
 
   // Style 1
   std::string st1gcovOutputRex1
@@ -234,22 +542,13 @@
   cmsys::RegularExpression st2re5(st2gcovOutputRex5.c_str());
   cmsys::RegularExpression st2re6(st2gcovOutputRex6.c_str());
 
-  cmCTestLog(this->CTest, HANDLER_OUTPUT, "Performing coverage" << std::endl);
-
-  std::string coverage_start_time = this->CTest->CurrentTime();
-
-  std::string testingDir = this->CTest->GetBinaryDir() + "/Testing";
-  std::string tempDir = testingDir + "/CoverageInfo";
-  std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory();
-  cmSystemTools::MakeDirectory(tempDir.c_str());
-  cmSystemTools::ChangeDirectory(tempDir.c_str());
 
   cmsys::Glob gl;
   gl.RecurseOn();
-  std::string daGlob = binaryDir + "/*.da";
+  std::string daGlob = cont->BinaryDir + "/*.da";
   gl.FindFiles(daGlob);
   std::vector<std::string> files = gl.GetFiles();
-  daGlob = binaryDir + "/*.gcda";
+  daGlob = cont->BinaryDir + "/*.gcda";
   gl.FindFiles(daGlob);
   std::vector<std::string>& moreFiles = gl.GetFiles();
   files.insert(files.end(), moreFiles.begin(), moreFiles.end());
@@ -257,14 +556,19 @@
 
   if ( files.size() == 0 )
     {
-    cmCTestLog(this->CTest, WARNING,
-      " Cannot find any coverage files. Ignoring Coverage request."
+    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+      " Cannot find any GCov coverage files."
       << std::endl);
     // No coverage files is a valid thing, so the exit code is 0 
-    cmSystemTools::ChangeDirectory(currentDirectory.c_str());
     return 0;
     }
 
+  std::string testingDir = this->CTest->GetBinaryDir() + "/Testing";
+  std::string tempDir = testingDir + "/CoverageInfo";
+  std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory();
+  cmSystemTools::MakeDirectory(tempDir.c_str());
+  cmSystemTools::ChangeDirectory(tempDir.c_str());
+
   this->CustomCoverageExcludeRegex.empty();
   std::vector<cmStdString>::iterator rexIt;
   for ( rexIt = this->CustomCoverageExclude.begin();
@@ -275,11 +579,6 @@
       cmsys::RegularExpression(rexIt->c_str()));
     }
 
-  typedef std::vector<int> singleFileCoverageVector;
-  typedef std::map<std::string, singleFileCoverageVector> totalCoverageMap;
-
-  totalCoverageMap totalCoverage;
-
   int gcovStyle = 0;
 
   std::set<std::string> missingFiles;
@@ -300,20 +599,20 @@
     std::string output = "";
     std::string errors = "";
     int retVal = 0;
-    ofs << "* Run coverage for: " << fileDir.c_str() << std::endl;
-    ofs << "  Command: " << command.c_str() << std::endl;
+    *cont->OFS << "* Run coverage for: " << fileDir.c_str() << std::endl;
+    *cont->OFS << "  Command: " << command.c_str() << std::endl;
     int res = this->CTest->RunCommand(command.c_str(), &output, &errors,
       &retVal, tempDir.c_str(), 0 /*this->TimeOut*/);
 
-    ofs << "  Output: " << output.c_str() << std::endl;
-    ofs << "  Errors: " << errors.c_str() << std::endl;
+    *cont->OFS << "  Output: " << output.c_str() << std::endl;
+    *cont->OFS << "  Errors: " << errors.c_str() << std::endl;
     if ( ! res )
       {
       cmCTestLog(this->CTest, ERROR_MESSAGE,
         "Problem running coverage on file: " << it->c_str() << std::endl);
       cmCTestLog(this->CTest, ERROR_MESSAGE,
         "Command produced error: " << errors << std::endl);
-      error ++;
+      cont->Error ++;
       continue;
       }
     if ( retVal != 0 )
@@ -321,7 +620,7 @@
       cmCTestLog(this->CTest, ERROR_MESSAGE, "Coverage command returned: "
         << retVal << " while processing: " << it->c_str() << std::endl);
       cmCTestLog(this->CTest, ERROR_MESSAGE,
-        "Command produced error: " << error << std::endl);
+        "Command produced error: " << cont->Error << std::endl);
       }
     cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
       "--------------------------------------------------------------"
@@ -353,7 +652,7 @@
             {
             cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style"
               << std::endl);
-            error ++;
+            cont->Error ++;
             break;
             }
           gcovStyle = 1;
@@ -370,7 +669,7 @@
             {
             cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style"
               << std::endl);
-            error ++;
+            cont->Error ++;
             break;
             }
           gcovStyle = 1;
@@ -386,7 +685,7 @@
             {
             cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style"
               << std::endl);
-            error ++;
+            cont->Error ++;
             break;
             }
           gcovStyle = 2;
@@ -403,7 +702,7 @@
             {
             cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style"
               << std::endl);
-            error ++;
+            cont->Error ++;
             break;
             }
           gcovStyle = 2;
@@ -417,7 +716,7 @@
             {
             cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style"
               << std::endl);
-            error ++;
+            cont->Error ++;
             break;
             }
           gcovStyle = 2;
@@ -433,7 +732,7 @@
             {
             cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style"
               << std::endl);
-            error ++;
+            cont->Error ++;
             break;
             }
           gcovStyle = 2;
@@ -450,7 +749,7 @@
             {
             cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style"
               << std::endl);
-            error ++;
+            cont->Error ++;
             break;
             }
           gcovStyle = 2;
@@ -467,7 +766,7 @@
             {
             cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style"
               << std::endl);
-            error ++;
+            cont->Error ++;
             break;
             }
           gcovStyle = 2;
@@ -480,12 +779,13 @@
         {
         cmCTestLog(this->CTest, ERROR_MESSAGE,
           "Unknown line: [" << line->c_str() << "]" << std::endl);
-        error ++;
+        cont->Error ++;
         //abort();
         }
       if ( !gcovFile.empty() && actualSourceFile.size() )
         {
-        singleFileCoverageVector* vec = &totalCoverage[actualSourceFile];
+        cmCTestCoverageHandlerContainer::SingleFileCoverageVector* vec
+          = &cont->TotalCoverage[actualSourceFile];
         cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "   in file: "
           << gcovFile << std::endl);
         std::ifstream ifile(gcovFile.c_str());
@@ -527,7 +827,7 @@
             if ( lineIdx >= 0 )
               {
               while ( vec->size() <=
-                static_cast<singleFileCoverageVector::size_type>(lineIdx) )
+                static_cast<size_t>(lineIdx) )
                 {
                 vec->push_back(-1);
                 }
@@ -550,25 +850,25 @@
         {
         gcovFile = "";
         // Is it in the source dir?
-        if ( sourceFile.size() > sourceDir.size() &&
-          sourceFile.substr(0, sourceDir.size()) == sourceDir &&
-          sourceFile[sourceDir.size()] == '/' )
+        if ( sourceFile.size() > cont->SourceDir.size() &&
+          sourceFile.substr(0, cont->SourceDir.size()) == cont->SourceDir &&
+          sourceFile[cont->SourceDir.size()] == '/' )
           {
           cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "   produced s: "
             << sourceFile.c_str() << std::endl);
-          ofs << "  produced in source dir: " << sourceFile.c_str()
+          *cont->OFS << "  produced in source dir: " << sourceFile.c_str()
             << std::endl;
           actualSourceFile
             = cmSystemTools::CollapseFullPath(sourceFile.c_str());
           }
         // Binary dir?
-        if ( sourceFile.size() > binaryDir.size() &&
-          sourceFile.substr(0, binaryDir.size()) == binaryDir &&
-          sourceFile[binaryDir.size()] == '/' )
+        if ( sourceFile.size() > cont->BinaryDir.size() &&
+          sourceFile.substr(0, cont->BinaryDir.size()) == cont->BinaryDir &&
+          sourceFile[cont->BinaryDir.size()] == '/' )
           {
           cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "   produced b: "
             << sourceFile.c_str() << std::endl);
-          ofs << "  produced in binary dir: " << sourceFile.c_str()
+          *cont->OFS << "  produced in binary dir: " << sourceFile.c_str()
             << std::endl;
           actualSourceFile
             = cmSystemTools::CollapseFullPath(sourceFile.c_str());
@@ -582,13 +882,13 @@
             cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "File: ["
               << sourceFile.c_str() << "]" << std::endl);
             cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "s: ["
-              << sourceFile.substr(0, sourceDir.size()) << "]" << std::endl);
+              << sourceFile.substr(0, cont->SourceDir.size()) << "]" << std::endl);
             cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "b: ["
-              << sourceFile.substr(0, binaryDir.size()) << "]" << std::endl);
-            ofs << "  Something went wrong. Cannot find: "
+              << sourceFile.substr(0, cont->BinaryDir.size()) << "]" << std::endl);
+            *cont->OFS << "  Something went wrong. Cannot find: "
               << sourceFile.c_str()
-              << " in source dir: " << sourceDir.c_str()
-              << " or binary dir: " << binaryDir.c_str() << std::endl;
+              << " in source dir: " << cont->SourceDir.c_str()
+              << " or binary dir: " << cont->BinaryDir.c_str() << std::endl;
             missingFiles.insert(actualSourceFile);
             }
           }
@@ -602,259 +902,160 @@
       cmCTestLog(this->CTest, HANDLER_OUTPUT, "    ");
       }
     }
+  cmSystemTools::ChangeDirectory(currentDirectory.c_str());
+  return file_count;
+}
 
-  cmGeneratedFileStream covSumFile;
-  cmGeneratedFileStream covLogFile;
+//----------------------------------------------------------------------
+int cmCTestCoverageHandler::HandleTracePyCoverage(
+  cmCTestCoverageHandlerContainer* cont)
+{
+  cmsys::Glob gl;
+  gl.RecurseOn();
+  std::string daGlob = cont->BinaryDir + "/*.cover";
+  gl.FindFiles(daGlob);
+  std::vector<std::string> files = gl.GetFiles();
 
-  if (!this->StartResultingXML("Coverage", covSumFile))
+  if ( files.size() == 0 )
     {
-    cmCTestLog(this->CTest, ERROR_MESSAGE,
-      "Cannot open coverage summary file." << std::endl);
-    cmSystemTools::ChangeDirectory(currentDirectory.c_str());
-    return -1;
+    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+      " Cannot find any Python Trace.py coverage files."
+      << std::endl);
+    // No coverage files is a valid thing, so the exit code is 0 
+    return 0;
     }
 
-  this->CTest->StartXML(covSumFile);
-  // Produce output xml files
-
-  covSumFile << "<Coverage>" << std::endl
-    << "\t<StartDateTime>" << coverage_start_time << "</StartDateTime>"
-    << std::endl;
-  int logFileCount = 0;
-  if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
-    {
-    cmSystemTools::ChangeDirectory(currentDirectory.c_str());
-    return -1;
-    }
-  totalCoverageMap::iterator fileIterator;
-  int cnt = 0;
-  long total_tested = 0;
-  long total_untested = 0;
-  //std::string fullSourceDir = sourceDir + "/";
-  //std::string fullBinaryDir = binaryDir + "/";
-  cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
-  cmCTestLog(this->CTest, HANDLER_OUTPUT,
-    "   Acumulating results (each . represents one file):" << std::endl);
-  cmCTestLog(this->CTest, HANDLER_OUTPUT, "    ");
+  std::string testingDir = this->CTest->GetBinaryDir() + "/Testing";
+  std::string tempDir = testingDir + "/CoverageInfo";
+  std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory();
+  cmSystemTools::MakeDirectory(tempDir.c_str());
+  cmSystemTools::ChangeDirectory(tempDir.c_str());
 
-  std::vector<std::string> errorsWhileAccumulating;
+  cmSystemTools::ChangeDirectory(currentDirectory.c_str());
 
-  file_count = 0;
-  for ( fileIterator = totalCoverage.begin();
-    fileIterator != totalCoverage.end();
-    ++fileIterator )
+  std::vector<std::string>::iterator fileIt;
+  int file_count = 0;
+  for ( fileIt = files.begin(); fileIt != files.end(); ++ fileIt )
     {
-    cmCTestLog(this->CTest, HANDLER_OUTPUT, "." << std::flush);
-    file_count ++;
-    if ( file_count % 50 == 0 )
-      {
-      cmCTestLog(this->CTest, HANDLER_OUTPUT, " processed: " << file_count
-        << " out of "
-        << totalCoverage.size() << std::endl);
-      cmCTestLog(this->CTest, HANDLER_OUTPUT, "    ");
-      }
-    if ( cnt % 100 == 0 )
-      {
-      this->EndCoverageLogFile(covLogFile, logFileCount);
-      logFileCount ++;
-      if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
-        {
-        cmSystemTools::ChangeDirectory(currentDirectory.c_str());
-        return -1;
-        }
-      }
-    const std::string fullFileName = fileIterator->first;
-    const std::string fileName
-      = cmSystemTools::GetFilenameName(fullFileName.c_str());
-    std::string fullFilePath
-      = cmSystemTools::GetFilenamePath(fullFileName.c_str());
-    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Process file: "
-      << fullFileName << std::endl);
-
-    cmSystemTools::ConvertToUnixSlashes(fullFilePath);
-
-    if ( !cmSystemTools::FileExists(fullFileName.c_str()) )
+    std::string fileName = this->FindFile(cont, *fileIt);
+    if ( fileName.empty() )
       {
-      cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot find file: "
-        << fullFileName.c_str() << std::endl);
+      cmCTestLog(this->CTest, ERROR_MESSAGE,
+        "Cannot find source Python file corresponding to: "
+        << fileIt->c_str() << std::endl);
       continue;
       }
 
-    bool shouldIDoCoverage
-      = this->ShouldIDoCoverage(fullFileName.c_str(),
-        sourceDir.c_str(), binaryDir.c_str());
-    if ( !shouldIDoCoverage )
+    std::string actualSourceFile
+      = cmSystemTools::CollapseFullPath(fileName.c_str());
+    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+      "   Check coverage for file: " << actualSourceFile.c_str()
+      << std::endl);
+    cmCTestCoverageHandlerContainer::SingleFileCoverageVector* vec
+      = &cont->TotalCoverage[actualSourceFile];
+    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+      "   in file: " << fileIt->c_str() << std::endl);
+    std::ifstream ifile(fileIt->c_str());
+    if ( ! ifile )
       {
-      cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
-        ".NoDartCoverage found, so skip coverage check for: "
-        << fullFileName.c_str()
-        << std::endl);
-      continue;
+      cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open file: "
+        << fileIt->c_str() << std::endl);
       }
-
-    const singleFileCoverageVector& fcov = fileIterator->second;
-    covLogFile << "\t<File Name=\""
-      << this->CTest->MakeXMLSafe(fileName.c_str())
-      << "\" FullPath=\"" << this->CTest->MakeXMLSafe(
-        this->CTest->GetShortPathToFile(
-          fileIterator->first.c_str())) << "\">" << std::endl
-      << "\t\t<Report>" << std::endl;
-
-    std::ifstream ifs(fullFileName.c_str());
-    if ( !ifs)
+    else
       {
-      cmOStringStream ostr;
-      ostr <<  "Cannot open source file: " << fullFileName.c_str();
-      errorsWhileAccumulating.push_back(ostr.str());
-      error ++;
-      continue;
-      }
+      long cnt = -1;
+      std::string nl;
+      while ( cmSystemTools::GetLineFromStream(ifile, nl) )
+        {
+        cnt ++;
 
-    int tested = 0;
-    int untested = 0;
+        // Skip empty lines
+        if ( !nl.size() )
+          {
+          continue;
+          }
 
-    singleFileCoverageVector::size_type cc;
-    std::string line;
-    for ( cc= 0; cc < fcov.size(); cc ++ )
-      {
-      if ( !cmSystemTools::GetLineFromStream(ifs, line) &&
-        cc != fcov.size() -1 )
-        {
-        cmOStringStream ostr;
-        ostr << "Problem reading source file: " << fullFileName.c_str()
-          << " line:" << cc;
-        errorsWhileAccumulating.push_back(ostr.str());
-        error ++;
-        break;
-        }
-      covLogFile << "\t\t<Line Number=\"" << cc << "\" Count=\"" << fcov[cc]
-        << "\">"
-        << this->CTest->MakeXMLSafe(line.c_str()) << "</Line>" << std::endl;
-      if ( fcov[cc] == 0 )
-        {
-        untested ++;
-        }
-      else if ( fcov[cc] > 0 )
-        {
-        tested ++;
-        }
-      }
-    if ( cmSystemTools::GetLineFromStream(ifs, line) )
-      {
-      cmOStringStream ostr;
-      ostr <<  "Looks like there are more lines in the file: " << line;
-      errorsWhileAccumulating.push_back(ostr.str());
-      }
-    float cper = 0;
-    float cmet = 0;
-    if ( tested + untested > 0 )
-      {
-      cper = (100 * SAFEDIV(static_cast<float>(tested),
-          static_cast<float>(tested + untested)));
-      cmet = ( SAFEDIV(static_cast<float>(tested + 10),
-          static_cast<float>(tested + untested + 10)));
-      }
-    total_tested += tested;
-    total_untested += untested;
-    covLogFile << "\t\t</Report>" << std::endl
-      << "\t</File>" << std::endl;
-    covSumFile << "\t<File Name=\"" << this->CTest->MakeXMLSafe(fileName)
-      << "\" FullPath=\"" << this->CTest->MakeXMLSafe(
-        this->CTest->GetShortPathToFile(fullFileName.c_str()))
-      << "\" Covered=\"" << (cmet>0?"true":"false") << "\">\n"
-      << "\t\t<LOCTested>" << tested << "</LOCTested>\n"
-      << "\t\t<LOCUnTested>" << untested << "</LOCUnTested>\n"
-      << "\t\t<PercentCoverage>";
-    covSumFile.setf(std::ios::fixed, std::ios::floatfield);
-    covSumFile.precision(2);
-    covSumFile << (cper) << "</PercentCoverage>\n"
-      << "\t\t<CoverageMetric>";
-    covSumFile.setf(std::ios::fixed, std::ios::floatfield);
-    covSumFile.precision(2);
-    covSumFile << (cmet) << "</CoverageMetric>\n"
-      << "\t</File>" << std::endl;
-    cnt ++;
-    }
-  this->EndCoverageLogFile(covLogFile, logFileCount);
+        // Skip unused lines
+        if ( nl.size() < 12 )
+          {
+          continue;
+          }
 
-  if ( errorsWhileAccumulating.size() > 0 )
-    {
-    cmCTestLog(this->CTest, ERROR_MESSAGE, std::endl);
-    cmCTestLog(this->CTest, ERROR_MESSAGE,
-      "Error(s) while acumulating results:" << std::endl);
-    std::vector<std::string>::iterator erIt;
-    for ( erIt = errorsWhileAccumulating.begin();
-      erIt != errorsWhileAccumulating.end();
-      ++ erIt )
-      {
-      cmCTestLog(this->CTest, ERROR_MESSAGE,
-        "  " << erIt->c_str() << std::endl);
+        // Read the coverage count from the beginning of the Trace.py output
+        // line
+        std::string prefix = nl.substr(0, 6);
+        if ( prefix[5] != ' ' && prefix[5] != ':' )
+          {
+          // This is a hack. We should really do something more elaborate
+          prefix = nl.substr(0, 7);
+          if ( prefix[6] != ' ' && prefix[6] != ':' )
+            {
+            prefix = nl.substr(0, 8);
+            if ( prefix[7] != ' ' && prefix[7] != ':' )
+              {
+              cmCTestLog(this->CTest, ERROR_MESSAGE,
+                "Currently the limit is maximum coverage of 999999"
+                << std::endl);
+              }
+            }
+          }
+        int cov = atoi(prefix.c_str());
+        if ( prefix[prefix.size()-1] != ':' )
+          {
+          // This line does not have ':' so no coverage here. That said,
+          // Trace.py does not handle not covered lines versus comments etc.
+          // So, this will be set to 0.
+          cov = 0;
+          }
+        cmCTestLog(this->CTest, DEBUG, "Prefix: " << prefix.c_str()
+          << " cov: " << cov
+          << std::endl);
+        // Read the line number starting at the 10th character of the gcov
+        // output line
+        int lineIdx = cnt;
+        if ( lineIdx >= 0 )
+          {
+          while ( vec->size() <=
+            static_cast<size_t>(lineIdx) )
+            {
+            vec->push_back(-1);
+            }
+          // Initially all entries are -1 (not used). If we get coverage
+          // information, increment it to 0 first.
+          if ( (*vec)[lineIdx] < 0 )
+            {
+            if ( cov >= 0 )
+              {
+              (*vec)[lineIdx] = 0;
+              }
+            }
+          (*vec)[lineIdx] += cov;
+          }
+        }
       }
+    ++ file_count;
     }
-
-  int total_lines = total_tested + total_untested;
-  float percent_coverage = 100 * SAFEDIV(static_cast<float>(total_tested),
-    static_cast<float>(total_lines));
-  if ( total_lines == 0 )
-    {
-    percent_coverage = 0;
-    }
-
-  std::string end_time = this->CTest->CurrentTime();
-
-  covSumFile << "\t<LOCTested>" << total_tested << "</LOCTested>\n"
-    << "\t<LOCUntested>" << total_untested << "</LOCUntested>\n"
-    << "\t<LOC>" << total_lines << "</LOC>\n"
-    << "\t<PercentCoverage>";
-  covSumFile.setf(std::ios::fixed, std::ios::floatfield);
-  covSumFile.precision(2);
-  covSumFile << (percent_coverage)<< "</PercentCoverage>\n"
-    << "\t<EndDateTime>" << end_time << "</EndDateTime>\n";
-  covSumFile << "<ElapsedMinutes>" <<
-    static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
-    << "</ElapsedMinutes>"
-    << "</Coverage>" << std::endl;
-  this->CTest->EndXML(covSumFile);
-
-  cmCTestLog(this->CTest, HANDLER_OUTPUT, "\tCovered LOC:         "
-    << total_tested << std::endl
-    << "\tNot covered LOC:     " << total_untested << std::endl
-    << "\tTotal LOC:           " << total_lines << std::endl
-    << "\tPercentage Coverage: "
-    << std::setiosflags(std::ios::fixed)
-    << std::setprecision(2)
-    << (percent_coverage) << "%" << std::endl);
-
-  ofs << "\tCovered LOC:         " << total_tested << std::endl
-    << "\tNot covered LOC:     " << total_untested << std::endl
-    << "\tTotal LOC:           " << total_lines << std::endl
-    << "\tPercentage Coverage: "
-    << std::setiosflags(std::ios::fixed)
-    << std::setprecision(2)
-    << (percent_coverage) << "%" << std::endl;
-
   cmSystemTools::ChangeDirectory(currentDirectory.c_str());
-
-  if ( error )
-    {
-    return -1;
-    }
-  return 0;
+  return file_count;
 }
 
 //----------------------------------------------------------------------
-void cmCTestCoverageHandler::PopulateCustomVectors(cmMakefile *mf)
+std::string cmCTestCoverageHandler::FindFile(
+  cmCTestCoverageHandlerContainer* cont,
+  std::string fileName)
 {
-  cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
-    " Add coverage exclude regular expressions." << std::endl);
-  this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_COVERAGE_EXCLUDE",
-                                this->CustomCoverageExclude);
-  std::vector<cmStdString>::iterator it;
-  for ( it = this->CustomCoverageExclude.begin();
-    it != this->CustomCoverageExclude.end();
-    ++ it )
+  std::string fileNameNoE
+    = cmSystemTools::GetFilenameWithoutLastExtension(fileName);
+  // First check in source and binary directory
+  std::string fullName = cont->SourceDir + "/" + fileNameNoE + ".py";
+  if ( cmSystemTools::FileExists(fullName.c_str()) )
     {
-    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Add coverage exclude: "
-      << it->c_str() << std::endl);
+    return fullName;
     }
+  fullName = cont->BinaryDir + "/" + fileNameNoE + ".py";
+  if ( cmSystemTools::FileExists(fullName.c_str()) )
+    {
+    return fullName;
+    }
+  return "";
 }

Index: cmCTestCoverageHandler.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/CTest/cmCTestCoverageHandler.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- cmCTestCoverageHandler.h	10 Mar 2006 20:03:09 -0000	1.13
+++ cmCTestCoverageHandler.h	27 Apr 2007 03:20:12 -0000	1.14
@@ -25,6 +25,7 @@
 #include <cmsys/RegularExpression.hxx>
 
 class cmGeneratedFileStream;
+class cmCTestCoverageHandlerContainer;
 
 /** \class cmCTestCoverageHandler
  * \brief A class that handles coverage computaiton for ctest
@@ -55,6 +56,12 @@
   bool StartCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount);
   void EndCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount);
 
+  int HandleGCovCoverage(cmCTestCoverageHandlerContainer* cont);
+  int HandleTracePyCoverage(cmCTestCoverageHandlerContainer* cont);
+
+  std::string FindFile(cmCTestCoverageHandlerContainer* cont,
+    std::string fileName);
+
   struct cmCTestCoverage
     {
     cmCTestCoverage()



More information about the Cmake-commits mailing list