cmCTest*Command: Port to cmArgumentParser

This commit is contained in:
Regina Pfeifer 2019-09-19 13:11:55 +02:00
parent d5a6a13368
commit 0aa8a2ab8b
18 changed files with 271 additions and 540 deletions

View File

@ -9,6 +9,7 @@
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cm_static_string_view.hxx"
#include "cmake.h"
#include <cstring>
@ -16,17 +17,15 @@
class cmExecutionStatus;
cmCTestBuildCommand::cmCTestBuildCommand()
void cmCTestBuildCommand::BindArguments()
{
this->GlobalGenerator = nullptr;
this->Arguments[ctb_NUMBER_ERRORS] = "NUMBER_ERRORS";
this->Arguments[ctb_NUMBER_WARNINGS] = "NUMBER_WARNINGS";
this->Arguments[ctb_TARGET] = "TARGET";
this->Arguments[ctb_CONFIGURATION] = "CONFIGURATION";
this->Arguments[ctb_FLAGS] = "FLAGS";
this->Arguments[ctb_PROJECT_NAME] = "PROJECT_NAME";
this->Arguments[ctb_LAST] = nullptr;
this->Last = ctb_LAST;
this->cmCTestHandlerCommand::BindArguments();
this->Bind("NUMBER_ERRORS"_s, this->NumberErrors);
this->Bind("NUMBER_WARNINGS"_s, this->NumberWarnings);
this->Bind("TARGET"_s, this->Target);
this->Bind("CONFIGURATION"_s, this->Configuration);
this->Bind("FLAGS"_s, this->Flags);
this->Bind("PROJECT_NAME"_s, this->ProjectName);
}
cmCTestBuildCommand::~cmCTestBuildCommand()
@ -60,20 +59,17 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
//
const char* ctestBuildConfiguration =
this->Makefile->GetDefinition("CTEST_BUILD_CONFIGURATION");
const char* cmakeBuildConfiguration =
(this->Values[ctb_CONFIGURATION] && *this->Values[ctb_CONFIGURATION])
? this->Values[ctb_CONFIGURATION]
const char* cmakeBuildConfiguration = !this->Configuration.empty()
? this->Configuration.c_str()
: ((ctestBuildConfiguration && *ctestBuildConfiguration)
? ctestBuildConfiguration
: this->CTest->GetConfigType().c_str());
const char* cmakeBuildAdditionalFlags =
(this->Values[ctb_FLAGS] && *this->Values[ctb_FLAGS])
? this->Values[ctb_FLAGS]
const char* cmakeBuildAdditionalFlags = !this->Flags.empty()
? this->Flags.c_str()
: this->Makefile->GetDefinition("CTEST_BUILD_FLAGS");
const char* cmakeBuildTarget =
(this->Values[ctb_TARGET] && *this->Values[ctb_TARGET])
? this->Values[ctb_TARGET]
const char* cmakeBuildTarget = !this->Target.empty()
? this->Target.c_str()
: this->Makefile->GetDefinition("CTEST_BUILD_TARGET");
if (cmakeGeneratorName && *cmakeGeneratorName) {
@ -153,16 +149,13 @@ bool cmCTestBuildCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
bool ret = cmCTestHandlerCommand::InitialPass(args, status);
if (this->Values[ctb_NUMBER_ERRORS] && *this->Values[ctb_NUMBER_ERRORS]) {
if (!this->NumberErrors.empty()) {
this->Makefile->AddDefinition(
this->Values[ctb_NUMBER_ERRORS],
std::to_string(this->Handler->GetTotalErrors()));
this->NumberErrors, std::to_string(this->Handler->GetTotalErrors()));
}
if (this->Values[ctb_NUMBER_WARNINGS] &&
*this->Values[ctb_NUMBER_WARNINGS]) {
if (!this->NumberWarnings.empty()) {
this->Makefile->AddDefinition(
this->Values[ctb_NUMBER_WARNINGS],
std::to_string(this->Handler->GetTotalWarnings()));
this->NumberWarnings, std::to_string(this->Handler->GetTotalWarnings()));
}
return ret;
}

View File

