summaryrefslogtreecommitdiffstats
path: root/Source/CTest
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CTest')
-rw-r--r--Source/CTest/cmCTestCoverageCommand.cxx12
-rw-r--r--Source/CTest/cmCTestCoverageCommand.h6
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx20
-rw-r--r--Source/CTest/cmCTestHandlerCommand.h5
-rw-r--r--Source/CTest/cmCTestRunTest.cxx146
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx65
-rw-r--r--Source/CTest/cmCTestSubmitCommand.h13
-rw-r--r--Source/CTest/cmCTestUploadCommand.cxx2
-rw-r--r--Source/CTest/cmCTestUploadCommand.h5
9 files changed, 73 insertions, 201 deletions
diff --git a/Source/CTest/cmCTestCoverageCommand.cxx b/Source/CTest/cmCTestCoverageCommand.cxx
index 7432d08..97b0a89 100644
--- a/Source/CTest/cmCTestCoverageCommand.cxx
+++ b/Source/CTest/cmCTestCoverageCommand.cxx
@@ -4,7 +4,6 @@
#include <set>
-#include <cmext/algorithm>
#include <cmext/string_view>
#include "cmCTest.h"
@@ -18,13 +17,6 @@ void cmCTestCoverageCommand::BindArguments()
this->Bind("LABELS"_s, this->Labels);
}
-void cmCTestCoverageCommand::CheckArguments(
- std::vector<std::string> const& keywords)
-{
- this->LabelsMentioned =
- !this->Labels.empty() || cm::contains(keywords, "LABELS");
-}
-
cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
{
this->CTest->SetCTestConfigurationFromCMakeVariable(
@@ -36,9 +28,9 @@ cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
handler->Initialize();
// If a LABELS option was given, select only files with the labels.
- if (this->LabelsMentioned) {
+ if (this->Labels) {
handler->SetLabelFilter(
- std::set<std::string>(this->Labels.begin(), this->Labels.end()));
+ std::set<std::string>(this->Labels->begin(), this->Labels->end()));
}
handler->SetQuiet(this->Quiet);
diff --git a/Source/CTest/cmCTestCoverageCommand.h b/Source/CTest/cmCTestCoverageCommand.h
index 9344852..55c68b2 100644
--- a/Source/CTest/cmCTestCoverageCommand.h
+++ b/Source/CTest/cmCTestCoverageCommand.h
@@ -9,7 +9,9 @@
#include <vector>
#include <cm/memory>
+#include <cm/optional>
+#include "cmArgumentParserTypes.h" // IWYU pragma: keep
#include "cmCTestHandlerCommand.h"
#include "cmCommand.h"
@@ -41,9 +43,7 @@ public:
protected:
void BindArguments() override;
- void CheckArguments(std::vector<std::string> const& keywords) override;
cmCTestGenericHandler* InitializeHandler() override;
- bool LabelsMentioned;
- std::vector<std::string> Labels;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Labels;
};
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index 5494d20..be952cd 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -7,6 +7,7 @@
#include <cstring>
#include <sstream>
+#include <cm/string_view>
#include <cmext/string_view>
#include "cmCTest.h"
@@ -81,15 +82,13 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
// Process input arguments.
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
- std::vector<std::string> parsedKeywords;
- this->Parse(args, &unparsedArguments, &keywordsMissingValue,
- &parsedKeywords);
- this->CheckArguments(keywordsMissingValue);
-
- std::sort(parsedKeywords.begin(), parsedKeywords.end());
- auto it = std::adjacent_find(parsedKeywords.begin(), parsedKeywords.end());
- if (it != parsedKeywords.end()) {
+ this->Parse(args, &unparsedArguments);
+ this->CheckArguments();
+
+ std::sort(this->ParsedKeywords.begin(), this->ParsedKeywords.end());
+ auto it = std::adjacent_find(this->ParsedKeywords.begin(),
+ this->ParsedKeywords.end());
+ if (it != this->ParsedKeywords.end()) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat("Called with more than one value for ", *it));
@@ -233,6 +232,7 @@ void cmCTestHandlerCommand::ProcessAdditionalValues(cmCTestGenericHandler*)
void cmCTestHandlerCommand::BindArguments()
{
+ this->BindParsedKeywords(this->ParsedKeywords);
this->Bind("APPEND"_s, this->Append);
this->Bind("QUIET"_s, this->Quiet);
this->Bind("RETURN_VALUE"_s, this->ReturnValue);
@@ -242,6 +242,6 @@ void cmCTestHandlerCommand::BindArguments()
this->Bind("SUBMIT_INDEX"_s, this->SubmitIndex);
}
-void cmCTestHandlerCommand::CheckArguments(std::vector<std::string> const&)
+void cmCTestHandlerCommand::CheckArguments()
{
}
diff --git a/Source/CTest/cmCTestHandlerCommand.h b/Source/CTest/cmCTestHandlerCommand.h
index 756952d..ed6d9af 100644
--- a/Source/CTest/cmCTestHandlerCommand.h
+++ b/Source/CTest/cmCTestHandlerCommand.h
@@ -7,6 +7,8 @@
#include <string>
#include <vector>
+#include <cm/string_view>
+
#include "cmArgumentParser.h"
#include "cmCTestCommand.h"
@@ -42,8 +44,9 @@ protected:
// Command argument handling.
virtual void BindArguments();
- virtual void CheckArguments(std::vector<std::string> const& keywords);
+ virtual void CheckArguments();
+ std::vector<cm::string_view> ParsedKeywords;
bool Append = false;
bool Quiet = false;
std::string CaptureCMakeError;
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 2a2cb1c..5efe69f 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -8,16 +8,12 @@
#include <cstdint>
#include <cstdio>
#include <cstring>
-#include <functional>
#include <iomanip>
#include <ratio>
#include <sstream>
#include <utility>
#include <cm/memory>
-#include <cm/optional>
-#include <cm/string_view>
-#include <cmext/string_view>
#include "cmsys/RegularExpression.hxx"
@@ -787,149 +783,31 @@ bool cmCTestRunTest::ForkProcess(
this->TestProcess->SetTimeout(timeout);
-#ifndef CMAKE_BOOTSTRAP
cmSystemTools::SaveRestoreEnvironment sre;
-#endif
-
std::ostringstream envMeasurement;
+
+ // We split processing ENVIRONMENT and ENVIRONMENT_MODIFICATION into two
+ // phases to ensure that MYVAR=reset: in the latter phase resets to the
+ // former phase's settings, rather than to the original environment.
if (environment && !environment->empty()) {
- // Environment modification works on the assumption that the environment is
- // actually modified here. If another strategy is used, there will need to
- // be updates below in `apply_diff`.
- cmSystemTools::AppendEnv(*environment);
- for (auto const& var : *environment) {
- envMeasurement << var << std::endl;
- }
+ cmSystemTools::EnvDiff diff;
+ diff.AppendEnv(*environment);
+ diff.ApplyToCurrentEnv(&envMeasurement);
}
if (environment_modification && !environment_modification->empty()) {
- std::map<std::string, cm::optional<std::string>> env_application;
-
-#ifdef _WIN32
- char path_sep = ';';
-#else
- char path_sep = ':';
-#endif
-
- auto apply_diff =
- [&env_application](const std::string& name,
- std::function<void(std::string&)> const& apply) {
- cm::optional<std::string> old_value = env_application[name];
- std::string output;
- if (old_value) {
- output = *old_value;
- } else {
- // This only works because the environment is actually modified above
- // (`AppendEnv`). If CTest ever just creates an environment block
- // directly, that block will need to be queried for the subprocess'
- // value instead.
- const char* curval = cmSystemTools::GetEnv(name);
- if (curval) {
- output = curval;
- }
- }
- apply(output);
- env_application[name] = output;
- };
-
- bool err_occurred = false;
+ cmSystemTools::EnvDiff diff;
+ bool env_ok = true;
for (auto const& envmod : *environment_modification) {
- // Split on `=`
- auto const eq_loc = envmod.find_first_of('=');
- if (eq_loc == std::string::npos) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Error: Missing `=` after the variable name in: "
- << envmod << std::endl);
- err_occurred = true;
- continue;
- }
- auto const name = envmod.substr(0, eq_loc);
-
- // Split value on `:`
- auto const op_value_start = eq_loc + 1;
- auto const colon_loc = envmod.find_first_of(':', op_value_start);
- if (colon_loc == std::string::npos) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Error: Missing `:` after the operation in: " << envmod
- << std::endl);
- err_occurred = true;
- continue;
- }
- auto const op =
- envmod.substr(op_value_start, colon_loc - op_value_start);
-
- auto const value_start = colon_loc + 1;
- auto const value = envmod.substr(value_start);
-
- // Determine what to do with the operation.
- if (op == "reset"_s) {
- auto entry = env_application.find(name);
- if (entry != env_application.end()) {
- env_application.erase(entry);
- }
- } else if (op == "set"_s) {
- env_application[name] = value;
- } else if (op == "unset"_s) {
- env_application[name] = {};
- } else if (op == "string_append"_s) {
- apply_diff(name, [&value](std::string& output) { output += value; });
- } else if (op == "string_prepend"_s) {
- apply_diff(name,
- [&value](std::string& output) { output.insert(0, value); });
- } else if (op == "path_list_append"_s) {
- apply_diff(name, [&value, path_sep](std::string& output) {
- if (!output.empty()) {
- output += path_sep;
- }
- output += value;
- });
- } else if (op == "path_list_prepend"_s) {
- apply_diff(name, [&value, path_sep](std::string& output) {
- if (!output.empty()) {
- output.insert(output.begin(), path_sep);
- }
- output.insert(0, value);
- });
- } else if (op == "cmake_list_append"_s) {
- apply_diff(name, [&value](std::string& output) {
- if (!output.empty()) {
- output += ';';
- }
- output += value;
- });
- } else if (op == "cmake_list_prepend"_s) {
- apply_diff(name, [&value](std::string& output) {
- if (!output.empty()) {
- output.insert(output.begin(), ';');
- }
- output.insert(0, value);
- });
- } else {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Error: Unrecognized environment manipulation argument: "
- << op << std::endl);
- err_occurred = true;
- continue;
- }
+ env_ok &= diff.ParseOperation(envmod);
}
- if (err_occurred) {
+ if (!env_ok) {
return false;
}
- for (auto const& env_apply : env_application) {
- if (env_apply.second) {
- auto const env_update =
- cmStrCat(env_apply.first, '=', *env_apply.second);
- cmSystemTools::PutEnv(env_update);
- envMeasurement << env_update << std::endl;
- } else {
- cmSystemTools::UnsetEnv(env_apply.first.c_str());
- // Signify that this variable is being actively unset
- envMeasurement << "#" << env_apply.first << "=" << std::endl;
- }
- }
+ diff.ApplyToCurrentEnv(&envMeasurement);
}
if (this->UseAllocatedResources) {
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index a2dc615..a1933cc 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -8,7 +8,6 @@
#include <cm/memory>
#include <cm/vector>
-#include <cmext/algorithm>
#include <cmext/string_view>
#include "cmCTest.h"
@@ -87,7 +86,7 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
// If FILES are given, but not PARTS, only the FILES are submitted
// and *no* PARTS are submitted.
// (This is why we select the empty "noParts" set in the
- // FilesMentioned block below...)
+ // if(this->Files) block below...)
//
// If PARTS are given, only the selected PARTS are submitted.
//
@@ -96,7 +95,7 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
// If given explicit FILES to submit, pass them to the handler.
//
- if (this->FilesMentioned) {
+ if (this->Files) {
// Intentionally select *no* PARTS. (Pass an empty set.) If PARTS
// were also explicitly mentioned, they will be selected below...
// But FILES with no PARTS mentioned should just submit the FILES
@@ -104,14 +103,14 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
//
handler->SelectParts(std::set<cmCTest::Part>());
handler->SelectFiles(
- std::set<std::string>(this->Files.begin(), this->Files.end()));
+ std::set<std::string>(this->Files->begin(), this->Files->end()));
}
// If a PARTS option was given, select only the named parts for submission.
//
- if (this->PartsMentioned) {
+ if (this->Parts) {
auto parts =
- cmMakeRange(this->Parts).transform([this](std::string const& arg) {
+ cmMakeRange(*(this->Parts)).transform([this](std::string const& arg) {
return this->CTest->GetPartFromName(arg);
});
handler->SelectParts(std::set<cmCTest::Part>(parts.begin(), parts.end()));
@@ -172,33 +171,31 @@ void cmCTestSubmitCommand::BindArguments()
this->cmCTestHandlerCommand::BindArguments();
}
-void cmCTestSubmitCommand::CheckArguments(
- std::vector<std::string> const& keywords)
+void cmCTestSubmitCommand::CheckArguments()
{
- this->PartsMentioned =
- !this->Parts.empty() || cm::contains(keywords, "PARTS");
- this->FilesMentioned =
- !this->Files.empty() || cm::contains(keywords, "FILES");
-
- cm::erase_if(this->Parts, [this](std::string const& arg) -> bool {
- cmCTest::Part p = this->CTest->GetPartFromName(arg);
- if (p == cmCTest::PartCount) {
- std::ostringstream e;
- e << "Part name \"" << arg << "\" is invalid.";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return true;
- }
- return false;
- });
-
- cm::erase_if(this->Files, [this](std::string const& arg) -> bool {
- if (!cmSystemTools::FileExists(arg)) {
- std::ostringstream e;
- e << "File \"" << arg << "\" does not exist. Cannot submit "
- << "a non-existent file.";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return true;
- }
- return false;
- });
+ if (this->Parts) {
+ cm::erase_if(*(this->Parts), [this](std::string const& arg) -> bool {
+ cmCTest::Part p = this->CTest->GetPartFromName(arg);
+ if (p == cmCTest::PartCount) {
+ std::ostringstream e;
+ e << "Part name \"" << arg << "\" is invalid.";
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return true;
+ }
+ return false;
+ });
+ }
+
+ if (this->Files) {
+ cm::erase_if(*(this->Files), [this](std::string const& arg) -> bool {
+ if (!cmSystemTools::FileExists(arg)) {
+ std::ostringstream e;
+ e << "File \"" << arg << "\" does not exist. Cannot submit "
+ << "a non-existent file.";
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return true;
+ }
+ return false;
+ });
+ }
}
diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h
index c5d11df..b67f182 100644
--- a/Source/CTest/cmCTestSubmitCommand.h
+++ b/Source/CTest/cmCTestSubmitCommand.h
@@ -8,6 +8,9 @@
#include <string>
#include <vector>
+#include <cm/optional>
+
+#include "cmArgumentParserTypes.h"
#include "cmCTestHandlerCommand.h"
class cmCommand;
@@ -35,13 +38,11 @@ public:
protected:
void BindArguments() override;
- void CheckArguments(std::vector<std::string> const& keywords) override;
+ void CheckArguments() override;
cmCTestGenericHandler* InitializeHandler() override;
bool CDashUpload = false;
- bool FilesMentioned = false;
bool InternalTest = false;
- bool PartsMentioned = false;
std::string BuildID;
std::string CDashUploadFile;
@@ -50,7 +51,7 @@ protected:
std::string RetryDelay;
std::string SubmitURL;
- std::vector<std::string> Files;
- std::vector<std::string> HttpHeaders;
- std::vector<std::string> Parts;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Files;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> HttpHeaders;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Parts;
};
diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx
index f86ee0d..2ed671c 100644
--- a/Source/CTest/cmCTestUploadCommand.cxx
+++ b/Source/CTest/cmCTestUploadCommand.cxx
@@ -21,7 +21,7 @@ void cmCTestUploadCommand::BindArguments()
this->Bind("CAPTURE_CMAKE_ERROR"_s, this->CaptureCMakeError);
}
-void cmCTestUploadCommand::CheckArguments(std::vector<std::string> const&)
+void cmCTestUploadCommand::CheckArguments()
{
cm::erase_if(this->Files, [this](std::string const& arg) -> bool {
if (!cmSystemTools::FileExists(arg)) {
diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h
index fe155f6..a9d1dd2 100644
--- a/Source/CTest/cmCTestUploadCommand.h
+++ b/Source/CTest/cmCTestUploadCommand.h
@@ -10,6 +10,7 @@
#include <cm/memory>
+#include "cmArgumentParserTypes.h"
#include "cmCTestHandlerCommand.h"
#include "cmCommand.h"
@@ -42,8 +43,8 @@ public:
protected:
void BindArguments() override;
- void CheckArguments(std::vector<std::string> const&) override;
+ void CheckArguments() override;
cmCTestGenericHandler* InitializeHandler() override;
- std::vector<std::string> Files;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Files;
};