cmCTest: Replace cmsysProcess with cmUVProcessChain

This commit is contained in:
Kyle Edwards 2023-07-25 17:14:20 -04:00
parent 50a6e78a82
commit b15ad7ebb6
4 changed files with 246 additions and 216 deletions

View File

@ -7,8 +7,6 @@
#include <cstring> #include <cstring>
#include <ratio> #include <ratio>
#include "cmsys/Process.h"
#include "cmBuildOptions.h" #include "cmBuildOptions.h"
#include "cmCTest.h" #include "cmCTest.h"
#include "cmCTestTestHandler.h" #include "cmCTestTestHandler.h"
@ -308,12 +306,11 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
return 1; return 1;
} }
std::vector<const char*> testCommand; std::vector<std::string> testCommand;
testCommand.push_back(fullPath.c_str()); testCommand.push_back(fullPath);
for (std::string const& testCommandArg : this->TestCommandArgs) { for (std::string const& testCommandArg : this->TestCommandArgs) {
testCommand.push_back(testCommandArg.c_str()); testCommand.push_back(testCommandArg);
} }
testCommand.push_back(nullptr);
std::string outs; std::string outs;
int retval = 0; int retval = 0;
// run the test from the this->BuildRunDir if set // run the test from the this->BuildRunDir if set
@ -349,10 +346,10 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
} }
} }
int runTestRes = this->CTest->RunTest(testCommand, &outs, &retval, nullptr, bool runTestRes = this->CTest->RunTest(testCommand, &outs, &retval, nullptr,
remainingTime, nullptr); remainingTime, nullptr);
if (runTestRes != cmsysProcess_State_Exited || retval != 0) { if (!runTestRes || retval != 0) {
out << "Test command failed: " << testCommand[0] << "\n"; out << "Test command failed: " << testCommand[0] << "\n";
retval = 1; retval = 1;
} }

View File

