summaryrefslogtreecommitdiffstats
path: root/Source/cmCTest.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2024-01-25 15:52:01 (GMT)
committerBrad King <brad.king@kitware.com>2024-01-25 15:53:04 (GMT)
commit151601c2e3419bd65bb276e77588c551487b4744 (patch)
tree6fef8b57dd7aa10c9f15447b18dc74951de68dad /Source/cmCTest.cxx
parent23747f705602cbc47672c6db6716afbe8b5b013e (diff)
parentbcbb212df704d36736731aa567b291fd97401804 (diff)
downloadCMake-151601c2e3419bd65bb276e77588c551487b4744.zip
CMake-151601c2e3419bd65bb276e77588c551487b4744.tar.gz
CMake-151601c2e3419bd65bb276e77588c551487b4744.tar.bz2
Merge topic 'revert-replace-cmsysprocess-with-cmuvprocesschain' into release-3.28
bcbb212df7 Revert use of libuv for process execution for 3.28 Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !9176
Diffstat (limited to 'Source/cmCTest.cxx')
-rw-r--r--Source/cmCTest.cxx429
1 files changed, 198 insertions, 231 deletions
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 6e684a3..988a4eb 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -5,7 +5,6 @@
#include <algorithm>
#include <cctype>
#include <chrono>
-#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
@@ -25,13 +24,13 @@
#include <cmext/string_view>
#include <cm3p/curl/curl.h>
-#include <cm3p/uv.h>
#include <cm3p/zlib.h>
#include "cmsys/Base64.h"
#include "cmsys/Directory.hxx"
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
+#include "cmsys/Process.h"
#include "cmsys/RegularExpression.hxx"
#include "cmsys/SystemInformation.hxx"
#if defined(_WIN32)
@@ -65,9 +64,6 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmUVHandlePtr.h"
-#include "cmUVProcessChain.h"
-#include "cmUVStream.h"
#include "cmValue.h"
#include "cmVersion.h"
#include "cmVersionConfig.h"
@@ -1077,9 +1073,9 @@ int cmCTest::GetTestModelFromString(const std::string& str)
// ######################################################################
// ######################################################################
-bool cmCTest::RunMakeCommand(const std::string& command, std::string& output,
- int* retVal, const char* dir, cmDuration timeout,
- std::ostream& ofs, Encoding encoding)
+int cmCTest::RunMakeCommand(const std::string& command, std::string& output,
+ int* retVal, const char* dir, cmDuration timeout,
+ std::ostream& ofs, Encoding encoding)
{
// First generate the command and arguments
std::vector<std::string> args = cmSystemTools::ParseArguments(command);
@@ -1088,107 +1084,107 @@ bool cmCTest::RunMakeCommand(const std::string& command, std::string& output,
return false;
}
+ std::vector<const char*> argv;
+ argv.reserve(args.size() + 1);
+ for (std::string const& a : args) {
+ argv.push_back(a.c_str());
+ }
+ argv.push_back(nullptr);
+
output.clear();
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Run command:");
- for (auto const& arg : args) {
+ for (char const* arg : argv) {
+ if (!arg) {
+ break;
+ }
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, " \"" << arg << "\"");
}
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, std::endl);
// Now create process object
- cmUVProcessChainBuilder builder;
- builder.AddCommand(args).SetMergedBuiltinStreams();
- if (dir) {
- builder.SetWorkingDirectory(dir);
- }
- auto chain = builder.Start();
- cm::uv_pipe_ptr outputStream;
- outputStream.init(chain.GetLoop(), 0);
- uv_pipe_open(outputStream, chain.OutputStream());
+ cmsysProcess* cp = cmsysProcess_New();
+ cmsysProcess_SetCommand(cp, argv.data());
+ cmsysProcess_SetWorkingDirectory(cp, dir);
+ cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
+ cmsysProcess_SetTimeout(cp, timeout.count());
+ cmsysProcess_Execute(cp);
// Initialize tick's
std::string::size_type tick = 0;
std::string::size_type tick_len = 1024;
std::string::size_type tick_line_len = 50;
+ char* data;
+ int length;
cmProcessOutput processOutput(encoding);
+ std::string strdata;
cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
" Each . represents " << tick_len
<< " bytes of output\n"
" "
<< std::flush);
- auto outputHandle = cmUVStreamRead(
- outputStream,
- [this, &processOutput, &output, &tick, &tick_len, &tick_line_len,
- &ofs](std::vector<char> data) {
- std::string strdata;
- processOutput.DecodeText(data.data(), data.size(), strdata);
- for (char& cc : strdata) {
- if (cc == 0) {
- cc = '\n';
- }
+ while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) {
+ processOutput.DecodeText(data, length, strdata);
+ for (char& cc : strdata) {
+ if (cc == 0) {
+ cc = '\n';
}
- output.append(strdata);
- while (output.size() > (tick * tick_len)) {
- tick++;
- cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, "." << std::flush);
- if (tick % tick_line_len == 0 && tick > 0) {
- cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
- " Size: " << int((double(output.size()) / 1024.0) + 1)
- << "K\n " << std::flush);
- }
- }
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
- cmCTestLogWrite(strdata.c_str(), strdata.size()));
- if (ofs) {
- ofs << cmCTestLogWrite(strdata.c_str(), strdata.size());
- }
- },
- [this, &processOutput, &output, &ofs]() {
- std::string strdata;
- processOutput.DecodeText(std::string(), strdata);
- if (!strdata.empty()) {
- output.append(strdata);
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
- cmCTestLogWrite(strdata.c_str(), strdata.size()));
- if (ofs) {
- ofs << cmCTestLogWrite(strdata.c_str(), strdata.size());
- }
+ }
+ output.append(strdata);
+ while (output.size() > (tick * tick_len)) {
+ tick++;
+ cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, "." << std::flush);
+ if (tick % tick_line_len == 0 && tick > 0) {
+ cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
+ " Size: " << int((double(output.size()) / 1024.0) + 1)
+ << "K\n " << std::flush);
}
- });
-
- bool finished = chain.Wait(static_cast<uint64_t>(timeout.count() * 1000.0));
+ }
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ cmCTestLogWrite(strdata.c_str(), strdata.size()));
+ if (ofs) {
+ ofs << cmCTestLogWrite(strdata.c_str(), strdata.size());
+ }
+ }
+ processOutput.DecodeText(std::string(), strdata);
+ if (!strdata.empty()) {
+ output.append(strdata);
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ cmCTestLogWrite(strdata.c_str(), strdata.size()));
+ if (ofs) {
+ ofs << cmCTestLogWrite(strdata.c_str(), strdata.size());
+ }
+ }
cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
" Size of output: " << int(double(output.size()) / 1024.0) << "K"
<< std::endl);
- if (finished) {
- auto const& status = chain.GetStatus(0);
- auto exception = status.GetException();
- switch (exception.first) {
- case cmUVProcessChain::ExceptionCode::None:
- *retVal = static_cast<int>(status.ExitStatus);
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
- "Command exited with the value: " << *retVal << std::endl);
- break;
- case cmUVProcessChain::ExceptionCode::Spawn:
- output += "\n*** ERROR executing: ";
- output += exception.second;
- output += "\n***The build process failed.";
- cmCTestLog(this, ERROR_MESSAGE,
- "There was an error: " << exception.second << std::endl);
- break;
- default:
- *retVal = static_cast<int>(exception.first);
- cmCTestLog(this, WARNING,
- "There was an exception: " << *retVal << std::endl);
- break;
- }
- } else {
+ cmsysProcess_WaitForExit(cp, nullptr);
+
+ int result = cmsysProcess_GetState(cp);
+
+ if (result == cmsysProcess_State_Exited) {
+ *retVal = cmsysProcess_GetExitValue(cp);
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ "Command exited with the value: " << *retVal << std::endl);
+ } else if (result == cmsysProcess_State_Exception) {
+ *retVal = cmsysProcess_GetExitException(cp);
+ cmCTestLog(this, WARNING,
+ "There was an exception: " << *retVal << std::endl);
+ } else if (result == cmsysProcess_State_Expired) {
cmCTestLog(this, WARNING, "There was a timeout" << std::endl);
+ } else if (result == cmsysProcess_State_Error) {
+ output += "\n*** ERROR executing: ";
+ output += cmsysProcess_GetErrorString(cp);
+ output += "\n***The build process failed.";
+ cmCTestLog(this, ERROR_MESSAGE,
+ "There was an error: " << cmsysProcess_GetErrorString(cp)
+ << std::endl);
}
- return true;
+ cmsysProcess_Delete(cp);
+
+ return result;
}
// ######################################################################
@@ -1196,10 +1192,9 @@ bool cmCTest::RunMakeCommand(const std::string& command, std::string& output,
// ######################################################################
// ######################################################################
-bool cmCTest::RunTest(const std::vector<std::string>& argv,
- std::string* output, int* retVal, std::ostream* log,
- cmDuration testTimeOut,
- std::vector<std::string>* environment, Encoding encoding)
+int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
+ int* retVal, std::ostream* log, cmDuration testTimeOut,
+ std::vector<std::string>* environment, Encoding encoding)
{
bool modifyEnv = (environment && !environment->empty());
@@ -1238,16 +1233,19 @@ bool cmCTest::RunTest(const std::vector<std::string>& argv,
inst.SetStreams(&oss, &oss);
std::vector<std::string> args;
- for (auto const& i : argv) {
- // 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 (i == "--build-generator" && timeout != cmCTest::MaxDuration() &&
- timeout > cmDuration::zero()) {
- args.emplace_back("--test-timeout");
- args.push_back(std::to_string(cmDurationTo<unsigned int>(timeout)));
+ for (char const* i : argv) {
+ if (i) {
+ // 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 != cmCTest::MaxDuration() &&
+ timeout > cmDuration::zero()) {
+ args.emplace_back("--test-timeout");
+ args.push_back(std::to_string(cmDurationTo<unsigned int>(timeout)));
+ }
+ args.emplace_back(i);
}
- args.emplace_back(i);
}
if (log) {
*log << "* Run internal CTest" << std::endl;
@@ -1273,7 +1271,7 @@ bool cmCTest::RunTest(const std::vector<std::string>& argv,
<< std::endl);
}
- return true;
+ return cmsysProcess_State_Exited;
}
std::vector<char> tempOutput;
if (output) {
@@ -1286,43 +1284,41 @@ bool cmCTest::RunTest(const std::vector<std::string>& argv,
cmSystemTools::AppendEnv(*environment);
}
- cmUVProcessChainBuilder builder;
- builder.AddCommand(argv).SetMergedBuiltinStreams();
+ cmsysProcess* cp = cmsysProcess_New();
+ cmsysProcess_SetCommand(cp, argv.data());
cmCTestLog(this, DEBUG, "Command is: " << argv[0] << std::endl);
- auto chain = builder.Start();
+ if (cmSystemTools::GetRunCommandHideConsole()) {
+ cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
+ }
+ cmsysProcess_SetTimeout(cp, timeout.count());
+ cmsysProcess_Execute(cp);
+
+ char* data;
+ int length;
cmProcessOutput processOutput(encoding);
- cm::uv_pipe_ptr outputStream;
- outputStream.init(chain.GetLoop(), 0);
- uv_pipe_open(outputStream, chain.OutputStream());
- auto outputHandle = cmUVStreamRead(
- outputStream,
- [this, &processOutput, &output, &tempOutput,
- &log](std::vector<char> data) {
- std::string strdata;
- processOutput.DecodeText(data.data(), data.size(), strdata);
- if (output) {
- cm::append(tempOutput, data.data(), data.data() + data.size());
- }
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
- cmCTestLogWrite(strdata.c_str(), strdata.size()));
- if (log) {
- log->write(strdata.c_str(), strdata.size());
- }
- },
- [this, &processOutput, &log]() {
- std::string strdata;
- processOutput.DecodeText(std::string(), strdata);
- if (!strdata.empty()) {
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
- cmCTestLogWrite(strdata.c_str(), strdata.size()));
- if (log) {
- log->write(strdata.c_str(), strdata.size());
- }
- }
- });
+ std::string strdata;
+ while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) {
+ processOutput.DecodeText(data, length, strdata);
+ if (output) {
+ cm::append(tempOutput, data, data + length);
+ }
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ cmCTestLogWrite(strdata.c_str(), strdata.size()));
+ if (log) {
+ log->write(strdata.c_str(), strdata.size());
+ }
+ }
+ processOutput.DecodeText(std::string(), strdata);
+ if (!strdata.empty()) {
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ cmCTestLogWrite(strdata.c_str(), strdata.size()));
+ if (log) {
+ log->write(strdata.c_str(), strdata.size());
+ }
+ }
- bool complete = chain.Wait(static_cast<uint64_t>(timeout.count() * 1000.0));
+ cmsysProcess_WaitForExit(cp, nullptr);
processOutput.DecodeText(tempOutput, tempOutput);
if (output && tempOutput.begin() != tempOutput.end()) {
output->append(tempOutput.data(), tempOutput.size());
@@ -1330,41 +1326,33 @@ bool cmCTest::RunTest(const std::vector<std::string>& argv,
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
"-- Process completed" << std::endl);
- bool result = false;
+ int result = cmsysProcess_GetState(cp);
- if (complete) {
- auto const& status = chain.GetStatus(0);
- auto exception = status.GetException();
- switch (exception.first) {
- case cmUVProcessChain::ExceptionCode::None:
- *retVal = static_cast<int>(status.ExitStatus);
- if (*retVal != 0 && this->Impl->OutputTestOutputOnTestFailure) {
- this->OutputTestErrors(tempOutput);
- }
- result = true;
- break;
- case cmUVProcessChain::ExceptionCode::Spawn: {
- std::string outerr =
- cmStrCat("\n*** ERROR executing: ", exception.second);
- if (output) {
- *output += outerr;
- }
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl);
- } break;
- default: {
- if (this->Impl->OutputTestOutputOnTestFailure) {
- this->OutputTestErrors(tempOutput);
- }
- *retVal = status.TermSignal;
- std::string outerr =
- cmStrCat("\n*** Exception executing: ", exception.second);
- if (output) {
- *output += outerr;
- }
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl);
- } break;
+ if (result == cmsysProcess_State_Exited) {
+ *retVal = cmsysProcess_GetExitValue(cp);
+ if (*retVal != 0 && this->Impl->OutputTestOutputOnTestFailure) {
+ this->OutputTestErrors(tempOutput);
+ }
+ } else if (result == cmsysProcess_State_Exception) {
+ if (this->Impl->OutputTestOutputOnTestFailure) {
+ this->OutputTestErrors(tempOutput);
+ }
+ *retVal = cmsysProcess_GetExitException(cp);
+ std::string outerr = cmStrCat("\n*** Exception executing: ",
+ cmsysProcess_GetExceptionString(cp));
+ if (output) {
+ *output += outerr;
+ }
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl);
+ } else if (result == cmsysProcess_State_Error) {
+ std::string outerr =
+ cmStrCat("\n*** ERROR executing: ", cmsysProcess_GetErrorString(cp));
+ if (output) {
+ *output += outerr;
}
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl);
}
+ cmsysProcess_Delete(cp);
return result;
}
@@ -3482,70 +3470,49 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args,
stdOut->clear();
stdErr->clear();
- cmUVProcessChainBuilder builder;
- builder.AddCommand(args)
- .SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
- .SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR);
- if (dir) {
- builder.SetWorkingDirectory(dir);
- }
- auto chain = builder.Start();
-
- cm::uv_timer_ptr timer;
- bool timedOut = false;
- if (timeout.count()) {
- timer.init(chain.GetLoop(), &timedOut);
- timer.start(
- [](uv_timer_t* t) {
- auto* timedOutPtr = static_cast<bool*>(t->data);
- *timedOutPtr = true;
- },
- static_cast<uint64_t>(timeout.count() * 1000.0), 0);
+ cmsysProcess* cp = cmsysProcess_New();
+ cmsysProcess_SetCommand(cp, argv.data());
+ cmsysProcess_SetWorkingDirectory(cp, dir);
+ if (cmSystemTools::GetRunCommandHideConsole()) {
+ cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
}
+ cmsysProcess_SetTimeout(cp, timeout.count());
+ cmsysProcess_Execute(cp);
std::vector<char> tempOutput;
- bool outFinished = false;
- cm::uv_pipe_ptr outStream;
std::vector<char> tempError;
- bool errFinished = false;
- cm::uv_pipe_ptr errStream;
+ char* data;
+ int length;
cmProcessOutput processOutput(encoding);
- auto startRead = [this, &chain, &processOutput](
- cm::uv_pipe_ptr& pipe, int stream,
- std::vector<char>& temp,
- bool& finished) -> std::unique_ptr<cmUVStreamReadHandle> {
- pipe.init(chain.GetLoop(), 0);
- uv_pipe_open(pipe, stream);
- return cmUVStreamRead(
- pipe,
- [this, &temp, &processOutput](std::vector<char> data) {
- cm::append(temp, data);
- if (this->Impl->ExtraVerbose) {
- std::string strdata;
- processOutput.DecodeText(data.data(), data.size(), strdata);
- cmSystemTools::Stdout(strdata);
- }
- },
- [&finished]() { finished = true; });
- };
- auto outputHandle =
- startRead(outStream, chain.OutputStream(), tempOutput, outFinished);
- auto errorHandle =
- startRead(errStream, chain.ErrorStream(), tempError, errFinished);
- while (!timedOut && !(outFinished && errFinished)) {
- uv_run(&chain.GetLoop(), UV_RUN_ONCE);
+ std::string strdata;
+ int res;
+ bool done = false;
+ while (!done) {
+ res = cmsysProcess_WaitForData(cp, &data, &length, nullptr);
+ switch (res) {
+ case cmsysProcess_Pipe_STDOUT:
+ cm::append(tempOutput, data, data + length);
+ break;
+ case cmsysProcess_Pipe_STDERR:
+ cm::append(tempError, data, data + length);
+ break;
+ default:
+ done = true;
+ }
+ if ((res == cmsysProcess_Pipe_STDOUT || res == cmsysProcess_Pipe_STDERR) &&
+ this->Impl->ExtraVerbose) {
+ processOutput.DecodeText(data, length, strdata);
+ cmSystemTools::Stdout(strdata);
+ }
}
if (this->Impl->ExtraVerbose) {
- std::string strdata;
processOutput.DecodeText(std::string(), strdata);
if (!strdata.empty()) {
cmSystemTools::Stdout(strdata);
}
}
- while (!timedOut && !chain.Finished()) {
- uv_run(&chain.GetLoop(), UV_RUN_ONCE);
- }
+ cmsysProcess_WaitForExit(cp, nullptr);
if (!tempOutput.empty()) {
processOutput.DecodeText(tempOutput, tempOutput);
stdOut->append(tempOutput.data(), tempOutput.size());
@@ -3556,32 +3523,32 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args,
}
bool result = true;
- if (timedOut) {
+ if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
+ if (retVal) {
+ *retVal = cmsysProcess_GetExitValue(cp);
+ } else {
+ if (cmsysProcess_GetExitValue(cp) != 0) {
+ result = false;
+ }
+ }
+ } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exception) {
+ const char* exception_str = cmsysProcess_GetExceptionString(cp);
+ cmCTestLog(this, ERROR_MESSAGE, exception_str << std::endl);
+ stdErr->append(exception_str, strlen(exception_str));
+ result = false;
+ } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Error) {
+ const char* error_str = cmsysProcess_GetErrorString(cp);
+ cmCTestLog(this, ERROR_MESSAGE, error_str << std::endl);
+ stdErr->append(error_str, strlen(error_str));
+ result = false;
+ } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Expired) {
const char* error_str = "Process terminated due to timeout\n";
cmCTestLog(this, ERROR_MESSAGE, error_str << std::endl);
stdErr->append(error_str, strlen(error_str));
result = false;
- } else {
- auto const& status = chain.GetStatus(0);
- auto exception = status.GetException();
- switch (exception.first) {
- case cmUVProcessChain::ExceptionCode::None:
- if (retVal) {
- *retVal = static_cast<int>(status.ExitStatus);
- } else {
- if (status.ExitStatus != 0) {
- result = false;
- }
- }
- break;
- default: {
- cmCTestLog(this, ERROR_MESSAGE, exception.second << std::endl);
- stdErr->append(exception.second);
- result = false;
- } break;
- }
}
+ cmsysProcess_Delete(cp);
return result;
}