@ -27,7 +27,6 @@ class cmGlobalGenerator;
class cmCTestBuildCommand : public cmCTestHandlerCommand
{
public:
cmCTestBuildCommand();
~cmCTestBuildCommand() override;
/**
@ -49,23 +48,19 @@ public:
bool InitialPass(std::vector<std::string> const& args,
cmExecutionStatus& status) override;
cmGlobalGenerator* GlobalGenerator;
cmGlobalGenerator* GlobalGenerator = nullptr;
protected:
cmCTestBuildHandler* Handler;
enum
{
ctb_BUILD = ct_LAST,
ctb_NUMBER_ERRORS,
ctb_NUMBER_WARNINGS,
ctb_TARGET,
ctb_CONFIGURATION,
ctb_FLAGS,
ctb_PROJECT_NAME,
ctb_LAST
};
void BindArguments() override;
cmCTestGenericHandler* InitializeHandler() override;
std::string NumberErrors;
std::string NumberWarnings;
std::string Target;
std::string Configuration;
std::string Flags;
std::string ProjectName;
};
#endif

View File

@ -8,25 +8,25 @@
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cm_static_string_view.hxx"
#include "cmake.h"
#include <cstring>
#include <sstream>
#include <vector>
cmCTestConfigureCommand::cmCTestConfigureCommand()
void cmCTestConfigureCommand::BindArguments()
{
this->Arguments[ctc_OPTIONS] = "OPTIONS";
this->Arguments[ctc_LAST] = nullptr;
this->Last = ctc_LAST;
this->cmCTestHandlerCommand::BindArguments();
this->Bind("OPTIONS"_s, this->Options);
}
cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
{
std::vector<std::string> options;
if (this->Values[ctc_OPTIONS]) {
cmExpandList(this->Values[ctc_OPTIONS], options);
if (!this->Options.empty()) {
cmExpandList(this->Options, options);
}
if (this->CTest->GetCTestConfiguration("BuildDirectory").empty()) {

View File

@ -23,8 +23,6 @@ class cmCTestGenericHandler;
class cmCTestConfigureCommand : public cmCTestHandlerCommand
{
public:
cmCTestConfigureCommand();
/**
* This is a virtual constructor for the command.
*/
@ -42,14 +40,10 @@ public:
std::string GetName() const override { return "ctest_configure"; }
protected:
void BindArguments() override;
cmCTestGenericHandler* InitializeHandler() override;
enum
{
ctc_FIRST = ct_LAST,
ctc_OPTIONS,
ctc_LAST
};
std::string Options;
};
#endif

View File

@ -2,14 +2,26 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestCoverageCommand.h"
#include <set>
#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestCoverageHandler.h"
#include "cm_static_string_view.hxx"
class cmCTestGenericHandler;
cmCTestCoverageCommand::cmCTestCoverageCommand()
void cmCTestCoverageCommand::BindArguments()
{
this->LabelsMentioned = false;
this->cmCTestHandlerCommand::BindArguments();
this->Bind("LABELS"_s, this->Labels);
}
void cmCTestCoverageCommand::CheckArguments(
std::vector<std::string> const& keywords)
{
this->LabelsMentioned =
!this->Labels.empty() || cmContains(keywords, "LABELS");
}
cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
@ -24,34 +36,10 @@ cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
// If a LABELS option was given, select only files with the labels.
if (this->LabelsMentioned) {
handler->SetLabelFilter(this->Labels);
handler->SetLabelFilter(
std::set<std::string>(this->Labels.begin(), this->Labels.end()));
}
handler->SetQuiet(this->Quiet);
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);
}

View File

@ -8,9 +8,9 @@
#include "cmCTestHandlerCommand.h"
#include "cmCommand.h"
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "cm_memory.hxx"
@ -24,8 +24,6 @@ class cmCTestGenericHandler;
class cmCTestCoverageCommand : public cmCTestHandlerCommand
{
public:
cmCTestCoverageCommand();
/**
* This is a virtual constructor for the command.
*/
@ -42,22 +40,13 @@ public:
*/
std::string GetName() const override { return "ctest_coverage"; }
using Superclass = cmCTestHandlerCommand;
protected:
void BindArguments() override;
void CheckArguments(std::vector<std::string> const& keywords) override;
cmCTestGenericHandler* InitializeHandler() override;
bool CheckArgumentKeyword(std::string const& arg) override;
bool CheckArgumentValue(std::string const& arg) override;
enum
{
ArgumentDoingLabels = Superclass::ArgumentDoingLast1,
ArgumentDoingLast2
};
bool LabelsMentioned;
std::set<std::string> Labels;
std::vector<std::string> Labels;
};
#endif

View File

