summaryrefslogtreecommitdiffstats
path: root/Source/CTest
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CTest')
-rw-r--r--Source/CTest/cmCTestBuildCommand.h8
-rw-r--r--Source/CTest/cmCTestBuildHandler.cxx4
-rw-r--r--Source/CTest/cmCTestGIT.cxx9
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx151
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.h6
-rw-r--r--Source/CTest/cmCTestRunTest.cxx29
-rw-r--r--Source/CTest/cmCTestRunTest.h3
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx12
-rw-r--r--Source/CTest/cmProcess.cxx6
-rw-r--r--Source/CTest/cmProcess.h2
10 files changed, 137 insertions, 93 deletions
diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h
index 228067e..9eb4907 100644
--- a/Source/CTest/cmCTestBuildCommand.h
+++ b/Source/CTest/cmCTestBuildCommand.h
@@ -60,10 +60,12 @@ public:
virtual const char* GetFullDocumentation()
{
return
- " ctest_build([BUILD build_dir] [RETURN_VALUE res] [APPEND]\n"
- " [NUMBER_ERRORS val] [NUMBER_WARNINGS val])\n"
+ " ctest_build([BUILD build_dir] [TARGET target] [RETURN_VALUE res]\n"
+ " [APPEND][NUMBER_ERRORS val] [NUMBER_WARNINGS val])\n"
"Builds the given build directory and stores results in Build.xml. "
- "If no BUILD is given, the CTEST_BINARY_DIRECTORY variable is used. "
+ "If no BUILD is given, the CTEST_BINARY_DIRECTORY variable is used.\n"
+ "The TARGET variable can be used to specify a build target. If none "
+ "is specified, the \"all\" target will be built.\n"
"The RETURN_VALUE option specifies a variable in which to store the "
"return value of the native build tool. "
"The NUMBER_ERRORS and NUMBER_WARNINGS options specify variables in "
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 619783f..3c5993d 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -974,7 +974,7 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command,
this->ProcessBuffer(0, 0, tick, tick_len, ofs,
&this->BuildProcessingErrorQueue);
cmCTestLog(this->CTest, OUTPUT, " Size of output: "
- << int(this->BuildOutputLogSize / 1024.0) << "K" << std::endl);
+ << ((this->BuildOutputLogSize + 512) / 1024) << "K" << std::endl);
// Properly handle output of the build command
cmsysProcess_WaitForExit(cp, 0);
@@ -1186,7 +1186,7 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, int length,
if ( tick % tick_line_len == 0 && tick > 0 )
{
cmCTestLog(this->CTest, HANDLER_OUTPUT, " Size: "
- << int((this->BuildOutputLogSize / 1024.0) + 1) << "K" << std::endl
+ << ((this->BuildOutputLogSize + 512) / 1024) << "K" << std::endl
<< " ");
}
}
diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx
index 6c3631c..a49c852 100644
--- a/Source/CTest/cmCTestGIT.cxx
+++ b/Source/CTest/cmCTestGIT.cxx
@@ -317,8 +317,12 @@ protected:
\n
Log message indented by (4) spaces\n
(even blank lines have the spaces)\n
+ [[
\n
[Diff format]
+ OR
+ \0
+ ]]
The header may have more fields. See 'git help diff-tree'.
*/
@@ -372,6 +376,11 @@ private:
{
if(this->Line.empty())
{
+ if(this->Section == SectionBody && this->LineEnd == '\0')
+ {
+ // Skip SectionDiff
+ this->NextSection();
+ }
this->NextSection();
}
else
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 8a69780..d50eaaa 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -18,11 +18,29 @@
#include <stack>
#include <float.h>
+class TestComparator
+{
+public:
+ TestComparator(cmCTestMultiProcessHandler* handler) : Handler(handler) {}
+ ~TestComparator() {}
+
+ // Sorts tests in descending order of cost
+ bool operator() (int index1, int index2) const
+ {
+ return Handler->Properties[index1]->Cost >
+ Handler->Properties[index2]->Cost;
+ }
+
+private:
+ cmCTestMultiProcessHandler* Handler;
+};
+
cmCTestMultiProcessHandler::cmCTestMultiProcessHandler()
{
this->ParallelLevel = 1;
this->Completed = 0;
this->RunningCount = 0;
+ this->StopTimePassed = false;
}
cmCTestMultiProcessHandler::~cmCTestMultiProcessHandler()
@@ -69,6 +87,10 @@ void cmCTestMultiProcessHandler::RunTests()
this->StartNextTests();
while(this->Tests.size() != 0)
{
+ if(this->StopTimePassed)
+ {
+ return;
+ }
this->CheckOutput();
this->StartNextTests();
}
@@ -87,6 +109,7 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test)
this->TestRunningMap[test] = true; // mark the test as running
// now remove the test itself
this->EraseTest(test);
+ this->RunningCount += GetProcessorsUsed(test);
cmCTestRunTest* testRun = new cmCTestRunTest(this->TestHandler);
testRun->SetIndex(test);
@@ -102,6 +125,12 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test)
{
this->RunningTests.insert(testRun);
}
+ else if(testRun->IsStopTimePassed())
+ {
+ this->StopTimePassed = true;
+ delete testRun;
+ return;
+ }
else
{
this->UnlockResources(test);
@@ -142,15 +171,8 @@ void cmCTestMultiProcessHandler::UnlockResources(int index)
void cmCTestMultiProcessHandler::EraseTest(int test)
{
this->Tests.erase(test);
- for(TestCostMap::iterator i = this->TestCosts.begin();
- i != this->TestCosts.end(); ++i)
- {
- if(i->second.find(test) != i->second.end())
- {
- i->second.erase(test);
- return;
- }
- }
+ this->SortedTests.erase(
+ std::find(this->SortedTests.begin(), this->SortedTests.end(), test));
}
//---------------------------------------------------------
@@ -232,38 +254,36 @@ void cmCTestMultiProcessHandler::StartNextTests()
return;
}
- for(TestCostMap::reverse_iterator i = this->TestCosts.rbegin();
- i != this->TestCosts.rend(); ++i)
+ TestList copy = this->SortedTests;
+ for(TestList::iterator test = copy.begin(); test != copy.end(); ++test)
{
- TestSet tests = i->second; //copy the test set
- for(TestSet::iterator test = tests.begin();
- test != tests.end(); ++test)
+ //in case this test has already been started due to dependency
+ if(this->TestRunningMap[*test] || this->TestFinishMap[*test])
{
- //in case this test has already been started due to dependency
- if(this->TestRunningMap[*test] || this->TestFinishMap[*test])
- {
- continue;
- }
- size_t processors = GetProcessorsUsed(*test);
- if(processors > numToStart)
- {
- return;
- }
- if(this->StartTest(*test))
- {
- numToStart -= processors;
- this->RunningCount += processors;
- }
- else
- {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl
- << "Test did not start waiting on depends to finish: "
- << *test << "\n");
- }
- if(numToStart == 0)
+ continue;
+ }
+ size_t processors = GetProcessorsUsed(*test);
+ if(processors > numToStart)
+ {
+ return;
+ }
+ if(this->StartTest(*test))
+ {
+ if(this->StopTimePassed)
{
return;
}
+ numToStart -= processors;
+ }
+ else
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl
+ << "Test did not start waiting on depends to finish: "
+ << *test << "\n");
+ }
+ if(numToStart == 0)
+ {
+ return;
}
}
}
@@ -453,26 +473,22 @@ void cmCTestMultiProcessHandler::CreateTestCostList()
for(TestMap::iterator i = this->Tests.begin();
i != this->Tests.end(); ++i)
{
- //We only want to schedule them by cost in a parallel situation
- if(this->ParallelLevel > 1)
- {
- std::string name = this->Properties[i->first]->Name;
- if(std::find(this->LastTestsFailed.begin(), this->LastTestsFailed.end(),
- name) != this->LastTestsFailed.end())
- {
- this->TestCosts[FLT_MAX].insert(i->first);
- }
- else
- {
- this->TestCosts[this->Properties[i->first]->Cost].insert(i->first);
- }
- }
- else //we ignore their cost
+ SortedTests.push_back(i->first);
+
+ //If the test failed last time, it should be run first, so max the cost
+ if(std::find(this->LastTestsFailed.begin(),
+ this->LastTestsFailed.end(),
+ this->Properties[i->first]->Name)
+ != this->LastTestsFailed.end())
{
- this->TestCosts[this->Tests.size()
- - this->Properties[i->first]->Index].insert(i->first);
+ this->Properties[i->first]->Cost = FLT_MAX;
}
}
+ if(this->ParallelLevel > 1)
+ {
+ TestComparator comp(this);
+ std::sort(SortedTests.begin(), SortedTests.end(), comp);
+ }
}
//---------------------------------------------------------
@@ -595,7 +611,7 @@ int cmCTestMultiProcessHandler::FindMaxIndex()
//Returns true if no cycles exist in the dependency graph
bool cmCTestMultiProcessHandler::CheckCycles()
{
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Checking test dependency graph..." << std::endl);
for(TestMap::iterator it = this->Tests.begin();
it != this->Tests.end(); ++it)
@@ -603,34 +619,29 @@ bool cmCTestMultiProcessHandler::CheckCycles()
//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(std::find(visited.begin(), visited.end(), *d) != visited.end())
{
- 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;
- }
+ //cycle exists
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "Error: a cycle exists in "
+ "the test dependency graph for the test \""
+ << this->Properties[it->first]->Name << "\"." << std::endl
+ << "Please fix the cycle and run ctest again." << std::endl);
+ return false;
}
- visited.push_back(*d);
+ s.push(*d);
}
- visited.pop_back();
+ visited.push_back(test);
}
}
return true;
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index d4f6c71..cc330f7 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -23,10 +23,11 @@
*/
class cmCTestMultiProcessHandler
{
+ friend class TestComparator;
public:
struct TestSet : public std::set<int> {};
struct TestMap : public std::map<int, TestSet> {};
- struct TestCostMap : public std::map<float, TestSet> {};
+ struct TestList : public std::vector<int> {};
struct PropertiesMap : public
std::map<int, cmCTestTestHandler::cmCTestTestProperties*> {};
@@ -88,12 +89,13 @@ protected:
void UnlockResources(int index);
// map from test number to set of depend tests
TestMap Tests;
- TestCostMap TestCosts;
+ TestList SortedTests;
//Total number of tests we'll be running
size_t Total;
//Number of tests that are complete
size_t Completed;
size_t RunningCount;
+ bool StopTimePassed;
//list of test properties (indices concurrent to the test map)
PropertiesMap Properties;
std::map<int, bool> TestRunningMap;
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 4c9675b..ce44097 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -32,6 +32,7 @@ cmCTestRunTest::cmCTestRunTest(cmCTestTestHandler* handler)
this->ProcessOutput = "";
this->CompressedOutput = "";
this->CompressionRatio = 2;
+ this->StopTimePassed = false;
}
cmCTestRunTest::~cmCTestRunTest()
@@ -82,7 +83,8 @@ void cmCTestRunTest::CompressOutput()
reinterpret_cast<unsigned char*>(
const_cast<char*>(this->ProcessOutput.c_str()));
//zlib makes the guarantee that this is the maximum output size
- int outSize = static_cast<int>(this->ProcessOutput.size() * 1.001 + 13);
+ int outSize = static_cast<int>(
+ static_cast<double>(this->ProcessOutput.size()) * 1.001 + 13.0);
unsigned char* out = new unsigned char[outSize];
strm.zalloc = Z_NULL;
@@ -220,7 +222,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
{
outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Exception: ");
- switch ( retVal )
+ switch(this->TestProcess->GetExitException())
{
case cmsysProcess_Exception_Fault:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "SegFault");
@@ -341,13 +343,14 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
//----------------------------------------------------------------------
void cmCTestRunTest::ComputeWeightedCost()
{
- int prev = this->TestProperties->PreviousRuns;
- float avgcost = this->TestProperties->Cost;
+ double prev = static_cast<double>(this->TestProperties->PreviousRuns);
+ double avgcost = static_cast<double>(this->TestProperties->Cost);
double current = this->TestResult.ExecutionTime;
if(this->TestResult.Status == cmCTestTestHandler::COMPLETED)
{
- this->TestProperties->Cost = ((prev * avgcost) + current) / (prev + 1);
+ this->TestProperties->Cost =
+ static_cast<float>(((prev * avgcost) + current) / (prev + 1.0));
this->TestProperties->PreviousRuns++;
}
}
@@ -436,8 +439,13 @@ bool cmCTestRunTest::StartTest(size_t total)
}
this->StartTime = this->CTest->CurrentTime();
- return this->ForkProcess(this->ResolveTimeout(),
- &this->TestProperties->Environment);
+ double timeout = this->ResolveTimeout();
+
+ if(this->StopTimePassed)
+ {
+ return false;
+ }
+ return this->ForkProcess(timeout, &this->TestProperties->Environment);
}
//----------------------------------------------------------------------
@@ -563,14 +571,15 @@ double cmCTestRunTest::ResolveTimeout()
{
stop_time += 24*60*60;
}
- int stop_timeout = (stop_time - current_time) % (24*60*60);
+ int stop_timeout = static_cast<int>(stop_time - current_time) % (24*60*60);
this->CTest->LastStopTimeout = stop_timeout;
if(stop_timeout <= 0 || stop_timeout > this->CTest->LastStopTimeout)
{
cmCTestLog(this->CTest, ERROR_MESSAGE, "The stop time has been passed. "
- "Exiting ctest." << std::endl);
- exit(-1);
+ "Stopping all tests." << std::endl);
+ this->StopTimePassed = true;
+ return 0;
}
return timeout == 0 ? stop_timeout :
(timeout < stop_timeout ? timeout : stop_timeout);
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index d7d3a2f..e0cb888 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -39,6 +39,8 @@ public:
std::string GetProcessOutput() { return this->ProcessOutput; }
+ bool IsStopTimePassed() { return this->StopTimePassed; }
+
cmCTestTestHandler::cmCTestTestResult GetTestResults()
{ return this->TestResult; }
@@ -90,6 +92,7 @@ private:
std::string TestCommand;
std::string ActualCommand;
std::vector<std::string> Arguments;
+ bool StopTimePassed;
};
inline int getNumWidth(size_t n)
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index b9cee6c..a4a4863 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -1036,9 +1036,9 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
bool randomSchedule = this->CTest->GetScheduleType() == "Random";
if(randomSchedule)
- {
+ {
srand((unsigned)time(0));
- }
+ }
for (ListOfTests::iterator it = this->TestList.begin();
it != this->TestList.end(); ++it)
@@ -1048,7 +1048,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
if(randomSchedule)
{
- p.Cost = rand();
+ p.Cost = static_cast<float>(rand());
}
if(p.Timeout == 0 && this->CTest->GetGlobalTimeout() != 0)
@@ -1309,7 +1309,8 @@ std::string cmCTestTestHandler::EncodeFile(std::string file)
cmSystemTools::RemoveFile(tarFile.c_str());
unsigned char *encoded_buffer
- = new unsigned char [ static_cast<int>(len * 1.5 + 5) ];
+ = new unsigned char [ static_cast<int>(
+ static_cast<double>(len) * 1.5 + 5.0) ];
unsigned long rlen
= cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1);
@@ -1881,7 +1882,8 @@ std::string cmCTestTestHandler::GenerateRegressionImages(
unsigned char *file_buffer = new unsigned char [ len + 1 ];
ifs.read(reinterpret_cast<char*>(file_buffer), len);
unsigned char *encoded_buffer
- = new unsigned char [ static_cast<int>(len * 1.5 + 5) ];
+ = new unsigned char [ static_cast<int>(
+ static_cast<double>(len) * 1.5 + 5.0) ];
unsigned long rlen
= cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1);
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index 9aa40d6..0ee631f 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -264,3 +264,9 @@ int cmProcess::ReportStatus()
return result;
}
+
+
+int cmProcess::GetExitException()
+{
+ return cmsysProcess_GetExitException(this->Process);
+}
diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h
index 01dacf9..ff99ca2 100644
--- a/Source/CTest/cmProcess.h
+++ b/Source/CTest/cmProcess.h
@@ -43,7 +43,7 @@ public:
void SetId(int id) { this->Id = id;}
int GetExitValue() { return this->ExitValue;}
double GetTotalTime() { return this->TotalTime;}
-
+ int GetExitException();
/**
* Read one line of output but block for no more than timeout.
* Returns: