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);
64 sset.process_queues();
66 assert(p.get_state() == service_state_t::STARTING);
68 base_process_service_test::exec_succeeded(&p);
69 sset.process_queues();
71 assert(p.get_state() == service_state_t::STARTED);
72 assert(event_loop.active_timers.size() == 0);
75 // Unexpected termination
76 void test_proc_unexpected_term()
82 string command = "test-command";
83 list<pair<unsigned,unsigned>> command_offsets;
84 command_offsets.emplace_back(0, command.length());
85 std::list<prelim_dep> depends;
87 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
89 sset.process_queues();
91 base_process_service_test::exec_succeeded(&p);
92 sset.process_queues();
94 assert(p.get_state() == service_state_t::STARTED);
96 base_process_service_test::handle_exit(&p, 0);
97 sset.process_queues();
99 assert(p.get_state() == service_state_t::STOPPED);
100 assert(event_loop.active_timers.size() == 0);
103 // Termination via stop request
104 void test_term_via_stop()
110 string command = "test-command";
111 list<pair<unsigned,unsigned>> command_offsets;
112 command_offsets.emplace_back(0, command.length());
113 std::list<prelim_dep> depends;
115 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
116 init_service_defaults(p);
119 sset.process_queues();
121 base_process_service_test::exec_succeeded(&p);
122 sset.process_queues();
124 assert(p.get_state() == service_state_t::STARTED);
125 assert(event_loop.active_timers.size() == 0);
128 sset.process_queues();
130 assert(p.get_state() == service_state_t::STOPPING);
131 assert(event_loop.active_timers.size() == 1);
133 base_process_service_test::handle_exit(&p, 0);
134 sset.process_queues();
136 assert(p.get_state() == service_state_t::STOPPED);
137 assert(event_loop.active_timers.size() == 0);
140 // Time-out during start
141 void test_proc_start_timeout()
147 string command = "test-command";
148 list<pair<unsigned,unsigned>> command_offsets;
149 command_offsets.emplace_back(0, command.length());
150 std::list<prelim_dep> depends;
152 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
153 init_service_defaults(p);
156 sset.process_queues();
158 assert(p.get_state() == service_state_t::STARTING);
161 sset.process_queues();
163 assert(p.get_state() == service_state_t::STOPPING);
165 base_process_service_test::handle_exit(&p, 0);
166 sset.process_queues();
168 assert(p.get_state() == service_state_t::STOPPED);
169 assert(event_loop.active_timers.size() == 0);
173 void test_proc_stop_timeout()
179 string command = "test-command";
180 list<pair<unsigned,unsigned>> command_offsets;
181 command_offsets.emplace_back(0, command.length());
182 std::list<prelim_dep> depends;
184 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
185 init_service_defaults(p);
188 sset.process_queues();
190 assert(p.get_state() == service_state_t::STARTING);
192 base_process_service_test::exec_succeeded(&p);
193 sset.process_queues();
195 assert(p.get_state() == service_state_t::STARTED);
198 sset.process_queues();
200 assert(p.get_state() == service_state_t::STOPPING);
201 assert(bp_sys::last_sig_sent == SIGTERM);
204 sset.process_queues();
206 // kill signal (SIGKILL) should have been sent; process not dead until it's dead, however
207 assert(p.get_state() == service_state_t::STOPPING);
208 assert(bp_sys::last_sig_sent == SIGKILL);
210 base_process_service_test::handle_exit(&p, 0);
211 sset.process_queues();
213 assert(p.get_state() == service_state_t::STOPPED);
214 // Note that timer is still active as we faked its expiry above
215 //assert(event_loop.active_timers.size() == 0);
216 event_loop.active_timers.clear();
220 void test_proc_smooth_recovery1()
226 string command = "test-command";
227 list<pair<unsigned,unsigned>> command_offsets;
228 command_offsets.emplace_back(0, command.length());
229 std::list<prelim_dep> depends;
231 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
232 init_service_defaults(p);
233 p.set_smooth_recovery(true);
236 sset.process_queues();
238 base_process_service_test::exec_succeeded(&p);
239 sset.process_queues();
241 pid_t first_instance = bp_sys::last_forked_pid;
243 assert(p.get_state() == service_state_t::STARTED);
245 base_process_service_test::handle_exit(&p, 0);
246 sset.process_queues();
248 // since time hasn't been changed, we expect that the process has not yet been re-launched:
249 assert(first_instance == bp_sys::last_forked_pid);
250 assert(p.get_state() == service_state_t::STARTED);
253 sset.process_queues();
255 // Now a new process should've been launched:
256 assert(first_instance + 1 == bp_sys::last_forked_pid);
257 assert(p.get_state() == service_state_t::STARTED);
258 event_loop.active_timers.clear();
261 // Smooth recovery without restart delay
262 void test_proc_smooth_recovery2()
268 string command = "test-command";
269 list<pair<unsigned,unsigned>> command_offsets;
270 command_offsets.emplace_back(0, command.length());
271 std::list<prelim_dep> depends;
273 process_service p = process_service(&sset, "testproc", std::move(command), command_offsets, depends);
274 init_service_defaults(p);
275 p.set_smooth_recovery(true);
276 p.set_restart_delay(time_val(0, 0));
279 sset.process_queues();
281 base_process_service_test::exec_succeeded(&p);
282 sset.process_queues();
284 pid_t first_instance = bp_sys::last_forked_pid;
286 assert(p.get_state() == service_state_t::STARTED);
287 assert(event_loop.active_timers.size() == 0);
289 base_process_service_test::handle_exit(&p, 0);
290 sset.process_queues();
292 // no restart delay, process should restart immediately:
293 assert(first_instance + 1 == bp_sys::last_forked_pid);
294 assert(p.get_state() == service_state_t::STARTED);
295 assert(event_loop.active_timers.size() == 0);
299 void test_scripted_stop_timeout()
305 string command = "test-command";
306 string stopcommand = "stop-command";
307 list<pair<unsigned,unsigned>> command_offsets;
308 command_offsets.emplace_back(0, command.length());
309 std::list<prelim_dep> depends;
311 scripted_service p = scripted_service(&sset, "testscripted", std::move(command), command_offsets, depends);
312 init_service_defaults(p);
313 p.set_stop_command(stopcommand, command_offsets);
316 sset.process_queues();
318 assert(p.get_state() == service_state_t::STARTING);
320 base_process_service_test::exec_succeeded(&p);
321 sset.process_queues();
322 base_process_service_test::handle_exit(&p, 0);
323 sset.process_queues();
325 assert(p.get_state() == service_state_t::STARTED);
328 sset.process_queues();
330 assert(p.get_state() == service_state_t::STOPPING);
332 base_process_service_test::exec_succeeded(&p);
333 sset.process_queues();
335 // should still be stopping:
336 assert(p.get_state() == service_state_t::STOPPING);
339 sset.process_queues();
341 // kill signal (SIGKILL) should have been sent; process not dead until it's dead, however
342 assert(p.get_state() == service_state_t::STOPPING);
343 assert(bp_sys::last_sig_sent == SIGKILL);
345 base_process_service_test::handle_exit(&p, SIGKILL);
346 sset.process_queues();
348 assert(p.get_state() == service_state_t::STOPPED);
349 event_loop.active_timers.clear();
353 #define RUN_TEST(name, spacing) \
354 std::cout << #name "..." spacing; \
356 std::cout << "PASSED" << std::endl;
358 int main(int argc, char **argv)
360 RUN_TEST(test_proc_service_start, " ");
361 RUN_TEST(test_proc_unexpected_term, " ");
362 RUN_TEST(test_term_via_stop, " ");
363 RUN_TEST(test_proc_start_timeout, " ");
364 RUN_TEST(test_proc_stop_timeout, " ");
365 RUN_TEST(test_proc_smooth_recovery1, "");
366 RUN_TEST(test_proc_smooth_recovery2, "");
367 RUN_TEST(test_scripted_stop_timeout, "");