@ -7,31 +7,16 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
#include "cm_static_string_view.hxx"
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <sstream>
cmCTestHandlerCommand::cmCTestHandlerCommand()
{
const size_t INIT_SIZE = 100;
size_t cc;
this->Arguments.reserve(INIT_SIZE);
for (cc = 0; cc < INIT_SIZE; ++cc) {
this->Arguments.push_back(nullptr);
}
this->Arguments[ct_RETURN_VALUE] = "RETURN_VALUE";
this->Arguments[ct_CAPTURE_CMAKE_ERROR] = "CAPTURE_CMAKE_ERROR";
this->Arguments[ct_SOURCE] = "SOURCE";
this->Arguments[ct_BUILD] = "BUILD";
this->Arguments[ct_SUBMIT_INDEX] = "SUBMIT_INDEX";
this->Last = ct_LAST;
this->AppendXML = false;
this->Quiet = false;
}
namespace {
// class to save and restore the error state for ctest_* commands
// if a ctest_* command has a CAPTURE_CMAKE_ERROR then put the error
@ -90,30 +75,30 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
// save error state and restore it if needed
SaveRestoreErrorState errorState;
// Allocate space for argument values.
this->Values.clear();
this->Values.resize(this->Last, nullptr);
this->BindArguments();
// Process input arguments.
this->ArgumentDoing = ArgumentDoingNone;
// look at all arguments and do not short circuit on the first
// bad one so that CAPTURE_CMAKE_ERROR can override setting the
// global error state
bool foundBadArgument = false;
for (std::string const& arg : args) {
// Check this argument.
if (!this->CheckArgumentKeyword(arg) && !this->CheckArgumentValue(arg)) {
std::ostringstream e;
e << "called with unknown argument \"" << arg << "\".";
this->SetError(e.str());
foundBadArgument = true;
}
// note bad argument
if (this->ArgumentDoing == ArgumentDoingError) {
foundBadArgument = true;
}
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->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat("Called with more than one value for ", *it));
}
bool captureCMakeError = (this->Values[ct_CAPTURE_CMAKE_ERROR] &&
*this->Values[ct_CAPTURE_CMAKE_ERROR]);
bool const foundBadArgument = !unparsedArguments.empty();
if (foundBadArgument) {
this->SetError(cmStrCat("called with unknown argument \"",
unparsedArguments.front(), "\"."));
}
bool const captureCMakeError = !this->CaptureCMakeError.empty();
// now that arguments are parsed check to see if there is a
// CAPTURE_CMAKE_ERROR specified let the errorState object know.
if (captureCMakeError) {
@ -123,8 +108,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
if (foundBadArgument) {
// store the cmake error
if (captureCMakeError) {
this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
"-1");
this->Makefile->AddDefinition(this->CaptureCMakeError, "-1");
std::string const err = this->GetName() + " " + status.GetError();
if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n");
@ -146,10 +130,9 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
this->CTest->SetConfigType(ctestConfigType);
}
if (this->Values[ct_BUILD]) {
if (!this->Build.empty()) {
this->CTest->SetCTestConfiguration(
"BuildDirectory",
cmSystemTools::CollapseFullPath(this->Values[ct_BUILD]).c_str(),
"BuildDirectory", cmSystemTools::CollapseFullPath(this->Build).c_str(),
this->Quiet);
} else {
std::string const& bdir =
@ -163,13 +146,11 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
"CTEST_BINARY_DIRECTORY not set" << std::endl;);
}
}
if (this->Values[ct_SOURCE]) {
if (!this->Source.empty()) {
cmCTestLog(this->CTest, DEBUG,
"Set source directory to: " << this->Values[ct_SOURCE]
<< std::endl);
"Set source directory to: " << this->Source << std::endl);
this->CTest->SetCTestConfiguration(
"SourceDirectory",
cmSystemTools::CollapseFullPath(this->Values[ct_SOURCE]).c_str(),
"SourceDirectory", cmSystemTools::CollapseFullPath(this->Source).c_str(),
this->Quiet);
} else {
this->CTest->SetCTestConfiguration(
@ -192,8 +173,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
"Cannot instantiate test handler " << this->GetName()
<< std::endl);
if (captureCMakeError) {
this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
"-1");
this->Makefile->AddDefinition(this->CaptureCMakeError, "-1");
std::string const& err = status.GetError();
if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n");
@ -203,11 +183,11 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
return false;
}
handler->SetAppendXML(this->AppendXML);
handler->SetAppendXML(this->Append);
handler->PopulateCustomVectors(this->Makefile);
if (this->Values[ct_SUBMIT_INDEX]) {
handler->SetSubmitIndex(atoi(this->Values[ct_SUBMIT_INDEX]));
if (!this->SubmitIndex.empty()) {
handler->SetSubmitIndex(atoi(this->SubmitIndex.c_str()));
}
cmWorkingDirectory workdir(
this->CTest->GetCTestConfiguration("BuildDirectory"));
@ -216,8 +196,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
this->CTest->GetCTestConfiguration("BuildDirectory") +
" : " + std::strerror(workdir.GetLastResult()));
if (captureCMakeError) {
this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
"-1");
this->Makefile->AddDefinition(this->CaptureCMakeError, "-1");
cmCTestLog(this->CTest, ERROR_MESSAGE,
this->GetName() << " " << status.GetError() << "\n");
// return success because failure is recorded in CAPTURE_CMAKE_ERROR
@ -227,9 +206,8 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
}
int res = handler->ProcessHandler();
if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) {
this->Makefile->AddDefinition(this->Values[ct_RETURN_VALUE],
std::to_string(res));
if (!this->ReturnValue.empty()) {
this->Makefile->AddDefinition(this->ReturnValue, std::to_string(res));
}
this->ProcessAdditionalValues(handler);
// log the error message if there was an error
@ -245,8 +223,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
}
}
// store the captured cmake error state 0 or -1
this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
returnString);
this->Makefile->AddDefinition(this->CaptureCMakeError, returnString);
}
return true;
}
@ -255,47 +232,17 @@ void cmCTestHandlerCommand::ProcessAdditionalValues(cmCTestGenericHandler*)
{
}
bool cmCTestHandlerCommand::CheckArgumentKeyword(std::string const& arg)
void cmCTestHandlerCommand::BindArguments()
{
// Look for non-value arguments common to all commands.
if (arg == "APPEND") {
this->ArgumentDoing = ArgumentDoingNone;
this->AppendXML = true;
return true;
}
if (arg == "QUIET") {
this->ArgumentDoing = ArgumentDoingNone;
this->Quiet = true;
return true;
}
// Check for a keyword in our argument/value table.
for (unsigned int k = 0; k < this->Arguments.size(); ++k) {
if (this->Arguments[k] && arg == this->Arguments[k]) {
this->ArgumentDoing = ArgumentDoingKeyword;
this->ArgumentIndex = k;
return true;
}
}
return false;
this->Bind("APPEND"_s, this->Append);
this->Bind("QUIET"_s, this->Quiet);
this->Bind("RETURN_VALUE"_s, this->ReturnValue);
this->Bind("CAPTURE_CMAKE_ERROR"_s, this->CaptureCMakeError);
this->Bind("SOURCE"_s, this->Source);
this->Bind("BUILD"_s, this->Build);
this->Bind("SUBMIT_INDEX"_s, this->SubmitIndex);
}
bool cmCTestHandlerCommand::CheckArgumentValue(std::string const& arg)
void cmCTestHandlerCommand::CheckArguments(std::vector<std::string> const&)
{
if (this->ArgumentDoing == ArgumentDoingKeyword) {
this->ArgumentDoing = ArgumentDoingNone;
unsigned int k = this->ArgumentIndex;
if (this->Values[k]) {
std::ostringstream e;
e << "Called with more than one value for " << this->Arguments[k];
this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
this->ArgumentDoing = ArgumentDoingError;
return true;
}
this->Values[k] = arg.c_str();
cmCTestLog(this->CTest, DEBUG,
"Set " << this->Arguments[k] << " to " << arg << "\n");
return true;
}
return false;
}

