From aad15c3abfbffc216bbbab654f6eb19f312c1e56 Mon Sep 17 00:00:00 2001 From: David Cole Date: Tue, 29 Dec 2009 14:38:31 -0500 Subject: [PATCH] Fix issue #10060 - add APPEND arg to ctest_start command. If APPEND is given to ctest_start, it will read the tag from the current existing Testing/TAG file rather than creating a new one based on the current time stamp. This allows a developer to run several dashboard scripts in a row, all of which will share the same tag/stamp/buildid when they finally get submitted to CDash. Now you can split the running of build phases and test phases for the same dashboard row into multiple scripts. --- Source/CTest/cmCTestStartCommand.cxx | 14 +++ Source/CTest/cmCTestStartCommand.h | 18 ++- Source/cmCTest.cxx | 132 +++++++++++++-------- Source/cmCTest.h | 8 +- Tests/CTestTestFailedSubmits/test.cmake.in | 4 + 5 files changed, 118 insertions(+), 58 deletions(-) diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx index 606fbbef7..228a17300 100644 --- a/Source/CTest/cmCTestStartCommand.cxx +++ b/Source/CTest/cmCTestStartCommand.cxx @@ -17,6 +17,11 @@ #include "cmCTestVC.h" #include "cmGeneratedFileStream.h" +cmCTestStartCommand::cmCTestStartCommand() +{ + this->CreateNewTag = true; +} + bool cmCTestStartCommand ::InitialPass(std::vector const& args, cmExecutionStatus &) { @@ -44,6 +49,15 @@ bool cmCTestStartCommand } } + if (cnt < args.size()) + { + if (args[cnt] == "APPEND") + { + cnt ++; + this->CreateNewTag = false; + } + } + if ( cnt < args.size() ) { src_dir = args[cnt].c_str(); diff --git a/Source/CTest/cmCTestStartCommand.h b/Source/CTest/cmCTestStartCommand.h index ae2f26b85..afbc77b4a 100644 --- a/Source/CTest/cmCTestStartCommand.h +++ b/Source/CTest/cmCTestStartCommand.h @@ -23,7 +23,7 @@ class cmCTestStartCommand : public cmCTestCommand { public: - cmCTestStartCommand() {} + cmCTestStartCommand(); /** * This is a virtual constructor for the command. @@ -33,6 +33,7 @@ public: cmCTestStartCommand* ni = new cmCTestStartCommand; ni->CTest = this->CTest; ni->CTestScriptHandler = this->CTestScriptHandler; + ni->CreateNewTag = this->CreateNewTag; return ni; } @@ -43,6 +44,14 @@ public: virtual bool InitialPass(std::vector const& args, cmExecutionStatus &status); + /** + * Will this invocation of ctest_start create a new TAG file? + */ + bool ShouldCreateNewTag() + { + return this->CreateNewTag; + } + /** * The name of the command as specified in CMakeList.txt. */ @@ -62,18 +71,21 @@ public: virtual const char* GetFullDocumentation() { return - " ctest_start(Model [TRACK ] [source [binary]])\n" + " ctest_start(Model [TRACK ] [APPEND] [source [binary]])\n" "Starts the testing for a given model. The command should be called " "after the binary directory is initialized. If the 'source' and " "'binary' directory are not specified, it reads the " "CTEST_SOURCE_DIRECTORY and CTEST_BINARY_DIRECTORY. If the track is " - "specified, the submissions will go to the specified track."; + "specified, the submissions will go to the specified track. " + "If APPEND is used, the existing TAG is used rather than " + "creating a new one based on the current time stamp."; } cmTypeMacro(cmCTestStartCommand, cmCTestCommand); private: bool InitialCheckout(std::ostream& ofs, std::string const& sourceDir); + bool CreateNewTag; }; diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index c9ef5f38a..31f132142 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -402,7 +402,7 @@ cmCTest::Part cmCTest::GetPartFromName(const char* name) } //---------------------------------------------------------------------- -int cmCTest::Initialize(const char* binary_dir, bool script) +int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) { cmCTestLog(this, DEBUG, "Here: " << __LINE__ << std::endl); if(!this->InteractiveDebugMode) @@ -453,6 +453,8 @@ int cmCTest::Initialize(const char* binary_dir, bool script) if ( this->ProduceXML ) { + // Verify "Testing" directory exists: + // std::string testingDir = this->BinaryDir + "/Testing"; if ( cmSystemTools::FileExists(testingDir.c_str()) ) { @@ -472,73 +474,101 @@ int cmCTest::Initialize(const char* binary_dir, bool script) return 0; } } + + // Create new "TAG" file or read existing one: + // std::string tagfile = testingDir + "/TAG"; std::ifstream tfin(tagfile.c_str()); std::string tag; - time_t tctime = time(0); - if ( this->TomorrowTag ) + + if (command->ShouldCreateNewTag()) { - tctime += ( 24 * 60 * 60 ); - } - struct tm *lctime = gmtime(&tctime); - if ( tfin && cmSystemTools::GetLineFromStream(tfin, tag) ) - { - int year = 0; - int mon = 0; - int day = 0; - int hour = 0; - int min = 0; - sscanf(tag.c_str(), "%04d%02d%02d-%02d%02d", - &year, &mon, &day, &hour, &min); - if ( year != lctime->tm_year + 1900 || - mon != lctime->tm_mon+1 || - day != lctime->tm_mday ) + time_t tctime = time(0); + if ( this->TomorrowTag ) { - tag = ""; + tctime += ( 24 * 60 * 60 ); } - std::string tagmode; - if ( cmSystemTools::GetLineFromStream(tfin, tagmode) ) + struct tm *lctime = gmtime(&tctime); + if ( tfin && cmSystemTools::GetLineFromStream(tfin, tag) ) { - if (tagmode.size() > 4 && !this->Parts[PartStart]) + int year = 0; + int mon = 0; + int day = 0; + int hour = 0; + int min = 0; + sscanf(tag.c_str(), "%04d%02d%02d-%02d%02d", + &year, &mon, &day, &hour, &min); + if ( year != lctime->tm_year + 1900 || + mon != lctime->tm_mon+1 || + day != lctime->tm_mday ) { - this->TestModel = cmCTest::GetTestModelFromString(tagmode.c_str()); + tag = ""; + } + std::string tagmode; + if ( cmSystemTools::GetLineFromStream(tfin, tagmode) ) + { + if (tagmode.size() > 4 && !this->Parts[PartStart]) + { + this->TestModel = cmCTest::GetTestModelFromString(tagmode.c_str()); + } + } + tfin.close(); + } + if (tag.size() == 0 || (0 != command) || this->Parts[PartStart]) + { + cmCTestLog(this, DEBUG, "TestModel: " << this->GetTestModelString() + << std::endl); + cmCTestLog(this, DEBUG, "TestModel: " << this->TestModel << std::endl); + if ( this->TestModel == cmCTest::NIGHTLY ) + { + lctime = this->GetNightlyTime( + this->GetCTestConfiguration("NightlyStartTime"), this->TomorrowTag); + } + char datestring[100]; + sprintf(datestring, "%04d%02d%02d-%02d%02d", + lctime->tm_year + 1900, + lctime->tm_mon+1, + lctime->tm_mday, + lctime->tm_hour, + lctime->tm_min); + tag = datestring; + std::ofstream ofs(tagfile.c_str()); + if ( ofs ) + { + ofs << tag << std::endl; + ofs << this->GetTestModelString() << std::endl; + } + ofs.close(); + if ( 0 == command ) + { + cmCTestLog(this, OUTPUT, "Create new tag: " << tag << " - " + << this->GetTestModelString() << std::endl); } } - tfin.close(); } - if (tag.size() == 0 || script || this->Parts[PartStart]) + else { - cmCTestLog(this, DEBUG, "TestModel: " << this->GetTestModelString() - << std::endl); - cmCTestLog(this, DEBUG, "TestModel: " << this->TestModel << std::endl); - if ( this->TestModel == cmCTest::NIGHTLY ) + if ( tfin ) { - lctime = this->GetNightlyTime( - this->GetCTestConfiguration("NightlyStartTime"), this->TomorrowTag); + cmSystemTools::GetLineFromStream(tfin, tag); + tfin.close(); } - char datestring[100]; - sprintf(datestring, "%04d%02d%02d-%02d%02d", - lctime->tm_year + 1900, - lctime->tm_mon+1, - lctime->tm_mday, - lctime->tm_hour, - lctime->tm_min); - tag = datestring; - std::ofstream ofs(tagfile.c_str()); - if ( ofs ) + + if ( tag.empty() ) { - ofs << tag << std::endl; - ofs << this->GetTestModelString() << std::endl; - } - ofs.close(); - if ( !script ) - { - cmCTestLog(this, OUTPUT, "Create new tag: " << tag << " - " - << this->GetTestModelString() << std::endl); + cmCTestLog(this, ERROR_MESSAGE, + "Cannot read existing TAG file in " << testingDir + << std::endl); + return 0; } + + cmCTestLog(this, OUTPUT, " Use existing tag: " << tag << " - " + << this->GetTestModelString() << std::endl); } + this->CurrentTag = tag; } + return 1; } @@ -596,7 +626,7 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command) } } - if ( !this->Initialize(bld_dir.c_str(), true) ) + if ( !this->Initialize(bld_dir.c_str(), command) ) { return false; } @@ -2206,7 +2236,7 @@ int cmCTest::Run(std::vector &args, std::string* output) it->second->SetSubmitIndex(this->SubmitIndex); } std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); - if(!this->Initialize(cwd.c_str(), false)) + if(!this->Initialize(cwd.c_str(), 0)) { res = 12; cmCTestLog(this, ERROR_MESSAGE, "Problem initializing the dashboard." diff --git a/Source/cmCTest.h b/Source/cmCTest.h index eb88f6293..2b7912c51 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -475,14 +475,14 @@ private: void BlockTestErrorDiagnostics(); /** - * Initialize a dashboard run in the given build tree. The "script" - * argument is true when running from a command-driven (ctest_start) - * dashboard script, and false when running from the CTest command + * Initialize a dashboard run in the given build tree. The "command" + * argument is non-NULL when running from a command-driven (ctest_start) + * dashboard script, and NULL when running from the CTest command * line. Note that a declarative dashboard script does not actually * call this method because it sets CTEST_COMMAND to drive a build * through the ctest command line. */ - int Initialize(const char* binary_dir, bool script); + int Initialize(const char* binary_dir, cmCTestStartCommand* command); //! parse the option after -D and convert it into the appropriate steps bool AddTestsForDashboardType(std::string &targ); diff --git a/Tests/CTestTestFailedSubmits/test.cmake.in b/Tests/CTestTestFailedSubmits/test.cmake.in index 42bc79c67..9b581ebea 100644 --- a/Tests/CTestTestFailedSubmits/test.cmake.in +++ b/Tests/CTestTestFailedSubmits/test.cmake.in @@ -45,3 +45,7 @@ CTEST_COVERAGE(BUILD "${CTEST_BINARY_DIRECTORY}" @ctest_coverage_labels_args@ RE # ok to call ctest_submit - still avoids network activity because there is # not a valid drop location given above... CTEST_SUBMIT(RETURN_VALUE res) + +# Add coverage for the new APPEND arg to ctest_start: +# +CTEST_START(Experimental APPEND)