ENH: put the 64 bit paths first
[cmake.git] / Source / CTest / cmCTestMemCheckHandler.cxx
blobf369ac6b6ed46413db607e7d9c7be54c7692babc
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCTestMemCheckHandler.cxx,v $
5 Language: C++
6 Date: $Date: 2009-05-27 15:14:08 $
7 Version: $Revision: 1.23 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
18 #include "cmCTestMemCheckHandler.h"
19 #include "cmXMLParser.h"
20 #include "cmCTest.h"
21 #include "cmake.h"
22 #include "cmGeneratedFileStream.h"
23 #include <cmsys/Process.h>
24 #include <cmsys/RegularExpression.hxx>
25 #include <cmsys/Base64.h>
26 #include "cmMakefile.h"
27 #include "cmXMLSafe.h"
29 #include <stdlib.h>
30 #include <math.h>
31 #include <float.h>
33 struct CatToErrorType
35 const char* ErrorCategory;
36 int ErrorCode;
40 static CatToErrorType cmCTestMemCheckBoundsChecker[] = {
41 // Error tags
42 {"Write Overrun", cmCTestMemCheckHandler::ABW},
43 {"Read Overrun", cmCTestMemCheckHandler::ABR},
44 {"Memory Overrun", cmCTestMemCheckHandler::ABW},
45 {"Allocation Conflict", cmCTestMemCheckHandler::FMM},
46 {"Bad Pointer Use", cmCTestMemCheckHandler::FMW},
47 {"Dangling Pointer", cmCTestMemCheckHandler::FMR},
48 {0,0}
51 // parse the xml file storing the installed version of Xcode on
52 // the machine
53 class cmBoundsCheckerParser : public cmXMLParser
55 public:
56 cmBoundsCheckerParser(cmCTest* c) { this->CTest = c;}
57 void StartElement(const char* name, const char** atts)
59 if(strcmp(name, "MemoryLeak") == 0)
61 this->Errors.push_back(cmCTestMemCheckHandler::MLK);
63 if(strcmp(name, "ResourceLeak") == 0)
65 this->Errors.push_back(cmCTestMemCheckHandler::MLK);
67 if(strcmp(name, "Error") == 0)
69 this->ParseError(atts);
71 if(strcmp(name, "Dangling Pointer") == 0)
73 this->ParseError(atts);
75 // Create the log
76 cmOStringStream ostr;
77 ostr << name << ":\n";
78 int i = 0;
79 for(; atts[i] != 0; i+=2)
81 ostr << " " << cmXMLSafe(atts[i])
82 << " - " << cmXMLSafe(atts[i+1]) << "\n";
84 ostr << "\n";
85 this->Log += ostr.str();
87 void EndElement(const char* )
91 const char* GetAttribute(const char* name, const char** atts)
93 int i = 0;
94 for(; atts[i] != 0; ++i)
96 if(strcmp(name, atts[i]) == 0)
98 return atts[i+1];
101 return 0;
103 void ParseError(const char** atts)
105 CatToErrorType* ptr = cmCTestMemCheckBoundsChecker;
106 const char* cat = this->GetAttribute("ErrorCategory", atts);
107 if(!cat)
109 this->Errors.push_back(cmCTestMemCheckHandler::ABW); // do not know
110 cmCTestLog(this->CTest, ERROR_MESSAGE,
111 "No Category found in Bounds checker XML\n" );
112 return;
114 while(ptr->ErrorCategory && cat)
116 if(strcmp(ptr->ErrorCategory, cat) == 0)
118 this->Errors.push_back(ptr->ErrorCode);
119 return; // found it we are done
121 ptr++;
123 if(ptr->ErrorCategory)
125 this->Errors.push_back(cmCTestMemCheckHandler::ABW); // do not know
126 cmCTestLog(this->CTest, ERROR_MESSAGE,
127 "Found unknown Bounds Checker error "
128 << ptr->ErrorCategory << std::endl);
131 cmCTest* CTest;
132 std::vector<int> Errors;
133 std::string Log;
136 #define BOUNDS_CHECKER_MARKER \
137 "******######*****Begin BOUNDS CHECKER XML******######******"
138 //----------------------------------------------------------------------
139 static const char* cmCTestMemCheckResultStrings[] = {
140 "ABR",
141 "ABW",
142 "ABWL",
143 "COR",
144 "EXU",
145 "FFM",
146 "FIM",
147 "FMM",
148 "FMR",
149 "FMW",
150 "FUM",
151 "IPR",
152 "IPW",
153 "MAF",
154 "MLK",
155 "MPK",
156 "NPR",
157 "ODS",
158 "PAR",
159 "PLK",
160 "UMC",
161 "UMR",
166 //----------------------------------------------------------------------
167 static const char* cmCTestMemCheckResultLongStrings[] = {
168 "Threading Problem",
169 "ABW",
170 "ABWL",
171 "COR",
172 "EXU",
173 "FFM",
174 "FIM",
175 "Mismatched deallocation",
176 "FMR",
177 "FMW",
178 "FUM",
179 "IPR",
180 "IPW",
181 "MAF",
182 "Memory Leak",
183 "Potential Memory Leak",
184 "NPR",
185 "ODS",
186 "Invalid syscall param",
187 "PLK",
188 "Uninitialized Memory Conditional",
189 "Uninitialized Memory Read",
194 //----------------------------------------------------------------------
195 cmCTestMemCheckHandler::cmCTestMemCheckHandler()
197 this->MemCheck = true;
198 this->CustomMaximumPassedTestOutputSize = 0;
199 this->CustomMaximumFailedTestOutputSize = 0;
202 //----------------------------------------------------------------------
203 void cmCTestMemCheckHandler::Initialize()
205 this->Superclass::Initialize();
206 this->CustomMaximumPassedTestOutputSize = 0;
207 this->CustomMaximumFailedTestOutputSize = 0;
208 this->MemoryTester = "";
209 this->MemoryTesterOptionsParsed.clear();
210 this->MemoryTesterOptions = "";
211 this->MemoryTesterStyle = UNKNOWN;
212 this->MemoryTesterOutputFile = "";
213 int cc;
214 for ( cc = 0; cc < NO_MEMORY_FAULT; cc ++ )
216 this->MemoryTesterGlobalResults[cc] = 0;
221 //----------------------------------------------------------------------
222 int cmCTestMemCheckHandler::PreProcessHandler()
224 if ( !this->InitializeMemoryChecking() )
226 return 0;
229 if ( !this->ExecuteCommands(this->CustomPreMemCheck) )
231 cmCTestLog(this->CTest, ERROR_MESSAGE,
232 "Problem executing pre-memcheck command(s)." << std::endl);
233 return 0;
235 return 1;
238 //----------------------------------------------------------------------
239 int cmCTestMemCheckHandler::PostProcessHandler()
241 if ( !this->ExecuteCommands(this->CustomPostMemCheck) )
243 cmCTestLog(this->CTest, ERROR_MESSAGE,
244 "Problem executing post-memcheck command(s)." << std::endl);
245 return 0;
247 return 1;
250 //----------------------------------------------------------------------
251 void cmCTestMemCheckHandler::GenerateTestCommand(
252 std::vector<const char*>& args)
254 std::vector<cmStdString>::size_type pp;
255 args.push_back(this->MemoryTester.c_str());
256 std::string memcheckcommand = "";
257 memcheckcommand = this->MemoryTester;
258 for ( pp = 0; pp < this->MemoryTesterOptionsParsed.size(); pp ++ )
260 args.push_back(this->MemoryTesterOptionsParsed[pp].c_str());
261 memcheckcommand += " ";
262 memcheckcommand += cmSystemTools::EscapeSpaces(
263 this->MemoryTesterOptionsParsed[pp].c_str());
265 cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Memory check command: "
266 << memcheckcommand << std::endl);
269 //----------------------------------------------------------------------
270 void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile *mf)
272 this->cmCTestTestHandler::PopulateCustomVectors(mf);
273 this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_PRE_MEMCHECK",
274 this->CustomPreMemCheck);
275 this->CTest->PopulateCustomVector(mf, "CTEST_CUSTOM_POST_MEMCHECK",
276 this->CustomPostMemCheck);
278 this->CTest->PopulateCustomVector(mf,
279 "CTEST_CUSTOM_MEMCHECK_IGNORE",
280 this->CustomTestsIgnore);
283 //----------------------------------------------------------------------
284 void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
286 if ( !this->CTest->GetProduceXML() )
288 return;
291 this->CTest->StartXML(os, this->AppendXML);
292 os << "<DynamicAnalysis Checker=\"";
293 switch ( this->MemoryTesterStyle )
295 case cmCTestMemCheckHandler::VALGRIND:
296 os << "Valgrind";
297 break;
298 case cmCTestMemCheckHandler::PURIFY:
299 os << "Purify";
300 break;
301 case cmCTestMemCheckHandler::BOUNDS_CHECKER:
302 os << "BoundsChecker";
303 break;
304 default:
305 os << "Unknown";
307 os << "\">" << std::endl;
309 os << "\t<StartDateTime>" << this->StartTest << "</StartDateTime>\n"
310 << "\t<StartTestTime>" << this->StartTestTime << "</StartTestTime>\n"
311 << "\t<TestList>\n";
312 cmCTestMemCheckHandler::TestResultsVector::size_type cc;
313 for ( cc = 0; cc < this->TestResults.size(); cc ++ )
315 cmCTestTestResult *result = &this->TestResults[cc];
316 std::string testPath = result->Path + "/" + result->Name;
317 os << "\t\t<Test>" << cmXMLSafe(
318 this->CTest->GetShortPathToFile(testPath.c_str()))
319 << "</Test>" << std::endl;
321 os << "\t</TestList>\n";
322 cmCTestLog(this->CTest, HANDLER_OUTPUT,
323 "-- Processing memory checking output: ");
324 size_t total = this->TestResults.size();
325 size_t step = total / 10;
326 size_t current = 0;
327 for ( cc = 0; cc < this->TestResults.size(); cc ++ )
329 cmCTestTestResult *result = &this->TestResults[cc];
330 std::string memcheckstr;
331 int memcheckresults[cmCTestMemCheckHandler::NO_MEMORY_FAULT];
332 int kk;
333 bool res = this->ProcessMemCheckOutput(result->Output, memcheckstr,
334 memcheckresults);
335 if ( res && result->Status == cmCTestMemCheckHandler::COMPLETED )
337 continue;
339 this->CleanTestOutput(memcheckstr,
340 static_cast<size_t>(this->CustomMaximumFailedTestOutputSize));
341 this->WriteTestResultHeader(os, result);
342 os << "\t\t<Results>" << std::endl;
343 for ( kk = 0; cmCTestMemCheckResultLongStrings[kk]; kk ++ )
345 if ( memcheckresults[kk] )
347 os << "\t\t\t<Defect type=\"" << cmCTestMemCheckResultLongStrings[kk]
348 << "\">"
349 << memcheckresults[kk]
350 << "</Defect>" << std::endl;
352 this->MemoryTesterGlobalResults[kk] += memcheckresults[kk];
355 << "\t\t</Results>\n"
356 << "\t<Log>\n" << memcheckstr << std::endl
357 << "\t</Log>\n";
358 this->WriteTestResultFooter(os, result);
359 if ( current < cc )
361 cmCTestLog(this->CTest, HANDLER_OUTPUT, "#" << std::flush);
362 current += step;
365 cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
366 cmCTestLog(this->CTest, HANDLER_OUTPUT, "Memory checking results:"
367 << std::endl);
368 os << "\t<DefectList>" << std::endl;
369 for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ )
371 if ( this->MemoryTesterGlobalResults[cc] )
373 #ifdef cerr
374 # undef cerr
375 #endif
376 std::cerr.width(35);
377 #define cerr no_cerr
378 cmCTestLog(this->CTest, HANDLER_OUTPUT,
379 cmCTestMemCheckResultLongStrings[cc] << " - "
380 << this->MemoryTesterGlobalResults[cc] << std::endl);
381 os << "\t\t<Defect Type=\"" << cmCTestMemCheckResultLongStrings[cc]
382 << "\"/>" << std::endl;
385 os << "\t</DefectList>" << std::endl;
387 os << "\t<EndDateTime>" << this->EndTest << "</EndDateTime>" << std::endl;
388 os << "\t<EndTestTime>" << this->EndTestTime
389 << "</EndTestTime>" << std::endl;
390 os << "<ElapsedMinutes>"
391 << static_cast<int>(this->ElapsedTestingTime/6)/10.0
392 << "</ElapsedMinutes>\n";
394 os << "</DynamicAnalysis>" << std::endl;
395 this->CTest->EndXML(os);
400 //----------------------------------------------------------------------
401 bool cmCTestMemCheckHandler::InitializeMemoryChecking()
403 // Setup the command
404 if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
405 "MemoryCheckCommand").c_str()) )
407 this->MemoryTester
408 = cmSystemTools::ConvertToOutputPath(this->CTest->GetCTestConfiguration(
409 "MemoryCheckCommand").c_str());
411 else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
412 "PurifyCommand").c_str()) )
414 this->MemoryTester
415 = cmSystemTools::ConvertToOutputPath(this->CTest->GetCTestConfiguration(
416 "PurifyCommand").c_str());
418 else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
419 "ValgrindCommand").c_str()) )
421 this->MemoryTester
422 = cmSystemTools::ConvertToOutputPath(this->CTest->GetCTestConfiguration(
423 "ValgrindCommand").c_str());
425 else if ( cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
426 "BoundsCheckerCommand").c_str()) )
428 this->MemoryTester
429 = cmSystemTools::ConvertToOutputPath(this->CTest->GetCTestConfiguration(
430 "BoundsCheckerCommand").c_str());
432 else
434 cmCTestLog(this->CTest, WARNING,
435 "Memory checker (MemoryCheckCommand) "
436 "not set, or cannot find the specified program."
437 << std::endl);
438 return false;
441 if ( this->MemoryTester[0] == '\"' &&
442 this->MemoryTester[this->MemoryTester.size()-1] == '\"' )
444 this->MemoryTester
445 = this->MemoryTester.substr(1, this->MemoryTester.size()-2);
448 // Setup the options
449 if ( this->CTest->GetCTestConfiguration(
450 "MemoryCheckCommandOptions").size() )
452 this->MemoryTesterOptions = this->CTest->GetCTestConfiguration(
453 "MemoryCheckCommandOptions");
455 else if ( this->CTest->GetCTestConfiguration(
456 "ValgrindCommandOptions").size() )
458 this->MemoryTesterOptions = this->CTest->GetCTestConfiguration(
459 "ValgrindCommandOptions");
462 this->MemoryTesterOutputFile
463 = this->CTest->GetBinaryDir() + "/Testing/Temporary/MemoryChecker.log";
465 if ( this->MemoryTester.find("valgrind") != std::string::npos )
467 this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND;
468 if ( !this->MemoryTesterOptions.size() )
470 this->MemoryTesterOptions = "-q --tool=memcheck --leak-check=yes "
471 "--show-reachable=yes --workaround-gcc296-bugs=yes --num-callers=100";
473 if ( this->CTest->GetCTestConfiguration(
474 "MemoryCheckSuppressionFile").size() )
476 if ( !cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
477 "MemoryCheckSuppressionFile").c_str()) )
479 cmCTestLog(this->CTest, ERROR_MESSAGE,
480 "Cannot find memory checker suppression file: "
481 << this->CTest->GetCTestConfiguration(
482 "MemoryCheckSuppressionFile").c_str() << std::endl);
483 return false;
485 this->MemoryTesterOptions += " --suppressions=" +
486 cmSystemTools::EscapeSpaces(this->CTest->GetCTestConfiguration(
487 "MemoryCheckSuppressionFile").c_str()) + "";
490 else if ( this->MemoryTester.find("purify") != std::string::npos )
492 this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY;
493 std::string outputFile =
494 cmSystemTools::EscapeSpaces(this->MemoryTesterOutputFile.c_str());
496 #ifdef _WIN32
497 if( this->CTest->GetCTestConfiguration(
498 "MemoryCheckSuppressionFile").size() )
500 if( !cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
501 "MemoryCheckSuppressionFile").c_str()) )
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;
509 this->MemoryTesterOptions += " /FilterFiles=" +
510 cmSystemTools::EscapeSpaces(this->CTest->GetCTestConfiguration(
511 "MemoryCheckSuppressionFile").c_str());
513 this->MemoryTesterOptions += " /SAVETEXTDATA=" + outputFile;
514 #else
515 this->MemoryTesterOptions += " -log-file=" + outputFile;
516 #endif
518 else if ( this->MemoryTester.find("BC") != std::string::npos )
520 this->BoundsCheckerXMLFile = this->MemoryTesterOutputFile;
521 std::string outputFile =
522 cmSystemTools::EscapeSpaces(this->MemoryTesterOutputFile.c_str());
523 std::string dpbdFile = this->CTest->GetBinaryDir()
524 + "/Testing/Temporary/MemoryChecker.DPbd";
525 std::string errorFile = this->CTest->GetBinaryDir()
526 + "/Testing/Temporary/MemoryChecker.error";
527 errorFile = cmSystemTools::EscapeSpaces(errorFile.c_str());
528 this->BoundsCheckerDPBDFile = dpbdFile;
529 dpbdFile = cmSystemTools::EscapeSpaces(dpbdFile.c_str());
530 this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER;
531 this->MemoryTesterOptions += " /B " + dpbdFile;
532 this->MemoryTesterOptions += " /X " + outputFile;
533 this->MemoryTesterOptions += " /M ";
535 else
537 cmCTestLog(this->CTest, ERROR_MESSAGE,
538 "Do not understand memory checker: " << this->MemoryTester.c_str()
539 << std::endl);
540 return false;
543 this->MemoryTesterOptionsParsed
544 = cmSystemTools::ParseArguments(this->MemoryTesterOptions.c_str());
545 std::vector<cmStdString>::size_type cc;
546 for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ )
548 this->MemoryTesterGlobalResults[cc] = 0;
550 return true;
553 //----------------------------------------------------------------------
554 bool cmCTestMemCheckHandler::ProcessMemCheckOutput(const std::string& str,
555 std::string& log, int* results)
557 std::string::size_type cc;
558 for ( cc = 0; cc < cmCTestMemCheckHandler::NO_MEMORY_FAULT; cc ++ )
560 results[cc] = 0;
563 if ( this->MemoryTesterStyle == cmCTestMemCheckHandler::VALGRIND )
565 return this->ProcessMemCheckValgrindOutput(str, log, results);
567 else if ( this->MemoryTesterStyle == cmCTestMemCheckHandler::PURIFY )
569 return this->ProcessMemCheckPurifyOutput(str, log, results);
571 else if ( this->MemoryTesterStyle ==
572 cmCTestMemCheckHandler::BOUNDS_CHECKER )
574 return this->ProcessMemCheckBoundsCheckerOutput(str, log, results);
576 else
578 log.append("\nMemory checking style used was: ");
579 log.append("None that I know");
580 log = str;
584 return true;
587 //----------------------------------------------------------------------
588 bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput(
589 const std::string& str, std::string& log,
590 int* results)
592 std::vector<cmStdString> lines;
593 cmSystemTools::Split(str.c_str(), lines);
594 cmOStringStream ostr;
595 log = "";
597 cmsys::RegularExpression pfW("^\\[[WEI]\\] ([A-Z][A-Z][A-Z][A-Z]*): ");
599 int defects = 0;
601 for( std::vector<cmStdString>::iterator i = lines.begin();
602 i != lines.end(); ++i)
604 int failure = cmCTestMemCheckHandler::NO_MEMORY_FAULT;
605 if ( pfW.find(*i) )
607 int cc;
608 for ( cc = 0; cc < cmCTestMemCheckHandler::NO_MEMORY_FAULT; cc ++ )
610 if ( pfW.match(1) == cmCTestMemCheckResultStrings[cc] )
612 failure = cc;
613 break;
616 if ( cc == cmCTestMemCheckHandler::NO_MEMORY_FAULT )
618 cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown Purify memory fault: "
619 << pfW.match(1) << std::endl);
620 ostr << "*** Unknown Purify memory fault: " << pfW.match(1)
621 << std::endl;
624 if ( failure != NO_MEMORY_FAULT )
626 ostr << "<b>" << cmCTestMemCheckResultStrings[failure] << "</b> ";
627 results[failure] ++;
628 defects ++;
630 ostr << cmXMLSafe(*i) << std::endl;
633 log = ostr.str();
634 if ( defects )
636 return false;
638 return true;
641 //----------------------------------------------------------------------
642 bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
643 const std::string& str, std::string& log,
644 int* results)
646 std::vector<cmStdString> lines;
647 cmSystemTools::Split(str.c_str(), lines);
648 bool unlimitedOutput = false;
649 if(str.find("CTEST_FULL_OUTPUT") != str.npos ||
650 this->CustomMaximumFailedTestOutputSize == 0)
652 unlimitedOutput = true;
655 std::string::size_type cc;
657 cmOStringStream ostr;
658 log = "";
660 int defects = 0;
662 cmsys::RegularExpression valgrindLine("^==[0-9][0-9]*==");
664 cmsys::RegularExpression vgFIM(
665 "== .*Invalid free\\(\\) / delete / delete\\[\\]");
666 cmsys::RegularExpression vgFMM(
667 "== .*Mismatched free\\(\\) / delete / delete \\[\\]");
668 cmsys::RegularExpression vgMLK(
669 "== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are definitely lost"
670 " in loss record [0-9][0-9]* of [0-9]");
671 cmsys::RegularExpression vgPAR(
672 "== .*Syscall param .* contains unaddressable byte\\(s\\)");
673 cmsys::RegularExpression vgMPK1(
674 "== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are possibly lost in"
675 " loss record [0-9][0-9]* of [0-9]");
676 cmsys::RegularExpression vgMPK2(
677 "== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are still reachable"
678 " in loss record [0-9][0-9]* of [0-9]");
679 cmsys::RegularExpression vgUMC(
680 "== .*Conditional jump or move depends on uninitialised value\\(s\\)");
681 cmsys::RegularExpression vgUMR1(
682 "== .*Use of uninitialised value of size [0-9][0-9]*");
683 cmsys::RegularExpression vgUMR2("== .*Invalid read of size [0-9][0-9]*");
684 cmsys::RegularExpression vgUMR3("== .*Jump to the invalid address ");
685 cmsys::RegularExpression vgUMR4("== .*Syscall param .* contains "
686 "uninitialised or unaddressable byte\\(s\\)");
687 cmsys::RegularExpression vgUMR5("== .*Syscall param .* uninitialised");
688 cmsys::RegularExpression vgIPW("== .*Invalid write of size [0-9]");
689 cmsys::RegularExpression vgABR("== .*pthread_mutex_unlock: mutex is "
690 "locked by a different thread");
691 std::vector<std::string::size_type> nonValGrindOutput;
692 double sttime = cmSystemTools::GetTime();
693 cmCTestLog(this->CTest, DEBUG, "Start test: " << lines.size() << std::endl);
694 std::string::size_type totalOutputSize = 0;
695 bool outputFull = false;
696 for ( cc = 0; cc < lines.size(); cc ++ )
698 cmCTestLog(this->CTest, DEBUG, "test line "
699 << lines[cc] << std::endl);
701 if ( valgrindLine.find(lines[cc]) )
703 cmCTestLog(this->CTest, DEBUG, "valgrind line "
704 << lines[cc] << std::endl);
705 int failure = cmCTestMemCheckHandler::NO_MEMORY_FAULT;
706 if ( vgFIM.find(lines[cc]) )
708 failure = cmCTestMemCheckHandler::FIM;
710 else if ( vgFMM.find(lines[cc]) )
712 failure = cmCTestMemCheckHandler::FMM;
714 else if ( vgMLK.find(lines[cc]) )
716 failure = cmCTestMemCheckHandler::MLK;
718 else if ( vgPAR.find(lines[cc]) )
720 failure = cmCTestMemCheckHandler::PAR;
722 else if ( vgMPK1.find(lines[cc]) )
724 failure = cmCTestMemCheckHandler::MPK;
726 else if ( vgMPK2.find(lines[cc]) )
728 failure = cmCTestMemCheckHandler::MPK;
730 else if ( vgUMC.find(lines[cc]) )
732 failure = cmCTestMemCheckHandler::UMC;
734 else if ( vgUMR1.find(lines[cc]) )
736 failure = cmCTestMemCheckHandler::UMR;
738 else if ( vgUMR2.find(lines[cc]) )
740 failure = cmCTestMemCheckHandler::UMR;
742 else if ( vgUMR3.find(lines[cc]) )
744 failure = cmCTestMemCheckHandler::UMR;
746 else if ( vgUMR4.find(lines[cc]) )
748 failure = cmCTestMemCheckHandler::UMR;
750 else if ( vgUMR5.find(lines[cc]) )
752 failure = cmCTestMemCheckHandler::UMR;
754 else if ( vgIPW.find(lines[cc]) )
756 failure = cmCTestMemCheckHandler::IPW;
758 else if ( vgABR.find(lines[cc]) )
760 failure = cmCTestMemCheckHandler::ABR;
763 if ( failure != cmCTestMemCheckHandler::NO_MEMORY_FAULT )
765 ostr << "<b>" << cmCTestMemCheckResultStrings[failure] << "</b> ";
766 results[failure] ++;
767 defects ++;
769 totalOutputSize += lines[cc].size();
770 ostr << cmXMLSafe(lines[cc]) << std::endl;
772 else
774 nonValGrindOutput.push_back(cc);
777 // Now put all all the non valgrind output into the test output
778 if(!outputFull)
780 for(std::vector<std::string::size_type>::iterator i =
781 nonValGrindOutput.begin(); i != nonValGrindOutput.end(); ++i)
783 totalOutputSize += lines[*i].size();
784 cmCTestLog(this->CTest, DEBUG, "before xml safe "
785 << lines[*i] << std::endl);
786 cmCTestLog(this->CTest, DEBUG, "after xml safe "
787 << cmXMLSafe(lines[*i]) << std::endl);
789 ostr << cmXMLSafe(lines[*i]) << std::endl;
790 if(!unlimitedOutput && totalOutputSize >
791 static_cast<size_t>(this->CustomMaximumFailedTestOutputSize))
793 outputFull = true;
794 ostr << "....\n";
795 ostr << "Test Output for this test has been truncated see testing"
796 " machine logs for full output,\n";
797 ostr << "or put CTEST_FULL_OUTPUT in the output of "
798 "this test program.\n";
802 cmCTestLog(this->CTest, DEBUG, "End test (elapsed: "
803 << (cmSystemTools::GetTime() - sttime) << std::endl);
804 log = ostr.str();
805 if ( defects )
807 return false;
809 return true;
814 //----------------------------------------------------------------------
815 bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
816 const std::string& str, std::string& log,
817 int* results)
819 log = "";
820 double sttime = cmSystemTools::GetTime();
821 std::vector<cmStdString> lines;
822 cmSystemTools::Split(str.c_str(), lines);
823 cmCTestLog(this->CTest, DEBUG, "Start test: " << lines.size() << std::endl);
824 std::vector<cmStdString>::size_type cc;
825 for ( cc = 0; cc < lines.size(); cc ++ )
827 if(lines[cc] == BOUNDS_CHECKER_MARKER)
829 break;
832 cmBoundsCheckerParser parser(this->CTest);
833 parser.InitializeParser();
834 if(cc < lines.size())
836 for(cc++; cc < lines.size(); ++cc)
838 std::string& theLine = lines[cc];
839 // check for command line arguments that are not escaped
840 // correctly by BC
841 if(theLine.find("TargetArgs=") != theLine.npos)
843 // skip this because BC gets it wrong and we can't parse it
845 else if(!parser.ParseChunk(theLine.c_str(), theLine.size()))
847 cmCTestLog(this->CTest, ERROR_MESSAGE,
848 "Error in ParseChunk: " << theLine.c_str()
849 << std::endl);
853 int defects = 0;
854 for(cc =0; cc < parser.Errors.size(); ++cc)
856 results[parser.Errors[cc]]++;
857 defects++;
859 cmCTestLog(this->CTest, DEBUG, "End test (elapsed: "
860 << (cmSystemTools::GetTime() - sttime) << std::endl);
861 if(defects)
863 // only put the output of Bounds Checker if there were
864 // errors or leaks detected
865 log = parser.Log;
866 return false;
868 return true;
871 void
872 cmCTestMemCheckHandler::ProcessOneTest(cmCTestTestProperties *props,
873 std::vector<cmStdString> &passed,
874 std::vector<cmStdString> &failed,
875 int count, int tmsize)
877 // run parent test
878 cmCTestTestHandler::ProcessOneTest(props, passed, failed, count, tmsize);
879 cmCTestTestResult& res = this->TestResults[this->TestResults.size()-1];
880 cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "process test output now: "
881 << props->Name.c_str() << " " << res.Name.c_str() << std::endl);
882 if( this->MemoryTesterStyle == cmCTestMemCheckHandler::BOUNDS_CHECKER)
884 this->PostProcessBoundsCheckerTest(res);
886 else if(this->MemoryTesterStyle == cmCTestMemCheckHandler::PURIFY )
888 this->PostProcessPurifyTest(res);
892 // This method puts the bounds checker output file into the output
893 // for the test
894 void
895 cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res)
897 cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
898 "PostProcessBoundsCheckerTest for : "
899 << res.Name.c_str() << std::endl);
900 if ( !cmSystemTools::FileExists(this->MemoryTesterOutputFile.c_str()) )
902 std::string log = "Cannot find memory tester output file: "
903 + this->MemoryTesterOutputFile;
904 cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
905 return;
907 // put a scope around this to close ifs so the file can be removed
909 std::ifstream ifs(this->MemoryTesterOutputFile.c_str());
910 if ( !ifs )
912 std::string log = "Cannot read memory tester output file: "
913 + this->MemoryTesterOutputFile;
914 cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
915 return;
917 res.Output += BOUNDS_CHECKER_MARKER;
918 res.Output += "\n";
919 std::string line;
920 while ( cmSystemTools::GetLineFromStream(ifs, line) )
922 res.Output += line;
923 res.Output += "\n";
926 cmSystemTools::Delay(1000);
927 cmSystemTools::RemoveFile(this->BoundsCheckerDPBDFile.c_str());
928 cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Remove: "
929 << this->BoundsCheckerDPBDFile.c_str() << std::endl);
930 cmSystemTools::RemoveFile(this->BoundsCheckerXMLFile.c_str());
931 cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Remove: "
932 << this->BoundsCheckerXMLFile.c_str() << std::endl);
935 void
936 cmCTestMemCheckHandler::PostProcessPurifyTest(cmCTestTestResult& res)
938 cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
939 "PostProcessPurifyTest for : "
940 << res.Name.c_str() << std::endl);
941 if ( !cmSystemTools::FileExists(this->MemoryTesterOutputFile.c_str()) )
943 std::string log = "Cannot find memory tester output file: "
944 + this->MemoryTesterOutputFile;
945 cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
946 return;
948 std::ifstream ifs(this->MemoryTesterOutputFile.c_str());
949 if ( !ifs )
951 std::string log = "Cannot read memory tester output file: "
952 + this->MemoryTesterOutputFile;
953 cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
954 return;
956 std::string line;
957 while ( cmSystemTools::GetLineFromStream(ifs, line) )
959 res.Output += line;
960 res.Output += "\n";