diff options
author | Zach Mullen <zach.mullen@kitware.com> | 2009-11-02 17:52:50 (GMT) |
---|---|---|
committer | Zach Mullen <zach.mullen@kitware.com> | 2009-11-02 17:52:50 (GMT) |
commit | d47ada823abbed75f20e086176d5345ca0fb965a (patch) | |
tree | dc9d0d3dee184c06c79bdda64bbee352be2c70df | |
parent | 59f6f383e9f87ee39f8cef7984b2993204fbd214 (diff) | |
download | CMake-d47ada823abbed75f20e086176d5345ca0fb965a.zip CMake-d47ada823abbed75f20e086176d5345ca0fb965a.tar.gz CMake-d47ada823abbed75f20e086176d5345ca0fb965a.tar.bz2 |
Added logic to check for cycles in the test dependency graph before any tests are run. Previously a cycle resulted in a segfault from stack overflow.
-rw-r--r-- | Source/CTest/cmCTestMultiProcessHandler.cxx | 51 | ||||
-rw-r--r-- | Source/CTest/cmCTestMultiProcessHandler.h | 2 |
2 files changed, 52 insertions, 1 deletions
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 024599c..4f3a605 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -15,6 +15,7 @@ #include "cmCTest.h" #include "cmSystemTools.h" #include <stdlib.h> +#include <stack> cmCTestMultiProcessHandler::cmCTestMultiProcessHandler() { @@ -56,6 +57,10 @@ void cmCTestMultiProcessHandler::SetParallelLevel(size_t level) void cmCTestMultiProcessHandler::RunTests() { this->CheckResume(); + if(!this->CheckCycles()) + { + return; + } this->TestHandler->SetMaxIndex(this->FindMaxIndex()); this->StartNextTests(); while(this->Tests.size() != 0) @@ -340,7 +345,7 @@ void cmCTestMultiProcessHandler::PrintTestList() this->TestHandler->SetMaxIndex(this->FindMaxIndex()); int count = 0; for (PropertiesMap::iterator it = this->Properties.begin(); - it != this->Properties.end(); it ++ ) + it != this->Properties.end(); ++it) { count++; cmCTestTestHandler::cmCTestTestProperties& p = *it->second; @@ -433,3 +438,47 @@ int cmCTestMultiProcessHandler::FindMaxIndex() } return max; } + +//Returns true if no cycles exist in the dependency graph +bool cmCTestMultiProcessHandler::CheckCycles() +{ + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "Checking test dependency graph..." << std::endl); + for(TestMap::iterator it = this->Tests.begin(); + it != this->Tests.end(); ++it) + { + //DFS from each element to itself + std::stack<int> s; + std::vector<int> visited; + s.push(it->first); + visited.push_back(it->first); + + while(!s.empty()) + { + int test = s.top(); + s.pop(); + + for(TestSet::iterator d = this->Tests[test].begin(); + d != this->Tests[test].end(); ++d) + { + s.push(*d); + for(std::vector<int>::iterator v = visited.begin(); + v != visited.end(); ++v) + { + if(*v == *d) + { + //cycle exists + cmCTestLog(this->CTest, ERROR_MESSAGE, "Error: a cycle exists in " + "the test dependency graph for the test \"" + << this->Properties[*d]->Name << "\"." << std::endl + << "Please fix the cycle and run ctest again." << std::endl); + return false; + } + } + visited.push_back(*d); + } + visited.pop_back(); + } + } + return true; +} diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index c99eb3d..16591b0 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -76,6 +76,8 @@ protected: void RemoveTest(int index); //Check if we need to resume an interrupted test set void CheckResume(); + //Check if there are any circular dependencies + bool CheckCycles(); int FindMaxIndex(); inline size_t GetProcessorsUsed(int index); // map from test number to set of depend tests |