diff options
author | Bill Hoffman <bill.hoffman@kitware.com> | 2016-07-28 19:12:43 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2016-09-20 17:14:20 (GMT) |
commit | d328dc6853e211dc05c4abcf62cc64b9c91235a2 (patch) | |
tree | 188238fc8ae3c7a85dc3edf1eae3a70b85b6197f /Source/CTest | |
parent | 9ac2e189607433b45b252a1e2261ccfaf11e492b (diff) | |
download | CMake-d328dc6853e211dc05c4abcf62cc64b9c91235a2.zip CMake-d328dc6853e211dc05c4abcf62cc64b9c91235a2.tar.gz CMake-d328dc6853e211dc05c4abcf62cc64b9c91235a2.tar.bz2 |
CTest: Add CAPTURE_CMAKE_ERROR val to `ctest_*` commands
If a `ctest_*` command has CAPTURE_CMAKE_ERROR then any errors generated
by cmake during that command will cause the value to be assigned `-1`.
This will prevent a `ctest -S` script from returning non-zero unless the
script explicitly calls `message(FATAL_ERROR)`.
Diffstat (limited to 'Source/CTest')
-rw-r--r-- | Source/CTest/cmCTestHandlerCommand.cxx | 112 | ||||
-rw-r--r-- | Source/CTest/cmCTestHandlerCommand.h | 1 | ||||
-rw-r--r-- | Source/CTest/cmCTestUploadCommand.cxx | 8 | ||||
-rw-r--r-- | Source/CTest/cmCTestUploadCommand.h | 1 |
4 files changed, 118 insertions, 4 deletions
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index e8e2956..19d8595 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -31,6 +31,7 @@ cmCTestHandlerCommand::cmCTestHandlerCommand() this->Arguments.push_back(CM_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"; @@ -39,15 +40,71 @@ cmCTestHandlerCommand::cmCTestHandlerCommand() 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 +// state into there and restore the system wide error to what +// it was before the command ran +class SaveRestoreErrorState +{ +public: + SaveRestoreErrorState() + { + this->InitialErrorState = cmSystemTools::GetErrorOccuredFlag(); + cmSystemTools::ResetErrorOccuredFlag(); // rest the error state + this->CaptureCMakeErrorValue = false; + } + // if the function has a CAPTURE_CMAKE_ERROR then we should restore + // the error state to what it was before the function was run + // if not then let the error state be what it is + void CaptureCMakeError() { this->CaptureCMakeErrorValue = true; } + ~SaveRestoreErrorState() + { + // if we are not saving the return value then make sure + // if it was in error it goes back to being in error + // otherwise leave it be what it is + if (!this->CaptureCMakeErrorValue) { + if (this->InitialErrorState) { + cmSystemTools::SetErrorOccured(); + } + return; + } + // if we have saved the error in a return variable + // then put things back exactly like they were + bool currentState = cmSystemTools::GetErrorOccuredFlag(); + // if the state changed during this command we need + // to handle it, if not then nothing needs to be done + if (currentState != this->InitialErrorState) { + // restore the initial error state + if (this->InitialErrorState) { + cmSystemTools::SetErrorOccured(); + } else { + cmSystemTools::ResetErrorOccuredFlag(); + } + } + } + +private: + bool InitialErrorState; + bool CaptureCMakeErrorValue; +}; +} + bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus& /*unused*/) { + // save error state and restore it if needed + SaveRestoreErrorState errorState; // Allocate space for argument values. this->Values.clear(); this->Values.resize(this->Last, CM_NULLPTR); // 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 (unsigned int i = 0; i < args.size(); ++i) { // Check this argument. if (!this->CheckArgumentKeyword(args[i]) && @@ -55,14 +112,36 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, std::ostringstream e; e << "called with unknown argument \"" << args[i] << "\"."; this->SetError(e.str()); - return false; + foundBadArgument = true; } - - // Quit if an argument is invalid. + // note bad argument if (this->ArgumentDoing == ArgumentDoingError) { - return false; + foundBadArgument = true; } } + bool capureCMakeError = (this->Values[ct_CAPTURE_CMAKE_ERROR] && + *this->Values[ct_CAPTURE_CMAKE_ERROR]); + // now that arguments are parsed check to see if there is a + // CAPTURE_CMAKE_ERROR specified let the errorState object know. + if (capureCMakeError) { + errorState.CaptureCMakeError(); + } + // if we found a bad argument then exit before running command + if (foundBadArgument) { + // store the cmake error + if (capureCMakeError) { + this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], + "-1"); + const char* err = this->GetError(); + if (err && !cmSystemTools::FindLastString(err, "unknown error.")) { + cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n"); + } + // return success because failure is recorded in CAPTURE_CMAKE_ERROR + return true; + } + // return failure because of bad argument + return false; + } // Set the config type of this ctest to the current value of the // CTEST_CONFIGURATION_TYPE script variable if it is defined. @@ -117,6 +196,15 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, if (!handler) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot instantiate test handler " << this->GetName() << std::endl); + if (capureCMakeError) { + this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], + "-1"); + const char* err = this->GetError(); + if (err && !cmSystemTools::FindLastString(err, "unknown error.")) { + cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n"); + } + return true; + } return false; } @@ -147,6 +235,22 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, this->Makefile->AddDefinition(this->Values[ct_RETURN_VALUE], str.str().c_str()); } + // log the error message if there was an error + if (capureCMakeError) { + const char* returnString = "0"; + if (cmSystemTools::GetErrorOccuredFlag()) { + returnString = "-1"; + const char* err = this->GetError(); + // print out the error if it is not "unknown error" which means + // there was no message + if (err && !cmSystemTools::FindLastString(err, "unknown error.")) { + cmCTestLog(this->CTest, ERROR_MESSAGE, err); + } + } + // store the captured cmake error state 0 or -1 + this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], + returnString); + } cmSystemTools::ChangeDirectory(current_dir); return true; } diff --git a/Source/CTest/cmCTestHandlerCommand.h b/Source/CTest/cmCTestHandlerCommand.h index 7c9fd50..95a1581 100644 --- a/Source/CTest/cmCTestHandlerCommand.h +++ b/Source/CTest/cmCTestHandlerCommand.h @@ -47,6 +47,7 @@ public: { ct_NONE, ct_RETURN_VALUE, + ct_CAPTURE_CMAKE_ERROR, ct_BUILD, ct_SOURCE, ct_SUBMIT_INDEX, diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx index 5ea637e..c4458dd 100644 --- a/Source/CTest/cmCTestUploadCommand.cxx +++ b/Source/CTest/cmCTestUploadCommand.cxx @@ -45,11 +45,19 @@ bool cmCTestUploadCommand::CheckArgumentKeyword(std::string const& arg) 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.c_str())) { this->Files.insert(arg); diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h index da291f3..3a5bdef 100644 --- a/Source/CTest/cmCTestUploadCommand.h +++ b/Source/CTest/cmCTestUploadCommand.h @@ -61,6 +61,7 @@ protected: enum { ArgumentDoingFiles = Superclass::ArgumentDoingLast1, + ArgumentDoingCaptureCMakeError, ArgumentDoingLast2 }; |