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.
This commit is contained in:
Brad King 2009-03-09 12:19:56 -04:00
parent a86e81c358
commit 1d96c943e0
2 changed files with 58 additions and 18 deletions

View File

@ -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<std::string> files = gl.GetFiles();
daGlob = cont->BinaryDir + "/*.gcda";
gl.FindFiles(daGlob);
std::vector<std::string>& moreFiles = gl.GetFiles();
files.insert(files.end(), moreFiles.begin(), moreFiles.end());
std::vector<std::string> files;
this->FindGCovFiles(files);
std::vector<std::string>::iterator it;
if ( files.size() == 0 )
@ -1061,6 +1052,37 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
return file_count;
}
//----------------------------------------------------------------------------
void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& 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);
@ -1846,6 +1870,23 @@ cmCTestCoverageHandler::SetLabelFilter(std::set<cmStdString> 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<int> 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)
{
@ -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<int> 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;
}

View File

@ -61,6 +61,7 @@ private:
//! Handle coverage using GCC's GCov
int HandleGCovCoverage(cmCTestCoverageHandlerContainer* cont);
void FindGCovFiles(std::vector<std::string>& files);
//! Handle coverage using Bullseye
int HandleBullseyeCoverage(cmCTestCoverageHandlerContainer* cont);
@ -145,6 +146,7 @@ private:
class LabelSet: public std::set<int> {};
typedef std::map<cmStdString, LabelSet> LabelMapType;
LabelMapType SourceLabels;
LabelMapType TargetDirs;
// Map from label name to label id.
typedef std::map<cmStdString, int> LabelIdMapType;
@ -159,6 +161,7 @@ private:
// Label-based filtering.
std::set<int> LabelFilter;
bool IntersectsFilter(LabelSet const& labels);
bool IsFilteredOut(std::string const& source);
};