From 1d96c943e0d029c4ad0b98d5a08e34f54ed8a8e5 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 9 Mar 2009 12:19:56 -0400 Subject: ENH: Efficiently filter CTest coverage by label This teaches CTest to process coverage information only for object files in targets containing labels of interest. This change also improves loading of global coverage information by globbing only in each target support directory instead of the entire build tree. --- Source/CTest/cmCTestCoverageHandler.cxx | 73 +++++++++++++++++++++++++-------- Source/CTest/cmCTestCoverageHandler.h | 3 ++ 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index fa9a220..ee9a169 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -694,17 +694,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage( cmsys::RegularExpression st2re5(st2gcovOutputRex5.c_str()); cmsys::RegularExpression st2re6(st2gcovOutputRex6.c_str()); - - cmsys::Glob gl; - gl.RecurseOn(); - gl.RecurseThroughSymlinksOff(); - std::string daGlob = cont->BinaryDir + "/*.da"; - gl.FindFiles(daGlob); - std::vector files = gl.GetFiles(); - daGlob = cont->BinaryDir + "/*.gcda"; - gl.FindFiles(daGlob); - std::vector& moreFiles = gl.GetFiles(); - files.insert(files.end(), moreFiles.begin(), moreFiles.end()); + std::vector files; + this->FindGCovFiles(files); std::vector::iterator it; if ( files.size() == 0 ) @@ -1061,6 +1052,37 @@ int cmCTestCoverageHandler::HandleGCovCoverage( return file_count; } +//---------------------------------------------------------------------------- +void cmCTestCoverageHandler::FindGCovFiles(std::vector& files) +{ + cmsys::Glob gl; + gl.RecurseOn(); + gl.RecurseThroughSymlinksOff(); + + for(LabelMapType::const_iterator lmi = this->TargetDirs.begin(); + lmi != this->TargetDirs.end(); ++lmi) + { + // Skip targets containing no interesting labels. + if(!this->IntersectsFilter(lmi->second)) + { + continue; + } + + // Coverage files appear next to their object files in the target + // support directory. + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + " globbing for coverage in: " << lmi->first << std::endl); + std::string daGlob = lmi->first; + daGlob += "/*.da"; + gl.FindFiles(daGlob); + files.insert(files.end(), gl.GetFiles().begin(), gl.GetFiles().end()); + daGlob = lmi->first; + daGlob += "/*.gcda"; + gl.FindFiles(daGlob); + files.insert(files.end(), gl.GetFiles().begin(), gl.GetFiles().end()); + } +} + //---------------------------------------------------------------------- int cmCTestCoverageHandler::HandleTracePyCoverage( cmCTestCoverageHandlerContainer* cont) @@ -1763,6 +1785,7 @@ void cmCTestCoverageHandler::LoadLabels() //---------------------------------------------------------------------- void cmCTestCoverageHandler::LoadLabels(const char* dir) { + LabelSet& dirLabels = this->TargetDirs[dir]; std::string fname = dir; fname += "/Labels.txt"; std::ifstream fin(fname.c_str()); @@ -1789,6 +1812,7 @@ void cmCTestCoverageHandler::LoadLabels(const char* dir) // Label lines appear indented by one space. std::string label = line.substr(1); int id = this->GetLabelId(label); + dirLabels.insert(id); if(inTarget) { targetLabels.push_back(id); @@ -1847,6 +1871,23 @@ cmCTestCoverageHandler::SetLabelFilter(std::set const& labels) } //---------------------------------------------------------------------- +bool cmCTestCoverageHandler::IntersectsFilter(LabelSet const& labels) +{ + // If there is no label filter then nothing is filtered out. + if(this->LabelFilter.empty()) + { + return true; + } + + std::vector ids; + cmsys_stl::set_intersection + (labels.begin(), labels.end(), + this->LabelFilter.begin(), this->LabelFilter.end(), + cmsys_stl::back_inserter(ids)); + return !ids.empty(); +} + +//---------------------------------------------------------------------- bool cmCTestCoverageHandler::IsFilteredOut(std::string const& source) { // If there is no label filter then nothing is filtered out. @@ -1857,15 +1898,11 @@ bool cmCTestCoverageHandler::IsFilteredOut(std::string const& source) // The source is filtered out if it does not have any labels in // common with the filter set. - std::vector ids; std::string shortSrc = this->CTest->GetShortPathToFile(source.c_str()); LabelMapType::const_iterator li = this->SourceLabels.find(shortSrc); - if(li != this->SourceLabels.end() && !li->second.empty()) + if(li != this->SourceLabels.end()) { - cmsys_stl::set_intersection - (li->second.begin(), li->second.end(), - this->LabelFilter.begin(), this->LabelFilter.end(), - cmsys_stl::back_inserter(ids)); + return !this->IntersectsFilter(li->second); } - return ids.empty(); + return true; } diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h index 46bcec1..c58b6ab 100644 --- a/Source/CTest/cmCTestCoverageHandler.h +++ b/Source/CTest/cmCTestCoverageHandler.h @@ -61,6 +61,7 @@ private: //! Handle coverage using GCC's GCov int HandleGCovCoverage(cmCTestCoverageHandlerContainer* cont); + void FindGCovFiles(std::vector& files); //! Handle coverage using Bullseye int HandleBullseyeCoverage(cmCTestCoverageHandlerContainer* cont); @@ -145,6 +146,7 @@ private: class LabelSet: public std::set {}; typedef std::map LabelMapType; LabelMapType SourceLabels; + LabelMapType TargetDirs; // Map from label name to label id. typedef std::map LabelIdMapType; @@ -159,6 +161,7 @@ private: // Label-based filtering. std::set LabelFilter; + bool IntersectsFilter(LabelSet const& labels); bool IsFilteredOut(std::string const& source); }; -- cgit v0.12