View File

@ -5,9 +5,9 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmArgumentParser.h"
#include "cmCTestCommand.h"
#include <stddef.h>
#include <string>
#include <vector>
@ -19,11 +19,11 @@ class cmExecutionStatus;
*
* cmCTestHandlerCommand defineds the command to test the project.
*/
class cmCTestHandlerCommand : public cmCTestCommand
class cmCTestHandlerCommand
: public cmCTestCommand
, public cmArgumentParser<void>
{
public:
cmCTestHandlerCommand();
/**
* The name of the command as specified in CMakeList.txt.
*/
@ -36,42 +36,22 @@ public:
bool InitialPass(std::vector<std::string> const& args,
cmExecutionStatus& status) override;
enum
{
ct_NONE,
ct_RETURN_VALUE,
ct_CAPTURE_CMAKE_ERROR,
ct_BUILD,
ct_SOURCE,
ct_SUBMIT_INDEX,
ct_LAST
};
protected:
virtual cmCTestGenericHandler* InitializeHandler() = 0;
virtual void ProcessAdditionalValues(cmCTestGenericHandler* handler);
// Command argument handling.
virtual bool CheckArgumentKeyword(std::string const& arg);
virtual bool CheckArgumentValue(std::string const& arg);
enum
{
ArgumentDoingNone,
ArgumentDoingError,
ArgumentDoingKeyword,
ArgumentDoingLast1
};
int ArgumentDoing;
unsigned int ArgumentIndex;
virtual void BindArguments();
virtual void CheckArguments(std::vector<std::string> const& keywords);
bool AppendXML;
bool Quiet;
std::string ReturnVariable;
std::vector<const char*> Arguments;
std::vector<const char*> Values;
size_t Last;
bool Append = false;
bool Quiet = false;
std::string CaptureCMakeError;
std::string ReturnValue;
std::string Build;
std::string Source;
std::string SubmitIndex;
};
#define CTEST_COMMAND_APPEND_OPTION_DOCS \

View File

