ctest: Support multiple -L and -LE options to mean "AND"

Fixes: #21087
This commit is contained in:
Adriaan de Groot 2021-03-20 16:53:14 +11:00 committed by Craig Scott
parent 61fd90b90c
commit 44ad3f0b7f
14 changed files with 223 additions and 83 deletions

View File

@ -155,7 +155,10 @@ Options
Run tests with labels matching regular expression. Run tests with labels matching regular expression.
This option tells CTest to run only the tests whose labels match the This option tells CTest to run only the tests whose labels match the
given regular expression. given regular expression. When more than one ``-L`` option is given,
a test will only be run if each regular expression matches at least one
of the test's labels (i.e. the multiple ``-L`` labels form an ``AND``
relationship). See `Label Matching`_.
``-R <regex>, --tests-regex <regex>`` ``-R <regex>, --tests-regex <regex>``
Run tests matching regular expression. Run tests matching regular expression.
@ -173,7 +176,10 @@ Options
Exclude tests with labels matching regular expression. Exclude tests with labels matching regular expression.
This option tells CTest to NOT run the tests whose labels match the This option tells CTest to NOT run the tests whose labels match the
given regular expression. given regular expression. When more than one ``-LE`` option is given,
a test will only be excluded if each regular expression matches at least one
of the test's labels (i.e. the multiple ``-LE`` labels form an ``AND``
relationship). See `Label Matching`_.
``-FA <regex>, --fixture-exclude-any <regex>`` ``-FA <regex>, --fixture-exclude-any <regex>``
Exclude fixtures matching ``<regex>`` from automatically adding any tests to Exclude fixtures matching ``<regex>`` from automatically adding any tests to
@ -398,6 +404,46 @@ Specify the directory in which to look for tests.
.. include:: OPTIONS_HELP.txt .. include:: OPTIONS_HELP.txt
.. _`Label Matching`:
Label Matching
==============
Tests may have labels attached to them. Tests may be included
or excluded from a test run by filtering on the labels.
Each individual filter is a regular expression applied to
the labels attached to a test.
When ``-L`` is used, in order for a test to be included in a
test run, each regular expression must match at least one
label. Using more than one ``-L`` option means "match **all**
of these".
The ``-LE`` option works just like ``-L``, but excludes tests
rather than including them. A test is excluded if each regular
expression matches at least one label.
If a test has no labels attached to it, then ``-L`` will never
include that test, and ``-LE`` will never exclude that test.
As an example of tests with labels, consider five tests,
with the following labels:
* *test1* has labels *tuesday* and *production*
* *test2* has labels *tuesday* and *test*
* *test3* has labels *wednesday* and *production*
* *test4* has label *wednesday*
* *test5* has labels *friday* and *test*
Running ``ctest`` with ``-L tuesday -L test`` will select *test2*, which has
both labels. Running CTest with ``-L test`` will select *test2* and
*test5*, because both of them have a label that matches that regular
expression.
Because the matching works with regular expressions, take note that
running CTest with ``-L es`` will match all five tests.
To select the *tuesday* and *wednesday* tests together, use a single
regular expression that matches either of them, like ``-L "tue|wed"``.
.. _`Label and Subproject Summary`: .. _`Label and Subproject Summary`:
Label and Subproject Summary Label and Subproject Summary

View File

