diff options
Diffstat (limited to 'Source/CTest/cmCTestMultiProcessHandler.cxx')
-rw-r--r-- | Source/CTest/cmCTestMultiProcessHandler.cxx | 115 |
1 files changed, 74 insertions, 41 deletions
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index dcef8a0..f026001 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -5,7 +5,6 @@ #include "cmAffinity.h" #include "cmCTest.h" #include "cmCTestRunTest.h" -#include "cmCTestScriptHandler.h" #include "cmCTestTestHandler.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" @@ -15,7 +14,6 @@ #include "cmUVSignalHackRAII.h" // IWYU pragma: keep #include "cmsys/FStream.hxx" -#include "cmsys/String.hxx" #include "cmsys/SystemInformation.hxx" #include <algorithm> @@ -53,11 +51,11 @@ cmCTestMultiProcessHandler::cmCTestMultiProcessHandler() { this->ParallelLevel = 1; this->TestLoad = 0; + this->FakeLoadForTesting = 0; this->Completed = 0; this->RunningCount = 0; this->ProcessorsAvailable = cmAffinity::GetProcessorsAvailable(); this->HaveAffinity = this->ProcessorsAvailable.size(); - this->StopTimePassed = false; this->HasCycles = false; this->SerialTestRunning = false; } @@ -97,6 +95,16 @@ void cmCTestMultiProcessHandler::SetParallelLevel(size_t level) void cmCTestMultiProcessHandler::SetTestLoad(unsigned long load) { this->TestLoad = load; + + std::string fake_load_value; + if (cmSystemTools::GetEnv("__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING", + fake_load_value)) { + if (!cmSystemTools::StringToULong(fake_load_value.c_str(), + &this->FakeLoadForTesting)) { + cmSystemTools::Error("Failed to parse fake load value: ", + fake_load_value.c_str()); + } + } } void cmCTestMultiProcessHandler::RunTests() @@ -121,17 +129,6 @@ void cmCTestMultiProcessHandler::RunTests() bool cmCTestMultiProcessHandler::StartTestProcess(int test) { - std::chrono::system_clock::time_point stop_time = this->CTest->GetStopTime(); - if (stop_time != std::chrono::system_clock::time_point() && - stop_time <= std::chrono::system_clock::now()) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "The stop time has been passed. " - "Stopping all tests." - << std::endl); - this->StopTimePassed = true; - return false; - } - if (this->HaveAffinity && this->Properties[test]->WantAffinity) { size_t needProcessors = this->GetProcessorsUsed(test); if (needProcessors > this->ProcessorsAvailable.size()) { @@ -181,7 +178,7 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) this->Properties[test]->Directory + " : " + std::strerror(workdir.GetLastResult())); } else { - if (testRun->StartTest(this->Total)) { + if (testRun->StartTest(this->Completed, this->Total)) { return true; } } @@ -190,6 +187,30 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) return false; } +bool cmCTestMultiProcessHandler::CheckStopTimePassed() +{ + if (!this->StopTimePassed) { + std::chrono::system_clock::time_point stop_time = + this->CTest->GetStopTime(); + if (stop_time != std::chrono::system_clock::time_point() && + stop_time <= std::chrono::system_clock::now()) { + this->SetStopTimePassed(); + } + } + return this->StopTimePassed; +} + +void cmCTestMultiProcessHandler::SetStopTimePassed() +{ + if (!this->StopTimePassed) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "The stop time has been passed. " + "Stopping all tests." + << std::endl); + this->StopTimePassed = true; + } +} + void cmCTestMultiProcessHandler::LockResources(int index) { this->LockedResources.insert( @@ -259,12 +280,23 @@ bool cmCTestMultiProcessHandler::StartTest(int test) void cmCTestMultiProcessHandler::StartNextTests() { - size_t numToStart = 0; + if (this->TestLoadRetryTimer.get() != nullptr) { + // This timer may be waiting to call StartNextTests again. + // Since we have been called it is no longer needed. + uv_timer_stop(this->TestLoadRetryTimer); + } if (this->Tests.empty()) { + this->TestLoadRetryTimer.reset(); return; } + if (this->CheckStopTimePassed()) { + return; + } + + size_t numToStart = 0; + if (this->RunningCount < this->ParallelLevel) { numToStart = this->ParallelLevel - this->RunningCount; } @@ -280,7 +312,6 @@ void cmCTestMultiProcessHandler::StartNextTests() } bool allTestsFailedTestLoadCheck = false; - bool usedFakeLoadForTesting = false; size_t minProcessorsRequired = this->ParallelLevel; std::string testWithMinProcessors; @@ -293,15 +324,11 @@ void cmCTestMultiProcessHandler::StartNextTests() allTestsFailedTestLoadCheck = true; // Check for a fake load average value used in testing. - std::string fake_load_value; - if (cmSystemTools::GetEnv("__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING", - fake_load_value)) { - usedFakeLoadForTesting = true; - if (!cmSystemTools::StringToULong(fake_load_value.c_str(), - &systemLoad)) { - cmSystemTools::Error("Failed to parse fake load value: ", - fake_load_value.c_str()); - } + if (this->FakeLoadForTesting > 0) { + systemLoad = this->FakeLoadForTesting; + // Drop the fake load for the next iteration to a value low enough + // that the next iteration will start tests. + this->FakeLoadForTesting = 1; } // If it's not set, look up the true load average. else { @@ -347,10 +374,6 @@ void cmCTestMultiProcessHandler::StartNextTests() } if (testLoadOk && processors <= numToStart && this->StartTest(test)) { - if (this->StopTimePassed) { - return; - } - numToStart -= processors; } else if (numToStart == 0) { break; @@ -385,18 +408,25 @@ void cmCTestMultiProcessHandler::StartNextTests() } cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl); - if (usedFakeLoadForTesting) { - // Break out of the infinite loop of waiting for our fake load - // to come down. - this->StopTimePassed = true; - } else { - // Wait between 1 and 5 seconds before trying again. - cmCTestScriptHandler::SleepInSeconds(cmSystemTools::RandomSeed() % 5 + - 1); + // Wait between 1 and 5 seconds before trying again. + unsigned int milliseconds = (cmSystemTools::RandomSeed() % 5 + 1) * 1000; + if (this->FakeLoadForTesting) { + milliseconds = 10; } + if (this->TestLoadRetryTimer.get() == nullptr) { + this->TestLoadRetryTimer.init(this->Loop, this); + } + this->TestLoadRetryTimer.start( + &cmCTestMultiProcessHandler::OnTestLoadRetryCB, milliseconds, 0); } } +void cmCTestMultiProcessHandler::OnTestLoadRetryCB(uv_timer_t* timer) +{ + auto self = static_cast<cmCTestMultiProcessHandler*>(timer->data); + self->StartNextTests(); +} + void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner, bool started) { @@ -406,8 +436,11 @@ void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner, auto properties = runner->GetTestProperties(); bool testResult = runner->EndTest(this->Completed, this->Total, started); + if (runner->TimedOutForStopTime()) { + this->SetStopTimePassed(); + } if (started) { - if (runner->StartAgain()) { + if (!this->StopTimePassed && runner->StartAgain(this->Completed)) { this->Completed--; // remove the completed test because run again return; } @@ -458,7 +491,7 @@ void cmCTestMultiProcessHandler::UpdateCostData() if (line == "---") { break; } - std::vector<cmsys::String> parts = cmSystemTools::SplitString(line, ' '); + std::vector<std::string> parts = cmSystemTools::SplitString(line, ' '); // Format: <name> <previous_runs> <avg_cost> if (parts.size() < 3) { break; @@ -511,7 +544,7 @@ void cmCTestMultiProcessHandler::ReadCostData() break; } - std::vector<cmsys::String> parts = cmSystemTools::SplitString(line, ' '); + std::vector<std::string> parts = cmSystemTools::SplitString(line, ' '); // Probably an older version of the file, will be fixed next run if (parts.size() < 3) { |