Fixed ctest -N segfault issue. Further refactored ctest. Enabled failover for ctest

This commit is contained in:
Zach Mullen 2009-08-27 10:37:30 -04:00
parent fdc0d9777c
commit 177edc5ed1
10 changed files with 255 additions and 436 deletions

View File

@ -166,12 +166,6 @@ bool cmCTestGenericHandler::StartLogFile(const char* name,
ostr << "_" << this->CTest->GetCurrentTag();
}
ostr << ".log";
// if this is a parallel subprocess then add the id to the
// file so they don't clobber each other
if(this->CTest->GetParallelSubprocess())
{
ostr << "." << this->CTest->GetParallelSubprocessId();
}
if( !this->CTest->OpenOutputFile("Temporary", ostr.str().c_str(), xofs) )
{
cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create log file: "

View File

@ -18,7 +18,8 @@
#include "cmProcess.h"
#include "cmStandardIncludes.h"
#include "cmCTest.h"
#include "cmSystemTools.h"
#include <stdlib.h>
cmCTestMultiProcessHandler::cmCTestMultiProcessHandler()
{
@ -39,6 +40,7 @@ cmCTestMultiProcessHandler::SetTests(TestMap& tests,
this->Tests = tests;
this->Properties = properties;
}
// Set the max number of tests that can be run at the same time.
void cmCTestMultiProcessHandler::SetParallelLevel(size_t level)
{
@ -47,6 +49,7 @@ void cmCTestMultiProcessHandler::SetParallelLevel(size_t level)
void cmCTestMultiProcessHandler::RunTests()
{
this->CheckResume();
this->StartNextTests();
while(this->Tests.size() != 0)
{
@ -57,6 +60,7 @@ void cmCTestMultiProcessHandler::RunTests()
while(this->CheckOutput())
{
}
this->MarkFinished();
}
void cmCTestMultiProcessHandler::StartTestProcess(int test)
@ -176,7 +180,6 @@ bool cmCTestMultiProcessHandler::CheckOutput()
finished.push_back(p);
}
}
for( std::vector<cmCTestRunTest*>::iterator i = finished.begin();
i != finished.end(); ++i)
{
@ -199,12 +202,30 @@ bool cmCTestMultiProcessHandler::CheckOutput()
this->TestFinishMap[test] = true;
this->TestRunningMap[test] = false;
this->RunningTests.erase(p);
this->WriteCheckpoint(test);
delete p;
}
return true;
}
void cmCTestMultiProcessHandler::WriteCheckpoint(int index)
{
std::string fname = this->CTest->GetBinaryDir()
+ "/Testing/Temporary/CTestCheckpoint.txt";
std::fstream fout;
fout.open(fname.c_str(), std::ios::app);
fout << index << "\n";
fout.close();
}
void cmCTestMultiProcessHandler::MarkFinished()
{
std::string fname = this->CTest->GetBinaryDir()
+ "/Testing/Temporary/CTestCheckpoint.txt";
cmSystemTools::RemoveFile(fname.c_str());
}
void cmCTestMultiProcessHandler::PrintTests()
{
#undef cout
@ -221,6 +242,48 @@ void cmCTestMultiProcessHandler::PrintTests()
}
}
//----------------------------------------------------------------
void cmCTestMultiProcessHandler::CheckResume()
{
std::string fname = this->CTest->GetBinaryDir()
+ "/Testing/Temporary/CTestCheckpoint.txt";
if(this->CTest->GetFailover())
{
if(cmSystemTools::FileExists(fname.c_str(), true))
{
*this->TestHandler->LogFile << "Resuming previously interrupted test set"
<< std::endl
<< "----------------------------------------------------------"
<< std::endl;
std::ifstream fin;
fin.open(fname.c_str());
std::string line;
while(std::getline(fin, line))
{
int index = atoi(line.c_str());
this->RemoveTest(index);
}
fin.close();
}
}
else
{
if(cmSystemTools::FileExists(fname.c_str(), true))
{
cmSystemTools::RemoveFile(fname.c_str());
}
}
}
void cmCTestMultiProcessHandler::RemoveTest(int index)
{
this->Tests.erase(index);
this->Properties.erase(index);
this->TestRunningMap[index] = false;
this->TestFinishMap[index] = true;
}
#if 0
int main()
{

View File

@ -68,10 +68,16 @@ protected:
void StartNextTests();
void StartTestProcess(int test);
bool StartTest(int test);
//void EndTest(cmProcess*);
// Mark the checkpoint for the given test
void WriteCheckpoint(int index);
// Removes the checkpoint file
void MarkFinished();
// Return true if there are still tests running
// check all running processes for output and exit case
bool CheckOutput();
void RemoveTest(int index);
//Check if we need to resume an interrupted test set
void CheckResume();
// map from test number to set of depend tests
TestMap Tests;
//list of test properties (indices concurrent to the test map)
@ -79,8 +85,6 @@ protected:
std::map<int, bool> TestRunningMap;
std::map<int, bool> TestFinishMap;
std::map<int, cmStdString> TestOutput;
//std::string CTestCommand;
//std::string CTestCacheFile;
std::vector<cmStdString>* Passed;
std::vector<cmStdString>* Failed;
std::vector<cmCTestTestHandler::cmCTestTestResult>* TestResults;

View File

@ -67,120 +67,118 @@ bool cmCTestRunTest::EndTest()
bool passed = true;
int res = this->TestProcess->GetProcessStatus();
int retVal = this->TestProcess->GetExitValue();
if ( !this->CTest->GetShowOnly() )
std::vector<std::pair<cmsys::RegularExpression,
std::string> >::iterator passIt;
bool forceFail = false;
if ( this->TestProperties->RequiredRegularExpressions.size() > 0 )
{
std::vector<std::pair<cmsys::RegularExpression,
std::string> >::iterator passIt;
bool forceFail = false;
if ( this->TestProperties->RequiredRegularExpressions.size() > 0 )
bool found = false;
for ( passIt = this->TestProperties->RequiredRegularExpressions.begin();
passIt != this->TestProperties->RequiredRegularExpressions.end();
++ passIt )
{
bool found = false;
for ( passIt = this->TestProperties->RequiredRegularExpressions.begin();
passIt != this->TestProperties->RequiredRegularExpressions.end();
++ passIt )
if ( passIt->first.find(this->ProcessOutput.c_str()) )
{
if ( passIt->first.find(this->ProcessOutput.c_str()) )
{
found = true;
reason = "Required regular expression found.";
}
found = true;
reason = "Required regular expression found.";
}
if ( !found )
{
reason = "Required regular expression not found.";
}
if ( !found )
{
reason = "Required regular expression not found.";
forceFail = true;
}
reason += "Regex=[";
for ( passIt = this->TestProperties->RequiredRegularExpressions.begin();
passIt != this->TestProperties->RequiredRegularExpressions.end();
++ passIt )
{
reason += passIt->second;
reason += "\n";
}
reason += "]";
}
if ( this->TestProperties->ErrorRegularExpressions.size() > 0 )
{
for ( passIt = this->TestProperties->ErrorRegularExpressions.begin();
passIt != this->TestProperties->ErrorRegularExpressions.end();
++ passIt )
{
if ( passIt->first.find(this->ProcessOutput.c_str()) )
{
reason = "Error regular expression found in output.";
reason += " Regex=[";
reason += passIt->second;
reason += "]";
forceFail = true;
}
reason += "Regex=[";
for ( passIt = this->TestProperties->RequiredRegularExpressions.begin();
passIt != this->TestProperties->RequiredRegularExpressions.end();
++ passIt )
{
reason += passIt->second;
reason += "\n";
}
reason += "]";
}
if ( this->TestProperties->ErrorRegularExpressions.size() > 0 )
}
if (res == cmsysProcess_State_Exited)
{
bool success =
!forceFail && (retVal == 0 ||
this->TestProperties->RequiredRegularExpressions.size());
if((success && !this->TestProperties->WillFail)
|| (!success && this->TestProperties->WillFail))
{
for ( passIt = this->TestProperties->ErrorRegularExpressions.begin();
passIt != this->TestProperties->ErrorRegularExpressions.end();
++ passIt )
{
if ( passIt->first.find(this->ProcessOutput.c_str()) )
{
reason = "Error regular expression found in output.";
reason += " Regex=[";
reason += passIt->second;
reason += "]";
forceFail = true;
}
}
this->TestResult.Status = cmCTestTestHandler::COMPLETED;
cmCTestLog(this->CTest, HANDLER_OUTPUT, " Passed " );
}
if (res == cmsysProcess_State_Exited)
else
{
bool success =
!forceFail && (retVal == 0 ||
this->TestProperties->RequiredRegularExpressions.size());
if((success && !this->TestProperties->WillFail)
|| (!success && this->TestProperties->WillFail))
{
this->TestResult.Status = cmCTestTestHandler::COMPLETED;
cmCTestLog(this->CTest, HANDLER_OUTPUT, " Passed " );
}
else
{
this->TestResult.Status = cmCTestTestHandler::FAILED;
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Failed " << reason );
}
this->TestResult.Status = cmCTestTestHandler::FAILED;
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Failed " << reason );
}
else if ( res == cmsysProcess_State_Expired )
}
else if ( res == cmsysProcess_State_Expired )
{
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Timeout");
this->TestResult.Status = cmCTestTestHandler::TIMEOUT;
}
else if ( res == cmsysProcess_State_Exception )
{
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Exception: ");
switch ( retVal )
{
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Timeout");
this->TestResult.Status = cmCTestTestHandler::TIMEOUT;
}
else if ( res == cmsysProcess_State_Exception )
{
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Exception: ");
switch ( retVal )
{
case cmsysProcess_Exception_Fault:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "SegFault");
this->TestResult.Status = cmCTestTestHandler::SEGFAULT;
break;
case cmsysProcess_Exception_Illegal:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Illegal");
this->TestResult.Status = cmCTestTestHandler::ILLEGAL;
break;
case cmsysProcess_Exception_Interrupt:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Interrupt");
this->TestResult.Status = cmCTestTestHandler::INTERRUPT;
break;
case cmsysProcess_Exception_Numerical:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Numerical");
this->TestResult.Status = cmCTestTestHandler::NUMERICAL;
break;
default:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Other");
this->TestResult.Status = cmCTestTestHandler::OTHER_FAULT;
}
}
else // if ( res == cmsysProcess_State_Error )
{
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Bad command " << res );
this->TestResult.Status = cmCTestTestHandler::BAD_COMMAND;
case cmsysProcess_Exception_Fault:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "SegFault");
this->TestResult.Status = cmCTestTestHandler::SEGFAULT;
break;
case cmsysProcess_Exception_Illegal:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Illegal");
this->TestResult.Status = cmCTestTestHandler::ILLEGAL;
break;
case cmsysProcess_Exception_Interrupt:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Interrupt");
this->TestResult.Status = cmCTestTestHandler::INTERRUPT;
break;
case cmsysProcess_Exception_Numerical:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Numerical");
this->TestResult.Status = cmCTestTestHandler::NUMERICAL;
break;
default:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Other");
this->TestResult.Status = cmCTestTestHandler::OTHER_FAULT;
}
}
else // if ( res == cmsysProcess_State_Error )
{
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Bad command " << res );
this->TestResult.Status = cmCTestTestHandler::BAD_COMMAND;
}
passed = this->TestResult.Status == cmCTestTestHandler::COMPLETED;
passed = this->TestResult.Status == cmCTestTestHandler::COMPLETED;
char buf[1024];
sprintf(buf, "%6.2f sec", this->TestProcess->GetTotalTime());
cmCTestLog(this->CTest, HANDLER_OUTPUT, buf << "\n" );
if ( this->TestHandler->LogFile )
{
*this->TestHandler->LogFile << "Test time = " << buf << std::endl;
}
this->DartProcessing();
}
char buf[1024];
sprintf(buf, "%6.2f sec", this->TestProcess->GetTotalTime());
cmCTestLog(this->CTest, HANDLER_OUTPUT, buf << "\n" );
if ( this->TestHandler->LogFile )
{
*this->TestHandler->LogFile << "Test time = " << buf << std::endl;
}
this->DartProcessing();
// if this is doing MemCheck then all the output needs to be put into
// Output since that is what is parsed by cmCTestMemCheckHandler
if(!this->TestHandler->MemCheck)
@ -303,14 +301,10 @@ bool cmCTestRunTest::StartTest()
this->StartTime = this->CTest->CurrentTime();
if ( !this->CTest->GetShowOnly() )
{
return this->CreateProcess(this->ActualCommand,
this->TestProperties->Args,
this->TestProperties->Timeout,
&this->TestProperties->Environment);
}
return true;
return this->CreateProcess(this->ActualCommand,
this->TestProperties->Args,
this->TestProperties->Timeout,
&this->TestProperties->Environment);
}
//----------------------------------------------------------------------
@ -449,15 +443,7 @@ void cmCTestRunTest::WriteLogOutputTop()
*this->TestHandler->LogFile
<< this->ProcessOutput.c_str() << "<end of output>" << std::endl;
if ( this->CTest->GetShowOnly() )
{
cmCTestLog(this->CTest, HANDLER_OUTPUT, outname.c_str() << std::endl);
}
else
{
cmCTestLog(this->CTest, HANDLER_OUTPUT, outname.c_str());
}
cmCTestLog(this->CTest, HANDLER_OUTPUT, outname.c_str());
cmCTestLog(this->CTest, DEBUG, "Testing "
<< this->TestProperties->Name.c_str() << " ... ");
}

