Add integration test for service "restart" function.
[oweals/dinit.git] / src / igr-tests / igr-runner.cc
1 #include <string>
2 #include <iostream>
3 #include <cstring>
4
5 #include <spawn.h>
6 #include <unistd.h>
7 #include <sys/wait.h>
8
9 extern char **environ;
10
11 // Integration test suite runner.
12
13 int main(int argc, char **argv)
14 {
15     const char * const test_dirs[] = { "basic", "environ", "ps-environ", "chain-to", "force-stop", "restart" };
16     constexpr int num_tests = sizeof(test_dirs) / sizeof(test_dirs[0]);
17
18     int passed = 0;
19     int skipped = 0;
20     int failed = 0;
21
22     bool aborted_run = false;
23
24     std::cout << "============== INTEGRATION TESTS =====================" << std::endl;
25
26     for (int i = 0; i < num_tests; i++) {
27         const char * test_dir = test_dirs[i];
28
29         std::string prog_path = "./run-test.sh";
30         char * const p_argv[2] = { const_cast<char *>(prog_path.c_str()), nullptr };
31
32         std::cout << test_dir << "... ";
33
34         // "Use posix_spawn", they said. "It will be easy", they said.
35
36         if (chdir(test_dir) != 0) {
37             std::cerr << "Couldn't chdir: " << test_dir << ": " << strerror(errno) << std::endl;
38             continue;
39         }
40
41         posix_spawn_file_actions_t p_actions;
42         posix_spawnattr_t p_attr;
43
44         if (posix_spawn_file_actions_init(&p_actions) != 0) {
45             // out of memory?
46             std::cerr << "Error launching process: " << test_dir << "/run-test.sh: " << strerror(errno) << std::endl;
47             aborted_run = true;
48             break;
49         }
50
51         if (posix_spawnattr_init(&p_attr) != 0) {
52             // out of memory?
53             std::cerr << "Error launching process: " << test_dir << "/run-test.sh: " << strerror(errno) << std::endl;
54             aborted_run = true;
55             break;
56         }
57
58         pid_t subproc_pid;
59         if (posix_spawn(&subproc_pid, prog_path.c_str(), &p_actions, &p_attr, p_argv, environ) != 0) {
60             // fail out
61             std::cerr << "Failed to run run-test.sh in " << test_dir << std::endl;
62             continue;
63         }
64
65         int wstatus;
66         if (waitpid(subproc_pid, &wstatus, 0) == -1) {
67             std::cout << "(unknown)" << std::endl;
68             std::cerr << "waitpid() failed" << std::endl;
69             aborted_run = true;
70             break;
71         }
72
73         if (WIFEXITED(wstatus)) {
74             if (WEXITSTATUS(wstatus) == 0) {
75                 std::cout << "PASSED" << std::endl;
76                 passed++;
77             }
78             else if (WEXITSTATUS(wstatus) == 1) {
79                 std::cout << "FAILED" << std::endl;
80                 failed++;
81             }
82             else if (WEXITSTATUS(wstatus) == 2) {
83                 std::cout << "SKIPPED" << std::endl;
84                 skipped++;
85             }
86             else {
87                 std::cout << "???" << std::endl;
88             }
89         }
90         else {
91             std::cout << "*** terminated abnormally ***" << std::endl;
92             aborted_run = true;
93             break;
94         }
95
96         posix_spawnattr_destroy(&p_attr);
97         posix_spawn_file_actions_destroy(&p_actions);
98         chdir("..");
99     }
100
101     std::cout << "======================================================" << std::endl;
102
103     if (! aborted_run) {
104         std::cout << "Test run finished.\n"
105                 "Passed: " << passed << "\n"
106                 "Failed: " << failed;
107         if (failed != 0) {
108             std::cout << " XXX";
109         }
110         std::cout << "\n"
111                 "Skipped: " << skipped << std::endl;
112     }
113     else {
114         std::cout << "Test run aborted." << std::endl;
115     }
116
117     return failed == 0 ? 0 : 1;
118 }