1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCTestMemCheckHandler.cxx,v $
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"
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"
35 const char* ErrorCategory
;
40 static CatToErrorType cmCTestMemCheckBoundsChecker
[] = {
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
},
51 // parse the xml file storing the installed version of Xcode on
53 class cmBoundsCheckerParser
: public cmXMLParser
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
);
77 ostr
<< name
<< ":\n";
79 for(; atts
[i
] != 0; i
+=2)
81 ostr
<< " " << cmXMLSafe(atts
[i
])
82 << " - " << cmXMLSafe(atts
[i
+1]) << "\n";
85 this->Log
+= ostr
.str();
87 void EndElement(const char* )
91 const char* GetAttribute(const char* name
, const char** atts
)
94 for(; atts
[i
] != 0; ++i
)
96 if(strcmp(name
, atts
[i
]) == 0)
103 void ParseError(const char** atts
)
105 CatToErrorType
* ptr
= cmCTestMemCheckBoundsChecker
;
106 const char* cat
= this->GetAttribute("ErrorCategory", atts
);
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" );
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
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
);
132 std::vector
<int> Errors
;
136 #define BOUNDS_CHECKER_MARKER \
137 "******######*****Begin BOUNDS CHECKER XML******######******"
138 //----------------------------------------------------------------------
139 static const char* cmCTestMemCheckResultStrings
[] = {
166 //----------------------------------------------------------------------
167 static const char* cmCTestMemCheckResultLongStrings
[] = {
175 "Mismatched deallocation",
183 "Potential Memory Leak",
186 "Invalid syscall param",
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
= "";
214 for ( cc
= 0; cc
< NO_MEMORY_FAULT
; cc
++ )
216 this->MemoryTesterGlobalResults
[cc
] = 0;
221 //----------------------------------------------------------------------
222 int cmCTestMemCheckHandler::PreProcessHandler()
224 if ( !this->InitializeMemoryChecking() )
229 if ( !this->ExecuteCommands(this->CustomPreMemCheck
) )
231 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
232 "Problem executing pre-memcheck command(s)." << std::endl
);
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
);
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() )
291 this->CTest
->StartXML(os
, this->AppendXML
);
292 os
<< "<DynamicAnalysis Checker=\"";
293 switch ( this->MemoryTesterStyle
)
295 case cmCTestMemCheckHandler::VALGRIND
:
298 case cmCTestMemCheckHandler::PURIFY
:
301 case cmCTestMemCheckHandler::BOUNDS_CHECKER
:
302 os
<< "BoundsChecker";
307 os
<< "\">" << std::endl
;
309 os
<< "\t<StartDateTime>" << this->StartTest
<< "</StartDateTime>\n"
310 << "\t<StartTestTime>" << this->StartTestTime
<< "</StartTestTime>\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;
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
];
333 bool res
= this->ProcessMemCheckOutput(result
->Output
, memcheckstr
,
335 if ( res
&& result
->Status
== cmCTestMemCheckHandler::COMPLETED
)
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
]
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
358 this->WriteTestResultFooter(os
, result
);
361 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "#" << std::flush
);
365 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, std::endl
);
366 cmCTestLog(this->CTest
, HANDLER_OUTPUT
, "Memory checking results:"
368 os
<< "\t<DefectList>" << std::endl
;
369 for ( cc
= 0; cmCTestMemCheckResultStrings
[cc
]; cc
++ )
371 if ( this->MemoryTesterGlobalResults
[cc
] )
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()
404 if ( cmSystemTools::FileExists(this->CTest
->GetCTestConfiguration(
405 "MemoryCheckCommand").c_str()) )
408 = cmSystemTools::ConvertToOutputPath(this->CTest
->GetCTestConfiguration(
409 "MemoryCheckCommand").c_str());
411 else if ( cmSystemTools::FileExists(this->CTest
->GetCTestConfiguration(
412 "PurifyCommand").c_str()) )
415 = cmSystemTools::ConvertToOutputPath(this->CTest
->GetCTestConfiguration(
416 "PurifyCommand").c_str());
418 else if ( cmSystemTools::FileExists(this->CTest
->GetCTestConfiguration(
419 "ValgrindCommand").c_str()) )
422 = cmSystemTools::ConvertToOutputPath(this->CTest
->GetCTestConfiguration(
423 "ValgrindCommand").c_str());
425 else if ( cmSystemTools::FileExists(this->CTest
->GetCTestConfiguration(
426 "BoundsCheckerCommand").c_str()) )
429 = cmSystemTools::ConvertToOutputPath(this->CTest
->GetCTestConfiguration(
430 "BoundsCheckerCommand").c_str());
434 cmCTestLog(this->CTest
, WARNING
,
435 "Memory checker (MemoryCheckCommand) "
436 "not set, or cannot find the specified program."
441 if ( this->MemoryTester
[0] == '\"' &&
442 this->MemoryTester
[this->MemoryTester
.size()-1] == '\"' )
445 = this->MemoryTester
.substr(1, this->MemoryTester
.size()-2);
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
);
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());
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
);
509 this->MemoryTesterOptions
+= " /FilterFiles=" +
510 cmSystemTools::EscapeSpaces(this->CTest
->GetCTestConfiguration(
511 "MemoryCheckSuppressionFile").c_str());
513 this->MemoryTesterOptions
+= " /SAVETEXTDATA=" + outputFile
;
515 this->MemoryTesterOptions
+= " -log-file=" + outputFile
;
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 ";
537 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
538 "Do not understand memory checker: " << this->MemoryTester
.c_str()
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;
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
++ )
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
);
578 log
.append("\nMemory checking style used was: ");
579 log
.append("None that I know");
587 //----------------------------------------------------------------------
588 bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput(
589 const std::string
& str
, std::string
& log
,
592 std::vector
<cmStdString
> lines
;
593 cmSystemTools::Split(str
.c_str(), lines
);
594 cmOStringStream ostr
;
597 cmsys::RegularExpression
pfW("^\\[[WEI]\\] ([A-Z][A-Z][A-Z][A-Z]*): ");
601 for( std::vector
<cmStdString
>::iterator i
= lines
.begin();
602 i
!= lines
.end(); ++i
)
604 int failure
= cmCTestMemCheckHandler::NO_MEMORY_FAULT
;
608 for ( cc
= 0; cc
< cmCTestMemCheckHandler::NO_MEMORY_FAULT
; cc
++ )
610 if ( pfW
.match(1) == cmCTestMemCheckResultStrings
[cc
] )
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)
624 if ( failure
!= NO_MEMORY_FAULT
)
626 ostr
<< "<b>" << cmCTestMemCheckResultStrings
[failure
] << "</b> ";
630 ostr
<< cmXMLSafe(*i
) << std::endl
;
641 //----------------------------------------------------------------------
642 bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
643 const std::string
& str
, std::string
& log
,
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
;
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> ";
769 totalOutputSize
+= lines
[cc
].size();
770 ostr
<< cmXMLSafe(lines
[cc
]) << std::endl
;
774 nonValGrindOutput
.push_back(cc
);
777 // Now put all all the non valgrind output into the test output
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
))
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
);
814 //----------------------------------------------------------------------
815 bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
816 const std::string
& str
, std::string
& 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
)
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
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()
854 for(cc
=0; cc
< parser
.Errors
.size(); ++cc
)
856 results
[parser
.Errors
[cc
]]++;
859 cmCTestLog(this->CTest
, DEBUG
, "End test (elapsed: "
860 << (cmSystemTools::GetTime() - sttime
) << std::endl
);
863 // only put the output of Bounds Checker if there were
864 // errors or leaks detected
872 cmCTestMemCheckHandler::ProcessOneTest(cmCTestTestProperties
*props
,
873 std::vector
<cmStdString
> &passed
,
874 std::vector
<cmStdString
> &failed
,
875 int count
, int tmsize
)
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
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
);
907 // put a scope around this to close ifs so the file can be removed
909 std::ifstream
ifs(this->MemoryTesterOutputFile
.c_str());
912 std::string log
= "Cannot read memory tester output file: "
913 + this->MemoryTesterOutputFile
;
914 cmCTestLog(this->CTest
, ERROR_MESSAGE
, log
.c_str() << std::endl
);
917 res
.Output
+= BOUNDS_CHECKER_MARKER
;
920 while ( cmSystemTools::GetLineFromStream(ifs
, line
) )
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
);
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
);
948 std::ifstream
ifs(this->MemoryTesterOutputFile
.c_str());
951 std::string log
= "Cannot read memory tester output file: "
952 + this->MemoryTesterOutputFile
;
953 cmCTestLog(this->CTest
, ERROR_MESSAGE
, log
.c_str() << std::endl
);
957 while ( cmSystemTools::GetLineFromStream(ifs
, line
) )