ENH: Several cleanups and improvements

This commit is contained in:
Andy Cedilnik 2005-01-27 15:54:47 -05:00
parent d268431ac8
commit c22cc421e0
19 changed files with 886 additions and 704 deletions

View File

@ -149,6 +149,7 @@ SET(CMTEST_SRCS ctest.cxx cmCTest.cxx
CTest/cmCTestEmptyBinaryDirectoryCommand.cxx CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
CTest/cmCTestRunScriptCommand.cxx CTest/cmCTestRunScriptCommand.cxx
CTest/cmCTestSleepCommand.cxx CTest/cmCTestSleepCommand.cxx
CTest/cmCTestMemCheckHandler.cxx
) )
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/Source/CTest) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/Source/CTest)

View File

@ -192,20 +192,20 @@ void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile *mf)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
//clearly it would be nice if this were broken up into a few smaller //clearly it would be nice if this were broken up into a few smaller
//functions and commented... //functions and commented...
int cmCTestBuildHandler::BuildDirectory() int cmCTestBuildHandler::ProcessHandler()
{ {
std::cout << "Build project" << std::endl; std::cout << "Build project" << std::endl;
std::string makeCommand = m_CTest->GetDartConfiguration("MakeCommand"); std::string makeCommand = m_CTest->GetDartConfiguration("MakeCommand");
if ( makeCommand.size() == 0 ) if ( makeCommand.size() == 0 )
{ {
std::cerr << "Cannot find MakeCommand key in the DartConfiguration.tcl" << std::endl; std::cerr << "Cannot find MakeCommand key in the DartConfiguration.tcl" << std::endl;
return 1; return -1;
} }
std::string buildDirectory = m_CTest->GetDartConfiguration("BuildDirectory"); std::string buildDirectory = m_CTest->GetDartConfiguration("BuildDirectory");
if ( buildDirectory.size() == 0 ) if ( buildDirectory.size() == 0 )
{ {
std::cerr << "Cannot find BuildDirectory key in the DartConfiguration.tcl" << std::endl; std::cerr << "Cannot find BuildDirectory key in the DartConfiguration.tcl" << std::endl;
return 1; return -1;
} }
cmGeneratedFileStream ofs; cmGeneratedFileStream ofs;
@ -438,7 +438,7 @@ int cmCTestBuildHandler::BuildDirectory()
if( !m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), "Build.xml", xofs, true) ) if( !m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), "Build.xml", xofs, true) )
{ {
std::cerr << "Cannot create build XML file" << std::endl; std::cerr << "Cannot create build XML file" << std::endl;
return 1; return -1;
} }
this->GenerateDartBuildOutput(xofs, errorsWarnings, elapsed_build_time); this->GenerateDartBuildOutput(xofs, errorsWarnings, elapsed_build_time);
return 0; return 0;

View File

@ -37,7 +37,7 @@ public:
/* /*
* The main entry point for this class * The main entry point for this class
*/ */
int BuildDirectory(); int ProcessHandler();
cmCTestBuildHandler(); cmCTestBuildHandler();

View File

@ -34,7 +34,7 @@ cmCTestConfigureHandler::cmCTestConfigureHandler()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
//clearly it would be nice if this were broken up into a few smaller //clearly it would be nice if this were broken up into a few smaller
//functions and commented... //functions and commented...
int cmCTestConfigureHandler::ConfigureDirectory() int cmCTestConfigureHandler::ProcessHandler()
{ {
std::cout << "Configure project" << std::endl; std::cout << "Configure project" << std::endl;
std::string cCommand = m_CTest->GetDartConfiguration("ConfigureCommand"); 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::cerr << "Cannot find ConfigureCommand key in the DartConfiguration.tcl"
<< std::endl; << std::endl;
return 1; return -1;
} }
std::string buildDirectory = m_CTest->GetDartConfiguration("BuildDirectory"); std::string buildDirectory = m_CTest->GetDartConfiguration("BuildDirectory");
if ( buildDirectory.size() == 0 ) if ( buildDirectory.size() == 0 )
{ {
std::cerr << "Cannot find BuildDirectory key in the DartConfiguration.tcl" << std::endl; std::cerr << "Cannot find BuildDirectory key in the DartConfiguration.tcl" << std::endl;
return 1; return -1;
} }
double elapsed_time_start = cmSystemTools::GetTime(); double elapsed_time_start = cmSystemTools::GetTime();
@ -107,7 +107,7 @@ int cmCTestConfigureHandler::ConfigureDirectory()
if (! res || retVal ) if (! res || retVal )
{ {
std::cerr << "Error(s) when updating the project" << std::endl; std::cerr << "Error(s) when updating the project" << std::endl;
return 1; return -1;
} }
return 0; return 0;
} }

View File

@ -33,7 +33,7 @@ public:
/* /*
* The main entry point for this class * The main entry point for this class
*/ */
int ConfigureDirectory(); int ProcessHandler();
cmCTestConfigureHandler(); cmCTestConfigureHandler();
}; };

View File

