[Cmake-commits] [cmake-commits] hoffman committed cmCTestGenericHandler.cxx 1.16 1.17 cmCTestMultiProcessHandler.cxx NONE 1.1 cmCTestMultiProcessHandler.h NONE 1.1 cmCTestTestHandler.cxx 1.71 1.72 cmCTestTestHandler.h 1.27 1.28
cmake-commits at cmake.org
cmake-commits at cmake.org
Thu Jul 3 09:31:35 EDT 2008
Update of /cvsroot/CMake/CMake/Source/CTest
In directory public:/mounts/ram/cvs-serv18162/Source/CTest
Modified Files:
cmCTestGenericHandler.cxx cmCTestTestHandler.cxx
cmCTestTestHandler.h
Added Files:
cmCTestMultiProcessHandler.cxx cmCTestMultiProcessHandler.h
Log Message:
ENH: add initial ctest -j feature
--- NEW FILE: cmCTestMultiProcessHandler.cxx ---
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile: cmCTestMultiProcessHandler.cxx,v $
Language: C++
Date: $Date: 2008-07-03 13:31:30 $
Version: $Revision: 1.1 $
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "cmCTestMultiProcessHandler.h"
#include "cmProcess.h"
#include "cmStandardIncludes.h"
#include "cmCTest.h"
cmCTestMultiProcessHandler::cmCTestMultiProcessHandler()
{
this->ParallelLevel = 1;
this->ProcessId = 0;
}
// Set the tests
void
cmCTestMultiProcessHandler::SetTests(std::map<int, std::set<int> >& tests,
std::map<int,cmStdString>& testNames)
{
// set test run map to false for all
for(std::map<int, std::set<int> >::iterator i = this->Tests.begin();
i != this->Tests.end(); ++i)
{
this->TestRunningMap[i->first] = false;
this->TestFinishMap[i->first] = false;
}
this->Tests = tests;
this->TestNames = testNames;
}
// Set the max number of tests that can be run at the same time.
void cmCTestMultiProcessHandler::SetParallelLevel(size_t l)
{
this->ParallelLevel = l;
}
void cmCTestMultiProcessHandler::RunTests()
{
this->StartNextTests();
while(this->Tests.size() != 0)
{
this->CheckOutput();
this->StartNextTests();
}
// let all running tests finish
while(this->CheckOutput())
{
}
for(std::map<int, cmStdString>::iterator i =
this->TestOutput.begin();
i != this->TestOutput.end(); ++i)
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
i->second << std::endl);
}
}
void cmCTestMultiProcessHandler::StartTestProcess(int test)
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
" test " << test << "\n");
this->TestRunningMap[test] = true; // mark the test as running
// now remove the test itself
this->Tests.erase(test);
// now run the test
cmProcess* newp = new cmProcess;
newp->SetId(this->ProcessId);
newp->SetId(test);
newp->SetCommand(this->CTestCommand.c_str());
std::vector<std::string> args;
args.push_back("-I");
cmOStringStream strm;
strm << test << "," << test;
args.push_back(strm.str());
args.push_back("--parallel-cache");
args.push_back(this->CTestCacheFile.c_str());
args.push_back("--internal-ctest-parallel");
cmOStringStream strm2;
strm2 << test;
args.push_back(strm2.str());
if(this->CTest->GetExtraVerbose())
{
args.push_back("-VV");
}
newp->SetCommandArguments(args);
if(!newp->StartProcess())
{
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Error starting " << newp->GetCommand() << "\n");
this->EndTest(newp);
}
else
{
this->RunningTests.insert(newp);
}
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"ctest -I " << test << "\n");
this->ProcessId++;
}
bool cmCTestMultiProcessHandler::StartTest(int test)
{
// copy the depend tests locally because when
// a test is finished it will be removed from the depend list
// and we don't want to be iterating a list while removing from it
std::set<int> depends = this->Tests[test];
size_t totalDepends = depends.size();
if(totalDepends)
{
for(std::set<int>::const_iterator i = depends.begin();
i != depends.end(); ++i)
{
// if the test is not already running then start it
if(!this->TestRunningMap[*i])
{
// this test might be finished, but since
// this is a copy of the depend map we might
// still have it
if(!this->TestFinishMap[*i])
{
// only start one test in this function
return this->StartTest(*i);
}
else
{
// the depend has been and finished
totalDepends--;
}
}
}
}
// if there are no depends left then run this test
if(totalDepends == 0)
{
// Start this test it has no depends
this->StartTestProcess(test);
return true;
}
// This test was not able to start because it is waiting
// on depends to run
return false;
}
void cmCTestMultiProcessHandler::StartNextTests()
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl
<< "Number of running tests : " << this->RunningTests.size()
<< "\n");
size_t numToStart = this->ParallelLevel - this->RunningTests.size();
if(numToStart == 0)
{
return;
}
std::map<int, std::set<int> > tests = this->Tests;
for(std::map<int, std::set<int> >::iterator i = tests.begin();
i != tests.end(); ++i)
{
// start test should start only one test
if(this->StartTest(i->first))
{
numToStart--;
}
else
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl
<< "Test did not start waiting on depends to finish: "
<< i->first << "\n");
}
if(numToStart == 0 )
{
return;
}
}
}
bool cmCTestMultiProcessHandler::CheckOutput()
{
// no more output we are done
if(this->RunningTests.size() == 0)
{
return false;
}
std::vector<cmProcess*> finished;
std::string out, err;
for(std::set<cmProcess*>::const_iterator i = this->RunningTests.begin();
i != this->RunningTests.end(); ++i)
{
cmProcess* p = *i;
int pipe = p->CheckOutput(.1, out, err);
if(pipe == cmsysProcess_Pipe_STDOUT)
{
cmCTestLog(this->CTest, HANDLER_OUTPUT,
p->GetId() << ": " << out << std::endl);
this->TestOutput[ p->GetId() ] += out;
this->TestOutput[ p->GetId() ] += "\n";
}
else if(pipe == cmsysProcess_Pipe_STDERR)
{
cmCTestLog(this->CTest, HANDLER_OUTPUT,
p->GetId() << ": " << err << std::endl);
this->TestOutput[ p->GetId() ] += err;
this->TestOutput[ p->GetId() ] += "\n";
}
if(!p->IsRunning())
{
finished.push_back(p);
}
}
for( std::vector<cmProcess*>::iterator i = finished.begin();
i != finished.end(); ++i)
{
cmProcess* p = *i;
this->EndTest(p);
}
return true;
}
void cmCTestMultiProcessHandler::EndTest(cmProcess* p)
{
int test = p->GetId();
int exitVal = p->GetExitValue();
cmCTestTestHandler::cmCTestTestResult cres;
cres.Properties = 0;
cres.ExecutionTime = 0;// ???
cres.ReturnValue = exitVal;
cres.Status = cmCTestTestHandler::COMPLETED;
cres.TestCount = test;
cres.Name = this->TestNames[test];
cres.Path.clear();
if(exitVal)
{
cres.Status = cmCTestTestHandler::FAILED;
this->Failed->push_back(this->TestNames[test]);
}
else
{
this->Passed->push_back(this->TestNames[test]);
}
this->TestResults->push_back(cres);
// remove test from depend of all other tests
for( std::map<int, std::set<int> >::iterator i = this->Tests.begin();
i!= this->Tests.end(); ++i)
{
i->second.erase(test);
}
this->TestFinishMap[test] = true;
this->TestRunningMap[test] = false;
this->RunningTests.erase(p);
delete p;
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"finish test " << test << "\n");
}
void cmCTestMultiProcessHandler::PrintTests()
{
#undef cout
for( std::map<int, std::set<int> >::iterator i = this->Tests.begin();
i!= this->Tests.end(); ++i)
{
std::cout << "Test " << i->first << " (";
for(std::set<int>::iterator j = i->second.begin();
j != i->second.end(); ++j)
{
std::cout << *j << " ";
}
std::cout << ")\n";
}
}
#if 0
int main()
{
cmCTestMultiProcessHandler h;
h.SetParallelLevel(4);
std::map<int, std::set<int> > tests;
std::set<int> depends;
for(int i =1; i < 92; i++)
{
tests[i] = depends;
}
depends.clear();
depends.insert(45); subprject
tests[46] = depends; subproject-stage2
depends.clear();
depends.insert(55); simpleinstall simpleinstall-s2
tests[56] = depends;
depends.clear();
depends.insert(70); wrapping
tests[71] = depends; qtwrapping
depends.clear();
depends.insert(71); qtwrapping
tests[72] = depends; testdriver1
depends.clear();
depends.insert(72) testdriver1
tests[73] = depends; testdriver2
depends.clear();
depends.insert(73); testdriver2
tests[74] = depends; testdriver3
depends.clear();
depends.insert(79); linkorder1
tests[80] = depends; linkorder2
h.SetTests(tests);
h.PrintTests();
h.RunTests();
}
#endif
--- NEW FILE: cmCTestMultiProcessHandler.h ---
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile: cmCTestMultiProcessHandler.h,v $
Language: C++
Date: $Date: 2008-07-03 13:31:31 $
Version: $Revision: 1.1 $
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef cmCTestMultiProcessHandler_h
#define cmCTestMultiProcessHandler_h
#include <set>
#include <map>
#include <string>
#include <vector>
class cmProcess;
#include <cmStandardIncludes.h>
#include <cmCTestTestHandler.h>
/** \class cmCTestMultiProcessHandler
* \brief run parallel ctest
*
* cmCTestMultiProcessHandler
*/
class cmCTestMultiProcessHandler
{
public:
cmCTestMultiProcessHandler();
// Set the tests
void SetTests(std::map<int, std::set<int> >& tests,
std::map<int, cmStdString>& testNames);
// Set the max number of tests that can be run at the same time.
void SetParallelLevel(size_t);
void RunTests();
void PrintTests();
void SetCTestCommand(const char* c) { this->CTestCommand = c;}
void SetTestCacheFile(const char* c) { this->CTestCacheFile = c;}
void SetPassFailVectors(std::vector<cmStdString>* passed,
std::vector<cmStdString>* failed)
{
this->Passed = passed;
this->Failed = failed;
}
void SetTestResults(std::vector<cmCTestTestHandler::cmCTestTestResult>* r)
{
this->TestResults = r;
}
void SetCTest(cmCTest* ctest) { this->CTest = ctest;}
protected:
cmCTest* CTest;
// Start the next test or tests as many as are allowed by
// ParallelLevel
void StartNextTests();
void StartTestProcess(int test);
bool StartTest(int test);
void EndTest(cmProcess*);
// Return true if there are still tests running
// check all running processes for output and exit case
bool CheckOutput();
// map from test number to set of depend tests
std::map<int, std::set<int> > Tests;
std::map<int, cmStdString> TestNames;
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;
int ProcessId;
size_t ParallelLevel; // max number of process that can be run at once
std::set<cmProcess*> RunningTests; // current running tests
};
#endif
Index: cmCTestTestHandler.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/CTest/cmCTestTestHandler.cxx,v
retrieving revision 1.71
retrieving revision 1.72
diff -C 2 -d -r1.71 -r1.72
*** cmCTestTestHandler.cxx 17 Jun 2008 18:03:49 -0000 1.71
--- cmCTestTestHandler.cxx 3 Jul 2008 13:31:32 -0000 1.72
***************
*** 17,21 ****
#include "cmCTestTestHandler.h"
!
#include "cmCTest.h"
#include "cmake.h"
--- 17,21 ----
#include "cmCTestTestHandler.h"
! #include "cmCTestMultiProcessHandler.h"
#include "cmCTest.h"
#include "cmake.h"
***************
*** 501,509 ****
this->TestResults.clear();
!
! cmCTestLog(this->CTest, HANDLER_OUTPUT,
! (this->MemCheck ? "Memory check" : "Test")
! << " project " << cmSystemTools::GetCurrentWorkingDirectory()
! << std::endl);
if ( ! this->PreProcessHandler() )
{
--- 501,512 ----
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);
! }
if ( ! this->PreProcessHandler() )
{
***************
*** 518,522 ****
std::vector<cmStdString> failed;
int total;
-
this->ProcessDirectory(passed, failed);
--- 521,524 ----
***************
*** 551,581 ****
percent = 99;
}
! cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl
! << static_cast<int>(percent + .5) << "% tests passed, "
! << failed.size() << " tests failed out of " << total << std::endl);
! //fprintf(stderr,"\n%.0f%% tests passed, %i tests failed out of %i\n",
! // percent, int(failed.size()), total);
if (failed.size())
{
cmGeneratedFileStream ofs;
!
! 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 )
{
! 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);
}
}
-
}
}
--- 553,587 ----
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);
! }
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)
{
! 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);
! }
}
+
}
}
}
***************
*** 678,683 ****
// add the arguments
std::vector<std::string>::const_iterator j = args.begin();
! ++j;
! ++j;
std::vector<const char*> arguments;
this->GenerateTestCommand(arguments);
--- 684,689 ----
// add the arguments
std::vector<std::string>::const_iterator j = args.begin();
! ++j; // skip test name
! ++j; // skip command as it is in actualCommand
std::vector<const char*> arguments;
this->GenerateTestCommand(arguments);
***************
*** 918,938 ****
//----------------------------------------------------------------------
! void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
! std::vector<cmStdString> &failed)
{
! std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
! this->TestList.clear();
!
! this->GetListOfTests();
cmCTestTestHandler::ListOfTests::size_type tmsize = this->TestList.size();
- this->StartTest = this->CTest->CurrentTime();
- this->StartTestTime = static_cast<unsigned int>(cmSystemTools::GetTime());
- double elapsed_time_start = cmSystemTools::GetTime();
-
- *this->LogFile << "Start testing: " << this->StartTest << std::endl
- << "----------------------------------------------------------"
- << std::endl;
-
// how many tests are in based on RegExp?
int inREcnt = 0;
--- 924,941 ----
//----------------------------------------------------------------------
! void cmCTestTestHandler::ComputeTestList()
{
! this->TestList.clear(); // clear list of test
! if(this->CTest->GetParallelSubprocess())
! {
! this->LoadTestList();
! return;
! }
! else
! {
! this->GetListOfTests();
! }
cmCTestTestHandler::ListOfTests::size_type tmsize = this->TestList.size();
// how many tests are in based on RegExp?
int inREcnt = 0;
***************
*** 954,961 ****
this->ExpandTestsToRunInformation(inREcnt);
}
!
int cnt = 0;
inREcnt = 0;
! std::string last_directory = "";
for ( it = this->TestList.begin(); it != this->TestList.end(); it ++ )
{
--- 957,965 ----
this->ExpandTestsToRunInformation(inREcnt);
}
! // Now create a final list of tests to run
int cnt = 0;
inREcnt = 0;
! std::string last_directory = "";
! ListOfTests finalList;
for ( it = this->TestList.begin(); it != this->TestList.end(); it ++ )
{
***************
*** 966,986 ****
}
- // if we are out of time then skip this test, we leave two minutes
- // to submit results
- if (this->CTest->GetRemainingTimeAllowed() - 120 <= 0)
- {
- continue;
- }
-
- if (!(last_directory == it->Directory))
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Changing directory into " << it->Directory.c_str() << "\n");
- *this->LogFile << "Changing directory into: " << it->Directory.c_str()
- << std::endl;
- last_directory = it->Directory;
- cmSystemTools::ChangeDirectory(it->Directory.c_str());
- }
-
if (this->UseUnion)
{
--- 970,973 ----
***************
*** 1004,1011 ****
}
}
!
// process this one test
! this->ProcessOneTest(&(*it), passed, failed, cnt,
! static_cast<int>(tmsize));
}
--- 991,1310 ----
}
}
! it->Index = cnt; // save the index into the test list for this test
! finalList.push_back(*it);
! }
! // Save the total number of tests before exclusions
! this->TotalNumberOfTests = this->TestList.size();
! // Set the TestList to the final list of all test
! this->TestList = finalList;
! }
!
! bool cmCTestTestHandler::GetValue(const char* tag,
! int& value,
! std::ifstream& fin)
! {
! std::string line;
! cmSystemTools::GetLineFromStream(fin, line);
! if(line == tag)
! {
! fin >> value;
! cmSystemTools::GetLineFromStream(fin, line); // read blank line
! }
! else
! {
! cmCTestLog(this->CTest, ERROR_MESSAGE,
! "parse error: missing tag: "
! << tag << " found [" << line << "]" << std::endl);
! return false;
! }
! return true;
! }
!
! bool cmCTestTestHandler::GetValue(const char* tag,
! double& value,
! std::ifstream& fin)
! {
! std::string line;
! cmSystemTools::GetLineFromStream(fin, line);
! if(line == tag)
! {
! fin >> value;
! cmSystemTools::GetLineFromStream(fin, line); // read blank line
! }
! else
! {
! cmCTestLog(this->CTest, ERROR_MESSAGE,
! "parse error: missing tag: "
! << tag << " found [" << line << "]" << std::endl);
! return false;
! }
! return true;
! }
!
! bool cmCTestTestHandler::GetValue(const char* tag,
! bool& value,
! std::ifstream& fin)
! {
! std::string line;
! cmSystemTools::GetLineFromStream(fin, line);
! if(line == tag)
! {
! fin >> value;
! cmSystemTools::GetLineFromStream(fin, line); // read blank line
! }
! else
! {
! cmCTestLog(this->CTest, ERROR_MESSAGE,
! "parse error: missing tag: "
! << tag << " found [" << line << "]" << std::endl);
! return false;
! }
! return true;
! }
!
! bool cmCTestTestHandler::GetValue(const char* tag,
! size_t& value,
! std::ifstream& fin)
! {
! std::string line;
! cmSystemTools::GetLineFromStream(fin, line);
! if(line == tag)
! {
! fin >> value;
! cmSystemTools::GetLineFromStream(fin, line); // read blank line
! }
! else
! {
! cmCTestLog(this->CTest, ERROR_MESSAGE,
! "parse error: missing tag: "
! << tag << " found [" << line.c_str() << "]" << std::endl);
! return false;
! }
! return true;
! }
!
! bool cmCTestTestHandler::GetValue(const char* tag,
! std::string& value,
! std::ifstream& fin)
! {
! std::string line;
! cmSystemTools::GetLineFromStream(fin, line);
! if(line == tag)
! {
! return cmSystemTools::GetLineFromStream(fin, value);
! }
! else
! {
! cmCTestLog(this->CTest, ERROR_MESSAGE,
! "parse error: missing tag: "
! << tag << " found [" << line << "]" << std::endl);
! return false;
! }
! return true;
! }
!
!
! // 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()
! {
! 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;
! 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;
! bool 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 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);
! if(!ok)
! {
! 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";
! 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";
! }
! fout << "IsInBasedOnREOptions:\n"
! << p.IsInBasedOnREOptions
! << "\nWillFail:\n"
! << p.WillFail
! << "\nTimeOut:\n"
! << p.Timeout
! << "\nIndex:\n"
! << p.Index << "\n";
! }
! fout.close();
! return fname;
! }
!
! void cmCTestTestHandler::ProcessParallel(std::vector<cmStdString> &passed,
! std::vector<cmStdString> &failed)
! {
! this->ComputeTestList();
! cmCTestMultiProcessHandler parallel;
! parallel.SetCTest(this->CTest);
! parallel.SetParallelLevel(this->CTest->GetParallelLevel());
! std::set<int> depends;
! std::map<int, std::set<int> > tests;
! std::map<int, cmStdString> testnames;
! for (ListOfTests::iterator it = this->TestList.begin();
! it != this->TestList.end(); it ++ )
! {
! cmCTestTestProperties& p = *it;
! testnames[p.Index] = p.Name;
! if(p.Depends.size())
! {
! for(std::vector<std::string>::iterator i = p.Depends.begin();
! i != p.Depends.end(); ++i)
! {
! for(ListOfTests::iterator it2 = this->TestList.begin();
! it2 != this->TestList.end(); it2 ++ )
! {
! if(it2->Name == *i)
! {
! depends.insert(it2->Index);
! break; // break out of test loop as name can only match 1
! }
! }
! }
! }
! tests[it->Index] = depends;
! }
! parallel.SetCTestCommand(this->CTest->GetCTestExecutable());
! parallel.SetTests(tests, testnames);
! std::string fname = this->SaveTestList();
! parallel.SetTestCacheFile(fname.c_str());
! parallel.SetPassFailVectors(&passed, &failed);
! this->TestResults.clear();
! parallel.SetTestResults(&this->TestResults);
! parallel.RunTests();
! cmSystemTools::RemoveFile(fname.c_str());
! }
!
!
! //----------------------------------------------------------------------
! void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
! std::vector<cmStdString> &failed)
! {
! if(this->CTest->GetParallelLevel() > 0)
! {
! this->ProcessParallel(passed, failed);
! return;
! }
! // save the current working directory
! std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
! // compute the list of tests to run
! this->ComputeTestList();
! this->StartTest = this->CTest->CurrentTime();
! this->StartTestTime = static_cast<unsigned int>(cmSystemTools::GetTime());
! double elapsed_time_start = cmSystemTools::GetTime();
! *this->LogFile << "Start testing: " << this->StartTest << std::endl
! << "----------------------------------------------------------"
! << std::endl;
! std::string last_directory = "";
! // run each test
! for (ListOfTests::iterator it = this->TestList.begin();
! it != this->TestList.end(); it ++ )
! {
! if (!(last_directory == it->Directory))
! {
! cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
! "Changing directory into " << it->Directory.c_str() << "\n");
! *this->LogFile << "Changing directory into: " << it->Directory.c_str()
! << std::endl;
! last_directory = it->Directory;
! cmSystemTools::ChangeDirectory(it->Directory.c_str());
! }
// process this one test
! this->ProcessOneTest(&(*it), passed, failed, it->Index,
! static_cast<int>(this->TotalNumberOfTests));
}
***************
*** 1891,1894 ****
--- 2190,2204 ----
}
}
+ if ( key == "DEPENDS" )
+ {
+ std::vector<std::string> lval;
+ cmSystemTools::ExpandListArgument(val.c_str(), lval);
+ std::vector<std::string>::iterator crit;
+ for ( crit = lval.begin(); crit != lval.end(); ++ crit )
+ {
+ cmCTestTestProperties* tp = &(*rtit);
+ rtit->Depends.push_back(*crit);
+ }
+ }
if ( key == "MEASUREMENT" )
{
Index: cmCTestTestHandler.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/CTest/cmCTestTestHandler.h,v
retrieving revision 1.27
retrieving revision 1.28
diff -C 2 -d -r1.27 -r1.28
*** cmCTestTestHandler.h 30 Jan 2008 16:17:36 -0000 1.27
--- cmCTestTestHandler.h 3 Jul 2008 13:31:32 -0000 1.28
***************
*** 81,84 ****
--- 81,85 ----
cmStdString Directory;
std::vector<std::string> Args;
+ std::vector<std::string> Depends;
std::vector<std::pair<cmsys::RegularExpression,
std::string> > ErrorRegularExpressions;
***************
*** 89,92 ****
--- 90,94 ----
bool WillFail;
double Timeout;
+ int Index;
};
***************
*** 121,124 ****
--- 123,127 ----
protected:
+ // comput a final test list
virtual int PreProcessHandler();
virtual int PostProcessHandler();
***************
*** 153,157 ****
! private:
enum { // Program statuses
NOT_RUN = 0,
--- 156,160 ----
! public:
enum { // Program statuses
NOT_RUN = 0,
***************
*** 167,171 ****
};
!
/**
* Generate the Dart compatible output
--- 170,174 ----
};
! private:
/**
* Generate the Dart compatible output
***************
*** 184,188 ****
*/
void GetListOfTests();
!
/**
* Find the executable for a test
--- 187,216 ----
*/
void GetListOfTests();
! // compute the lists of tests that will actually run
! // 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);
! bool GetValue(const char* tag,
! int& value,
! std::ifstream& fin);
! bool GetValue(const char* tag,
! size_t& value,
! std::ifstream& fin);
! bool GetValue(const char* tag,
! bool& value,
! std::ifstream& fin);
! bool GetValue(const char* tag,
! double& value,
! std::ifstream& fin);
! // run in -j N mode
! void ProcessParallel(std::vector<cmStdString> &passed,
! std::vector<cmStdString> &failed);
/**
* Find the executable for a test
***************
*** 211,214 ****
--- 239,243 ----
bool UseUnion;
ListOfTests TestList;
+ size_t TotalNumberOfTests;
cmsys::RegularExpression DartStuff;
Index: cmCTestGenericHandler.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/CTest/cmCTestGenericHandler.cxx,v
retrieving revision 1.16
retrieving revision 1.17
diff -C 2 -d -r1.16 -r1.17
*** cmCTestGenericHandler.cxx 28 Aug 2007 17:46:57 -0000 1.16
--- cmCTestGenericHandler.cxx 3 Jul 2008 13:31:30 -0000 1.17
***************
*** 162,165 ****
--- 162,171 ----
}
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) )
{
More information about the Cmake-commits
mailing list