15 #include <gtest/gtest.h>
31 std::vector<std::string> args = {
34 "for x in {1. .2}; do sleep 1 && dd if=/dev/random of=/dev/stdout count=2 bs=4096 "
35 "iflag=fullblock status=none; done"};
38 std::string stdout_at_term;
41 EXPECT_FALSE(proc.IsRunning());
42 EXPECT_FALSE(proc.GetPid().has_value());
45 proc.ConnectStdout([&](pid_t, std::string
const& line) { stdout += line; });
47 boost::future<int> fut = proc.Initiate().then(m_exec, [&](boost::future<int> exit_code) ->
int {
49 stdout_at_term = stdout;
50 EXPECT_FALSE(proc.IsRunning());
51 auto code = exit_code.get();
52 EXPECT_EQ(code, 0) <<
"Unexpected exit code";
56 EXPECT_TRUE(proc.IsRunning());
57 EXPECT_TRUE(proc.GetPid().has_value());
62 <<
"Expected continuation to have been executed as io_context::run has exited";
64 <<
"Output changed after future continuation executed. "
65 "This indicates that the process termination synchronization in AsyncProcess "
66 "doesn't work as advertised!";
72 std::vector<std::string> args = {
"sleep",
"2"};
76 EXPECT_EQ(proc.Signal(SIGTERM), std::errc::no_such_process);
77 EXPECT_FALSE(proc.IsRunning());
80 boost::future<int> fut =
81 proc.Initiate().then(m_exec, [&](boost::future<int> exit_code) ->
int {
83 EXPECT_FALSE(proc.IsRunning());
84 auto code = exit_code.get();
85 EXPECT_EQ(code, 15) <<
"Unexpected exit code for SIGTERM";
89 EXPECT_TRUE(proc.IsRunning());
96 <<
"Expected continuation to have been executed as io_context::run has exited";
101 std::vector<std::string> args = {
"sleep",
"2"};
105 EXPECT_EQ(proc.Abort(), std::errc::no_such_process);
106 EXPECT_FALSE(proc.IsRunning());
109 boost::future<int> fut =
110 proc.Initiate().then(m_exec, [&](boost::future<int> exit_code) ->
int {
112 EXPECT_FALSE(proc.IsRunning());
113 auto code = exit_code.get();
114 EXPECT_EQ(code, 9) <<
"Unexpected exit code for a SIGKILL";
118 EXPECT_TRUE(proc.IsRunning());
125 <<
"Expected continuation to have been executed as io_context::run has exited";
130 std::vector<std::string> args = {
133 "for x in {1. .2}; do sleep 1 && dd if=/dev/random of=/dev/stdout count=2 bs=4096 "
134 "iflag=fullblock status=none; done"};
136 for (
int i = 0;
i < 10; ++
i) {
137 auto proc = std::make_shared<daq::AsyncProcess>(m_ctx, args);
138 auto stdout = std::make_shared<std::string>();
139 proc->ConnectStdout([&, stdout](pid_t, std::string
const& line) { *stdout += line; });
141 proc->Initiate().then(m_exec, [&, proc, stdout](boost::future<int> exit_code) {
143 EXPECT_EQ(exit_code.get(), 0) <<
"Unexpected exit code";
daq::AsyncProcess class definition
boost::asio::io_context m_ctx
Represents a subprocess as an asynchronous operation.
Adapts boost::asio::io_context into a compatible boost::thread Executor type.
TEST_F(AsyncProcessTest, ReadAll)
EXPECT_EQ(meta.rr_uri, "zpb.rr://meta")