diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 992652599..52916fced 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -149,6 +149,7 @@ SET(CMTEST_SRCS ctest.cxx cmCTest.cxx CTest/cmCTestEmptyBinaryDirectoryCommand.cxx CTest/cmCTestRunScriptCommand.cxx CTest/cmCTestSleepCommand.cxx + CTest/cmCTestMemCheckHandler.cxx ) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/Source/CTest) diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 24a57a2e5..49d7a1e53 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -192,20 +192,20 @@ void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile *mf) //---------------------------------------------------------------------- //clearly it would be nice if this were broken up into a few smaller //functions and commented... -int cmCTestBuildHandler::BuildDirectory() +int cmCTestBuildHandler::ProcessHandler() { std::cout << "Build project" << std::endl; std::string makeCommand = m_CTest->GetDartConfiguration("MakeCommand"); if ( makeCommand.size() == 0 ) { std::cerr << "Cannot find MakeCommand key in the DartConfiguration.tcl" << std::endl; - return 1; + return -1; } std::string buildDirectory = m_CTest->GetDartConfiguration("BuildDirectory"); if ( buildDirectory.size() == 0 ) { std::cerr << "Cannot find BuildDirectory key in the DartConfiguration.tcl" << std::endl; - return 1; + return -1; } cmGeneratedFileStream ofs; @@ -438,7 +438,7 @@ int cmCTestBuildHandler::BuildDirectory() if( !m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), "Build.xml", xofs, true) ) { std::cerr << "Cannot create build XML file" << std::endl; - return 1; + return -1; } this->GenerateDartBuildOutput(xofs, errorsWarnings, elapsed_build_time); return 0; diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h index 9a6b15a4c..575068e29 100644 --- a/Source/CTest/cmCTestBuildHandler.h +++ b/Source/CTest/cmCTestBuildHandler.h @@ -37,7 +37,7 @@ public: /* * The main entry point for this class */ - int BuildDirectory(); + int ProcessHandler(); cmCTestBuildHandler(); diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx index dc7076893..9351b31be 100644 --- a/Source/CTest/cmCTestConfigureHandler.cxx +++ b/Source/CTest/cmCTestConfigureHandler.cxx @@ -34,7 +34,7 @@ cmCTestConfigureHandler::cmCTestConfigureHandler() //---------------------------------------------------------------------- //clearly it would be nice if this were broken up into a few smaller //functions and commented... -int cmCTestConfigureHandler::ConfigureDirectory() +int cmCTestConfigureHandler::ProcessHandler() { std::cout << "Configure project" << std::endl; std::string cCommand = m_CTest->GetDartConfiguration("ConfigureCommand"); @@ -42,14 +42,14 @@ int cmCTestConfigureHandler::ConfigureDirectory() { std::cerr << "Cannot find ConfigureCommand key in the DartConfiguration.tcl" << std::endl; - return 1; + return -1; } std::string buildDirectory = m_CTest->GetDartConfiguration("BuildDirectory"); if ( buildDirectory.size() == 0 ) { std::cerr << "Cannot find BuildDirectory key in the DartConfiguration.tcl" << std::endl; - return 1; + return -1; } double elapsed_time_start = cmSystemTools::GetTime(); @@ -107,7 +107,7 @@ int cmCTestConfigureHandler::ConfigureDirectory() if (! res || retVal ) { std::cerr << "Error(s) when updating the project" << std::endl; - return 1; + return -1; } return 0; } diff --git a/Source/CTest/cmCTestConfigureHandler.h b/Source/CTest/cmCTestConfigureHandler.h index c475d6d94..e48f08857 100644 --- a/Source/CTest/cmCTestConfigureHandler.h +++ b/Source/CTest/cmCTestConfigureHandler.h @@ -33,7 +33,7 @@ public: /* * The main entry point for this class */ - int ConfigureDirectory(); + int ProcessHandler(); cmCTestConfigureHandler(); }; diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 4f7a42ee0..b09ac4d7e 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -154,7 +154,7 @@ bool cmCTestCoverageHandler::ShouldIDoCoverage(const char* file, const char* src //---------------------------------------------------------------------- //clearly it would be nice if this were broken up into a few smaller //functions and commented... -int cmCTestCoverageHandler::CoverageDirectory() +int cmCTestCoverageHandler::ProcessHandler() { int error = 0; @@ -330,7 +330,7 @@ int cmCTestCoverageHandler::CoverageDirectory() "Coverage.xml", covSumFile, true)) { std::cerr << "Cannot open coverage summary file: Coverage.xml" << std::endl; - return 1; + return -1; } m_CTest->StartXML(covSumFile); @@ -341,7 +341,7 @@ int cmCTestCoverageHandler::CoverageDirectory() int logFileCount = 0; if ( !this->StartLogFile(covLogFile, logFileCount) ) { - return 1; + return -1; } totalCoverageMap::iterator fileIterator; int cnt = 0; @@ -360,7 +360,7 @@ int cmCTestCoverageHandler::CoverageDirectory() logFileCount ++; if ( !this->StartLogFile(covLogFile, logFileCount) ) { - return 1; + return -1; } } const std::string fullFileName = fileIterator->first; @@ -503,5 +503,9 @@ int cmCTestCoverageHandler::CoverageDirectory() cmSystemTools::ChangeDirectory(currentDirectory.c_str()); - return error; + if ( error ) + { + return -1; + } + return 0; } diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h index 1c5aaf6d1..d303ff1b8 100644 --- a/Source/CTest/cmCTestCoverageHandler.h +++ b/Source/CTest/cmCTestCoverageHandler.h @@ -35,7 +35,7 @@ public: /* * The main entry point for this class */ - int CoverageDirectory(); + int ProcessHandler(); cmCTestCoverageHandler(); diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index 10d4f9413..9ae2ff7ba 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -23,3 +23,8 @@ cmCTestGenericHandler::cmCTestGenericHandler() m_CTest = 0; } +cmCTestGenericHandler::~cmCTestGenericHandler() +{ +} + + diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index 56105a53f..26fdc02f8 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -39,7 +39,13 @@ public: /** * Populate internals from CTest custom scripts */ - void PopulateCustomVectors(cmMakefile *) {} + virtual void PopulateCustomVectors(cmMakefile *) {} + + /** + * Do the actual processing. Subclass has to override it. + * Return < 0 if error. + */ + virtual int ProcessHandler() = 0; /** * Set the CTest instance @@ -50,6 +56,7 @@ public: * Construct handler */ cmCTestGenericHandler(); + virtual ~cmCTestGenericHandler(); protected: bool m_Verbose; diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx new file mode 100644 index 000000000..73577fc9c --- /dev/null +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -0,0 +1,548 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "cmCTestMemCheckHandler.h" + +#include "cmCTest.h" +#include "cmake.h" +#include "cmGeneratedFileStream.h" +#include +#include +#include +#include "cmMakefile.h" + +#include +#include +#include + +//---------------------------------------------------------------------- +static const char* cmCTestMemCheckResultStrings[] = { + "ABR", + "ABW", + "ABWL", + "COR", + "EXU", + "FFM", + "FIM", + "FMM", + "FMR", + "FMW", + "FUM", + "IPR", + "IPW", + "MAF", + "MLK", + "MPK", + "NPR", + "ODS", + "PAR", + "PLK", + "UMC", + "UMR", + 0 +}; + +//---------------------------------------------------------------------- +static const char* cmCTestMemCheckResultLongStrings[] = { + "Threading Problem", + "ABW", + "ABWL", + "COR", + "EXU", + "FFM", + "FIM", + "Mismatched deallocation", + "FMR", + "FMW", + "FUM", + "IPR", + "IPW", + "MAF", + "Memory Leak", + "Potential Memory Leak", + "NPR", + "ODS", + "Invalid syscall param", + "PLK", + "Uninitialized Memory Conditional", + "Uninitialized Memory Read", + 0 +}; + + +//---------------------------------------------------------------------- +cmCTestMemCheckHandler::cmCTestMemCheckHandler() +{ + m_MemCheck = true; +} + +//---------------------------------------------------------------------- +int cmCTestMemCheckHandler::PreProcessHandler() +{ + if ( !this->InitializeMemoryChecking() ) + { + return 0; + } + + if ( !this->ExecuteCommands(m_CustomPreMemCheck) ) + { + std::cerr << "Problem executing pre-memcheck command(s)." << std::endl; + return 0; + } + return 1; +} + +//---------------------------------------------------------------------- +int cmCTestMemCheckHandler::PostProcessHandler() +{ + if ( !this->ExecuteCommands(m_CustomPostMemCheck) ) + { + std::cerr << "Problem executing post-memcheck command(s)." << std::endl; + return 0; + } + return 1; +} + +//---------------------------------------------------------------------- +void cmCTestMemCheckHandler::GenerateTestCommand(std::vector& args) +{ + std::vector::size_type pp; + args.push_back(m_MemoryTester.c_str()); + std::string memcheckcommand = ""; + memcheckcommand = m_MemoryTester; + for ( pp = 0; pp < m_MemoryTesterOptionsParsed.size(); pp ++ ) + { + args.push_back(m_MemoryTesterOptionsParsed[pp].c_str()); + memcheckcommand += " "; + memcheckcommand += cmSystemTools::EscapeSpaces(m_MemoryTesterOptionsParsed[pp].c_str()); + } + if ( m_Verbose ) + { + std::cout << "Memory check command: " << memcheckcommand << std::endl; + } +} + +//---------------------------------------------------------------------- +void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile *mf) +{ + this->cmCTestTestHandler::PopulateCustomVectors(mf); + cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_PRE_MEMCHECK", + m_CustomPreMemCheck); + cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_POST_MEMCHECK", + m_CustomPostMemCheck); + + cmCTest::PopulateCustomVector(mf, + "CTEST_CUSTOM_MEMCHECK_IGNORE", + m_CustomTestsIgnore); +} + +//---------------------------------------------------------------------- +void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os) +{ + if ( !m_CTest->GetProduceXML() ) + { + return; + } + + m_CTest->StartXML(os); + os << "" << std::endl; + + os << "\t" << m_StartTest << "\n" + << "\t\n"; + tm_TestResultsVector::size_type cc; + for ( cc = 0; cc < m_TestResults.size(); cc ++ ) + { + cmCTestTestResult *result = &m_TestResults[cc]; + std::string testPath = result->m_Path + "/" + result->m_Name; + os << "\t\t" << cmCTest::MakeXMLSafe( + m_CTest->GetShortPathToFile(testPath.c_str())) + << "" << std::endl; + } + os << "\t\n"; + std::cout << "-- Processing memory checking output: "; + unsigned int total = m_TestResults.size(); + unsigned int step = total / 10; + unsigned int current = 0; + for ( cc = 0; cc < m_TestResults.size(); cc ++ ) + { + cmCTestTestResult *result = &m_TestResults[cc]; + std::string memcheckstr; + int memcheckresults[cmCTestMemCheckHandler::NO_MEMORY_FAULT]; + int kk; + bool res = this->ProcessMemCheckOutput(result->m_Output, memcheckstr, memcheckresults); + if ( res && result->m_Status == cmCTestMemCheckHandler::COMPLETED ) + { + continue; + } + os << "\tm_Status == cmCTestMemCheckHandler::COMPLETED ) + { + os << "passed"; + } + else if ( result->m_Status == cmCTestMemCheckHandler::NOT_RUN ) + { + os << "notrun"; + } + else + { + os << "failed"; + } + std::string testPath = result->m_Path + "/" + result->m_Name; + os << "\">\n" + << "\t\t" << cmCTest::MakeXMLSafe(result->m_Name) << "\n" + << "\t\t" << cmCTest::MakeXMLSafe( + m_CTest->GetShortPathToFile(result->m_Path.c_str())) << "\n" + << "\t\t" << cmCTest::MakeXMLSafe( + m_CTest->GetShortPathToFile(testPath.c_str())) << "\n" + << "\t\t" + << cmCTest::MakeXMLSafe(result->m_FullCommandLine) + << "\n" + << "\t\t" << std::endl; + for ( kk = 0; cmCTestMemCheckResultLongStrings[kk]; kk ++ ) + { + if ( memcheckresults[kk] ) + { + os << "\t\t\t" + << memcheckresults[kk] + << "" << std::endl; + } + m_MemoryTesterGlobalResults[kk] += memcheckresults[kk]; + } + os + << "\t\t\n" + << "\t\n" << memcheckstr << std::endl + << "\t\n" + << "\t" << std::endl; + if ( current < cc ) + { + std::cout << "#"; + std::cout.flush(); + current += step; + } + } + std::cout << std::endl; + std::cerr << "Memory checking results:" << std::endl; + os << "\t" << std::endl; + for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ ) + { + if ( m_MemoryTesterGlobalResults[cc] ) + { + std::cerr.width(35); + std::cerr << cmCTestMemCheckResultLongStrings[cc] << " - " + << m_MemoryTesterGlobalResults[cc] << std::endl; + os << "\t\t" << std::endl; + } + } + os << "\t" << std::endl; + + os << "\t" << m_EndTest << "" << std::endl; + os << "" + << static_cast(m_ElapsedTestingTime/6)/10.0 + << "\n"; + + os << "" << std::endl; + m_CTest->EndXML(os); + + +} + +//---------------------------------------------------------------------- +bool cmCTestMemCheckHandler::InitializeMemoryChecking() +{ + // Setup the command + if ( cmSystemTools::FileExists(m_CTest->GetDartConfiguration("MemoryCheckCommand").c_str()) ) + { + m_MemoryTester + = cmSystemTools::ConvertToOutputPath(m_CTest->GetDartConfiguration("MemoryCheckCommand").c_str()); + } + else if ( cmSystemTools::FileExists(m_CTest->GetDartConfiguration("PurifyCommand").c_str()) ) + { + m_MemoryTester + = cmSystemTools::ConvertToOutputPath(m_CTest->GetDartConfiguration("PurifyCommand").c_str()); + } + else if ( cmSystemTools::FileExists(m_CTest->GetDartConfiguration("ValgrindCommand").c_str()) ) + { + m_MemoryTester + = cmSystemTools::ConvertToOutputPath(m_CTest->GetDartConfiguration("ValgrindCommand").c_str()); + } + else + { + std::cerr << "Memory checker (MemoryCheckCommand) not set, or cannot find the specified program." + << std::endl; + return false; + } + + if ( m_MemoryTester[0] == '\"' && m_MemoryTester[m_MemoryTester.size()-1] == '\"' ) + { + m_MemoryTester = m_MemoryTester.substr(1, m_MemoryTester.size()-2); + } + + // Setup the options + if ( m_CTest->GetDartConfiguration("MemoryCheckCommandOptions").size() ) + { + m_MemoryTesterOptions = m_CTest->GetDartConfiguration("MemoryCheckCommandOptions"); + } + else if ( m_CTest->GetDartConfiguration("ValgrindCommandOptions").size() ) + { + m_MemoryTesterOptions = m_CTest->GetDartConfiguration("ValgrindCommandOptions"); + } + + m_MemoryTesterOutputFile = m_CTest->GetToplevelPath() + "/Testing/Temporary/MemoryChecker.log"; + m_MemoryTesterOutputFile = cmSystemTools::EscapeSpaces(m_MemoryTesterOutputFile.c_str()); + + if ( m_MemoryTester.find("valgrind") != std::string::npos ) + { + m_MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND; + if ( !m_MemoryTesterOptions.size() ) + { + m_MemoryTesterOptions = "-q --skin=memcheck --leak-check=yes --show-reachable=yes --workaround-gcc296-bugs=yes --num-callers=100"; + } + if ( m_CTest->GetDartConfiguration("MemoryCheckSuppressionFile").size() ) + { + if ( !cmSystemTools::FileExists(m_CTest->GetDartConfiguration("MemoryCheckSuppressionFile").c_str()) ) + { + std::cerr << "Cannot find memory checker suppression file: " + << m_CTest->GetDartConfiguration("MemoryCheckSuppressionFile").c_str() << std::endl; + return false; + } + m_MemoryTesterOptions += " --suppressions=" + cmSystemTools::EscapeSpaces(m_CTest->GetDartConfiguration("MemoryCheckSuppressionFile").c_str()) + ""; + } + } + else if ( m_MemoryTester.find("purify") != std::string::npos ) + { + m_MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY; +#ifdef _WIN32 + m_MemoryTesterOptions += " /SAVETEXTDATA=" + m_MemoryTesterOutputFile; +#else + m_MemoryTesterOptions += " -log-file=" + m_MemoryTesterOutputFile; +#endif + } + else if ( m_MemoryTester.find("boundschecker") != std::string::npos ) + { + m_MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER; + std::cerr << "Bounds checker not yet implemented" << std::endl; + return false; + } + else + { + std::cerr << "Do not understand memory checker: " << m_MemoryTester.c_str() << std::endl; + return false; + } + + m_MemoryTesterOptionsParsed = cmSystemTools::ParseArguments(m_MemoryTesterOptions.c_str()); + std::vector::size_type cc; + for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ ) + { + m_MemoryTesterGlobalResults[cc] = 0; + } + return true; +} + +//---------------------------------------------------------------------- +bool cmCTestMemCheckHandler::ProcessMemCheckOutput(const std::string& str, + std::string& log, int* results) +{ + std::string::size_type cc; + for ( cc = 0; cc < cmCTestMemCheckHandler::NO_MEMORY_FAULT; cc ++ ) + { + results[cc] = 0; + } + + if ( m_MemoryTesterStyle == cmCTestMemCheckHandler::VALGRIND ) + { + return this->ProcessMemCheckValgrindOutput(str, log, results); + } + else if ( m_MemoryTesterStyle == cmCTestMemCheckHandler::PURIFY ) + { + return this->ProcessMemCheckPurifyOutput(str, log, results); + } + else if ( m_MemoryTesterStyle == cmCTestMemCheckHandler::BOUNDS_CHECKER ) + { + log.append("\nMemory checking style used was: "); + log.append("Bounds Checker"); + } + else + { + log.append("\nMemory checking style used was: "); + log.append("None that I know"); + log = str; + } + + + return true; +} + +//---------------------------------------------------------------------- +bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput( + const std::string&, std::string& log, + int* results) +{ + if ( !cmSystemTools::FileExists(m_MemoryTesterOutputFile.c_str()) ) + { + log = "Cannot find Purify output file: " + m_MemoryTesterOutputFile; + std::cerr << log.c_str() << std::endl; + return false; + } + + std::ifstream ifs(m_MemoryTesterOutputFile.c_str()); + if ( !ifs ) + { + log = "Cannot read Purify output file: " + m_MemoryTesterOutputFile; + std::cerr << log.c_str() << std::endl; + return false; + } + + cmOStringStream ostr; + log = ""; + + cmsys::RegularExpression pfW("^\\[[WEI]\\] ([A-Z][A-Z][A-Z][A-Z]*): "); + + int defects = 0; + + std::string line; + while ( cmSystemTools::GetLineFromStream(ifs, line) ) + { + int failure = cmCTestMemCheckHandler::NO_MEMORY_FAULT; + if ( pfW.find(line) ) + { + int cc; + for ( cc = 0; cc < cmCTestMemCheckHandler::NO_MEMORY_FAULT; cc ++ ) + { + if ( pfW.match(1) == cmCTestMemCheckResultStrings[cc] ) + { + failure = cc; + break; + } + } + if ( cc == cmCTestMemCheckHandler::NO_MEMORY_FAULT ) + { + std::cerr<< "Unknown Purify memory fault: " << pfW.match(1) << std::endl; + ostr << "*** Unknown Purify memory fault: " << pfW.match(1) << std::endl; + } + } + if ( failure != NO_MEMORY_FAULT ) + { + ostr << "" << cmCTestMemCheckResultStrings[failure] << " "; + results[failure] ++; + defects ++; + } + ostr << cmCTest::MakeXMLSafe(line) << std::endl; + } + + log = ostr.str(); + if ( defects ) + { + return false; + } + return true; +} + +//---------------------------------------------------------------------- +bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( + const std::string& str, std::string& log, + int* results) +{ + std::vector lines; + cmSystemTools::Split(str.c_str(), lines); + + std::string::size_type cc; + + cmOStringStream ostr; + log = ""; + + int defects = 0; + + cmsys::RegularExpression valgrindLine("^==[0-9][0-9]*=="); + + cmsys::RegularExpression vgFIM( + "== .*Invalid free\\(\\) / delete / delete\\[\\]"); + cmsys::RegularExpression vgFMM( + "== .*Mismatched free\\(\\) / delete / delete \\[\\]"); + cmsys::RegularExpression vgMLK( + "== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are definitely lost" + " in loss record [0-9][0-9]* of [0-9]"); + cmsys::RegularExpression vgPAR( + "== .*Syscall param .* contains unaddressable byte\\(s\\)"); + cmsys::RegularExpression vgMPK1( + "== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are possibly lost in" + " loss record [0-9][0-9]* of [0-9]"); + cmsys::RegularExpression vgMPK2( + "== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are still reachable" + " in loss record [0-9][0-9]* of [0-9]"); + cmsys::RegularExpression vgUMC( + "== .*Conditional jump or move depends on uninitialised value\\(s\\)"); + cmsys::RegularExpression vgUMR1("== .*Use of uninitialised value of size [0-9][0-9]*"); + cmsys::RegularExpression vgUMR2("== .*Invalid read of size [0-9][0-9]*"); + cmsys::RegularExpression vgUMR3("== .*Jump to the invalid address "); + cmsys::RegularExpression vgUMR4( + "== .*Syscall param .* contains uninitialised or unaddressable byte\\(s\\)"); + cmsys::RegularExpression vgIPW("== .*Invalid write of size [0-9]"); + cmsys::RegularExpression vgABR("== .*pthread_mutex_unlock: mutex is locked by a different thread"); + + //double sttime = cmSystemTools::GetTime(); + //std::cout << "Start test: " << lines.size() << std::endl; + for ( cc = 0; cc < lines.size(); cc ++ ) + { + if ( valgrindLine.find(lines[cc]) ) + { + int failure = cmCTestMemCheckHandler::NO_MEMORY_FAULT; + if ( vgFIM.find(lines[cc]) ) { failure = cmCTestMemCheckHandler::FIM; } + else if ( vgFMM.find(lines[cc]) ) { failure = cmCTestMemCheckHandler::FMM; } + else if ( vgMLK.find(lines[cc]) ) { failure = cmCTestMemCheckHandler::MLK; } + else if ( vgPAR.find(lines[cc]) ) { failure = cmCTestMemCheckHandler::PAR; } + else if ( vgMPK1.find(lines[cc]) ){ failure = cmCTestMemCheckHandler::MPK; } + else if ( vgMPK2.find(lines[cc]) ){ failure = cmCTestMemCheckHandler::MPK; } + else if ( vgUMC.find(lines[cc]) ) { failure = cmCTestMemCheckHandler::UMC; } + else if ( vgUMR1.find(lines[cc]) ){ failure = cmCTestMemCheckHandler::UMR; } + else if ( vgUMR2.find(lines[cc]) ){ failure = cmCTestMemCheckHandler::UMR; } + else if ( vgUMR3.find(lines[cc]) ){ failure = cmCTestMemCheckHandler::UMR; } + else if ( vgUMR4.find(lines[cc]) ){ failure = cmCTestMemCheckHandler::UMR; } + else if ( vgIPW.find(lines[cc]) ) { failure = cmCTestMemCheckHandler::IPW; } + else if ( vgABR.find(lines[cc]) ) { failure = cmCTestMemCheckHandler::ABR; } + + if ( failure != cmCTestMemCheckHandler::NO_MEMORY_FAULT ) + { + ostr << "" << cmCTestMemCheckResultStrings[failure] << " "; + results[failure] ++; + defects ++; + } + ostr << cmCTest::MakeXMLSafe(lines[cc]) << std::endl; + } + } + //std::cout << "End test (elapsed: " << (cmSystemTools::GetTime() - sttime) << std::endl; + log = ostr.str(); + if ( defects ) + { + return false; + } + return true; +} diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h new file mode 100644 index 000000000..8ff6a3c7d --- /dev/null +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -0,0 +1,122 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef cmCTestMemCheckHandler_h +#define cmCTestMemCheckHandler_h + + +#include "cmCTestTestHandler.h" +#include "cmListFileCache.h" + +class cmMakefile; + +/** \class cmCTestMemCheckHandler + * \brief A class that handles ctest -S invocations + * + */ +class cmCTestMemCheckHandler : public cmCTestTestHandler +{ +public: + void PopulateCustomVectors(cmMakefile *mf); + + cmCTestMemCheckHandler(); + +protected: + virtual int PreProcessHandler(); + virtual int PostProcessHandler(); + virtual void GenerateTestCommand(std::vector& args); + +private: + + enum { // Memory checkers + UNKNOWN = 0, + VALGRIND, + PURIFY, + BOUNDS_CHECKER + }; + + enum { // Memory faults + ABR = 0, + ABW, + ABWL, + COR, + EXU, + FFM, + FIM, + FMM, + FMR, + FMW, + FUM, + IPR, + IPW, + MAF, + MLK, + MPK, + NPR, + ODS, + PAR, + PLK, + UMC, + UMR, + NO_MEMORY_FAULT + }; + + enum { // Program statuses + NOT_RUN = 0, + TIMEOUT, + SEGFAULT, + ILLEGAL, + INTERRUPT, + NUMERICAL, + OTHER_FAULT, + FAILED, + BAD_COMMAND, + COMPLETED + }; + + std::string m_MemoryTester; + std::vector m_MemoryTesterOptionsParsed; + std::string m_MemoryTesterOptions; + int m_MemoryTesterStyle; + std::string m_MemoryTesterOutputFile; + int m_MemoryTesterGlobalResults[NO_MEMORY_FAULT]; + + ///! Initialize memory checking subsystem. + bool InitializeMemoryChecking(); + + /** + * Generate the Dart compatible output + */ + void GenerateDartOutput(std::ostream& os); + + std::vector m_CustomPreMemCheck; + std::vector m_CustomPostMemCheck; + + //! Parse Valgrind/Purify/Bounds Checker result out of the output + //string. After running, log holds the output and results hold the + //different memmory errors. + bool ProcessMemCheckOutput(const std::string& str, + std::string& log, int* results); + bool ProcessMemCheckValgrindOutput(const std::string& str, + std::string& log, int* results); + bool ProcessMemCheckPurifyOutput(const std::string& str, + std::string& log, int* results); + +}; + +#endif + diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 458b02955..b91147c40 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -124,7 +124,7 @@ void cmCTestScriptHandler::AddConfigurationScript(const char *script) //---------------------------------------------------------------------- // the generic entry point for handling scripts, this routine will run all // the scripts provides a -S arguments -int cmCTestScriptHandler::RunConfigurationScript() +int cmCTestScriptHandler::ProcessHandler() { int res = 0; std::vector::iterator it; @@ -136,7 +136,11 @@ int cmCTestScriptHandler::RunConfigurationScript() res += this->RunConfigurationScript( cmSystemTools::CollapseFullPath(it->c_str())); } - return res; + if ( res ) + { + return -1; + } + return 0; } void cmCTestScriptHandler::UpdateElapsedTime() @@ -761,7 +765,7 @@ bool cmCTestScriptHandler::RunScript(cmCTest* ctest, const char *sname) cmCTestScriptHandler* sh = new cmCTestScriptHandler(); sh->SetCTestInstance(ctest); sh->AddConfigurationScript(sname); - sh->RunConfigurationScript(); + sh->ProcessHandler(); delete sh; return true; } diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h index 7dfb59caa..4d316cef1 100644 --- a/Source/CTest/cmCTestScriptHandler.h +++ b/Source/CTest/cmCTestScriptHandler.h @@ -70,11 +70,11 @@ public: * Add a script to run */ void AddConfigurationScript(const char *); - + /** * Run a dashboard using a specified confiuration script */ - int RunConfigurationScript(); + int ProcessHandler(); /* * Run a script diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 3766a1e39..dcc464590 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -29,59 +29,7 @@ #include #include -static const char* cmCTestMemCheckResultStrings[] = { - "ABR", - "ABW", - "ABWL", - "COR", - "EXU", - "FFM", - "FIM", - "FMM", - "FMR", - "FMW", - "FUM", - "IPR", - "IPW", - "MAF", - "MLK", - "MPK", - "NPR", - "ODS", - "PAR", - "PLK", - "UMC", - "UMR", - 0 -}; - -static const char* cmCTestMemCheckResultLongStrings[] = { - "Threading Problem", - "ABW", - "ABWL", - "COR", - "EXU", - "FFM", - "FIM", - "Mismatched deallocation", - "FMR", - "FMW", - "FUM", - "IPR", - "IPW", - "MAF", - "Memory Leak", - "Potential Memory Leak", - "NPR", - "ODS", - "Invalid syscall param", - "PLK", - "Uninitialized Memory Conditional", - "Uninitialized Memory Read", - 0 -}; - - +//---------------------------------------------------------------------- bool TryExecutable(const char *dir, const char *file, std::string *fullPath, const char *subdir) { @@ -114,6 +62,7 @@ bool TryExecutable(const char *dir, const char *file, return false; } +//---------------------------------------------------------------------- // get the next number in a string with numbers separated by , // pos is the start of the search and pos2 is the end of the search // pos becomes pos2 after a call to GetNextNumber. @@ -151,6 +100,7 @@ inline int GetNextNumber(std::string const& in, } } +//---------------------------------------------------------------------- // get the next number in a string with numbers separated by , // pos is the start of the search and pos2 is the end of the search // pos becomes pos2 after a call to GetNextNumber. @@ -200,6 +150,8 @@ cmCTestTestHandler::cmCTestTestHandler() m_CustomMaximumPassedTestOutputSize = 1 * 1024; m_CustomMaximumFailedTestOutputSize = 300 * 1024; + + m_MemCheck = false; } //---------------------------------------------------------------------- @@ -209,17 +161,9 @@ void cmCTestTestHandler::PopulateCustomVectors(cmMakefile *mf) m_CustomPreTest); cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_POST_TEST", m_CustomPostTest); - cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_PRE_MEMCHECK", - m_CustomPreMemCheck); - cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_POST_MEMCHECK", - m_CustomPostMemCheck); - cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_TESTS_IGNORE", m_CustomTestsIgnore); - cmCTest::PopulateCustomVector(mf, - "CTEST_CUSTOM_MEMCHECK_IGNORE", - m_CustomMemCheckIgnore); cmCTest::PopulateCustomInteger(mf, "CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE", m_CustomMaximumPassedTestOutputSize); @@ -228,44 +172,46 @@ void cmCTestTestHandler::PopulateCustomVectors(cmMakefile *mf) m_CustomMaximumFailedTestOutputSize); } +//---------------------------------------------------------------------- +int cmCTestTestHandler::PreProcessHandler() +{ + if ( !this->ExecuteCommands(m_CustomPreTest) ) + { + std::cerr << "Problem executing pre-test command(s)." << std::endl; + return 0; + } + return 1; +} + +//---------------------------------------------------------------------- +int cmCTestTestHandler::PostProcessHandler() +{ + if ( !this->ExecuteCommands(m_CustomPostTest) ) + { + std::cerr << "Problem executing post-test command(s)." << std::endl; + return 0; + } + return 1; +} //---------------------------------------------------------------------- //clearly it would be nice if this were broken up into a few smaller //functions and commented... -int cmCTestTestHandler::TestDirectory(bool memcheck) +int cmCTestTestHandler::ProcessHandler() { m_TestResults.clear(); - std::cout << (memcheck ? "Memory check" : "Test") << " project" << std::endl; - if ( memcheck ) - { - if ( !this->InitializeMemoryChecking() ) - { - return 1; - } - } - if ( memcheck ) + std::cout << (m_MemCheck ? "Memory check" : "Test") << " project" << std::endl; + if ( ! this->PreProcessHandler() ) { - if ( !this->ExecuteCommands(m_CustomPreMemCheck) ) - { - std::cerr << "Problem executing pre-memcheck command(s)." << std::endl; - return 1; - } - } - else - { - if ( !this->ExecuteCommands(m_CustomPreTest) ) - { - std::cerr << "Problem executing pre-test command(s)." << std::endl; - return 1; - } + return -1; } std::vector passed; std::vector failed; int total; - this->ProcessDirectory(passed, failed, memcheck); + this->ProcessDirectory(passed, failed); total = int(passed.size()) + int(failed.size()); @@ -323,57 +269,42 @@ int cmCTestTestHandler::TestDirectory(bool memcheck) { cmGeneratedFileStream xmlfile; if( !m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), - (memcheck ? "DynamicAnalysis.xml" : "Test.xml"), xmlfile, true) ) + (m_MemCheck ? "DynamicAnalysis.xml" : "Test.xml"), xmlfile, true) ) { - std::cerr << "Cannot create " << (memcheck ? "memory check" : "testing") + std::cerr << "Cannot create " << (m_MemCheck ? "memory check" : "testing") << " XML file" << std::endl; return 1; } - if ( memcheck ) - { - this->GenerateDartMemCheckOutput(xmlfile); - } - else - { - this->GenerateDartTestOutput(xmlfile); - } + this->GenerateDartOutput(xmlfile); } - if ( memcheck ) + if ( ! this->PostProcessHandler() ) { - if ( !this->ExecuteCommands(m_CustomPostMemCheck) ) - { - std::cerr << "Problem executing post-memcheck command(s)." << std::endl; - return 1; - } - } - else - { - if ( !this->ExecuteCommands(m_CustomPostTest) ) - { - std::cerr << "Problem executing post-test command(s)." << std::endl; - return 1; - } + return -1; } - return int(failed.size()); + if ( !failed.empty() ) + { + return -1; + } + return 0; } +//---------------------------------------------------------------------- void cmCTestTestHandler::ProcessDirectory(std::vector &passed, - std::vector &failed, - bool memcheck) + std::vector &failed) { std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory(); cmsys::RegularExpression dartStuff("()"); tm_ListOfTests testlist; - this->GetListOfTests(&testlist, memcheck); + this->GetListOfTests(&testlist); tm_ListOfTests::size_type tmsize = testlist.size(); cmGeneratedFileStream ofs; cmGeneratedFileStream *olog = 0; if ( !m_CTest->GetShowOnly() && tmsize > 0 && m_CTest->OpenOutputFile("Temporary", - (memcheck?"LastMemCheck.log":"LastTest.log"), ofs) ) + (m_MemCheck?"LastMemCheck.log":"LastTest.log"), ofs) ) { olog = &ofs; } @@ -479,7 +410,6 @@ void cmCTestTestHandler::ProcessDirectory(std::vector &passed, // find the test executable std::string actualCommand = this->FindTheExecutable(args[1].Value.c_str()); std::string testCommand = cmSystemTools::ConvertToOutputPath(actualCommand.c_str()); - std::string memcheckcommand = ""; // continue if we did not find the executable if (testCommand == "") @@ -500,18 +430,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector &passed, ++j; ++j; std::vector arguments; - if ( memcheck ) - { - std::vector::size_type pp; - arguments.push_back(m_MemoryTester.c_str()); - memcheckcommand = m_MemoryTester; - for ( pp = 0; pp < m_MemoryTesterOptionsParsed.size(); pp ++ ) - { - arguments.push_back(m_MemoryTesterOptionsParsed[pp].c_str()); - memcheckcommand += " "; - memcheckcommand += cmSystemTools::EscapeSpaces(m_MemoryTesterOptionsParsed[pp].c_str()); - } - } + this->GenerateTestCommand(arguments); arguments.push_back(actualCommand.c_str()); for(;j != args.end(); ++j) { @@ -530,11 +449,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector &passed, if ( m_Verbose ) { - std::cout << std::endl << (memcheck?"MemCheck":"Test") << " command: " << testCommand << std::endl; - if ( memcheck ) - { - std::cout << "Memory check command: " << memcheckcommand << std::endl; - } + std::cout << std::endl << (m_MemCheck?"MemCheck":"Test") << " command: " << testCommand << std::endl; } if ( olog ) { @@ -677,131 +592,13 @@ void cmCTestTestHandler::ProcessDirectory(std::vector &passed, cmSystemTools::ChangeDirectory(current_dir.c_str()); } -void cmCTestTestHandler::GenerateDartMemCheckOutput(std::ostream& os) +//---------------------------------------------------------------------- +void cmCTestTestHandler::GenerateTestCommand(std::vector&) { - if ( !m_CTest->GetProduceXML() ) - { - return; - } - - m_CTest->StartXML(os); - os << "" << std::endl; - - os << "\t" << m_StartTest << "\n" - << "\t\n"; - tm_TestResultsVector::size_type cc; - for ( cc = 0; cc < m_TestResults.size(); cc ++ ) - { - cmCTestTestResult *result = &m_TestResults[cc]; - std::string testPath = result->m_Path + "/" + result->m_Name; - os << "\t\t" << cmCTest::MakeXMLSafe( - m_CTest->GetShortPathToFile(testPath.c_str())) - << "" << std::endl; - } - os << "\t\n"; - std::cout << "-- Processing memory checking output: "; - unsigned int total = m_TestResults.size(); - unsigned int step = total / 10; - unsigned int current = 0; - for ( cc = 0; cc < m_TestResults.size(); cc ++ ) - { - cmCTestTestResult *result = &m_TestResults[cc]; - std::string memcheckstr; - int memcheckresults[cmCTestTestHandler::NO_MEMORY_FAULT]; - int kk; - bool res = this->ProcessMemCheckOutput(result->m_Output, memcheckstr, memcheckresults); - if ( res && result->m_Status == cmCTestTestHandler::COMPLETED ) - { - continue; - } - os << "\tm_Status == cmCTestTestHandler::COMPLETED ) - { - os << "passed"; - } - else if ( result->m_Status == cmCTestTestHandler::NOT_RUN ) - { - os << "notrun"; - } - else - { - os << "failed"; - } - std::string testPath = result->m_Path + "/" + result->m_Name; - os << "\">\n" - << "\t\t" << cmCTest::MakeXMLSafe(result->m_Name) << "\n" - << "\t\t" << cmCTest::MakeXMLSafe( - m_CTest->GetShortPathToFile(result->m_Path.c_str())) << "\n" - << "\t\t" << cmCTest::MakeXMLSafe( - m_CTest->GetShortPathToFile(testPath.c_str())) << "\n" - << "\t\t" - << cmCTest::MakeXMLSafe(result->m_FullCommandLine) - << "\n" - << "\t\t" << std::endl; - for ( kk = 0; cmCTestMemCheckResultLongStrings[kk]; kk ++ ) - { - if ( memcheckresults[kk] ) - { - os << "\t\t\t" - << memcheckresults[kk] - << "" << std::endl; - } - m_MemoryTesterGlobalResults[kk] += memcheckresults[kk]; - } - os - << "\t\t\n" - << "\t\n" << memcheckstr << std::endl - << "\t\n" - << "\t" << std::endl; - if ( current < cc ) - { - std::cout << "#"; - std::cout.flush(); - current += step; - } - } - std::cout << std::endl; - std::cerr << "Memory checking results:" << std::endl; - os << "\t" << std::endl; - for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ ) - { - if ( m_MemoryTesterGlobalResults[cc] ) - { - std::cerr.width(35); - std::cerr << cmCTestMemCheckResultLongStrings[cc] << " - " - << m_MemoryTesterGlobalResults[cc] << std::endl; - os << "\t\t" << std::endl; - } - } - os << "\t" << std::endl; - - os << "\t" << m_EndTest << "" << std::endl; - os << "" - << static_cast(m_ElapsedTestingTime/6)/10.0 - << "\n"; - - os << "" << std::endl; - m_CTest->EndXML(os); - - } -void cmCTestTestHandler::GenerateDartTestOutput(std::ostream& os) +//---------------------------------------------------------------------- +void cmCTestTestHandler::GenerateDartOutput(std::ostream& os) { if ( !m_CTest->GetProduceXML() ) { @@ -886,97 +683,7 @@ void cmCTestTestHandler::GenerateDartTestOutput(std::ostream& os) m_CTest->EndXML(os); } -bool cmCTestTestHandler::InitializeMemoryChecking() -{ - // Setup the command - if ( cmSystemTools::FileExists(m_CTest->GetDartConfiguration("MemoryCheckCommand").c_str()) ) - { - m_MemoryTester - = cmSystemTools::ConvertToOutputPath(m_CTest->GetDartConfiguration("MemoryCheckCommand").c_str()); - } - else if ( cmSystemTools::FileExists(m_CTest->GetDartConfiguration("PurifyCommand").c_str()) ) - { - m_MemoryTester - = cmSystemTools::ConvertToOutputPath(m_CTest->GetDartConfiguration("PurifyCommand").c_str()); - } - else if ( cmSystemTools::FileExists(m_CTest->GetDartConfiguration("ValgrindCommand").c_str()) ) - { - m_MemoryTester - = cmSystemTools::ConvertToOutputPath(m_CTest->GetDartConfiguration("ValgrindCommand").c_str()); - } - else - { - std::cerr << "Memory checker (MemoryCheckCommand) not set, or cannot find the specified program." - << std::endl; - return false; - } - - if ( m_MemoryTester[0] == '\"' && m_MemoryTester[m_MemoryTester.size()-1] == '\"' ) - { - m_MemoryTester = m_MemoryTester.substr(1, m_MemoryTester.size()-2); - } - - // Setup the options - if ( m_CTest->GetDartConfiguration("MemoryCheckCommandOptions").size() ) - { - m_MemoryTesterOptions = m_CTest->GetDartConfiguration("MemoryCheckCommandOptions"); - } - else if ( m_CTest->GetDartConfiguration("ValgrindCommandOptions").size() ) - { - m_MemoryTesterOptions = m_CTest->GetDartConfiguration("ValgrindCommandOptions"); - } - - m_MemoryTesterOutputFile = m_CTest->GetToplevelPath() + "/Testing/Temporary/MemoryChecker.log"; - m_MemoryTesterOutputFile = cmSystemTools::EscapeSpaces(m_MemoryTesterOutputFile.c_str()); - - if ( m_MemoryTester.find("valgrind") != std::string::npos ) - { - m_MemoryTesterStyle = cmCTestTestHandler::VALGRIND; - if ( !m_MemoryTesterOptions.size() ) - { - m_MemoryTesterOptions = "-q --skin=memcheck --leak-check=yes --show-reachable=yes --workaround-gcc296-bugs=yes --num-callers=100"; - } - if ( m_CTest->GetDartConfiguration("MemoryCheckSuppressionFile").size() ) - { - if ( !cmSystemTools::FileExists(m_CTest->GetDartConfiguration("MemoryCheckSuppressionFile").c_str()) ) - { - std::cerr << "Cannot find memory checker suppression file: " - << m_CTest->GetDartConfiguration("MemoryCheckSuppressionFile").c_str() << std::endl; - return false; - } - m_MemoryTesterOptions += " --suppressions=" + cmSystemTools::EscapeSpaces(m_CTest->GetDartConfiguration("MemoryCheckSuppressionFile").c_str()) + ""; - } - } - else if ( m_MemoryTester.find("purify") != std::string::npos ) - { - m_MemoryTesterStyle = cmCTestTestHandler::PURIFY; -#ifdef _WIN32 - m_MemoryTesterOptions += " /SAVETEXTDATA=" + m_MemoryTesterOutputFile; -#else - m_MemoryTesterOptions += " -log-file=" + m_MemoryTesterOutputFile; -#endif - } - else if ( m_MemoryTester.find("boundschecker") != std::string::npos ) - { - m_MemoryTesterStyle = cmCTestTestHandler::BOUNDS_CHECKER; - std::cerr << "Bounds checker not yet implemented" << std::endl; - return false; - } - else - { - std::cerr << "Do not understand memory checker: " << m_MemoryTester.c_str() << std::endl; - return false; - } - - m_MemoryTesterOptionsParsed = cmSystemTools::ParseArguments(m_MemoryTesterOptions.c_str()); - std::vector::size_type cc; - for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ ) - { - m_MemoryTesterGlobalResults[cc] = 0; - } - return true; -} - +//---------------------------------------------------------------------- int cmCTestTestHandler::ExecuteCommands(std::vector& vec) { std::vector::iterator it; @@ -998,6 +705,7 @@ int cmCTestTestHandler::ExecuteCommands(std::vector& vec) } +//---------------------------------------------------------------------- std::string cmCTestTestHandler::FindTheExecutable(const char *exe) { std::string fullPath = ""; @@ -1070,8 +778,8 @@ std::string cmCTestTestHandler::FindTheExecutable(const char *exe) } -void cmCTestTestHandler::GetListOfTests(tm_ListOfTests* testlist, - bool memcheck) +//---------------------------------------------------------------------- +void cmCTestTestHandler::GetListOfTests(tm_ListOfTests* testlist) { // does the DartTestfile.txt exist ? if(!cmSystemTools::FileExists("DartTestfile.txt")) @@ -1108,7 +816,7 @@ void cmCTestTestHandler::GetListOfTests(tm_ListOfTests* testlist, if (cmSystemTools::FileIsDirectory(nwd.c_str())) { cmSystemTools::ChangeDirectory(nwd.c_str()); - this->GetListOfTests(testlist, memcheck); + this->GetListOfTests(testlist); } } // return to the original directory @@ -1124,12 +832,12 @@ void cmCTestTestHandler::GetListOfTests(tm_ListOfTests* testlist, { continue; } - if ( memcheck ) + if ( m_MemCheck ) { std::vector::iterator it; bool found = false; - for ( it = m_CustomMemCheckIgnore.begin(); - it != m_CustomMemCheckIgnore.end(); ++ it ) + for ( it = m_CustomTestsIgnore.begin(); + it != m_CustomTestsIgnore.end(); ++ it ) { if ( *it == testname ) { @@ -1189,18 +897,20 @@ void cmCTestTestHandler::GetListOfTests(tm_ListOfTests* testlist, } } - +//---------------------------------------------------------------------- void cmCTestTestHandler::UseIncludeRegExp() { this->m_UseIncludeRegExp = true; } +//---------------------------------------------------------------------- void cmCTestTestHandler::UseExcludeRegExp() { this->m_UseExcludeRegExp = true; this->m_UseExcludeRegExpFirst = this->m_UseIncludeRegExp ? false : true; } +//---------------------------------------------------------------------- const char* cmCTestTestHandler::GetTestStatus(int status) { static const char statuses[][100] = { @@ -1224,6 +934,7 @@ const char* cmCTestTestHandler::GetTestStatus(int status) return statuses[status]; } +//---------------------------------------------------------------------- void cmCTestTestHandler::ExpandTestsToRunInformation(int numTests) { if (this->TestsToRunString.empty()) @@ -1293,8 +1004,10 @@ void cmCTestTestHandler::ExpandTestsToRunInformation(int numTests) m_TestsToRun.erase(new_end, m_TestsToRun.end()); } +//---------------------------------------------------------------------- +// Just for convenience #define SPACE_REGEX "[ \t\r\n]" - +//---------------------------------------------------------------------- std::string cmCTestTestHandler::GenerateRegressionImages( const std::string& xml) { @@ -1453,193 +1166,19 @@ std::string cmCTestTestHandler::GenerateRegressionImages( return ostr.str(); } -bool cmCTestTestHandler::ProcessMemCheckOutput(const std::string& str, - std::string& log, int* results) -{ - std::string::size_type cc; - for ( cc = 0; cc < cmCTestTestHandler::NO_MEMORY_FAULT; cc ++ ) - { - results[cc] = 0; - } - - if ( m_MemoryTesterStyle == cmCTestTestHandler::VALGRIND ) - { - return this->ProcessMemCheckValgrindOutput(str, log, results); - } - else if ( m_MemoryTesterStyle == cmCTestTestHandler::PURIFY ) - { - return this->ProcessMemCheckPurifyOutput(str, log, results); - } - else if ( m_MemoryTesterStyle == cmCTestTestHandler::BOUNDS_CHECKER ) - { - log.append("\nMemory checking style used was: "); - log.append("Bounds Checker"); - } - else - { - log.append("\nMemory checking style used was: "); - log.append("None that I know"); - log = str; - } - - - return true; -} - -bool cmCTestTestHandler::ProcessMemCheckPurifyOutput( - const std::string&, std::string& log, - int* results) -{ - if ( !cmSystemTools::FileExists(m_MemoryTesterOutputFile.c_str()) ) - { - log = "Cannot find Purify output file: " + m_MemoryTesterOutputFile; - std::cerr << log.c_str() << std::endl; - return false; - } - - std::ifstream ifs(m_MemoryTesterOutputFile.c_str()); - if ( !ifs ) - { - log = "Cannot read Purify output file: " + m_MemoryTesterOutputFile; - std::cerr << log.c_str() << std::endl; - return false; - } - - cmOStringStream ostr; - log = ""; - - cmsys::RegularExpression pfW("^\\[[WEI]\\] ([A-Z][A-Z][A-Z][A-Z]*): "); - - int defects = 0; - - std::string line; - while ( cmSystemTools::GetLineFromStream(ifs, line) ) - { - int failure = cmCTestTestHandler::NO_MEMORY_FAULT; - if ( pfW.find(line) ) - { - int cc; - for ( cc = 0; cc < cmCTestTestHandler::NO_MEMORY_FAULT; cc ++ ) - { - if ( pfW.match(1) == cmCTestMemCheckResultStrings[cc] ) - { - failure = cc; - break; - } - } - if ( cc == cmCTestTestHandler::NO_MEMORY_FAULT ) - { - std::cerr<< "Unknown Purify memory fault: " << pfW.match(1) << std::endl; - ostr << "*** Unknown Purify memory fault: " << pfW.match(1) << std::endl; - } - } - if ( failure != NO_MEMORY_FAULT ) - { - ostr << "" << cmCTestMemCheckResultStrings[failure] << " "; - results[failure] ++; - defects ++; - } - ostr << cmCTest::MakeXMLSafe(line) << std::endl; - } - - log = ostr.str(); - if ( defects ) - { - return false; - } - return true; -} - -bool cmCTestTestHandler::ProcessMemCheckValgrindOutput( - const std::string& str, std::string& log, - int* results) -{ - std::vector lines; - cmSystemTools::Split(str.c_str(), lines); - - std::string::size_type cc; - - cmOStringStream ostr; - log = ""; - - int defects = 0; - - cmsys::RegularExpression valgrindLine("^==[0-9][0-9]*=="); - - cmsys::RegularExpression vgFIM( - "== .*Invalid free\\(\\) / delete / delete\\[\\]"); - cmsys::RegularExpression vgFMM( - "== .*Mismatched free\\(\\) / delete / delete \\[\\]"); - cmsys::RegularExpression vgMLK( - "== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are definitely lost" - " in loss record [0-9][0-9]* of [0-9]"); - cmsys::RegularExpression vgPAR( - "== .*Syscall param .* contains unaddressable byte\\(s\\)"); - cmsys::RegularExpression vgMPK1( - "== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are possibly lost in" - " loss record [0-9][0-9]* of [0-9]"); - cmsys::RegularExpression vgMPK2( - "== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are still reachable" - " in loss record [0-9][0-9]* of [0-9]"); - cmsys::RegularExpression vgUMC( - "== .*Conditional jump or move depends on uninitialised value\\(s\\)"); - cmsys::RegularExpression vgUMR1("== .*Use of uninitialised value of size [0-9][0-9]*"); - cmsys::RegularExpression vgUMR2("== .*Invalid read of size [0-9][0-9]*"); - cmsys::RegularExpression vgUMR3("== .*Jump to the invalid address "); - cmsys::RegularExpression vgUMR4( - "== .*Syscall param .* contains uninitialised or unaddressable byte\\(s\\)"); - cmsys::RegularExpression vgIPW("== .*Invalid write of size [0-9]"); - cmsys::RegularExpression vgABR("== .*pthread_mutex_unlock: mutex is locked by a different thread"); - - //double sttime = cmSystemTools::GetTime(); - //std::cout << "Start test: " << lines.size() << std::endl; - for ( cc = 0; cc < lines.size(); cc ++ ) - { - if ( valgrindLine.find(lines[cc]) ) - { - int failure = cmCTestTestHandler::NO_MEMORY_FAULT; - if ( vgFIM.find(lines[cc]) ) { failure = cmCTestTestHandler::FIM; } - else if ( vgFMM.find(lines[cc]) ) { failure = cmCTestTestHandler::FMM; } - else if ( vgMLK.find(lines[cc]) ) { failure = cmCTestTestHandler::MLK; } - else if ( vgPAR.find(lines[cc]) ) { failure = cmCTestTestHandler::PAR; } - else if ( vgMPK1.find(lines[cc]) ){ failure = cmCTestTestHandler::MPK; } - else if ( vgMPK2.find(lines[cc]) ){ failure = cmCTestTestHandler::MPK; } - else if ( vgUMC.find(lines[cc]) ) { failure = cmCTestTestHandler::UMC; } - else if ( vgUMR1.find(lines[cc]) ){ failure = cmCTestTestHandler::UMR; } - else if ( vgUMR2.find(lines[cc]) ){ failure = cmCTestTestHandler::UMR; } - else if ( vgUMR3.find(lines[cc]) ){ failure = cmCTestTestHandler::UMR; } - else if ( vgUMR4.find(lines[cc]) ){ failure = cmCTestTestHandler::UMR; } - else if ( vgIPW.find(lines[cc]) ) { failure = cmCTestTestHandler::IPW; } - else if ( vgABR.find(lines[cc]) ) { failure = cmCTestTestHandler::ABR; } - - if ( failure != cmCTestTestHandler::NO_MEMORY_FAULT ) - { - ostr << "" << cmCTestMemCheckResultStrings[failure] << " "; - results[failure] ++; - defects ++; - } - ostr << cmCTest::MakeXMLSafe(lines[cc]) << std::endl; - } - } - //std::cout << "End test (elapsed: " << (cmSystemTools::GetTime() - sttime) << std::endl; - log = ostr.str(); - if ( defects ) - { - return false; - } - return true; -} - +//---------------------------------------------------------------------- void cmCTestTestHandler::SetIncludeRegExp(const char *arg) { m_IncludeRegExp = arg; } +//---------------------------------------------------------------------- void cmCTestTestHandler::SetExcludeRegExp(const char *arg) { m_ExcludeRegExp = arg; } +//---------------------------------------------------------------------- void cmCTestTestHandler::SetTestsToRunInformation(const char* in) { this->TestsToRunString = in; @@ -1655,6 +1194,7 @@ void cmCTestTestHandler::SetTestsToRunInformation(const char* in) } } +//---------------------------------------------------------------------- bool cmCTestTestHandler::CleanTestOutput(std::string& output, size_t remove_threshold) { if ( remove_threshold == 0 ) diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index e938a233d..e94413f6a 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -32,18 +32,21 @@ class cmCTestTestHandler : public cmCTestGenericHandler { public: - /* + /** * The main entry point for this class */ - int TestDirectory(bool memcheck); + int ProcessHandler(); - /* + /** * When both -R and -I are used should te resulting test list be the * intersection or the union of the lists. By default it is the * intersection. */ void SetUseUnion(bool val) { m_UseUnion = val; } + /** + * This method is called when reading CTest custom file + */ void PopulateCustomVectors(cmMakefile *mf); ///! Control the use of the regular expresisons, call these methods to turn @@ -53,69 +56,13 @@ public: void SetIncludeRegExp(const char *); void SetExcludeRegExp(const char *); - cmCTestTestHandler(); ///! pass the -I argument down void SetTestsToRunInformation(const char*); - typedef std::vector tm_VectorOfListFileArgs; - -private: + cmCTestTestHandler(); - enum { // Memory checkers - UNKNOWN = 0, - VALGRIND, - PURIFY, - BOUNDS_CHECKER - }; - - enum { // Memory faults - ABR = 0, - ABW, - ABWL, - COR, - EXU, - FFM, - FIM, - FMM, - FMR, - FMW, - FUM, - IPR, - IPW, - MAF, - MLK, - MPK, - NPR, - ODS, - PAR, - PLK, - UMC, - UMR, - NO_MEMORY_FAULT - }; - - enum { // Program statuses - NOT_RUN = 0, - TIMEOUT, - SEGFAULT, - ILLEGAL, - INTERRUPT, - NUMERICAL, - OTHER_FAULT, - FAILED, - BAD_COMMAND, - COMPLETED - }; - - std::string m_MemoryTester; - std::vector m_MemoryTesterOptionsParsed; - std::string m_MemoryTesterOptions; - int m_MemoryTesterStyle; - std::string m_MemoryTesterOutputFile; - int m_MemoryTesterGlobalResults[NO_MEMORY_FAULT]; - - +protected: struct cmCTestTestResult { std::string m_Name; @@ -130,26 +77,48 @@ private: int m_TestCount; }; + typedef std::vector tm_VectorOfListFileArgs; + + virtual int PreProcessHandler(); + virtual int PostProcessHandler(); + virtual void GenerateTestCommand(std::vector& args); + int ExecuteCommands(std::vector& vec); + + double m_ElapsedTestingTime; + typedef std::vector tm_TestResultsVector; tm_TestResultsVector m_TestResults; - int ExecuteCommands(std::vector& vec); + std::vector m_CustomTestsIgnore; + std::string m_StartTest; + std::string m_EndTest; + bool m_MemCheck; + +private: + enum { // Program statuses + NOT_RUN = 0, + TIMEOUT, + SEGFAULT, + ILLEGAL, + INTERRUPT, + NUMERICAL, + OTHER_FAULT, + FAILED, + BAD_COMMAND, + COMPLETED + }; - ///! Initialize memory checking subsystem. - bool InitializeMemoryChecking(); /** * Generate the Dart compatible output */ - void GenerateDartTestOutput(std::ostream& os); - void GenerateDartMemCheckOutput(std::ostream& os); + virtual void GenerateDartOutput(std::ostream& os); /** * Run the test for a directory and any subdirectories */ void ProcessDirectory(std::vector &passed, - std::vector &failed, - bool memcheck); + std::vector &failed); struct cmCTestTestProperties { @@ -163,7 +132,7 @@ private: /** * Get the list of tests in directory and subdirectories. */ - void GetListOfTests(tm_ListOfTests* testlist, bool memcheck); + void GetListOfTests(tm_ListOfTests* testlist); /** * Find the executable for a test @@ -175,17 +144,10 @@ private: std::vector m_CustomPreTest; std::vector m_CustomPostTest; - std::vector m_CustomPreMemCheck; - std::vector m_CustomPostMemCheck; - std::vector m_CustomTestsIgnore; - std::vector m_CustomMemCheckIgnore; int m_CustomMaximumPassedTestOutputSize; int m_CustomMaximumFailedTestOutputSize; - std::string m_StartTest; - std::string m_EndTest; - double m_ElapsedTestingTime; std::vector m_TestsToRun; bool m_UseIncludeRegExp; @@ -196,16 +158,6 @@ private: std::string GenerateRegressionImages(const std::string& xml); - //! Parse Valgrind/Purify/Bounds Checker result out of the output - //string. After running, log holds the output and results hold the - //different memmory errors. - bool ProcessMemCheckOutput(const std::string& str, - std::string& log, int* results); - bool ProcessMemCheckValgrindOutput(const std::string& str, - std::string& log, int* results); - bool ProcessMemCheckPurifyOutput(const std::string& str, - std::string& log, int* results); - //! Clean test output to specified length bool CleanTestOutput(std::string& output, size_t length); diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index 5054e045b..9a4ae632e 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -49,7 +49,7 @@ cmCTestUpdateHandler::cmCTestUpdateHandler() //---------------------------------------------------------------------- //clearly it would be nice if this were broken up into a few smaller //functions and commented... -int cmCTestUpdateHandler::UpdateDirectory() +int cmCTestUpdateHandler::ProcessHandler() { int count = 0; std::string::size_type cc, kk; diff --git a/Source/CTest/cmCTestUpdateHandler.h b/Source/CTest/cmCTestUpdateHandler.h index 3528edaae..c8bb304bb 100644 --- a/Source/CTest/cmCTestUpdateHandler.h +++ b/Source/CTest/cmCTestUpdateHandler.h @@ -33,7 +33,7 @@ public: /* * The main entry point for this class */ - int UpdateDirectory(); + int ProcessHandler(); cmCTestUpdateHandler(); diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 41d5d8970..7a62cfea2 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -27,11 +27,12 @@ #include "cmGeneratedFileStream.h" #include "cmCTestBuildHandler.h" +#include "cmCTestConfigureHandler.h" #include "cmCTestCoverageHandler.h" +#include "cmCTestMemCheckHandler.h" #include "cmCTestScriptHandler.h" #include "cmCTestTestHandler.h" #include "cmCTestUpdateHandler.h" -#include "cmCTestConfigureHandler.h" #include "cmCTestSubmit.h" #include "cmVersion.h" @@ -240,29 +241,29 @@ cmCTest::cmCTest() } m_ShortDateFormat = true; - this->BuildHandler = new cmCTestBuildHandler; - this->CoverageHandler = new cmCTestCoverageHandler; - this->ScriptHandler = new cmCTestScriptHandler; - this->TestHandler = new cmCTestTestHandler; - this->UpdateHandler = new cmCTestUpdateHandler; - this->ConfigureHandler = new cmCTestConfigureHandler; + m_TestingHandlers["build"] = new cmCTestBuildHandler; + m_TestingHandlers["coverage"] = new cmCTestCoverageHandler; + m_TestingHandlers["script"] = new cmCTestScriptHandler; + m_TestingHandlers["test"] = new cmCTestTestHandler; + m_TestingHandlers["update"] = new cmCTestUpdateHandler; + m_TestingHandlers["configure"] = new cmCTestConfigureHandler; + m_TestingHandlers["memcheck"] = new cmCTestMemCheckHandler; - this->BuildHandler->SetCTestInstance(this); - this->CoverageHandler->SetCTestInstance(this); - this->ScriptHandler->SetCTestInstance(this); - this->TestHandler->SetCTestInstance(this); - this->UpdateHandler->SetCTestInstance(this); - this->ConfigureHandler->SetCTestInstance(this); + cmCTest::t_TestingHandlers::iterator it; + for ( it = m_TestingHandlers.begin(); it != m_TestingHandlers.end(); ++ it ) + { + it->second->SetCTestInstance(this); + } } cmCTest::~cmCTest() { - delete this->BuildHandler; - delete this->CoverageHandler; - delete this->ScriptHandler; - delete this->TestHandler; - delete this->UpdateHandler; - delete this->ConfigureHandler; + cmCTest::t_TestingHandlers::iterator it; + for ( it = m_TestingHandlers.begin(); it != m_TestingHandlers.end(); ++ it ) + { + delete it->second; + it->second = 0; + } } int cmCTest::Initialize() @@ -727,7 +728,7 @@ int cmCTest::ProcessTests() } if ( m_Tests[UPDATE_TEST] || m_Tests[ALL_TEST] ) { - update_count = this->UpdateHandler->UpdateDirectory(); + update_count = m_TestingHandlers["update"]->ProcessHandler(); if ( update_count < 0 ) { res |= cmCTest::UPDATE_ERRORS; @@ -739,7 +740,7 @@ int cmCTest::ProcessTests() } if ( m_Tests[CONFIGURE_TEST] || m_Tests[ALL_TEST] ) { - if (this->ConfigureHandler->ConfigureDirectory()) + if (m_TestingHandlers["configure"]->ProcessHandler() < 0) { res |= cmCTest::CONFIGURE_ERRORS; } @@ -747,7 +748,7 @@ int cmCTest::ProcessTests() if ( m_Tests[BUILD_TEST] || m_Tests[ALL_TEST] ) { this->UpdateCTestConfiguration(); - if (this->BuildHandler->BuildDirectory()) + if (m_TestingHandlers["build"]->ProcessHandler() < 0) { res |= cmCTest::BUILD_ERRORS; } @@ -755,7 +756,7 @@ int cmCTest::ProcessTests() if ( m_Tests[TEST_TEST] || m_Tests[ALL_TEST] || notest ) { this->UpdateCTestConfiguration(); - if (this->TestHandler->TestDirectory(false)) + if (m_TestingHandlers["test"]->ProcessHandler() < 0) { res |= cmCTest::TEST_ERRORS; } @@ -763,7 +764,7 @@ int cmCTest::ProcessTests() if ( m_Tests[COVERAGE_TEST] || m_Tests[ALL_TEST] ) { this->UpdateCTestConfiguration(); - if (this->CoverageHandler->CoverageDirectory()) + if (m_TestingHandlers["coverage"]->ProcessHandler() < 0) { res |= cmCTest::COVERAGE_ERRORS; } @@ -771,7 +772,7 @@ int cmCTest::ProcessTests() if ( m_Tests[MEMCHECK_TEST] || m_Tests[ALL_TEST] ) { this->UpdateCTestConfiguration(); - if (this->TestHandler->TestDirectory(true)) + if (m_TestingHandlers["memcheck"]->ProcessHandler() < 0) { res |= cmCTest::MEMORY_ERRORS; } @@ -1181,12 +1182,11 @@ int cmCTest::Run(std::vectorconst& args, std::string* output) if( arg.find("-V",0) == 0 || arg.find("--verbose",0) == 0 ) { this->m_Verbose = true; - this->BuildHandler->SetVerbose(this->m_Verbose); - this->ConfigureHandler->SetVerbose(this->m_Verbose); - this->CoverageHandler->SetVerbose(this->m_Verbose); - this->ScriptHandler->SetVerbose(this->m_Verbose); - this->TestHandler->SetVerbose(this->m_Verbose); - this->UpdateHandler->SetVerbose(this->m_Verbose); + cmCTest::t_TestingHandlers::iterator it; + for ( it = m_TestingHandlers.begin(); it != m_TestingHandlers.end(); ++ it ) + { + it->second->SetVerbose(this->m_Verbose); + } } if( arg.find("-N",0) == 0 || arg.find("--show-only",0) == 0 ) @@ -1198,7 +1198,8 @@ int cmCTest::Run(std::vectorconst& args, std::string* output) { this->m_RunConfigurationScript = true; i++; - this->ScriptHandler->AddConfigurationScript(args[i].c_str()); + cmCTestScriptHandler* ch = static_cast(m_TestingHandlers["script"]); + ch->AddConfigurationScript(args[i].c_str()); } if( arg.find("--tomorrow-tag",0) == 0 ) @@ -1468,24 +1469,28 @@ int cmCTest::Run(std::vectorconst& args, std::string* output) if(arg.find("-I",0) == 0 && i < args.size() - 1) { i++; - this->TestHandler->SetTestsToRunInformation(args[i].c_str()); - } - if(arg.find("-U",0) == 0) - { - this->TestHandler->SetUseUnion(true); - } - if(arg.find("-R",0) == 0 && i < args.size() - 1) - { - this->TestHandler->UseIncludeRegExp(); + cmCTestTestHandler* th = static_cast(m_TestingHandlers["test"]); + th->SetTestsToRunInformation(args[i].c_str()); + } + if(arg.find("-U",0) == 0) + { + cmCTestTestHandler* th = static_cast(m_TestingHandlers["test"]); + th->SetUseUnion(true); + } + if(arg.find("-R",0) == 0 && i < args.size() - 1) + { + cmCTestTestHandler* th = static_cast(m_TestingHandlers["test"]); + th->UseIncludeRegExp(); + i++; + th->SetIncludeRegExp(args[i].c_str()); + } + + if(arg.find("-E",0) == 0 && i < args.size() - 1) + { + cmCTestTestHandler* th = static_cast(m_TestingHandlers["test"]); + th->UseExcludeRegExp(); i++; - this->TestHandler->SetIncludeRegExp(args[i].c_str()); - } - - if(arg.find("-E",0) == 0 && i < args.size() - 1) - { - this->TestHandler->UseExcludeRegExp(); - i++; - this->TestHandler->SetExcludeRegExp(args[i].c_str()); + th->SetExcludeRegExp(args[i].c_str()); } if(arg.find("-A",0) == 0 && i < args.size() - 1) @@ -1607,7 +1612,7 @@ int cmCTest::Run(std::vectorconst& args, std::string* output) // call process directory if (this->m_RunConfigurationScript) { - res = this->ScriptHandler->RunConfigurationScript(); + res = m_TestingHandlers["script"]->ProcessHandler(); } else { @@ -2138,8 +2143,11 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir) dirs.insert(dirs.end(), ndirs.begin(), ndirs.end()); } - this->BuildHandler->PopulateCustomVectors(mf); - this->TestHandler->PopulateCustomVectors(mf); + cmCTest::t_TestingHandlers::iterator it; + for ( it = m_TestingHandlers.begin(); it != m_TestingHandlers.end(); ++ it ) + { + it->second->PopulateCustomVectors(mf); + } return 1; } diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 9df0b800e..adb8d9b2b 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -24,12 +24,7 @@ #include class cmMakefile; -class cmCTestBuildHandler; -class cmCTestConfigureHandler; -class cmCTestCoverageHandler; -class cmCTestScriptHandler; -class cmCTestTestHandler; -class cmCTestUpdateHandler; +class cmCTestGenericHandler; class cmGeneratedFileStream; class cmCTest @@ -194,12 +189,8 @@ public: private: // these are helper classes - cmCTestBuildHandler *BuildHandler; - cmCTestCoverageHandler *CoverageHandler; - cmCTestScriptHandler *ScriptHandler; - cmCTestTestHandler *TestHandler; - cmCTestUpdateHandler *UpdateHandler; - cmCTestConfigureHandler *ConfigureHandler; + typedef std::map t_TestingHandlers; + t_TestingHandlers m_TestingHandlers; bool m_ShowOnly;