@ -45,7 +45,7 @@ int cmCTestConfigureHandler::ProcessHandler()
auto elapsed_time_start = std::chrono::steady_clock::now(); auto elapsed_time_start = std::chrono::steady_clock::now();
std::string output; std::string output;
int retVal = 0; int retVal = 0;
int res = 0; bool res = false;
if (!this->CTest->GetShowOnly()) { if (!this->CTest->GetShowOnly()) {
cmGeneratedFileStream os; cmGeneratedFileStream os;
if (!this->StartResultingXML(cmCTest::PartConfigure, "Configure", os)) { if (!this->StartResultingXML(cmCTest::PartConfigure, "Configure", os)) {

View File

@ -5,6 +5,7 @@
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include <chrono> #include <chrono>
#include <cstdint>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
@ -24,13 +25,13 @@
#include <cmext/string_view> #include <cmext/string_view>
#include <cm3p/curl/curl.h> #include <cm3p/curl/curl.h>
#include <cm3p/uv.h>
#include <cm3p/zlib.h> #include <cm3p/zlib.h>
#include "cmsys/Base64.h" #include "cmsys/Base64.h"
#include "cmsys/Directory.hxx" #include "cmsys/Directory.hxx"
#include "cmsys/FStream.hxx" #include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx" #include "cmsys/Glob.hxx"
#include "cmsys/Process.h"
#include "cmsys/RegularExpression.hxx" #include "cmsys/RegularExpression.hxx"
#include "cmsys/SystemInformation.hxx" #include "cmsys/SystemInformation.hxx"
#if defined(_WIN32) #if defined(_WIN32)
@ -64,6 +65,9 @@
#include "cmStateTypes.h" #include "cmStateTypes.h"
#include "cmStringAlgorithms.h" #include "cmStringAlgorithms.h"
#include "cmSystemTools.h" #include "cmSystemTools.h"
#include "cmUVHandlePtr.h"
#include "cmUVProcessChain.h"
#include "cmUVStream.h"
#include "cmValue.h" #include "cmValue.h"
#include "cmVersion.h" #include "cmVersion.h"
#include "cmVersionConfig.h" #include "cmVersionConfig.h"
@ -1074,9 +1078,9 @@ int cmCTest::GetTestModelFromString(const std::string& str)
// ###################################################################### // ######################################################################
// ###################################################################### // ######################################################################
int cmCTest::RunMakeCommand(const std::string& command, std::string& output, bool cmCTest::RunMakeCommand(const std::string& command, std::string& output,
int* retVal, const char* dir, cmDuration timeout, int* retVal, const char* dir, cmDuration timeout,
std::ostream& ofs, Encoding encoding) std::ostream& ofs, Encoding encoding)
{ {
// First generate the command and arguments // First generate the command and arguments
std::vector<std::string> args = cmSystemTools::ParseArguments(command); std::vector<std::string> args = cmSystemTools::ParseArguments(command);
@ -1085,107 +1089,107 @@ int cmCTest::RunMakeCommand(const std::string& command, std::string& output,
return false; 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(); output.clear();
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Run command:"); cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Run command:");
for (char const* arg : argv) { for (auto const& arg : args) {
if (!arg) {
break;
}
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, " \"" << arg << "\""); cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, " \"" << arg << "\"");
} }
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, std::endl); cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, std::endl);
// Now create process object // Now create process object
cmsysProcess* cp = cmsysProcess_New(); cmUVProcessChainBuilder builder;
cmsysProcess_SetCommand(cp, argv.data()); builder.AddCommand(args).SetMergedBuiltinStreams();
cmsysProcess_SetWorkingDirectory(cp, dir); if (dir) {
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); builder.SetWorkingDirectory(dir);
cmsysProcess_SetTimeout(cp, timeout.count()); }
cmsysProcess_Execute(cp); auto chain = builder.Start();
cm::uv_pipe_ptr outputStream;
outputStream.init(chain.GetLoop(), 0);
uv_pipe_open(outputStream, chain.OutputStream());
// Initialize tick's // Initialize tick's
std::string::size_type tick = 0; std::string::size_type tick = 0;
std::string::size_type tick_len = 1024; std::string::size_type tick_len = 1024;
std::string::size_type tick_line_len = 50; std::string::size_type tick_line_len = 50;
char* data;
int length;
cmProcessOutput processOutput(encoding); cmProcessOutput processOutput(encoding);
std::string strdata;
cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
" Each . represents " << tick_len " Each . represents " << tick_len
<< " bytes of output\n" << " bytes of output\n"
" " " "
<< std::flush); << std::flush);
while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) { auto outputHandle = cmUVStreamRead(
processOutput.DecodeText(data, length, strdata); outputStream,
for (char& cc : strdata) { [this, &processOutput, &output, &tick, &tick_len, &tick_line_len,
if (cc == 0) { &ofs](std::vector<char> data) {
cc = '\n'; std::string strdata;
processOutput.DecodeText(data.data(), data.size(), strdata);
for (char& cc : strdata) {
if (cc == 0) {
cc = '\n';
}
} }
} output.append(strdata);
output.append(strdata); while (output.size() > (tick * tick_len)) {
while (output.size() > (tick * tick_len)) { tick++;
tick++; cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, "." << std::flush);
cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, "." << std::flush); if (tick % tick_line_len == 0 && tick > 0) {
if (tick % tick_line_len == 0 && tick > 0) { cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Size: " << int((double(output.size()) / 1024.0) + 1)
" Size: " << int((double(output.size()) / 1024.0) + 1) << "K\n " << std::flush);
<< "K\n " << std::flush); }
} }
} cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, cmCTestLogWrite(strdata.c_str(), strdata.size()));
cmCTestLogWrite(strdata.c_str(), strdata.size())); if (ofs) {
if (ofs) { ofs << cmCTestLogWrite(strdata.c_str(), strdata.size());
ofs << cmCTestLogWrite(strdata.c_str(), strdata.size()); }
} },
} [this, &processOutput, &output, &ofs]() {
processOutput.DecodeText(std::string(), strdata); std::string strdata;
if (!strdata.empty()) { processOutput.DecodeText(std::string(), strdata);
output.append(strdata); if (!strdata.empty()) {
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, output.append(strdata);
cmCTestLogWrite(strdata.c_str(), strdata.size())); cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
if (ofs) { cmCTestLogWrite(strdata.c_str(), strdata.size()));
ofs << cmCTestLogWrite(strdata.c_str(), strdata.size()); if (ofs) {
} ofs << cmCTestLogWrite(strdata.c_str(), strdata.size());
} }
}
});
bool finished = chain.Wait(static_cast<uint64_t>(timeout.count() * 1000.0));
cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
" Size of output: " << int(double(output.size()) / 1024.0) << "K" " Size of output: " << int(double(output.size()) / 1024.0) << "K"
<< std::endl); << std::endl);
cmsysProcess_WaitForExit(cp, nullptr); if (finished) {
auto const& status = chain.GetStatus(0);
int result = cmsysProcess_GetState(cp); auto exception = status.GetException();
switch (exception.first) {
if (result == cmsysProcess_State_Exited) { case cmUVProcessChain::ExceptionCode::None:
*retVal = cmsysProcess_GetExitValue(cp); *retVal = static_cast<int>(status.ExitStatus);
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
"Command exited with the value: " << *retVal << std::endl); "Command exited with the value: " << *retVal << std::endl);
} else if (result == cmsysProcess_State_Exception) { break;
*retVal = cmsysProcess_GetExitException(cp); case cmUVProcessChain::ExceptionCode::Spawn:
cmCTestLog(this, WARNING, output += "\n*** ERROR executing: ";
"There was an exception: " << *retVal << std::endl); output += exception.second;
} else if (result == cmsysProcess_State_Expired) { 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 {
cmCTestLog(this, WARNING, "There was a timeout" << std::endl); 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);
} }
cmsysProcess_Delete(cp); return true;
return result;
} }
// ###################################################################### // ######################################################################
@ -1193,9 +1197,10 @@ int cmCTest::RunMakeCommand(const std::string& command, std::string& output,
// ###################################################################### // ######################################################################
// ###################################################################### // ######################################################################
int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, bool cmCTest::RunTest(const std::vector<std::string>& argv,
int* retVal, std::ostream* log, cmDuration testTimeOut, std::string* output, int* retVal, std::ostream* log,
std::vector<std::string>* environment, Encoding encoding) cmDuration testTimeOut,
std::vector<std::string>* environment, Encoding encoding)
{ {
bool modifyEnv = (environment && !environment->empty()); bool modifyEnv = (environment && !environment->empty());
@ -1234,19 +1239,16 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
inst.SetStreams(&oss, &oss); inst.SetStreams(&oss, &oss);
std::vector<std::string> args; std::vector<std::string> args;
for (char const* i : argv) { for (auto const& i : argv) {
if (i) { // make sure we pass the timeout in for any build and test
// make sure we pass the timeout in for any build and test // invocations. Since --build-generator is required this is a
// invocations. Since --build-generator is required this is a // good place to check for it, and to add the arguments in
// good place to check for it, and to add the arguments in if (i == "--build-generator" && timeout != cmCTest::MaxDuration() &&
if (strcmp(i, "--build-generator") == 0 && timeout > cmDuration::zero()) {
timeout != cmCTest::MaxDuration() && args.emplace_back("--test-timeout");
timeout > cmDuration::zero()) { args.push_back(std::to_string(cmDurationTo<unsigned int>(timeout)));
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) { if (log) {
*log << "* Run internal CTest" << std::endl; *log << "* Run internal CTest" << std::endl;
@ -1272,7 +1274,7 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
<< std::endl); << std::endl);
} }
return cmsysProcess_State_Exited; return true;
} }
std::vector<char> tempOutput; std::vector<char> tempOutput;
if (output) { if (output) {
@ -1285,41 +1287,43 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
cmSystemTools::AppendEnv(*environment); cmSystemTools::AppendEnv(*environment);
} }
cmsysProcess* cp = cmsysProcess_New(); cmUVProcessChainBuilder builder;
cmsysProcess_SetCommand(cp, argv.data()); builder.AddCommand(argv).SetMergedBuiltinStreams();
cmCTestLog(this, DEBUG, "Command is: " << argv[0] << std::endl); cmCTestLog(this, DEBUG, "Command is: " << argv[0] << std::endl);
if (cmSystemTools::GetRunCommandHideConsole()) { auto chain = builder.Start();
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
}
cmsysProcess_SetTimeout(cp, timeout.count());
cmsysProcess_Execute(cp);
char* data;
int length;
cmProcessOutput processOutput(encoding); cmProcessOutput processOutput(encoding);
std::string strdata; cm::uv_pipe_ptr outputStream;
while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) { outputStream.init(chain.GetLoop(), 0);
processOutput.DecodeText(data, length, strdata); uv_pipe_open(outputStream, chain.OutputStream());
if (output) { auto outputHandle = cmUVStreamRead(
cm::append(tempOutput, data, data + length); outputStream,
} [this, &processOutput, &output, &tempOutput,
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, &log](std::vector<char> data) {
cmCTestLogWrite(strdata.c_str(), strdata.size())); std::string strdata;
if (log) { processOutput.DecodeText(data.data(), data.size(), strdata);
log->write(strdata.c_str(), strdata.size()); if (output) {
} cm::append(tempOutput, data.data(), data.data() + data.size());
} }
processOutput.DecodeText(std::string(), strdata); cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
if (!strdata.empty()) { cmCTestLogWrite(strdata.c_str(), strdata.size()));
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, if (log) {
cmCTestLogWrite(strdata.c_str(), strdata.size())); log->write(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());
}
}
});
cmsysProcess_WaitForExit(cp, nullptr); bool complete = chain.Wait(static_cast<uint64_t>(timeout.count() * 1000.0));
processOutput.DecodeText(tempOutput, tempOutput); processOutput.DecodeText(tempOutput, tempOutput);
if (output && tempOutput.begin() != tempOutput.end()) { if (output && tempOutput.begin() != tempOutput.end()) {
output->append(tempOutput.data(), tempOutput.size()); output->append(tempOutput.data(), tempOutput.size());
@ -1327,33 +1331,41 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
"-- Process completed" << std::endl); "-- Process completed" << std::endl);
int result = cmsysProcess_GetState(cp); bool result = false;
if (result == cmsysProcess_State_Exited) { if (complete) {
*retVal = cmsysProcess_GetExitValue(cp); auto const& status = chain.GetStatus(0);
if (*retVal != 0 && this->Impl->OutputTestOutputOnTestFailure) { auto exception = status.GetException();
this->OutputTestErrors(tempOutput); 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;
} }
} 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; return result;
} }
@ -3471,49 +3483,70 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args,
stdOut->clear(); stdOut->clear();
stdErr->clear(); stdErr->clear();
cmsysProcess* cp = cmsysProcess_New(); cmUVProcessChainBuilder builder;
cmsysProcess_SetCommand(cp, argv.data()); builder.AddCommand(args)
cmsysProcess_SetWorkingDirectory(cp, dir); .SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
if (cmSystemTools::GetRunCommandHideConsole()) { .SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR);
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); 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_SetTimeout(cp, timeout.count());
cmsysProcess_Execute(cp);
std::vector<char> tempOutput; std::vector<char> tempOutput;
bool outFinished = false;
cm::uv_pipe_ptr outStream;
std::vector<char> tempError; std::vector<char> tempError;
char* data; bool errFinished = false;
int length; cm::uv_pipe_ptr errStream;
cmProcessOutput processOutput(encoding); cmProcessOutput processOutput(encoding);
std::string strdata; auto startRead = [this, &chain, &processOutput](
int res; cm::uv_pipe_ptr& pipe, int stream,
bool done = false; std::vector<char>& temp,
while (!done) { bool& finished) -> std::unique_ptr<cmUVStreamReadHandle> {
res = cmsysProcess_WaitForData(cp, &data, &length, nullptr); pipe.init(chain.GetLoop(), 0);
switch (res) { uv_pipe_open(pipe, stream);
case cmsysProcess_Pipe_STDOUT: return cmUVStreamRead(
cm::append(tempOutput, data, data + length); pipe,
break; [this, &temp, &processOutput](std::vector<char> data) {
case cmsysProcess_Pipe_STDERR: cm::append(temp, data);
cm::append(tempError, data, data + length); if (this->Impl->ExtraVerbose) {
break; std::string strdata;
default: processOutput.DecodeText(data.data(), data.size(), strdata);
done = true; cmSystemTools::Stdout(strdata);
} }
if ((res == cmsysProcess_Pipe_STDOUT || res == cmsysProcess_Pipe_STDERR) && },
this->Impl->ExtraVerbose) { [&finished]() { finished = true; });
processOutput.DecodeText(data, length, strdata); };
cmSystemTools::Stdout(strdata); 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);
} }
if (this->Impl->ExtraVerbose) { if (this->Impl->ExtraVerbose) {
std::string strdata;
processOutput.DecodeText(std::string(), strdata); processOutput.DecodeText(std::string(), strdata);
if (!strdata.empty()) { if (!strdata.empty()) {
cmSystemTools::Stdout(strdata); cmSystemTools::Stdout(strdata);
} }
} }
cmsysProcess_WaitForExit(cp, nullptr); while (!timedOut && !chain.Finished()) {
uv_run(&chain.GetLoop(), UV_RUN_ONCE);
}
if (!tempOutput.empty()) { if (!tempOutput.empty()) {
processOutput.DecodeText(tempOutput, tempOutput); processOutput.DecodeText(tempOutput, tempOutput);
stdOut->append(tempOutput.data(), tempOutput.size()); stdOut->append(tempOutput.data(), tempOutput.size());
@ -3524,32 +3557,32 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args,
} }
bool result = true; bool result = true;
if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) { if (timedOut) {
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"; const char* error_str = "Process terminated due to timeout\n";
cmCTestLog(this, ERROR_MESSAGE, error_str << std::endl); cmCTestLog(this, ERROR_MESSAGE, error_str << std::endl);
stdErr->append(error_str, strlen(error_str)); stdErr->append(error_str, strlen(error_str));
result = false; 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; return result;
} }

