summaryrefslogtreecommitdiff
path: root/Source/CTest/cmCTestSubmitHandler.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CTest/cmCTestSubmitHandler.cxx')
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx1508
1 files changed, 1508 insertions, 0 deletions
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
new file mode 100644
index 000000000..142bb4613
--- /dev/null
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -0,0 +1,1508 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2009 Kitware, Inc.
+
+ 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 "cmCTestSubmitHandler.h"
+
+#include "cmSystemTools.h"
+#include "cmVersion.h"
+#include "cmGeneratedFileStream.h"
+#include "cmCTest.h"
+#include "cmXMLParser.h"
+
+#include <cmsys/Process.h>
+#include <cmsys/Base64.h>
+
+// For XML-RPC submission
+#include "cm_xmlrpc.h"
+
+// For curl submission
+#include "cm_curl.h"
+
+#include <sys/stat.h>
+
+#define SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT 120
+
+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::vector<char> CurrentValue;
+
+ std::string GetCurrentValue()
+ {
+ std::string val;
+ if(this->CurrentValue.size())
+ {
+ val.assign(&this->CurrentValue[0], this->CurrentValue.size());
+ }
+ return val;
+ }
+
+ virtual void StartElement(const char* name, const char** atts)
+ {
+ this->CurrentValue.clear();
+ 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)
+ {
+ std::string status = cmSystemTools::UpperCase(this->GetCurrentValue());
+ if(status == "OK" || status == "SUCCESS")
+ {
+ this->Status = STATUS_OK;
+ }
+ else if(status == "WARNING")
+ {
+ this->Status = STATUS_WARNING;
+ }
+ else
+ {
+ this->Status = STATUS_ERROR;
+ }
+ }
+ else if(strcmp(name, "filename") == 0)
+ {
+ this->Filename = this->GetCurrentValue();
+ }
+ else if(strcmp(name, "md5") == 0)
+ {
+ this->MD5 = this->GetCurrentValue();
+ }
+ else if(strcmp(name, "message") == 0)
+ {
+ this->Message = this->GetCurrentValue();
+ }
+ }
+};
+
+
+static size_t
+cmCTestSubmitHandlerWriteMemoryCallback(void *ptr, size_t size, size_t nmemb,
+ void *data)
+{
+ register int realsize = (int)(size * nmemb);
+
+ cmCTestSubmitHandlerVectorOfChar *vec
+ = static_cast<cmCTestSubmitHandlerVectorOfChar*>(data);
+ const char* chPtr = static_cast<char*>(ptr);
+ vec->insert(vec->end(), chPtr, chPtr + realsize);
+
+ return realsize;
+}
+
+static size_t
+cmCTestSubmitHandlerCurlDebugCallback(CURL *, curl_infotype, char *chPtr,
+ size_t size, void *data)
+{
+ cmCTestSubmitHandlerVectorOfChar *vec
+ = static_cast<cmCTestSubmitHandlerVectorOfChar*>(data);
+ vec->insert(vec->end(), chPtr, chPtr + size);
+
+ return size;
+}
+
+//----------------------------------------------------------------------------
+cmCTestSubmitHandler::cmCTestSubmitHandler() : HTTPProxy(), FTPProxy()
+{
+ this->Initialize();
+}
+
+//----------------------------------------------------------------------------
+void cmCTestSubmitHandler::Initialize()
+{
+ // We submit all available parts by default.
+ for(cmCTest::Part p = cmCTest::PartStart;
+ p != cmCTest::PartCount; p = cmCTest::Part(p+1))
+ {
+ this->SubmitPart[p] = true;
+ }
+ this->CDash = false;
+ this->HasWarnings = false;
+ this->HasErrors = false;
+ this->Superclass::Initialize();
+ this->HTTPProxy = "";
+ this->HTTPProxyType = 0;
+ this->HTTPProxyAuth = "";
+ this->FTPProxy = "";
+ this->FTPProxyType = 0;
+ this->LogFile = 0;
+ this->Files.clear();
+}
+
+//----------------------------------------------------------------------------
+bool cmCTestSubmitHandler::SubmitUsingFTP(const cmStdString& localprefix,
+ const std::set<cmStdString>& files,
+ const cmStdString& remoteprefix,
+ const cmStdString& url)
+{
+ CURL *curl;
+ CURLcode res;
+ FILE* ftpfile;
+ char error_buffer[1024];
+
+ /* In windows, this will init the winsock stuff */
+ ::curl_global_init(CURL_GLOBAL_ALL);
+
+ cmCTest::SetOfStrings::const_iterator file;
+ for ( file = files.begin(); file != files.end(); ++file )
+ {
+ /* get a curl handle */
+ curl = curl_easy_init();
+ if(curl)
+ {
+ // Using proxy
+ if ( this->FTPProxyType > 0 )
+ {
+ curl_easy_setopt(curl, CURLOPT_PROXY, this->FTPProxy.c_str());
+ switch (this->FTPProxyType)
+ {
+ case 2:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
+ break;
+ case 3:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
+ break;
+ default:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
+ }
+ }
+
+ // enable uploading
+ ::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
+
+ // if there is little to no activity for too long stop submitting
+ ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1);
+ ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME,
+ SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT);
+
+ ::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
+
+ cmStdString local_file = *file;
+ if ( !cmSystemTools::FileExists(local_file.c_str()) )
+ {
+ local_file = localprefix + "/" + *file;
+ }
+ cmStdString upload_as
+ = url + "/" + remoteprefix + cmSystemTools::GetFilenameName(*file);
+
+ struct stat st;
+ if ( ::stat(local_file.c_str(), &st) )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: "
+ << local_file.c_str() << std::endl);
+ ::curl_easy_cleanup(curl);
+ ::curl_global_cleanup();
+ return false;
+ }
+
+ ftpfile = ::fopen(local_file.c_str(), "rb");
+ *this->LogFile << "\tUpload file: " << local_file.c_str() << " to "
+ << upload_as.c_str() << std::endl;
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Upload file: "
+ << local_file.c_str() << " to "
+ << upload_as.c_str() << std::endl);
+
+ ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
+
+ // specify target
+ ::curl_easy_setopt(curl,CURLOPT_URL, upload_as.c_str());
+
+ // now specify which file to upload
+ ::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile);
+
+ // and give the size of the upload (optional)
+ ::curl_easy_setopt(curl, CURLOPT_INFILESIZE,
+ static_cast<long>(st.st_size));
+
+ // and give curl the buffer for errors
+ ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
+
+ // specify handler for output
+ ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
+ cmCTestSubmitHandlerWriteMemoryCallback);
+ ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
+ cmCTestSubmitHandlerCurlDebugCallback);
+
+ /* we pass our 'chunk' struct to the callback function */
+ cmCTestSubmitHandlerVectorOfChar chunk;
+ cmCTestSubmitHandlerVectorOfChar chunkDebug;
+ ::curl_easy_setopt(curl, CURLOPT_FILE, (void *)&chunk);
+ ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)&chunkDebug);
+
+ // Now run off and do what you've been told!
+ res = ::curl_easy_perform(curl);
+
+ if ( chunk.size() > 0 )
+ {
+ cmCTestLog(this->CTest, DEBUG, "CURL output: ["
+ << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
+ << std::endl);
+ }
+ if ( chunkDebug.size() > 0 )
+ {
+ cmCTestLog(this->CTest, DEBUG, "CURL debug output: ["
+ << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
+ << std::endl);
+ }
+
+ fclose(ftpfile);
+ if ( res )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Error when uploading file: "
+ << local_file.c_str() << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " Error message was: "
+ << error_buffer << std::endl);
+ *this->LogFile << " Error when uploading file: "
+ << local_file.c_str()
+ << std::endl
+ << " Error message was: "
+ << error_buffer << std::endl
+ << " Curl output was: ";
+ // avoid dereference of empty vector
+ if(chunk.size())
+ {
+ *this->LogFile << cmCTestLogWrite(&*chunk.begin(), chunk.size());
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
+ << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
+ << std::endl);
+ }
+ *this->LogFile << std::endl;
+ ::curl_easy_cleanup(curl);
+ ::curl_global_cleanup();
+ return false;
+ }
+ // always cleanup
+ ::curl_easy_cleanup(curl);
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Uploaded: " + local_file
+ << std::endl);
+ }
+ }
+ ::curl_global_cleanup();
+ return true;
+}
+
+//----------------------------------------------------------------------------
+// Uploading files is simpler
+bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
+ const std::set<cmStdString>& files,
+ const cmStdString& remoteprefix,
+ const cmStdString& url)
+{
+ CURL *curl;
+ CURLcode res;
+ FILE* ftpfile;
+ char error_buffer[1024];
+
+ /* In windows, this will init the winsock stuff */
+ ::curl_global_init(CURL_GLOBAL_ALL);
+ cmStdString dropMethod(this->CTest->GetCTestConfiguration("DropMethod"));
+ cmStdString curlopt(this->CTest->GetCTestConfiguration("CurlOptions"));
+ std::vector<std::string> args;
+ cmSystemTools::ExpandListArgument(curlopt.c_str(), args);
+ bool verifyPeerOff = false;
+ bool verifyHostOff = false;
+ for( std::vector<std::string>::iterator i = args.begin();
+ i != args.end(); ++i)
+ {
+ if(*i == "CURLOPT_SSL_VERIFYPEER_OFF")
+ {
+ verifyPeerOff = true;
+ }
+ if(*i == "CURLOPT_SSL_VERIFYHOST_OFF")
+ {
+ verifyHostOff = true;
+ }
+ }
+ cmStdString::size_type kk;
+ cmCTest::SetOfStrings::const_iterator file;
+ for ( file = files.begin(); file != files.end(); ++file )
+ {
+ /* get a curl handle */
+ curl = curl_easy_init();
+ if(curl)
+ {
+ if(verifyPeerOff)
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Set CURLOPT_SSL_VERIFYPEER to off\n");
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
+ }
+ if(verifyHostOff)
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " Set CURLOPT_SSL_VERIFYHOST to off\n");
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
+ }
+
+ // Using proxy
+ if ( this->HTTPProxyType > 0 )
+ {
+ curl_easy_setopt(curl, CURLOPT_PROXY, this->HTTPProxy.c_str());
+ switch (this->HTTPProxyType)
+ {
+ case 2:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
+ break;
+ case 3:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
+ break;
+ default:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
+ if (this->HTTPProxyAuth.size() > 0)
+ {
+ curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD,
+ this->HTTPProxyAuth.c_str());
+ }
+ }
+ }
+ if(this->CTest->ShouldUseHTTP10())
+ {
+ curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ }
+ // enable HTTP ERROR parsing
+ curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
+ /* enable uploading */
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
+
+ // if there is little to no activity for too long stop submitting
+ ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1);
+ ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME,
+ SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT);
+
+ /* HTTP PUT please */
+ ::curl_easy_setopt(curl, CURLOPT_PUT, 1);
+ ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
+
+ cmStdString local_file = *file;
+ if ( !cmSystemTools::FileExists(local_file.c_str()) )
+ {
+ local_file = localprefix + "/" + *file;
+ }
+ cmStdString remote_file
+ = remoteprefix + cmSystemTools::GetFilenameName(*file);
+
+ *this->LogFile << "\tUpload file: " << local_file.c_str() << " to "
+ << remote_file.c_str() << std::endl;
+
+ cmStdString ofile = "";
+ for ( kk = 0; kk < remote_file.size(); kk ++ )
+ {
+ char c = remote_file[kk];
+ char hexCh[4] = { 0, 0, 0, 0 };
+ hexCh[0] = c;
+ switch ( c )
+ {
+ case '+':
+ case '?':
+ case '/':
+ case '\\':
+ case '&':
+ case ' ':
+ case '=':
+ case '%':
+ sprintf(hexCh, "%%%02X", (int)c);
+ ofile.append(hexCh);
+ break;
+ default:
+ ofile.append(hexCh);
+ }
+ }
+ cmStdString upload_as
+ = url + ((url.find("?",0) == cmStdString::npos) ? "?" : "&")
+ + "FileName=" + ofile;
+
+ upload_as += "&MD5=";
+
+ if(cmSystemTools::IsOn(this->GetOption("InternalTest")))
+ {
+ upload_as += "bad_md5sum";
+ }
+ else
+ {
+ char md5[33];
+ cmSystemTools::ComputeFileMD5(local_file.c_str(), md5);
+ md5[32] = 0;
+ upload_as += md5;
+ }
+
+ struct stat st;
+ if ( ::stat(local_file.c_str(), &st) )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: "
+ << local_file.c_str() << std::endl);
+ ::curl_easy_cleanup(curl);
+ ::curl_global_cleanup();
+ return false;
+ }
+
+ ftpfile = ::fopen(local_file.c_str(), "rb");
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Upload file: "
+ << 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());
+
+ // now specify which file to upload
+ ::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile);
+
+ // and give the size of the upload (optional)
+ ::curl_easy_setopt(curl, CURLOPT_INFILESIZE,
+ static_cast<long>(st.st_size));
+
+ // and give curl the buffer for errors
+ ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
+
+ // specify handler for output
+ ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
+ cmCTestSubmitHandlerWriteMemoryCallback);
+ ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
+ cmCTestSubmitHandlerCurlDebugCallback);
+
+ /* we pass our 'chunk' struct to the callback function */
+ cmCTestSubmitHandlerVectorOfChar chunk;
+ cmCTestSubmitHandlerVectorOfChar chunkDebug;
+ ::curl_easy_setopt(curl, CURLOPT_FILE, (void *)&chunk);
+ ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)&chunkDebug);
+
+ // Now run off and do what you've been told!
+ res = ::curl_easy_perform(curl);
+
+ if(cmSystemTools::IsOn(this->GetOption("InternalTest")) &&
+ cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
+ this->CTest->GetCDashVersion().c_str(), "1.7"))
+ {
+ // mock failure output for internal test case
+ std::string mock_output = "<cdash version=\"1.7.0\">\n"
+ " <status>ERROR</status>\n"
+ " <message>Checksum failed for file.</message>\n"
+ "</cdash>\n";
+ chunk.clear();
+ chunk.assign(mock_output.begin(), mock_output.end());
+ }
+
+ if ( chunk.size() > 0 )
+ {
+ cmCTestLog(this->CTest, DEBUG, "CURL output: ["
+ << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
+ << std::endl);
+ this->ParseResponse(chunk);
+ }
+ if ( chunkDebug.size() > 0 )
+ {
+ cmCTestLog(this->CTest, DEBUG, "CURL debug output: ["
+ << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
+ << std::endl);
+ }
+
+ // If curl failed for any reason, or checksum fails, wait and retry
+ //
+ if(res != CURLE_OK || this->HasErrors)
+ {
+ std::string retryDelay = this->GetOption("RetryDelay") == NULL ?
+ "" : this->GetOption("RetryDelay");
+ std::string retryCount = this->GetOption("RetryCount") == NULL ?
+ "" : this->GetOption("RetryCount");
+
+ int delay = retryDelay == "" ? atoi(this->CTest->GetCTestConfiguration(
+ "CTestSubmitRetryDelay").c_str()) : atoi(retryDelay.c_str());
+ int count = retryCount == "" ? atoi(this->CTest->GetCTestConfiguration(
+ "CTestSubmitRetryCount").c_str()) : atoi(retryCount.c_str());
+
+ for(int i = 0; i < count; i++)
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Submit failed, waiting " << delay << " seconds...\n");
+
+ double stop = cmSystemTools::GetTime() + delay;
+ while(cmSystemTools::GetTime() < stop)
+ {
+ cmSystemTools::Delay(100);
+ }
+
+ 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();
+ this->HasErrors = false;
+
+ res = ::curl_easy_perform(curl);
+
+ if ( chunk.size() > 0 )
+ {
+ cmCTestLog(this->CTest, DEBUG, "CURL output: ["
+ << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
+ << std::endl);
+ this->ParseResponse(chunk);
+ }
+
+ if(res == CURLE_OK && !this->HasErrors)
+ {
+ break;
+ }
+ }
+ }
+
+ fclose(ftpfile);
+ if ( res )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Error when uploading file: "
+ << local_file.c_str() << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " Error message was: "
+ << error_buffer << std::endl);
+ *this->LogFile << " Error when uploading file: "
+ << local_file.c_str()
+ << std::endl
+ << " Error message was: " << error_buffer
+ << std::endl;
+ // avoid deref of begin for zero size array
+ if(chunk.size())
+ {
+ *this->LogFile << " Curl output was: "
+ << cmCTestLogWrite(&*chunk.begin(), chunk.size())
+ << std::endl;
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
+ << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
+ << std::endl);
+ }
+ ::curl_easy_cleanup(curl);
+ ::curl_global_cleanup();
+ return false;
+ }
+ // always cleanup
+ ::curl_easy_cleanup(curl);
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Uploaded: " + local_file
+ << std::endl);
+ }
+ }
+ ::curl_global_cleanup();
+ return true;
+}
+
+//----------------------------------------------------------------------------
+void cmCTestSubmitHandler
+::ParseResponse(cmCTestSubmitHandlerVectorOfChar chunk)
+{
+ std::string output = "";
+ output.append(chunk.begin(), chunk.end());
+
+ if(output.find("<cdash") != output.npos)
+ {
+ 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;
+ }
+ }
+ 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");
+ }
+}
+
+//----------------------------------------------------------------------------
+bool cmCTestSubmitHandler::TriggerUsingHTTP(
+ const std::set<cmStdString>& files,
+ const cmStdString& remoteprefix,
+ const cmStdString& url)
+{
+ CURL *curl;
+ char error_buffer[1024];
+ /* In windows, this will init the winsock stuff */
+ ::curl_global_init(CURL_GLOBAL_ALL);
+
+ cmCTest::SetOfStrings::const_iterator file;
+ for ( file = files.begin(); file != files.end(); ++file )
+ {
+ /* get a curl handle */
+ curl = curl_easy_init();
+ if(curl)
+ {
+ // Using proxy
+ if ( this->HTTPProxyType > 0 )
+ {
+ curl_easy_setopt(curl, CURLOPT_PROXY, this->HTTPProxy.c_str());
+ switch (this->HTTPProxyType)
+ {
+ case 2:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
+ break;
+ case 3:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
+ break;
+ default:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
+ if (this->HTTPProxyAuth.size() > 0)
+ {
+ curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD,
+ this->HTTPProxyAuth.c_str());
+ }
+ }
+ }
+
+ ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
+
+ // and give curl the buffer for errors
+ ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
+
+ // specify handler for output
+ ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
+ cmCTestSubmitHandlerWriteMemoryCallback);
+ ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
+ cmCTestSubmitHandlerCurlDebugCallback);
+
+ /* we pass our 'chunk' struct to the callback function */
+ cmCTestSubmitHandlerVectorOfChar chunk;
+ cmCTestSubmitHandlerVectorOfChar chunkDebug;
+ ::curl_easy_setopt(curl, CURLOPT_FILE, (void *)&chunk);
+ ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)&chunkDebug);
+
+ cmStdString rfile
+ = remoteprefix + cmSystemTools::GetFilenameName(*file);
+ cmStdString ofile = "";
+ cmStdString::iterator kk;
+ for ( kk = rfile.begin(); kk < rfile.end(); ++ kk)
+ {
+ char c = *kk;
+ char hexCh[4] = { 0, 0, 0, 0 };
+ hexCh[0] = c;
+ switch ( c )
+ {
+ case '+':
+ case '?':
+ case '/':
+ case '\\':
+ case '&':
+ case ' ':
+ case '=':
+ case '%':
+ sprintf(hexCh, "%%%02X", (int)c);
+ ofile.append(hexCh);
+ break;
+ default:
+ ofile.append(hexCh);
+ }
+ }
+ cmStdString turl
+ = url + ((url.find("?",0) == cmStdString::npos) ? "?" : "&")
+ + "xmlfile=" + ofile;
+ *this->LogFile << "Trigger url: " << turl.c_str() << std::endl;
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Trigger url: "
+ << turl.c_str() << std::endl);
+ curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+ curl_easy_setopt(curl, CURLOPT_URL, turl.c_str());
+ if ( curl_easy_perform(curl) )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " Error when triggering: "
+ << turl.c_str() << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " Error message was: "
+ << error_buffer << std::endl);
+ *this->LogFile << "\tTriggering failed with error: " << error_buffer
+ << std::endl
+ << " Error message was: " << error_buffer
+ << std::endl;
+ if(chunk.size())
+ {
+ *this->LogFile
+ << " Curl output was: "
+ << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << std::endl;
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
+ << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
+ << std::endl);
+ }
+ ::curl_easy_cleanup(curl);
+ ::curl_global_cleanup();
+ return false;
+ }
+
+ if ( chunk.size() > 0 )
+ {
+ cmCTestLog(this->CTest, DEBUG, "CURL output: ["
+ << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
+ << std::endl);
+ }
+ if ( chunkDebug.size() > 0 )
+ {
+ cmCTestLog(this->CTest, DEBUG, "CURL debug output: ["
+ << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size())
+ << "]" << std::endl);
+ }
+
+ // always cleanup
+ ::curl_easy_cleanup(curl);
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl);
+ }
+ }
+ ::curl_global_cleanup();
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Dart server triggered..."
+ << std::endl);
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmCTestSubmitHandler::SubmitUsingSCP(
+ const cmStdString& scp_command,
+ const cmStdString& localprefix,
+ const std::set<cmStdString>& files,
+ const cmStdString& remoteprefix,
+ const cmStdString& url)
+{
+ if ( !scp_command.size() || !localprefix.size() ||
+ !files.size() || !remoteprefix.size() || !url.size() )
+ {
+ return 0;
+ }
+ std::vector<const char*> argv;
+ argv.push_back(scp_command.c_str()); // Scp command
+ argv.push_back(scp_command.c_str()); // Dummy string for file
+ argv.push_back(scp_command.c_str()); // Dummy string for remote url
+ argv.push_back(0);
+
+ cmsysProcess* cp = cmsysProcess_New();
+ cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
+ //cmsysProcess_SetTimeout(cp, timeout);
+
+ int problems = 0;
+
+ cmCTest::SetOfStrings::const_iterator file;
+ for ( file = files.begin(); file != files.end(); ++file )
+ {
+ int retVal;
+
+ std::string lfname = localprefix;
+ cmSystemTools::ConvertToUnixSlashes(lfname);
+ lfname += "/" + *file;
+ lfname = cmSystemTools::ConvertToOutputPath(lfname.c_str());
+ argv[1] = lfname.c_str();
+ std::string rfname = url + "/" + remoteprefix + *file;
+ argv[2] = rfname.c_str();
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Execute \"" << argv[0]
+ << "\" \"" << argv[1] << "\" \""
+ << argv[2] << "\"" << std::endl);
+ *this->LogFile << "Execute \"" << argv[0] << "\" \"" << argv[1] << "\" \""
+ << argv[2] << "\"" << std::endl;
+
+ cmsysProcess_SetCommand(cp, &*argv.begin());
+ cmsysProcess_Execute(cp);
+ char* data;
+ int length;
+
+ while(cmsysProcess_WaitForData(cp, &data, &length, 0))
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ cmCTestLogWrite(data, length));
+ }
+
+ cmsysProcess_WaitForExit(cp, 0);
+
+ int result = cmsysProcess_GetState(cp);
+
+ if(result == cmsysProcess_State_Exited)
+ {
+ retVal = cmsysProcess_GetExitValue(cp);
+ if ( retVal != 0 )
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "\tSCP returned: "
+ << retVal << std::endl);
+ *this->LogFile << "\tSCP returned: " << retVal << std::endl;
+ problems ++;
+ }
+ }
+ else if(result == cmsysProcess_State_Exception)
+ {
+ retVal = cmsysProcess_GetExitException(cp);
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was an exception: "
+ << retVal << std::endl);
+ *this->LogFile << "\tThere was an exception: " << retVal << std::endl;
+ problems ++;
+ }
+ else if(result == cmsysProcess_State_Expired)
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was a timeout"
+ << std::endl);
+ *this->LogFile << "\tThere was a timeout" << std::endl;
+ problems ++;
+ }
+ else if(result == cmsysProcess_State_Error)
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "\tError executing SCP: "
+ << cmsysProcess_GetErrorString(cp) << std::endl);
+ *this->LogFile << "\tError executing SCP: "
+ << cmsysProcess_GetErrorString(cp) << std::endl;
+ problems ++;
+ }
+ }
+ cmsysProcess_Delete(cp);
+ if ( problems )
+ {
+ return false;
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmCTestSubmitHandler::SubmitUsingCP(
+ const cmStdString& localprefix,
+ const std::set<cmStdString>& files,
+ const cmStdString& remoteprefix,
+ const cmStdString& destination)
+{
+ if ( !localprefix.size() ||
+ !files.size() || !remoteprefix.size() || !destination.size() )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Missing arguments for submit via cp:\n"
+ << "\tlocalprefix: " << localprefix << "\n"
+ << "\tNumber of files: " << files.size() << "\n"
+ << "\tremoteprefix: " << remoteprefix << "\n"
+ << "\tdestination: " << destination << std::endl);
+ return 0;
+ }
+ cmCTest::SetOfStrings::const_iterator file;
+ bool problems = false;
+ for ( file = files.begin(); file != files.end(); ++file )
+ {
+ std::string lfname = localprefix;
+ cmSystemTools::ConvertToUnixSlashes(lfname);
+ lfname += "/" + *file;
+ std::string rfname = destination + "/" + remoteprefix + *file;
+ cmSystemTools::CopyFileAlways(lfname.c_str(), rfname.c_str());
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Copy file: "
+ << lfname.c_str() << " to "
+ << rfname.c_str() << std::endl);
+ }
+ std::string tagDoneFile = destination + "/" + remoteprefix + "DONE";
+ cmSystemTools::Touch(tagDoneFile.c_str(), true);
+ if ( problems )
+ {
+ return false;
+ }
+ return true;
+}
+
+
+//----------------------------------------------------------------------------
+#if defined(CTEST_USE_XMLRPC)
+bool cmCTestSubmitHandler::SubmitUsingXMLRPC(const cmStdString& localprefix,
+ const std::set<cmStdString>& files,
+ const cmStdString& remoteprefix,
+ const cmStdString& url)
+{
+ xmlrpc_env env;
+ char ctestString[] = "CTest";
+ std::string ctestVersionString = cmVersion::GetCMakeVersion();
+ char* ctestVersion = const_cast<char*>(ctestVersionString.c_str());
+
+ cmStdString realURL = url + "/" + remoteprefix + "/Command/";
+
+ /* Start up our XML-RPC client library. */
+ xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, ctestString, ctestVersion);
+
+ /* Initialize our error-handling environment. */
+ xmlrpc_env_init(&env);
+
+ /* Call the famous server at UserLand. */
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submitting to: "
+ << realURL.c_str() << " (" << remoteprefix.c_str() << ")" << std::endl);
+ cmCTest::SetOfStrings::const_iterator file;
+ for ( file = files.begin(); file != files.end(); ++file )
+ {
+ xmlrpc_value *result;
+
+ cmStdString local_file = *file;
+ if ( !cmSystemTools::FileExists(local_file.c_str()) )
+ {
+ local_file = localprefix + "/" + *file;
+ }
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submit file: "
+ << local_file.c_str() << std::endl);
+ struct stat st;
+ if ( ::stat(local_file.c_str(), &st) )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: "
+ << local_file.c_str() << std::endl);
+ return false;
+ }
+
+ // off_t can be bigger than size_t. fread takes size_t.
+ // make sure the file is not too big.
+ if(static_cast<off_t>(static_cast<size_t>(st.st_size)) !=
+ static_cast<off_t>(st.st_size))
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " File too big: "
+ << local_file.c_str() << std::endl);
+ return false;
+ }
+ size_t fileSize = static_cast<size_t>(st.st_size);
+ FILE* fp = fopen(local_file.c_str(), "rb");
+ if ( !fp )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot open file: "
+ << local_file.c_str() << std::endl);
+ return false;
+ }
+
+ unsigned char *fileBuffer = new unsigned char[fileSize];
+ if ( fread(fileBuffer, 1, fileSize, fp) != fileSize )
+ {
+ delete [] fileBuffer;
+ fclose(fp);
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot read file: "
+ << local_file.c_str() << std::endl);
+ return false;
+ }
+ fclose(fp);
+
+ char remoteCommand[] = "Submit.put";
+ char* pRealURL = const_cast<char*>(realURL.c_str());
+ result = xmlrpc_client_call(&env, pRealURL, remoteCommand,
+ "(6)", fileBuffer, (xmlrpc_int32)fileSize );
+
+ delete [] fileBuffer;
+
+ if ( env.fault_occurred )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " Submission problem: "
+ << env.fault_string << " (" << env.fault_code << ")" << std::endl);
+ xmlrpc_env_clean(&env);
+ xmlrpc_client_cleanup();
+ return false;
+ }
+
+ /* Dispose of our result value. */
+ xmlrpc_DECREF(result);
+ }
+
+ /* Clean up our error-handling environment. */
+ xmlrpc_env_clean(&env);
+
+ /* Shutdown our XML-RPC client library. */
+ xmlrpc_client_cleanup();
+ return true;
+}
+#else
+bool cmCTestSubmitHandler::SubmitUsingXMLRPC(cmStdString const&,
+ std::set<cmStdString> const&,
+ cmStdString const&,
+ cmStdString const&)
+{
+ return false;
+}
+#endif
+
+//----------------------------------------------------------------------------
+int cmCTestSubmitHandler::ProcessHandler()
+{
+ std::string iscdash = this->CTest->GetCTestConfiguration("IsCDash");
+ // cdash does not need to trigger so just return true
+ if(iscdash.size())
+ {
+ this->CDash = true;
+ }
+
+ const std::string &buildDirectory
+ = this->CTest->GetCTestConfiguration("BuildDirectory");
+ if ( buildDirectory.size() == 0 )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot find BuildDirectory key in the DartConfiguration.tcl"
+ << std::endl);
+ return -1;
+ }
+
+ if ( getenv("HTTP_PROXY") )
+ {
+ this->HTTPProxyType = 1;
+ this->HTTPProxy = getenv("HTTP_PROXY");
+ if ( getenv("HTTP_PROXY_PORT") )
+ {
+ this->HTTPProxy += ":";
+ this->HTTPProxy += getenv("HTTP_PROXY_PORT");
+ }
+ if ( getenv("HTTP_PROXY_TYPE") )
+ {
+ cmStdString type = getenv("HTTP_PROXY_TYPE");
+ // HTTP/SOCKS4/SOCKS5
+ if ( type == "HTTP" )
+ {
+ this->HTTPProxyType = 1;
+ }
+ else if ( type == "SOCKS4" )
+ {
+ this->HTTPProxyType = 2;
+ }
+ else if ( type == "SOCKS5" )
+ {
+ this->HTTPProxyType = 3;
+ }
+ }
+ if ( getenv("HTTP_PROXY_USER") )
+ {
+ this->HTTPProxyAuth = getenv("HTTP_PROXY_USER");
+ }
+ if ( getenv("HTTP_PROXY_PASSWD") )
+ {
+ this->HTTPProxyAuth += ":";
+ this->HTTPProxyAuth += getenv("HTTP_PROXY_PASSWD");
+ }
+ }
+
+ if ( getenv("FTP_PROXY") )
+ {
+ this->FTPProxyType = 1;
+ this->FTPProxy = getenv("FTP_PROXY");
+ if ( getenv("FTP_PROXY_PORT") )
+ {
+ this->FTPProxy += ":";
+ this->FTPProxy += getenv("FTP_PROXY_PORT");
+ }
+ if ( getenv("FTP_PROXY_TYPE") )
+ {
+ cmStdString type = getenv("FTP_PROXY_TYPE");
+ // HTTP/SOCKS4/SOCKS5
+ if ( type == "HTTP" )
+ {
+ this->FTPProxyType = 1;
+ }
+ else if ( type == "SOCKS4" )
+ {
+ this->FTPProxyType = 2;
+ }
+ else if ( type == "SOCKS5" )
+ {
+ this->FTPProxyType = 3;
+ }
+ }
+ }
+
+ if ( this->HTTPProxy.size() > 0 )
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Use HTTP Proxy: "
+ << this->HTTPProxy << std::endl);
+ }
+ if ( this->FTPProxy.size() > 0 )
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Use FTP Proxy: "
+ << this->FTPProxy << std::endl);
+ }
+ cmGeneratedFileStream ofs;
+ this->StartLogFile("Submit", ofs);
+
+ cmCTest::SetOfStrings files;
+ std::string prefix = this->GetSubmitResultsPrefix();
+
+ if (!this->Files.empty())
+ {
+ // Submit the explicitly selected files:
+ //
+ cmCTest::SetOfStrings::const_iterator it;
+ for (it = this->Files.begin(); it != this->Files.end(); ++it)
+ {
+ files.insert(*it);
+ }
+ }
+
+ // Add to the list of files to submit from any selected, existing parts:
+ //
+
+ // TODO:
+ // Check if test is enabled
+
+ this->CTest->AddIfExists(cmCTest::PartUpdate, "Update.xml");
+ this->CTest->AddIfExists(cmCTest::PartConfigure, "Configure.xml");
+ this->CTest->AddIfExists(cmCTest::PartBuild, "Build.xml");
+ this->CTest->AddIfExists(cmCTest::PartTest, "Test.xml");
+ if(this->CTest->AddIfExists(cmCTest::PartCoverage, "Coverage.xml"))
+ {
+ cmCTest::VectorOfStrings gfiles;
+ std::string gpath
+ = buildDirectory + "/Testing/" + this->CTest->GetCurrentTag();
+ std::string::size_type glen = gpath.size() + 1;
+ gpath = gpath + "/CoverageLog*";
+ cmCTestLog(this->CTest, DEBUG, "Globbing for: " << gpath.c_str()
+ << std::endl);
+ if ( cmSystemTools::SimpleGlob(gpath, gfiles, 1) )
+ {
+ size_t cc;
+ for ( cc = 0; cc < gfiles.size(); cc ++ )
+ {
+ gfiles[cc] = gfiles[cc].substr(glen);
+ cmCTestLog(this->CTest, DEBUG, "Glob file: " << gfiles[cc].c_str()
+ << std::endl);
+ this->CTest->AddSubmitFile(cmCTest::PartCoverage, gfiles[cc].c_str());
+ }
+ }
+ else
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem globbing" << std::endl);
+ }
+ }
+ this->CTest->AddIfExists(cmCTest::PartMemCheck, "DynamicAnalysis.xml");
+ this->CTest->AddIfExists(cmCTest::PartMemCheck, "Purify.xml");
+ this->CTest->AddIfExists(cmCTest::PartNotes, "Notes.xml");
+ this->CTest->AddIfExists(cmCTest::PartUpload, "Upload.xml");
+
+ // Query parts for files to submit.
+ for(cmCTest::Part p = cmCTest::PartStart;
+ p != cmCTest::PartCount; p = cmCTest::Part(p+1))
+ {
+ // Skip parts we are not submitting.
+ if(!this->SubmitPart[p])
+ {
+ continue;
+ }
+
+ // Submit files from this part.
+ std::vector<std::string> const& pfiles = this->CTest->GetSubmitFiles(p);
+ for(std::vector<std::string>::const_iterator pi = pfiles.begin();
+ pi != pfiles.end(); ++pi)
+ {
+ files.insert(*pi);
+ }
+ }
+
+ if ( ofs )
+ {
+ ofs << "Upload files:" << std::endl;
+ int cnt = 0;
+ cmCTest::SetOfStrings::iterator it;
+ for ( it = files.begin(); it != files.end(); ++ it )
+ {
+ ofs << cnt << "\t" << it->c_str() << std::endl;
+ cnt ++;
+ }
+ }
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, "Submit files (using "
+ << this->CTest->GetCTestConfiguration("DropMethod") << ")"
+ << std::endl);
+ const char* specificTrack = this->CTest->GetSpecificTrack();
+ if ( specificTrack )
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Send to track: "
+ << specificTrack << std::endl);
+ }
+ this->SetLogFile(&ofs);
+
+ cmStdString dropMethod(this->CTest->GetCTestConfiguration("DropMethod"));
+
+ if ( dropMethod == "" || dropMethod == "ftp" )
+ {
+ ofs << "Using drop method: FTP" << std::endl;
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using FTP submit method"
+ << std::endl
+ << " Drop site: ftp://");
+ std::string url = "ftp://";
+ url += cmCTest::MakeURLSafe(
+ this->CTest->GetCTestConfiguration("DropSiteUser")) + ":" +
+ cmCTest::MakeURLSafe(this->CTest->GetCTestConfiguration(
+ "DropSitePassword")) + "@" +
+ this->CTest->GetCTestConfiguration("DropSite") +
+ cmCTest::MakeURLSafe(
+ this->CTest->GetCTestConfiguration("DropLocation"));
+ if ( this->CTest->GetCTestConfiguration("DropSiteUser").size() > 0 )
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ this->CTest->GetCTestConfiguration(
+ "DropSiteUser").c_str());
+ if ( this->CTest->GetCTestConfiguration("DropSitePassword").size() > 0 )
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, ":******");
+ }
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, "@");
+ }
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ this->CTest->GetCTestConfiguration("DropSite")
+ << this->CTest->GetCTestConfiguration("DropLocation") << std::endl);
+ if ( !this->SubmitUsingFTP(buildDirectory + "/Testing/"
+ + this->CTest->GetCurrentTag(),
+ files, prefix, url) )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Problems when submitting via FTP"
+ << std::endl);
+ ofs << " Problems when submitting via FTP" << std::endl;
+ return -1;
+ }
+ if(!this->CDash)
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using HTTP trigger method"
+ << std::endl
+ << " Trigger site: "
+ << this->CTest->GetCTestConfiguration("TriggerSite")
+ << std::endl);
+ if ( !this->
+ TriggerUsingHTTP(files, prefix,
+ this->CTest->GetCTestConfiguration("TriggerSite")))
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Problems when triggering via HTTP" << std::endl);
+ ofs << " Problems when triggering via HTTP" << std::endl;
+ return -1;
+ }
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
+ << std::endl);
+ ofs << " Submission successful" << std::endl;
+ return 0;
+ }
+ }
+ else if ( dropMethod == "http" || dropMethod == "https" )
+ {
+ std::string url = dropMethod;
+ url += "://";
+ ofs << "Using drop method: " << dropMethod << std::endl;
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using HTTP submit method"
+ << std::endl
+ << " Drop site:" << url);
+ if ( this->CTest->GetCTestConfiguration("DropSiteUser").size() > 0 )
+ {
+ url += this->CTest->GetCTestConfiguration("DropSiteUser");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ this->CTest->GetCTestConfiguration("DropSiteUser").c_str());
+ if ( this->CTest->GetCTestConfiguration("DropSitePassword").size() > 0 )
+ {
+ url += ":" + this->CTest->GetCTestConfiguration("DropSitePassword");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, ":******");
+ }
+ url += "@";
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, "@");
+ }
+ url += this->CTest->GetCTestConfiguration("DropSite") +
+ this->CTest->GetCTestConfiguration("DropLocation");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ this->CTest->GetCTestConfiguration("DropSite")
+ << this->CTest->GetCTestConfiguration("DropLocation") << std::endl);
+ if ( !this->SubmitUsingHTTP(buildDirectory + "/Testing/" +
+ this->CTest->GetCurrentTag(), files, prefix, url) )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Problems when submitting via HTTP" << std::endl);
+ ofs << " Problems when submitting via HTTP" << std::endl;
+ return -1;
+ }
+ if(!this->CDash)
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using HTTP trigger method"
+ << std::endl
+ << " Trigger site: "
+ << this->CTest->GetCTestConfiguration("TriggerSite")
+ << std::endl);
+ if ( !this->
+ TriggerUsingHTTP(files, prefix,
+ this->CTest->GetCTestConfiguration("TriggerSite")))
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Problems when triggering via HTTP" << std::endl);
+ ofs << " Problems when triggering via HTTP" << std::endl;
+ return -1;
+ }
+ }
+ if(this->HasErrors)
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Errors occurred during "
+ "submission." << std::endl);
+ ofs << " Errors occurred during submission. " << std::endl;
+ }
+ else
+ {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful" <<
+ (this->HasWarnings ? ", with warnings." : "") << std::endl);
+ ofs << " Submission successful" <<
+ (this->HasWarnings ? ", with warnings." : "") << std::endl;
+ }
+
+ return 0;
+ }
+ else if ( dropMethod == "xmlrpc" )
+ {
+#if defined(CTEST_USE_XMLRPC)
+ ofs << "Using drop method: XML-RPC" << std::endl;
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using XML-RPC submit method"
+ << std::endl);
+ std::string url = this->CTest->GetCTestConfiguration("DropSite");
+ prefix = this->CTest->GetCTestConfiguration("DropLocation");
+ if ( !this->SubmitUsingXMLRPC(buildDirectory + "/Testing/" +
+ this->CTest->GetCurrentTag(), files, prefix, url) )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Problems when submitting via XML-RPC" << std::endl);
+ ofs << " Problems when submitting via XML-RPC" << std::endl;
+ return -1;
+ }
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
+ << std::endl);
+ ofs << " Submission successful" << std::endl;
+ return 0;
+#else
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Submission method \"xmlrpc\" not compiled into CTest!"
+ << std::endl);
+ return -1;
+#endif
+ }
+ else if ( dropMethod == "scp" )
+ {
+ std::string url;
+ std::string oldWorkingDirectory;
+ if ( this->CTest->GetCTestConfiguration("DropSiteUser").size() > 0 )
+ {
+ url += this->CTest->GetCTestConfiguration("DropSiteUser") + "@";
+ }
+ url += this->CTest->GetCTestConfiguration("DropSite") + ":" +
+ this->CTest->GetCTestConfiguration("DropLocation");
+
+ // change to the build directory so that we can uses a relative path
+ // on windows since scp dosn't support "c:" a drive in the path
+ oldWorkingDirectory = cmSystemTools::GetCurrentWorkingDirectory();
+ cmSystemTools::ChangeDirectory(buildDirectory.c_str());
+
+ if ( !this->SubmitUsingSCP(
+ this->CTest->GetCTestConfiguration("ScpCommand"),
+ "Testing/"+this->CTest->GetCurrentTag(), files, prefix, url) )
+ {
+ cmSystemTools::ChangeDirectory(oldWorkingDirectory.c_str());
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Problems when submitting via SCP"
+ << std::endl);
+ ofs << " Problems when submitting via SCP" << std::endl;
+ return -1;
+ }
+ cmSystemTools::ChangeDirectory(oldWorkingDirectory.c_str());
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
+ << std::endl);
+ ofs << " Submission successful" << std::endl;
+ return 0;
+ }
+ else if ( dropMethod == "cp" )
+ {
+ std::string location
+ = this->CTest->GetCTestConfiguration("DropLocation");
+
+
+ // change to the build directory so that we can uses a relative path
+ // on windows since scp dosn't support "c:" a drive in the path
+ std::string
+ oldWorkingDirectory = cmSystemTools::GetCurrentWorkingDirectory();
+ cmSystemTools::ChangeDirectory(buildDirectory.c_str());
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Change directory: "
+ << buildDirectory.c_str() << std::endl);
+
+ if ( !this->SubmitUsingCP(
+ "Testing/"+this->CTest->GetCurrentTag(),
+ files,
+ prefix,
+ location) )
+ {
+ cmSystemTools::ChangeDirectory(oldWorkingDirectory.c_str());
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Problems when submitting via CP"
+ << std::endl);
+ ofs << " Problems when submitting via cp" << std::endl;
+ return -1;
+ }
+ cmSystemTools::ChangeDirectory(oldWorkingDirectory.c_str());
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
+ << std::endl);
+ ofs << " Submission successful" << std::endl;
+ return 0;
+ }
+
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " Unknown submission method: \""
+ << dropMethod << "\"" << std::endl);
+ return -1;
+}
+
+//----------------------------------------------------------------------------
+std::string cmCTestSubmitHandler::GetSubmitResultsPrefix()
+{
+ std::string name = this->CTest->GetCTestConfiguration("Site") +
+ "___" + this->CTest->GetCTestConfiguration("BuildName") +
+ "___" + this->CTest->GetCurrentTag() + "-" +
+ this->CTest->GetTestModelString() + "___XML___";
+ return name;
+}
+
+//----------------------------------------------------------------------------
+void cmCTestSubmitHandler::SelectParts(std::set<cmCTest::Part> const& parts)
+{
+ // Check whether each part is selected.
+ for(cmCTest::Part p = cmCTest::PartStart;
+ p != cmCTest::PartCount; p = cmCTest::Part(p+1))
+ {
+ this->SubmitPart[p] =
+ (std::set<cmCTest::Part>::const_iterator(parts.find(p)) != parts.end());
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmCTestSubmitHandler::SelectFiles(cmCTest::SetOfStrings const& files)
+{
+ cmCTest::SetOfStrings::const_iterator it;
+ for (it = files.begin(); it != files.end(); ++it)
+ {
+ this->Files.insert(*it);
+ }
+}