@ -2,18 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestMemCheckCommand.h"
#include <string>
#include <vector>
#include "cmCTest.h"
#include "cmCTestMemCheckHandler.h"
#include "cmMakefile.h"
#include "cm_static_string_view.hxx"
cmCTestMemCheckCommand::cmCTestMemCheckCommand()
void cmCTestMemCheckCommand::BindArguments()
{
this->Arguments[ctm_DEFECT_COUNT] = "DEFECT_COUNT";
this->Arguments[ctm_LAST] = nullptr;
this->Last = ctm_LAST;
this->cmCTestTestCommand::BindArguments();
this->Bind("DEFECT_COUNT"_s, this->DefectCount);
}
cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler()
@ -43,9 +40,9 @@ cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler()
void cmCTestMemCheckCommand::ProcessAdditionalValues(
cmCTestGenericHandler* handler)
{
if (this->Values[ctm_DEFECT_COUNT] && *this->Values[ctm_DEFECT_COUNT]) {
if (!this->DefectCount.empty()) {
this->Makefile->AddDefinition(
this->Values[ctm_DEFECT_COUNT],
this->DefectCount,
std::to_string(
static_cast<cmCTestMemCheckHandler*>(handler)->GetDefectCount()));
}

View File

@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <utility>
#include "cm_memory.hxx"
@ -22,8 +23,6 @@ class cmCTestGenericHandler;
class cmCTestMemCheckCommand : public cmCTestTestCommand
{
public:
cmCTestMemCheckCommand();
/**
* This is a virtual constructor for the command.
*/
@ -36,15 +35,13 @@ public:
}
protected:
void BindArguments() override;
cmCTestGenericHandler* InitializeActualHandler() override;
void ProcessAdditionalValues(cmCTestGenericHandler* handler) override;
enum
{
ctm_DEFECT_COUNT = ctt_LAST,
ctm_LAST
};
std::string DefectCount;
};
#endif

View File

@ -2,14 +2,18 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestSubmitCommand.h"
#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestSubmitHandler.h"
#include "cmCommand.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cm_static_string_view.hxx"
#include <set>
#include <sstream>
#include <utility>
@ -17,18 +21,6 @@
class cmExecutionStatus;
cmCTestSubmitCommand::cmCTestSubmitCommand()
{
this->PartsMentioned = false;
this->FilesMentioned = false;
this->InternalTest = false;
this->RetryCount = "";
this->RetryDelay = "";
this->CDashUpload = false;
this->Arguments[cts_BUILD_ID] = "BUILD_ID";
this->Last = cts_LAST;
}
/**
* This is a virtual constructor for the command.
*/
@ -106,13 +98,18 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
// without any of the default parts.
//
handler->SelectParts(std::set<cmCTest::Part>());
handler->SelectFiles(this->Files);
handler->SelectFiles(
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) {
handler->SelectParts(this->Parts);
auto parts =
cmMakeRange(this->Parts).transform([this](std::string const& arg) {
return this->CTest->GetPartFromName(arg.c_str());
});
handler->SelectParts(std::set<cmCTest::Part>(parts.begin(), parts.end()));
}
// Pass along any HTTPHEADER to the handler if this option was given.
@ -140,133 +137,61 @@ bool cmCTestSubmitCommand::InitialPass(std::vector<std::string> const& args,
bool ret = this->cmCTestHandlerCommand::InitialPass(args, status);
if (this->Values[cts_BUILD_ID] && *this->Values[cts_BUILD_ID]) {
this->Makefile->AddDefinition(this->Values[cts_BUILD_ID],
this->CTest->GetBuildID());
if (!this->BuildID.empty()) {
this->Makefile->AddDefinition(this->BuildID, this->CTest->GetBuildID());
}
return ret;
}
bool cmCTestSubmitCommand::CheckArgumentKeyword(std::string const& arg)
void cmCTestSubmitCommand::BindArguments()
{
if (this->CDashUpload) {
// Arguments specific to the CDASH_UPLOAD signature.
if (arg == "CDASH_UPLOAD") {
this->ArgumentDoing = ArgumentDoingCDashUpload;
return true;
}
if (arg == "CDASH_UPLOAD_TYPE") {
this->ArgumentDoing = ArgumentDoingCDashUploadType;
return true;
}
this->Bind("CDASH_UPLOAD", this->CDashUploadFile);
this->Bind("CDASH_UPLOAD_TYPE", this->CDashUploadType);
} else {
// Arguments that cannot be used with CDASH_UPLOAD.
if (arg == "PARTS") {
this->ArgumentDoing = ArgumentDoingParts;
this->PartsMentioned = true;
return true;
}
if (arg == "FILES") {
this->ArgumentDoing = ArgumentDoingFiles;
this->FilesMentioned = true;
return true;
}
this->Bind("PARTS"_s, this->Parts);
this->Bind("FILES"_s, this->Files);
}
// Arguments used by both modes.
if (arg == "HTTPHEADER") {
this->ArgumentDoing = ArgumentDoingHttpHeader;
return true;
}
if (arg == "RETRY_COUNT") {
this->ArgumentDoing = ArgumentDoingRetryCount;
return true;
}
if (arg == "RETRY_DELAY") {
this->ArgumentDoing = ArgumentDoingRetryDelay;
return true;
}
if (arg == "SUBMIT_URL") {
this->ArgumentDoing = ArgumentDoingSubmitURL;
return true;
}
if (arg == "INTERNAL_TEST_CHECKSUM") {
this->InternalTest = true;
return true;
}
this->Bind("BUILD_ID"_s, this->BuildID);
this->Bind("HTTPHEADER"_s, this->HttpHeaders);
this->Bind("RETRY_COUNT"_s, this->RetryCount);
this->Bind("RETRY_DELAY"_s, this->RetryDelay);
this->Bind("SUBMIT_URL"_s, this->SubmitURL);
this->Bind("INTERNAL_TEST_CHECKSUM", this->InternalTest);
// Look for other arguments.
return this->Superclass::CheckArgumentKeyword(arg);
this->cmCTestHandlerCommand::BindArguments();
}
bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg)
void cmCTestSubmitCommand::CheckArguments(
std::vector<std::string> const& keywords)
{
// Handle states specific to this command.
if (this->ArgumentDoing == ArgumentDoingParts) {
this->PartsMentioned = !this->Parts.empty() || cmContains(keywords, "PARTS");
this->FilesMentioned = !this->Files.empty() || cmContains(keywords, "FILES");
cmEraseIf(this->Parts, [this](std::string const& arg) -> bool {
cmCTest::Part p = this->CTest->GetPartFromName(arg.c_str());
if (p != cmCTest::PartCount) {
this->Parts.insert(p);
} else {
if (p == cmCTest::PartCount) {
std::ostringstream e;
e << "Part name \"" << arg << "\" is invalid.";
this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
this->ArgumentDoing = ArgumentDoingError;
return true;
}
return true;
}
return false;
});
if (this->ArgumentDoing == ArgumentDoingFiles) {
if (cmSystemTools::FileExists(arg)) {
this->Files.insert(arg);
} else {
cmEraseIf(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());
this->ArgumentDoing = ArgumentDoingError;
return true;
}
return true;
}
if (this->ArgumentDoing == ArgumentDoingHttpHeader) {
this->HttpHeaders.push_back(arg);
return true;
}
if (this->ArgumentDoing == ArgumentDoingRetryCount) {
this->RetryCount = arg;
return true;
}
if (this->ArgumentDoing == ArgumentDoingRetryDelay) {
this->RetryDelay = arg;
return true;
}
if (this->ArgumentDoing == ArgumentDoingCDashUpload) {
this->ArgumentDoing = ArgumentDoingNone;
this->CDashUploadFile = arg;
return true;
}
if (this->ArgumentDoing == ArgumentDoingCDashUploadType) {
this->ArgumentDoing = ArgumentDoingNone;
this->CDashUploadType = arg;
return true;
}
if (this->ArgumentDoing == ArgumentDoingSubmitURL) {
this->ArgumentDoing = ArgumentDoingNone;
this->SubmitURL = arg;
return true;
}
// Look for other arguments.
return this->Superclass::CheckArgumentValue(arg);
return false;
});
}

