Browse Source

Igr: convert force-stop test to run via igr-runner

Davin McCall 1 month ago
parent
commit
5efb6c0679
2 changed files with 98 additions and 12 deletions
  1. 41 3
      src/igr-tests/igr-runner.cc
  2. 57 9
      src/igr-tests/igr.h

+ 41 - 3
src/igr-tests/igr-runner.cc

@@ -22,10 +22,12 @@ void environ_test();
 void environ2_test();
 void ps_environ_test();
 void chain_to_test();
+void force_stop_test();
 
 int main(int argc, char **argv)
 {
-    void (*test_funcs[])() = { basic_test, environ_test, environ2_test, ps_environ_test, chain_to_test };
+    void (*test_funcs[])() = { basic_test, environ_test, environ2_test, ps_environ_test, chain_to_test,
+            force_stop_test };
     const char * const test_dirs[] = { "basic", "environ", "environ2", "ps-environ", "chain-to", "force-stop",
             "restart", "check-basic", "check-cycle", "check-cycle2", "check-lint", "reload1", "reload2",
             "no-command-error", "add-rm-dep", "var-subst", "svc-start-fail", "dep-not-found", "pseudo-cycle",
@@ -63,21 +65,24 @@ int main(int argc, char **argv)
         if ((unsigned)i < (sizeof(test_funcs) / sizeof(test_funcs[0]))) {
             // run function instead
             bool success;
+            std::string failure_msg;
             try {
                 test_funcs[i]();
                 success = true;
             }
             catch (igr_failure_exc &exc) {
                 success = false;
+                failure_msg = exc.get_message();
             }
 
             if (success) {
-                std::cout << "PASSED" << std::endl;
+                std::cout << "PASSED\n";
                 passed++;
             }
             else {
-                std::cout << "FAILED" << std::endl;
+                std::cout << "FAILED\n";
                 failed++;
+                std::cout << failure_msg << std::endl;
             }
 
             continue;
@@ -293,3 +298,36 @@ void chain_to_test()
 
     check_file_contents(output_file, read_file_contents("./chain-to/expected-output"));
 }
+
+void force_stop_test()
+{
+    igr_test_setup setup("force-stop");
+
+    dinit_proc dinit_p;
+    dinit_p.start("force-stop", {"-u", "-d", "sd", "-p", igr_dinit_socket_path, "-q"}, true);
+
+    // "dinitctl list"
+    dinitctl_proc dinitctl_p;
+    dinitctl_p.start("force-stop", {"-p", igr_dinit_socket_path, "list"});
+    dinitctl_p.wait_for_term({1, 0}  /* max 1 second */);
+
+    igr_assert_eq(read_file_contents("./force-stop/expected-1"), dinitctl_p.get_stdout());
+    igr_assert_eq("", dinitctl_p.get_stderr());
+
+    // "dinitctl stop critical"
+    dinitctl_p.start("force-stop", {"-p", igr_dinit_socket_path, "stop", "critical"});
+    dinitctl_p.wait_for_term({1, 0}  /* max 1 second */);
+
+    igr_assert_eq("", dinitctl_p.get_stdout());
+    igr_assert_eq(read_file_contents("./force-stop/expected-2.err"), dinitctl_p.get_stderr());
+
+    // "dinitctl stop --force critical"
+    dinitctl_p.start("force-stop", {"-p", igr_dinit_socket_path, "stop", "--force", "critical"});
+    dinitctl_p.wait_for_term({1, 0}  /* max 1 second */);
+
+    igr_assert_eq(read_file_contents("./force-stop/expected-3"), dinitctl_p.get_stdout());
+    igr_assert_eq("", dinitctl_p.get_stderr());
+
+    // dinit should stop since all services are now stopped
+    dinit_p.wait_for_term({1, 0});
+}

+ 57 - 9
src/igr-tests/igr.h

@@ -19,6 +19,7 @@ class igr_failure_exc
     std::string message;
 public:
     igr_failure_exc(std::string message_p) : message(message_p) { }
+    const std::string &get_message() { return message; }
 };
 
 // A process watcher that cleans up by terminating the child process
@@ -137,6 +138,11 @@ public:
         return buffer;
     }
 
+    void clear()
+    {
+        buffer.clear();
+    }
+
     dasynq::rearm fd_event(event_loop_t &loop, int fd, int flags)
     {
         // read all we can
@@ -162,24 +168,26 @@ public:
     }
 };
 
-// dinit process
-class dinit_proc
+// External process, for which all output is stored in a buffer (separately for stdout/stderr).
+class igr_proc
 {
     igr_proc_watch pwatch;
     pipe_consume_buffer out;
     pipe_consume_buffer err;
 
 public:
-    dinit_proc() {}
+    igr_proc() {}
 
-    ~dinit_proc() {}
+    ~igr_proc() {}
 
-    // start, in specified working directory, with given arguments
-    void start(const char *wdir, std::vector<std::string> args = {})
+    // Start, in specified working directory, with given arguments
+    void start(const char *wdir, const char *executable, std::vector<std::string> args = {})
     {
-        std::string dinit_exec = dinit_bindir + "/dinit";
+        out.clear();
+        err.clear();
+
         char **arg_arr = new char *[args.size() + 2];
-        arg_arr[0] = const_cast<char *>(dinit_exec.c_str());
+        arg_arr[0] = const_cast<char *>(executable);
 
         unsigned i;
         for (i = 0; i < args.size(); ++i) {
@@ -193,7 +201,7 @@ public:
             dup2(out.get_output_fd(), STDOUT_FILENO);
             dup2(err.get_output_fd(), STDERR_FILENO);
 
-            execv(dinit_exec.c_str(), arg_arr);
+            execv(executable, arg_arr);
             exit(EXIT_FAILURE);
         }
 
@@ -227,6 +235,46 @@ public:
     }
 };
 
+// dinit process
+class dinit_proc : public igr_proc
+{
+    std::unique_ptr<pipe_consume_buffer> ready_pipe_ptr;
+
+public:
+    dinit_proc() {}
+    ~dinit_proc() {}
+
+    void start(const char *wdir, std::vector<std::string> args = {}, bool with_ready_wait = false)
+    {
+        if (with_ready_wait) {
+            ready_pipe_ptr.reset(new pipe_consume_buffer());
+            args.insert(args.begin(), std::to_string(ready_pipe_ptr->get_output_fd()));
+            args.insert(args.begin(), "--ready-fd");
+        }
+
+        igr_proc::start(wdir, (dinit_bindir + "/dinit").c_str(), args);
+
+        if (with_ready_wait) {
+            while (ready_pipe_ptr->get_output().empty()) {
+                event_loop.run();
+            }
+        }
+    }
+};
+
+// dinitctl process
+class dinitctl_proc : public igr_proc
+{
+public:
+    dinitctl_proc() {}
+    ~dinitctl_proc() {}
+
+    void start(const char *wdir, std::vector<std::string> args = {}, bool with_ready_wait = false)
+    {
+        igr_proc::start(wdir, (dinit_bindir + "/dinitctl").c_str(), args);
+    }
+};
+
 // perform basic setup for a test (with automatic teardown)
 class igr_test_setup
 {