summaryrefslogtreecommitdiffstats
path: root/Source/CTest/cmCTestRunTest.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CTest/cmCTestRunTest.cxx')
-rw-r--r--Source/CTest/cmCTestRunTest.cxx124
1 files changed, 83 insertions, 41 deletions
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index abdb643..a056f4b 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -1,5 +1,9 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+#ifdef _WIN32
+/* windows.h defines min() and max() macros that interfere. */
+#define NOMINMAX
+#endif
#include "cmCTestRunTest.h"
#include "cmCTest.h"
@@ -14,6 +18,8 @@
#include "cmsys/Base64.h"
#include "cmsys/Process.h"
#include "cmsys/RegularExpression.hxx"
+#include <algorithm>
+#include <chrono>
#include <iomanip>
#include <sstream>
#include <stdio.h>
@@ -25,7 +31,7 @@ cmCTestRunTest::cmCTestRunTest(cmCTestTestHandler* handler)
this->CTest = handler->CTest;
this->TestHandler = handler;
this->TestProcess = nullptr;
- this->TestResult.ExecutionTime = 0;
+ this->TestResult.ExecutionTime = std::chrono::duration<double>::zero();
this->TestResult.ReturnValue = 0;
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
this->TestResult.TestCount = 0;
@@ -46,10 +52,11 @@ cmCTestRunTest::~cmCTestRunTest()
bool cmCTestRunTest::CheckOutput()
{
// Read lines for up to 0.1 seconds of total time.
- double timeout = 0.1;
- double timeEnd = cmSystemTools::GetTime() + timeout;
+ std::chrono::duration<double> timeout = std::chrono::milliseconds(100);
+ auto timeEnd = std::chrono::steady_clock::now() + timeout;
std::string line;
- while ((timeout = timeEnd - cmSystemTools::GetTime(), timeout > 0)) {
+ while ((timeout = timeEnd - std::chrono::steady_clock::now(),
+ timeout > std::chrono::seconds(0))) {
int p = this->TestProcess->GetNextOutputLine(line, timeout);
if (p == cmsysProcess_Pipe_None) {
// Process has terminated and all output read.
@@ -69,7 +76,9 @@ bool cmCTestRunTest::CheckOutput()
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->GetIndex()
<< ": "
<< "Test timeout changed to "
- << this->TestProperties->AlternateTimeout
+ << std::chrono::duration_cast<std::chrono::seconds>(
+ this->TestProperties->AlternateTimeout)
+ .count()
<< std::endl);
this->TestProcess->ResetStartTime();
this->TestProcess->ChangeTimeout(
@@ -257,7 +266,11 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
passed = this->TestResult.Status == cmCTestTestHandler::COMPLETED;
char buf[1024];
- sprintf(buf, "%6.2f sec", this->TestProcess->GetTotalTime());
+ sprintf(buf, "%6.2f sec",
+ double(std::chrono::duration_cast<std::chrono::milliseconds>(
+ this->TestProcess->GetTotalTime())
+ .count()) /
+ 1000.0);
cmCTestLog(this->CTest, HANDLER_OUTPUT, buf << "\n");
if (outputTestErrorsToConsole) {
@@ -293,12 +306,16 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
reasonType = "Test Fail Reason";
pass = false;
}
- double ttime = this->TestProcess->GetTotalTime();
- int hours = static_cast<int>(ttime / (60 * 60));
- int minutes = static_cast<int>(ttime / 60) % 60;
- int seconds = static_cast<int>(ttime) % 60;
+ auto ttime = this->TestProcess->GetTotalTime();
+ auto hours = std::chrono::duration_cast<std::chrono::hours>(ttime);
+ ttime -= hours;
+ auto minutes = std::chrono::duration_cast<std::chrono::minutes>(ttime);
+ ttime -= minutes;
+ auto seconds = std::chrono::duration_cast<std::chrono::seconds>(ttime);
char buffer[100];
- sprintf(buffer, "%02d:%02d:%02d", hours, minutes, seconds);
+ sprintf(buffer, "%02d:%02d:%02d", static_cast<unsigned>(hours.count()),
+ static_cast<unsigned>(minutes.count()),
+ static_cast<unsigned>(seconds.count()));
*this->TestHandler->LogFile
<< "----------------------------------------------------------"
<< std::endl;
@@ -378,7 +395,11 @@ void cmCTestRunTest::ComputeWeightedCost()
{
double prev = static_cast<double>(this->TestProperties->PreviousRuns);
double avgcost = static_cast<double>(this->TestProperties->Cost);
- double current = this->TestResult.ExecutionTime;
+ double current =
+ double(std::chrono::duration_cast<std::chrono::milliseconds>(
+ this->TestResult.ExecutionTime)
+ .count()) /
+ 1000.0;
if (this->TestResult.Status == cmCTestTestHandler::COMPLETED) {
this->TestProperties->Cost =
@@ -416,7 +437,7 @@ bool cmCTestRunTest::StartTest(size_t total)
// Return immediately if test is disabled
if (this->TestProperties->Disabled) {
this->TestResult.Properties = this->TestProperties;
- this->TestResult.ExecutionTime = 0;
+ this->TestResult.ExecutionTime = std::chrono::duration<double>::zero();
this->TestResult.CompressOutput = false;
this->TestResult.ReturnValue = -1;
this->TestResult.CompletionStatus = "Disabled";
@@ -430,10 +451,8 @@ bool cmCTestRunTest::StartTest(size_t total)
return false;
}
- this->ComputeArguments();
- std::vector<std::string>& args = this->TestProperties->Args;
this->TestResult.Properties = this->TestProperties;
- this->TestResult.ExecutionTime = 0;
+ this->TestResult.ExecutionTime = std::chrono::duration<double>::zero();
this->TestResult.CompressOutput = false;
this->TestResult.ReturnValue = -1;
this->TestResult.CompletionStatus = "Failed to start";
@@ -442,6 +461,10 @@ bool cmCTestRunTest::StartTest(size_t total)
this->TestResult.Name = this->TestProperties->Name;
this->TestResult.Path = this->TestProperties->Directory;
+ // Check for failed fixture dependencies before we even look at the command
+ // arguments because if we are not going to run the test, the command and
+ // its arguments are irrelevant. This matters for the case where a fixture
+ // dependency might be creating the executable we want to run.
if (!this->FailedDependencies.empty()) {
this->TestProcess = new cmProcess;
std::string msg = "Failed test dependencies:";
@@ -457,6 +480,8 @@ bool cmCTestRunTest::StartTest(size_t total)
return false;
}
+ this->ComputeArguments();
+ std::vector<std::string>& args = this->TestProperties->Args;
if (args.size() >= 2 && args[1] == "NOT_AVAILABLE") {
this->TestProcess = new cmProcess;
std::string msg;
@@ -510,7 +535,7 @@ bool cmCTestRunTest::StartTest(size_t total)
}
this->StartTime = this->CTest->CurrentTime();
- double timeout = this->ResolveTimeout();
+ auto timeout = this->ResolveTimeout();
if (this->StopTimePassed) {
return false;
@@ -591,9 +616,9 @@ void cmCTestRunTest::DartProcessing()
}
}
-double cmCTestRunTest::ResolveTimeout()
+std::chrono::duration<double> cmCTestRunTest::ResolveTimeout()
{
- double timeout = this->TestProperties->Timeout;
+ auto timeout = this->TestProperties->Timeout;
if (this->CTest->GetStopTime().empty()) {
return timeout;
@@ -623,31 +648,37 @@ double cmCTestRunTest::ResolveTimeout()
lctime->tm_mon + 1, lctime->tm_mday,
this->CTest->GetStopTime().c_str(), tzone_offset);
- time_t stop_time = curl_getdate(buf, &current_time);
- if (stop_time == -1) {
+ time_t stop_time_t = curl_getdate(buf, &current_time);
+ if (stop_time_t == -1) {
return timeout;
}
+ auto stop_time = std::chrono::system_clock::from_time_t(stop_time_t);
+
// the stop time refers to the next day
if (this->CTest->NextDayStopTime) {
- stop_time += 24 * 60 * 60;
+ stop_time += std::chrono::hours(24);
}
- int stop_timeout =
- static_cast<int>(stop_time - current_time) % (24 * 60 * 60);
+ auto stop_timeout =
+ (stop_time - std::chrono::system_clock::from_time_t(current_time)) %
+ std::chrono::hours(24);
this->CTest->LastStopTimeout = stop_timeout;
- if (stop_timeout <= 0 || stop_timeout > this->CTest->LastStopTimeout) {
+ if (stop_timeout <= std::chrono::duration<double>::zero() ||
+ stop_timeout > this->CTest->LastStopTimeout) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "The stop time has been passed. "
"Stopping all tests."
<< std::endl);
this->StopTimePassed = true;
- return 0;
+ return std::chrono::duration<double>::zero();
}
- return timeout == 0 ? stop_timeout
- : (timeout < stop_timeout ? timeout : stop_timeout);
+ return timeout == std::chrono::duration<double>::zero()
+ ? stop_timeout
+ : (timeout < stop_timeout ? timeout : stop_timeout);
}
-bool cmCTestRunTest::ForkProcess(double testTimeOut, bool explicitTimeout,
+bool cmCTestRunTest::ForkProcess(std::chrono::duration<double> testTimeOut,
+ bool explicitTimeout,
std::vector<std::string>* environment)
{
this->TestProcess = new cmProcess;
@@ -658,26 +689,37 @@ bool cmCTestRunTest::ForkProcess(double testTimeOut, bool explicitTimeout,
this->TestProcess->SetCommandArguments(this->Arguments);
// determine how much time we have
- double timeout = this->CTest->GetRemainingTimeAllowed() - 120;
- if (this->CTest->GetTimeOut() > 0 && this->CTest->GetTimeOut() < timeout) {
+ std::chrono::duration<double> timeout =
+ std::min<std::chrono::duration<double>>(
+ this->CTest->GetRemainingTimeAllowed(), std::chrono::minutes(2));
+ if (this->CTest->GetTimeOut() > std::chrono::duration<double>::zero() &&
+ this->CTest->GetTimeOut() < timeout) {
timeout = this->CTest->GetTimeOut();
}
- if (testTimeOut > 0 &&
+ if (testTimeOut > std::chrono::duration<double>::zero() &&
testTimeOut < this->CTest->GetRemainingTimeAllowed()) {
timeout = testTimeOut;
}
// always have at least 1 second if we got to here
- if (timeout <= 0) {
- timeout = 1;
+ if (timeout <= std::chrono::duration<double>::zero()) {
+ timeout = std::chrono::seconds(1);
}
// handle timeout explicitly set to 0
- if (testTimeOut == 0 && explicitTimeout) {
- timeout = 0;
- }
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index
- << ": "
- << "Test timeout computed to be: " << timeout << "\n",
- this->TestHandler->GetQuiet());
+ if (testTimeOut == std::chrono::duration<double>::zero() &&
+ explicitTimeout) {
+ timeout = std::chrono::duration<double>::zero();
+ }
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index
+ << ": "
+ << "Test timeout computed to be: "
+ << (timeout == std::chrono::duration<double>::max()
+ ? std::string("infinite")
+ : std::to_string(
+ std::chrono::duration_cast<std::chrono::seconds>(timeout)
+ .count()))
+ << "\n",
+ this->TestHandler->GetQuiet());
this->TestProcess->SetTimeout(timeout);