@ -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 //clearly it would be nice if this were broken up into a few smaller
//functions and commented... //functions and commented...
int cmCTestCoverageHandler::CoverageDirectory() int cmCTestCoverageHandler::ProcessHandler()
{ {
int error = 0; int error = 0;
@ -330,7 +330,7 @@ int cmCTestCoverageHandler::CoverageDirectory()
"Coverage.xml", covSumFile, true)) "Coverage.xml", covSumFile, true))
{ {
std::cerr << "Cannot open coverage summary file: Coverage.xml" << std::endl; std::cerr << "Cannot open coverage summary file: Coverage.xml" << std::endl;
return 1; return -1;
} }
m_CTest->StartXML(covSumFile); m_CTest->StartXML(covSumFile);
@ -341,7 +341,7 @@ int cmCTestCoverageHandler::CoverageDirectory()
int logFileCount = 0; int logFileCount = 0;
if ( !this->StartLogFile(covLogFile, logFileCount) ) if ( !this->StartLogFile(covLogFile, logFileCount) )
{ {
return 1; return -1;
} }
totalCoverageMap::iterator fileIterator; totalCoverageMap::iterator fileIterator;
int cnt = 0; int cnt = 0;
@ -360,7 +360,7 @@ int cmCTestCoverageHandler::CoverageDirectory()
logFileCount ++; logFileCount ++;
if ( !this->StartLogFile(covLogFile, logFileCount) ) if ( !this->StartLogFile(covLogFile, logFileCount) )
{ {
return 1; return -1;
} }
} }
const std::string fullFileName = fileIterator->first; const std::string fullFileName = fileIterator->first;
@ -503,5 +503,9 @@ int cmCTestCoverageHandler::CoverageDirectory()
cmSystemTools::ChangeDirectory(currentDirectory.c_str()); cmSystemTools::ChangeDirectory(currentDirectory.c_str());
return error; if ( error )
{
return -1;
}
return 0;
} }

View File

@ -35,7 +35,7 @@ public:
/* /*
* The main entry point for this class * The main entry point for this class
*/ */
int CoverageDirectory(); int ProcessHandler();
cmCTestCoverageHandler(); cmCTestCoverageHandler();

View File

@ -23,3 +23,8 @@ cmCTestGenericHandler::cmCTestGenericHandler()
m_CTest = 0; m_CTest = 0;
} }
cmCTestGenericHandler::~cmCTestGenericHandler()
{
}

View File

@ -39,7 +39,13 @@ public:
/** /**
* Populate internals from CTest custom scripts * 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 * Set the CTest instance
@ -50,6 +56,7 @@ public:
* Construct handler * Construct handler
*/ */
cmCTestGenericHandler(); cmCTestGenericHandler();
virtual ~cmCTestGenericHandler();
protected: protected:
bool m_Verbose; bool m_Verbose;

View File

@ -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 <cmsys/Process.h>
#include <cmsys/RegularExpression.hxx>
#include <cmsys/Base64.h>
#include "cmMakefile.h"
#include <stdlib.h>
#include <math.h>
#include <float.h>
//----------------------------------------------------------------------
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<const char*>& args)
{
std::vector<cmStdString>::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 << "<DynamicAnalysis Checker=\"";
switch ( m_MemoryTesterStyle )
{
case cmCTestMemCheckHandler::VALGRIND:
os << "Valgrind";
break;
case cmCTestMemCheckHandler::PURIFY:
os << "Purify";
break;
case cmCTestMemCheckHandler::BOUNDS_CHECKER:
os << "BoundsChecker";
break;
default:
os << "Unknown";
}
os << "\">" << std::endl;
os << "\t<StartDateTime>" << m_StartTest << "</StartDateTime>\n"
<< "\t<TestList>\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<Test>" << cmCTest::MakeXMLSafe(
m_CTest->GetShortPathToFile(testPath.c_str()))
<< "</Test>" << std::endl;
}
os << "\t</TestList>\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 << "\t<Test Status=\"";
if ( result->m_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<Name>" << cmCTest::MakeXMLSafe(result->m_Name) << "</Name>\n"
<< "\t\t<Path>" << cmCTest::MakeXMLSafe(
m_CTest->GetShortPathToFile(result->m_Path.c_str())) << "</Path>\n"
<< "\t\t<FullName>" << cmCTest::MakeXMLSafe(
m_CTest->GetShortPathToFile(testPath.c_str())) << "</FullName>\n"
<< "\t\t<FullCommandLine>"
<< cmCTest::MakeXMLSafe(result->m_FullCommandLine)
<< "</FullCommandLine>\n"
<< "\t\t<Results>" << std::endl;
for ( kk = 0; cmCTestMemCheckResultLongStrings[kk]; kk ++ )
{
if ( memcheckresults[kk] )
{
os << "\t\t\t<Defect type=\"" << cmCTestMemCheckResultLongStrings[kk] << "\">"
<< memcheckresults[kk]
<< "</Defect>" << std::endl;
}
m_MemoryTesterGlobalResults[kk] += memcheckresults[kk];
}
os
<< "\t\t</Results>\n"
<< "\t<Log>\n" << memcheckstr << std::endl
<< "\t</Log>\n"
<< "\t</Test>" << 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<DefectList>" << 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<Defect Type=\"" << cmCTestMemCheckResultLongStrings[cc] << "\"/>" << std::endl;
}
}
os << "\t</DefectList>" << std::endl;
os << "\t<EndDateTime>" << m_EndTest << "</EndDateTime>" << std::endl;
os << "<ElapsedMinutes>"
<< static_cast<int>(m_ElapsedTestingTime/6)/10.0
<< "</ElapsedMinutes>\n";
os << "</DynamicAnalysis>" << 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<cmStdString>::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 << "<b>" << cmCTestMemCheckResultStrings[failure] << "</b> ";
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<cmStdString> 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 << "<b>" << cmCTestMemCheckResultStrings[failure] << "</b> ";
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;
}

View File

@ -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<const char*>& 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<cmStdString> 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<cmStdString> m_CustomPreMemCheck;
std::vector<cmStdString> 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

View File

