summaryrefslogtreecommitdiffstats
path: root/Source/CTest
diff options
context:
space:
mode:
authorZach Mullen <zach.mullen@kitware.com>2009-11-02 17:52:50 (GMT)
committerZach Mullen <zach.mullen@kitware.com>2009-11-02 17:52:50 (GMT)
commitd47ada823abbed75f20e086176d5345ca0fb965a (patch)
treedc9d0d3dee184c06c79bdda64bbee352be2c70df /Source/CTest
parent59f6f383e9f87ee39f8cef7984b2993204fbd214 (diff)
downloadCMake-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.
Diffstat (limited to 'Source/CTest')
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx51
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.h2
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