summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorZach Mullen <zach.mullen@kitware.com>2009-08-27 14:37:30 (GMT)
committerZach Mullen <zach.mullen@kitware.com>2009-08-27 14:37:30 (GMT)
commit177edc5ed1bed7306a122129dfcaf13d898f83ef (patch)
tree43db43d2af66aec0f021ad5e8e7d9067d46088ce /Source
parentfdc0d9777cf548b44d8cfa43502efb26a6247e9b (diff)
downloadCMake-177edc5ed1bed7306a122129dfcaf13d898f83ef.zip
CMake-177edc5ed1bed7306a122129dfcaf13d898f83ef.tar.gz
CMake-177edc5ed1bed7306a122129dfcaf13d898f83ef.tar.bz2
Fixed ctest -N segfault issue. Further refactored ctest. Enabled failover for ctest
Diffstat (limited to 'Source')
-rw-r--r--Source/CTest/cmCTestGenericHandler.cxx6
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx67
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.h10
-rw-r--r--Source/CTest/cmCTestRunTest.cxx210
-rw-r--r--Source/CTest/cmCTestRunTest.h4
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx329
-rw-r--r--Source/CTest/cmCTestTestHandler.h5
-rw-r--r--Source/cmCTest.cxx31
-rw-r--r--Source/cmCTest.h18
-rw-r--r--Source/ctest.cxx3
10 files changed, 251 insertions, 432 deletions
diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx
index 0196c89..3658ef2 100644
--- a/Source/CTest/cmCTestGenericHandler.cxx
+++ b/Source/CTest/cmCTestGenericHandler.cxx
@@ -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: "
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 328e2e5..1c81825 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -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()
{
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index 413bff2..3a47a36 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -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;
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index d444249..7b42a3d 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -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()) )
- {
- found = true;
- reason = "Required regular expression 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 )
+ if ( passIt->first.find(this->ProcessOutput.c_str()) )
{
- reason += passIt->second;
- reason += "\n";
+ found = true;
+ reason = "Required regular expression found.";
}
- reason += "]";
}
- if ( this->TestProperties->ErrorRegularExpressions.size() > 0 )
+ if ( !found )
+ {
+ reason = "Required regular expression not found.";
+ forceFail = true;
+ }
+ reason += "Regex=[";
+ for ( passIt = this->TestProperties->RequiredRegularExpressions.begin();
+ passIt != this->TestProperties->RequiredRegularExpressions.end();
+ ++ passIt )
{
- 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 += passIt->second;
+ reason += "\n";
}
- if (res == cmsysProcess_State_Exited)
+ reason += "]";
+ }
+ if ( this->TestProperties->ErrorRegularExpressions.size() > 0 )
+ {
+ for ( passIt = this->TestProperties->ErrorRegularExpressions.begin();
+ passIt != this->TestProperties->ErrorRegularExpressions.end();
+ ++ passIt )
{
- bool success =
- !forceFail && (retVal == 0 ||
- this->TestProperties->RequiredRegularExpressions.size());
- if((success && !this->TestProperties->WillFail)
- || (!success && this->TestProperties->WillFail))
+ if ( passIt->first.find(this->ProcessOutput.c_str()) )
{
- this->TestResult.Status = cmCTestTestHandler::COMPLETED;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Passed " );
- }
- else
- {
- this->TestResult.Status = cmCTestTestHandler::FAILED;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Failed " << reason );
+ reason = "Error regular expression found in output.";
+ reason += " Regex=[";
+ reason += passIt->second;
+ reason += "]";
+ forceFail = true;
}
}
- else if ( res == cmsysProcess_State_Expired )
+ }
+ if (res == cmsysProcess_State_Exited)
+ {
+ bool success =
+ !forceFail && (retVal == 0 ||
+ this->TestProperties->RequiredRegularExpressions.size());
+ if((success && !this->TestProperties->WillFail)
+ || (!success && this->TestProperties->WillFail))
{
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Timeout");
- this->TestResult.Status = cmCTestTestHandler::TIMEOUT;
+ this->TestResult.Status = cmCTestTestHandler::COMPLETED;
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, " Passed " );
}
- else if ( res == cmsysProcess_State_Exception )
+ else
{
- 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;
- }
+ this->TestResult.Status = cmCTestTestHandler::FAILED;
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Failed " << reason );
}
- else // if ( res == cmsysProcess_State_Error )
+ }
+ 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, "***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() << " ... ");
}
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index 72a108a..2609808 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -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
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 6df925c..b51b7c5 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -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;
+ 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" );
-
+ 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" );
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)
- {
- fout << i->c_str() << "\n";
- }
- fout << "Depends:\n" << p.Depends.size() << "\n";
- for(std::vector<std::string>::iterator i = p.Depends.begin();
- i != p.Depends.end(); ++i)
- {
- 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++)
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(3)
+ << p.Index << "/");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(3)
+ << total << " ");
+ if (this->MemCheck)
{
- fout << regxi->second << "\n";
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, "Memory Check");
}
- fout << "RequiredRegularExpressions:\n" <<
- p.RequiredRegularExpressions.size() << "\n";
- for(regxi = p.RequiredRegularExpressions.begin();
- regxi != p.RequiredRegularExpressions.end(); regxi++)
+ else
{
- 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());
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index a6b8e8e..9dbb52c 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -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);
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 7590772..f1ad1a7 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -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)
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 91a0fc6..222cbe5 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -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
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index 7cf2bcd..9cb0aab 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -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 "