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:
parent
a86e81c358
commit
1d96c943e0
@ -694,17 +694,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
|
|||||||
cmsys::RegularExpression st2re5(st2gcovOutputRex5.c_str());
|
cmsys::RegularExpression st2re5(st2gcovOutputRex5.c_str());
|
||||||
cmsys::RegularExpression st2re6(st2gcovOutputRex6.c_str());
|
cmsys::RegularExpression st2re6(st2gcovOutputRex6.c_str());
|
||||||
|
|
||||||
|
std::vector<std::string> files;
|
||||||
cmsys::Glob gl;
|
this->FindGCovFiles(files);
|
||||||
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>::iterator it;
|
std::vector<std::string>::iterator it;
|
||||||
|
|
||||||
if ( files.size() == 0 )
|
if ( files.size() == 0 )
|
||||||
@ -1061,6 +1052,37 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
|
|||||||
return file_count;
|
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(
|
int cmCTestCoverageHandler::HandleTracePyCoverage(
|
||||||
cmCTestCoverageHandlerContainer* cont)
|
cmCTestCoverageHandlerContainer* cont)
|
||||||
@ -1763,6 +1785,7 @@ void cmCTestCoverageHandler::LoadLabels()
|
|||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void cmCTestCoverageHandler::LoadLabels(const char* dir)
|
void cmCTestCoverageHandler::LoadLabels(const char* dir)
|
||||||
{
|
{
|
||||||
|
LabelSet& dirLabels = this->TargetDirs[dir];
|
||||||
std::string fname = dir;
|
std::string fname = dir;
|
||||||
fname += "/Labels.txt";
|
fname += "/Labels.txt";
|
||||||
std::ifstream fin(fname.c_str());
|
std::ifstream fin(fname.c_str());
|
||||||
@ -1789,6 +1812,7 @@ void cmCTestCoverageHandler::LoadLabels(const char* dir)
|
|||||||
// Label lines appear indented by one space.
|
// Label lines appear indented by one space.
|
||||||
std::string label = line.substr(1);
|
std::string label = line.substr(1);
|
||||||
int id = this->GetLabelId(label);
|
int id = this->GetLabelId(label);
|
||||||
|
dirLabels.insert(id);
|
||||||
if(inTarget)
|
if(inTarget)
|
||||||
{
|
{
|
||||||
targetLabels.push_back(id);
|
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)
|
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
|
// The source is filtered out if it does not have any labels in
|
||||||
// common with the filter set.
|
// common with the filter set.
|
||||||
std::vector<int> ids;
|
|
||||||
std::string shortSrc = this->CTest->GetShortPathToFile(source.c_str());
|
std::string shortSrc = this->CTest->GetShortPathToFile(source.c_str());
|
||||||
LabelMapType::const_iterator li = this->SourceLabels.find(shortSrc);
|
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
|
return !this->IntersectsFilter(li->second);
|
||||||
(li->second.begin(), li->second.end(),
|
|
||||||
this->LabelFilter.begin(), this->LabelFilter.end(),
|
|
||||||
cmsys_stl::back_inserter(ids));
|
|
||||||
}
|
}
|
||||||
return ids.empty();
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@ private:
|
|||||||
|
|
||||||
//! Handle coverage using GCC's GCov
|
//! Handle coverage using GCC's GCov
|
||||||
int HandleGCovCoverage(cmCTestCoverageHandlerContainer* cont);
|
int HandleGCovCoverage(cmCTestCoverageHandlerContainer* cont);
|
||||||
|
void FindGCovFiles(std::vector<std::string>& files);
|
||||||
|
|
||||||
//! Handle coverage using Bullseye
|
//! Handle coverage using Bullseye
|
||||||
int HandleBullseyeCoverage(cmCTestCoverageHandlerContainer* cont);
|
int HandleBullseyeCoverage(cmCTestCoverageHandlerContainer* cont);
|
||||||
@ -145,6 +146,7 @@ private:
|
|||||||
class LabelSet: public std::set<int> {};
|
class LabelSet: public std::set<int> {};
|
||||||
typedef std::map<cmStdString, LabelSet> LabelMapType;
|
typedef std::map<cmStdString, LabelSet> LabelMapType;
|
||||||
LabelMapType SourceLabels;
|
LabelMapType SourceLabels;
|
||||||
|
LabelMapType TargetDirs;
|
||||||
|
|
||||||
// Map from label name to label id.
|
// Map from label name to label id.
|
||||||
typedef std::map<cmStdString, int> LabelIdMapType;
|
typedef std::map<cmStdString, int> LabelIdMapType;
|
||||||
@ -159,6 +161,7 @@ private:
|
|||||||
|
|
||||||
// Label-based filtering.
|
// Label-based filtering.
|
||||||
std::set<int> LabelFilter;
|
std::set<int> LabelFilter;
|
||||||
|
bool IntersectsFilter(LabelSet const& labels);
|
||||||
bool IsFilteredOut(std::string const& source);
|
bool IsFilteredOut(std::string const& source);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user