View File

@ -254,10 +254,10 @@ public:
* Run command specialized for make and configure. Returns process status * Run command specialized for make and configure. Returns process status
* and retVal is return value or exception. * and retVal is return value or exception.
*/ */
int RunMakeCommand(const std::string& command, std::string& output, bool RunMakeCommand(const std::string& command, std::string& output,
int* retVal, const char* dir, cmDuration timeout, int* retVal, const char* dir, cmDuration timeout,
std::ostream& ofs, std::ostream& ofs,
Encoding encoding = cmProcessOutput::Auto); Encoding encoding = cmProcessOutput::Auto);
/** Return the current tag */ /** Return the current tag */
std::string GetCurrentTag(); std::string GetCurrentTag();
@ -303,10 +303,10 @@ public:
* environment variables prior to running the test. After running the test, * environment variables prior to running the test. After running the test,
* environment variables are restored to their previous values. * environment variables are restored to their previous values.
*/ */
int RunTest(std::vector<const char*> args, std::string* output, int* retVal, bool RunTest(const std::vector<std::string>& args, std::string* output,
std::ostream* logfile, cmDuration testTimeOut, int* retVal, std::ostream* logfile, cmDuration testTimeOut,
std::vector<std::string>* environment, std::vector<std::string>* environment,
Encoding encoding = cmProcessOutput::Auto); Encoding encoding = cmProcessOutput::Auto);
/** /**
* Get the handler object * Get the handler object