8 #include "proc-service.h"
10 // Tests of process-service related functionality.
12 // These tests work mostly by completely mocking out the base_process_service class. The mock
13 // implementations can be found in test-baseproc.cc.
15 // Friend interface to access base_process_service private/protected members.
16 class base_process_service_test
19 static void exec_succeeded(base_process_service *bsp)
21 bsp->waiting_for_execstat = false;
22 bsp->exec_succeeded();
25 static void handle_exit(base_process_service *bsp, int exit_status)
28 bsp->handle_exit_status(exit_status);
34 extern int last_sig_sent;
35 extern pid_t last_forked_pid;
38 static void init_service_defaults(process_service &ps)
40 ps.set_restart_interval(time_val(10,0), 3);
41 ps.set_restart_delay(time_val(0, 200000000)); // 200 milliseconds
42 ps.set_stop_timeout(time_val(10,0));
43 ps.set_start_timeout(time_val(10,0));
44 ps.set_start_interruptible(false);
47 // Regular service start
48 void test_proc_service_start()
54 string command = "test-command";
55 list<pair<unsigned,unsigned>> command_offsets;
56 command_offsets.emplace_back(0, command.length());
57 std::list<prelim_dep> depends;
59 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
60 init_service_defaults(p);
63 sset.process_queues();
65 assert(p.get_state() == service_state_t::STARTING);
67 base_process_service_test::exec_succeeded(&p);
68 sset.process_queues();
70 assert(p.get_state() == service_state_t::STARTED);
73 // Unexpected termination
74 void test_proc_unexpected_term()
80 string command = "test-command";
81 list<pair<unsigned,unsigned>> command_offsets;
82 command_offsets.emplace_back(0, command.length());
83 std::list<prelim_dep> depends;
85 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
87 sset.process_queues();
89 base_process_service_test::exec_succeeded(&p);
90 sset.process_queues();
92 assert(p.get_state() == service_state_t::STARTED);
94 base_process_service_test::handle_exit(&p, 0);
95 sset.process_queues();
97 assert(p.get_state() == service_state_t::STOPPED);
100 // Termination via stop request
101 void test_term_via_stop()
107 string command = "test-command";
108 list<pair<unsigned,unsigned>> command_offsets;
109 command_offsets.emplace_back(0, command.length());
110 std::list<prelim_dep> depends;
112 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
113 init_service_defaults(p);
116 sset.process_queues();
118 base_process_service_test::exec_succeeded(&p);
119 sset.process_queues();
121 assert(p.get_state() == service_state_t::STARTED);
124 sset.process_queues();
126 assert(p.get_state() == service_state_t::STOPPING);
128 base_process_service_test::handle_exit(&p, 0);
129 sset.process_queues();
131 assert(p.get_state() == service_state_t::STOPPED);
134 // Time-out during start
135 void test_proc_start_timeout()
141 string command = "test-command";
142 list<pair<unsigned,unsigned>> command_offsets;
143 command_offsets.emplace_back(0, command.length());
144 std::list<prelim_dep> depends;
146 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
147 init_service_defaults(p);
150 sset.process_queues();
152 assert(p.get_state() == service_state_t::STARTING);
155 sset.process_queues();
157 assert(p.get_state() == service_state_t::STOPPING);
159 base_process_service_test::handle_exit(&p, 0);
160 sset.process_queues();
162 assert(p.get_state() == service_state_t::STOPPED);
166 void test_proc_stop_timeout()
172 string command = "test-command";
173 list<pair<unsigned,unsigned>> command_offsets;
174 command_offsets.emplace_back(0, command.length());
175 std::list<prelim_dep> depends;
177 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
178 init_service_defaults(p);
181 sset.process_queues();
183 assert(p.get_state() == service_state_t::STARTING);
185 base_process_service_test::exec_succeeded(&p);
186 sset.process_queues();
188 assert(p.get_state() == service_state_t::STARTED);
191 sset.process_queues();
193 assert(p.get_state() == service_state_t::STOPPING);
194 assert(bp_sys::last_sig_sent == SIGTERM);
197 sset.process_queues();
199 // kill signal (SIGKILL) should have been sent; process not dead until it's dead, however
200 assert(p.get_state() == service_state_t::STOPPING);
201 assert(bp_sys::last_sig_sent == SIGKILL);
203 base_process_service_test::handle_exit(&p, 0);
204 sset.process_queues();
206 assert(p.get_state() == service_state_t::STOPPED);
210 void test_proc_smooth_recovery1()
216 string command = "test-command";
217 list<pair<unsigned,unsigned>> command_offsets;
218 command_offsets.emplace_back(0, command.length());
219 std::list<prelim_dep> depends;
221 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
222 init_service_defaults(p);
223 p.set_smooth_recovery(true);
226 sset.process_queues();
228 base_process_service_test::exec_succeeded(&p);
229 sset.process_queues();
231 pid_t first_instance = bp_sys::last_forked_pid;
233 assert(p.get_state() == service_state_t::STARTED);
235 base_process_service_test::handle_exit(&p, 0);
236 sset.process_queues();
238 // since time hasn't been changed, we expect that the process has not yet been re-launched:
239 assert(first_instance == bp_sys::last_forked_pid);
240 assert(p.get_state() == service_state_t::STARTED);
243 sset.process_queues();
245 // Now a new process should've been launched:
246 assert(first_instance + 1 == bp_sys::last_forked_pid);
247 assert(p.get_state() == service_state_t::STARTED);
250 // Smooth recovery without restart delay
251 void test_proc_smooth_recovery2()
257 string command = "test-command";
258 list<pair<unsigned,unsigned>> command_offsets;
259 command_offsets.emplace_back(0, command.length());
260 std::list<prelim_dep> depends;
262 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
263 init_service_defaults(p);
264 p.set_smooth_recovery(true);
265 p.set_restart_delay(time_val(0, 0));
268 sset.process_queues();
270 base_process_service_test::exec_succeeded(&p);
271 sset.process_queues();
273 pid_t first_instance = bp_sys::last_forked_pid;
275 assert(p.get_state() == service_state_t::STARTED);
277 base_process_service_test::handle_exit(&p, 0);
278 sset.process_queues();
280 // no restart delay, process should restart immediately:
281 assert(first_instance + 1 == bp_sys::last_forked_pid);
282 assert(p.get_state() == service_state_t::STARTED);
285 #define RUN_TEST(name, spacing) \
286 std::cout << #name "..." spacing; \
288 std::cout << "PASSED" << std::endl;
290 int main(int argc, char **argv)
292 RUN_TEST(test_proc_service_start, " ");
293 RUN_TEST(test_proc_unexpected_term, " ");
294 RUN_TEST(test_term_via_stop, " ");
295 RUN_TEST(test_proc_start_timeout, " ");
296 RUN_TEST(test_proc_stop_timeout, " ");
297 RUN_TEST(test_proc_smooth_recovery1, "");
298 RUN_TEST(test_proc_smooth_recovery2, "");