@ -21,32 +21,47 @@ cmCTestGenericHandler::cmCTestGenericHandler()
cmCTestGenericHandler::~cmCTestGenericHandler() = default; cmCTestGenericHandler::~cmCTestGenericHandler() = default;
void cmCTestGenericHandler::SetOption(const std::string& op, const char* value) /* Modify the given `map`, setting key `op` to `value` if `value`
* is non-null, otherwise removing key `op` (if it exists).
*/
static void SetMapValue(cmCTestGenericHandler::t_StringToString& map,
const std::string& op, const char* value)
{ {
if (!value) { if (!value) {
auto remit = this->Options.find(op); map.erase(op);
if (remit != this->Options.end()) {
this->Options.erase(remit);
}
return; return;
} }
this->Options[op] = value; map[op] = value;
}
void cmCTestGenericHandler::SetOption(const std::string& op, const char* value)
{
SetMapValue(this->Options, op, value);
} }
void cmCTestGenericHandler::SetPersistentOption(const std::string& op, void cmCTestGenericHandler::SetPersistentOption(const std::string& op,
const char* value) const char* value)
{ {
this->SetOption(op, value); this->SetOption(op, value);
if (!value) { SetMapValue(this->PersistentOptions, op, value);
auto remit = this->PersistentOptions.find(op); }
if (remit != this->PersistentOptions.end()) {
this->PersistentOptions.erase(remit);
}
return;
}
this->PersistentOptions[op] = value; void cmCTestGenericHandler::AddMultiOption(const std::string& op,
const std::string& value)
{
if (!value.empty()) {
this->MultiOptions[op].emplace_back(value);
}
}
void cmCTestGenericHandler::AddPersistentMultiOption(const std::string& op,
const std::string& value)
{
if (!value.empty()) {
this->MultiOptions[op].emplace_back(value);
this->PersistentMultiOptions[op].emplace_back(value);
}
} }
void cmCTestGenericHandler::Initialize() void cmCTestGenericHandler::Initialize()
@ -68,6 +83,17 @@ const char* cmCTestGenericHandler::GetOption(const std::string& op)
return remit->second.c_str(); return remit->second.c_str();
} }
std::vector<std::string> cmCTestGenericHandler::GetMultiOption(
const std::string& optionName) const
{
// Avoid inserting a key, which MultiOptions[op] would do.
auto remit = this->MultiOptions.find(optionName);
if (remit == this->MultiOptions.end()) {
return {};
}
return remit->second;
}
bool cmCTestGenericHandler::StartResultingXML(cmCTest::Part part, bool cmCTestGenericHandler::StartResultingXML(cmCTest::Part part,
const char* name, const char* name,
cmGeneratedFileStream& xofs) cmGeneratedFileStream& xofs)

View File

@ -72,11 +72,41 @@ public:
virtual ~cmCTestGenericHandler(); virtual ~cmCTestGenericHandler();
using t_StringToString = std::map<std::string, std::string>; using t_StringToString = std::map<std::string, std::string>;
using t_StringToMultiString =
std::map<std::string, std::vector<std::string>>;
/**
* Options collect a single value from flags; passing the
* flag multiple times on the command-line *overwrites* values,
* and only the last one specified counts. Set an option to
* nullptr to "unset" it.
*
* The value is stored as a string. The values set for single
* and multi-options (see below) live in different spaces,
* so calling a single-getter for a key that has only been set
* as a multi-value will return nullptr.
*/
void SetPersistentOption(const std::string& op, const char* value); void SetPersistentOption(const std::string& op, const char* value);
void SetOption(const std::string& op, const char* value); void SetOption(const std::string& op, const char* value);
const char* GetOption(const std::string& op); const char* GetOption(const std::string& op);
/**
* Multi-Options collect one or more values from flags; passing
* the flag multiple times on the command-line *adds* values,
* rather than overwriting the previous values.
*
* Adding an empty value does nothing.
*
* The value is stored as a vector of strings. The values set for single
* (see above) and multi-options live in different spaces,
* so calling a multi-getter for a key that has only been set
* as a single-value will return an empty vector.
*/
void AddPersistentMultiOption(const std::string& optionName,
const std::string& value);
void AddMultiOption(const std::string& optionName, const std::string& value);
std::vector<std::string> GetMultiOption(const std::string& op) const;
void SetCommand(cmCTestCommand* command) { this->Command = command; } void SetCommand(cmCTestCommand* command) { this->Command = command; }
void SetSubmitIndex(int idx) { this->SubmitIndex = idx; } void SetSubmitIndex(int idx) { this->SubmitIndex = idx; }
@ -100,6 +130,8 @@ protected:
cmCTest* CTest; cmCTest* CTest;
t_StringToString Options; t_StringToString Options;
t_StringToString PersistentOptions; t_StringToString PersistentOptions;
t_StringToMultiString MultiOptions;
t_StringToMultiString PersistentMultiOptions;
t_StringToString LogFileNames; t_StringToString LogFileNames;
cmCTestCommand* Command; cmCTestCommand* Command;

