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