Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / CTest / cmCTestMemCheckHandler.cxx
blob8f15ca15dffb735b45ad7e40ddd377b12aae0041
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCTestMemCheckHandler.cxx,v $
5 Language: C++
6 Date: $Date: 2009-02-05 21:31:37 $
7 Version: $Revision: 1.22 $
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 this->MemoryTesterOptions += " /SAVETEXTDATA=" + outputFile;
498 #else
499 this->MemoryTesterOptions += " -log-file=" + outputFile;
500 #endif
502 else if ( this->MemoryTester.find("BC") != std::string::npos )
504 this->BoundsCheckerXMLFile = this->MemoryTesterOutputFile;
505 std::string outputFile =
506 cmSystemTools::EscapeSpaces(this->MemoryTesterOutputFile.c_str());
507 std::string dpbdFile = this->CTest->GetBinaryDir()
508 + "/Testing/Temporary/MemoryChecker.DPbd";
509 std::string errorFile = this->CTest->GetBinaryDir()
510 + "/Testing/Temporary/MemoryChecker.error";
511 errorFile = cmSystemTools::EscapeSpaces(errorFile.c_str());
512 this->BoundsCheckerDPBDFile = dpbdFile;
513 dpbdFile = cmSystemTools::EscapeSpaces(dpbdFile.c_str());
514 this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER;
515 this->MemoryTesterOptions += " /B " + dpbdFile;
516 this->MemoryTesterOptions += " /X " + outputFile;
517 this->MemoryTesterOptions += " /M ";
519 else
521 cmCTestLog(this->CTest, ERROR_MESSAGE,
522 "Do not understand memory checker: " << this->MemoryTester.c_str()
523 << std::endl);
524 return false;
527 this->MemoryTesterOptionsParsed
528 = cmSystemTools::ParseArguments(this->MemoryTesterOptions.c_str());
529 std::vector<cmStdString>::size_type cc;
530 for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ )
532 this->MemoryTesterGlobalResults[cc] = 0;
534 return true;
537 //----------------------------------------------------------------------
538 bool cmCTestMemCheckHandler::ProcessMemCheckOutput(const std::string& str,
539 std::string& log, int* results)
541 std::string::size_type cc;
542 for ( cc = 0; cc < cmCTestMemCheckHandler::NO_MEMORY_FAULT; cc ++ )
544 results[cc] = 0;
547 if ( this->MemoryTesterStyle == cmCTestMemCheckHandler::VALGRIND )
549 return this->ProcessMemCheckValgrindOutput(str, log, results);
551 else if ( this->MemoryTesterStyle == cmCTestMemCheckHandler::PURIFY )
553 return this->ProcessMemCheckPurifyOutput(str, log, results);
555 else if ( this->MemoryTesterStyle ==
556 cmCTestMemCheckHandler::BOUNDS_CHECKER )
558 return this->ProcessMemCheckBoundsCheckerOutput(str, log, results);
560 else
562 log.append("\nMemory checking style used was: ");
563 log.append("None that I know");
564 log = str;
568 return true;
571 //----------------------------------------------------------------------
572 bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput(
573 const std::string& str, std::string& log,
574 int* results)
576 std::vector<cmStdString> lines;
577 cmSystemTools::Split(str.c_str(), lines);
578 cmOStringStream ostr;
579 log = "";
581 cmsys::RegularExpression pfW("^\\[[WEI]\\] ([A-Z][A-Z][A-Z][A-Z]*): ");
583 int defects = 0;
585 for( std::vector<cmStdString>::iterator i = lines.begin();
586 i != lines.end(); ++i)
588 int failure = cmCTestMemCheckHandler::NO_MEMORY_FAULT;
589 if ( pfW.find(*i) )
591 int cc;
592 for ( cc = 0; cc < cmCTestMemCheckHandler::NO_MEMORY_FAULT; cc ++ )
594 if ( pfW.match(1) == cmCTestMemCheckResultStrings[cc] )
596 failure = cc;
597 break;
600 if ( cc == cmCTestMemCheckHandler::NO_MEMORY_FAULT )
602 cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown Purify memory fault: "
603 << pfW.match(1) << std::endl);
604 ostr << "*** Unknown Purify memory fault: " << pfW.match(1)
605 << std::endl;
608 if ( failure != NO_MEMORY_FAULT )
610 ostr << "<b>" << cmCTestMemCheckResultStrings[failure] << "</b> ";
611 results[failure] ++;
612 defects ++;
614 ostr << cmXMLSafe(*i) << std::endl;
617 log = ostr.str();
618 if ( defects )
620 return false;
622 return true;
625 //----------------------------------------------------------------------
626 bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
627 const std::string& str, std::string& log,
628 int* results)
630 std::vector<cmStdString> lines;
631 cmSystemTools::Split(str.c_str(), lines);
632 bool unlimitedOutput = false;
633 if(str.find("CTEST_FULL_OUTPUT") != str.npos ||
634 this->CustomMaximumFailedTestOutputSize == 0)
636 unlimitedOutput = true;
639 std::string::size_type cc;
641 cmOStringStream ostr;
642 log = "";
644 int defects = 0;
646 cmsys::RegularExpression valgrindLine("^==[0-9][0-9]*==");
648 cmsys::RegularExpression vgFIM(
649 "== .*Invalid free\\(\\) / delete / delete\\[\\]");
650 cmsys::RegularExpression vgFMM(
651 "== .*Mismatched free\\(\\) / delete / delete \\[\\]");
652 cmsys::RegularExpression vgMLK(
653 "== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are definitely lost"
654 " in loss record [0-9][0-9]* of [0-9]");
655 cmsys::RegularExpression vgPAR(
656 "== .*Syscall param .* contains unaddressable byte\\(s\\)");
657 cmsys::RegularExpression vgMPK1(
658 "== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are possibly lost in"
659 " loss record [0-9][0-9]* of [0-9]");
660 cmsys::RegularExpression vgMPK2(
661 "== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are still reachable"
662 " in loss record [0-9][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][0-9]*");
667 cmsys::RegularExpression vgUMR2("== .*Invalid read of size [0-9][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 ++ )
682 cmCTestLog(this->CTest, DEBUG, "test line "
683 << lines[cc] << std::endl);
685 if ( valgrindLine.find(lines[cc]) )
687 cmCTestLog(this->CTest, DEBUG, "valgrind line "
688 << lines[cc] << std::endl);
689 int failure = cmCTestMemCheckHandler::NO_MEMORY_FAULT;
690 if ( vgFIM.find(lines[cc]) )
692 failure = cmCTestMemCheckHandler::FIM;
694 else if ( vgFMM.find(lines[cc]) )
696 failure = cmCTestMemCheckHandler::FMM;
698 else if ( vgMLK.find(lines[cc]) )
700 failure = cmCTestMemCheckHandler::MLK;
702 else if ( vgPAR.find(lines[cc]) )
704 failure = cmCTestMemCheckHandler::PAR;
706 else if ( vgMPK1.find(lines[cc]) )
708 failure = cmCTestMemCheckHandler::MPK;
710 else if ( vgMPK2.find(lines[cc]) )
712 failure = cmCTestMemCheckHandler::MPK;
714 else if ( vgUMC.find(lines[cc]) )
716 failure = cmCTestMemCheckHandler::UMC;
718 else if ( vgUMR1.find(lines[cc]) )
720 failure = cmCTestMemCheckHandler::UMR;
722 else if ( vgUMR2.find(lines[cc]) )
724 failure = cmCTestMemCheckHandler::UMR;
726 else if ( vgUMR3.find(lines[cc]) )
728 failure = cmCTestMemCheckHandler::UMR;
730 else if ( vgUMR4.find(lines[cc]) )
732 failure = cmCTestMemCheckHandler::UMR;
734 else if ( vgUMR5.find(lines[cc]) )
736 failure = cmCTestMemCheckHandler::UMR;
738 else if ( vgIPW.find(lines[cc]) )
740 failure = cmCTestMemCheckHandler::IPW;
742 else if ( vgABR.find(lines[cc]) )
744 failure = cmCTestMemCheckHandler::ABR;
747 if ( failure != cmCTestMemCheckHandler::NO_MEMORY_FAULT )
749 ostr << "<b>" << cmCTestMemCheckResultStrings[failure] << "</b> ";
750 results[failure] ++;
751 defects ++;
753 totalOutputSize += lines[cc].size();
754 ostr << cmXMLSafe(lines[cc]) << std::endl;
756 else
758 nonValGrindOutput.push_back(cc);
761 // Now put all all the non valgrind output into the test output
762 if(!outputFull)
764 for(std::vector<std::string::size_type>::iterator i =
765 nonValGrindOutput.begin(); i != nonValGrindOutput.end(); ++i)
767 totalOutputSize += lines[*i].size();
768 cmCTestLog(this->CTest, DEBUG, "before xml safe "
769 << lines[*i] << std::endl);
770 cmCTestLog(this->CTest, DEBUG, "after xml safe "
771 << cmXMLSafe(lines[*i]) << std::endl);
773 ostr << cmXMLSafe(lines[*i]) << std::endl;
774 if(!unlimitedOutput && totalOutputSize >
775 static_cast<size_t>(this->CustomMaximumFailedTestOutputSize))
777 outputFull = true;
778 ostr << "....\n";
779 ostr << "Test Output for this test has been truncated see testing"
780 " machine logs for full output,\n";
781 ostr << "or put CTEST_FULL_OUTPUT in the output of "
782 "this test program.\n";
786 cmCTestLog(this->CTest, DEBUG, "End test (elapsed: "
787 << (cmSystemTools::GetTime() - sttime) << std::endl);
788 log = ostr.str();
789 if ( defects )
791 return false;
793 return true;
798 //----------------------------------------------------------------------
799 bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
800 const std::string& str, std::string& log,
801 int* results)
803 log = "";
804 double sttime = cmSystemTools::GetTime();
805 std::vector<cmStdString> lines;
806 cmSystemTools::Split(str.c_str(), lines);
807 cmCTestLog(this->CTest, DEBUG, "Start test: " << lines.size() << std::endl);
808 std::vector<cmStdString>::size_type cc;
809 for ( cc = 0; cc < lines.size(); cc ++ )
811 if(lines[cc] == BOUNDS_CHECKER_MARKER)
813 break;
816 cmBoundsCheckerParser parser(this->CTest);
817 parser.InitializeParser();
818 if(cc < lines.size())
820 for(cc++; cc < lines.size(); ++cc)
822 std::string& theLine = lines[cc];
823 // check for command line arguments that are not escaped
824 // correctly by BC
825 if(theLine.find("TargetArgs=") != theLine.npos)
827 // skip this because BC gets it wrong and we can't parse it
829 else if(!parser.ParseChunk(theLine.c_str(), theLine.size()))
831 cmCTestLog(this->CTest, ERROR_MESSAGE,
832 "Error in ParseChunk: " << theLine.c_str()
833 << std::endl);
837 int defects = 0;
838 for(cc =0; cc < parser.Errors.size(); ++cc)
840 results[parser.Errors[cc]]++;
841 defects++;
843 cmCTestLog(this->CTest, DEBUG, "End test (elapsed: "
844 << (cmSystemTools::GetTime() - sttime) << std::endl);
845 if(defects)
847 // only put the output of Bounds Checker if there were
848 // errors or leaks detected
849 log = parser.Log;
850 return false;
852 return true;
855 void
856 cmCTestMemCheckHandler::ProcessOneTest(cmCTestTestProperties *props,
857 std::vector<cmStdString> &passed,
858 std::vector<cmStdString> &failed,
859 int count, int tmsize)
861 // run parent test
862 cmCTestTestHandler::ProcessOneTest(props, passed, failed, count, tmsize);
863 cmCTestTestResult& res = this->TestResults[this->TestResults.size()-1];
864 cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "process test output now: "
865 << props->Name.c_str() << " " << res.Name.c_str() << std::endl);
866 if( this->MemoryTesterStyle == cmCTestMemCheckHandler::BOUNDS_CHECKER)
868 this->PostProcessBoundsCheckerTest(res);
870 else if(this->MemoryTesterStyle == cmCTestMemCheckHandler::PURIFY )
872 this->PostProcessPurifyTest(res);
876 // This method puts the bounds checker output file into the output
877 // for the test
878 void
879 cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res)
881 cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
882 "PostProcessBoundsCheckerTest for : "
883 << res.Name.c_str() << std::endl);
884 if ( !cmSystemTools::FileExists(this->MemoryTesterOutputFile.c_str()) )
886 std::string log = "Cannot find memory tester output file: "
887 + this->MemoryTesterOutputFile;
888 cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
889 return;
891 // put a scope around this to close ifs so the file can be removed
893 std::ifstream ifs(this->MemoryTesterOutputFile.c_str());
894 if ( !ifs )
896 std::string log = "Cannot read memory tester output file: "
897 + this->MemoryTesterOutputFile;
898 cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
899 return;
901 res.Output += BOUNDS_CHECKER_MARKER;
902 res.Output += "\n";
903 std::string line;
904 while ( cmSystemTools::GetLineFromStream(ifs, line) )
906 res.Output += line;
907 res.Output += "\n";
910 cmSystemTools::Delay(1000);
911 cmSystemTools::RemoveFile(this->BoundsCheckerDPBDFile.c_str());
912 cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Remove: "
913 << this->BoundsCheckerDPBDFile.c_str() << std::endl);
914 cmSystemTools::RemoveFile(this->BoundsCheckerXMLFile.c_str());
915 cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Remove: "
916 << this->BoundsCheckerXMLFile.c_str() << std::endl);
919 void
920 cmCTestMemCheckHandler::PostProcessPurifyTest(cmCTestTestResult& res)
922 cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
923 "PostProcessPurifyTest for : "
924 << res.Name.c_str() << std::endl);
925 if ( !cmSystemTools::FileExists(this->MemoryTesterOutputFile.c_str()) )
927 std::string log = "Cannot find memory tester output file: "
928 + this->MemoryTesterOutputFile;
929 cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
930 return;
932 std::ifstream ifs(this->MemoryTesterOutputFile.c_str());
933 if ( !ifs )
935 std::string log = "Cannot read memory tester output file: "
936 + this->MemoryTesterOutputFile;
937 cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
938 return;
940 std::string line;
941 while ( cmSystemTools::GetLineFromStream(ifs, line) )
943 res.Output += line;