Fixed ctest -N segfault issue. Further refactored ctest. Enabled failover for ctest
This commit is contained in:
parent
fdc0d9777c
commit
177edc5ed1
|
@ -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: "
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() << " ... ");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 "
|
||||
|
|
Loading…
Reference in New Issue