View File

@ -73,11 +73,11 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
handler->SetOption("IncludeRegularExpression", this->Include.c_str()); handler->SetOption("IncludeRegularExpression", this->Include.c_str());
} }
if (!this->ExcludeLabel.empty()) { if (!this->ExcludeLabel.empty()) {
handler->SetOption("ExcludeLabelRegularExpression", handler->AddMultiOption("ExcludeLabelRegularExpression",
this->ExcludeLabel.c_str()); this->ExcludeLabel);
} }
if (!this->IncludeLabel.empty()) { if (!this->IncludeLabel.empty()) {
handler->SetOption("LabelRegularExpression", this->IncludeLabel.c_str()); handler->AddMultiOption("LabelRegularExpression", this->IncludeLabel);
} }
if (!this->ExcludeFixture.empty()) { if (!this->ExcludeFixture.empty()) {
handler->SetOption("ExcludeFixtureRegularExpression", handler->SetOption("ExcludeFixtureRegularExpression",

View File

@ -287,8 +287,6 @@ cmCTestTestHandler::cmCTestTestHandler()
{ {
this->UseUnion = false; this->UseUnion = false;
this->UseIncludeLabelRegExpFlag = false;
this->UseExcludeLabelRegExpFlag = false;
this->UseIncludeRegExpFlag = false; this->UseIncludeRegExpFlag = false;
this->UseExcludeRegExpFlag = false; this->UseExcludeRegExpFlag = false;
this->UseExcludeRegExpFirst = false; this->UseExcludeRegExpFirst = false;
@ -327,13 +325,11 @@ void cmCTestTestHandler::Initialize()
this->TestsToRun.clear(); this->TestsToRun.clear();
this->UseIncludeLabelRegExpFlag = false;
this->UseExcludeLabelRegExpFlag = false;
this->UseIncludeRegExpFlag = false; this->UseIncludeRegExpFlag = false;
this->UseExcludeRegExpFlag = false; this->UseExcludeRegExpFlag = false;
this->UseExcludeRegExpFirst = false; this->UseExcludeRegExpFirst = false;
this->IncludeLabelRegularExpression = ""; this->IncludeLabelRegularExpressions.clear();
this->ExcludeLabelRegularExpression = ""; this->ExcludeLabelRegularExpressions.clear();
this->IncludeRegExp.clear(); this->IncludeRegExp.clear();
this->ExcludeRegExp.clear(); this->ExcludeRegExp.clear();
this->ExcludeFixtureRegExp.clear(); this->ExcludeFixtureRegExp.clear();
@ -479,6 +475,22 @@ int cmCTestTestHandler::ProcessHandler()
return 0; return 0;
} }
/* Given a multi-option value `parts`, compile those parts into
* regular expressions in `expressions`. Skip empty values.
* Returns true if there were any expressions.
*/
static bool BuildLabelRE(const std::vector<std::string>& parts,
std::vector<cmsys::RegularExpression>& expressions)
{
expressions.clear();
for (const auto& p : parts) {
if (!p.empty()) {
expressions.emplace_back(p);
}
}
return !expressions.empty();
}
bool cmCTestTestHandler::ProcessOptions() bool cmCTestTestHandler::ProcessOptions()
{ {
// Update internal data structure from generic one // Update internal data structure from generic one
@ -519,18 +531,11 @@ bool cmCTestTestHandler::ProcessOptions()
this->CTest->SetStopOnFailure(true); this->CTest->SetStopOnFailure(true);
} }
const char* val; BuildLabelRE(this->GetMultiOption("LabelRegularExpression"),
val = this->GetOption("LabelRegularExpression"); this->IncludeLabelRegularExpressions);
if (val) { BuildLabelRE(this->GetMultiOption("ExcludeLabelRegularExpression"),
this->UseIncludeLabelRegExpFlag = true; this->ExcludeLabelRegularExpressions);
this->IncludeLabelRegExp = val; const char* val = this->GetOption("IncludeRegularExpression");
}
val = this->GetOption("ExcludeLabelRegularExpression");
if (val) {
this->UseExcludeLabelRegExpFlag = true;
this->ExcludeLabelRegExp = val;
}
val = this->GetOption("IncludeRegularExpression");
if (val) { if (val) {
this->UseIncludeRegExp(); this->UseIncludeRegExp();
this->SetIncludeRegExp(val); this->SetIncludeRegExp(val);
@ -763,10 +768,40 @@ void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject)
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet);
} }
/**
* Check if the labels (from a test) match all the expressions.
*
* Each of the RE's must match at least one label
* (e.g. all of the REs must match **some** label,
* in order for the filter to apply to the test).
*/
static bool MatchLabelsAgainstFilterRE(
const std::vector<std::string>& labels,
const std::vector<cmsys::RegularExpression>& expressions)
{
for (const auto& re : expressions) {
// check to see if the label regular expression matches
bool found = false; // assume it does not match
cmsys::RegularExpressionMatch match;
// loop over all labels and look for match
for (std::string const& l : labels) {
if (re.find(l.c_str(), match)) {
found = true;
break;
}
}
// if no match was found, exclude the test
if (!found) {
return false;
}
}
return true;
}
void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it) void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it)
{ {
// if not using Labels to filter then return // if not using Labels to filter then return
if (!this->UseIncludeLabelRegExpFlag) { if (this->IncludeLabelRegularExpressions.empty()) {
return; return;
} }
// if there are no labels and we are filtering by labels // if there are no labels and we are filtering by labels
@ -775,16 +810,9 @@ void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it)
it.IsInBasedOnREOptions = false; it.IsInBasedOnREOptions = false;
return; return;
} }
// check to see if the label regular expression matches
bool found = false; // assume it does not match
// loop over all labels and look for match
for (std::string const& l : it.Labels) {
if (this->IncludeLabelRegularExpression.find(l)) {
found = true;
}
}
// if no match was found, exclude the test // if no match was found, exclude the test
if (!found) { if (!MatchLabelsAgainstFilterRE(it.Labels,
this->IncludeLabelRegularExpressions)) {
it.IsInBasedOnREOptions = false; it.IsInBasedOnREOptions = false;
} }
} }
@ -792,7 +820,7 @@ void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it)
void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it) void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it)
{ {
// if not using Labels to filter then return // if not using Labels to filter then return
if (!this->UseExcludeLabelRegExpFlag) { if (this->ExcludeLabelRegularExpressions.empty()) {
return; return;
} }
// if there are no labels and we are excluding by labels // if there are no labels and we are excluding by labels
@ -800,16 +828,9 @@ void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it)
if (it.Labels.empty()) { if (it.Labels.empty()) {
return; return;
} }
// check to see if the label regular expression matches
bool found = false; // assume it does not match
// loop over all labels and look for match
for (std::string const& l : it.Labels) {
if (this->ExcludeLabelRegularExpression.find(l)) {
found = true;
}
}
// if match was found, exclude the test // if match was found, exclude the test
if (found) { if (MatchLabelsAgainstFilterRE(it.Labels,
this->ExcludeLabelRegularExpressions)) {
it.IsInBasedOnREOptions = false; it.IsInBasedOnREOptions = false;
} }
} }
@ -1704,12 +1725,6 @@ bool cmCTestTestHandler::ParseResourceGroupsProperty(
bool cmCTestTestHandler::GetListOfTests() bool cmCTestTestHandler::GetListOfTests()
{ {
if (!this->IncludeLabelRegExp.empty()) {
this->IncludeLabelRegularExpression.compile(this->IncludeLabelRegExp);
}
if (!this->ExcludeLabelRegExp.empty()) {
this->ExcludeLabelRegularExpression.compile(this->ExcludeLabelRegExp);
}
if (!this->IncludeRegExp.empty()) { if (!this->IncludeRegExp.empty()) {
this->IncludeTestsRegularExpression.compile(this->IncludeRegExp); this->IncludeTestsRegularExpression.compile(this->IncludeRegExp);
} }

View File

@ -320,20 +320,16 @@ private:
std::vector<int> TestsToRun; std::vector<int> TestsToRun;
bool UseIncludeLabelRegExpFlag;
bool UseExcludeLabelRegExpFlag;
bool UseIncludeRegExpFlag; bool UseIncludeRegExpFlag;
bool UseExcludeRegExpFlag; bool UseExcludeRegExpFlag;
bool UseExcludeRegExpFirst; bool UseExcludeRegExpFirst;
std::string IncludeLabelRegExp;
std::string ExcludeLabelRegExp;
std::string IncludeRegExp; std::string IncludeRegExp;
std::string ExcludeRegExp; std::string ExcludeRegExp;
std::string ExcludeFixtureRegExp; std::string ExcludeFixtureRegExp;
std::string ExcludeFixtureSetupRegExp; std::string ExcludeFixtureSetupRegExp;
std::string ExcludeFixtureCleanupRegExp; std::string ExcludeFixtureCleanupRegExp;
cmsys::RegularExpression IncludeLabelRegularExpression; std::vector<cmsys::RegularExpression> IncludeLabelRegularExpressions;
cmsys::RegularExpression ExcludeLabelRegularExpression; std::vector<cmsys::RegularExpression> ExcludeLabelRegularExpressions;
cmsys::RegularExpression IncludeTestsRegularExpression; cmsys::RegularExpression IncludeTestsRegularExpression;
cmsys::RegularExpression ExcludeTestsRegularExpression; cmsys::RegularExpression ExcludeTestsRegularExpression;

View File

@ -2108,17 +2108,17 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
} else if (this->CheckArgument(arg, "-L"_s, "--label-regex") && } else if (this->CheckArgument(arg, "-L"_s, "--label-regex") &&
i < args.size() - 1) { i < args.size() - 1) {
i++; i++;
this->GetTestHandler()->SetPersistentOption("LabelRegularExpression", this->GetTestHandler()->AddPersistentMultiOption("LabelRegularExpression",
args[i].c_str()); args[i]);
this->GetMemCheckHandler()->SetPersistentOption("LabelRegularExpression", this->GetMemCheckHandler()->AddPersistentMultiOption(
args[i].c_str()); "LabelRegularExpression", args[i]);
} else if (this->CheckArgument(arg, "-LE"_s, "--label-exclude") && } else if (this->CheckArgument(arg, "-LE"_s, "--label-exclude") &&
i < args.size() - 1) { i < args.size() - 1) {
i++; i++;
this->GetTestHandler()->SetPersistentOption( this->GetTestHandler()->AddPersistentMultiOption(
"ExcludeLabelRegularExpression", args[i].c_str()); "ExcludeLabelRegularExpression", args[i]);
this->GetMemCheckHandler()->SetPersistentOption( this->GetMemCheckHandler()->AddPersistentMultiOption(
"ExcludeLabelRegularExpression", args[i].c_str()); "ExcludeLabelRegularExpression", args[i]);
} }
else if (this->CheckArgument(arg, "-E"_s, "--exclude-regex") && else if (this->CheckArgument(arg, "-E"_s, "--exclude-regex") &&
@ -2268,6 +2268,15 @@ void cmCTest::SetPersistentOptionIfNotEmpty(const std::string& value,
} }
} }
void cmCTest::AddPersistentMultiOptionIfNotEmpty(const std::string& value,
const std::string& optionName)
{
if (!value.empty()) {
this->GetTestHandler()->AddPersistentMultiOption(optionName, value);
this->GetMemCheckHandler()->AddPersistentMultiOption(optionName, value);
}
}
bool cmCTest::SetArgsFromPreset(const std::string& presetName, bool cmCTest::SetArgsFromPreset(const std::string& presetName,
bool listPresets) bool listPresets)
{ {
@ -2419,7 +2428,7 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
if (expandedPreset->Filter->Include) { if (expandedPreset->Filter->Include) {
this->SetPersistentOptionIfNotEmpty( this->SetPersistentOptionIfNotEmpty(
expandedPreset->Filter->Include->Name, "IncludeRegularExpression"); expandedPreset->Filter->Include->Name, "IncludeRegularExpression");
this->SetPersistentOptionIfNotEmpty( this->AddPersistentMultiOptionIfNotEmpty(
expandedPreset->Filter->Include->Label, "LabelRegularExpression"); expandedPreset->Filter->Include->Label, "LabelRegularExpression");
if (expandedPreset->Filter->Include->Index) { if (expandedPreset->Filter->Include->Index) {
@ -2452,7 +2461,7 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
if (expandedPreset->Filter->Exclude) { if (expandedPreset->Filter->Exclude) {
this->SetPersistentOptionIfNotEmpty( this->SetPersistentOptionIfNotEmpty(
expandedPreset->Filter->Exclude->Name, "ExcludeRegularExpression"); expandedPreset->Filter->Exclude->Name, "ExcludeRegularExpression");
this->SetPersistentOptionIfNotEmpty( this->AddPersistentMultiOptionIfNotEmpty(
expandedPreset->Filter->Exclude->Label, expandedPreset->Filter->Exclude->Label,
"ExcludeLabelRegularExpression"); "ExcludeLabelRegularExpression");

View File

@ -463,6 +463,8 @@ public:
private: private:
void SetPersistentOptionIfNotEmpty(const std::string& value, void SetPersistentOptionIfNotEmpty(const std::string& value,
const std::string& optionName); const std::string& optionName);
void AddPersistentMultiOptionIfNotEmpty(const std::string& value,
const std::string& optionName);
int GenerateNotesFile(const std::string& files); int GenerateNotesFile(const std::string& files);

View File

@ -55,8 +55,9 @@ static const char* cmDocumentationOptions[][2] = {
"format of the test information and can be 'human' for the current text " "format of the test information and can be 'human' for the current text "
"format or 'json-v1' for json format. Defaults to 'human'." }, "format or 'json-v1' for json format. Defaults to 'human'." },
{ "-L <regex>, --label-regex <regex>", { "-L <regex>, --label-regex <regex>",
"Run tests with labels matching " "Run tests with labels matching regular expression. "
"regular expression." }, "With multiple -L, run tests where each "
"regular expression matches at least one label." },
{ "-R <regex>, --tests-regex <regex>", { "-R <regex>, --tests-regex <regex>",
"Run tests matching regular " "Run tests matching regular "
"expression." }, "expression." },
@ -64,8 +65,9 @@ static const char* cmDocumentationOptions[][2] = {
"Exclude tests matching regular " "Exclude tests matching regular "
"expression." }, "expression." },
{ "-LE <regex>, --label-exclude <regex>", { "-LE <regex>, --label-exclude <regex>",
"Exclude tests with labels " "Exclude tests with labels matching regular expression. "
"matching regular expression." }, "With multiple -LE, exclude tests where each "
"regular expression matches at least one label." },
{ "-FA <regex>, --fixture-exclude-any <regex>", { "-FA <regex>, --fixture-exclude-any <regex>",
"Do not automatically " "Do not automatically "
"add any tests for " "add any tests for "

View File

@ -7,6 +7,7 @@ macro(AddCMakeTest TestName PreArgs)
add_test(NAME CMake.${TestName} add_test(NAME CMake.${TestName}
COMMAND ${CMAKE_EXECUTABLE} ${PreArgs} COMMAND ${CMAKE_EXECUTABLE} ${PreArgs}
-P "${CMAKE_CURRENT_BINARY_DIR}/${TestName}Test.cmake" ${ARGN}) -P "${CMAKE_CURRENT_BINARY_DIR}/${TestName}Test.cmake" ${ARGN})
set_tests_properties("CMake.${TestName}" PROPERTIES LABELS "CMake;command")
endmacro() endmacro()

View File

@ -27,11 +27,15 @@ expect_test_list("test1.*test3.*Total Tests: 2" --label-regex foo)
expect_test_list("test2.*test3.*Total Tests: 2" --label-regex bar) expect_test_list("test2.*test3.*Total Tests: 2" --label-regex bar)
expect_test_list("test1.*test2.*test3.*Total Tests: 3" --label-regex foo|bar) expect_test_list("test1.*test2.*test3.*Total Tests: 3" --label-regex foo|bar)
expect_test_list("Total Tests: 0" --label-regex baz) expect_test_list("Total Tests: 0" --label-regex baz)
expect_test_list("Total Tests: 0" --label-regex foo --label-regex baz)
expect_test_list("test3.*Total Tests: 1" --label-regex foo --label-regex bar)
expect_test_list("test2.*Total Tests: 1" --label-exclude foo) expect_test_list("test2.*Total Tests: 1" --label-exclude foo)
expect_test_list("test1.*Total Tests: 1" --label-exclude bar) expect_test_list("test1.*Total Tests: 1" --label-exclude bar)
expect_test_list("Total Tests: 0" --label-exclude foo|bar) expect_test_list("Total Tests: 0" --label-exclude foo|bar)
expect_test_list("test1.*test2.*test3.*Total Tests: 3" --label-exclude baz) expect_test_list("test1.*test2.*test3.*Total Tests: 3" --label-exclude baz)
expect_test_list("test1.*test2.*Total Tests: 2" --label-exclude foo --label-exclude bar)
expect_test_list("test1.*test2.*test3.*Total Tests: 3" --label-exclude foo --label-exclude baz)
expect_test_list("test1.*Total Tests: 1" --label-regex foo --label-exclude bar) expect_test_list("test1.*Total Tests: 1" --label-regex foo --label-exclude bar)
expect_test_list("test2.*Total Tests: 1" --label-regex bar --label-exclude foo) expect_test_list("test2.*Total Tests: 1" --label-regex bar --label-exclude foo)

View File

@ -43,6 +43,7 @@ macro(ADD_AUTOGEN_TEST NAME)
--build-options ${build_options} ${Autogen_BUILD_OPTIONS} --build-options ${build_options} ${Autogen_BUILD_OPTIONS}
${_TestCommand} ${_TestCommand}
) )
set_tests_properties("${_QtXAutogen}.${NAME}" PROPERTIES LABELS "Qt${QT_TEST_VERSION}")
list(APPEND TEST_BUILD_DIRS "${_BuildDir}") list(APPEND TEST_BUILD_DIRS "${_BuildDir}")
unset(_TestCommand) unset(_TestCommand)
unset(_QtXAutogen) unset(_QtXAutogen)

View File

@ -36,7 +36,9 @@ ADD_AUTOGEN_TEST(UnityMocSource)
if(QT_TEST_ALLOW_QT_MACROS) if(QT_TEST_ALLOW_QT_MACROS)
ADD_AUTOGEN_TEST(MocCMP0071) ADD_AUTOGEN_TEST(MocCMP0071)
set_property(TEST "Qt${QT_TEST_VERSION}Autogen.MocCMP0071" APPEND PROPERTY LABELS "policy")
ADD_AUTOGEN_TEST(MocCMP0100) ADD_AUTOGEN_TEST(MocCMP0100)
set_property(TEST "Qt${QT_TEST_VERSION}Autogen.MocCMP0100" APPEND PROPERTY LABELS "policy")
ADD_AUTOGEN_TEST(MocInclude) ADD_AUTOGEN_TEST(MocInclude)
ADD_AUTOGEN_TEST(MocIncludeSymlink) ADD_AUTOGEN_TEST(MocIncludeSymlink)
ADD_AUTOGEN_TEST(MocSkipSource) ADD_AUTOGEN_TEST(MocSkipSource)

View File

@ -29,6 +29,10 @@ macro(add_RunCMake_test test)
${TEST_ARGS} ${TEST_ARGS}
-P "${CMAKE_CURRENT_SOURCE_DIR}/${Test_Dir}/RunCMakeTest.cmake" -P "${CMAKE_CURRENT_SOURCE_DIR}/${Test_Dir}/RunCMakeTest.cmake"
) )
set_tests_properties("RunCMake.${test}" PROPERTIES LABELS "CMake;run")
if(${test} MATCHES ^CMP)
set_property(TEST "RunCMake.${test}" APPEND PROPERTY LABELS "policy")
endif()
endmacro() endmacro()
function(add_RunCMake_test_group test types) function(add_RunCMake_test_group test types)