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/cmCTestRunScriptCommand.cxx
CTest/cmCTestSleepCommand.cxx
CTest/cmCTestMemCheckHandler.cxx
)
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
//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;

View File

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

View File

@ -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;
}

View File

@ -33,7 +33,7 @@ public:
/*
* The main entry point for this class
*/
int ConfigureDirectory();
int ProcessHandler();
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
//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;
}

View File

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

View File

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

View File

@ -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;

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 scripts provides a -S arguments
int cmCTestScriptHandler::RunConfigurationScript()
int cmCTestScriptHandler::ProcessHandler()
{
int res = 0;
std::vector<cmStdString>::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;
}

View File

@ -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

View File

@ -29,59 +29,7 @@
#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
};
//----------------------------------------------------------------------
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<cmStdString> passed;
std::vector<cmStdString> 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<cmStdString> &passed,
std::vector<cmStdString> &failed,
bool memcheck)
std::vector<cmStdString> &failed)
{
std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
cmsys::RegularExpression dartStuff("(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)");
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<cmStdString> &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<cmStdString> &passed,
++j;
++j;
std::vector<const char*> arguments;
if ( memcheck )
{
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());
}
}
this->GenerateTestCommand(arguments);
arguments.push_back(actualCommand.c_str());
for(;j != args.end(); ++j)
{
@ -530,11 +449,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &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<cmStdString> &passed,
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() )
{
@ -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<cmStdString>::size_type cc;
for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ )
{
m_MemoryTesterGlobalResults[cc] = 0;
}
return true;
}
//----------------------------------------------------------------------
int cmCTestTestHandler::ExecuteCommands(std::vector<cmStdString>& vec)
{
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 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<cmStdString>::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 << "<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)
{
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 )

View File

@ -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<cmListFileArgument> 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<cmStdString> 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<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;
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
*/
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<cmStdString> &passed,
std::vector<cmStdString> &failed,
bool memcheck);
std::vector<cmStdString> &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<cmStdString> m_CustomPreTest;
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_CustomMaximumFailedTestOutputSize;
std::string m_StartTest;
std::string m_EndTest;
double m_ElapsedTestingTime;
std::vector<int> 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);

View File

@ -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;

View File

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

View File

@ -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::vector<std::string>const& 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::vector<std::string>const& args, std::string* output)
{
this->m_RunConfigurationScript = true;
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 )
@ -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)
{
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<cmCTestTestHandler*>(m_TestingHandlers["test"]);
th->SetTestsToRunInformation(args[i].c_str());
}
if(arg.find("-U",0) == 0)
{
cmCTestTestHandler* th = static_cast<cmCTestTestHandler*>(m_TestingHandlers["test"]);
th->SetUseUnion(true);
}
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++;
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::vector<std::string>const& 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;
}

View File

@ -24,12 +24,7 @@
#include <time.h>
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<cmStdString,cmCTestGenericHandler*> t_TestingHandlers;
t_TestingHandlers m_TestingHandlers;
bool m_ShowOnly;