cmCTestMemCheckHandler.cxx 29 KB

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