cmCTestSubmitHandler.cxx 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmCTestSubmitHandler.h"
  14. #include "cmSystemTools.h"
  15. #include "cmVersion.h"
  16. #include "cmGeneratedFileStream.h"
  17. #include "cmCTest.h"
  18. #include <cmsys/Process.h>
  19. #include <cmsys/Base64.h>
  20. // For XML-RPC submission
  21. #include "cm_xmlrpc.h"
  22. // For curl submission
  23. #include "cm_curl.h"
  24. #include <sys/stat.h>
  25. typedef std::vector<char> cmCTestSubmitHandlerVectorOfChar;
  26. static size_t
  27. cmCTestSubmitHandlerWriteMemoryCallback(void *ptr, size_t size, size_t nmemb,
  28. void *data)
  29. {
  30. register int realsize = (int)(size * nmemb);
  31. cmCTestSubmitHandlerVectorOfChar *vec
  32. = static_cast<cmCTestSubmitHandlerVectorOfChar*>(data);
  33. const char* chPtr = static_cast<char*>(ptr);
  34. vec->insert(vec->end(), chPtr, chPtr + realsize);
  35. return realsize;
  36. }
  37. static size_t
  38. cmCTestSubmitHandlerCurlDebugCallback(CURL *, curl_infotype, char *chPtr,
  39. size_t size, void *data)
  40. {
  41. cmCTestSubmitHandlerVectorOfChar *vec
  42. = static_cast<cmCTestSubmitHandlerVectorOfChar*>(data);
  43. vec->insert(vec->end(), chPtr, chPtr + size);
  44. return size;
  45. }
  46. //----------------------------------------------------------------------------
  47. cmCTestSubmitHandler::cmCTestSubmitHandler() : HTTPProxy(), FTPProxy()
  48. {
  49. this->Initialize();
  50. }
  51. //----------------------------------------------------------------------------
  52. void cmCTestSubmitHandler::Initialize()
  53. {
  54. // We submit all available parts by default.
  55. for(cmCTest::Part p = cmCTest::PartStart;
  56. p != cmCTest::PartCount; p = cmCTest::Part(p+1))
  57. {
  58. this->SubmitPart[p] = true;
  59. }
  60. this->CDash = false;
  61. this->Superclass::Initialize();
  62. this->HTTPProxy = "";
  63. this->HTTPProxyType = 0;
  64. this->HTTPProxyAuth = "";
  65. this->FTPProxy = "";
  66. this->FTPProxyType = 0;
  67. this->LogFile = 0;
  68. this->Files.clear();
  69. }
  70. //----------------------------------------------------------------------------
  71. bool cmCTestSubmitHandler::SubmitUsingFTP(const cmStdString& localprefix,
  72. const std::set<cmStdString>& files,
  73. const cmStdString& remoteprefix,
  74. const cmStdString& url)
  75. {
  76. CURL *curl;
  77. CURLcode res;
  78. FILE* ftpfile;
  79. char error_buffer[1024];
  80. /* In windows, this will init the winsock stuff */
  81. ::curl_global_init(CURL_GLOBAL_ALL);
  82. cmCTest::SetOfStrings::const_iterator file;
  83. for ( file = files.begin(); file != files.end(); ++file )
  84. {
  85. /* get a curl handle */
  86. curl = curl_easy_init();
  87. if(curl)
  88. {
  89. // Using proxy
  90. if ( this->FTPProxyType > 0 )
  91. {
  92. curl_easy_setopt(curl, CURLOPT_PROXY, this->FTPProxy.c_str());
  93. switch (this->FTPProxyType)
  94. {
  95. case 2:
  96. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
  97. break;
  98. case 3:
  99. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
  100. break;
  101. default:
  102. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
  103. }
  104. }
  105. // enable uploading
  106. ::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1) ;
  107. cmStdString local_file = *file;
  108. if ( !cmSystemTools::FileExists(local_file.c_str()) )
  109. {
  110. local_file = localprefix + "/" + *file;
  111. }
  112. cmStdString upload_as
  113. = url + "/" + remoteprefix + cmSystemTools::GetFilenameName(*file);
  114. struct stat st;
  115. if ( ::stat(local_file.c_str(), &st) )
  116. {
  117. cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: "
  118. << local_file.c_str() << std::endl);
  119. ::curl_easy_cleanup(curl);
  120. ::curl_global_cleanup();
  121. return false;
  122. }
  123. ftpfile = ::fopen(local_file.c_str(), "rb");
  124. *this->LogFile << "\tUpload file: " << local_file.c_str() << " to "
  125. << upload_as.c_str() << std::endl;
  126. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Upload file: "
  127. << local_file.c_str() << " to "
  128. << upload_as.c_str() << std::endl);
  129. ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  130. // specify target
  131. ::curl_easy_setopt(curl,CURLOPT_URL, upload_as.c_str());
  132. // now specify which file to upload
  133. ::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile);
  134. // and give the size of the upload (optional)
  135. ::curl_easy_setopt(curl, CURLOPT_INFILESIZE,
  136. static_cast<long>(st.st_size));
  137. // and give curl the buffer for errors
  138. ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
  139. // specify handler for output
  140. ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
  141. cmCTestSubmitHandlerWriteMemoryCallback);
  142. ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
  143. cmCTestSubmitHandlerCurlDebugCallback);
  144. /* we pass our 'chunk' struct to the callback function */
  145. cmCTestSubmitHandlerVectorOfChar chunk;
  146. cmCTestSubmitHandlerVectorOfChar chunkDebug;
  147. ::curl_easy_setopt(curl, CURLOPT_FILE, (void *)&chunk);
  148. ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)&chunkDebug);
  149. // Now run off and do what you've been told!
  150. res = ::curl_easy_perform(curl);
  151. if ( chunk.size() > 0 )
  152. {
  153. cmCTestLog(this->CTest, DEBUG, "CURL output: ["
  154. << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
  155. << std::endl);
  156. }
  157. if ( chunkDebug.size() > 0 )
  158. {
  159. cmCTestLog(this->CTest, DEBUG, "CURL debug output: ["
  160. << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
  161. << std::endl);
  162. }
  163. fclose(ftpfile);
  164. if ( res )
  165. {
  166. cmCTestLog(this->CTest, ERROR_MESSAGE,
  167. " Error when uploading file: "
  168. << local_file.c_str() << std::endl);
  169. cmCTestLog(this->CTest, ERROR_MESSAGE, " Error message was: "
  170. << error_buffer << std::endl);
  171. *this->LogFile << " Error when uploading file: "
  172. << local_file.c_str()
  173. << std::endl
  174. << " Error message was: "
  175. << error_buffer << std::endl
  176. << " Curl output was: ";
  177. // avoid dereference of empty vector
  178. if(chunk.size())
  179. {
  180. *this->LogFile << cmCTestLogWrite(&*chunk.begin(), chunk.size());
  181. cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
  182. << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
  183. << std::endl);
  184. }
  185. *this->LogFile << std::endl;
  186. ::curl_easy_cleanup(curl);
  187. ::curl_global_cleanup();
  188. return false;
  189. }
  190. // always cleanup
  191. ::curl_easy_cleanup(curl);
  192. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Uploaded: " + local_file
  193. << std::endl);
  194. }
  195. }
  196. ::curl_global_cleanup();
  197. return true;
  198. }
  199. //----------------------------------------------------------------------------
  200. // Uploading files is simpler
  201. bool cmCTestSubmitHandler::SubmitUsingHTTP(const cmStdString& localprefix,
  202. const std::set<cmStdString>& files,
  203. const cmStdString& remoteprefix,
  204. const cmStdString& url)
  205. {
  206. CURL *curl;
  207. CURLcode res;
  208. FILE* ftpfile;
  209. char error_buffer[1024];
  210. /* In windows, this will init the winsock stuff */
  211. ::curl_global_init(CURL_GLOBAL_ALL);
  212. cmStdString::size_type kk;
  213. cmCTest::SetOfStrings::const_iterator file;
  214. for ( file = files.begin(); file != files.end(); ++file )
  215. {
  216. /* get a curl handle */
  217. curl = curl_easy_init();
  218. if(curl)
  219. {
  220. // Using proxy
  221. if ( this->HTTPProxyType > 0 )
  222. {
  223. curl_easy_setopt(curl, CURLOPT_PROXY, this->HTTPProxy.c_str());
  224. switch (this->HTTPProxyType)
  225. {
  226. case 2:
  227. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
  228. break;
  229. case 3:
  230. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
  231. break;
  232. default:
  233. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
  234. if (this->HTTPProxyAuth.size() > 0)
  235. {
  236. curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD,
  237. this->HTTPProxyAuth.c_str());
  238. }
  239. }
  240. }
  241. /* enable uploading */
  242. curl_easy_setopt(curl, CURLOPT_UPLOAD, 1) ;
  243. /* HTTP PUT please */
  244. ::curl_easy_setopt(curl, CURLOPT_PUT, 1);
  245. ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  246. cmStdString local_file = *file;
  247. if ( !cmSystemTools::FileExists(local_file.c_str()) )
  248. {
  249. local_file = localprefix + "/" + *file;
  250. }
  251. cmStdString remote_file
  252. = remoteprefix + cmSystemTools::GetFilenameName(*file);
  253. *this->LogFile << "\tUpload file: " << local_file.c_str() << " to "
  254. << remote_file.c_str() << std::endl;
  255. cmStdString ofile = "";
  256. for ( kk = 0; kk < remote_file.size(); kk ++ )
  257. {
  258. char c = remote_file[kk];
  259. char hexCh[4] = { 0, 0, 0, 0 };
  260. hexCh[0] = c;
  261. switch ( c )
  262. {
  263. case '+':
  264. case '?':
  265. case '/':
  266. case '\\':
  267. case '&':
  268. case ' ':
  269. case '=':
  270. case '%':
  271. sprintf(hexCh, "%%%02X", (int)c);
  272. ofile.append(hexCh);
  273. break;
  274. default:
  275. ofile.append(hexCh);
  276. }
  277. }
  278. cmStdString upload_as
  279. = url + ((url.find("?",0) == cmStdString::npos) ? "?" : "&")
  280. + "FileName=" + ofile;
  281. struct stat st;
  282. if ( ::stat(local_file.c_str(), &st) )
  283. {
  284. cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: "
  285. << local_file.c_str() << std::endl);
  286. ::curl_easy_cleanup(curl);
  287. ::curl_global_cleanup();
  288. return false;
  289. }
  290. ftpfile = ::fopen(local_file.c_str(), "rb");
  291. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Upload file: "
  292. << local_file.c_str() << " to "
  293. << upload_as.c_str() << " Size: " << st.st_size << std::endl);
  294. // specify target
  295. ::curl_easy_setopt(curl,CURLOPT_URL, upload_as.c_str());
  296. // now specify which file to upload
  297. ::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile);
  298. // and give the size of the upload (optional)
  299. ::curl_easy_setopt(curl, CURLOPT_INFILESIZE,
  300. static_cast<long>(st.st_size));
  301. // and give curl the buffer for errors
  302. ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
  303. // specify handler for output
  304. ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
  305. cmCTestSubmitHandlerWriteMemoryCallback);
  306. ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
  307. cmCTestSubmitHandlerCurlDebugCallback);
  308. /* we pass our 'chunk' struct to the callback function */
  309. cmCTestSubmitHandlerVectorOfChar chunk;
  310. cmCTestSubmitHandlerVectorOfChar chunkDebug;
  311. ::curl_easy_setopt(curl, CURLOPT_FILE, (void *)&chunk);
  312. ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)&chunkDebug);
  313. // Now run off and do what you've been told!
  314. res = ::curl_easy_perform(curl);
  315. if ( chunk.size() > 0 )
  316. {
  317. cmCTestLog(this->CTest, DEBUG, "CURL output: ["
  318. << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
  319. << std::endl);
  320. }
  321. if ( chunkDebug.size() > 0 )
  322. {
  323. cmCTestLog(this->CTest, DEBUG, "CURL debug output: ["
  324. << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
  325. << std::endl);
  326. }
  327. fclose(ftpfile);
  328. if ( res )
  329. {
  330. cmCTestLog(this->CTest, ERROR_MESSAGE,
  331. " Error when uploading file: "
  332. << local_file.c_str() << std::endl);
  333. cmCTestLog(this->CTest, ERROR_MESSAGE, " Error message was: "
  334. << error_buffer << std::endl);
  335. *this->LogFile << " Error when uploading file: "
  336. << local_file.c_str()
  337. << std::endl
  338. << " Error message was: " << error_buffer
  339. << std::endl;
  340. // avoid deref of begin for zero size array
  341. if(chunk.size())
  342. {
  343. *this->LogFile << " Curl output was: "
  344. << cmCTestLogWrite(&*chunk.begin(), chunk.size())
  345. << std::endl;
  346. cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
  347. << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
  348. << std::endl);
  349. }
  350. ::curl_easy_cleanup(curl);
  351. ::curl_global_cleanup();
  352. return false;
  353. }
  354. // always cleanup
  355. ::curl_easy_cleanup(curl);
  356. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Uploaded: " + local_file
  357. << std::endl);
  358. }
  359. }
  360. ::curl_global_cleanup();
  361. return true;
  362. }
  363. //----------------------------------------------------------------------------
  364. bool cmCTestSubmitHandler::TriggerUsingHTTP(
  365. const std::set<cmStdString>& files,
  366. const cmStdString& remoteprefix,
  367. const cmStdString& url)
  368. {
  369. CURL *curl;
  370. char error_buffer[1024];
  371. /* In windows, this will init the winsock stuff */
  372. ::curl_global_init(CURL_GLOBAL_ALL);
  373. cmCTest::SetOfStrings::const_iterator file;
  374. for ( file = files.begin(); file != files.end(); ++file )
  375. {
  376. /* get a curl handle */
  377. curl = curl_easy_init();
  378. if(curl)
  379. {
  380. // Using proxy
  381. if ( this->HTTPProxyType > 0 )
  382. {
  383. curl_easy_setopt(curl, CURLOPT_PROXY, this->HTTPProxy.c_str());
  384. switch (this->HTTPProxyType)
  385. {
  386. case 2:
  387. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
  388. break;
  389. case 3:
  390. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
  391. break;
  392. default:
  393. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
  394. if (this->HTTPProxyAuth.size() > 0)
  395. {
  396. curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD,
  397. this->HTTPProxyAuth.c_str());
  398. }
  399. }
  400. }
  401. ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  402. // and give curl the buffer for errors
  403. ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
  404. // specify handler for output
  405. ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
  406. cmCTestSubmitHandlerWriteMemoryCallback);
  407. ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
  408. cmCTestSubmitHandlerCurlDebugCallback);
  409. /* we pass our 'chunk' struct to the callback function */
  410. cmCTestSubmitHandlerVectorOfChar chunk;
  411. cmCTestSubmitHandlerVectorOfChar chunkDebug;
  412. ::curl_easy_setopt(curl, CURLOPT_FILE, (void *)&chunk);
  413. ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)&chunkDebug);
  414. cmStdString rfile
  415. = remoteprefix + cmSystemTools::GetFilenameName(*file);
  416. cmStdString ofile = "";
  417. cmStdString::iterator kk;
  418. for ( kk = rfile.begin(); kk < rfile.end(); ++ kk)
  419. {
  420. char c = *kk;
  421. char hexCh[4] = { 0, 0, 0, 0 };
  422. hexCh[0] = c;
  423. switch ( c )
  424. {
  425. case '+':
  426. case '?':
  427. case '/':
  428. case '\\':
  429. case '&':
  430. case ' ':
  431. case '=':
  432. case '%':
  433. sprintf(hexCh, "%%%02X", (int)c);
  434. ofile.append(hexCh);
  435. break;
  436. default:
  437. ofile.append(hexCh);
  438. }
  439. }
  440. cmStdString turl
  441. = url + ((url.find("?",0) == cmStdString::npos) ? "?" : "&")
  442. + "xmlfile=" + ofile;
  443. *this->LogFile << "Trigger url: " << turl.c_str() << std::endl;
  444. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Trigger url: "
  445. << turl.c_str() << std::endl);
  446. curl_easy_setopt(curl, CURLOPT_URL, turl.c_str());
  447. if ( curl_easy_perform(curl) )
  448. {
  449. cmCTestLog(this->CTest, ERROR_MESSAGE, " Error when triggering: "
  450. << turl.c_str() << std::endl);
  451. cmCTestLog(this->CTest, ERROR_MESSAGE, " Error message was: "
  452. << error_buffer << std::endl);
  453. *this->LogFile << "\tTrigerring failed with error: " << error_buffer
  454. << std::endl
  455. << " Error message was: " << error_buffer
  456. << std::endl;
  457. if(chunk.size())
  458. {
  459. *this->LogFile
  460. << " Curl output was: "
  461. << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << std::endl;
  462. cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
  463. << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
  464. << std::endl);
  465. }
  466. ::curl_easy_cleanup(curl);
  467. ::curl_global_cleanup();
  468. return false;
  469. }
  470. if ( chunk.size() > 0 )
  471. {
  472. cmCTestLog(this->CTest, DEBUG, "CURL output: ["
  473. << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
  474. << std::endl);
  475. }
  476. if ( chunkDebug.size() > 0 )
  477. {
  478. cmCTestLog(this->CTest, DEBUG, "CURL debug output: ["
  479. << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size())
  480. << "]" << std::endl);
  481. }
  482. // always cleanup
  483. ::curl_easy_cleanup(curl);
  484. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl);
  485. }
  486. }
  487. ::curl_global_cleanup();
  488. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Dart server triggered..."
  489. << std::endl);
  490. return true;
  491. }
  492. //----------------------------------------------------------------------------
  493. bool cmCTestSubmitHandler::SubmitUsingSCP(
  494. const cmStdString& scp_command,
  495. const cmStdString& localprefix,
  496. const std::set<cmStdString>& files,
  497. const cmStdString& remoteprefix,
  498. const cmStdString& url)
  499. {
  500. if ( !scp_command.size() || !localprefix.size() ||
  501. !files.size() || !remoteprefix.size() || !url.size() )
  502. {
  503. return 0;
  504. }
  505. std::vector<const char*> argv;
  506. argv.push_back(scp_command.c_str()); // Scp command
  507. argv.push_back(scp_command.c_str()); // Dummy string for file
  508. argv.push_back(scp_command.c_str()); // Dummy string for remote url
  509. argv.push_back(0);
  510. cmsysProcess* cp = cmsysProcess_New();
  511. cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
  512. //cmsysProcess_SetTimeout(cp, timeout);
  513. int problems = 0;
  514. cmCTest::SetOfStrings::const_iterator file;
  515. for ( file = files.begin(); file != files.end(); ++file )
  516. {
  517. int retVal;
  518. std::string lfname = localprefix;
  519. cmSystemTools::ConvertToUnixSlashes(lfname);
  520. lfname += "/" + *file;
  521. lfname = cmSystemTools::ConvertToOutputPath(lfname.c_str());
  522. argv[1] = lfname.c_str();
  523. std::string rfname = url + "/" + remoteprefix + *file;
  524. argv[2] = rfname.c_str();
  525. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Execute \"" << argv[0]
  526. << "\" \"" << argv[1] << "\" \""
  527. << argv[2] << "\"" << std::endl);
  528. *this->LogFile << "Execute \"" << argv[0] << "\" \"" << argv[1] << "\" \""
  529. << argv[2] << "\"" << std::endl;
  530. cmsysProcess_SetCommand(cp, &*argv.begin());
  531. cmsysProcess_Execute(cp);
  532. char* data;
  533. int length;
  534. while(cmsysProcess_WaitForData(cp, &data, &length, 0))
  535. {
  536. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
  537. cmCTestLogWrite(data, length));
  538. }
  539. cmsysProcess_WaitForExit(cp, 0);
  540. int result = cmsysProcess_GetState(cp);
  541. if(result == cmsysProcess_State_Exited)
  542. {
  543. retVal = cmsysProcess_GetExitValue(cp);
  544. if ( retVal != 0 )
  545. {
  546. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "\tSCP returned: "
  547. << retVal << std::endl);
  548. *this->LogFile << "\tSCP returned: " << retVal << std::endl;
  549. problems ++;
  550. }
  551. }
  552. else if(result == cmsysProcess_State_Exception)
  553. {
  554. retVal = cmsysProcess_GetExitException(cp);
  555. cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was an exception: "
  556. << retVal << std::endl);
  557. *this->LogFile << "\tThere was an exception: " << retVal << std::endl;
  558. problems ++;
  559. }
  560. else if(result == cmsysProcess_State_Expired)
  561. {
  562. cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was a timeout"
  563. << std::endl);
  564. *this->LogFile << "\tThere was a timeout" << std::endl;
  565. problems ++;
  566. }
  567. else if(result == cmsysProcess_State_Error)
  568. {
  569. cmCTestLog(this->CTest, ERROR_MESSAGE, "\tError executing SCP: "
  570. << cmsysProcess_GetErrorString(cp) << std::endl);
  571. *this->LogFile << "\tError executing SCP: "
  572. << cmsysProcess_GetErrorString(cp) << std::endl;
  573. problems ++;
  574. }
  575. }
  576. cmsysProcess_Delete(cp);
  577. if ( problems )
  578. {
  579. return false;
  580. }
  581. return true;
  582. }
  583. //----------------------------------------------------------------------------
  584. bool cmCTestSubmitHandler::SubmitUsingXMLRPC(const cmStdString& localprefix,
  585. const std::set<cmStdString>& files,
  586. const cmStdString& remoteprefix,
  587. const cmStdString& url)
  588. {
  589. xmlrpc_env env;
  590. char ctestString[] = "CTest";
  591. std::string ctestVersionString = cmVersion::GetCMakeVersion();
  592. char* ctestVersion = const_cast<char*>(ctestVersionString.c_str());
  593. cmStdString realURL = url + "/" + remoteprefix + "/Command/";
  594. /* Start up our XML-RPC client library. */
  595. xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, ctestString, ctestVersion);
  596. /* Initialize our error-handling environment. */
  597. xmlrpc_env_init(&env);
  598. /* Call the famous server at UserLand. */
  599. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submitting to: "
  600. << realURL.c_str() << " (" << remoteprefix.c_str() << ")" << std::endl);
  601. cmCTest::SetOfStrings::const_iterator file;
  602. for ( file = files.begin(); file != files.end(); ++file )
  603. {
  604. xmlrpc_value *result;
  605. cmStdString local_file = *file;
  606. if ( !cmSystemTools::FileExists(local_file.c_str()) )
  607. {
  608. local_file = localprefix + "/" + *file;
  609. }
  610. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submit file: "
  611. << local_file.c_str() << std::endl);
  612. struct stat st;
  613. if ( ::stat(local_file.c_str(), &st) )
  614. {
  615. cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: "
  616. << local_file.c_str() << std::endl);
  617. return false;
  618. }
  619. // off_t can be bigger than size_t. fread takes size_t.
  620. // make sure the file is not too big.
  621. if(static_cast<off_t>(static_cast<size_t>(st.st_size)) !=
  622. static_cast<off_t>(st.st_size))
  623. {
  624. cmCTestLog(this->CTest, ERROR_MESSAGE, " File too big: "
  625. << local_file.c_str() << std::endl);
  626. return false;
  627. }
  628. size_t fileSize = static_cast<size_t>(st.st_size);
  629. FILE* fp = fopen(local_file.c_str(), "rb");
  630. if ( !fp )
  631. {
  632. cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot open file: "
  633. << local_file.c_str() << std::endl);
  634. return false;
  635. }
  636. unsigned char *fileBuffer = new unsigned char[fileSize];
  637. if ( fread(fileBuffer, 1, fileSize, fp) != fileSize )
  638. {
  639. delete [] fileBuffer;
  640. fclose(fp);
  641. cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot read file: "
  642. << local_file.c_str() << std::endl);
  643. return false;
  644. }
  645. fclose(fp);
  646. char remoteCommand[] = "Submit.put";
  647. char* pRealURL = const_cast<char*>(realURL.c_str());
  648. result = xmlrpc_client_call(&env, pRealURL, remoteCommand,
  649. "(6)", fileBuffer, (xmlrpc_int32)fileSize );
  650. delete [] fileBuffer;
  651. if ( env.fault_occurred )
  652. {
  653. cmCTestLog(this->CTest, ERROR_MESSAGE, " Submission problem: "
  654. << env.fault_string << " (" << env.fault_code << ")" << std::endl);
  655. xmlrpc_env_clean(&env);
  656. xmlrpc_client_cleanup();
  657. return false;
  658. }
  659. /* Dispose of our result value. */
  660. xmlrpc_DECREF(result);
  661. }
  662. /* Clean up our error-handling environment. */
  663. xmlrpc_env_clean(&env);
  664. /* Shutdown our XML-RPC client library. */
  665. xmlrpc_client_cleanup();
  666. return true;
  667. }
  668. //----------------------------------------------------------------------------
  669. int cmCTestSubmitHandler::ProcessHandler()
  670. {
  671. std::string iscdash = this->CTest->GetCTestConfiguration("IsCDash");
  672. // cdash does not need to trigger so just return true
  673. if(iscdash.size())
  674. {
  675. this->CDash = true;
  676. }
  677. const std::string &buildDirectory
  678. = this->CTest->GetCTestConfiguration("BuildDirectory");
  679. if ( buildDirectory.size() == 0 )
  680. {
  681. cmCTestLog(this->CTest, ERROR_MESSAGE,
  682. "Cannot find BuildDirectory key in the DartConfiguration.tcl"
  683. << std::endl);
  684. return -1;
  685. }
  686. if ( getenv("HTTP_PROXY") )
  687. {
  688. this->HTTPProxyType = 1;
  689. this->HTTPProxy = getenv("HTTP_PROXY");
  690. if ( getenv("HTTP_PROXY_PORT") )
  691. {
  692. this->HTTPProxy += ":";
  693. this->HTTPProxy += getenv("HTTP_PROXY_PORT");
  694. }
  695. if ( getenv("HTTP_PROXY_TYPE") )
  696. {
  697. cmStdString type = getenv("HTTP_PROXY_TYPE");
  698. // HTTP/SOCKS4/SOCKS5
  699. if ( type == "HTTP" )
  700. {
  701. this->HTTPProxyType = 1;
  702. }
  703. else if ( type == "SOCKS4" )
  704. {
  705. this->HTTPProxyType = 2;
  706. }
  707. else if ( type == "SOCKS5" )
  708. {
  709. this->HTTPProxyType = 3;
  710. }
  711. }
  712. if ( getenv("HTTP_PROXY_USER") )
  713. {
  714. this->HTTPProxyAuth = getenv("HTTP_PROXY_USER");
  715. }
  716. if ( getenv("HTTP_PROXY_PASSWD") )
  717. {
  718. this->HTTPProxyAuth += ":";
  719. this->HTTPProxyAuth += getenv("HTTP_PROXY_PASSWD");
  720. }
  721. }
  722. if ( getenv("FTP_PROXY") )
  723. {
  724. this->FTPProxyType = 1;
  725. this->FTPProxy = getenv("FTP_PROXY");
  726. if ( getenv("FTP_PROXY_PORT") )
  727. {
  728. this->FTPProxy += ":";
  729. this->FTPProxy += getenv("FTP_PROXY_PORT");
  730. }
  731. if ( getenv("FTP_PROXY_TYPE") )
  732. {
  733. cmStdString type = getenv("FTP_PROXY_TYPE");
  734. // HTTP/SOCKS4/SOCKS5
  735. if ( type == "HTTP" )
  736. {
  737. this->FTPProxyType = 1;
  738. }
  739. else if ( type == "SOCKS4" )
  740. {
  741. this->FTPProxyType = 2;
  742. }
  743. else if ( type == "SOCKS5" )
  744. {
  745. this->FTPProxyType = 3;
  746. }
  747. }
  748. }
  749. if ( this->HTTPProxy.size() > 0 )
  750. {
  751. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Use HTTP Proxy: "
  752. << this->HTTPProxy << std::endl);
  753. }
  754. if ( this->FTPProxy.size() > 0 )
  755. {
  756. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Use FTP Proxy: "
  757. << this->FTPProxy << std::endl);
  758. }
  759. cmGeneratedFileStream ofs;
  760. this->StartLogFile("Submit", ofs);
  761. cmCTest::SetOfStrings files;
  762. std::string prefix = this->GetSubmitResultsPrefix();
  763. if (!this->Files.empty())
  764. {
  765. // Submit the explicitly selected files:
  766. //
  767. cmCTest::SetOfStrings::const_iterator it;
  768. for (it = this->Files.begin(); it != this->Files.end(); ++it)
  769. {
  770. files.insert(*it);
  771. }
  772. }
  773. // Add to the list of files to submit from any selected, existing parts:
  774. //
  775. // TODO:
  776. // Check if test is enabled
  777. this->CTest->AddIfExists(cmCTest::PartUpdate, "Update.xml");
  778. this->CTest->AddIfExists(cmCTest::PartConfigure, "Configure.xml");
  779. this->CTest->AddIfExists(cmCTest::PartBuild, "Build.xml");
  780. this->CTest->AddIfExists(cmCTest::PartTest, "Test.xml");
  781. if(this->CTest->AddIfExists(cmCTest::PartCoverage, "Coverage.xml"))
  782. {
  783. cmCTest::VectorOfStrings gfiles;
  784. std::string gpath
  785. = buildDirectory + "/Testing/" + this->CTest->GetCurrentTag();
  786. std::string::size_type glen = gpath.size() + 1;
  787. gpath = gpath + "/CoverageLog*";
  788. cmCTestLog(this->CTest, DEBUG, "Globbing for: " << gpath.c_str()
  789. << std::endl);
  790. if ( cmSystemTools::SimpleGlob(gpath, gfiles, 1) )
  791. {
  792. size_t cc;
  793. for ( cc = 0; cc < gfiles.size(); cc ++ )
  794. {
  795. gfiles[cc] = gfiles[cc].substr(glen);
  796. cmCTestLog(this->CTest, DEBUG, "Glob file: " << gfiles[cc].c_str()
  797. << std::endl);
  798. this->CTest->AddSubmitFile(cmCTest::PartCoverage, gfiles[cc].c_str());
  799. }
  800. }
  801. else
  802. {
  803. cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem globbing" << std::endl);
  804. }
  805. }
  806. this->CTest->AddIfExists(cmCTest::PartMemCheck, "DynamicAnalysis.xml");
  807. this->CTest->AddIfExists(cmCTest::PartMemCheck, "Purify.xml");
  808. this->CTest->AddIfExists(cmCTest::PartNotes, "Notes.xml");
  809. // Query parts for files to submit.
  810. for(cmCTest::Part p = cmCTest::PartStart;
  811. p != cmCTest::PartCount; p = cmCTest::Part(p+1))
  812. {
  813. // Skip parts we are not submitting.
  814. if(!this->SubmitPart[p])
  815. {
  816. continue;
  817. }
  818. // Submit files from this part.
  819. std::vector<std::string> const& pfiles = this->CTest->GetSubmitFiles(p);
  820. for(std::vector<std::string>::const_iterator pi = pfiles.begin();
  821. pi != pfiles.end(); ++pi)
  822. {
  823. files.insert(*pi);
  824. }
  825. }
  826. if ( ofs )
  827. {
  828. ofs << "Upload files:" << std::endl;
  829. int cnt = 0;
  830. cmCTest::SetOfStrings::iterator it;
  831. for ( it = files.begin(); it != files.end(); ++ it )
  832. {
  833. ofs << cnt << "\t" << it->c_str() << std::endl;
  834. cnt ++;
  835. }
  836. }
  837. cmCTestLog(this->CTest, HANDLER_OUTPUT, "Submit files (using "
  838. << this->CTest->GetCTestConfiguration("DropMethod") << ")"
  839. << std::endl);
  840. const char* specificTrack = this->CTest->GetSpecificTrack();
  841. if ( specificTrack )
  842. {
  843. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Send to track: "
  844. << specificTrack << std::endl);
  845. }
  846. this->SetLogFile(&ofs);
  847. cmStdString dropMethod(this->CTest->GetCTestConfiguration("DropMethod"));
  848. if ( dropMethod == "" || dropMethod == "ftp" )
  849. {
  850. ofs << "Using drop method: FTP" << std::endl;
  851. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using FTP submit method"
  852. << std::endl
  853. << " Drop site: ftp://");
  854. std::string url = "ftp://";
  855. url += cmCTest::MakeURLSafe(
  856. this->CTest->GetCTestConfiguration("DropSiteUser")) + ":" +
  857. cmCTest::MakeURLSafe(this->CTest->GetCTestConfiguration(
  858. "DropSitePassword")) + "@" +
  859. this->CTest->GetCTestConfiguration("DropSite") +
  860. cmCTest::MakeURLSafe(
  861. this->CTest->GetCTestConfiguration("DropLocation"));
  862. if ( this->CTest->GetCTestConfiguration("DropSiteUser").size() > 0 )
  863. {
  864. cmCTestLog(this->CTest, HANDLER_OUTPUT,
  865. this->CTest->GetCTestConfiguration(
  866. "DropSiteUser").c_str());
  867. if ( this->CTest->GetCTestConfiguration("DropSitePassword").size() > 0 )
  868. {
  869. cmCTestLog(this->CTest, HANDLER_OUTPUT, ":******");
  870. }
  871. cmCTestLog(this->CTest, HANDLER_OUTPUT, "@");
  872. }
  873. cmCTestLog(this->CTest, HANDLER_OUTPUT,
  874. this->CTest->GetCTestConfiguration("DropSite")
  875. << this->CTest->GetCTestConfiguration("DropLocation") << std::endl);
  876. if ( !this->SubmitUsingFTP(buildDirectory + "/Testing/"
  877. + this->CTest->GetCurrentTag(),
  878. files, prefix, url) )
  879. {
  880. cmCTestLog(this->CTest, ERROR_MESSAGE,
  881. " Problems when submitting via FTP"
  882. << std::endl);
  883. ofs << " Problems when submitting via FTP" << std::endl;
  884. return -1;
  885. }
  886. if(!this->CDash)
  887. {
  888. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using HTTP trigger method"
  889. << std::endl
  890. << " Trigger site: "
  891. << this->CTest->GetCTestConfiguration("TriggerSite")
  892. << std::endl);
  893. if ( !this->
  894. TriggerUsingHTTP(files, prefix,
  895. this->CTest->GetCTestConfiguration("TriggerSite")))
  896. {
  897. cmCTestLog(this->CTest, ERROR_MESSAGE,
  898. " Problems when triggering via HTTP" << std::endl);
  899. ofs << " Problems when triggering via HTTP" << std::endl;
  900. return -1;
  901. }
  902. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
  903. << std::endl);
  904. ofs << " Submission successful" << std::endl;
  905. return 0;
  906. }
  907. }
  908. else if ( dropMethod == "http" )
  909. {
  910. ofs << "Using drop method: HTTP" << std::endl;
  911. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using HTTP submit method"
  912. << std::endl
  913. << " Drop site: http://");
  914. std::string url = "http://";
  915. if ( this->CTest->GetCTestConfiguration("DropSiteUser").size() > 0 )
  916. {
  917. url += this->CTest->GetCTestConfiguration("DropSiteUser");
  918. cmCTestLog(this->CTest, HANDLER_OUTPUT,
  919. this->CTest->GetCTestConfiguration("DropSiteUser").c_str());
  920. if ( this->CTest->GetCTestConfiguration("DropSitePassword").size() > 0 )
  921. {
  922. url += ":" + this->CTest->GetCTestConfiguration("DropSitePassword");
  923. cmCTestLog(this->CTest, HANDLER_OUTPUT, ":******");
  924. }
  925. url += "@";
  926. cmCTestLog(this->CTest, HANDLER_OUTPUT, "@");
  927. }
  928. url += this->CTest->GetCTestConfiguration("DropSite") +
  929. this->CTest->GetCTestConfiguration("DropLocation");
  930. cmCTestLog(this->CTest, HANDLER_OUTPUT,
  931. this->CTest->GetCTestConfiguration("DropSite")
  932. << this->CTest->GetCTestConfiguration("DropLocation") << std::endl);
  933. if ( !this->SubmitUsingHTTP(buildDirectory + "/Testing/" +
  934. this->CTest->GetCurrentTag(), files, prefix, url) )
  935. {
  936. cmCTestLog(this->CTest, ERROR_MESSAGE,
  937. " Problems when submitting via HTTP" << std::endl);
  938. ofs << " Problems when submitting via HTTP" << std::endl;
  939. return -1;
  940. }
  941. if(!this->CDash)
  942. {
  943. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using HTTP trigger method"
  944. << std::endl
  945. << " Trigger site: "
  946. << this->CTest->GetCTestConfiguration("TriggerSite")
  947. << std::endl);
  948. if ( !this->
  949. TriggerUsingHTTP(files, prefix,
  950. this->CTest->GetCTestConfiguration("TriggerSite")))
  951. {
  952. cmCTestLog(this->CTest, ERROR_MESSAGE,
  953. " Problems when triggering via HTTP" << std::endl);
  954. ofs << " Problems when triggering via HTTP" << std::endl;
  955. return -1;
  956. }
  957. }
  958. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
  959. << std::endl);
  960. ofs << " Submission successful" << std::endl;
  961. return 0;
  962. }
  963. else if ( dropMethod == "xmlrpc" )
  964. {
  965. ofs << "Using drop method: XML-RPC" << std::endl;
  966. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Using XML-RPC submit method"
  967. << std::endl);
  968. std::string url = this->CTest->GetCTestConfiguration("DropSite");
  969. prefix = this->CTest->GetCTestConfiguration("DropLocation");
  970. if ( !this->SubmitUsingXMLRPC(buildDirectory + "/Testing/" +
  971. this->CTest->GetCurrentTag(), files, prefix, url) )
  972. {
  973. cmCTestLog(this->CTest, ERROR_MESSAGE,
  974. " Problems when submitting via XML-RPC" << std::endl);
  975. ofs << " Problems when submitting via XML-RPC" << std::endl;
  976. return -1;
  977. }
  978. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
  979. << std::endl);
  980. ofs << " Submission successful" << std::endl;
  981. return 0;
  982. }
  983. else if ( dropMethod == "scp" )
  984. {
  985. std::string url;
  986. std::string oldWorkingDirectory;
  987. if ( this->CTest->GetCTestConfiguration("DropSiteUser").size() > 0 )
  988. {
  989. url += this->CTest->GetCTestConfiguration("DropSiteUser") + "@";
  990. }
  991. url += this->CTest->GetCTestConfiguration("DropSite") + ":" +
  992. this->CTest->GetCTestConfiguration("DropLocation");
  993. // change to the build directory so that we can uses a relative path
  994. // on windows since scp dosn't support "c:" a drive in the path
  995. oldWorkingDirectory = cmSystemTools::GetCurrentWorkingDirectory();
  996. cmSystemTools::ChangeDirectory(buildDirectory.c_str());
  997. if ( !this->SubmitUsingSCP(
  998. this->CTest->GetCTestConfiguration("ScpCommand"),
  999. "Testing/"+this->CTest->GetCurrentTag(), files, prefix, url) )
  1000. {
  1001. cmSystemTools::ChangeDirectory(oldWorkingDirectory.c_str());
  1002. cmCTestLog(this->CTest, ERROR_MESSAGE,
  1003. " Problems when submitting via SCP"
  1004. << std::endl);
  1005. ofs << " Problems when submitting via SCP" << std::endl;
  1006. return -1;
  1007. }
  1008. cmSystemTools::ChangeDirectory(oldWorkingDirectory.c_str());
  1009. cmCTestLog(this->CTest, HANDLER_OUTPUT, " Submission successful"
  1010. << std::endl);
  1011. ofs << " Submission successful" << std::endl;
  1012. return 0;
  1013. }
  1014. cmCTestLog(this->CTest, ERROR_MESSAGE, " Unknown submission method: \""
  1015. << dropMethod << "\"" << std::endl);
  1016. return -1;
  1017. }
  1018. //----------------------------------------------------------------------------
  1019. std::string cmCTestSubmitHandler::GetSubmitResultsPrefix()
  1020. {
  1021. std::string name = this->CTest->GetCTestConfiguration("Site") +
  1022. "___" + this->CTest->GetCTestConfiguration("BuildName") +
  1023. "___" + this->CTest->GetCurrentTag() + "-" +
  1024. this->CTest->GetTestModelString() + "___XML___";
  1025. return name;
  1026. }
  1027. //----------------------------------------------------------------------------
  1028. void cmCTestSubmitHandler::SelectParts(std::set<cmCTest::Part> const& parts)
  1029. {
  1030. // Check whether each part is selected.
  1031. for(cmCTest::Part p = cmCTest::PartStart;
  1032. p != cmCTest::PartCount; p = cmCTest::Part(p+1))
  1033. {
  1034. this->SubmitPart[p] =
  1035. (std::set<cmCTest::Part>::const_iterator(parts.find(p)) != parts.end());
  1036. }
  1037. }
  1038. //----------------------------------------------------------------------------
  1039. void cmCTestSubmitHandler::SelectFiles(cmCTest::SetOfStrings const& files)
  1040. {
  1041. cmCTest::SetOfStrings::const_iterator it;
  1042. for (it = files.begin(); it != files.end(); ++it)
  1043. {
  1044. this->Files.insert(*it);
  1045. }
  1046. }