@ -124,7 +124,7 @@ void cmCTestScriptHandler::AddConfigurationScript(const char *script)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// the generic entry point for handling scripts, this routine will run all // the generic entry point for handling scripts, this routine will run all
// the scripts provides a -S arguments // the scripts provides a -S arguments
int cmCTestScriptHandler::RunConfigurationScript() int cmCTestScriptHandler::ProcessHandler()
{ {
int res = 0; int res = 0;
std::vector<cmStdString>::iterator it; std::vector<cmStdString>::iterator it;
@ -136,7 +136,11 @@ int cmCTestScriptHandler::RunConfigurationScript()
res += this->RunConfigurationScript( res += this->RunConfigurationScript(
cmSystemTools::CollapseFullPath(it->c_str())); cmSystemTools::CollapseFullPath(it->c_str()));
} }
return res; if ( res )
{
return -1;
}
return 0;
} }
void cmCTestScriptHandler::UpdateElapsedTime() void cmCTestScriptHandler::UpdateElapsedTime()
@ -761,7 +765,7 @@ bool cmCTestScriptHandler::RunScript(cmCTest* ctest, const char *sname)
cmCTestScriptHandler* sh = new cmCTestScriptHandler(); cmCTestScriptHandler* sh = new cmCTestScriptHandler();
sh->SetCTestInstance(ctest); sh->SetCTestInstance(ctest);
sh->AddConfigurationScript(sname); sh->AddConfigurationScript(sname);
sh->RunConfigurationScript(); sh->ProcessHandler();
delete sh; delete sh;
return true; return true;
} }

View File

