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 extern eventloop_t event_loop;
17 // Friend interface to access base_process_service private/protected members.
18 class base_process_service_test
21 static void exec_succeeded(base_process_service *bsp)
23 bsp->waiting_for_execstat = false;
24 bsp->exec_succeeded();
27 static void handle_exit(base_process_service *bsp, int exit_status)
30 bsp->handle_exit_status(exit_status);
36 extern int last_sig_sent;
37 extern pid_t last_forked_pid;
40 static void init_service_defaults(base_process_service &ps)
42 ps.set_restart_interval(time_val(10,0), 3);
43 ps.set_restart_delay(time_val(0, 200000000)); // 200 milliseconds
44 ps.set_stop_timeout(time_val(10,0));
45 ps.set_start_interruptible(false);
48 // Regular service start
49 void test_proc_service_start()
55 string command = "test-command";
56 list<pair<unsigned,unsigned>> command_offsets;
57 command_offsets.emplace_back(0, command.length());
58 std::list<prelim_dep> depends;
60 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
61 init_service_defaults(p);
65 sset.process_queues();
67 assert(p.get_state() == service_state_t::STARTING);
69 base_process_service_test::exec_succeeded(&p);
70 sset.process_queues();
72 assert(p.get_state() == service_state_t::STARTED);
73 assert(event_loop.active_timers.size() == 0);
75 sset.remove_service(&p);
78 // Unexpected termination
79 void test_proc_unexpected_term()
85 string command = "test-command";
86 list<pair<unsigned,unsigned>> command_offsets;
87 command_offsets.emplace_back(0, command.length());
88 std::list<prelim_dep> depends;
90 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
91 init_service_defaults(p);
95 sset.process_queues();
97 base_process_service_test::exec_succeeded(&p);
98 sset.process_queues();
100 assert(p.get_state() == service_state_t::STARTED);
102 base_process_service_test::handle_exit(&p, 0);
103 sset.process_queues();
105 assert(p.get_state() == service_state_t::STOPPED);
106 assert(event_loop.active_timers.size() == 0);
108 sset.remove_service(&p);
111 // Termination via stop request
112 void test_term_via_stop()
118 string command = "test-command";
119 list<pair<unsigned,unsigned>> command_offsets;
120 command_offsets.emplace_back(0, command.length());
121 std::list<prelim_dep> depends;
123 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
124 init_service_defaults(p);
125 sset.add_service(&p);
128 sset.process_queues();
130 base_process_service_test::exec_succeeded(&p);
131 sset.process_queues();
133 assert(p.get_state() == service_state_t::STARTED);
134 assert(event_loop.active_timers.size() == 0);
137 sset.process_queues();
139 assert(p.get_state() == service_state_t::STOPPING);
140 assert(event_loop.active_timers.size() == 1);
142 base_process_service_test::handle_exit(&p, 0);
143 sset.process_queues();
145 assert(p.get_state() == service_state_t::STOPPED);
146 assert(event_loop.active_timers.size() == 0);
148 sset.remove_service(&p);
151 // Time-out during start
152 void test_proc_start_timeout()
158 string command = "test-command";
159 list<pair<unsigned,unsigned>> command_offsets;
160 command_offsets.emplace_back(0, command.length());
161 std::list<prelim_dep> depends;
163 process_service p {&sset, "testproc", std::move(command), command_offsets, depends};
164 init_service_defaults(p);
165 sset.add_service(&p);
168 sset.process_queues();
170 assert(p.get_state() == service_state_t::STARTING);
173 sset.process_queues();
175 assert(p.get_state() == service_state_t::STOPPING);
177 base_process_service_test::handle_exit(&p, 0);
178 sset.process_queues();
180 assert(p.get_state() == service_state_t::STOPPED);
181 assert(event_loop.active_timers.size() == 0);
183 sset.remove_service(&p);
186 // Test that a timeout doesn't stop a "waits for" dependent to fail to start
187 void test_proc_start_timeout2()
193 string command = "test-command";
194 list<pair<unsigned,unsigned>> command_offsets;
195 command_offsets.emplace_back(0, command.length());
196 std::list<prelim_dep> depends;
198 process_service p {&sset, "testproc", std::move(command), command_offsets, depends};
199 init_service_defaults(p);
200 sset.add_service(&p);
202 service_record ts {&sset, "test-service-1", service_type_t::INTERNAL, {{&p, dependency_type::WAITS_FOR}} };
205 sset.process_queues();
207 assert(p.get_state() == service_state_t::STARTING);
208 assert(ts.get_state() == service_state_t::STARTING);
211 sset.process_queues();
213 assert(p.get_state() == service_state_t::STOPPING);
215 base_process_service_test::handle_exit(&p, 0);
216 sset.process_queues();
218 assert(p.get_state() == service_state_t::STOPPED);
219 assert(ts.get_state() == service_state_t::STARTED);
220 assert(event_loop.active_timers.size() == 0);
222 sset.remove_service(&p);
226 void test_proc_stop_timeout()
232 string command = "test-command";
233 list<pair<unsigned,unsigned>> command_offsets;
234 command_offsets.emplace_back(0, command.length());
235 std::list<prelim_dep> depends;
237 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
238 init_service_defaults(p);
239 sset.add_service(&p);
242 sset.process_queues();
244 assert(p.get_state() == service_state_t::STARTING);
246 base_process_service_test::exec_succeeded(&p);
247 sset.process_queues();
249 assert(p.get_state() == service_state_t::STARTED);
252 sset.process_queues();
254 assert(p.get_state() == service_state_t::STOPPING);
255 assert(bp_sys::last_sig_sent == SIGTERM);
258 sset.process_queues();
260 // kill signal (SIGKILL) should have been sent; process not dead until it's dead, however
261 assert(p.get_state() == service_state_t::STOPPING);
262 assert(bp_sys::last_sig_sent == SIGKILL);
264 base_process_service_test::handle_exit(&p, 0);
265 sset.process_queues();
267 assert(p.get_state() == service_state_t::STOPPED);
269 // Note that timer is still active as we faked its expiry above
270 //assert(event_loop.active_timers.size() == 0);
271 event_loop.active_timers.clear();
272 sset.remove_service(&p);
276 void test_proc_smooth_recovery1()
282 string command = "test-command";
283 list<pair<unsigned,unsigned>> command_offsets;
284 command_offsets.emplace_back(0, command.length());
285 std::list<prelim_dep> depends;
287 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
288 init_service_defaults(p);
289 p.set_smooth_recovery(true);
290 sset.add_service(&p);
293 sset.process_queues();
295 base_process_service_test::exec_succeeded(&p);
296 sset.process_queues();
298 pid_t first_instance = bp_sys::last_forked_pid;
300 assert(p.get_state() == service_state_t::STARTED);
302 base_process_service_test::handle_exit(&p, 0);
303 sset.process_queues();
305 // since time hasn't been changed, we expect that the process has not yet been re-launched:
306 assert(first_instance == bp_sys::last_forked_pid);
307 assert(p.get_state() == service_state_t::STARTED);
310 sset.process_queues();
312 // Now a new process should've been launched:
313 assert(first_instance + 1 == bp_sys::last_forked_pid);
314 assert(p.get_state() == service_state_t::STARTED);
315 event_loop.active_timers.clear();
317 sset.remove_service(&p);
320 // Smooth recovery without restart delay
321 void test_proc_smooth_recovery2()
327 string command = "test-command";
328 list<pair<unsigned,unsigned>> command_offsets;
329 command_offsets.emplace_back(0, command.length());
330 std::list<prelim_dep> depends;
332 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
333 init_service_defaults(p);
334 p.set_smooth_recovery(true);
335 p.set_restart_delay(time_val(0, 0));
336 sset.add_service(&p);
339 sset.process_queues();
341 base_process_service_test::exec_succeeded(&p);
342 sset.process_queues();
344 pid_t first_instance = bp_sys::last_forked_pid;
346 assert(p.get_state() == service_state_t::STARTED);
347 assert(event_loop.active_timers.size() == 0);
349 base_process_service_test::handle_exit(&p, 0);
350 sset.process_queues();
352 // no restart delay, process should restart immediately:
353 assert(first_instance + 1 == bp_sys::last_forked_pid);
354 assert(p.get_state() == service_state_t::STARTED);
355 assert(event_loop.active_timers.size() == 0);
357 sset.remove_service(&p);
361 void test_scripted_stop_timeout()
367 string command = "test-command";
368 string stopcommand = "stop-command";
369 list<pair<unsigned,unsigned>> command_offsets;
370 command_offsets.emplace_back(0, command.length());
371 std::list<prelim_dep> depends;
373 scripted_service p = scripted_service(&sset, "testscripted", std::move(command), command_offsets, depends);
374 init_service_defaults(p);
375 p.set_stop_command(stopcommand, command_offsets);
376 sset.add_service(&p);
379 sset.process_queues();
381 assert(p.get_state() == service_state_t::STARTING);
383 base_process_service_test::exec_succeeded(&p);
384 sset.process_queues();
385 base_process_service_test::handle_exit(&p, 0);
386 sset.process_queues();
388 assert(p.get_state() == service_state_t::STARTED);
391 sset.process_queues();
393 assert(p.get_state() == service_state_t::STOPPING);
395 base_process_service_test::exec_succeeded(&p);
396 sset.process_queues();
398 // should still be stopping:
399 assert(p.get_state() == service_state_t::STOPPING);
402 sset.process_queues();
404 // kill signal (SIGKILL) should have been sent; process not dead until it's dead, however
405 assert(p.get_state() == service_state_t::STOPPING);
406 assert(bp_sys::last_sig_sent == SIGKILL);
408 base_process_service_test::handle_exit(&p, SIGKILL);
409 sset.process_queues();
411 assert(p.get_state() == service_state_t::STOPPED);
413 event_loop.active_timers.clear();
414 sset.remove_service(&p);
418 #define RUN_TEST(name, spacing) \
419 std::cout << #name "..." spacing; \
421 std::cout << "PASSED" << std::endl;
423 int main(int argc, char **argv)
425 RUN_TEST(test_proc_service_start, " ");
426 RUN_TEST(test_proc_unexpected_term, " ");
427 RUN_TEST(test_term_via_stop, " ");
428 RUN_TEST(test_proc_start_timeout, " ");
429 RUN_TEST(test_proc_start_timeout2, " ");
430 RUN_TEST(test_proc_stop_timeout, " ");
431 RUN_TEST(test_proc_smooth_recovery1, "");
432 RUN_TEST(test_proc_smooth_recovery2, "");
433 RUN_TEST(test_scripted_stop_timeout, "");