cmCTestMemCheckHandler.cxx 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017
  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/FStream.hxx>
  19. #include "cmMakefile.h"
  20. #include "cmXMLSafe.h"
  21. #include <stdlib.h>
  22. #include <math.h>
  23. #include <float.h>
  24. struct CatToErrorType
  25. {
  26. const char* ErrorCategory;
  27. int ErrorCode;
  28. };
  29. static CatToErrorType cmCTestMemCheckBoundsChecker[] = {
  30. // Error tags
  31. {"Write Overrun", cmCTestMemCheckHandler::ABW},
  32. {"Read Overrun", cmCTestMemCheckHandler::ABR},
  33. {"Memory Overrun", cmCTestMemCheckHandler::ABW},
  34. {"Allocation Conflict", cmCTestMemCheckHandler::FMM},
  35. {"Bad Pointer Use", cmCTestMemCheckHandler::FMW},
  36. {"Dangling Pointer", cmCTestMemCheckHandler::FMR},
  37. {0,0}
  38. };
  39. // parse the xml file containing the results of last BoundsChecker run
  40. class cmBoundsCheckerParser : public cmXMLParser
  41. {
  42. public:
  43. cmBoundsCheckerParser(cmCTest* c) { this->CTest = c;}
  44. void StartElement(const std::string& name, const char** atts)
  45. {
  46. if(name == "MemoryLeak" ||
  47. name == "ResourceLeak")
  48. {
  49. this->Errors.push_back(cmCTestMemCheckHandler::MLK);
  50. }
  51. else if(name == "Error" ||
  52. name == "Dangling Pointer")
  53. {
  54. this->ParseError(atts);
  55. }
  56. // Create the log
  57. cmOStringStream ostr;
  58. ostr << name << ":\n";
  59. int i = 0;
  60. for(; atts[i] != 0; i+=2)
  61. {
  62. ostr << " " << cmXMLSafe(atts[i])
  63. << " - " << cmXMLSafe(atts[i+1]) << "\n";
  64. }
  65. ostr << "\n";
  66. this->Log += ostr.str();
  67. }
  68. void EndElement(const std::string& )
  69. {
  70. }
  71. const char* GetAttribute(const char* name, const char** atts)
  72. {
  73. int i = 0;
  74. for(; atts[i] != 0; ++i)
  75. {
  76. if(strcmp(name, atts[i]) == 0)
  77. {
  78. return atts[i+1];
  79. }
  80. }
  81. return 0;
  82. }
  83. void ParseError(const char** atts)
  84. {
  85. CatToErrorType* ptr = cmCTestMemCheckBoundsChecker;
  86. const char* cat = this->GetAttribute("ErrorCategory", atts);
  87. if(!cat)
  88. {
  89. this->Errors.push_back(cmCTestMemCheckHandler::ABW); // do not know
  90. cmCTestLog(this->CTest, ERROR_MESSAGE,
  91. "No Category found in Bounds checker XML\n" );
  92. return;
  93. }
  94. while(ptr->ErrorCategory && cat)
  95. {
  96. if(strcmp(ptr->ErrorCategory, cat) == 0)
  97. {
  98. this->Errors.push_back(ptr->ErrorCode);
  99. return; // found it we are done
  100. }
  101. ptr++;
  102. }
  103. if(ptr->ErrorCategory)
  104. {
  105. this->Errors.push_back(cmCTestMemCheckHandler::ABW); // do not know
  106. cmCTestLog(this->CTest, ERROR_MESSAGE,
  107. "Found unknown Bounds Checker error "
  108. << ptr->ErrorCategory << std::endl);
  109. }
  110. }
  111. cmCTest* CTest;
  112. std::vector<int> Errors;
  113. std::string Log;
  114. };
  115. #define BOUNDS_CHECKER_MARKER \
  116. "******######*****Begin BOUNDS CHECKER XML******######******"
  117. //----------------------------------------------------------------------
  118. static const char* cmCTestMemCheckResultStrings[] = {
  119. "ABR",
  120. "ABW",
  121. "ABWL",
  122. "COR",
  123. "EXU",
  124. "FFM",
  125. "FIM",
  126. "FMM",
  127. "FMR",
  128. "FMW",
  129. "FUM",
  130. "IPR",
  131. "IPW",
  132. "MAF",
  133. "MLK",
  134. "MPK",
  135. "NPR",
  136. "ODS",
  137. "PAR",
  138. "PLK",
  139. "UMC",
  140. "UMR",
  141. 0
  142. };
  143. //----------------------------------------------------------------------
  144. static const char* cmCTestMemCheckResultLongStrings[] = {
  145. "Threading Problem",
  146. "ABW",
  147. "ABWL",
  148. "COR",
  149. "EXU",
  150. "FFM",
  151. "FIM",
  152. "Mismatched deallocation",
  153. "FMR",
  154. "FMW",
  155. "FUM",
  156. "IPR",
  157. "IPW",
  158. "MAF",
  159. "Memory Leak",
  160. "Potential Memory Leak",
  161. "NPR",
  162. "ODS",
  163. "Invalid syscall param",
  164. "PLK",
  165. "Uninitialized Memory Conditional",
  166. "Uninitialized Memory Read",
  167. 0
  168. };
  169. //----------------------------------------------------------------------
  170. cmCTestMemCheckHandler::cmCTestMemCheckHandler()
  171. {
  172. this->MemCheck = true;
  173. this->CustomMaximumPassedTestOutputSize = 0;
  174. this->CustomMaximumFailedTestOutputSize = 0;
  175. }
  176. //----------------------------------------------------------------------
  177. void cmCTestMemCheckHandler::Initialize()
  178. {
  179. this->Superclass::Initialize();
  180. this->CustomMaximumPassedTestOutputSize = 0;
  181. this->CustomMaximumFailedTestOutputSize = 0;
  182. this->MemoryTester = "";
  183. this->MemoryTesterDynamicOptions.clear();
  184. this->MemoryTesterOptions.clear();
  185. this->MemoryTesterStyle = UNKNOWN;
  186. this->MemoryTesterOutputFile = "";
  187. int cc;
  188. for ( cc = 0; cc < NO_MEMORY_FAULT; cc ++ )
  189. {
  190. this->MemoryTesterGlobalResults[cc] = 0;
  191. }
  192. }
  193. //----------------------------------------------------------------------
  194. int cmCTestMemCheckHandler::PreProcessHandler()
  195. {
  196. if ( !this->InitializeMemoryChecking() )
  197. {
  198. return 0;
  199. }
  200. if ( !this->ExecuteCommands(this->CustomPreMemCheck) )
  201. {
  202. cmCTestLog(this->CTest, ERROR_MESSAGE,
  203. "Problem executing pre-memcheck command(s)." << std::endl);
  204. return 0;
  205. }
  206. return 1;
  207. }
  208. //----------------------------------------------------------------------
  209. int cmCTestMemCheckHandler::PostProcessHandler()
  210. {
  211. if ( !this->ExecuteCommands(this->CustomPostMemCheck) )
  212. {
  213. cmCTestLog(this->CTest, ERROR_MESSAGE,
  214. "Problem executing post-memcheck command(s)." << std::endl);
  215. return 0;
  216. }
  217. return 1;
  218. }
  219. //----------------------------------------------------------------------
  220. void cmCTestMemCheckHandler::GenerateTestCommand(
  221. std::vector<std::string>& args, int test)
  222. {
  223. std::vector<std::string>::size_type pp;
  224. std::string index;
  225. cmOStringStream stream;
  226. std::string memcheckcommand
  227. = cmSystemTools::ConvertToOutputPath(this->MemoryTester.c_str());
  228. stream << test;
  229. index = stream.str();
  230. for ( pp = 0; pp < this->MemoryTesterDynamicOptions.size(); pp ++ )
  231. {
  232. std::string arg = this->MemoryTesterDynamicOptions[pp];
  233. std::string::size_type pos = arg.find("??");
  234. if (pos != std::string::npos)
  235. {
  236. arg.replace(pos, 2, index);
  237. }
  238. args.push_back(arg);
  239. memcheckcommand += " \"";
  240. memcheckcommand += arg;
  241. memcheckcommand += "\"";
  242. }
  243. for ( pp = 0; pp < this->MemoryTesterOptions.size(); pp ++ )
  244. {
  245. args.push_back(this->MemoryTesterOptions[pp]);
  246. memcheckcommand += " \"";
  247. memcheckcommand += this->MemoryTesterOptions[pp];
  248. memcheckcommand += "\"";
  249. }
  250. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Memory check command: "
  251. << memcheckcommand << std::endl);
  252. }
  253. //----------------------------------------------------------------------
  254. void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile *mf)
  255. {
  256. this->cmCTestTestHandler::PopulateCustomVectors(mf);
  257. this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_PRE_MEMCHECK",
  258. this->CustomPreMemCheck);
  259. this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_POST_MEMCHECK",
  260. this->CustomPostMemCheck);
  261. this->CTest->PopulateCustomVector(mf,
  262. "CTEST_CUSTOM_MEMCHECK_IGNORE",
  263. this->CustomTestsIgnore);
  264. }
  265. //----------------------------------------------------------------------
  266. void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
  267. {
  268. if ( !this->CTest->GetProduceXML() )
  269. {
  270. return;
  271. }
  272. this->CTest->StartXML(os, this->AppendXML);
  273. os << "<DynamicAnalysis Checker=\"";
  274. switch ( this->MemoryTesterStyle )
  275. {
  276. case cmCTestMemCheckHandler::VALGRIND:
  277. os << "Valgrind";
  278. break;
  279. case cmCTestMemCheckHandler::PURIFY:
  280. os << "Purify";
  281. break;
  282. case cmCTestMemCheckHandler::BOUNDS_CHECKER:
  283. os << "BoundsChecker";
  284. break;
  285. default:
  286. os << "Unknown";
  287. }
  288. os << "\">" << std::endl;
  289. os << "\t<StartDateTime>" << this->StartTest << "</StartDateTime>\n"
  290. << "\t<StartTestTime>" << this->StartTestTime << "</StartTestTime>\n"
  291. << "\t<TestList>\n";
  292. cmCTestMemCheckHandler::TestResultsVector::size_type cc;
  293. for ( cc = 0; cc < this->TestResults.size(); cc ++ )
  294. {
  295. cmCTestTestResult *result = &this->TestResults[cc];
  296. std::string testPath = result->Path + "/" + result->Name;
  297. os << "\t\t<Test>" << cmXMLSafe(
  298. this->CTest->GetShortPathToFile(testPath.c_str()))
  299. << "</Test>" << std::endl;
  300. }
  301. os << "\t</TestList>\n";
  302. cmCTestLog(this->CTest, HANDLER_OUTPUT,
  303. "-- Processing memory checking output: ");
  304. size_t total = this->TestResults.size();
  305. size_t step = total / 10;
  306. size_t current = 0;
  307. for ( cc = 0; cc < this->TestResults.size(); cc ++ )
  308. {
  309. cmCTestTestResult *result = &this->TestResults[cc];
  310. std::string memcheckstr;
  311. int memcheckresults[cmCTestMemCheckHandler::NO_MEMORY_FAULT];
  312. int kk;
  313. bool res = this->ProcessMemCheckOutput(result->Output, memcheckstr,
  314. memcheckresults);
  315. if ( res && result->Status == cmCTestMemCheckHandler::COMPLETED )
  316. {
  317. continue;
  318. }
  319. this->CleanTestOutput(memcheckstr,
  320. static_cast<size_t>(this->CustomMaximumFailedTestOutputSize));
  321. this->WriteTestResultHeader(os, result);
  322. os << "\t\t<Results>" << std::endl;
  323. for ( kk = 0; cmCTestMemCheckResultLongStrings[kk]; kk ++ )
  324. {
  325. if ( memcheckresults[kk] )
  326. {
  327. os << "\t\t\t<Defect type=\"" << cmCTestMemCheckResultLongStrings[kk]
  328. << "\">"
  329. << memcheckresults[kk]
  330. << "</Defect>" << std::endl;
  331. }
  332. this->MemoryTesterGlobalResults[kk] += memcheckresults[kk];
  333. }
  334. std::string logTag;
  335. if(this->CTest->ShouldCompressMemCheckOutput())
  336. {
  337. this->CTest->CompressString(memcheckstr);
  338. logTag = "\t<Log compression=\"gzip\" encoding=\"base64\">\n";
  339. }
  340. else
  341. {
  342. logTag = "\t<Log>\n";
  343. }
  344. os
  345. << "\t\t</Results>\n"
  346. << logTag << cmXMLSafe(memcheckstr) << std::endl
  347. << "\t</Log>\n";
  348. this->WriteTestResultFooter(os, result);
  349. if ( current < cc )
  350. {
  351. cmCTestLog(this->CTest, HANDLER_OUTPUT, "#" << std::flush);
  352. current += step;
  353. }
  354. }
  355. cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
  356. cmCTestLog(this->CTest, HANDLER_OUTPUT, "Memory checking results:"
  357. << std::endl);
  358. os << "\t<DefectList>" << std::endl;
  359. for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ )
  360. {
  361. if ( this->MemoryTesterGlobalResults[cc] )
  362. {
  363. #ifdef cerr
  364. # undef cerr
  365. #endif
  366. std::cerr.width(35);
  367. #define cerr no_cerr
  368. cmCTestLog(this->CTest, HANDLER_OUTPUT,
  369. cmCTestMemCheckResultLongStrings[cc] << " - "
  370. << this->MemoryTesterGlobalResults[cc] << std::endl);
  371. os << "\t\t<Defect Type=\"" << cmCTestMemCheckResultLongStrings[cc]
  372. << "\"/>" << std::endl;
  373. }
  374. }
  375. os << "\t</DefectList>" << std::endl;
  376. os << "\t<EndDateTime>" << this->EndTest << "</EndDateTime>" << std::endl;
  377. os << "\t<EndTestTime>" << this->EndTestTime
  378. << "</EndTestTime>" << std::endl;
  379. os << "<ElapsedMinutes>"
  380. << static_cast<int>(this->ElapsedTestingTime/6)/10.0
  381. << "</ElapsedMinutes>\n";
  382. os << "</DynamicAnalysis>" << std::endl;
  383. this->CTest->EndXML(os);
  384. }
  385. //----------------------------------------------------------------------
  386. bool cmCTestMemCheckHandler::InitializeMemoryChecking()
  387. {
  388. // Setup the command
  389. if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
  390. "MemoryCheckCommand").c_str()) )
  391. {
  392. this->MemoryTester
  393. = this->CTest->GetCTestConfiguration("MemoryCheckCommand").c_str();
  394. // determine the checker type
  395. if ( this->MemoryTester.find("valgrind") != std::string::npos )
  396. {
  397. this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND;
  398. }
  399. else if ( this->MemoryTester.find("purify") != std::string::npos )
  400. {
  401. this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY;
  402. }
  403. else if ( this->MemoryTester.find("BC") != std::string::npos )
  404. {
  405. this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER;
  406. }
  407. else
  408. {
  409. this->MemoryTesterStyle = cmCTestMemCheckHandler::UNKNOWN;
  410. }
  411. }
  412. else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
  413. "PurifyCommand").c_str()) )
  414. {
  415. this->MemoryTester
  416. = this->CTest->GetCTestConfiguration("PurifyCommand").c_str();
  417. this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY;
  418. }
  419. else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
  420. "ValgrindCommand").c_str()) )
  421. {
  422. this->MemoryTester
  423. = this->CTest->GetCTestConfiguration("ValgrindCommand").c_str();
  424. this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND;
  425. }
  426. else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
  427. "BoundsCheckerCommand").c_str()) )
  428. {
  429. this->MemoryTester
  430. = this->CTest->GetCTestConfiguration("BoundsCheckerCommand").c_str();
  431. this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER;
  432. }
  433. else
  434. {
  435. cmCTestLog(this->CTest, WARNING,
  436. "Memory checker (MemoryCheckCommand) "
  437. "not set, or cannot find the specified program."
  438. << std::endl);
  439. return false;
  440. }
  441. // Setup the options
  442. std::string memoryTesterOptions;
  443. if ( this->CTest->GetCTestConfiguration(
  444. "MemoryCheckCommandOptions").size() )
  445. {
  446. memoryTesterOptions = this->CTest->GetCTestConfiguration(
  447. "MemoryCheckCommandOptions");
  448. }
  449. else if ( this->CTest->GetCTestConfiguration(
  450. "ValgrindCommandOptions").size() )
  451. {
  452. memoryTesterOptions = this->CTest->GetCTestConfiguration(
  453. "ValgrindCommandOptions");
  454. }
  455. this->MemoryTesterOptions
  456. = cmSystemTools::ParseArguments(memoryTesterOptions.c_str());
  457. this->MemoryTesterOutputFile
  458. = this->CTest->GetBinaryDir()
  459. + "/Testing/Temporary/MemoryChecker.??.log";
  460. switch ( this->MemoryTesterStyle )
  461. {
  462. case cmCTestMemCheckHandler::VALGRIND:
  463. {
  464. if ( this->MemoryTesterOptions.empty() )
  465. {
  466. this->MemoryTesterOptions.push_back("-q");
  467. this->MemoryTesterOptions.push_back("--tool=memcheck");
  468. this->MemoryTesterOptions.push_back("--leak-check=yes");
  469. this->MemoryTesterOptions.push_back("--show-reachable=yes");
  470. this->MemoryTesterOptions.push_back("--num-callers=50");
  471. }
  472. if ( this->CTest->GetCTestConfiguration(
  473. "MemoryCheckSuppressionFile").size() )
  474. {
  475. if ( !cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
  476. "MemoryCheckSuppressionFile").c_str()) )
  477. {
  478. cmCTestLog(this->CTest, ERROR_MESSAGE,
  479. "Cannot find memory checker suppression file: "
  480. << this->CTest->GetCTestConfiguration(
  481. "MemoryCheckSuppressionFile") << std::endl);
  482. return false;
  483. }
  484. std::string suppressions = "--suppressions="
  485. + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile");
  486. this->MemoryTesterOptions.push_back(suppressions);
  487. }
  488. std::string outputFile = "--log-file="
  489. + this->MemoryTesterOutputFile;
  490. this->MemoryTesterDynamicOptions.push_back(outputFile);
  491. break;
  492. }
  493. case cmCTestMemCheckHandler::PURIFY:
  494. {
  495. std::string outputFile;
  496. #ifdef _WIN32
  497. if( this->CTest->GetCTestConfiguration(
  498. "MemoryCheckSuppressionFile").size() )
  499. {
  500. if( !cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
  501. "MemoryCheckSuppressionFile").c_str()) )
  502. {
  503. cmCTestLog(this->CTest, ERROR_MESSAGE,
  504. "Cannot find memory checker suppression file: "
  505. << this->CTest->GetCTestConfiguration(
  506. "MemoryCheckSuppressionFile").c_str() << std::endl);
  507. return false;
  508. }
  509. std::string filterFiles = "/FilterFiles="
  510. + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile");
  511. this->MemoryTesterOptions.push_back(filterFiles);
  512. }
  513. outputFile = "/SAVETEXTDATA=";
  514. #else
  515. outputFile = "-log-file=";
  516. #endif
  517. outputFile += this->MemoryTesterOutputFile;
  518. this->MemoryTesterDynamicOptions.push_back(outputFile);
  519. break;
  520. }
  521. case cmCTestMemCheckHandler::BOUNDS_CHECKER:
  522. {
  523. this->BoundsCheckerXMLFile = this->MemoryTesterOutputFile;
  524. std::string dpbdFile = this->CTest->GetBinaryDir()
  525. + "/Testing/Temporary/MemoryChecker.??.DPbd";
  526. this->BoundsCheckerDPBDFile = dpbdFile;
  527. this->MemoryTesterDynamicOptions.push_back("/B");
  528. this->MemoryTesterDynamicOptions.push_back(dpbdFile);
  529. this->MemoryTesterDynamicOptions.push_back("/X");
  530. this->MemoryTesterDynamicOptions.push_back(this->MemoryTesterOutputFile);
  531. this->MemoryTesterOptions.push_back("/M");
  532. break;
  533. }
  534. default:
  535. cmCTestLog(this->CTest, ERROR_MESSAGE,
  536. "Do not understand memory checker: " << this->MemoryTester
  537. << std::endl);
  538. return false;
  539. }
  540. std::vector<std::string>::size_type cc;
  541. for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ )
  542. {
  543. this->MemoryTesterGlobalResults[cc] = 0;
  544. }
  545. return true;
  546. }
  547. //----------------------------------------------------------------------
  548. bool cmCTestMemCheckHandler::ProcessMemCheckOutput(const std::string& str,
  549. std::string& log, int* results)
  550. {
  551. std::string::size_type cc;
  552. for ( cc = 0; cc < cmCTestMemCheckHandler::NO_MEMORY_FAULT; cc ++ )
  553. {
  554. results[cc] = 0;
  555. }
  556. if ( this->MemoryTesterStyle == cmCTestMemCheckHandler::VALGRIND )
  557. {
  558. return this->ProcessMemCheckValgrindOutput(str, log, results);
  559. }
  560. else if ( this->MemoryTesterStyle == cmCTestMemCheckHandler::PURIFY )
  561. {
  562. return this->ProcessMemCheckPurifyOutput(str, log, results);
  563. }
  564. else if ( this->MemoryTesterStyle ==
  565. cmCTestMemCheckHandler::BOUNDS_CHECKER )
  566. {
  567. return this->ProcessMemCheckBoundsCheckerOutput(str, log, results);
  568. }
  569. else
  570. {
  571. log.append("\nMemory checking style used was: ");
  572. log.append("None that I know");
  573. log = str;
  574. }
  575. return true;
  576. }
  577. //----------------------------------------------------------------------
  578. bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput(
  579. const std::string& str, std::string& log,
  580. int* results)
  581. {
  582. std::vector<std::string> lines;
  583. cmSystemTools::Split(str.c_str(), lines);
  584. cmOStringStream ostr;
  585. log = "";
  586. cmsys::RegularExpression pfW("^\\[[WEI]\\] ([A-Z][A-Z][A-Z][A-Z]*): ");
  587. int defects = 0;
  588. for( std::vector<std::string>::iterator i = lines.begin();
  589. i != lines.end(); ++i)
  590. {
  591. int failure = cmCTestMemCheckHandler::NO_MEMORY_FAULT;
  592. if ( pfW.find(*i) )
  593. {
  594. int cc;
  595. for ( cc = 0; cc < cmCTestMemCheckHandler::NO_MEMORY_FAULT; cc ++ )
  596. {
  597. if ( pfW.match(1) == cmCTestMemCheckResultStrings[cc] )
  598. {
  599. failure = cc;
  600. break;
  601. }
  602. }
  603. if ( cc == cmCTestMemCheckHandler::NO_MEMORY_FAULT )
  604. {
  605. cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown Purify memory fault: "
  606. << pfW.match(1) << std::endl);
  607. ostr << "*** Unknown Purify memory fault: " << pfW.match(1)
  608. << std::endl;
  609. }
  610. }
  611. if ( failure != NO_MEMORY_FAULT )
  612. {
  613. ostr << "<b>" << cmCTestMemCheckResultStrings[failure] << "</b> ";
  614. results[failure] ++;
  615. defects ++;
  616. }
  617. ostr << cmXMLSafe(*i) << std::endl;
  618. }
  619. log = ostr.str();
  620. if ( defects )
  621. {
  622. return false;
  623. }
  624. return true;
  625. }
  626. //----------------------------------------------------------------------
  627. bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
  628. const std::string& str, std::string& log,
  629. int* results)
  630. {
  631. std::vector<std::string> lines;
  632. cmSystemTools::Split(str.c_str(), lines);
  633. bool unlimitedOutput = false;
  634. if(str.find("CTEST_FULL_OUTPUT") != str.npos ||
  635. this->CustomMaximumFailedTestOutputSize == 0)
  636. {
  637. unlimitedOutput = true;
  638. }
  639. std::string::size_type cc;
  640. cmOStringStream ostr;
  641. log = "";
  642. int defects = 0;
  643. cmsys::RegularExpression valgrindLine("^==[0-9][0-9]*==");
  644. cmsys::RegularExpression vgFIM(
  645. "== .*Invalid free\\(\\) / delete / delete\\[\\]");
  646. cmsys::RegularExpression vgFMM(
  647. "== .*Mismatched free\\(\\) / delete / delete \\[\\]");
  648. cmsys::RegularExpression vgMLK1(
  649. "== .*[0-9,]+ bytes in [0-9,]+ blocks are definitely lost"
  650. " in loss record [0-9,]+ of [0-9,]+");
  651. cmsys::RegularExpression vgMLK2(
  652. "== .*[0-9,]+ \\([0-9,]+ direct, [0-9,]+ indirect\\)"
  653. " bytes in [0-9,]+ blocks are definitely lost"
  654. " in loss record [0-9,]+ of [0-9,]+");
  655. cmsys::RegularExpression vgPAR(
  656. "== .*Syscall param .* (contains|points to) unaddressable byte\\(s\\)");
  657. cmsys::RegularExpression vgMPK1(
  658. "== .*[0-9,]+ bytes in [0-9,]+ blocks are possibly lost in"
  659. " loss record [0-9,]+ of [0-9,]+");
  660. cmsys::RegularExpression vgMPK2(
  661. "== .*[0-9,]+ bytes in [0-9,]+ blocks are still reachable"
  662. " in loss record [0-9,]+ of [0-9,]+");
  663. cmsys::RegularExpression vgUMC(
  664. "== .*Conditional jump or move depends on uninitialised value\\(s\\)");
  665. cmsys::RegularExpression vgUMR1(
  666. "== .*Use of uninitialised value of size [0-9,]+");
  667. cmsys::RegularExpression vgUMR2("== .*Invalid read of size [0-9,]+");
  668. cmsys::RegularExpression vgUMR3("== .*Jump to the invalid address ");
  669. cmsys::RegularExpression vgUMR4("== .*Syscall param .* contains "
  670. "uninitialised or unaddressable byte\\(s\\)");
  671. cmsys::RegularExpression vgUMR5("== .*Syscall param .* uninitialised");
  672. cmsys::RegularExpression vgIPW("== .*Invalid write of size [0-9,]+");
  673. cmsys::RegularExpression vgABR("== .*pthread_mutex_unlock: mutex is "
  674. "locked by a different thread");
  675. std::vector<std::string::size_type> nonValGrindOutput;
  676. double sttime = cmSystemTools::GetTime();
  677. cmCTestLog(this->CTest, DEBUG, "Start test: " << lines.size() << std::endl);
  678. std::string::size_type totalOutputSize = 0;
  679. bool outputFull = false;
  680. for ( cc = 0; cc < lines.size(); cc ++ )
  681. {
  682. cmCTestLog(this->CTest, DEBUG, "test line "
  683. << lines[cc] << std::endl);
  684. if ( valgrindLine.find(lines[cc]) )
  685. {
  686. cmCTestLog(this->CTest, DEBUG, "valgrind line "
  687. << lines[cc] << std::endl);
  688. int failure = cmCTestMemCheckHandler::NO_MEMORY_FAULT;
  689. if ( vgFIM.find(lines[cc]) )
  690. {
  691. failure = cmCTestMemCheckHandler::FIM;
  692. }
  693. else if ( vgFMM.find(lines[cc]) )
  694. {
  695. failure = cmCTestMemCheckHandler::FMM;
  696. }
  697. else if ( vgMLK1.find(lines[cc]) )
  698. {
  699. failure = cmCTestMemCheckHandler::MLK;
  700. }
  701. else if ( vgMLK2.find(lines[cc]) )
  702. {
  703. failure = cmCTestMemCheckHandler::MLK;
  704. }
  705. else if ( vgPAR.find(lines[cc]) )
  706. {
  707. failure = cmCTestMemCheckHandler::PAR;
  708. }
  709. else if ( vgMPK1.find(lines[cc]) )
  710. {
  711. failure = cmCTestMemCheckHandler::MPK;
  712. }
  713. else if ( vgMPK2.find(lines[cc]) )
  714. {
  715. failure = cmCTestMemCheckHandler::MPK;
  716. }
  717. else if ( vgUMC.find(lines[cc]) )
  718. {
  719. failure = cmCTestMemCheckHandler::UMC;
  720. }
  721. else if ( vgUMR1.find(lines[cc]) )
  722. {
  723. failure = cmCTestMemCheckHandler::UMR;
  724. }
  725. else if ( vgUMR2.find(lines[cc]) )
  726. {
  727. failure = cmCTestMemCheckHandler::UMR;
  728. }
  729. else if ( vgUMR3.find(lines[cc]) )
  730. {
  731. failure = cmCTestMemCheckHandler::UMR;
  732. }
  733. else if ( vgUMR4.find(lines[cc]) )
  734. {
  735. failure = cmCTestMemCheckHandler::UMR;
  736. }
  737. else if ( vgUMR5.find(lines[cc]) )
  738. {
  739. failure = cmCTestMemCheckHandler::UMR;
  740. }
  741. else if ( vgIPW.find(lines[cc]) )
  742. {
  743. failure = cmCTestMemCheckHandler::IPW;
  744. }
  745. else if ( vgABR.find(lines[cc]) )
  746. {
  747. failure = cmCTestMemCheckHandler::ABR;
  748. }
  749. if ( failure != cmCTestMemCheckHandler::NO_MEMORY_FAULT )
  750. {
  751. ostr << "<b>" << cmCTestMemCheckResultStrings[failure] << "</b> ";
  752. results[failure] ++;
  753. defects ++;
  754. }
  755. totalOutputSize += lines[cc].size();
  756. ostr << cmXMLSafe(lines[cc]) << std::endl;
  757. }
  758. else
  759. {
  760. nonValGrindOutput.push_back(cc);
  761. }
  762. }
  763. // Now put all all the non valgrind output into the test output
  764. if(!outputFull)
  765. {
  766. for(std::vector<std::string::size_type>::iterator i =
  767. nonValGrindOutput.begin(); i != nonValGrindOutput.end(); ++i)
  768. {
  769. totalOutputSize += lines[*i].size();
  770. cmCTestLog(this->CTest, DEBUG, "before xml safe "
  771. << lines[*i] << std::endl);
  772. cmCTestLog(this->CTest, DEBUG, "after xml safe "
  773. << cmXMLSafe(lines[*i]) << std::endl);
  774. ostr << cmXMLSafe(lines[*i]) << std::endl;
  775. if(!unlimitedOutput && totalOutputSize >
  776. static_cast<size_t>(this->CustomMaximumFailedTestOutputSize))
  777. {
  778. outputFull = true;
  779. ostr << "....\n";
  780. ostr << "Test Output for this test has been truncated see testing"
  781. " machine logs for full output,\n";
  782. ostr << "or put CTEST_FULL_OUTPUT in the output of "
  783. "this test program.\n";
  784. }
  785. }
  786. }
  787. cmCTestLog(this->CTest, DEBUG, "End test (elapsed: "
  788. << (cmSystemTools::GetTime() - sttime) << std::endl);
  789. log = ostr.str();
  790. if ( defects )
  791. {
  792. return false;
  793. }
  794. return true;
  795. }
  796. //----------------------------------------------------------------------
  797. bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
  798. const std::string& str, std::string& log,
  799. int* results)
  800. {
  801. log = "";
  802. double sttime = cmSystemTools::GetTime();
  803. std::vector<std::string> lines;
  804. cmSystemTools::Split(str.c_str(), lines);
  805. cmCTestLog(this->CTest, DEBUG, "Start test: " << lines.size() << std::endl);
  806. std::vector<std::string>::size_type cc;
  807. for ( cc = 0; cc < lines.size(); cc ++ )
  808. {
  809. if(lines[cc] == BOUNDS_CHECKER_MARKER)
  810. {
  811. break;
  812. }
  813. }
  814. cmBoundsCheckerParser parser(this->CTest);
  815. parser.InitializeParser();
  816. if(cc < lines.size())
  817. {
  818. for(cc++; cc < lines.size(); ++cc)
  819. {
  820. std::string& theLine = lines[cc];
  821. // check for command line arguments that are not escaped
  822. // correctly by BC
  823. if(theLine.find("TargetArgs=") != theLine.npos)
  824. {
  825. // skip this because BC gets it wrong and we can't parse it
  826. }
  827. else if(!parser.ParseChunk(theLine.c_str(), theLine.size()))
  828. {
  829. cmCTestLog(this->CTest, ERROR_MESSAGE,
  830. "Error in ParseChunk: " << theLine
  831. << std::endl);
  832. }
  833. }
  834. }
  835. int defects = 0;
  836. for(cc =0; cc < parser.Errors.size(); ++cc)
  837. {
  838. results[parser.Errors[cc]]++;
  839. defects++;
  840. }
  841. cmCTestLog(this->CTest, DEBUG, "End test (elapsed: "
  842. << (cmSystemTools::GetTime() - sttime) << std::endl);
  843. if(defects)
  844. {
  845. // only put the output of Bounds Checker if there were
  846. // errors or leaks detected
  847. log = parser.Log;
  848. return false;
  849. }
  850. return true;
  851. }
  852. // This method puts the bounds checker output file into the output
  853. // for the test
  854. void
  855. cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res,
  856. int test)
  857. {
  858. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
  859. "PostProcessBoundsCheckerTest for : "
  860. << res.Name << std::endl);
  861. std::string ofile = testOutputFileName(test);
  862. if ( ofile.empty() )
  863. {
  864. return;
  865. }
  866. // put a scope around this to close ifs so the file can be removed
  867. {
  868. cmsys::ifstream ifs(ofile.c_str());
  869. if ( !ifs )
  870. {
  871. std::string log = "Cannot read memory tester output file: " + ofile;
  872. cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
  873. return;
  874. }
  875. res.Output += BOUNDS_CHECKER_MARKER;
  876. res.Output += "\n";
  877. std::string line;
  878. while ( cmSystemTools::GetLineFromStream(ifs, line) )
  879. {
  880. res.Output += line;
  881. res.Output += "\n";
  882. }
  883. }
  884. cmSystemTools::Delay(1000);
  885. cmSystemTools::RemoveFile(this->BoundsCheckerDPBDFile.c_str());
  886. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Remove: "
  887. << this->BoundsCheckerDPBDFile << std::endl);
  888. cmSystemTools::RemoveFile(this->BoundsCheckerXMLFile.c_str());
  889. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Remove: "
  890. << this->BoundsCheckerXMLFile << std::endl);
  891. }
  892. void
  893. cmCTestMemCheckHandler::PostProcessPurifyTest(cmCTestTestResult& res,
  894. int test)
  895. {
  896. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
  897. "PostProcessPurifyTest for : "
  898. << res.Name << std::endl);
  899. appendMemTesterOutput(res, test);
  900. }
  901. void
  902. cmCTestMemCheckHandler::PostProcessValgrindTest(cmCTestTestResult& res,
  903. int test)
  904. {
  905. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
  906. "PostProcessValgrindTest for : "
  907. << res.Name << std::endl);
  908. appendMemTesterOutput(res, test);
  909. }
  910. void
  911. cmCTestMemCheckHandler::appendMemTesterOutput(cmCTestTestResult& res,
  912. int test)
  913. {
  914. std::string ofile = testOutputFileName(test);
  915. if ( ofile.empty() )
  916. {
  917. return;
  918. }
  919. cmsys::ifstream ifs(ofile.c_str());
  920. if ( !ifs )
  921. {
  922. std::string log = "Cannot read memory tester output file: " + ofile;
  923. cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
  924. return;
  925. }
  926. std::string line;
  927. while ( cmSystemTools::GetLineFromStream(ifs, line) )
  928. {
  929. res.Output += line;
  930. res.Output += "\n";
  931. }
  932. }
  933. std::string
  934. cmCTestMemCheckHandler::testOutputFileName(int test)
  935. {
  936. std::string index;
  937. cmOStringStream stream;
  938. stream << test;
  939. index = stream.str();
  940. std::string ofile = this->MemoryTesterOutputFile;
  941. std::string::size_type pos = ofile.find("??");
  942. ofile.replace(pos, 2, index);
  943. if ( !cmSystemTools::FileExists(ofile.c_str()) )
  944. {
  945. std::string log = "Cannot find memory tester output file: "
  946. + ofile;
  947. cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
  948. ofile = "";
  949. }
  950. return ofile;
  951. }