summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZach Mullen <zach.mullen@kitware.com>2010-06-03 10:34:34 -0400
committerZach Mullen <zach.mullen@kitware.com>2010-06-03 10:34:34 -0400
commite525649a4e9f2578c41593b56f9af4b4b7719984 (patch)
tree46092e3926a2ff9bee3a2038f495fc0992e8635f
parent7f619608d50cabee8718d78427d560531a3b1ea1 (diff)
downloadcmake-e525649a4e9f2578c41593b56f9af4b4b7719984.tar.gz
Checksums on CTest submit files, and retry timed out submissions.
-rw-r--r--Modules/CTest.cmake9
-rw-r--r--Modules/DartConfiguration.tcl.in4
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx27
-rw-r--r--Source/CTest/cmCTestSubmitCommand.h6
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx170
-rw-r--r--Source/CTest/cmCTestSubmitHandler.h1
-rw-r--r--Tests/CTestTest3/test.cmake.in2
7 files changed, 198 insertions, 21 deletions
diff --git a/Modules/CTest.cmake b/Modules/CTest.cmake
index 2d0702e967..bdaf911b53 100644
--- a/Modules/CTest.cmake
+++ b/Modules/CTest.cmake
@@ -163,6 +163,11 @@ IF(BUILD_TESTING)
SET(DART_TESTING_TIMEOUT 1500 CACHE STRING
"Maximum time allowed before CTest will kill the test.")
+ SET(CTEST_SUBMIT_RETRY_DELAY 5 CACHE STRING
+ "How long to wait between timed-out CTest submissions.")
+ SET(CTEST_SUBMIT_RETRY_COUNT 3 CACHE STRING
+ "How many times to retry timed-out CTest submissions.")
+
FIND_PROGRAM(MEMORYCHECK_COMMAND
NAMES purify valgrind boundscheck
PATHS
@@ -262,7 +267,9 @@ IF(BUILD_TESTING)
SCPCOMMAND
SLURM_SBATCH_COMMAND
SLURM_SRUN_COMMAND
- SITE
+ SITE
+ CTEST_SUBMIT_RETRY_DELAY
+ CTEST_SUBMIT_RETRY_COUNT
)
# BUILDNAME
IF(NOT RUN_FROM_DART)
diff --git a/Modules/DartConfiguration.tcl.in b/Modules/DartConfiguration.tcl.in
index 85b4138ba4..799ff79a00 100644
--- a/Modules/DartConfiguration.tcl.in
+++ b/Modules/DartConfiguration.tcl.in
@@ -83,3 +83,7 @@ CurlOptions: @CTEST_CURL_OPTIONS@
# warning, if you add new options here that have to do with submit,
# you have to update cmCTestSubmitCommand.cxx
+# For CTest submissions that timeout, these options
+# specify behavior for retrying the submission
+CTestRetryTime: @CTEST_SUBMIT_RETRY_DELAY@
+CTestRetryCount: @CTEST_SUBMIT_RETRY_COUNT@
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index d1226da1f1..6a45d58825 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -147,6 +147,11 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
static_cast<cmCTestSubmitHandler*>(handler)->SelectParts(this->Parts);
}
+ static_cast<cmCTestSubmitHandler*>(handler)->SetOption("RetryTime",
+ this->RetryDelay.c_str());
+ static_cast<cmCTestSubmitHandler*>(handler)->SetOption("RetryCount",
+ this->RetryCount.c_str());
+
return handler;
}
@@ -169,6 +174,18 @@ bool cmCTestSubmitCommand::CheckArgumentKeyword(std::string const& arg)
return true;
}
+ if(arg == "RETRY_COUNT")
+ {
+ this->ArgumentDoing = ArgumentDoingRetryCount;
+ return true;
+ }
+
+ if(arg == "RETRY_DELAY")
+ {
+ this->ArgumentDoing = ArgumentDoingRetryDelay;
+ return true;
+ }
+
// Look for other arguments.
return this->Superclass::CheckArgumentKeyword(arg);
}
@@ -213,6 +230,16 @@ bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg)
return true;
}
+ if(this->ArgumentDoing == ArgumentDoingRetryCount)
+ {
+ this->RetryCount = arg;
+ }
+
+ if(this->ArgumentDoing == ArgumentDoingRetryDelay)
+ {
+ this->RetryDelay = arg;
+ }
+
// Look for other arguments.
return this->Superclass::CheckArgumentValue(arg);
}
diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h
index ccaef7e36d..14dfa37c06 100644
--- a/Source/CTest/cmCTestSubmitCommand.h
+++ b/Source/CTest/cmCTestSubmitCommand.h
@@ -29,6 +29,8 @@ public:
{
this->PartsMentioned = false;
this->FilesMentioned = false;
+ this->RetryCount = "";
+ this->RetryDelay = "";
}
/**
@@ -92,6 +94,8 @@ protected:
{
ArgumentDoingParts = Superclass::ArgumentDoingLast1,
ArgumentDoingFiles,
+ ArgumentDoingRetryDelay,
+ ArgumentDoingRetryCount,
ArgumentDoingLast2
};
@@ -99,6 +103,8 @@ protected:
std::set<cmCTest::Part> Parts;
bool FilesMentioned;
cmCTest::SetOfStrings Files;
+ std::string RetryCount;
+ std::string RetryDelay;
};
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 7b4f38b2c9..fca05aca11 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -15,6 +15,7 @@
#include "cmVersion.h"
#include "cmGeneratedFileStream.h"
#include "cmCTest.h"
+#include "cmXMLParser.h"
#include <cmsys/Process.h>
#include <cmsys/Base64.h>
@@ -31,6 +32,80 @@
typedef std::vector<char> cmCTestSubmitHandlerVectorOfChar;
+//----------------------------------------------------------------------------
+class cmCTestSubmitHandler::ResponseParser: public cmXMLParser
+{
+public:
+ ResponseParser() { this->Status = STATUS_OK; }
+ ~ResponseParser() {}
+
+public:
+
+ enum StatusType
+ {
+ STATUS_OK,
+ STATUS_WARNING,
+ STATUS_ERROR
+ };
+
+ StatusType Status;
+ std::string CDashVersion;
+ std::string Filename;
+ std::string MD5;
+ std::string Message;
+
+private:
+ std::string CurrentValue;
+ std::string CurrentTag;
+
+ virtual void StartElement(const char* name, const char** atts)
+ {
+ this->CurrentValue = "";
+ if(strcmp(name, "cdash") == 0)
+ {
+ this->CDashVersion = this->FindAttribute(atts, "version");
+ }
+ }
+
+ virtual void CharacterDataHandler(const char* data, int length)
+ {
+ this->CurrentValue.insert(this->CurrentValue.end(), data, data+length);
+ }
+
+ virtual void EndElement(const char* name)
+ {
+ if(strcmp(name, "status") == 0)
+ {
+ this->CurrentValue = cmSystemTools::UpperCase(this->CurrentValue);
+ if(this->CurrentValue == "OK" || this->CurrentValue == "SUCCESS")
+ {
+ this->Status = STATUS_OK;
+ }
+ else if(this->CurrentValue == "WARNING")
+ {
+ this->Status = STATUS_WARNING;
+ }
+ else
+ {
+ this->Status = STATUS_ERROR;
+ }
+ }
+ else if(strcmp(name, "filename") == 0)
+ {
+ this->Filename = this->CurrentValue;
+ }
+ else if(strcmp(name, "md5") == 0)
+ {
+ this->MD5 = this->CurrentValue;
+ }
+ else if(strcmp(name, "message") == 0)
+ {
+ this->Message = this->CurrentValue;
+ }
+ }
+};
+
+
static size_t
cmCTestSubmitHandlerWriteMemoryCallback(void *ptr, size_t size, size_t nmemb,
void *data)
@@ -367,6 +442,13 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
= url + ((url.find("?",0) == cmStdString::npos) ? "?" : "&")
+ "FileName=" + ofile;
+ char md5[33];
+ cmSystemTools::ComputeFileMD5(local_file.c_str(), md5);
+ md5[32] = 0;
+ std::stringstream md5string;
+ md5string << "&MD5=" << md5;
+ upload_as += md5string.str();
+
struct stat st;
if ( ::stat(local_file.c_str(), &st) )
{
@@ -382,7 +464,6 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
<< local_file.c_str() << " to "
<< upload_as.c_str() << " Size: " << st.st_size << std::endl);
-
// specify target
::curl_easy_setopt(curl,CURLOPT_URL, upload_as.c_str());
@@ -411,6 +492,47 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
// Now run off and do what you've been told!
res = ::curl_easy_perform(curl);
+ // If we time out or operation is too slow, wait and retry
+ if(res == CURLE_OPERATION_TIMEOUTED)
+ {
+ std::string retryTime = this->GetOption("RetryTime") == NULL ?
+ "" : this->GetOption("RetryTime");
+ std::string retryCount = this->GetOption("RetryCount") == NULL ?
+ "" : this->GetOption("RetryCount");
+
+ int time = retryTime == "" ? atoi(this->CTest->GetCTestConfiguration(
+ "CTestRetryTime").c_str()) : atoi(retryTime.c_str());
+ int count = retryCount == "" ? atoi(this->CTest->GetCTestConfiguration(
+ "CTestRetryCount").c_str()) : atoi(retryCount.c_str());
+
+ for(int i = 0; i < count; i++)
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Connection timed out, waiting " << time << " seconds...\n");
+
+ double stop = cmSystemTools::GetTime() + time;
+ while(cmSystemTools::GetTime() < stop) {} //wait <time> seconds
+
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Retry submission: Attempt " << (i + 1) << " of "
+ << count << std::endl);
+
+ ::fclose(ftpfile);
+ ftpfile = ::fopen(local_file.c_str(), "rb");
+ ::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile);
+
+ chunk.clear();
+ chunkDebug.clear();
+
+ res = ::curl_easy_perform(curl);
+
+ if(res != CURLE_OPERATION_TIMEDOUT)
+ {
+ break;
+ }
+ }
+ }
+
if ( chunk.size() > 0 )
{
cmCTestLog(this->CTest, DEBUG, "CURL output: ["
@@ -467,29 +589,39 @@ void cmCTestSubmitHandler
::ParseResponse(cmCTestSubmitHandlerVectorOfChar chunk)
{
std::string output = "";
+ output.append(chunk.begin(), chunk.end());
- for(cmCTestSubmitHandlerVectorOfChar::iterator i = chunk.begin();
- i != chunk.end(); ++i)
- {
- output += *i;
- }
- output = cmSystemTools::UpperCase(output);
-
- if(output.find("WARNING") != std::string::npos)
- {
- this->HasWarnings = true;
- }
- if(output.find("ERROR") != std::string::npos)
+ if(output.find("<cdash") != output.npos)
{
- this->HasErrors = true;
+ ResponseParser parser;
+ parser.Parse(output.c_str());
+
+ if(parser.Status != ResponseParser::STATUS_OK)
+ {
+ this->HasErrors = true;
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission failed: " <<
+ parser.Message << std::endl);
+ return;
+ }
}
-
- if(this->HasWarnings || this->HasErrors)
+ else
{
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Server Response:\n" <<
- cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "\n");
+ output = cmSystemTools::UpperCase(output);
+ if(output.find("WARNING") != std::string::npos)
+ {
+ this->HasWarnings = true;
+ }
+ if(output.find("ERROR") != std::string::npos)
+ {
+ this->HasErrors = true;
+ }
+
+ if(this->HasWarnings || this->HasErrors)
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Server Response:\n" <<
+ cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "\n");
+ }
}
-
}
//----------------------------------------------------------------------------
diff --git a/Source/CTest/cmCTestSubmitHandler.h b/Source/CTest/cmCTestSubmitHandler.h
index 8b011ea191..e7755b138b 100644
--- a/Source/CTest/cmCTestSubmitHandler.h
+++ b/Source/CTest/cmCTestSubmitHandler.h
@@ -79,6 +79,7 @@ private:
std::string GetSubmitResultsPrefix();
+ class ResponseParser;
cmStdString HTTPProxy;
int HTTPProxyType;
cmStdString HTTPProxyAuth;
diff --git a/Tests/CTestTest3/test.cmake.in b/Tests/CTestTest3/test.cmake.in
index 1e8ea50237..9819235c70 100644
--- a/Tests/CTestTest3/test.cmake.in
+++ b/Tests/CTestTest3/test.cmake.in
@@ -113,7 +113,7 @@ IF(svncommand)
CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res PARALLEL_LEVEL 5 SCHEDULE_RANDOM ON)
CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res PARALLEL_LEVEL 5)
CTEST_COVERAGE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
- CTEST_SUBMIT(RETURN_VALUE res)
+ CTEST_SUBMIT(RETRY_COUNT 4 RETRY_DELAY 10 RETURN_VALUE res)
ELSE(svncommand)
MESSAGE("Cannot find SVN command: ${svncommand}")