/*============================================================================ CMake - Cross Platform Makefile Generator Copyright 2000-2009 Kitware, Inc., Insight Software Consortium Distributed under the OSI-approved BSD License (the "License"); see accompanying file Copyright.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ #include "cmCTestHandlerCommand.h" #include "cmCTest.h" #include "cmCTestGenericHandler.h" 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(CM_NULLPTR); } this->Arguments[ct_RETURN_VALUE] = "RETURN_VALUE"; 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; } bool cmCTestHandlerCommand::InitialPass(std::vector const& args, cmExecutionStatus& /*unused*/) { // Allocate space for argument values. this->Values.clear(); this->Values.resize(this->Last, CM_NULLPTR); // Process input arguments. this->ArgumentDoing = ArgumentDoingNone; for (unsigned int i = 0; i < args.size(); ++i) { // Check this argument. if (!this->CheckArgumentKeyword(args[i]) && !this->CheckArgumentValue(args[i])) { std::ostringstream e; e << "called with unknown argument \"" << args[i] << "\"."; this->SetError(e.str()); return false; } // Quit if an argument is invalid. if (this->ArgumentDoing == ArgumentDoingError) { return false; } } // Set the config type of this ctest to the current value of the // CTEST_CONFIGURATION_TYPE script variable if it is defined. // The current script value trumps the -C argument on the command // line. const char* ctestConfigType = this->Makefile->GetDefinition("CTEST_CONFIGURATION_TYPE"); if (ctestConfigType) { this->CTest->SetConfigType(ctestConfigType); } if (this->Values[ct_BUILD]) { this->CTest->SetCTestConfiguration( "BuildDirectory", cmSystemTools::CollapseFullPath(this->Values[ct_BUILD]).c_str(), this->Quiet); } else { const char* bdir = this->Makefile->GetSafeDefinition("CTEST_BINARY_DIRECTORY"); if (bdir) { this->CTest->SetCTestConfiguration( "BuildDirectory", cmSystemTools::CollapseFullPath(bdir).c_str(), this->Quiet); } else { cmCTestLog(this->CTest, ERROR_MESSAGE, "CTEST_BINARY_DIRECTORY not set" << std::endl;); } } if (this->Values[ct_SOURCE]) { cmCTestLog(this->CTest, DEBUG, "Set source directory to: " << this->Values[ct_SOURCE] << std::endl); this->CTest->SetCTestConfiguration( "SourceDirectory", cmSystemTools::CollapseFullPath(this->Values[ct_SOURCE]).c_str(), this->Quiet); } else { this->CTest->SetCTestConfiguration( "SourceDirectory", cmSystemTools::CollapseFullPath( this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY")) .c_str(), this->Quiet); } if (const char* changeId = this->Makefile->GetDefinition("CTEST_CHANGE_ID")) { this->CTest->SetCTestConfiguration("ChangeId", changeId, this->Quiet); } cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;); cmCTestGenericHandler* handler = this->InitializeHandler(); if (!handler) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot instantiate test handler " << this->GetName() << std::endl); return false; } handler->SetAppendXML(this->AppendXML); handler->PopulateCustomVectors(this->Makefile); if (this->Values[ct_SUBMIT_INDEX]) { if (!this->CTest->GetDropSiteCDash() && this->CTest->GetDartVersion() <= 1) { cmCTestLog( this->CTest, ERROR_MESSAGE, "Dart before version 2.0 does not support collecting submissions." << std::endl << "Please upgrade the server to Dart 2 or higher, or do not use " "SUBMIT_INDEX." << std::endl); } else { handler->SetSubmitIndex(atoi(this->Values[ct_SUBMIT_INDEX])); } } std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory(); cmSystemTools::ChangeDirectory( this->CTest->GetCTestConfiguration("BuildDirectory")); int res = handler->ProcessHandler(); if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) { std::ostringstream str; str << res; this->Makefile->AddDefinition(this->Values[ct_RETURN_VALUE], str.str().c_str()); } cmSystemTools::ChangeDirectory(current_dir); return true; } bool cmCTestHandlerCommand::CheckArgumentKeyword(std::string const& arg) { // 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; } bool cmCTestHandlerCommand::CheckArgumentValue(std::string const& arg) { 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(cmake::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; }