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";