aboutsummaryrefslogtreecommitdiffstats
path: root/util/system
diff options
context:
space:
mode:
authortorkve <torkve@yandex-team.ru>2022-02-10 16:48:23 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:48:23 +0300
commitd2e3ef74aed5c066cc49df962b30ceb4318778ac (patch)
tree5d5cb817648f650d76cf1076100726fd9b8448e8 /util/system
parentf9cfbeee51d5849127bb58793a2edcdfd7bb91bb (diff)
downloadydb-d2e3ef74aed5c066cc49df962b30ceb4318778ac.tar.gz
Restoring authorship annotation for <torkve@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'util/system')
-rw-r--r--util/system/shellcommand.cpp202
-rw-r--r--util/system/shellcommand.h316
-rw-r--r--util/system/shellcommand_ut.cpp116
3 files changed, 317 insertions, 317 deletions
diff --git a/util/system/shellcommand.cpp b/util/system/shellcommand.cpp
index 9b30cfcc1b..b1989b5c8c 100644
--- a/util/system/shellcommand.cpp
+++ b/util/system/shellcommand.cpp
@@ -1,4 +1,4 @@
-#include "shellcommand.h"
+#include "shellcommand.h"
#include "user.h"
#include "nice.h"
#include "sigset.h"
@@ -10,14 +10,14 @@
#include <util/generic/vector.h>
#include <util/generic/yexception.h>
#include <util/memory/tempbuf.h>
-#include <util/network/socket.h>
+#include <util/network/socket.h>
#include <util/stream/pipe.h>
-#include <util/stream/str.h>
+#include <util/stream/str.h>
#include <util/string/cast.h>
#include <util/system/info.h>
-#include <errno.h>
-
+#include <errno.h>
+
#if defined(_unix_)
#include <unistd.h>
#include <fcntl.h>
@@ -177,7 +177,7 @@ public:
TRealPipeHandle(fds[1]).Swap(writer);
}
-private:
+private:
REALPIPEHANDLE Fd_;
};
@@ -203,7 +203,7 @@ private:
TString CollectedError;
TString InternalError;
TThread* WatchThread;
- TMutex TerminateMutex;
+ TMutex TerminateMutex;
TFileHandle InputHandle;
TFileHandle OutputHandle;
TFileHandle ErrorHandle;
@@ -227,8 +227,8 @@ private:
THashMap<TString, TString> Environment;
int Nice = 0;
std::function<void()> FuncAfterFork = {};
-
- struct TProcessInfo {
+
+ struct TProcessInfo {
TImpl* Parent;
TRealPipeHandle InputFd;
TRealPipeHandle OutputFd;
@@ -239,9 +239,9 @@ private:
, OutputFd(outputFd)
, ErrorFd(errorFd)
{
- }
- };
-
+ }
+ };
+
struct TPipes {
TRealPipeHandle OutputPipeFd[2];
TRealPipeHandle ErrorPipeFd[2];
@@ -279,7 +279,7 @@ private:
void StartProcess(TPipes& pipes);
#endif
-public:
+public:
inline TImpl(const TStringBuf cmd, const TList<TString>& args, const TShellCommandOptions& options, const TString& workdir)
: Pid(0)
, Command(ToString(cmd))
@@ -307,61 +307,61 @@ public:
, Environment(options.Environment)
, Nice(options.Nice)
, FuncAfterFork(options.FuncAfterFork)
- {
+ {
if (InputStream) {
// TODO change usages to call SetInputStream instead of directly assigning to InputStream
InputMode = TShellCommandOptions::HANDLE_STREAM;
}
- }
-
- inline ~TImpl() {
- if (WatchThread) {
+ }
+
+ inline ~TImpl() {
+ if (WatchThread) {
with_lock (TerminateMutex) {
- TerminateFlag = true;
- }
+ TerminateFlag = true;
+ }
- delete WatchThread;
- }
+ delete WatchThread;
+ }
#if defined(_win_)
if (Pid) {
CloseHandle(Pid);
}
#endif
- }
-
+ }
+
inline void AppendArgument(const TStringBuf argument) {
if (AtomicGet(ExecutionStatus) == SHELL_RUNNING) {
- ythrow yexception() << "You cannot change command parameters while process is running";
- }
+ ythrow yexception() << "You cannot change command parameters while process is running";
+ }
Arguments.push_back(ToString(argument));
- }
-
+ }
+
inline const TString& GetOutput() const {
if (AtomicGet(ExecutionStatus) == SHELL_RUNNING) {
- ythrow yexception() << "You cannot retrieve output while process is running.";
- }
- return CollectedOutput;
- }
-
+ ythrow yexception() << "You cannot retrieve output while process is running.";
+ }
+ return CollectedOutput;
+ }
+
inline const TString& GetError() const {
if (AtomicGet(ExecutionStatus) == SHELL_RUNNING) {
- ythrow yexception() << "You cannot retrieve output while process is running.";
- }
- return CollectedError;
- }
-
+ ythrow yexception() << "You cannot retrieve output while process is running.";
+ }
+ return CollectedError;
+ }
+
inline const TString& GetInternalError() const {
if (AtomicGet(ExecutionStatus) != SHELL_INTERNAL_ERROR) {
- ythrow yexception() << "Internal error hasn't occured so can't be retrieved.";
- }
- return InternalError;
- }
-
- inline ECommandStatus GetStatus() const {
+ ythrow yexception() << "Internal error hasn't occured so can't be retrieved.";
+ }
+ return InternalError;
+ }
+
+ inline ECommandStatus GetStatus() const {
return static_cast<ECommandStatus>(AtomicGet(ExecutionStatus));
- }
-
+ }
+
inline TMaybe<int> GetExitCode() const {
return ExitCode;
}
@@ -388,7 +388,7 @@ public:
// start child process
void Run();
-
+
inline void Terminate() {
if (!!Pid && (AtomicGet(ExecutionStatus) == SHELL_RUNNING)) {
bool ok =
@@ -408,24 +408,24 @@ public:
}
}
- inline void Wait() {
+ inline void Wait() {
if (WatchThread) {
- WatchThread->Join();
+ WatchThread->Join();
}
- }
-
+ }
+
inline void CloseInput() {
AtomicSet(ShouldCloseInput, true);
}
inline static bool TerminateIsRequired(void* processInfo) {
TProcessInfo* pi = reinterpret_cast<TProcessInfo*>(processInfo);
- if (!pi->Parent->TerminateFlag) {
- return false;
- }
- pi->InputFd.Close();
- pi->ErrorFd.Close();
- pi->OutputFd.Close();
+ if (!pi->Parent->TerminateFlag) {
+ return false;
+ }
+ pi->InputFd.Close();
+ pi->ErrorFd.Close();
+ pi->OutputFd.Close();
if (pi->Parent->CloseStreams) {
if (pi->Parent->ErrorStream) {
@@ -436,13 +436,13 @@ public:
}
}
- delete pi;
- return true;
- }
-
+ delete pi;
+ return true;
+ }
+
// interchange io while process is alive
inline static void Communicate(TProcessInfo* pi);
-
+
inline static void* WatchProcess(void* data) {
TProcessInfo* pi = reinterpret_cast<TProcessInfo*>(data);
Communicate(pi);
@@ -511,7 +511,7 @@ public:
TString GetQuotedCommand() const;
};
-
+
#if defined(_win_)
void TShellCommand::TImpl::StartProcess(TShellCommand::TImpl::TPipes& pipes) {
// Setup STARTUPINFO to redirect handles.
@@ -931,9 +931,9 @@ void TShellCommand::TImpl::Communicate(TProcessInfo* pi) {
{
with_lock (pi->Parent->TerminateMutex) {
if (TerminateIsRequired(pi)) {
- return;
+ return;
}
- }
+ }
waitPidResult =
#if defined(_unix_)
@@ -1039,20 +1039,20 @@ void TShellCommand::TImpl::Communicate(TProcessInfo* pi) {
input = nullptr;
}
continue;
- }
+ }
bufPos = inputBuffer.Data();
- }
+ }
bytes = pi->InputFd.Write(bufPos, bytesToWrite);
if (bytes > 0) {
bytesToWrite -= bytes;
bufPos += bytes;
- } else {
+ } else {
input = nullptr;
- }
+ }
DBG(Cerr << "transferred " << bytes << " bytes of input" << Endl);
- }
+ }
#endif
}
DBG(Cerr << "process finished" << Endl);
@@ -1075,19 +1075,19 @@ void TShellCommand::TImpl::Communicate(TProcessInfo* pi) {
DWORD exitCode = STILL_ACTIVE;
if (!GetExitCodeProcess(pi->Parent->Pid, &exitCode)) {
ythrow yexception() << "GetExitCodeProcess: " << LastSystemErrorText();
- }
+ }
if (exitCode == 0)
cleanExit = true;
processExitCode = static_cast<int>(exitCode);
DBG(Cerr << "exit code: " << exitCode << Endl);
- }
+ }
#endif
pi->Parent->ExitCode = processExitCode;
if (cleanExit) {
AtomicSet(pi->Parent->ExecutionStatus, SHELL_FINISHED);
} else {
AtomicSet(pi->Parent->ExecutionStatus, SHELL_ERROR);
- }
+ }
#if defined(_win_)
for (auto& threadHolder : streamThreads)
@@ -1115,12 +1115,12 @@ void TShellCommand::TImpl::Communicate(TProcessInfo* pi) {
pi->InputFd.Close();
}
Cdbg << "shell command internal error: " << pi->Parent->InternalError << Endl;
- }
+ }
// Now we can safely delete process info struct and other data
pi->Parent->TerminateFlag = true;
TerminateIsRequired(pi);
}
-
+
TShellCommand::TShellCommand(const TStringBuf cmd, const TList<TString>& args, const TShellCommandOptions& options,
const TString& workdir)
: Impl(new TImpl(cmd, args, options, workdir))
@@ -1129,32 +1129,32 @@ TShellCommand::TShellCommand(const TStringBuf cmd, const TList<TString>& args, c
TShellCommand::TShellCommand(const TStringBuf cmd, const TShellCommandOptions& options, const TString& workdir)
: Impl(new TImpl(cmd, TList<TString>(), options, workdir))
-{
-}
-
+{
+}
+
TShellCommand::~TShellCommand() = default;
-
+
TShellCommand& TShellCommand::operator<<(const TStringBuf argument) {
Impl->AppendArgument(argument);
- return *this;
-}
-
+ return *this;
+}
+
const TString& TShellCommand::GetOutput() const {
- return Impl->GetOutput();
-}
-
+ return Impl->GetOutput();
+}
+
const TString& TShellCommand::GetError() const {
- return Impl->GetError();
-}
-
+ return Impl->GetError();
+}
+
const TString& TShellCommand::GetInternalError() const {
- return Impl->GetInternalError();
-}
-
+ return Impl->GetInternalError();
+}
+
TShellCommand::ECommandStatus TShellCommand::GetStatus() const {
- return Impl->GetStatus();
-}
-
+ return Impl->GetStatus();
+}
+
TMaybe<int> TShellCommand::GetExitCode() const {
return Impl->GetExitCode();
}
@@ -1176,19 +1176,19 @@ TFileHandle& TShellCommand::GetErrorHandle() {
}
TShellCommand& TShellCommand::Run() {
- Impl->Run();
- return *this;
-}
-
+ Impl->Run();
+ return *this;
+}
+
TShellCommand& TShellCommand::Terminate() {
Impl->Terminate();
return *this;
}
TShellCommand& TShellCommand::Wait() {
- Impl->Wait();
- return *this;
-}
+ Impl->Wait();
+ return *this;
+}
TShellCommand& TShellCommand::CloseInput() {
Impl->CloseInput();
diff --git a/util/system/shellcommand.h b/util/system/shellcommand.h
index d787bf6384..8730627fe5 100644
--- a/util/system/shellcommand.h
+++ b/util/system/shellcommand.h
@@ -1,21 +1,21 @@
-#pragma once
-
-#include <util/generic/noncopyable.h>
+#pragma once
+
+#include <util/generic/noncopyable.h>
#include <util/generic/string.h>
-#include <util/generic/list.h>
+#include <util/generic/list.h>
#include <util/generic/hash.h>
-#include <util/generic/strbuf.h>
+#include <util/generic/strbuf.h>
#include <util/generic/maybe.h>
-#include <util/stream/input.h>
-#include <util/stream/output.h>
+#include <util/stream/input.h>
+#include <util/stream/output.h>
#include "file.h"
#include "getpid.h"
#include "thread.h"
#include "mutex.h"
-#include <sys/types.h>
-
+#include <sys/types.h>
+
class TShellCommandOptions {
-public:
+public:
struct TUserOptions {
TString Name;
#if defined(_win_)
@@ -57,15 +57,15 @@ public:
, Nice(0)
, FuncAfterFork(std::function<void()>())
{
- }
-
+ }
+
inline TShellCommandOptions& SetNice(int value) noexcept {
Nice = value;
return *this;
}
- /**
+ /**
* @brief clear signal mask from parent process. If true, child process
* clears the signal mask inherited from the parent process; otherwise
* child process retains the signal mask of the parent process.
@@ -94,21 +94,21 @@ public:
}
/**
- * @brief set asynchronous mode. If true, task will be run
- * in separate thread, and control will be returned immediately
- *
- * @param async true if asynchonous mode is needed
+ * @brief set asynchronous mode. If true, task will be run
+ * in separate thread, and control will be returned immediately
+ *
+ * @param async true if asynchonous mode is needed
* @note in default async mode launcher will need 100% cpu for rapid process termination
- * @return self
- */
+ * @return self
+ */
inline TShellCommandOptions& SetAsync(bool async) {
- AsyncMode = async;
+ AsyncMode = async;
if (AsyncMode)
PollDelayMs = 0;
- return *this;
- }
-
- /**
+ return *this;
+ }
+
+ /**
* @brief specify delay for process controlling loop
* @param ms number of milliseconds to poll for
* @note for synchronous process default of 1s should generally fit
@@ -122,52 +122,52 @@ public:
}
/**
- * @brief set the stream, which is input fetched from
- *
- * @param stream Pointer to stream.
- * If stream is NULL or not set, input channel will be closed.
- *
- * @return self
- */
+ * @brief set the stream, which is input fetched from
+ *
+ * @param stream Pointer to stream.
+ * If stream is NULL or not set, input channel will be closed.
+ *
+ * @return self
+ */
inline TShellCommandOptions& SetInputStream(IInputStream* stream) {
- InputStream = stream;
+ InputStream = stream;
if (InputStream == nullptr) {
InputMode = HANDLE_INHERIT;
} else {
InputMode = HANDLE_STREAM;
}
- return *this;
- }
-
- /**
- * @brief set the stream, collecting the command output
- *
- * @param stream Pointer to stream.
- * If stream is NULL or not set, output will be collected to the
- * internal variable
- *
- * @return self
- */
+ return *this;
+ }
+
+ /**
+ * @brief set the stream, collecting the command output
+ *
+ * @param stream Pointer to stream.
+ * If stream is NULL or not set, output will be collected to the
+ * internal variable
+ *
+ * @return self
+ */
inline TShellCommandOptions& SetOutputStream(IOutputStream* stream) {
- OutputStream = stream;
- return *this;
- }
-
- /**
- * @brief set the stream, collecting the command error output
- *
- * @param stream Pointer to stream.
- * If stream is NULL or not set, errors will be collected to the
- * internal variable
- *
- * @return self
- */
+ OutputStream = stream;
+ return *this;
+ }
+
+ /**
+ * @brief set the stream, collecting the command error output
+ *
+ * @param stream Pointer to stream.
+ * If stream is NULL or not set, errors will be collected to the
+ * internal variable
+ *
+ * @return self
+ */
inline TShellCommandOptions& SetErrorStream(IOutputStream* stream) {
- ErrorStream = stream;
- return *this;
- }
-
- /**
+ ErrorStream = stream;
+ return *this;
+ }
+
+ /**
* @brief set if Finish() should be called on user-supplied streams
* if process is run in async mode Finish will be called in process' thread
* @param val if Finish() should be called
@@ -205,25 +205,25 @@ public:
}
/**
- * @brief set if the arguments should be wrapped in quotes.
- * Please, note that this option makes no difference between
- * real arguments and shell syntax, so if you execute something
- * like \b TShellCommand("sleep") << "3" << "&&" << "ls", your
- * command will look like:
- * sleep "3" "&&" "ls"
- * which will never end successfully.
- * By default, this option is turned on.
- *
+ * @brief set if the arguments should be wrapped in quotes.
+ * Please, note that this option makes no difference between
+ * real arguments and shell syntax, so if you execute something
+ * like \b TShellCommand("sleep") << "3" << "&&" << "ls", your
+ * command will look like:
+ * sleep "3" "&&" "ls"
+ * which will never end successfully.
+ * By default, this option is turned on.
+ *
* @note arguments will only be quoted if shell is used
- * @param quote if the arguments should be quoted
- *
- * @return self
- */
+ * @param quote if the arguments should be quoted
+ *
+ * @return self
+ */
inline TShellCommandOptions& SetQuoteArguments(bool quote) {
- QuoteArguments = quote;
- return *this;
- }
-
+ QuoteArguments = quote;
+ return *this;
+ }
+
/**
* @brief set to run command in new session
* @note set this option to off to deliver parent's signals to command as well
@@ -323,82 +323,82 @@ public:
static const size_t DefaultSyncPollDelay = 1000; // ms
std::function<void()> FuncAfterFork = {};
-};
-
-/**
- * @brief Execute command in shell and provide its results
- * @attention Not thread-safe
- */
+};
+
+/**
+ * @brief Execute command in shell and provide its results
+ * @attention Not thread-safe
+ */
class TShellCommand: public TNonCopyable {
-private:
- TShellCommand();
-
-public:
- enum ECommandStatus {
- SHELL_NONE,
- SHELL_RUNNING,
- SHELL_FINISHED,
- SHELL_INTERNAL_ERROR,
- SHELL_ERROR
- };
-
-public:
- /**
- * @brief create the command with initial arguments list
- *
- * @param cmd binary name
- * @param args arguments list
- * @param options execution options
+private:
+ TShellCommand();
+
+public:
+ enum ECommandStatus {
+ SHELL_NONE,
+ SHELL_RUNNING,
+ SHELL_FINISHED,
+ SHELL_INTERNAL_ERROR,
+ SHELL_ERROR
+ };
+
+public:
+ /**
+ * @brief create the command with initial arguments list
+ *
+ * @param cmd binary name
+ * @param args arguments list
+ * @param options execution options
* @todo store entire options structure
- */
+ */
TShellCommand(const TStringBuf cmd, const TList<TString>& args, const TShellCommandOptions& options = TShellCommandOptions(),
const TString& workdir = TString());
TShellCommand(const TStringBuf cmd, const TShellCommandOptions& options = TShellCommandOptions(), const TString& workdir = TString());
~TShellCommand();
-public:
- /**
- * @brief append argument to the args list
- *
- * @param argument string argument
- *
- * @return self
- */
+public:
+ /**
+ * @brief append argument to the args list
+ *
+ * @param argument string argument
+ *
+ * @return self
+ */
TShellCommand& operator<<(const TStringBuf argument);
-
- /**
- * @brief return the collected output from the command.
- * If the output stream is set, empty string will be returned
- *
- * @return collected output
- */
+
+ /**
+ * @brief return the collected output from the command.
+ * If the output stream is set, empty string will be returned
+ *
+ * @return collected output
+ */
const TString& GetOutput() const;
-
- /**
- * @brief return the collected error output from the command.
- * If the error stream is set, empty string will be returned
- *
- * @return collected error output
- */
+
+ /**
+ * @brief return the collected error output from the command.
+ * If the error stream is set, empty string will be returned
+ *
+ * @return collected error output
+ */
const TString& GetError() const;
-
- /**
- * @brief return the internal error occured while watching
- * the command execution. Should be called if execution
- * status is SHELL_INTERNAL_ERROR
- *
- * @return error text
- */
+
+ /**
+ * @brief return the internal error occured while watching
+ * the command execution. Should be called if execution
+ * status is SHELL_INTERNAL_ERROR
+ *
+ * @return error text
+ */
const TString& GetInternalError() const;
-
- /**
- * @brief get current status of command execution
- *
- * @return current status
- */
- ECommandStatus GetStatus() const;
-
- /**
+
+ /**
+ * @brief get current status of command execution
+ *
+ * @return current status
+ */
+ ECommandStatus GetStatus() const;
+
+ /**
* @brief return exit code of finished process
* The value is unspecified in case of internal errors or if the process is running
*
@@ -436,13 +436,13 @@ public:
TFileHandle& GetErrorHandle();
/**
- * @brief run the execution
- *
- * @return self
- */
+ * @brief run the execution
+ *
+ * @return self
+ */
TShellCommand& Run();
-
- /**
+
+ /**
* @brief terminate the execution
* @note if DetachSession is set, it terminates all procs in command's new process group
*
@@ -451,10 +451,10 @@ public:
TShellCommand& Terminate();
/**
- * @brief wait until the execution is finished
- *
- * @return self
- */
+ * @brief wait until the execution is finished
+ *
+ * @return self
+ */
TShellCommand& Wait();
/**
@@ -469,11 +469,11 @@ public:
**/
TString GetQuotedCommand() const;
-private:
- class TImpl;
+private:
+ class TImpl;
using TImplRef = TSimpleIntrusivePtr<TImpl>;
- TImplRef Impl;
-};
+ TImplRef Impl;
+};
/// Appends to dst: quoted arg
void ShellQuoteArg(TString& dst, TStringBuf arg);
diff --git a/util/system/shellcommand_ut.cpp b/util/system/shellcommand_ut.cpp
index c5e1ca8d76..9d849279d2 100644
--- a/util/system/shellcommand_ut.cpp
+++ b/util/system/shellcommand_ut.cpp
@@ -12,11 +12,11 @@
#include <util/folder/dirut.h>
#include <util/random/random.h>
#include <util/stream/file.h>
-#include <util/stream/str.h>
-#include <util/stream/mem.h>
-#include <util/string/strip.h>
+#include <util/stream/str.h>
+#include <util/stream/mem.h>
+#include <util/string/strip.h>
#include <util/folder/tempdir.h>
-
+
#if defined(_win_)
#define NL "\r\n"
const char catCommand[] = "sort"; // not really cat but ok
@@ -119,7 +119,7 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) {
const char dir[] = "ls";
#endif
- TShellCommandOptions options;
+ TShellCommandOptions options;
options.SetQuoteArguments(false);
{
@@ -145,7 +145,7 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) {
}
Y_UNIT_TEST(TestAsyncRun) {
TShellCommandOptions options;
- options.SetAsync(true);
+ options.SetAsync(true);
#if defined(_win_)
// fails with weird error "Input redirection is not supported"
// TShellCommand cmd("sleep", options);
@@ -155,43 +155,43 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) {
TShellCommand cmd("sleep", options);
cmd << "2";
#endif
- UNIT_ASSERT(TShellCommand::SHELL_NONE == cmd.GetStatus());
- cmd.Run();
- sleep(1);
- UNIT_ASSERT(TShellCommand::SHELL_RUNNING == cmd.GetStatus());
- cmd.Wait();
+ UNIT_ASSERT(TShellCommand::SHELL_NONE == cmd.GetStatus());
+ cmd.Run();
+ sleep(1);
+ UNIT_ASSERT(TShellCommand::SHELL_RUNNING == cmd.GetStatus());
+ cmd.Wait();
UNIT_ASSERT(TShellCommand::SHELL_RUNNING != cmd.GetStatus());
UNIT_ASSERT_VALUES_EQUAL(cmd.GetError(), "");
#if !defined(_win_)
- UNIT_ASSERT(TShellCommand::SHELL_FINISHED == cmd.GetStatus());
+ UNIT_ASSERT(TShellCommand::SHELL_FINISHED == cmd.GetStatus());
UNIT_ASSERT_VALUES_EQUAL(cmd.GetOutput().size(), 0u);
UNIT_ASSERT(cmd.GetExitCode().Defined() && 0 == cmd.GetExitCode());
#endif
- }
+ }
Y_UNIT_TEST(TestQuotes) {
- TShellCommandOptions options;
+ TShellCommandOptions options;
TString input = TString("a\"a a");
TString output;
- TStringOutput outputStream(output);
- options.SetOutputStream(&outputStream);
+ TStringOutput outputStream(output);
+ options.SetOutputStream(&outputStream);
TShellCommand cmd("echo", options);
- cmd << input;
- cmd.Run().Wait();
- output = StripString(output);
+ cmd << input;
+ cmd.Run().Wait();
+ output = StripString(output);
#if defined(_win_)
UNIT_ASSERT_VALUES_EQUAL("\"a\\\"a a\"", output);
#else
- UNIT_ASSERT_VALUES_EQUAL(input, output);
+ UNIT_ASSERT_VALUES_EQUAL(input, output);
#endif
UNIT_ASSERT_VALUES_EQUAL(cmd.GetError().size(), 0u);
- }
+ }
Y_UNIT_TEST(TestRunNonexistent) {
- TShellCommand cmd("iwerognweiofnewio"); // some nonexistent command name
- cmd.Run().Wait();
- UNIT_ASSERT(TShellCommand::SHELL_ERROR == cmd.GetStatus());
+ TShellCommand cmd("iwerognweiofnewio"); // some nonexistent command name
+ cmd.Run().Wait();
+ UNIT_ASSERT(TShellCommand::SHELL_ERROR == cmd.GetStatus());
UNIT_ASSERT_VALUES_UNEQUAL(cmd.GetError().size(), 0u);
UNIT_ASSERT(cmd.GetExitCode().Defined() && 0 != cmd.GetExitCode());
- }
+ }
Y_UNIT_TEST(TestExitCode) {
TShellCommand cmd("grep qwerty qwerty"); // some nonexistent file name
cmd.Run().Wait();
@@ -201,28 +201,28 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) {
}
// 'type con' and 'copy con con' want real console, not stdin, use sort
Y_UNIT_TEST(TestInput) {
- TShellCommandOptions options;
+ TShellCommandOptions options;
TString input = (TString("a") * 2000).append(NL) * textSize;
- TStringInput inputStream(input);
- options.SetInputStream(&inputStream);
+ TStringInput inputStream(input);
+ options.SetInputStream(&inputStream);
TShellCommand cmd(catCommand, options);
- cmd.Run().Wait();
- UNIT_ASSERT_VALUES_EQUAL(input, cmd.GetOutput());
+ cmd.Run().Wait();
+ UNIT_ASSERT_VALUES_EQUAL(input, cmd.GetOutput());
UNIT_ASSERT_VALUES_EQUAL(cmd.GetError().size(), 0u);
- }
+ }
Y_UNIT_TEST(TestOutput) {
- TShellCommandOptions options;
+ TShellCommandOptions options;
TString input = (TString("a") * 2000).append(NL) * textSize;
- TStringInput inputStream(input);
- options.SetInputStream(&inputStream);
+ TStringInput inputStream(input);
+ options.SetInputStream(&inputStream);
TString output;
- TStringOutput outputStream(output);
- options.SetOutputStream(&outputStream);
+ TStringOutput outputStream(output);
+ options.SetOutputStream(&outputStream);
TShellCommand cmd(catCommand, options);
- cmd.Run().Wait();
- UNIT_ASSERT_VALUES_EQUAL(input, output);
+ cmd.Run().Wait();
+ UNIT_ASSERT_VALUES_EQUAL(input, output);
UNIT_ASSERT_VALUES_EQUAL(cmd.GetError().size(), 0u);
- }
+ }
Y_UNIT_TEST(TestIO) {
// descriptive test: use all options
TShellCommandOptions options;
@@ -299,24 +299,24 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) {
Y_UNIT_TEST(TestInterrupt) {
TString tmpfile = TString("shellcommand_ut.interrupt.") + ToString(RandomNumber<ui32>());
- TShellCommandOptions options;
- options.SetAsync(true);
- options.SetQuoteArguments(false);
- {
- TShellCommand cmd("/bin/sleep", options);
+ TShellCommandOptions options;
+ options.SetAsync(true);
+ options.SetQuoteArguments(false);
+ {
+ TShellCommand cmd("/bin/sleep", options);
cmd << " 1300 & wait; /usr/bin/touch " << tmpfile;
- cmd.Run();
- sleep(1);
- UNIT_ASSERT(TShellCommand::SHELL_RUNNING == cmd.GetStatus());
+ cmd.Run();
+ sleep(1);
+ UNIT_ASSERT(TShellCommand::SHELL_RUNNING == cmd.GetStatus());
// Async mode requires Terminate() + Wait() to send kill to child proc!
cmd.Terminate();
cmd.Wait();
UNIT_ASSERT(TShellCommand::SHELL_ERROR == cmd.GetStatus());
UNIT_ASSERT(cmd.GetExitCode().Defined() && -15 == cmd.GetExitCode());
- }
- sleep(1);
+ }
+ sleep(1);
UNIT_ASSERT(!NFs::Exists(tmpfile));
- }
+ }
// this ut is unix-only (win has no signal mask)
Y_UNIT_TEST(TestSignalMask) {
// block SIGTERM
@@ -382,16 +382,16 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) {
#endif
Y_UNIT_TEST(TestInternalError) {
TString input = (TString("a") * 2000).append("\n");
- TStringInput inputStream(input);
+ TStringInput inputStream(input);
TMemoryOutput outputStream(nullptr, 0);
- TShellCommandOptions options;
- options.SetInputStream(&inputStream);
- options.SetOutputStream(&outputStream);
+ TShellCommandOptions options;
+ options.SetInputStream(&inputStream);
+ options.SetOutputStream(&outputStream);
TShellCommand cmd(catCommand, options);
- cmd.Run().Wait();
- UNIT_ASSERT(TShellCommand::SHELL_INTERNAL_ERROR == cmd.GetStatus());
+ cmd.Run().Wait();
+ UNIT_ASSERT(TShellCommand::SHELL_INTERNAL_ERROR == cmd.GetStatus());
UNIT_ASSERT_VALUES_UNEQUAL(cmd.GetInternalError().size(), 0u);
- }
+ }
Y_UNIT_TEST(TestHugeOutput) {
TShellCommandOptions options;
TGuardedStringStream stream;
@@ -490,4 +490,4 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) {
UNIT_ASSERT_VALUES_EQUAL(firstLine, text);
}
-}
+}