ENH: Teach ctest_coverage to filter with LABELS
This teaches ctest_coverage() to report only coverage of files labeled with at least one label given by a new LABELS option.
This commit is contained in:
parent
3078fef81c
commit
91a8569648
@ -17,22 +17,55 @@
|
|||||||
#include "cmCTestCoverageCommand.h"
|
#include "cmCTestCoverageCommand.h"
|
||||||
|
|
||||||
#include "cmCTest.h"
|
#include "cmCTest.h"
|
||||||
#include "cmCTestGenericHandler.h"
|
#include "cmCTestCoverageHandler.h"
|
||||||
|
|
||||||
cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
|
cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
|
||||||
{
|
{
|
||||||
this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
|
this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
|
||||||
"CoverageCommand", "CTEST_COVERAGE_COMMAND");
|
"CoverageCommand", "CTEST_COVERAGE_COMMAND");
|
||||||
|
|
||||||
cmCTestGenericHandler* handler
|
cmCTestCoverageHandler* handler = static_cast<cmCTestCoverageHandler*>(
|
||||||
= this->CTest->GetInitializedHandler("coverage");
|
this->CTest->GetInitializedHandler("coverage"));
|
||||||
if ( !handler )
|
if ( !handler )
|
||||||
{
|
{
|
||||||
this->SetError("internal CTest error. Cannot instantiate test handler");
|
this->SetError("internal CTest error. Cannot instantiate test handler");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a LABELS option was given, select only files with the labels.
|
||||||
|
if(this->LabelsMentioned)
|
||||||
|
{
|
||||||
|
handler->SetLabelFilter(this->Labels);
|
||||||
|
}
|
||||||
|
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool cmCTestCoverageCommand::CheckArgumentKeyword(std::string const& arg)
|
||||||
|
{
|
||||||
|
// Look for arguments specific to this command.
|
||||||
|
if(arg == "LABELS")
|
||||||
|
{
|
||||||
|
this->ArgumentDoing = ArgumentDoingLabels;
|
||||||
|
this->LabelsMentioned = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for other arguments.
|
||||||
|
return this->Superclass::CheckArgumentKeyword(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool cmCTestCoverageCommand::CheckArgumentValue(std::string const& arg)
|
||||||
|
{
|
||||||
|
// Handle states specific to this command.
|
||||||
|
if(this->ArgumentDoing == ArgumentDoingLabels)
|
||||||
|
{
|
||||||
|
this->Labels.insert(arg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for other arguments.
|
||||||
|
return this->Superclass::CheckArgumentValue(arg);
|
||||||
|
}
|
||||||
|
@ -60,11 +60,15 @@ public:
|
|||||||
virtual const char* GetFullDocumentation()
|
virtual const char* GetFullDocumentation()
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
" ctest_coverage([BUILD build_dir] [RETURN_VALUE res] [APPEND])\n"
|
" ctest_coverage([BUILD build_dir] [RETURN_VALUE res] [APPEND]\n"
|
||||||
|
" [LABELS label1 [label2 [...]]])\n"
|
||||||
"Perform the coverage of the given build directory and stores results "
|
"Perform the coverage of the given build directory and stores results "
|
||||||
"in Coverage.xml. The second argument is a variable that will hold "
|
"in Coverage.xml. The second argument is a variable that will hold "
|
||||||
"value."
|
"value."
|
||||||
"\n"
|
"\n"
|
||||||
|
"The LABELS option filters the coverage report to include only "
|
||||||
|
"source files labeled with at least one of the labels specified."
|
||||||
|
"\n"
|
||||||
CTEST_COMMAND_APPEND_OPTION_DOCS;
|
CTEST_COMMAND_APPEND_OPTION_DOCS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,6 +76,18 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
cmCTestGenericHandler* InitializeHandler();
|
cmCTestGenericHandler* InitializeHandler();
|
||||||
|
|
||||||
|
virtual bool CheckArgumentKeyword(std::string const& arg);
|
||||||
|
virtual bool CheckArgumentValue(std::string const& arg);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ArgumentDoingLabels = Superclass::ArgumentDoingLast1,
|
||||||
|
ArgumentDoingLast2
|
||||||
|
};
|
||||||
|
|
||||||
|
bool LabelsMentioned;
|
||||||
|
std::set<cmStdString> Labels;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "cmCTestCoverageHandler.h"
|
#include "cmCTestCoverageHandler.h"
|
||||||
#include "cmCTest.h"
|
#include "cmCTest.h"
|
||||||
#include "cmake.h"
|
#include "cmake.h"
|
||||||
|
#include "cmMakefile.h"
|
||||||
#include "cmSystemTools.h"
|
#include "cmSystemTools.h"
|
||||||
#include "cmGeneratedFileStream.h"
|
#include "cmGeneratedFileStream.h"
|
||||||
#include "cmXMLSafe.h"
|
#include "cmXMLSafe.h"
|
||||||
@ -24,6 +25,8 @@
|
|||||||
#include <cmsys/Process.h>
|
#include <cmsys/Process.h>
|
||||||
#include <cmsys/RegularExpression.hxx>
|
#include <cmsys/RegularExpression.hxx>
|
||||||
#include <cmsys/Glob.hxx>
|
#include <cmsys/Glob.hxx>
|
||||||
|
#include <cmsys/stl/iterator>
|
||||||
|
#include <cmsys/stl/algorithm>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@ -156,6 +159,7 @@ void cmCTestCoverageHandler::Initialize()
|
|||||||
this->SourceLabels.clear();
|
this->SourceLabels.clear();
|
||||||
this->LabelIdMap.clear();
|
this->LabelIdMap.clear();
|
||||||
this->Labels.clear();
|
this->Labels.clear();
|
||||||
|
this->LabelFilter.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
@ -207,6 +211,11 @@ bool cmCTestCoverageHandler::ShouldIDoCoverage(const char* file,
|
|||||||
const char* srcDir,
|
const char* srcDir,
|
||||||
const char* binDir)
|
const char* binDir)
|
||||||
{
|
{
|
||||||
|
if(this->IsFilteredOut(file))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<cmsys::RegularExpression>::iterator sit;
|
std::vector<cmsys::RegularExpression>::iterator sit;
|
||||||
for ( sit = this->CustomCoverageExcludeRegex.begin();
|
for ( sit = this->CustomCoverageExcludeRegex.begin();
|
||||||
sit != this->CustomCoverageExcludeRegex.end(); ++ sit )
|
sit != this->CustomCoverageExcludeRegex.end(); ++ sit )
|
||||||
@ -1817,3 +1826,39 @@ void cmCTestCoverageHandler::WriteXMLLabels(std::ofstream& os,
|
|||||||
os << "\t\t</Labels>\n";
|
os << "\t\t</Labels>\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
cmCTestCoverageHandler::SetLabelFilter(std::set<cmStdString> const& labels)
|
||||||
|
{
|
||||||
|
this->LabelFilter.clear();
|
||||||
|
for(std::set<cmStdString>::const_iterator li = labels.begin();
|
||||||
|
li != labels.end(); ++li)
|
||||||
|
{
|
||||||
|
this->LabelFilter.insert(this->GetLabelId(*li));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
bool cmCTestCoverageHandler::IsFilteredOut(std::string const& source)
|
||||||
|
{
|
||||||
|
// If there is no label filter then nothing is filtered out.
|
||||||
|
if(this->LabelFilter.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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())
|
||||||
|
{
|
||||||
|
cmsys_stl::set_intersection
|
||||||
|
(li->second.begin(), li->second.end(),
|
||||||
|
this->LabelFilter.begin(), this->LabelFilter.end(),
|
||||||
|
cmsys_stl::back_inserter(ids));
|
||||||
|
}
|
||||||
|
return ids.empty();
|
||||||
|
}
|
||||||
|
@ -50,6 +50,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
void PopulateCustomVectors(cmMakefile *mf);
|
void PopulateCustomVectors(cmMakefile *mf);
|
||||||
|
|
||||||
|
/** Report coverage only for sources with these labels. */
|
||||||
|
void SetLabelFilter(std::set<cmStdString> const& labels);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ShouldIDoCoverage(const char* file, const char* srcDir,
|
bool ShouldIDoCoverage(const char* file, const char* srcDir,
|
||||||
const char* binDir);
|
const char* binDir);
|
||||||
@ -153,6 +156,10 @@ private:
|
|||||||
void LoadLabels();
|
void LoadLabels();
|
||||||
void LoadLabels(const char* fname);
|
void LoadLabels(const char* fname);
|
||||||
void WriteXMLLabels(std::ofstream& os, std::string const& source);
|
void WriteXMLLabels(std::ofstream& os, std::string const& source);
|
||||||
|
|
||||||
|
// Label-based filtering.
|
||||||
|
std::set<int> LabelFilter;
|
||||||
|
bool IsFilteredOut(std::string const& source);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user