View File

@ -5,11 +5,9 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmCTest.h"
#include "cmCTestHandlerCommand.h"
#include <memory>
#include <set>
#include <string>
#include <vector>
@ -26,7 +24,6 @@ class cmExecutionStatus;
class cmCTestSubmitCommand : public cmCTestHandlerCommand
{
public:
cmCTestSubmitCommand();
std::unique_ptr<cmCommand> Clone() override;
bool InitialPass(std::vector<std::string> const& args,
@ -37,45 +34,26 @@ public:
*/
std::string GetName() const override { return "ctest_submit"; }
using Superclass = cmCTestHandlerCommand;
protected:
void BindArguments() override;
void CheckArguments(std::vector<std::string> const& keywords) override;
cmCTestGenericHandler* InitializeHandler() override;
bool CheckArgumentKeyword(std::string const& arg) override;
bool CheckArgumentValue(std::string const& arg) override;
bool CDashUpload = false;
bool FilesMentioned = false;
bool InternalTest = false;
bool PartsMentioned = false;
enum
{
ArgumentDoingParts = Superclass::ArgumentDoingLast1,
ArgumentDoingFiles,
ArgumentDoingRetryDelay,
ArgumentDoingRetryCount,
ArgumentDoingCDashUpload,
ArgumentDoingCDashUploadType,
ArgumentDoingHttpHeader,
ArgumentDoingSubmitURL,
ArgumentDoingLast2
};
enum
{
cts_BUILD_ID = ct_LAST,
cts_LAST
};
bool PartsMentioned;
std::set<cmCTest::Part> Parts;
bool FilesMentioned;
bool InternalTest;
std::set<std::string> Files;
std::string RetryCount;
std::string RetryDelay;
bool CDashUpload;
std::string BuildID;
std::string CDashUploadFile;
std::string CDashUploadType;
std::vector<std::string> HttpHeaders;
std::string RetryCount;
std::string RetryDelay;
std::string SubmitURL;
std::vector<std::string> Files;
std::vector<std::string> HttpHeaders;
std::vector<std::string> Parts;
};
#endif

View File

@ -8,30 +8,29 @@
#include "cmDuration.h"
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
#include "cm_static_string_view.hxx"
#include <chrono>
#include <cstdlib>
#include <sstream>
#include <vector>
cmCTestTestCommand::cmCTestTestCommand()
void cmCTestTestCommand::BindArguments()
{
this->Arguments[ctt_START] = "START";
this->Arguments[ctt_END] = "END";
this->Arguments[ctt_STRIDE] = "STRIDE";
this->Arguments[ctt_EXCLUDE] = "EXCLUDE";
this->Arguments[ctt_INCLUDE] = "INCLUDE";
this->Arguments[ctt_EXCLUDE_LABEL] = "EXCLUDE_LABEL";
this->Arguments[ctt_INCLUDE_LABEL] = "INCLUDE_LABEL";
this->Arguments[ctt_EXCLUDE_FIXTURE] = "EXCLUDE_FIXTURE";
this->Arguments[ctt_EXCLUDE_FIXTURE_SETUP] = "EXCLUDE_FIXTURE_SETUP";
this->Arguments[ctt_EXCLUDE_FIXTURE_CLEANUP] = "EXCLUDE_FIXTURE_CLEANUP";
this->Arguments[ctt_PARALLEL_LEVEL] = "PARALLEL_LEVEL";
this->Arguments[ctt_SCHEDULE_RANDOM] = "SCHEDULE_RANDOM";
this->Arguments[ctt_STOP_TIME] = "STOP_TIME";
this->Arguments[ctt_TEST_LOAD] = "TEST_LOAD";
this->Arguments[ctt_LAST] = nullptr;
this->Last = ctt_LAST;
this->cmCTestHandlerCommand::BindArguments();
this->Bind("START"_s, this->Start);
this->Bind("END"_s, this->End);
this->Bind("STRIDE"_s, this->Stride);
this->Bind("EXCLUDE"_s, this->Exclude);
this->Bind("INCLUDE"_s, this->Include);
this->Bind("EXCLUDE_LABEL"_s, this->ExcludeLabel);
this->Bind("INCLUDE_LABEL"_s, this->IncludeLabel);
this->Bind("EXCLUDE_FIXTURE"_s, this->ExcludeFixture);
this->Bind("EXCLUDE_FIXTURE_SETUP"_s, this->ExcludeFixtureSetup);
this->Bind("EXCLUDE_FIXTURE_CLEANUP"_s, this->ExcludeFixtureCleanup);
this->Bind("PARALLEL_LEVEL"_s, this->ParallelLevel);
this->Bind("SCHEDULE_RANDOM"_s, this->ScheduleRandom);
this->Bind("STOP_TIME"_s, this->StopTime);
this->Bind("TEST_LOAD"_s, this->TestLoad);
}
cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
@ -51,57 +50,44 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
}
this->CTest->SetTimeOut(timeout);
cmCTestGenericHandler* handler = this->InitializeActualHandler();
if (this->Values[ctt_START] || this->Values[ctt_END] ||
this->Values[ctt_STRIDE]) {
std::ostringstream testsToRunString;
if (this->Values[ctt_START]) {
testsToRunString << this->Values[ctt_START];
}
testsToRunString << ",";
if (this->Values[ctt_END]) {
testsToRunString << this->Values[ctt_END];
}
testsToRunString << ",";
if (this->Values[ctt_STRIDE]) {
testsToRunString << this->Values[ctt_STRIDE];
}
handler->SetOption("TestsToRunInformation",
testsToRunString.str().c_str());
if (!this->Start.empty() || !this->End.empty() || !this->Stride.empty()) {
handler->SetOption(
"TestsToRunInformation",
cmStrCat(this->Start, ',', this->End, ',', this->Stride).c_str());
}
if (this->Values[ctt_EXCLUDE]) {
handler->SetOption("ExcludeRegularExpression", this->Values[ctt_EXCLUDE]);
if (!this->Exclude.empty()) {
handler->SetOption("ExcludeRegularExpression", this->Exclude.c_str());
}
if (this->Values[ctt_INCLUDE]) {
handler->SetOption("IncludeRegularExpression", this->Values[ctt_INCLUDE]);
if (!this->Include.empty()) {
handler->SetOption("IncludeRegularExpression", this->Include.c_str());
}
if (this->Values[ctt_EXCLUDE_LABEL]) {
if (!this->ExcludeLabel.empty()) {
handler->SetOption("ExcludeLabelRegularExpression",
this->Values[ctt_EXCLUDE_LABEL]);
this->ExcludeLabel.c_str());
}
if (this->Values[ctt_INCLUDE_LABEL]) {
handler->SetOption("LabelRegularExpression",
this->Values[ctt_INCLUDE_LABEL]);
if (!this->IncludeLabel.empty()) {
handler->SetOption("LabelRegularExpression", this->IncludeLabel.c_str());
}
if (this->Values[ctt_EXCLUDE_FIXTURE]) {
if (!this->ExcludeFixture.empty()) {
handler->SetOption("ExcludeFixtureRegularExpression",
this->Values[ctt_EXCLUDE_FIXTURE]);
this->ExcludeFixture.c_str());
}
if (this->Values[ctt_EXCLUDE_FIXTURE_SETUP]) {
if (!this->ExcludeFixtureSetup.empty()) {
handler->SetOption("ExcludeFixtureSetupRegularExpression",
this->Values[ctt_EXCLUDE_FIXTURE_SETUP]);
this->ExcludeFixtureSetup.c_str());
}
if (this->Values[ctt_EXCLUDE_FIXTURE_CLEANUP]) {
if (!this->ExcludeFixtureCleanup.empty()) {
handler->SetOption("ExcludeFixtureCleanupRegularExpression",
this->Values[ctt_EXCLUDE_FIXTURE_CLEANUP]);
this->ExcludeFixtureCleanup.c_str());
}
if (this->Values[ctt_PARALLEL_LEVEL]) {
handler->SetOption("ParallelLevel", this->Values[ctt_PARALLEL_LEVEL]);
if (!this->ParallelLevel.empty()) {
handler->SetOption("ParallelLevel", this->ParallelLevel.c_str());
}
if (this->Values[ctt_SCHEDULE_RANDOM]) {
handler->SetOption("ScheduleRandom", this->Values[ctt_SCHEDULE_RANDOM]);
if (!this->ScheduleRandom.empty()) {
handler->SetOption("ScheduleRandom", this->ScheduleRandom.c_str());
}
if (this->Values[ctt_STOP_TIME]) {
this->CTest->SetStopTime(this->Values[ctt_STOP_TIME]);
if (!this->StopTime.empty()) {
this->CTest->SetStopTime(this->StopTime);
}
// Test load is determined by: TEST_LOAD argument,
@ -109,12 +95,12 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
// command line argument... in that order.
unsigned long testLoad;
const char* ctestTestLoad = this->Makefile->GetDefinition("CTEST_TEST_LOAD");
if (this->Values[ctt_TEST_LOAD] && *this->Values[ctt_TEST_LOAD]) {
if (!cmStrToULong(this->Values[ctt_TEST_LOAD], &testLoad)) {
if (!this->TestLoad.empty()) {
if (!cmStrToULong(this->TestLoad.c_str(), &testLoad)) {
testLoad = 0;
cmCTestLog(this->CTest, WARNING,
"Invalid value for 'TEST_LOAD' : "
<< this->Values[ctt_TEST_LOAD] << std::endl);
"Invalid value for 'TEST_LOAD' : " << this->TestLoad
<< std::endl);
}
} else if (ctestTestLoad && *ctestTestLoad) {
if (!cmStrToULong(ctestTestLoad, &testLoad)) {

View File

@ -23,8 +23,6 @@ class cmCTestGenericHandler;
class cmCTestTestCommand : public cmCTestHandlerCommand
{
public:
cmCTestTestCommand();
/**
* This is a virtual constructor for the command.
*/
@ -42,29 +40,24 @@ public:
std::string GetName() const override { return "ctest_test"; }
protected:
void BindArguments() override;
virtual cmCTestGenericHandler* InitializeActualHandler();
cmCTestGenericHandler* InitializeHandler() override;
enum
{
ctt_BUILD = ct_LAST,
ctt_RETURN_VALUE,
ctt_START,
ctt_END,
ctt_STRIDE,
ctt_EXCLUDE,
ctt_INCLUDE,
ctt_EXCLUDE_LABEL,
ctt_INCLUDE_LABEL,
ctt_EXCLUDE_FIXTURE,
ctt_EXCLUDE_FIXTURE_SETUP,
ctt_EXCLUDE_FIXTURE_CLEANUP,
ctt_PARALLEL_LEVEL,
ctt_SCHEDULE_RANDOM,
ctt_STOP_TIME,
ctt_TEST_LOAD,
ctt_LAST
};
std::string Start;
std::string End;
std::string Stride;
std::string Exclude;
std::string Include;
std::string ExcludeLabel;
std::string IncludeLabel;
std::string ExcludeFixture;
std::string ExcludeFixtureSetup;
std::string ExcludeFixtureCleanup;
std::string ParallelLevel;
std::string ScheduleRandom;
std::string StopTime;
std::string TestLoad;
};
#endif

View File

@ -7,14 +7,11 @@
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include <vector>
cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
{
if (this->Values[ct_SOURCE]) {
if (!this->Source.empty()) {
this->CTest->SetCTestConfiguration(
"SourceDirectory",
cmSystemTools::CollapseFullPath(this->Values[ct_SOURCE]).c_str(),
"SourceDirectory", cmSystemTools::CollapseFullPath(this->Source).c_str(),
this->Quiet);
} else {
this->CTest->SetCTestConfiguration(

View File

@ -23,8 +23,6 @@ class cmCTestGenericHandler;
class cmCTestUpdateCommand : public cmCTestHandlerCommand
{
public:
cmCTestUpdateCommand() {}
/**
* This is a virtual constructor for the command.
*/

View File

@ -2,61 +2,45 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestUploadCommand.h"
#include <set>
#include <sstream>
#include <vector>
#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestUploadHandler.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmSystemTools.h"
#include "cm_static_string_view.hxx"
void cmCTestUploadCommand::BindArguments()
{
this->Bind("FILES"_s, this->Files);
this->Bind("QUIET"_s, this->Quiet);
this->Bind("CAPTURE_CMAKE_ERROR"_s, this->CaptureCMakeError);
}
void cmCTestUploadCommand::CheckArguments(std::vector<std::string> const&)
{
cmEraseIf(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;
});
}
cmCTestGenericHandler* cmCTestUploadCommand::InitializeHandler()
{
cmCTestUploadHandler* handler = this->CTest->GetUploadHandler();
handler->Initialize();
handler->SetFiles(this->Files);
handler->SetFiles(
std::set<std::string>(this->Files.begin(), this->Files.end()));
handler->SetQuiet(this->Quiet);
return handler;
}
bool cmCTestUploadCommand::CheckArgumentKeyword(std::string const& arg)
{
if (arg == "FILES") {
this->ArgumentDoing = ArgumentDoingFiles;
return true;
}
if (arg == "QUIET") {
this->ArgumentDoing = ArgumentDoingNone;
this->Quiet = true;
return true;
}
if (arg == "CAPTURE_CMAKE_ERROR") {
this->ArgumentDoing = ArgumentDoingCaptureCMakeError;
return true;
}
return false;
}
bool cmCTestUploadCommand::CheckArgumentValue(std::string const& arg)
{
if (this->ArgumentDoing == ArgumentDoingCaptureCMakeError) {
this->Values[ct_CAPTURE_CMAKE_ERROR] = arg.c_str();
return true;
}
if (this->ArgumentDoing == ArgumentDoingFiles) {
if (cmSystemTools::FileExists(arg)) {
this->Files.insert(arg);
return true;
}
std::ostringstream e;
e << "File \"" << arg << "\" does not exist. Cannot submit "
<< "a non-existent file.";
this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
this->ArgumentDoing = ArgumentDoingError;
return false;
}
// Look for other arguments.
return this->Superclass::CheckArgumentValue(arg);
}

View File

@ -8,9 +8,9 @@
#include "cmCTestHandlerCommand.h"
#include "cmCommand.h"
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "cm_memory.hxx"
@ -41,22 +41,12 @@ public:
*/
std::string GetName() const override { return "ctest_upload"; }
using Superclass = cmCTestHandlerCommand;
protected:
void BindArguments() override;
void CheckArguments(std::vector<std::string> const&) override;
cmCTestGenericHandler* InitializeHandler() override;
bool CheckArgumentKeyword(std::string const& arg) override;
bool CheckArgumentValue(std::string const& arg) override;
enum
{
ArgumentDoingFiles = Superclass::ArgumentDoingLast1,
ArgumentDoingCaptureCMakeError,
ArgumentDoingLast2
};
std::set<std::string> Files;
std::vector<std::string> Files;
};
#endif