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";
63 EXPECT_EQ(stdout, stdout_at_term)
64 <<
"Output changed after future continuation executed. "
65 "This indicates that the process termination synchronization in AsyncProcess "
66 "doesn't work as advertised!";
67 EXPECT_EQ(stdout.size(), 2 * 4096 * 2);
68 EXPECT_EQ(fut.get(), 0);
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";
97 EXPECT_EQ(fut.get(), 15);
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";
126 EXPECT_EQ(fut.get(), 9);
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) {
142 EXPECT_EQ(stdout->size(), 2 * 4096 * 2);
143 EXPECT_EQ(exit_code.get(), 0) <<
"Unexpected exit code";