View File

@ -63,7 +63,8 @@ protected:
std::vector<std::string> args,
double testTimeOut,
std::vector<std::string>* environment);
private:
void WriteLogOutputTop();
cmCTestTestHandler::cmCTestTestProperties * TestProperties;
//Pointer back to the "parent"; the handler that invoked this test run
cmCTestTestHandler * TestHandler;
@ -85,7 +86,6 @@ private:
std::string StartTime;
std::string TestCommand;
std::string ActualCommand;
void WriteLogOutputTop();
};
#endif

View File

@ -523,14 +523,11 @@ int cmCTestTestHandler::ProcessHandler()
}
this->TestResults.clear();
// do not output startup if this is a sub-process for parallel tests
if(!this->CTest->GetParallelSubprocess())
{
cmCTestLog(this->CTest, HANDLER_OUTPUT,
(this->MemCheck ? "Memory check" : "Test")
<< " project " << cmSystemTools::GetCurrentWorkingDirectory()
<< std::endl);
}
cmCTestLog(this->CTest, HANDLER_OUTPUT,
(this->MemCheck ? "Memory check" : "Test")
<< " project " << cmSystemTools::GetCurrentWorkingDirectory()
<< std::endl);
if ( ! this->PreProcessHandler() )
{
return -1;
@ -583,57 +580,49 @@ int cmCTestTestHandler::ProcessHandler()
percent = 99;
}
if(!this->CTest->GetParallelSubprocess())
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl
<< static_cast<int>(percent + .5) << "% tests passed, "
<< failed.size() << " tests failed out of "
<< total << std::endl);
double totalTestTime = 0;
for(cmCTestTestHandler::TestResultsVector::size_type cc = 0;
cc < this->TestResults.size(); cc ++ )
{
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl
<< static_cast<int>(percent + .5) << "% tests passed, "
<< failed.size() << " tests failed out of "
<< total << std::endl);
double totalTestTime = 0;
for(cmCTestTestHandler::TestResultsVector::size_type cc = 0;
cc < this->TestResults.size(); cc ++ )
{
cmCTestTestResult *result = &this->TestResults[cc];
totalTestTime += result->ExecutionTime;
}
char realBuf[1024];
sprintf(realBuf, "%6.2f sec", (double)(clock_finish - clock_start));
cmCTestLog(this->CTest, HANDLER_OUTPUT, "\nTotal Test time (real) = "
<< realBuf << "\n" );
char totalBuf[1024];
sprintf(totalBuf, "%6.2f sec", totalTestTime);
cmCTestLog(this->CTest, HANDLER_OUTPUT, "\nTotal Test time (parallel) = "
<< totalBuf << "\n" );
cmCTestTestResult *result = &this->TestResults[cc];
totalTestTime += result->ExecutionTime;
}
char realBuf[1024];
sprintf(realBuf, "%6.2f sec", (double)(clock_finish - clock_start));
cmCTestLog(this->CTest, HANDLER_OUTPUT, "\nTotal Test time (real) = "
<< realBuf << "\n" );
char totalBuf[1024];
sprintf(totalBuf, "%6.2f sec", totalTestTime);
cmCTestLog(this->CTest, HANDLER_OUTPUT, "\nTotal Test time (parallel) = "
<< totalBuf << "\n" );
if (failed.size())
{
cmGeneratedFileStream ofs;
if(!this->CTest->GetParallelSubprocess())
cmCTestLog(this->CTest, ERROR_MESSAGE, std::endl
<< "The following tests FAILED:" << std::endl);
this->StartLogFile("TestsFailed", ofs);
std::vector<cmCTestTestHandler::cmCTestTestResult>::iterator ftit;
for(ftit = this->TestResults.begin();
ftit != this->TestResults.end(); ++ftit)
{
cmCTestLog(this->CTest, ERROR_MESSAGE, std::endl
<< "The following tests FAILED:" << std::endl);
this->StartLogFile("TestsFailed", ofs);
std::vector<cmCTestTestHandler::cmCTestTestResult>::iterator ftit;
for(ftit = this->TestResults.begin();
ftit != this->TestResults.end(); ++ftit)
if ( ftit->Status != cmCTestTestHandler::COMPLETED )
{
if ( ftit->Status != cmCTestTestHandler::COMPLETED )
{
ofs << ftit->TestCount << ":" << ftit->Name << std::endl;
cmCTestLog(this->CTest, HANDLER_OUTPUT, "\t" << std::setw(3)
<< ftit->TestCount << " - "
<< ftit->Name.c_str() << " ("
<< this->GetTestStatus(ftit->Status) << ")"
<< std::endl);
}
ofs << ftit->TestCount << ":" << ftit->Name << std::endl;
cmCTestLog(this->CTest, HANDLER_OUTPUT, "\t" << std::setw(3)
<< ftit->TestCount << " - "
<< ftit->Name.c_str() << " ("
<< this->GetTestStatus(ftit->Status) << ")"
<< std::endl);
}
}
}
}
@ -808,7 +797,6 @@ void cmCTestTestHandler::ProcessOneTest(cmCTestTestProperties *it,
std::string output;
int retVal = 0;
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl
<< (this->MemCheck?"MemCheck":"Test")
<< " command: " << testCommand
@ -839,9 +827,7 @@ void cmCTestTestHandler::ProcessOneTest(cmCTestTestProperties *it,
it->Timeout, &it->Environment);
}
clock_finish = cmSystemTools::GetTime();
clock_finish = cmSystemTools::GetTime();
cres.ExecutionTime = (double)(clock_finish - clock_start);
cres.FullCommandLine = testCommand;
@ -1118,15 +1104,7 @@ void cmCTestTestHandler::CheckLabelFilter(cmCTestTestProperties& it)
void cmCTestTestHandler::ComputeTestList()
{
this->TestList.clear(); // clear list of test
if(this->CTest->GetParallelSubprocess())
{
this->LoadTestList();
return;
}
else
{
this->GetListOfTests();
}
this->GetListOfTests();
cmCTestTestHandler::ListOfTests::size_type tmsize = this->TestList.size();
// how many tests are in based on RegExp?
int inREcnt = 0;
@ -1325,225 +1303,42 @@ bool cmCTestTestHandler::GetValue(const char* tag,
return ret;
}
// This should load only one test and is used in -j N mode.
// it is used by the sub-process ctest runs which should have
// only one -I N test to run.
void cmCTestTestHandler::LoadTestList()
//---------------------------------------------------------------------
void cmCTestTestHandler::PrintTestList()
{
this->TestList.clear();
std::string fname = this->CTest->GetBinaryDir()
+ "/Testing/Temporary/PCache.txt";
std::ifstream fin(fname.c_str());
std::string line;
if(!fin)
{
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Could not load PCache.txt file: "
<< fname.c_str() << std::endl);
return;
}
bool ok = true;
int numTestsToRun = 0;
ok = ok && this->GetValue("TotalNumberOfTests:",
this->TotalNumberOfTests, fin);
ok = ok && this->GetValue("NumberOfTestsToRun:", numTestsToRun, fin);
this->ExpandTestsToRunInformation(this->TotalNumberOfTests);
if(this->TestsToRun.size() != 1)
{
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Error when in parallel mode only one test should be run: "
<< this->TestsToRun.size() << std::endl);
}
int testIndexToRun = this->TestsToRun[0];
this->CTest->SetParallelSubprocessId(testIndexToRun);
if(!ok)
{
return;
}
for(int i =0; i < numTestsToRun; i++)
{
cmCTestTestProperties p;
int numArgs = 0;
ok = this->GetValue("Name:", p.Name, fin);
ok = ok && this->GetValue("Directory:", p.Directory, fin);
ok = ok && this->GetValue("Args:", numArgs, fin);
for(int j =0; j < numArgs; ++j)
{
cmSystemTools::GetLineFromStream(fin, line);
p.Args.push_back(line);
}
int numDep = 0;
ok = ok && this->GetValue("Depends:", numDep, fin);
for(int j =0; j < numDep; ++j)
{
cmSystemTools::GetLineFromStream(fin, line);
p.Depends.push_back(line);
}
int numErrRegex = 0;
ok = ok && this->GetValue("ErrorRegularExpressions:",
numErrRegex, fin);
for(int j =0; j < numErrRegex; j++)
{
cmSystemTools::GetLineFromStream(fin, line);
std::pair<cmsys::RegularExpression, std::string> rpair;
rpair.first.compile(line.c_str());
rpair.second = line;
p.ErrorRegularExpressions.push_back(rpair);
}
int numReqRegex = 0;
ok = ok && this->GetValue("RequiredRegularExpressions:",
numReqRegex, fin);
for(int j =0; j < numReqRegex; j++)
{
cmSystemTools::GetLineFromStream(fin, line);
std::pair<cmsys::RegularExpression, std::string> rpair;
rpair.first.compile(line.c_str());
rpair.second = line;
p.RequiredRegularExpressions.push_back(rpair);
}
int numMeasure = 0;
ok = ok && this->GetValue("Measurements:",
numMeasure, fin);
for(int j =0; j < numMeasure; j++)
{
cmStdString m;
cmStdString v;
cmSystemTools::GetLineFromStream(fin, line);
m = line;
cmSystemTools::GetLineFromStream(fin, line);
v = line;
p.Measurements[m] = v;
}
int isinre;
ok = ok && this->GetValue("IsInBasedOnREOptions:", isinre, fin);
ok = ok && this->GetValue("WillFail:", p.WillFail, fin);
ok = ok && this->GetValue("TimeOut:", p.Timeout, fin);
ok = ok && this->GetValue("Index:", p.Index, fin);
int numEnv = 0;
ok = ok && this->GetValue("Environment:",
numEnv, fin);
for(int j =0; j < numEnv; j++)
{
cmSystemTools::GetLineFromStream(fin, line);
p.Environment.push_back(line);
}
int numLabels = 0;
ok = ok && this->GetValue("Labels:",
numLabels, fin);
for(int j =0; j < numLabels; j++)
{
cmSystemTools::GetLineFromStream(fin, line);
p.Labels.push_back(line);
}
if(!ok)
{
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Internal Error reading cached test information."
<< std::endl);
return;
}
if(p.Index == testIndexToRun)
{
// add the one test and stop reading
this->TestList.push_back(p);
return;
}
}
}
std::string cmCTestTestHandler::SaveTestList()
{
std::string fname = this->CTest->GetBinaryDir()
+ "/Testing/Temporary/PCache.txt";
cmGeneratedFileStream fout(fname.c_str());
if(!fout)
{
cmCTestLog(this->CTest, ERROR_MESSAGE, std::endl
<< "Could not open PCache.txt for write:"
<< fname.c_str()
<< std::endl);
}
fout << "TotalNumberOfTests:\n";
fout << this->TotalNumberOfTests << "\n";
fout << "NumberOfTestsToRun:\n";
fout << this->TestList.size() << "\n";
int total = this->TotalNumberOfTests;
for (ListOfTests::iterator it = this->TestList.begin();
it != this->TestList.end(); it ++ )
{
{
cmCTestTestProperties& p = *it;
fout << "Name:\n"
<< p.Name.c_str()
<< "\nDirectory:\n"
<< p.Directory.c_str()
<< "\nArgs:\n"
<< p.Args.size() << "\n";
for(std::vector<std::string>::iterator i = p.Args.begin();
i != p.Args.end(); ++i)
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(3)
<< p.Index << "/");
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(3)
<< total << " ");
if (this->MemCheck)
{
fout << i->c_str() << "\n";
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Memory Check");
}
fout << "Depends:\n" << p.Depends.size() << "\n";
for(std::vector<std::string>::iterator i = p.Depends.begin();
i != p.Depends.end(); ++i)
else
{
fout << i->c_str() << "\n";
}
std::vector<std::pair<cmsys::RegularExpression,
std::string> >::iterator regxi;
fout << "ErrorRegularExpressions:\n" <<
p.ErrorRegularExpressions.size() << "\n";
for(regxi = p.ErrorRegularExpressions.begin();
regxi != p.ErrorRegularExpressions.end(); regxi++)
{
fout << regxi->second << "\n";
}
fout << "RequiredRegularExpressions:\n" <<
p.RequiredRegularExpressions.size() << "\n";
for(regxi = p.RequiredRegularExpressions.begin();
regxi != p.RequiredRegularExpressions.end(); regxi++)
{
fout << regxi->second << "\n";
}
fout << "Measurements:\n" <<
p.Measurements.size() << "\n";
for(std::map<cmStdString, cmStdString>::const_iterator m =
p.Measurements.begin(); m != p.Measurements.end(); ++m)
{
fout << m->first << "\n";
fout << m->second << "\n";
}
fout << "IsInBasedOnREOptions:\n"
<< p.IsInBasedOnREOptions
<< "\nWillFail:\n"
<< p.WillFail
<< "\nTimeOut:\n"
<< p.Timeout
<< "\nIndex:\n"
<< p.Index << "\n";
fout << "Environment:\n" <<
p.Environment.size() << "\n";
for(std::vector<std::string>::const_iterator e =
p.Environment.begin(); e != p.Environment.end(); ++e)
{
fout << *e << "\n";
}
fout << "Labels:\n" <<
p.Labels.size() << "\n";
for(std::vector<std::string>::const_iterator e =
p.Labels.begin(); e != p.Labels.end(); ++e)
{
fout << *e << "\n";
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Testing");
}
cmCTestLog(this->CTest, HANDLER_OUTPUT, " ");
cmCTestLog(this->CTest, HANDLER_OUTPUT, p.Name.c_str() << std::endl);
}
fout.close();
return fname;
}
//---------------------------------------------------------------------
void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
std::vector<cmStdString> &failed)
{
this->ComputeTestList();
if(this->CTest->GetShowOnly())
{
this->PrintTestList();
return;
}
cmCTestMultiProcessHandler parallel;
parallel.SetCTest(this->CTest);
parallel.SetParallelLevel(this->CTest->GetParallelLevel());

View File

@ -141,6 +141,7 @@ protected:
void WriteTestResultHeader(std::ostream& os, cmCTestTestResult* result);
void WriteTestResultFooter(std::ostream& os, cmCTestTestResult* result);
void PrintTestList();
//! Clean test output to specified length
bool CleanTestOutput(std::string& output, size_t length);
@ -203,10 +204,6 @@ private:
// based on union regex and -I stuff
void ComputeTestList();
// Save the state of the test list and return the file
// name it was saved to
std::string SaveTestList();
void LoadTestList();
bool GetValue(const char* tag,
std::string& value,
std::ifstream& fin);

View File

@ -208,9 +208,9 @@ std::string cmCTest::DecodeURL(const std::string& in)
//----------------------------------------------------------------------
cmCTest::cmCTest()
{
this->ParallelSubprocess = false;
this->ParallelLevel = 1;
this->SubmitIndex = 0;
this->Failover = false;
this->ForceNewCTestProcess = false;
this->TomorrowTag = false;
this->Verbose = false;
@ -795,11 +795,7 @@ int cmCTest::ProcessTests()
bool notest = true;
int update_count = 0;
// do not output startup if this is a sub-process for parallel tests
if(!this->GetParallelSubprocess())
{
cmCTestLog(this, OUTPUT, "Start processing tests" << std::endl);
}
cmCTestLog(this, OUTPUT, "Start processing tests" << std::endl);
for(Part p = PartStart; notest && p != PartCount; p = Part(p+1))
{
@ -908,11 +904,8 @@ int cmCTest::ProcessTests()
}
if ( res != 0 )
{
if(!this->GetParallelSubprocess())
{
cmCTestLog(this, ERROR_MESSAGE, "Errors while running CTest"
cmCTestLog(this, ERROR_MESSAGE, "Errors while running CTest"
<< std::endl);
}
}
return res;
}
@ -1707,6 +1700,10 @@ void cmCTest::HandleCommandLineArguments(size_t &i,
{
std::string arg = args[i];
if(this->CheckArgument(arg, "-F"))
{
this->Failover = true;
}
if(this->CheckArgument(arg, "-j", "--parallel") && i < args.size() - 1)
{
i++;
@ -1718,20 +1715,6 @@ void cmCTest::HandleCommandLineArguments(size_t &i,
int plevel = atoi(arg.substr(2).c_str());
this->SetParallelLevel(plevel);
}
if(this->CheckArgument(arg, "--internal-ctest-parallel")
&& i < args.size() - 1)
{
i++;
int pid = atoi(args[i].c_str());
this->SetParallelSubprocessId(pid);
this->SetParallelSubprocess();
}
if(this->CheckArgument(arg, "--parallel-cache") && i < args.size() - 1)
{
i++;
this->SetParallelCacheFile(args[i].c_str());
}
if(this->CheckArgument(arg, "-C", "--build-config") &&
i < args.size() - 1)

View File

@ -138,15 +138,6 @@ public:
int GetParallelLevel() { return this->ParallelLevel; }
void SetParallelLevel(int);
bool GetParallelSubprocess() { return this->ParallelSubprocess; }
void SetParallelSubprocess() { this->ParallelSubprocess = true; }
void SetParallelSubprocessId(int id) { this->ParallelSubprocessId = id;}
int GetParallelSubprocessId() { return this->ParallelSubprocessId;}
const char* GetParallelCacheFile()
{ return this->ParallelCacheFile.c_str();}
void SetParallelCacheFile(const char* c) { this->ParallelCacheFile = c; }
/**
* Check if CTest file exists
*/
@ -371,6 +362,9 @@ public:
void SetSpecificTrack(const char* track);
const char* GetSpecificTrack();
void SetFailover(bool failover) { this->Failover = failover; }
bool GetFailover() { return this->Failover; }
bool GetVerbose() { return this->Verbose;}
bool GetExtraVerbose() { return this->ExtraVerbose;}
@ -384,6 +378,8 @@ private:
bool ExtraVerbose;
bool ProduceXML;
bool Failover;
bool ForceNewCTestProcess;
bool RunConfigurationScript;
@ -420,10 +416,8 @@ private:
int MaxTestNameWidth;
std::string ParallelCacheFile;
int ParallelLevel;
int ParallelSubprocessId;
bool ParallelSubprocess;
int CompatibilityMode;
// information for the --build-and-test options

View File

@ -70,6 +70,9 @@ static const char * cmDocumentationOptions[][3] =
{"--output-on-failure", "Output anything outputted by the test program "
"if the test should fail. This option can also be enabled by setting "
"the environment variable CTEST_OUTPUT_ON_FAILURE"},
{"-F", "Enable failover.", "This option allows ctest to resume a test "
"set execution that was previously interrupted. If no interruption "
"occurred, the -F option will have no effect."},
{"-Q,--quiet", "Make ctest quiet.",
"This option will suppress all the output. The output log file will "
"still be generated if the --output-log is specified. Options such "