@ -70,11 +70,11 @@ public:
* Add a script to run * Add a script to run
*/ */
void AddConfigurationScript(const char *); void AddConfigurationScript(const char *);
/** /**
* Run a dashboard using a specified confiuration script * Run a dashboard using a specified confiuration script
*/ */
int RunConfigurationScript(); int ProcessHandler();
/* /*
* Run a script * Run a script

View File

@ -29,59 +29,7 @@
#include <math.h> #include <math.h>
#include <float.h> #include <float.h>
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, bool TryExecutable(const char *dir, const char *file,
std::string *fullPath, const char *subdir) std::string *fullPath, const char *subdir)
{ {
@ -114,6 +62,7 @@ bool TryExecutable(const char *dir, const char *file,
return false; return false;
} }
//----------------------------------------------------------------------
// get the next number in a string with numbers separated by , // 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 is the start of the search and pos2 is the end of the search
// pos becomes pos2 after a call to GetNextNumber. // 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 , // 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 is the start of the search and pos2 is the end of the search
// pos becomes pos2 after a call to GetNextNumber. // pos becomes pos2 after a call to GetNextNumber.
@ -200,6 +150,8 @@ cmCTestTestHandler::cmCTestTestHandler()
m_CustomMaximumPassedTestOutputSize = 1 * 1024; m_CustomMaximumPassedTestOutputSize = 1 * 1024;
m_CustomMaximumFailedTestOutputSize = 300 * 1024; m_CustomMaximumFailedTestOutputSize = 300 * 1024;
m_MemCheck = false;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -209,17 +161,9 @@ void cmCTestTestHandler::PopulateCustomVectors(cmMakefile *mf)
m_CustomPreTest); m_CustomPreTest);
cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_POST_TEST", cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_POST_TEST",
m_CustomPostTest); m_CustomPostTest);
cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_PRE_MEMCHECK",
m_CustomPreMemCheck);
cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_POST_MEMCHECK",
m_CustomPostMemCheck);
cmCTest::PopulateCustomVector(mf, cmCTest::PopulateCustomVector(mf,
"CTEST_CUSTOM_TESTS_IGNORE", "CTEST_CUSTOM_TESTS_IGNORE",
m_CustomTestsIgnore); m_CustomTestsIgnore);
cmCTest::PopulateCustomVector(mf,
"CTEST_CUSTOM_MEMCHECK_IGNORE",
m_CustomMemCheckIgnore);
cmCTest::PopulateCustomInteger(mf, cmCTest::PopulateCustomInteger(mf,
"CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE", "CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE",
m_CustomMaximumPassedTestOutputSize); m_CustomMaximumPassedTestOutputSize);
@ -228,44 +172,46 @@ void cmCTestTestHandler::PopulateCustomVectors(cmMakefile *mf)
m_CustomMaximumFailedTestOutputSize); 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 //clearly it would be nice if this were broken up into a few smaller
//functions and commented... //functions and commented...
int cmCTestTestHandler::TestDirectory(bool memcheck) int cmCTestTestHandler::ProcessHandler()
{ {
m_TestResults.clear(); 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) ) return -1;
{
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;
}
} }
std::vector<cmStdString> passed; std::vector<cmStdString> passed;
std::vector<cmStdString> failed; std::vector<cmStdString> failed;
int total; int total;
this->ProcessDirectory(passed, failed, memcheck); this->ProcessDirectory(passed, failed);
total = int(passed.size()) + int(failed.size()); total = int(passed.size()) + int(failed.size());
@ -323,57 +269,42 @@ int cmCTestTestHandler::TestDirectory(bool memcheck)
{ {
cmGeneratedFileStream xmlfile; cmGeneratedFileStream xmlfile;
if( !m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), 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; << " XML file" << std::endl;
return 1; return 1;
} }
if ( memcheck ) this->GenerateDartOutput(xmlfile);
{
this->GenerateDartMemCheckOutput(xmlfile);
}
else
{
this->GenerateDartTestOutput(xmlfile);
}
} }
if ( memcheck ) if ( ! this->PostProcessHandler() )
{ {
if ( !this->ExecuteCommands(m_CustomPostMemCheck) ) return -1;
{
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 int(failed.size()); if ( !failed.empty() )
{
return -1;
}
return 0;
} }
//----------------------------------------------------------------------
void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed, void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
std::vector<cmStdString> &failed, std::vector<cmStdString> &failed)
bool memcheck)
{ {
std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory(); std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
cmsys::RegularExpression dartStuff("(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)"); cmsys::RegularExpression dartStuff("(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)");
tm_ListOfTests testlist; tm_ListOfTests testlist;
this->GetListOfTests(&testlist, memcheck); this->GetListOfTests(&testlist);
tm_ListOfTests::size_type tmsize = testlist.size(); tm_ListOfTests::size_type tmsize = testlist.size();
cmGeneratedFileStream ofs; cmGeneratedFileStream ofs;
cmGeneratedFileStream *olog = 0; cmGeneratedFileStream *olog = 0;
if ( !m_CTest->GetShowOnly() && tmsize > 0 && if ( !m_CTest->GetShowOnly() && tmsize > 0 &&
m_CTest->OpenOutputFile("Temporary", m_CTest->OpenOutputFile("Temporary",
(memcheck?"LastMemCheck.log":"LastTest.log"), ofs) ) (m_MemCheck?"LastMemCheck.log":"LastTest.log"), ofs) )
{ {
olog = &ofs; olog = &ofs;
} }
@ -479,7 +410,6 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
// find the test executable // find the test executable
std::string actualCommand = this->FindTheExecutable(args[1].Value.c_str()); std::string actualCommand = this->FindTheExecutable(args[1].Value.c_str());
std::string testCommand = cmSystemTools::ConvertToOutputPath(actualCommand.c_str()); std::string testCommand = cmSystemTools::ConvertToOutputPath(actualCommand.c_str());
std::string memcheckcommand = "";
// continue if we did not find the executable // continue if we did not find the executable
if (testCommand == "") if (testCommand == "")
@ -500,18 +430,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
++j; ++j;
++j; ++j;
std::vector<const char*> arguments; std::vector<const char*> arguments;
if ( memcheck ) this->GenerateTestCommand(arguments);
{
std::vector<cmStdString>::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());
}
}
arguments.push_back(actualCommand.c_str()); arguments.push_back(actualCommand.c_str());
for(;j != args.end(); ++j) for(;j != args.end(); ++j)
{ {
@ -530,11 +449,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
if ( m_Verbose ) if ( m_Verbose )
{ {
std::cout << std::endl << (memcheck?"MemCheck":"Test") << " command: " << testCommand << std::endl; std::cout << std::endl << (m_MemCheck?"MemCheck":"Test") << " command: " << testCommand << std::endl;
if ( memcheck )
{
std::cout << "Memory check command: " << memcheckcommand << std::endl;
}
} }
if ( olog ) if ( olog )
{ {
@ -677,131 +592,13 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
cmSystemTools::ChangeDirectory(current_dir.c_str()); cmSystemTools::ChangeDirectory(current_dir.c_str());
} }
void cmCTestTestHandler::GenerateDartMemCheckOutput(std::ostream& os) //----------------------------------------------------------------------
void cmCTestTestHandler::GenerateTestCommand(std::vector<const char*>&)
{ {
if ( !m_CTest->GetProduceXML() )
{
return;
}
m_CTest->StartXML(os);
os << "<DynamicAnalysis Checker=\"";
switch ( m_MemoryTesterStyle )
{
case cmCTestTestHandler::VALGRIND:
os << "Valgrind";
break;
case cmCTestTestHandler::PURIFY:
os << "Purify";
break;
case cmCTestTestHandler::BOUNDS_CHECKER:
os << "BoundsChecker";
break;
default:
os << "Unknown";
}
os << "\">" << std::endl;
os << "\t<StartDateTime>" << m_StartTest << "</StartDateTime>\n"
<< "\t<TestList>\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<Test>" << cmCTest::MakeXMLSafe(
m_CTest->GetShortPathToFile(testPath.c_str()))
<< "</Test>" << std::endl;
}
os << "\t</TestList>\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 << "\t<Test Status=\"";
if ( result->m_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<Name>" << cmCTest::MakeXMLSafe(result->m_Name) << "</Name>\n"
<< "\t\t<Path>" << cmCTest::MakeXMLSafe(
m_CTest->GetShortPathToFile(result->m_Path.c_str())) << "</Path>\n"
<< "\t\t<FullName>" << cmCTest::MakeXMLSafe(
m_CTest->GetShortPathToFile(testPath.c_str())) << "</FullName>\n"
<< "\t\t<FullCommandLine>"
<< cmCTest::MakeXMLSafe(result->m_FullCommandLine)
<< "</FullCommandLine>\n"
<< "\t\t<Results>" << std::endl;
for ( kk = 0; cmCTestMemCheckResultLongStrings[kk]; kk ++ )
{
if ( memcheckresults[kk] )
{
os << "\t\t\t<Defect type=\"" << cmCTestMemCheckResultLongStrings[kk] << "\">"
<< memcheckresults[kk]
<< "</Defect>" << std::endl;
}
m_MemoryTesterGlobalResults[kk] += memcheckresults[kk];
}
os
<< "\t\t</Results>\n"
<< "\t<Log>\n" << memcheckstr << std::endl
<< "\t</Log>\n"
<< "\t</Test>" << 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<DefectList>" << 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<Defect Type=\"" << cmCTestMemCheckResultLongStrings[cc] << "\"/>" << std::endl;
}
}
os << "\t</DefectList>" << std::endl;
os << "\t<EndDateTime>" << m_EndTest << "</EndDateTime>" << std::endl;
os << "<ElapsedMinutes>"
<< static_cast<int>(m_ElapsedTestingTime/6)/10.0
<< "</ElapsedMinutes>\n";
os << "</DynamicAnalysis>" << std::endl;
m_CTest->EndXML(os);
} }
void cmCTestTestHandler::GenerateDartTestOutput(std::ostream& os) //----------------------------------------------------------------------
void cmCTestTestHandler::GenerateDartOutput(std::ostream& os)
{ {
if ( !m_CTest->GetProduceXML() ) if ( !m_CTest->GetProduceXML() )
{ {
@ -886,97 +683,7 @@ void cmCTestTestHandler::GenerateDartTestOutput(std::ostream& os)
m_CTest->EndXML(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<cmStdString>::size_type cc;
for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ )
{
m_MemoryTesterGlobalResults[cc] = 0;
}
return true;
}
int cmCTestTestHandler::ExecuteCommands(std::vector<cmStdString>& vec) int cmCTestTestHandler::ExecuteCommands(std::vector<cmStdString>& vec)
{ {
std::vector<cmStdString>::iterator it; std::vector<cmStdString>::iterator it;
@ -998,6 +705,7 @@ int cmCTestTestHandler::ExecuteCommands(std::vector<cmStdString>& vec)
} }
//----------------------------------------------------------------------
std::string cmCTestTestHandler::FindTheExecutable(const char *exe) std::string cmCTestTestHandler::FindTheExecutable(const char *exe)
{ {
std::string fullPath = ""; 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 ? // does the DartTestfile.txt exist ?
if(!cmSystemTools::FileExists("DartTestfile.txt")) if(!cmSystemTools::FileExists("DartTestfile.txt"))
@ -1108,7 +816,7 @@ void cmCTestTestHandler::GetListOfTests(tm_ListOfTests* testlist,
if (cmSystemTools::FileIsDirectory(nwd.c_str())) if (cmSystemTools::FileIsDirectory(nwd.c_str()))
{ {
cmSystemTools::ChangeDirectory(nwd.c_str()); cmSystemTools::ChangeDirectory(nwd.c_str());
this->GetListOfTests(testlist, memcheck); this->GetListOfTests(testlist);
} }
} }
// return to the original directory // return to the original directory
@ -1124,12 +832,12 @@ void cmCTestTestHandler::GetListOfTests(tm_ListOfTests* testlist,
{ {
continue; continue;
} }
if ( memcheck ) if ( m_MemCheck )
{ {
std::vector<cmStdString>::iterator it; std::vector<cmStdString>::iterator it;
bool found = false; bool found = false;
for ( it = m_CustomMemCheckIgnore.begin(); for ( it = m_CustomTestsIgnore.begin();
it != m_CustomMemCheckIgnore.end(); ++ it ) it != m_CustomTestsIgnore.end(); ++ it )
{ {
if ( *it == testname ) if ( *it == testname )
{ {
@ -1189,18 +897,20 @@ void cmCTestTestHandler::GetListOfTests(tm_ListOfTests* testlist,
} }
} }
//----------------------------------------------------------------------
void cmCTestTestHandler::UseIncludeRegExp() void cmCTestTestHandler::UseIncludeRegExp()
{ {
this->m_UseIncludeRegExp = true; this->m_UseIncludeRegExp = true;
} }
//----------------------------------------------------------------------
void cmCTestTestHandler::UseExcludeRegExp() void cmCTestTestHandler::UseExcludeRegExp()
{ {
this->m_UseExcludeRegExp = true; this->m_UseExcludeRegExp = true;
this->m_UseExcludeRegExpFirst = this->m_UseIncludeRegExp ? false : true; this->m_UseExcludeRegExpFirst = this->m_UseIncludeRegExp ? false : true;
} }
//----------------------------------------------------------------------
const char* cmCTestTestHandler::GetTestStatus(int status) const char* cmCTestTestHandler::GetTestStatus(int status)
{ {
static const char statuses[][100] = { static const char statuses[][100] = {
@ -1224,6 +934,7 @@ const char* cmCTestTestHandler::GetTestStatus(int status)
return statuses[status]; return statuses[status];
} }
//----------------------------------------------------------------------
void cmCTestTestHandler::ExpandTestsToRunInformation(int numTests) void cmCTestTestHandler::ExpandTestsToRunInformation(int numTests)
{ {
if (this->TestsToRunString.empty()) if (this->TestsToRunString.empty())
@ -1293,8 +1004,10 @@ void cmCTestTestHandler::ExpandTestsToRunInformation(int numTests)
m_TestsToRun.erase(new_end, m_TestsToRun.end()); m_TestsToRun.erase(new_end, m_TestsToRun.end());
} }
//----------------------------------------------------------------------
// Just for convenience
#define SPACE_REGEX "[ \t\r\n]" #define SPACE_REGEX "[ \t\r\n]"
//----------------------------------------------------------------------
std::string cmCTestTestHandler::GenerateRegressionImages( std::string cmCTestTestHandler::GenerateRegressionImages(
const std::string& xml) const std::string& xml)
{ {
@ -1453,193 +1166,19 @@ std::string cmCTestTestHandler::GenerateRegressionImages(
return ostr.str(); 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 << "<b>" << cmCTestMemCheckResultStrings[failure] << "</b> ";
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<cmStdString> 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 << "<b>" << cmCTestMemCheckResultStrings[failure] << "</b> ";
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) void cmCTestTestHandler::SetIncludeRegExp(const char *arg)
{ {
m_IncludeRegExp = arg; m_IncludeRegExp = arg;
} }
//----------------------------------------------------------------------
void cmCTestTestHandler::SetExcludeRegExp(const char *arg) void cmCTestTestHandler::SetExcludeRegExp(const char *arg)
{ {
m_ExcludeRegExp = arg; m_ExcludeRegExp = arg;
} }
//----------------------------------------------------------------------
void cmCTestTestHandler::SetTestsToRunInformation(const char* in) void cmCTestTestHandler::SetTestsToRunInformation(const char* in)
{ {
this->TestsToRunString = in; this->TestsToRunString = in;
@ -1655,6 +1194,7 @@ void cmCTestTestHandler::SetTestsToRunInformation(const char* in)
} }
} }
//----------------------------------------------------------------------
bool cmCTestTestHandler::CleanTestOutput(std::string& output, size_t remove_threshold) bool cmCTestTestHandler::CleanTestOutput(std::string& output, size_t remove_threshold)
{ {
if ( remove_threshold == 0 ) if ( remove_threshold == 0 )

View File

@ -32,18 +32,21 @@ class cmCTestTestHandler : public cmCTestGenericHandler
{ {
public: public:
/* /**
* The main entry point for this class * 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 * 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 or the union of the lists. By default it is the
* intersection. * intersection.
*/ */
void SetUseUnion(bool val) { m_UseUnion = val; } void SetUseUnion(bool val) { m_UseUnion = val; }
/**
* This method is called when reading CTest custom file
*/
void PopulateCustomVectors(cmMakefile *mf); void PopulateCustomVectors(cmMakefile *mf);
///! Control the use of the regular expresisons, call these methods to turn ///! Control the use of the regular expresisons, call these methods to turn
@ -53,69 +56,13 @@ public:
void SetIncludeRegExp(const char *); void SetIncludeRegExp(const char *);
void SetExcludeRegExp(const char *); void SetExcludeRegExp(const char *);
cmCTestTestHandler();
///! pass the -I argument down ///! pass the -I argument down
void SetTestsToRunInformation(const char*); void SetTestsToRunInformation(const char*);
typedef std::vector<cmListFileArgument> tm_VectorOfListFileArgs; cmCTestTestHandler();
private:
enum { // Memory checkers protected:
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<cmStdString> m_MemoryTesterOptionsParsed;
std::string m_MemoryTesterOptions;
int m_MemoryTesterStyle;
std::string m_MemoryTesterOutputFile;
int m_MemoryTesterGlobalResults[NO_MEMORY_FAULT];
struct cmCTestTestResult struct cmCTestTestResult
{ {
std::string m_Name; std::string m_Name;
@ -130,26 +77,48 @@ private:
int m_TestCount; int m_TestCount;
}; };
typedef std::vector<cmListFileArgument> tm_VectorOfListFileArgs;
virtual int PreProcessHandler();
virtual int PostProcessHandler();
virtual void GenerateTestCommand(std::vector<const char*>& args);
int ExecuteCommands(std::vector<cmStdString>& vec);
double m_ElapsedTestingTime;
typedef std::vector<cmCTestTestResult> tm_TestResultsVector; typedef std::vector<cmCTestTestResult> tm_TestResultsVector;
tm_TestResultsVector m_TestResults; tm_TestResultsVector m_TestResults;
int ExecuteCommands(std::vector<cmStdString>& vec); std::vector<cmStdString> 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 * Generate the Dart compatible output
*/ */
void GenerateDartTestOutput(std::ostream& os); virtual void GenerateDartOutput(std::ostream& os);
void GenerateDartMemCheckOutput(std::ostream& os);
/** /**
* Run the test for a directory and any subdirectories * Run the test for a directory and any subdirectories
*/ */
void ProcessDirectory(std::vector<cmStdString> &passed, void ProcessDirectory(std::vector<cmStdString> &passed,
std::vector<cmStdString> &failed, std::vector<cmStdString> &failed);
bool memcheck);
struct cmCTestTestProperties struct cmCTestTestProperties
{ {
@ -163,7 +132,7 @@ private:
/** /**
* Get the list of tests in directory and subdirectories. * 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 * Find the executable for a test
@ -175,17 +144,10 @@ private:
std::vector<cmStdString> m_CustomPreTest; std::vector<cmStdString> m_CustomPreTest;
std::vector<cmStdString> m_CustomPostTest; std::vector<cmStdString> m_CustomPostTest;
std::vector<cmStdString> m_CustomPreMemCheck;
std::vector<cmStdString> m_CustomPostMemCheck;
std::vector<cmStdString> m_CustomTestsIgnore;
std::vector<cmStdString> m_CustomMemCheckIgnore;
int m_CustomMaximumPassedTestOutputSize; int m_CustomMaximumPassedTestOutputSize;
int m_CustomMaximumFailedTestOutputSize; int m_CustomMaximumFailedTestOutputSize;
std::string m_StartTest;
std::string m_EndTest;
double m_ElapsedTestingTime;
std::vector<int> m_TestsToRun; std::vector<int> m_TestsToRun;
bool m_UseIncludeRegExp; bool m_UseIncludeRegExp;
@ -196,16 +158,6 @@ private:
std::string GenerateRegressionImages(const std::string& xml); 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 //! Clean test output to specified length
bool CleanTestOutput(std::string& output, size_t length); bool CleanTestOutput(std::string& output, size_t length);

View File

@ -49,7 +49,7 @@ cmCTestUpdateHandler::cmCTestUpdateHandler()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
//clearly it would be nice if this were broken up into a few smaller //clearly it would be nice if this were broken up into a few smaller
//functions and commented... //functions and commented...
int cmCTestUpdateHandler::UpdateDirectory() int cmCTestUpdateHandler::ProcessHandler()
{ {
int count = 0; int count = 0;
std::string::size_type cc, kk; std::string::size_type cc, kk;

View File

@ -33,7 +33,7 @@ public:
/* /*
* The main entry point for this class * The main entry point for this class
*/ */
int UpdateDirectory(); int ProcessHandler();
cmCTestUpdateHandler(); cmCTestUpdateHandler();

View File

@ -27,11 +27,12 @@
#include "cmGeneratedFileStream.h" #include "cmGeneratedFileStream.h"
#include "cmCTestBuildHandler.h" #include "cmCTestBuildHandler.h"
#include "cmCTestConfigureHandler.h"
#include "cmCTestCoverageHandler.h" #include "cmCTestCoverageHandler.h"
#include "cmCTestMemCheckHandler.h"
#include "cmCTestScriptHandler.h" #include "cmCTestScriptHandler.h"
#include "cmCTestTestHandler.h" #include "cmCTestTestHandler.h"
#include "cmCTestUpdateHandler.h" #include "cmCTestUpdateHandler.h"
#include "cmCTestConfigureHandler.h"
#include "cmCTestSubmit.h" #include "cmCTestSubmit.h"
#include "cmVersion.h" #include "cmVersion.h"
@ -240,29 +241,29 @@ cmCTest::cmCTest()
} }
m_ShortDateFormat = true; m_ShortDateFormat = true;
this->BuildHandler = new cmCTestBuildHandler; m_TestingHandlers["build"] = new cmCTestBuildHandler;
this->CoverageHandler = new cmCTestCoverageHandler; m_TestingHandlers["coverage"] = new cmCTestCoverageHandler;
this->ScriptHandler = new cmCTestScriptHandler; m_TestingHandlers["script"] = new cmCTestScriptHandler;
this->TestHandler = new cmCTestTestHandler; m_TestingHandlers["test"] = new cmCTestTestHandler;
this->UpdateHandler = new cmCTestUpdateHandler; m_TestingHandlers["update"] = new cmCTestUpdateHandler;
this->ConfigureHandler = new cmCTestConfigureHandler; m_TestingHandlers["configure"] = new cmCTestConfigureHandler;
m_TestingHandlers["memcheck"] = new cmCTestMemCheckHandler;
this->BuildHandler->SetCTestInstance(this); cmCTest::t_TestingHandlers::iterator it;
this->CoverageHandler->SetCTestInstance(this); for ( it = m_TestingHandlers.begin(); it != m_TestingHandlers.end(); ++ it )
this->ScriptHandler->SetCTestInstance(this); {
this->TestHandler->SetCTestInstance(this); it->second->SetCTestInstance(this);
this->UpdateHandler->SetCTestInstance(this); }
this->ConfigureHandler->SetCTestInstance(this);
} }
cmCTest::~cmCTest() cmCTest::~cmCTest()
{ {
delete this->BuildHandler; cmCTest::t_TestingHandlers::iterator it;
delete this->CoverageHandler; for ( it = m_TestingHandlers.begin(); it != m_TestingHandlers.end(); ++ it )
delete this->ScriptHandler; {
delete this->TestHandler; delete it->second;
delete this->UpdateHandler; it->second = 0;
delete this->ConfigureHandler; }
} }
int cmCTest::Initialize() int cmCTest::Initialize()
@ -727,7 +728,7 @@ int cmCTest::ProcessTests()
} }
if ( m_Tests[UPDATE_TEST] || m_Tests[ALL_TEST] ) if ( m_Tests[UPDATE_TEST] || m_Tests[ALL_TEST] )
{ {
update_count = this->UpdateHandler->UpdateDirectory(); update_count = m_TestingHandlers["update"]->ProcessHandler();
if ( update_count < 0 ) if ( update_count < 0 )
{ {
res |= cmCTest::UPDATE_ERRORS; res |= cmCTest::UPDATE_ERRORS;
@ -739,7 +740,7 @@ int cmCTest::ProcessTests()
} }
if ( m_Tests[CONFIGURE_TEST] || m_Tests[ALL_TEST] ) if ( m_Tests[CONFIGURE_TEST] || m_Tests[ALL_TEST] )
{ {
if (this->ConfigureHandler->ConfigureDirectory()) if (m_TestingHandlers["configure"]->ProcessHandler() < 0)
{ {
res |= cmCTest::CONFIGURE_ERRORS; res |= cmCTest::CONFIGURE_ERRORS;
} }
@ -747,7 +748,7 @@ int cmCTest::ProcessTests()
if ( m_Tests[BUILD_TEST] || m_Tests[ALL_TEST] ) if ( m_Tests[BUILD_TEST] || m_Tests[ALL_TEST] )
{ {
this->UpdateCTestConfiguration(); this->UpdateCTestConfiguration();
if (this->BuildHandler->BuildDirectory()) if (m_TestingHandlers["build"]->ProcessHandler() < 0)
{ {
res |= cmCTest::BUILD_ERRORS; res |= cmCTest::BUILD_ERRORS;
} }
@ -755,7 +756,7 @@ int cmCTest::ProcessTests()
if ( m_Tests[TEST_TEST] || m_Tests[ALL_TEST] || notest ) if ( m_Tests[TEST_TEST] || m_Tests[ALL_TEST] || notest )
{ {
this->UpdateCTestConfiguration(); this->UpdateCTestConfiguration();
if (this->TestHandler->TestDirectory(false)) if (m_TestingHandlers["test"]->ProcessHandler() < 0)
{ {
res |= cmCTest::TEST_ERRORS; res |= cmCTest::TEST_ERRORS;
} }
@ -763,7 +764,7 @@ int cmCTest::ProcessTests()
if ( m_Tests[COVERAGE_TEST] || m_Tests[ALL_TEST] ) if ( m_Tests[COVERAGE_TEST] || m_Tests[ALL_TEST] )
{ {
this->UpdateCTestConfiguration(); this->UpdateCTestConfiguration();
if (this->CoverageHandler->CoverageDirectory()) if (m_TestingHandlers["coverage"]->ProcessHandler() < 0)
{ {
res |= cmCTest::COVERAGE_ERRORS; res |= cmCTest::COVERAGE_ERRORS;
} }
@ -771,7 +772,7 @@ int cmCTest::ProcessTests()
if ( m_Tests[MEMCHECK_TEST] || m_Tests[ALL_TEST] ) if ( m_Tests[MEMCHECK_TEST] || m_Tests[ALL_TEST] )
{ {
this->UpdateCTestConfiguration(); this->UpdateCTestConfiguration();
if (this->TestHandler->TestDirectory(true)) if (m_TestingHandlers["memcheck"]->ProcessHandler() < 0)
{ {
res |= cmCTest::MEMORY_ERRORS; res |= cmCTest::MEMORY_ERRORS;
} }
@ -1181,12 +1182,11 @@ int cmCTest::Run(std::vector<std::string>const& args, std::string* output)
if( arg.find("-V",0) == 0 || arg.find("--verbose",0) == 0 ) if( arg.find("-V",0) == 0 || arg.find("--verbose",0) == 0 )
{ {
this->m_Verbose = true; this->m_Verbose = true;
this->BuildHandler->SetVerbose(this->m_Verbose); cmCTest::t_TestingHandlers::iterator it;
this->ConfigureHandler->SetVerbose(this->m_Verbose); for ( it = m_TestingHandlers.begin(); it != m_TestingHandlers.end(); ++ it )
this->CoverageHandler->SetVerbose(this->m_Verbose); {
this->ScriptHandler->SetVerbose(this->m_Verbose); it->second->SetVerbose(this->m_Verbose);
this->TestHandler->SetVerbose(this->m_Verbose); }
this->UpdateHandler->SetVerbose(this->m_Verbose);
} }
if( arg.find("-N",0) == 0 || arg.find("--show-only",0) == 0 ) if( arg.find("-N",0) == 0 || arg.find("--show-only",0) == 0 )
@ -1198,7 +1198,8 @@ int cmCTest::Run(std::vector<std::string>const& args, std::string* output)
{ {
this->m_RunConfigurationScript = true; this->m_RunConfigurationScript = true;
i++; i++;
this->ScriptHandler->AddConfigurationScript(args[i].c_str()); cmCTestScriptHandler* ch = static_cast<cmCTestScriptHandler*>(m_TestingHandlers["script"]);
ch->AddConfigurationScript(args[i].c_str());
} }
if( arg.find("--tomorrow-tag",0) == 0 ) if( arg.find("--tomorrow-tag",0) == 0 )
@ -1468,24 +1469,28 @@ int cmCTest::Run(std::vector<std::string>const& args, std::string* output)
if(arg.find("-I",0) == 0 && i < args.size() - 1) if(arg.find("-I",0) == 0 && i < args.size() - 1)
{ {
i++; i++;
this->TestHandler->SetTestsToRunInformation(args[i].c_str()); cmCTestTestHandler* th = static_cast<cmCTestTestHandler*>(m_TestingHandlers["test"]);
} th->SetTestsToRunInformation(args[i].c_str());
if(arg.find("-U",0) == 0) }
{ if(arg.find("-U",0) == 0)
this->TestHandler->SetUseUnion(true); {
} cmCTestTestHandler* th = static_cast<cmCTestTestHandler*>(m_TestingHandlers["test"]);
if(arg.find("-R",0) == 0 && i < args.size() - 1) th->SetUseUnion(true);
{ }
this->TestHandler->UseIncludeRegExp(); if(arg.find("-R",0) == 0 && i < args.size() - 1)
{
cmCTestTestHandler* th = static_cast<cmCTestTestHandler*>(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<cmCTestTestHandler*>(m_TestingHandlers["test"]);
th->UseExcludeRegExp();
i++; i++;
this->TestHandler->SetIncludeRegExp(args[i].c_str()); th->SetExcludeRegExp(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());
} }
if(arg.find("-A",0) == 0 && i < args.size() - 1) if(arg.find("-A",0) == 0 && i < args.size() - 1)
@ -1607,7 +1612,7 @@ int cmCTest::Run(std::vector<std::string>const& args, std::string* output)
// call process directory // call process directory
if (this->m_RunConfigurationScript) if (this->m_RunConfigurationScript)
{ {
res = this->ScriptHandler->RunConfigurationScript(); res = m_TestingHandlers["script"]->ProcessHandler();
} }
else else
{ {
@ -2138,8 +2143,11 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir)
dirs.insert(dirs.end(), ndirs.begin(), ndirs.end()); dirs.insert(dirs.end(), ndirs.begin(), ndirs.end());
} }
this->BuildHandler->PopulateCustomVectors(mf); cmCTest::t_TestingHandlers::iterator it;
this->TestHandler->PopulateCustomVectors(mf); for ( it = m_TestingHandlers.begin(); it != m_TestingHandlers.end(); ++ it )
{
it->second->PopulateCustomVectors(mf);
}
return 1; return 1;
} }

View File

@ -24,12 +24,7 @@
#include <time.h> #include <time.h>
class cmMakefile; class cmMakefile;
class cmCTestBuildHandler; class cmCTestGenericHandler;
class cmCTestConfigureHandler;
class cmCTestCoverageHandler;
class cmCTestScriptHandler;
class cmCTestTestHandler;
class cmCTestUpdateHandler;
class cmGeneratedFileStream; class cmGeneratedFileStream;
class cmCTest class cmCTest
@ -194,12 +189,8 @@ public:
private: private:
// these are helper classes // these are helper classes
cmCTestBuildHandler *BuildHandler; typedef std::map<cmStdString,cmCTestGenericHandler*> t_TestingHandlers;
cmCTestCoverageHandler *CoverageHandler; t_TestingHandlers m_TestingHandlers;
cmCTestScriptHandler *ScriptHandler;
cmCTestTestHandler *TestHandler;
cmCTestUpdateHandler *UpdateHandler;
cmCTestConfigureHandler *ConfigureHandler;
bool m_ShowOnly; bool m_ShowOnly;