diff options
author | Brad King <brad.king@kitware.com> | 2017-12-05 13:12:40 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2017-12-05 13:12:52 (GMT) |
commit | b8e7af979d3d6dfef05fcebefe18907963221220 (patch) | |
tree | 049b34c1c621ae4e167d7e3644800e78809e9cec /Source | |
parent | 8616e9ba246242ff39d166afd2458fc78031918e (diff) | |
parent | 66419bc04620c5748df77e2b563d65b0e97b623a (diff) | |
download | CMake-b8e7af979d3d6dfef05fcebefe18907963221220.zip CMake-b8e7af979d3d6dfef05fcebefe18907963221220.tar.gz CMake-b8e7af979d3d6dfef05fcebefe18907963221220.tar.bz2 |
Merge topic 'ctest-chrono'
66419bc0 CTest: convert timeouts to std::chrono::duration
923b8fad IWYU: Add mappings for std::enable_if on chrono durations
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !1513
Diffstat (limited to 'Source')
-rw-r--r-- | Source/CTest/cmCTestBuildAndTestHandler.cxx | 2 | ||||
-rw-r--r-- | Source/CTest/cmCTestBuildHandler.cxx | 3 | ||||
-rw-r--r-- | Source/CTest/cmCTestConfigureHandler.cxx | 6 | ||||
-rw-r--r-- | Source/CTest/cmCTestCoverageHandler.cxx | 22 | ||||
-rw-r--r-- | Source/CTest/cmCTestMemCheckHandler.cxx | 1 | ||||
-rw-r--r-- | Source/CTest/cmCTestRunTest.cxx | 110 | ||||
-rw-r--r-- | Source/CTest/cmCTestRunTest.h | 6 | ||||
-rw-r--r-- | Source/CTest/cmCTestScriptHandler.cxx | 16 | ||||
-rw-r--r-- | Source/CTest/cmCTestScriptHandler.h | 4 | ||||
-rw-r--r-- | Source/CTest/cmCTestTestCommand.cxx | 9 | ||||
-rw-r--r-- | Source/CTest/cmCTestTestHandler.cxx | 24 | ||||
-rw-r--r-- | Source/CTest/cmCTestTestHandler.h | 6 | ||||
-rw-r--r-- | Source/CTest/cmCTestUpdateHandler.cxx | 1 | ||||
-rw-r--r-- | Source/CTest/cmProcess.cxx | 39 | ||||
-rw-r--r-- | Source/CTest/cmProcess.h | 20 | ||||
-rw-r--r-- | Source/cmCTest.cxx | 76 | ||||
-rw-r--r-- | Source/cmCTest.h | 29 |
17 files changed, 240 insertions, 134 deletions
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index b603758..672087d 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -337,7 +337,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) } int runTestRes = this->CTest->RunTest(testCommand, &outs, &retval, nullptr, - remainingTime.count(), nullptr); + remainingTime, nullptr); if (runTestRes != cmsysProcess_State_Exited || retval != 0) { out << "Test command failed: " << testCommand[0] << "\n"; diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index f25c9c3..ef4d3c6 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -17,7 +17,6 @@ #include <set> #include <stdlib.h> #include <string.h> -#include <type_traits> static const char* cmCTestErrorMatches[] = { "^[Bb]us [Ee]rror", @@ -283,7 +282,7 @@ int cmCTestBuildHandler::ProcessHandler() this->Quiet); // do we have time for this - if (this->CTest->GetRemainingTimeAllowed() < 120) { + if (this->CTest->GetRemainingTimeAllowed() < std::chrono::minutes(2)) { return 0; } diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx index ab77986..eb067e5 100644 --- a/Source/CTest/cmCTestConfigureHandler.cxx +++ b/Source/CTest/cmCTestConfigureHandler.cxx @@ -9,7 +9,6 @@ #include <chrono> #include <ostream> #include <string> -#include <type_traits> cmCTestConfigureHandler::cmCTestConfigureHandler() { @@ -63,8 +62,9 @@ int cmCTestConfigureHandler::ProcessHandler() cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Configure with command: " << cCommand << std::endl, this->Quiet); - res = this->CTest->RunMakeCommand(cCommand.c_str(), output, &retVal, - buildDirectory.c_str(), 0, ofs); + res = this->CTest->RunMakeCommand( + cCommand.c_str(), output, &retVal, buildDirectory.c_str(), + std::chrono::duration<double>::zero(), ofs); if (ofs) { ofs.close(); diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index bbfe9bd..39b90d8 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -11,6 +11,7 @@ #include "cmParseGTMCoverage.h" #include "cmParseJacocoCoverage.h" #include "cmParsePHPCoverage.h" +#include "cmProcess.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" #include "cmXMLWriter.h" @@ -27,7 +28,6 @@ #include <sstream> #include <stdio.h> #include <stdlib.h> -#include <type_traits> #include <utility> class cmMakefile; @@ -41,7 +41,7 @@ public: { this->Process = cmsysProcess_New(); this->PipeState = -1; - this->TimeOut = -1; + this->TimeOut = std::chrono::duration<double>(-1); } ~cmCTestRunProcess() { @@ -65,7 +65,7 @@ public: } } void SetWorkingDirectory(const char* dir) { this->WorkingDirectory = dir; } - void SetTimeout(double t) { this->TimeOut = t; } + void SetTimeout(std::chrono::duration<double> t) { this->TimeOut = t; } bool StartProcess() { std::vector<const char*> args; @@ -80,7 +80,7 @@ public: } cmsysProcess_SetOption(this->Process, cmsysProcess_Option_HideWindow, 1); - if (this->TimeOut != -1) { + if (this->TimeOut >= std::chrono::duration<double>::zero()) { cmsysProcess_SetTimeout(this->Process, this->TimeOut); } cmsysProcess_Execute(this->Process); @@ -109,7 +109,7 @@ private: cmsysProcess* Process; std::vector<std::string> CommandLineStrings; std::string WorkingDirectory; - double TimeOut; + std::chrono::duration<double> TimeOut; }; cmCTestCoverageHandler::cmCTestCoverageHandler() @@ -277,7 +277,7 @@ int cmCTestCoverageHandler::ProcessHandler() this->CTest->ClearSubmitFiles(cmCTest::PartCoverage); int error = 0; // do we have time for this - if (this->CTest->GetRemainingTimeAllowed() < 120) { + if (this->CTest->GetRemainingTimeAllowed() < std::chrono::minutes(2)) { return error; } @@ -1023,8 +1023,9 @@ int cmCTestCoverageHandler::HandleGCovCoverage( int retVal = 0; *cont->OFS << "* Run coverage for: " << fileDir << std::endl; *cont->OFS << " Command: " << command << std::endl; - int res = this->CTest->RunCommand(covargs, &output, &errors, &retVal, - tempDir.c_str(), 0 /*this->TimeOut*/); + int res = this->CTest->RunCommand( + covargs, &output, &errors, &retVal, tempDir.c_str(), + std::chrono::duration<double>::zero() /*this->TimeOut*/); *cont->OFS << " Output: " << output << std::endl; *cont->OFS << " Errors: " << errors << std::endl; @@ -1387,8 +1388,9 @@ int cmCTestCoverageHandler::HandleLCovCoverage( int retVal = 0; *cont->OFS << "* Run coverage for: " << fileDir << std::endl; *cont->OFS << " Command: " << command << std::endl; - int res = this->CTest->RunCommand(covargs, &output, &errors, &retVal, - fileDir.c_str(), 0 /*this->TimeOut*/); + int res = this->CTest->RunCommand( + covargs, &output, &errors, &retVal, fileDir.c_str(), + std::chrono::duration<double>::zero() /*this->TimeOut*/); *cont->OFS << " Output: " << output << std::endl; *cont->OFS << " Errors: " << errors << std::endl; diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 2e7874d..57d2489 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -14,7 +14,6 @@ #include <iostream> #include <sstream> #include <string.h> -#include <type_traits> struct CatToErrorType { diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 5443494..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,7 @@ #include "cmsys/Base64.h" #include "cmsys/Process.h" #include "cmsys/RegularExpression.hxx" +#include <algorithm> #include <chrono> #include <iomanip> #include <sstream> @@ -26,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; @@ -52,7 +57,7 @@ bool cmCTestRunTest::CheckOutput() std::string line; while ((timeout = timeEnd - std::chrono::steady_clock::now(), timeout > std::chrono::seconds(0))) { - int p = this->TestProcess->GetNextOutputLine(line, timeout.count()); + int p = this->TestProcess->GetNextOutputLine(line, timeout); if (p == cmsysProcess_Pipe_None) { // Process has terminated and all output read. return false; @@ -71,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( @@ -259,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) { @@ -295,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; @@ -380,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 = @@ -418,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"; @@ -433,7 +452,7 @@ bool cmCTestRunTest::StartTest(size_t total) } 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"; @@ -516,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; @@ -597,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; @@ -629,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, ¤t_time); - if (stop_time == -1) { + time_t stop_time_t = curl_getdate(buf, ¤t_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; @@ -664,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); diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index d3bb229..cd380ca 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <chrono> #include <set> #include <stddef.h> #include <string> @@ -78,8 +79,9 @@ private: void DartProcessing(); void ExeNotFound(std::string exe); // Figures out a final timeout which is min(STOP_TIME, NOW+TIMEOUT) - double ResolveTimeout(); - bool ForkProcess(double testTimeOut, bool explicitTimeout, + std::chrono::duration<double> ResolveTimeout(); + bool ForkProcess(std::chrono::duration<double> testTimeOut, + bool explicitTimeout, std::vector<std::string>* environment); void WriteLogOutputTop(size_t completed, size_t total); // Run post processing of the process output for MemCheck diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 3bf27a0..922f5c7 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -1,5 +1,12 @@ /* 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, unless told to otherwise. This + * interferes with std::min() and std::max() at the very least. */ +#define NOMINMAX +#endif + #include "cmCTestScriptHandler.h" #include "cmsys/Directory.hxx" @@ -10,7 +17,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <type_traits> #include <utility> #include "cmCTest.h" @@ -961,21 +967,21 @@ bool cmCTestScriptHandler::TryToRemoveBinaryDirectoryOnce( return cmSystemTools::RemoveADirectory(directoryPath); } -double cmCTestScriptHandler::GetRemainingTimeAllowed() +std::chrono::duration<double> cmCTestScriptHandler::GetRemainingTimeAllowed() { if (!this->Makefile) { - return 1.0e7; + return std::chrono::duration<double>::max(); } const char* timelimitS = this->Makefile->GetDefinition("CTEST_TIME_LIMIT"); if (!timelimitS) { - return 1.0e7; + return std::chrono::duration<double>::max(); } auto timelimit = std::chrono::duration<double>(atof(timelimitS)); auto duration = std::chrono::duration_cast<std::chrono::duration<double>>( std::chrono::steady_clock::now() - this->ScriptStartTime); - return (timelimit - duration).count(); + return (timelimit - duration); } diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h index 2090d04..9b7fa75 100644 --- a/Source/CTest/cmCTestScriptHandler.h +++ b/Source/CTest/cmCTestScriptHandler.h @@ -94,9 +94,9 @@ public: /** * Return the time remaianing that the script is allowed to run in * seconds if the user has set the variable CTEST_TIME_LIMIT. If that has - * not been set it returns 1e7 seconds + * not been set it returns a very large value. */ - double GetRemainingTimeAllowed(); + std::chrono::duration<double> GetRemainingTimeAllowed(); cmCTestScriptHandler(); ~cmCTestScriptHandler() override; diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index febd39e..232bd58 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -7,6 +7,7 @@ #include "cmMakefile.h" #include "cmSystemTools.h" +#include <chrono> #include <sstream> #include <stdlib.h> #include <vector> @@ -36,14 +37,14 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() const char* ctestTimeout = this->Makefile->GetDefinition("CTEST_TEST_TIMEOUT"); - double timeout; + std::chrono::duration<double> timeout; if (ctestTimeout) { - timeout = atof(ctestTimeout); + timeout = std::chrono::duration<double>(atof(ctestTimeout)); } else { timeout = this->CTest->GetTimeOut(); - if (timeout <= 0) { + if (timeout <= std::chrono::duration<double>::zero()) { // By default use timeout of 10 minutes - timeout = 600; + timeout = std::chrono::minutes(10); } } this->CTest->SetTimeOut(timeout); diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index e7c719c..1e15cc5 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -16,7 +16,6 @@ #include <stdlib.h> #include <string.h> #include <time.h> -#include <type_traits> #include "cmAlgorithms.h" #include "cmCTest.h" @@ -654,7 +653,11 @@ void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject) for (std::string const& l : p.Labels) { // only use labels found in labels if (labels.find(l) != labels.end()) { - labelTimes[l] += result.ExecutionTime * result.Properties->Processors; + labelTimes[l] += + double(std::chrono::duration_cast<std::chrono::milliseconds>( + result.ExecutionTime) + .count()) / + 1000.0 * result.Properties->Processors; ++labelCounts[l]; } } @@ -1240,7 +1243,9 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed, p.Cost = static_cast<float>(rand()); } - if (p.Timeout == 0 && this->CTest->GetGlobalTimeout() != 0) { + if (p.Timeout == std::chrono::duration<double>::zero() && + this->CTest->GetGlobalTimeout() != + std::chrono::duration<double>::zero()) { p.Timeout = this->CTest->GetGlobalTimeout(); } @@ -1322,7 +1327,11 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) xml.StartElement("NamedMeasurement"); xml.Attribute("type", "numeric/double"); xml.Attribute("name", "Execution Time"); - xml.Element("Value", result.ExecutionTime); + xml.Element("Value", + double(std::chrono::duration_cast<std::chrono::milliseconds>( + result.ExecutionTime) + .count()) / + 1000.0); xml.EndElement(); // NamedMeasurement if (!result.Reason.empty()) { const char* reasonType = "Pass Reason"; @@ -2143,7 +2152,7 @@ bool cmCTestTestHandler::SetTestsProperties( rt.FixturesRequired.insert(lval.begin(), lval.end()); } if (key == "TIMEOUT") { - rt.Timeout = atof(val.c_str()); + rt.Timeout = std::chrono::duration<double>(atof(val.c_str())); rt.ExplicitTimeout = true; } if (key == "COST") { @@ -2223,7 +2232,8 @@ bool cmCTestTestHandler::SetTestsProperties( "TIMEOUT_AFTER_MATCH expects two arguments, found " << propArgs.size() << std::endl); } else { - rt.AlternateTimeout = atof(propArgs[0].c_str()); + rt.AlternateTimeout = + std::chrono::duration<double>(atof(propArgs[0].c_str())); std::vector<std::string> lval; cmSystemTools::ExpandListArgument(propArgs[1], lval); for (std::string const& cr : lval) { @@ -2341,7 +2351,7 @@ bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args) test.WillFail = false; test.Disabled = false; test.RunSerial = false; - test.Timeout = 0; + test.Timeout = std::chrono::duration<double>::zero(); test.ExplicitTimeout = false; test.Cost = 0; test.Processors = 1; diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 8572e7b..19b345e 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -124,9 +124,9 @@ public: float Cost; int PreviousRuns; bool RunSerial; - double Timeout; + std::chrono::duration<double> Timeout; bool ExplicitTimeout; - double AlternateTimeout; + std::chrono::duration<double> AlternateTimeout; int Index; // Requested number of process slots int Processors; @@ -147,7 +147,7 @@ public: std::string Path; std::string Reason; std::string FullCommandLine; - double ExecutionTime; + std::chrono::duration<double> ExecutionTime; int ReturnValue; int Status; std::string ExceptionStatus; diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index f86d4a3..809abd1 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -20,7 +20,6 @@ #include <chrono> #include <memory> // IWYU pragma: keep #include <sstream> -#include <type_traits> static const char* cmCTestUpdateHandlerUpdateStrings[] = { "Unknown", "CVS", "SVN", "BZR", "GIT", "HG", "P4" diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index 78dd598..69ffb33 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -4,13 +4,22 @@ #include "cmProcessOutput.h" #include <iostream> -#include <type_traits> + +void cmsysProcess_SetTimeout(cmsysProcess* process, + std::chrono::duration<double> timeout) +{ + cmsysProcess_SetTimeout( + process, + double( + std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()) / + 1000.0); +}; cmProcess::cmProcess() { this->Process = nullptr; - this->Timeout = 0; - this->TotalTime = 0; + this->Timeout = std::chrono::duration<double>::zero(); + this->TotalTime = std::chrono::duration<double>::zero(); this->ExitValue = 0; this->Id = 0; this->StartTime = std::chrono::steady_clock::time_point(); @@ -101,10 +110,15 @@ bool cmProcess::Buffer::GetLast(std::string& line) return false; } -int cmProcess::GetNextOutputLine(std::string& line, double timeout) +int cmProcess::GetNextOutputLine(std::string& line, + std::chrono::duration<double> timeout) { cmProcessOutput processOutput(cmProcessOutput::UTF8); std::string strdata; + double waitTimeout = + double( + std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()) / + 1000.0; for (;;) { // Look for lines already buffered. if (this->Output.GetLine(line)) { @@ -114,7 +128,8 @@ int cmProcess::GetNextOutputLine(std::string& line, double timeout) // Check for more data from the process. char* data; int length; - int p = cmsysProcess_WaitForData(this->Process, &data, &length, &timeout); + int p = + cmsysProcess_WaitForData(this->Process, &data, &length, &waitTimeout); if (p == cmsysProcess_Pipe_Timeout) { return cmsysProcess_Pipe_Timeout; } @@ -137,23 +152,19 @@ int cmProcess::GetNextOutputLine(std::string& line, double timeout) } // No more data. Wait for process exit. - if (!cmsysProcess_WaitForExit(this->Process, &timeout)) { + if (!cmsysProcess_WaitForExit(this->Process, &waitTimeout)) { return cmsysProcess_Pipe_Timeout; } // Record exit information. this->ExitValue = cmsysProcess_GetExitValue(this->Process); - this->TotalTime = - static_cast<double>(std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::steady_clock::now() - this->StartTime) - .count()) / - 1000.0; + this->TotalTime = std::chrono::steady_clock::now() - this->StartTime; // Because of a processor clock scew the runtime may become slightly // negative. If someone changed the system clock while the process was // running this may be even more. Make sure not to report a negative // duration here. - if (this->TotalTime <= 0.0) { - this->TotalTime = 0.0; + if (this->TotalTime <= std::chrono::duration<double>::zero()) { + this->TotalTime = std::chrono::duration<double>::zero(); } // std::cerr << "Time to run: " << this->TotalTime << "\n"; return cmsysProcess_Pipe_None; @@ -226,7 +237,7 @@ int cmProcess::ReportStatus() return result; } -void cmProcess::ChangeTimeout(double t) +void cmProcess::ChangeTimeout(std::chrono::duration<double> t) { this->Timeout = t; cmsysProcess_SetTimeout(this->Process, this->Timeout); diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h index ddd69b6..cbb611d 100644 --- a/Source/CTest/cmProcess.h +++ b/Source/CTest/cmProcess.h @@ -10,6 +10,13 @@ #include <string> #include <vector> +/* + * A wrapper function for cmsysProcess_SetTimeout that takes an + * std::chrono::duration. For convenience only. + */ +void cmsysProcess_SetTimeout(cmsysProcess* process, + std::chrono::duration<double> timeout); + /** \class cmProcess * \brief run a process with c++ * @@ -24,8 +31,8 @@ public: void SetCommand(const char* command); void SetCommandArguments(std::vector<std::string> const& arg); void SetWorkingDirectory(const char* dir) { this->WorkingDirectory = dir; } - void SetTimeout(double t) { this->Timeout = t; } - void ChangeTimeout(double t); + void SetTimeout(std::chrono::duration<double> t) { this->Timeout = t; } + void ChangeTimeout(std::chrono::duration<double> t); void ResetStartTime(); // Return true if the process starts bool StartProcess(); @@ -37,7 +44,7 @@ public: int GetId() { return this->Id; } void SetId(int id) { this->Id = id; } int GetExitValue() { return this->ExitValue; } - double GetTotalTime() { return this->TotalTime; } + std::chrono::duration<double> GetTotalTime() { return this->TotalTime; } int GetExitException(); std::string GetExitExceptionString(); /** @@ -47,12 +54,13 @@ public: * cmsysProcess_Pipe_STDOUT = Line came from stdout or stderr * cmsysProcess_Pipe_Timeout = Timeout expired while waiting */ - int GetNextOutputLine(std::string& line, double timeout); + int GetNextOutputLine(std::string& line, + std::chrono::duration<double> timeout); private: - double Timeout; + std::chrono::duration<double> Timeout; std::chrono::steady_clock::time_point StartTime; - double TotalTime; + std::chrono::duration<double> TotalTime; cmsysProcess* Process; class Buffer : public std::vector<char> { diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index d358e3d..a4ca301 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -1,5 +1,11 @@ /* 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 by default. This interferes with + * C++ functions names. + */ +#define NOMINMAX +#endif #include "cmCTest.h" #include "cm_curl.h" @@ -44,6 +50,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmProcess.h" #include "cmProcessOutput.h" #include "cmState.h" #include "cmStateSnapshot.h" @@ -278,9 +285,9 @@ cmCTest::cmCTest() this->TestModel = cmCTest::EXPERIMENTAL; this->MaxTestNameWidth = 30; this->InteractiveDebugMode = true; - this->TimeOut = 0; - this->GlobalTimeout = 0; - this->LastStopTimeout = 24 * 60 * 60; + this->TimeOut = std::chrono::duration<double>::zero(); + this->GlobalTimeout = std::chrono::duration<double>::zero(); + this->LastStopTimeout = std::chrono::hours(24); this->CompressXMLFiles = false; this->ScheduleType.clear(); this->StopTime.clear(); @@ -678,7 +685,8 @@ bool cmCTest::UpdateCTestConfiguration() this->BinaryDir = this->GetCTestConfiguration("BuildDirectory"); cmSystemTools::ChangeDirectory(this->BinaryDir); } - this->TimeOut = atoi(this->GetCTestConfiguration("TimeOut").c_str()); + this->TimeOut = + std::chrono::seconds(atoi(this->GetCTestConfiguration("TimeOut").c_str())); std::string const& testLoad = this->GetCTestConfiguration("TestLoad"); if (!testLoad.empty()) { unsigned long load; @@ -836,7 +844,8 @@ int cmCTest::ProcessSteps() for (Part p = PartStart; notest && p != PartCount; p = Part(p + 1)) { notest = !this->Parts[p]; } - if (this->Parts[PartUpdate] && (this->GetRemainingTimeAllowed() - 120 > 0)) { + if (this->Parts[PartUpdate] && + (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) { cmCTestGenericHandler* uphandler = this->GetHandler("update"); uphandler->SetPersistentOption( "SourceDirectory", @@ -850,33 +859,34 @@ int cmCTest::ProcessSteps() return 0; } if (this->Parts[PartConfigure] && - (this->GetRemainingTimeAllowed() - 120 > 0)) { + (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) { if (this->GetHandler("configure")->ProcessHandler() < 0) { res |= cmCTest::CONFIGURE_ERRORS; } } - if (this->Parts[PartBuild] && (this->GetRemainingTimeAllowed() - 120 > 0)) { + if (this->Parts[PartBuild] && + (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) { this->UpdateCTestConfiguration(); if (this->GetHandler("build")->ProcessHandler() < 0) { res |= cmCTest::BUILD_ERRORS; } } if ((this->Parts[PartTest] || notest) && - (this->GetRemainingTimeAllowed() - 120 > 0)) { + (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) { this->UpdateCTestConfiguration(); if (this->GetHandler("test")->ProcessHandler() < 0) { res |= cmCTest::TEST_ERRORS; } } if (this->Parts[PartCoverage] && - (this->GetRemainingTimeAllowed() - 120 > 0)) { + (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) { this->UpdateCTestConfiguration(); if (this->GetHandler("coverage")->ProcessHandler() < 0) { res |= cmCTest::COVERAGE_ERRORS; } } if (this->Parts[PartMemCheck] && - (this->GetRemainingTimeAllowed() - 120 > 0)) { + (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) { this->UpdateCTestConfiguration(); if (this->GetHandler("memcheck")->ProcessHandler() < 0) { res |= cmCTest::MEMORY_ERRORS; @@ -955,7 +965,8 @@ int cmCTest::GetTestModelFromString(const char* str) //###################################################################### int cmCTest::RunMakeCommand(const char* command, std::string& output, - int* retVal, const char* dir, int timeout, + int* retVal, const char* dir, + std::chrono::duration<double> timeout, std::ostream& ofs, Encoding encoding) { // First generate the command and arguments @@ -1071,26 +1082,37 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output, //###################################################################### int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, - int* retVal, std::ostream* log, double testTimeOut, + int* retVal, std::ostream* log, + std::chrono::duration<double> testTimeOut, std::vector<std::string>* environment, Encoding encoding) { bool modifyEnv = (environment && !environment->empty()); // determine how much time we have - double timeout = this->GetRemainingTimeAllowed() - 120; - if (this->TimeOut > 0 && this->TimeOut < timeout) { + std::chrono::duration<double> timeout = + std::min<std::chrono::duration<double>>(this->GetRemainingTimeAllowed(), + std::chrono::minutes(2)); + if (this->TimeOut > std::chrono::duration<double>::zero() && + this->TimeOut < timeout) { timeout = this->TimeOut; } - if (testTimeOut > 0 && testTimeOut < this->GetRemainingTimeAllowed()) { + if (testTimeOut > std::chrono::duration<double>::zero() && + testTimeOut < this->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); } - cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, - "Test timeout computed to be: " << timeout << "\n"); + cmCTestLog( + this, HANDLER_VERBOSE_OUTPUT, "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"); if (cmSystemTools::SameFile(argv[0], cmSystemTools::GetCTestCommand()) && !this->ForceNewCTestProcess) { cmCTest inst; @@ -1107,10 +1129,12 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, // make sure we pass the timeout in for any build and test // invocations. Since --build-generator is required this is a // good place to check for it, and to add the arguments in - if (strcmp(i, "--build-generator") == 0 && timeout > 0) { + if (strcmp(i, "--build-generator") == 0 && + timeout > std::chrono::duration<double>::zero()) { args.push_back("--test-timeout"); std::ostringstream msg; - msg << timeout; + msg << std::chrono::duration_cast<std::chrono::seconds>(timeout) + .count(); args.push_back(msg.str()); } args.push_back(i); @@ -1757,7 +1781,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, if (this->CheckArgument(arg, "--timeout") && i < args.size() - 1) { i++; - double timeout = atof(args[i].c_str()); + auto timeout = std::chrono::duration<double>(atof(args[i].c_str())); this->GlobalTimeout = timeout; } @@ -2564,7 +2588,9 @@ bool cmCTest::SetCTestConfigurationFromCMakeVariable( bool cmCTest::RunCommand(std::vector<std::string> const& args, std::string* stdOut, std::string* stdErr, int* retVal, - const char* dir, double timeout, Encoding encoding) + const char* dir, + std::chrono::duration<double> timeout, + Encoding encoding) { std::vector<const char*> argv; argv.reserve(args.size() + 1); @@ -2775,10 +2801,10 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg, } } -double cmCTest::GetRemainingTimeAllowed() +std::chrono::duration<double> cmCTest::GetRemainingTimeAllowed() { if (!this->GetHandler("script")) { - return 1.0e7; + return std::chrono::duration<double>::max(); } cmCTestScriptHandler* ch = diff --git a/Source/cmCTest.h b/Source/cmCTest.h index a2d6fc3..ba94866 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -7,6 +7,7 @@ #include "cmProcessOutput.h" #include "cmsys/String.hxx" +#include <chrono> #include <map> #include <set> #include <sstream> @@ -139,10 +140,13 @@ public: /** what is the configuraiton type, e.g. Debug, Release etc. */ std::string const& GetConfigType(); - double GetTimeOut() { return this->TimeOut; } - void SetTimeOut(double t) { this->TimeOut = t; } + std::chrono::duration<double> GetTimeOut() { return this->TimeOut; } + void SetTimeOut(std::chrono::duration<double> t) { this->TimeOut = t; } - double GetGlobalTimeout() { return this->GlobalTimeout; } + std::chrono::duration<double> GetGlobalTimeout() + { + return this->GlobalTimeout; + } /** how many test to run at the same time */ int GetParallelLevel() { return this->ParallelLevel; } @@ -200,9 +204,9 @@ public: /** * Return the time remaining that the script is allowed to run in * seconds if the user has set the variable CTEST_TIME_LIMIT. If that has - * not been set it returns 1e7 seconds + * not been set it returns a very large duration. */ - double GetRemainingTimeAllowed(); + std::chrono::duration<double> GetRemainingTimeAllowed(); /** * Open file in the output directory and set the stream @@ -248,7 +252,9 @@ public: */ bool RunCommand(std::vector<std::string> const& args, std::string* stdOut, std::string* stdErr, int* retVal = nullptr, - const char* dir = nullptr, double timeout = 0.0, + const char* dir = nullptr, + std::chrono::duration<double> timeout = + std::chrono::duration<double>::zero(), Encoding encoding = cmProcessOutput::Auto); /** @@ -268,7 +274,8 @@ public: * and retVal is return value or exception. */ int RunMakeCommand(const char* command, std::string& output, int* retVal, - const char* dir, int timeout, std::ostream& ofs, + const char* dir, std::chrono::duration<double> timeout, + std::ostream& ofs, Encoding encoding = cmProcessOutput::Auto); /** Return the current tag */ @@ -315,7 +322,7 @@ public: * environment variables are restored to their previous values. */ int RunTest(std::vector<const char*> args, std::string* output, int* retVal, - std::ostream* logfile, double testTimeOut, + std::ostream* logfile, std::chrono::duration<double> testTimeOut, std::vector<std::string>* environment, Encoding encoding = cmProcessOutput::Auto); @@ -503,11 +510,11 @@ private: int TestModel; std::string SpecificTrack; - double TimeOut; + std::chrono::duration<double> TimeOut; - double GlobalTimeout; + std::chrono::duration<double> GlobalTimeout; - int LastStopTimeout; + std::chrono::duration<double> LastStopTimeout; int MaxTestNameWidth; |