cmCTestMemCheckHandler.cxx 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmCTestMemCheckHandler.h"
  11. #include "cmXMLParser.h"
  12. #include "cmCTest.h"
  13. #include "cmake.h"
  14. #include "cmGeneratedFileStream.h"
  15. #include <cmsys/Process.h>
  16. #include <cmsys/RegularExpression.hxx>
  17. #include <cmsys/Base64.h>
  18. #include <cmsys/Glob.hxx>
  19. #include <cmsys/FStream.hxx>
  20. #include "cmMakefile.h"
  21. #include "cmXMLSafe.h"
  22. #include <stdlib.h>
  23. #include <math.h>
  24. #include <float.h>
  25. struct CatToErrorType
  26. {
  27. const char* ErrorCategory;
  28. int ErrorCode;
  29. };
  30. static CatToErrorType cmCTestMemCheckBoundsChecker[] = {
  31. // Error tags
  32. {"Write Overrun", cmCTestMemCheckHandler::ABW},
  33. {"Read Overrun", cmCTestMemCheckHandler::ABR},
  34. {"Memory Overrun", cmCTestMemCheckHandler::ABW},
  35. {"Allocation Conflict", cmCTestMemCheckHandler::FMM},
  36. {"Bad Pointer Use", cmCTestMemCheckHandler::FMW},
  37. {"Dangling Pointer", cmCTestMemCheckHandler::FMR},
  38. {0,0}
  39. };
  40. static void xmlReportError(int line, const char* msg, void* data)
  41. {
  42. cmCTest* ctest = (cmCTest*)data;
  43. cmCTestLog(ctest, ERROR_MESSAGE,
  44. "Error parsing XML in stream at line "
  45. << line << ": " << msg << std::endl);
  46. }
  47. // parse the xml file containing the results of last BoundsChecker run
  48. class cmBoundsCheckerParser : public cmXMLParser
  49. {
  50. public:
  51. cmBoundsCheckerParser(cmCTest* c)
  52. {
  53. this->CTest = c;
  54. this->SetErrorCallback(xmlReportError, (void*)c);
  55. }
  56. void StartElement(const std::string& name, const char** atts)
  57. {
  58. if(name == "MemoryLeak" ||
  59. name == "ResourceLeak")
  60. {
  61. this->Errors.push_back(cmCTestMemCheckHandler::MLK);
  62. }
  63. else if(name == "Error" ||
  64. name == "Dangling Pointer")
  65. {
  66. this->ParseError(atts);
  67. }
  68. // Create the log
  69. cmOStringStream ostr;
  70. ostr << name << ":\n";
  71. int i = 0;
  72. for(; atts[i] != 0; i+=2)
  73. {
  74. ostr << " " << cmXMLSafe(atts[i])
  75. << " - " << cmXMLSafe(atts[i+1]) << "\n";
  76. }
  77. ostr << "\n";
  78. this->Log += ostr.str();
  79. }
  80. void EndElement(const std::string& )
  81. {
  82. }
  83. const char* GetAttribute(const char* name, const char** atts)
  84. {
  85. int i = 0;
  86. for(; atts[i] != 0; ++i)
  87. {
  88. if(strcmp(name, atts[i]) == 0)
  89. {
  90. return atts[i+1];
  91. }
  92. }
  93. return 0;
  94. }
  95. void ParseError(const char** atts)
  96. {
  97. CatToErrorType* ptr = cmCTestMemCheckBoundsChecker;
  98. const char* cat = this->GetAttribute("ErrorCategory", atts);
  99. if(!cat)
  100. {
  101. this->Errors.push_back(cmCTestMemCheckHandler::ABW); // do not know
  102. cmCTestLog(this->CTest, ERROR_MESSAGE,
  103. "No Category found in Bounds checker XML\n" );
  104. return;
  105. }
  106. while(ptr->ErrorCategory && cat)
  107. {
  108. if(strcmp(ptr->ErrorCategory, cat) == 0)
  109. {
  110. this->Errors.push_back(ptr->ErrorCode);
  111. return; // found it we are done
  112. }
  113. ptr++;
  114. }
  115. if(ptr->ErrorCategory)
  116. {
  117. this->Errors.push_back(cmCTestMemCheckHandler::ABW); // do not know
  118. cmCTestLog(this->CTest, ERROR_MESSAGE,
  119. "Found unknown Bounds Checker error "
  120. << ptr->ErrorCategory << std::endl);
  121. }
  122. }
  123. cmCTest* CTest;
  124. std::vector<int> Errors;
  125. std::string Log;
  126. };
  127. #define BOUNDS_CHECKER_MARKER \
  128. "******######*****Begin BOUNDS CHECKER XML******######******"
  129. //----------------------------------------------------------------------
  130. cmCTestMemCheckHandler::cmCTestMemCheckHandler()
  131. {
  132. this->MemCheck = true;
  133. this->CustomMaximumPassedTestOutputSize = 0;
  134. this->CustomMaximumFailedTestOutputSize = 0;
  135. this->LogWithPID = false;
  136. }
  137. //----------------------------------------------------------------------
  138. void cmCTestMemCheckHandler::Initialize()
  139. {
  140. this->Superclass::Initialize();
  141. this->LogWithPID = false;
  142. this->CustomMaximumPassedTestOutputSize = 0;
  143. this->CustomMaximumFailedTestOutputSize = 0;
  144. this->MemoryTester = "";
  145. this->MemoryTesterDynamicOptions.clear();
  146. this->MemoryTesterOptions.clear();
  147. this->MemoryTesterStyle = UNKNOWN;
  148. this->MemoryTesterOutputFile = "";
  149. }
  150. //----------------------------------------------------------------------
  151. int cmCTestMemCheckHandler::PreProcessHandler()
  152. {
  153. if ( !this->InitializeMemoryChecking() )
  154. {
  155. return 0;
  156. }
  157. if ( !this->ExecuteCommands(this->CustomPreMemCheck) )
  158. {
  159. cmCTestLog(this->CTest, ERROR_MESSAGE,
  160. "Problem executing pre-memcheck command(s)." << std::endl);
  161. return 0;
  162. }
  163. return 1;
  164. }
  165. //----------------------------------------------------------------------
  166. int cmCTestMemCheckHandler::PostProcessHandler()
  167. {
  168. if ( !this->ExecuteCommands(this->CustomPostMemCheck) )
  169. {
  170. cmCTestLog(this->CTest, ERROR_MESSAGE,
  171. "Problem executing post-memcheck command(s)." << std::endl);
  172. return 0;
  173. }
  174. return 1;
  175. }
  176. //----------------------------------------------------------------------
  177. void cmCTestMemCheckHandler::GenerateTestCommand(
  178. std::vector<std::string>& args, int test)
  179. {
  180. std::vector<std::string>::size_type pp;
  181. std::string index;
  182. cmOStringStream stream;
  183. std::string memcheckcommand
  184. = cmSystemTools::ConvertToOutputPath(this->MemoryTester.c_str());
  185. stream << test;
  186. index = stream.str();
  187. for ( pp = 0; pp < this->MemoryTesterDynamicOptions.size(); pp ++ )
  188. {
  189. std::string arg = this->MemoryTesterDynamicOptions[pp];
  190. std::string::size_type pos = arg.find("??");
  191. if (pos != std::string::npos)
  192. {
  193. arg.replace(pos, 2, index);
  194. }
  195. args.push_back(arg);
  196. memcheckcommand += " \"";
  197. memcheckcommand += arg;
  198. memcheckcommand += "\"";
  199. }
  200. // Create a copy of the memory tester environment variable.
  201. // This is used for memory testing programs that pass options
  202. // via environment varaibles.
  203. std::string memTesterEnvironmentVariable =
  204. this->MemoryTesterEnvironmentVariable;
  205. for ( pp = 0; pp < this->MemoryTesterOptions.size(); pp ++ )
  206. {
  207. if(memTesterEnvironmentVariable.size())
  208. {
  209. // If we are using env to pass options, append all the options to
  210. // this string with space separation.
  211. memTesterEnvironmentVariable += " " + this->MemoryTesterOptions[pp];
  212. }
  213. // for regular options just add them to args and memcheckcommand
  214. // which is just used for display
  215. else
  216. {
  217. args.push_back(this->MemoryTesterOptions[pp]);
  218. memcheckcommand += " \"";
  219. memcheckcommand += this->MemoryTesterOptions[pp];
  220. memcheckcommand += "\"";
  221. }
  222. }
  223. // if this is an env option type, then add the env string as a single
  224. // argument.
  225. if(memTesterEnvironmentVariable.size())
  226. {
  227. std::string::size_type pos = memTesterEnvironmentVariable.find("??");
  228. if (pos != std::string::npos)
  229. {
  230. memTesterEnvironmentVariable.replace(pos, 2, index);
  231. }
  232. memcheckcommand += " " + memTesterEnvironmentVariable;
  233. args.push_back(memTesterEnvironmentVariable);
  234. }
  235. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Memory check command: "
  236. << memcheckcommand << std::endl);
  237. }
  238. //----------------------------------------------------------------------
  239. void cmCTestMemCheckHandler::InitializeResultsVectors()
  240. {
  241. // fill these members
  242. // cmsys::vector<std::string> ResultStrings;
  243. // cmsys::vector<std::string> ResultStringsLong;
  244. // cmsys::vector<int> GlobalResults;
  245. this->ResultStringsLong.clear();
  246. this->ResultStrings.clear();
  247. this->GlobalResults.clear();
  248. // If we are working with style checkers that dynamically fill
  249. // the results strings then return.
  250. if(this->MemoryTesterStyle > cmCTestMemCheckHandler::BOUNDS_CHECKER)
  251. {
  252. return;
  253. }
  254. // define the standard set of errors
  255. //----------------------------------------------------------------------
  256. static const char* cmCTestMemCheckResultStrings[] = {
  257. "ABR",
  258. "ABW",
  259. "ABWL",
  260. "COR",
  261. "EXU",
  262. "FFM",
  263. "FIM",
  264. "FMM",
  265. "FMR",
  266. "FMW",
  267. "FUM",
  268. "IPR",
  269. "IPW",
  270. "MAF",
  271. "MLK",
  272. "MPK",
  273. "NPR",
  274. "ODS",
  275. "PAR",
  276. "PLK",
  277. "UMC",
  278. "UMR",
  279. 0
  280. };
  281. //----------------------------------------------------------------------
  282. static const char* cmCTestMemCheckResultLongStrings[] = {
  283. "Threading Problem",
  284. "ABW",
  285. "ABWL",
  286. "COR",
  287. "EXU",
  288. "FFM",
  289. "FIM",
  290. "Mismatched deallocation",
  291. "FMR",
  292. "FMW",
  293. "FUM",
  294. "IPR",
  295. "IPW",
  296. "MAF",
  297. "Memory Leak",
  298. "Potential Memory Leak",
  299. "NPR",
  300. "ODS",
  301. "Invalid syscall param",
  302. "PLK",
  303. "Uninitialized Memory Conditional",
  304. "Uninitialized Memory Read",
  305. 0
  306. };
  307. this->GlobalResults.clear();
  308. for(int i =0; cmCTestMemCheckResultStrings[i] != 0; ++i)
  309. {
  310. this->ResultStrings.push_back(cmCTestMemCheckResultStrings[i]);
  311. this->ResultStringsLong.push_back(cmCTestMemCheckResultLongStrings[i]);
  312. this->GlobalResults.push_back(0);
  313. }
  314. }
  315. //----------------------------------------------------------------------
  316. void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile *mf)
  317. {
  318. this->cmCTestTestHandler::PopulateCustomVectors(mf);
  319. this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_PRE_MEMCHECK",
  320. this->CustomPreMemCheck);
  321. this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_POST_MEMCHECK",
  322. this->CustomPostMemCheck);
  323. this->CTest->PopulateCustomVector(mf,
  324. "CTEST_CUSTOM_MEMCHECK_IGNORE",
  325. this->CustomTestsIgnore);
  326. std::string cmake = cmSystemTools::GetCMakeCommand();
  327. this->CTest->SetCTestConfiguration("CMakeCommand", cmake.c_str());
  328. }
  329. //----------------------------------------------------------------------
  330. void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
  331. {
  332. if ( !this->CTest->GetProduceXML() )
  333. {
  334. return;
  335. }
  336. this->CTest->StartXML(os, this->AppendXML);
  337. os << "<DynamicAnalysis Checker=\"";
  338. switch ( this->MemoryTesterStyle )
  339. {
  340. case cmCTestMemCheckHandler::VALGRIND:
  341. os << "Valgrind";
  342. break;
  343. case cmCTestMemCheckHandler::PURIFY:
  344. os << "Purify";
  345. break;
  346. case cmCTestMemCheckHandler::BOUNDS_CHECKER:
  347. os << "BoundsChecker";
  348. break;
  349. case cmCTestMemCheckHandler::THREAD_SANITIZER:
  350. os << "ThreadSanitizer";
  351. break;
  352. case cmCTestMemCheckHandler::ADDRESS_SANITIZER:
  353. os << "AddressSanitizer";
  354. break;
  355. default:
  356. os << "Unknown";
  357. }
  358. os << "\">" << std::endl;
  359. os << "\t<StartDateTime>" << this->StartTest << "</StartDateTime>\n"
  360. << "\t<StartTestTime>" << this->StartTestTime << "</StartTestTime>\n"
  361. << "\t<TestList>\n";
  362. cmCTestMemCheckHandler::TestResultsVector::size_type cc;
  363. for ( cc = 0; cc < this->TestResults.size(); cc ++ )
  364. {
  365. cmCTestTestResult *result = &this->TestResults[cc];
  366. std::string testPath = result->Path + "/" + result->Name;
  367. os << "\t\t<Test>" << cmXMLSafe(
  368. this->CTest->GetShortPathToFile(testPath.c_str()))
  369. << "</Test>" << std::endl;
  370. }
  371. os << "\t</TestList>\n";
  372. cmCTestLog(this->CTest, HANDLER_OUTPUT,
  373. "-- Processing memory checking output: ");
  374. size_t total = this->TestResults.size();
  375. size_t step = total / 10;
  376. size_t current = 0;
  377. for ( cc = 0; cc < this->TestResults.size(); cc ++ )
  378. {
  379. cmCTestTestResult *result = &this->TestResults[cc];
  380. std::string memcheckstr;
  381. std::vector<int> memcheckresults(this->ResultStrings.size(), 0);
  382. bool res = this->ProcessMemCheckOutput(result->Output, memcheckstr,
  383. memcheckresults);
  384. if ( res && result->Status == cmCTestMemCheckHandler::COMPLETED )
  385. {
  386. continue;
  387. }
  388. this->CleanTestOutput(memcheckstr,
  389. static_cast<size_t>(this->CustomMaximumFailedTestOutputSize));
  390. this->WriteTestResultHeader(os, result);
  391. os << "\t\t<Results>" << std::endl;
  392. for(std::vector<int>::size_type kk = 0;
  393. kk < memcheckresults.size(); ++kk)
  394. {
  395. if ( memcheckresults[kk] )
  396. {
  397. os << "\t\t\t<Defect type=\"" << this->ResultStringsLong[kk]
  398. << "\">"
  399. << memcheckresults[kk]
  400. << "</Defect>" << std::endl;
  401. }
  402. this->GlobalResults[kk] += memcheckresults[kk];
  403. }
  404. std::string logTag;
  405. if(this->CTest->ShouldCompressMemCheckOutput())
  406. {
  407. this->CTest->CompressString(memcheckstr);
  408. logTag = "\t<Log compression=\"gzip\" encoding=\"base64\">\n";
  409. }
  410. else
  411. {
  412. logTag = "\t<Log>\n";
  413. }
  414. os
  415. << "\t\t</Results>\n"
  416. << logTag << cmXMLSafe(memcheckstr) << std::endl
  417. << "\t</Log>\n";
  418. this->WriteTestResultFooter(os, result);
  419. if ( current < cc )
  420. {
  421. cmCTestLog(this->CTest, HANDLER_OUTPUT, "#" << std::flush);
  422. current += step;
  423. }
  424. }
  425. cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
  426. cmCTestLog(this->CTest, HANDLER_OUTPUT, "Memory checking results:"
  427. << std::endl);
  428. os << "\t<DefectList>" << std::endl;
  429. for ( cc = 0; cc < this->GlobalResults.size(); cc ++ )
  430. {
  431. if ( this->GlobalResults[cc] )
  432. {
  433. #ifdef cerr
  434. # undef cerr
  435. #endif
  436. std::cerr.width(35);
  437. #define cerr no_cerr
  438. cmCTestLog(this->CTest, HANDLER_OUTPUT,
  439. this->ResultStringsLong[cc] << " - "
  440. << this->GlobalResults[cc] << std::endl);
  441. os << "\t\t<Defect Type=\"" << this->ResultStringsLong[cc]
  442. << "\"/>" << std::endl;
  443. }
  444. }
  445. os << "\t</DefectList>" << std::endl;
  446. os << "\t<EndDateTime>" << this->EndTest << "</EndDateTime>" << std::endl;
  447. os << "\t<EndTestTime>" << this->EndTestTime
  448. << "</EndTestTime>" << std::endl;
  449. os << "<ElapsedMinutes>"
  450. << static_cast<int>(this->ElapsedTestingTime/6)/10.0
  451. << "</ElapsedMinutes>\n";
  452. os << "</DynamicAnalysis>" << std::endl;
  453. this->CTest->EndXML(os);
  454. }
  455. //----------------------------------------------------------------------
  456. bool cmCTestMemCheckHandler::InitializeMemoryChecking()
  457. {
  458. this->MemoryTesterEnvironmentVariable = "";
  459. this->MemoryTester = "";
  460. // Setup the command
  461. if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
  462. "MemoryCheckCommand").c_str()) )
  463. {
  464. this->MemoryTester
  465. = this->CTest->GetCTestConfiguration("MemoryCheckCommand").c_str();
  466. std::string testerName =
  467. cmSystemTools::GetFilenameName(this->MemoryTester);
  468. // determine the checker type
  469. if ( testerName.find("valgrind") != std::string::npos ||
  470. this->CTest->GetCTestConfiguration("MemoryCheckType")
  471. == "Valgrind")
  472. {
  473. this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND;
  474. }
  475. else if ( testerName.find("purify") != std::string::npos )
  476. {
  477. this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY;
  478. }
  479. else if ( testerName.find("BC") != std::string::npos )
  480. {
  481. this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER;
  482. }
  483. else
  484. {
  485. this->MemoryTesterStyle = cmCTestMemCheckHandler::UNKNOWN;
  486. }
  487. }
  488. else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
  489. "PurifyCommand").c_str()) )
  490. {
  491. this->MemoryTester
  492. = this->CTest->GetCTestConfiguration("PurifyCommand").c_str();
  493. this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY;
  494. }
  495. else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
  496. "ValgrindCommand").c_str()) )
  497. {
  498. this->MemoryTester
  499. = this->CTest->GetCTestConfiguration("ValgrindCommand").c_str();
  500. this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND;
  501. }
  502. else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
  503. "BoundsCheckerCommand").c_str()) )
  504. {
  505. this->MemoryTester
  506. = this->CTest->GetCTestConfiguration("BoundsCheckerCommand").c_str();
  507. this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER;
  508. }
  509. if ( this->CTest->GetCTestConfiguration("MemoryCheckType")
  510. == "ThreadSanitizer")
  511. {
  512. this->MemoryTester
  513. = this->CTest->GetCTestConfiguration("CMakeCommand").c_str();
  514. this->MemoryTesterStyle = cmCTestMemCheckHandler::THREAD_SANITIZER;
  515. this->LogWithPID = true; // even if we give the log file the pid is added
  516. }
  517. if ( this->CTest->GetCTestConfiguration("MemoryCheckType")
  518. == "AddressSanitizer")
  519. {
  520. this->MemoryTester
  521. = this->CTest->GetCTestConfiguration("CMakeCommand").c_str();
  522. this->MemoryTesterStyle = cmCTestMemCheckHandler::ADDRESS_SANITIZER;
  523. this->LogWithPID = true; // even if we give the log file the pid is added
  524. }
  525. // Check the MemoryCheckType
  526. if(this->MemoryTesterStyle == cmCTestMemCheckHandler::UNKNOWN)
  527. {
  528. std::string checkType =
  529. this->CTest->GetCTestConfiguration("MemoryCheckType");
  530. if(checkType == "Purify")
  531. {
  532. this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY;
  533. }
  534. else if(checkType == "BoundsChecker")
  535. {
  536. this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER;
  537. }
  538. else if(checkType == "Valgrind")
  539. {
  540. this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND;
  541. }
  542. }
  543. if(this->MemoryTester.size() == 0 )
  544. {
  545. cmCTestLog(this->CTest, WARNING,
  546. "Memory checker (MemoryCheckCommand) "
  547. "not set, or cannot find the specified program."
  548. << std::endl);
  549. return false;
  550. }
  551. // Setup the options
  552. std::string memoryTesterOptions;
  553. if ( this->CTest->GetCTestConfiguration(
  554. "MemoryCheckCommandOptions").size() )
  555. {
  556. memoryTesterOptions = this->CTest->GetCTestConfiguration(
  557. "MemoryCheckCommandOptions");
  558. }
  559. else if ( this->CTest->GetCTestConfiguration(
  560. "ValgrindCommandOptions").size() )
  561. {
  562. memoryTesterOptions = this->CTest->GetCTestConfiguration(
  563. "ValgrindCommandOptions");
  564. }
  565. this->MemoryTesterOptions
  566. = cmSystemTools::ParseArguments(memoryTesterOptions.c_str());
  567. this->MemoryTesterOutputFile
  568. = this->CTest->GetBinaryDir()
  569. + "/Testing/Temporary/MemoryChecker.??.log";
  570. switch ( this->MemoryTesterStyle )
  571. {
  572. case cmCTestMemCheckHandler::VALGRIND:
  573. {
  574. if ( this->MemoryTesterOptions.empty() )
  575. {
  576. this->MemoryTesterOptions.push_back("-q");
  577. this->MemoryTesterOptions.push_back("--tool=memcheck");
  578. this->MemoryTesterOptions.push_back("--leak-check=yes");
  579. this->MemoryTesterOptions.push_back("--show-reachable=yes");
  580. this->MemoryTesterOptions.push_back("--num-callers=50");
  581. }
  582. if ( this->CTest->GetCTestConfiguration(
  583. "MemoryCheckSuppressionFile").size() )
  584. {
  585. if ( !cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
  586. "MemoryCheckSuppressionFile").c_str()) )
  587. {
  588. cmCTestLog(this->CTest, ERROR_MESSAGE,
  589. "Cannot find memory checker suppression file: "
  590. << this->CTest->GetCTestConfiguration(
  591. "MemoryCheckSuppressionFile") << std::endl);
  592. return false;
  593. }
  594. std::string suppressions = "--suppressions="
  595. + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile");
  596. this->MemoryTesterOptions.push_back(suppressions);
  597. }
  598. std::string outputFile = "--log-file="
  599. + this->MemoryTesterOutputFile;
  600. this->MemoryTesterDynamicOptions.push_back(outputFile);
  601. break;
  602. }
  603. case cmCTestMemCheckHandler::PURIFY:
  604. {
  605. std::string outputFile;
  606. #ifdef _WIN32
  607. if( this->CTest->GetCTestConfiguration(
  608. "MemoryCheckSuppressionFile").size() )
  609. {
  610. if( !cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
  611. "MemoryCheckSuppressionFile").c_str()) )
  612. {
  613. cmCTestLog(this->CTest, ERROR_MESSAGE,
  614. "Cannot find memory checker suppression file: "
  615. << this->CTest->GetCTestConfiguration(
  616. "MemoryCheckSuppressionFile").c_str() << std::endl);
  617. return false;
  618. }
  619. std::string filterFiles = "/FilterFiles="
  620. + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile");
  621. this->MemoryTesterOptions.push_back(filterFiles);
  622. }
  623. outputFile = "/SAVETEXTDATA=";
  624. #else
  625. outputFile = "-log-file=";
  626. #endif
  627. outputFile += this->MemoryTesterOutputFile;
  628. this->MemoryTesterDynamicOptions.push_back(outputFile);
  629. break;
  630. }
  631. case cmCTestMemCheckHandler::BOUNDS_CHECKER:
  632. {
  633. this->BoundsCheckerXMLFile = this->MemoryTesterOutputFile;
  634. std::string dpbdFile = this->CTest->GetBinaryDir()
  635. + "/Testing/Temporary/MemoryChecker.??.DPbd";
  636. this->BoundsCheckerDPBDFile = dpbdFile;
  637. this->MemoryTesterDynamicOptions.push_back("/B");
  638. this->MemoryTesterDynamicOptions.push_back(dpbdFile);
  639. this->MemoryTesterDynamicOptions.push_back("/X");
  640. this->MemoryTesterDynamicOptions.push_back(this->MemoryTesterOutputFile);
  641. this->MemoryTesterOptions.push_back("/M");
  642. break;
  643. }
  644. // these two are almost the same but the env var used
  645. // is different
  646. case cmCTestMemCheckHandler::ADDRESS_SANITIZER:
  647. case cmCTestMemCheckHandler::THREAD_SANITIZER:
  648. {
  649. // To pass arguments to ThreadSanitizer the environment variable
  650. // TSAN_OPTIONS is used. This is done with the cmake -E env command.
  651. // The MemoryTesterDynamicOptions is setup with the -E env
  652. // Then the MemoryTesterEnvironmentVariable gets the
  653. // TSAN_OPTIONS string with the log_path in it.
  654. this->MemoryTesterDynamicOptions.push_back("-E");
  655. this->MemoryTesterDynamicOptions.push_back("env");
  656. std::string envVar = "TSAN_OPTIONS";
  657. std::string extraOptions;
  658. if(this->MemoryTesterStyle == cmCTestMemCheckHandler::ADDRESS_SANITIZER)
  659. {
  660. envVar = "ASAN_OPTIONS";
  661. extraOptions = " detect_leaks=1";
  662. }
  663. std::string outputFile = envVar + "=log_path=\""
  664. + this->MemoryTesterOutputFile + "\"";
  665. this->MemoryTesterEnvironmentVariable = outputFile + extraOptions;
  666. break;
  667. }
  668. default:
  669. cmCTestLog(this->CTest, ERROR_MESSAGE,
  670. "Do not understand memory checker: " << this->MemoryTester
  671. << std::endl);
  672. return false;
  673. }
  674. this->InitializeResultsVectors();
  675. // std::vector<std::string>::size_type cc;
  676. // for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ )
  677. // {
  678. // this->MemoryTesterGlobalResults[cc] = 0;
  679. // }
  680. return true;
  681. }
  682. //----------------------------------------------------------------------
  683. bool cmCTestMemCheckHandler::
  684. ProcessMemCheckOutput(const std::string& str,
  685. std::string& log, std::vector<int>& results)
  686. {
  687. if ( this->MemoryTesterStyle == cmCTestMemCheckHandler::VALGRIND )
  688. {
  689. return this->ProcessMemCheckValgrindOutput(str, log, results);
  690. }
  691. else if ( this->MemoryTesterStyle == cmCTestMemCheckHandler::PURIFY )
  692. {
  693. return this->ProcessMemCheckPurifyOutput(str, log, results);
  694. }
  695. else if ( this->MemoryTesterStyle ==
  696. cmCTestMemCheckHandler::THREAD_SANITIZER ||
  697. this->MemoryTesterStyle ==
  698. cmCTestMemCheckHandler::ADDRESS_SANITIZER)
  699. {
  700. return this->ProcessMemCheckSanitizerOutput(str, log, results);
  701. }
  702. else if ( this->MemoryTesterStyle ==
  703. cmCTestMemCheckHandler::BOUNDS_CHECKER )
  704. {
  705. return this->ProcessMemCheckBoundsCheckerOutput(str, log, results);
  706. }
  707. else
  708. {
  709. log.append("\nMemory checking style used was: ");
  710. log.append("None that I know");
  711. log = str;
  712. }
  713. return true;
  714. }
  715. std::vector<int>::size_type cmCTestMemCheckHandler::FindOrAddWarning(
  716. const std::string& warning)
  717. {
  718. for(std::vector<std::string>::size_type i =0;
  719. i < this->ResultStrings.size(); ++i)
  720. {
  721. if(this->ResultStrings[i] == warning)
  722. {
  723. return i;
  724. }
  725. }
  726. this->GlobalResults.push_back(0); // this must stay the same size
  727. this->ResultStrings.push_back(warning);
  728. this->ResultStringsLong.push_back(warning);
  729. return this->ResultStrings.size()-1;
  730. }
  731. //----------------------------------------------------------------------
  732. bool cmCTestMemCheckHandler::ProcessMemCheckSanitizerOutput(
  733. const std::string& str, std::string& log,
  734. std::vector<int>& result)
  735. {
  736. std::string regex;
  737. if(this->MemoryTesterStyle == cmCTestMemCheckHandler::THREAD_SANITIZER)
  738. {
  739. regex = "WARNING: ThreadSanitizer: (.*) \\(pid=.*\\)";
  740. }
  741. else
  742. {
  743. regex = "ERROR: AddressSanitizer: (.*) on.*";
  744. }
  745. cmsys::RegularExpression sanitizerWarning(regex);
  746. cmsys::RegularExpression leakWarning("(Direct|Indirect) leak of .*");
  747. int defects = 0;
  748. std::vector<std::string> lines;
  749. cmSystemTools::Split(str.c_str(), lines);
  750. cmOStringStream ostr;
  751. log = "";
  752. for( std::vector<std::string>::iterator i = lines.begin();
  753. i != lines.end(); ++i)
  754. {
  755. std::string resultFound;
  756. if(leakWarning.find(*i))
  757. {
  758. resultFound = leakWarning.match(1)+" leak";
  759. }
  760. else if (sanitizerWarning.find(*i))
  761. {
  762. resultFound = sanitizerWarning.match(1);
  763. }
  764. if(resultFound.size())
  765. {
  766. std::vector<int>::size_type idx = this->FindOrAddWarning(resultFound);
  767. if(result.size() == 0 || idx > result.size()-1)
  768. {
  769. result.push_back(1);
  770. }
  771. else
  772. {
  773. result[idx]++;
  774. }
  775. defects++;
  776. ostr << "<b>" << this->ResultStrings[idx] << "</b> ";
  777. }
  778. ostr << cmXMLSafe(*i) << std::endl;
  779. }
  780. log = ostr.str();
  781. if(defects)
  782. {
  783. return false;
  784. }
  785. return true;
  786. }
  787. //----------------------------------------------------------------------
  788. bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput(
  789. const std::string& str, std::string& log,
  790. std::vector<int>& results)
  791. {
  792. std::vector<std::string> lines;
  793. cmSystemTools::Split(str.c_str(), lines);
  794. cmOStringStream ostr;
  795. log = "";
  796. cmsys::RegularExpression pfW("^\\[[WEI]\\] ([A-Z][A-Z][A-Z][A-Z]*): ");
  797. int defects = 0;
  798. for( std::vector<std::string>::iterator i = lines.begin();
  799. i != lines.end(); ++i)
  800. {
  801. std::vector<int>::size_type failure = this->ResultStrings.size();
  802. if ( pfW.find(*i) )
  803. {
  804. std::vector<int>::size_type cc;
  805. for ( cc = 0; cc < this->ResultStrings.size(); cc ++ )
  806. {
  807. if ( pfW.match(1) == this->ResultStrings[cc] )
  808. {
  809. failure = cc;
  810. break;
  811. }
  812. }
  813. if ( cc == this->ResultStrings.size() )
  814. {
  815. cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown Purify memory fault: "
  816. << pfW.match(1) << std::endl);
  817. ostr << "*** Unknown Purify memory fault: " << pfW.match(1)
  818. << std::endl;
  819. }
  820. }
  821. if ( failure != this->ResultStrings.size() )
  822. {
  823. ostr << "<b>" << this->ResultStrings[failure] << "</b> ";
  824. results[failure] ++;
  825. defects ++;
  826. }
  827. ostr << cmXMLSafe(*i) << std::endl;
  828. }
  829. log = ostr.str();
  830. if ( defects )
  831. {
  832. return false;
  833. }
  834. return true;
  835. }
  836. //----------------------------------------------------------------------
  837. bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
  838. const std::string& str, std::string& log,
  839. std::vector<int>& results)
  840. {
  841. std::vector<std::string> lines;
  842. cmSystemTools::Split(str.c_str(), lines);
  843. bool unlimitedOutput = false;
  844. if(str.find("CTEST_FULL_OUTPUT") != str.npos ||
  845. this->CustomMaximumFailedTestOutputSize == 0)
  846. {
  847. unlimitedOutput = true;
  848. }
  849. std::string::size_type cc;
  850. cmOStringStream ostr;
  851. log = "";
  852. int defects = 0;
  853. cmsys::RegularExpression valgrindLine("^==[0-9][0-9]*==");
  854. cmsys::RegularExpression vgFIM(
  855. "== .*Invalid free\\(\\) / delete / delete\\[\\]");
  856. cmsys::RegularExpression vgFMM(
  857. "== .*Mismatched free\\(\\) / delete / delete \\[\\]");
  858. cmsys::RegularExpression vgMLK1(
  859. "== .*[0-9,]+ bytes in [0-9,]+ blocks are definitely lost"
  860. " in loss record [0-9,]+ of [0-9,]+");
  861. cmsys::RegularExpression vgMLK2(
  862. "== .*[0-9,]+ \\([0-9,]+ direct, [0-9,]+ indirect\\)"
  863. " bytes in [0-9,]+ blocks are definitely lost"
  864. " in loss record [0-9,]+ of [0-9,]+");
  865. cmsys::RegularExpression vgPAR(
  866. "== .*Syscall param .* (contains|points to) unaddressable byte\\(s\\)");
  867. cmsys::RegularExpression vgMPK1(
  868. "== .*[0-9,]+ bytes in [0-9,]+ blocks are possibly lost in"
  869. " loss record [0-9,]+ of [0-9,]+");
  870. cmsys::RegularExpression vgMPK2(
  871. "== .*[0-9,]+ bytes in [0-9,]+ blocks are still reachable"
  872. " in loss record [0-9,]+ of [0-9,]+");
  873. cmsys::RegularExpression vgUMC(
  874. "== .*Conditional jump or move depends on uninitialised value\\(s\\)");
  875. cmsys::RegularExpression vgUMR1(
  876. "== .*Use of uninitialised value of size [0-9,]+");
  877. cmsys::RegularExpression vgUMR2("== .*Invalid read of size [0-9,]+");
  878. cmsys::RegularExpression vgUMR3("== .*Jump to the invalid address ");
  879. cmsys::RegularExpression vgUMR4("== .*Syscall param .* contains "
  880. "uninitialised or unaddressable byte\\(s\\)");
  881. cmsys::RegularExpression vgUMR5("== .*Syscall param .* uninitialised");
  882. cmsys::RegularExpression vgIPW("== .*Invalid write of size [0-9,]+");
  883. cmsys::RegularExpression vgABR("== .*pthread_mutex_unlock: mutex is "
  884. "locked by a different thread");
  885. std::vector<std::string::size_type> nonValGrindOutput;
  886. double sttime = cmSystemTools::GetTime();
  887. cmCTestLog(this->CTest, DEBUG, "Start test: " << lines.size() << std::endl);
  888. std::string::size_type totalOutputSize = 0;
  889. for ( cc = 0; cc < lines.size(); cc ++ )
  890. {
  891. cmCTestLog(this->CTest, DEBUG, "test line "
  892. << lines[cc] << std::endl);
  893. if ( valgrindLine.find(lines[cc]) )
  894. {
  895. cmCTestLog(this->CTest, DEBUG, "valgrind line "
  896. << lines[cc] << std::endl);
  897. int failure = cmCTestMemCheckHandler::NO_MEMORY_FAULT;
  898. if ( vgFIM.find(lines[cc]) )
  899. {
  900. failure = cmCTestMemCheckHandler::FIM;
  901. }
  902. else if ( vgFMM.find(lines[cc]) )
  903. {
  904. failure = cmCTestMemCheckHandler::FMM;
  905. }
  906. else if ( vgMLK1.find(lines[cc]) )
  907. {
  908. failure = cmCTestMemCheckHandler::MLK;
  909. }
  910. else if ( vgMLK2.find(lines[cc]) )
  911. {
  912. failure = cmCTestMemCheckHandler::MLK;
  913. }
  914. else if ( vgPAR.find(lines[cc]) )
  915. {
  916. failure = cmCTestMemCheckHandler::PAR;
  917. }
  918. else if ( vgMPK1.find(lines[cc]) )
  919. {
  920. failure = cmCTestMemCheckHandler::MPK;
  921. }
  922. else if ( vgMPK2.find(lines[cc]) )
  923. {
  924. failure = cmCTestMemCheckHandler::MPK;
  925. }
  926. else if ( vgUMC.find(lines[cc]) )
  927. {
  928. failure = cmCTestMemCheckHandler::UMC;
  929. }
  930. else if ( vgUMR1.find(lines[cc]) )
  931. {
  932. failure = cmCTestMemCheckHandler::UMR;
  933. }
  934. else if ( vgUMR2.find(lines[cc]) )
  935. {
  936. failure = cmCTestMemCheckHandler::UMR;
  937. }
  938. else if ( vgUMR3.find(lines[cc]) )
  939. {
  940. failure = cmCTestMemCheckHandler::UMR;
  941. }
  942. else if ( vgUMR4.find(lines[cc]) )
  943. {
  944. failure = cmCTestMemCheckHandler::UMR;
  945. }
  946. else if ( vgUMR5.find(lines[cc]) )
  947. {
  948. failure = cmCTestMemCheckHandler::UMR;
  949. }
  950. else if ( vgIPW.find(lines[cc]) )
  951. {
  952. failure = cmCTestMemCheckHandler::IPW;
  953. }
  954. else if ( vgABR.find(lines[cc]) )
  955. {
  956. failure = cmCTestMemCheckHandler::ABR;
  957. }
  958. if ( failure != cmCTestMemCheckHandler::NO_MEMORY_FAULT )
  959. {
  960. ostr << "<b>" << this->ResultStrings[failure] << "</b> ";
  961. results[failure] ++;
  962. defects ++;
  963. }
  964. totalOutputSize += lines[cc].size();
  965. ostr << cmXMLSafe(lines[cc]) << std::endl;
  966. }
  967. else
  968. {
  969. nonValGrindOutput.push_back(cc);
  970. }
  971. }
  972. // Now put all all the non valgrind output into the test output
  973. // This should be last in case it gets truncated by the output
  974. // limiting code
  975. for(std::vector<std::string::size_type>::iterator i =
  976. nonValGrindOutput.begin(); i != nonValGrindOutput.end(); ++i)
  977. {
  978. totalOutputSize += lines[*i].size();
  979. cmCTestLog(this->CTest, DEBUG, "before xml safe "
  980. << lines[*i] << std::endl);
  981. cmCTestLog(this->CTest, DEBUG, "after xml safe "
  982. << cmXMLSafe(lines[*i]) << std::endl);
  983. ostr << cmXMLSafe(lines[*i]) << std::endl;
  984. if(!unlimitedOutput && totalOutputSize >
  985. static_cast<size_t>(this->CustomMaximumFailedTestOutputSize))
  986. {
  987. ostr << "....\n";
  988. ostr << "Test Output for this test has been truncated see testing"
  989. " machine logs for full output,\n";
  990. ostr << "or put CTEST_FULL_OUTPUT in the output of "
  991. "this test program.\n";
  992. break; // stop the copy of output if we are full
  993. }
  994. }
  995. cmCTestLog(this->CTest, DEBUG, "End test (elapsed: "
  996. << (cmSystemTools::GetTime() - sttime) << std::endl);
  997. log = ostr.str();
  998. if ( defects )
  999. {
  1000. return false;
  1001. }
  1002. return true;
  1003. }
  1004. //----------------------------------------------------------------------
  1005. bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
  1006. const std::string& str, std::string& log,
  1007. std::vector<int>& results)
  1008. {
  1009. log = "";
  1010. double sttime = cmSystemTools::GetTime();
  1011. std::vector<std::string> lines;
  1012. cmSystemTools::Split(str.c_str(), lines);
  1013. cmCTestLog(this->CTest, DEBUG, "Start test: " << lines.size() << std::endl);
  1014. std::vector<std::string>::size_type cc;
  1015. for ( cc = 0; cc < lines.size(); cc ++ )
  1016. {
  1017. if(lines[cc] == BOUNDS_CHECKER_MARKER)
  1018. {
  1019. break;
  1020. }
  1021. }
  1022. cmBoundsCheckerParser parser(this->CTest);
  1023. parser.InitializeParser();
  1024. if(cc < lines.size())
  1025. {
  1026. for(cc++; cc < lines.size(); ++cc)
  1027. {
  1028. std::string& theLine = lines[cc];
  1029. // check for command line arguments that are not escaped
  1030. // correctly by BC
  1031. if(theLine.find("TargetArgs=") != theLine.npos)
  1032. {
  1033. // skip this because BC gets it wrong and we can't parse it
  1034. }
  1035. else if(!parser.ParseChunk(theLine.c_str(), theLine.size()))
  1036. {
  1037. cmCTestLog(this->CTest, ERROR_MESSAGE,
  1038. "Error in ParseChunk: " << theLine
  1039. << std::endl);
  1040. }
  1041. }
  1042. }
  1043. int defects = 0;
  1044. for(cc =0; cc < parser.Errors.size(); ++cc)
  1045. {
  1046. results[parser.Errors[cc]]++;
  1047. defects++;
  1048. }
  1049. cmCTestLog(this->CTest, DEBUG, "End test (elapsed: "
  1050. << (cmSystemTools::GetTime() - sttime) << std::endl);
  1051. if(defects)
  1052. {
  1053. // only put the output of Bounds Checker if there were
  1054. // errors or leaks detected
  1055. log = parser.Log;
  1056. return false;
  1057. }
  1058. return true;
  1059. }
  1060. // PostProcessTest memcheck results
  1061. void
  1062. cmCTestMemCheckHandler::PostProcessTest(cmCTestTestResult& res,
  1063. int test)
  1064. {
  1065. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
  1066. "PostProcessTest memcheck results for : "
  1067. << res.Name << std::endl);
  1068. if(this->MemoryTesterStyle
  1069. == cmCTestMemCheckHandler::BOUNDS_CHECKER)
  1070. {
  1071. this->PostProcessBoundsCheckerTest(res, test);
  1072. }
  1073. else
  1074. {
  1075. std::vector<std::string> files;
  1076. this->TestOutputFileNames(test, files);
  1077. for(std::vector<std::string>::iterator i = files.begin();
  1078. i != files.end(); ++i)
  1079. {
  1080. this->AppendMemTesterOutput(res, *i);
  1081. }
  1082. }
  1083. }
  1084. // This method puts the bounds checker output file into the output
  1085. // for the test
  1086. void
  1087. cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res,
  1088. int test)
  1089. {
  1090. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
  1091. "PostProcessBoundsCheckerTest for : "
  1092. << res.Name << std::endl);
  1093. std::vector<std::string> files;
  1094. this->TestOutputFileNames(test, files);
  1095. if ( files.size() == 0 )
  1096. {
  1097. return;
  1098. }
  1099. std::string ofile = files[0];
  1100. // put a scope around this to close ifs so the file can be removed
  1101. {
  1102. cmsys::ifstream ifs(ofile.c_str());
  1103. if ( !ifs )
  1104. {
  1105. std::string log = "Cannot read memory tester output file: " + ofile;
  1106. cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
  1107. return;
  1108. }
  1109. res.Output += BOUNDS_CHECKER_MARKER;
  1110. res.Output += "\n";
  1111. std::string line;
  1112. while ( cmSystemTools::GetLineFromStream(ifs, line) )
  1113. {
  1114. res.Output += line;
  1115. res.Output += "\n";
  1116. }
  1117. }
  1118. cmSystemTools::Delay(1000);
  1119. cmSystemTools::RemoveFile(this->BoundsCheckerDPBDFile.c_str());
  1120. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Remove: "
  1121. << this->BoundsCheckerDPBDFile << std::endl);
  1122. cmSystemTools::RemoveFile(this->BoundsCheckerXMLFile.c_str());
  1123. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Remove: "
  1124. << this->BoundsCheckerXMLFile << std::endl);
  1125. }
  1126. void
  1127. cmCTestMemCheckHandler::AppendMemTesterOutput(cmCTestTestResult& res,
  1128. std::string const& ofile)
  1129. {
  1130. if ( ofile.empty() )
  1131. {
  1132. return;
  1133. }
  1134. // put ifs in scope so file can be deleted if needed
  1135. {
  1136. cmsys::ifstream ifs(ofile.c_str());
  1137. if ( !ifs )
  1138. {
  1139. std::string log = "Cannot read memory tester output file: " + ofile;
  1140. cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
  1141. return;
  1142. }
  1143. std::string line;
  1144. while ( cmSystemTools::GetLineFromStream(ifs, line) )
  1145. {
  1146. res.Output += line;
  1147. res.Output += "\n";
  1148. }
  1149. }
  1150. if(this->LogWithPID)
  1151. {
  1152. cmSystemTools::RemoveFile(ofile.c_str());
  1153. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Remove: "<< ofile <<"\n");
  1154. }
  1155. }
  1156. void cmCTestMemCheckHandler::TestOutputFileNames(int test,
  1157. std::vector<std::string>&
  1158. files)
  1159. {
  1160. std::string index;
  1161. cmOStringStream stream;
  1162. stream << test;
  1163. index = stream.str();
  1164. std::string ofile = this->MemoryTesterOutputFile;
  1165. std::string::size_type pos = ofile.find("??");
  1166. ofile.replace(pos, 2, index);
  1167. if(this->LogWithPID)
  1168. {
  1169. ofile += ".*";
  1170. cmsys::Glob g;
  1171. g.FindFiles(ofile);
  1172. if(g.GetFiles().size() == 0)
  1173. {
  1174. std::string log = "Cannot find memory tester output file: "
  1175. + ofile;
  1176. cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
  1177. ofile = "";
  1178. }
  1179. else
  1180. {
  1181. files = g.GetFiles();
  1182. return;
  1183. }
  1184. }
  1185. else if ( !cmSystemTools::FileExists(ofile.c_str()) )
  1186. {
  1187. std::string log = "Cannot find memory tester output file: "
  1188. + ofile;
  1189. cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
  1190. ofile = "";
  1191. }
  1192. files.push_back(ofile);
  1193. }