Re-work restart function.
[oweals/dinit.git] / src / tests / tests.cc
1 #include <cassert>
2 #include <iostream>
3
4 #include "service.h"
5 #include "test_service.h"
6
7 constexpr static auto REG = dependency_type::REGULAR;
8 constexpr static auto WAITS = dependency_type::WAITS_FOR;
9 constexpr static auto MS = dependency_type::MILESTONE;
10
11 class test_listener : public service_listener
12 {
13     public:
14     bool got_started = false;
15     bool got_stopped = false;
16     bool start_cancelled = false;
17     bool stop_cancelled = false;
18
19     void service_event(service_record * service, service_event_t event) noexcept override
20     {
21         switch (event) {
22         case service_event_t::STARTED:
23             got_started = true;
24             break;
25         case service_event_t::STOPPED:
26             got_stopped = true;
27             break;
28         case service_event_t::STARTCANCELLED:
29             start_cancelled = true;
30             break;
31         case service_event_t::STOPCANCELLED:
32             stop_cancelled = true;
33             break;
34         case service_event_t::FAILEDSTART:
35             break;
36         }
37     }
38 };
39
40 // Test 1: starting a service starts dependencies; stopping the service releases and
41 // stops dependencies.
42 void test1()
43 {
44     service_set sset;
45
46     service_record *s1 = new service_record(&sset, "test-service-1", service_type_t::INTERNAL, {});
47     service_record *s2 = new service_record(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, REG}});
48     service_record *s3 = new service_record(&sset, "test-service-3", service_type_t::INTERNAL, {{s2, REG}});
49     sset.add_service(s1);
50     sset.add_service(s2);
51     sset.add_service(s3);
52
53     assert(sset.find_service("test-service-1") == s1);
54     assert(sset.find_service("test-service-2") == s2);
55     assert(sset.find_service("test-service-3") == s3);
56
57     // s3 depends on s2, which depends on s1. So starting s3 should start all three services:
58     sset.start_service(s3);
59
60     assert(s1->get_state() == service_state_t::STARTED);
61     assert(s2->get_state() == service_state_t::STARTED);
62     assert(s3->get_state() == service_state_t::STARTED);
63
64     // stopping s3 should release the other two services:
65     sset.stop_service(s3);
66
67     assert(s3->get_state() == service_state_t::STOPPED);
68     assert(s2->get_state() == service_state_t::STOPPED);
69     assert(s1->get_state() == service_state_t::STOPPED);
70 }
71
72 // Test 2: Multiple dependents will hold a dependency active if one of the dependents is
73 // stopped/released.
74 void test2()
75 {
76     service_set sset;
77
78     service_record *s1 = new service_record(&sset, "test-service-1", service_type_t::INTERNAL, {});
79     service_record *s2 = new service_record(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, REG}});
80     service_record *s3 = new service_record(&sset, "test-service-3", service_type_t::INTERNAL, {{s2, REG}});
81     service_record *s4 = new service_record(&sset, "test-service-4", service_type_t::INTERNAL, {{s2, REG}});
82     sset.add_service(s1);
83     sset.add_service(s2);
84     sset.add_service(s3);
85     sset.add_service(s4);
86
87     // s3 depends on s2, which depends on s1. Similarly with s4. After starting both, all services
88     // should be started:
89     sset.start_service(s3);
90     sset.start_service(s4);
91
92     assert(s1->get_state() == service_state_t::STARTED);
93     assert(s2->get_state() == service_state_t::STARTED);
94     assert(s3->get_state() == service_state_t::STARTED);
95     assert(s4->get_state() == service_state_t::STARTED);
96
97     // after stopping s3, s4 should hold the other two services:
98     sset.stop_service(s3);
99
100     assert(s4->get_state() == service_state_t::STARTED);
101     assert(s3->get_state() == service_state_t::STOPPED);
102     assert(s2->get_state() == service_state_t::STARTED);
103     assert(s1->get_state() == service_state_t::STARTED);
104
105     // Now if we stop s4, s2 and s1 should also be released:
106     sset.stop_service(s4);
107
108     assert(s4->get_state() == service_state_t::STOPPED);
109     assert(s3->get_state() == service_state_t::STOPPED);
110     assert(s2->get_state() == service_state_t::STOPPED);
111     assert(s1->get_state() == service_state_t::STOPPED);
112 }
113
114 // Test 3: stopping a dependency causes its dependents to stop.
115 void test3()
116 {
117     service_set sset;
118
119     service_record *s1 = new service_record(&sset, "test-service-1", service_type_t::INTERNAL, {});
120     service_record *s2 = new service_record(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, REG}});
121     service_record *s3 = new service_record(&sset, "test-service-3", service_type_t::INTERNAL, {{s2, REG}});
122     sset.add_service(s1);
123     sset.add_service(s2);
124     sset.add_service(s3);
125
126     assert(sset.find_service("test-service-1") == s1);
127     assert(sset.find_service("test-service-2") == s2);
128     assert(sset.find_service("test-service-3") == s3);
129
130     // Start all three services:
131     sset.start_service(s3);
132
133     // Now stop s1, which should also force s2 and s3 to stop:
134     sset.stop_service(s1);
135
136     assert(s3->get_state() == service_state_t::STOPPED);
137     assert(s2->get_state() == service_state_t::STOPPED);
138     assert(s1->get_state() == service_state_t::STOPPED);
139 }
140
141 // Test 4: an explicitly activated service with automatic restart will restart if it
142 // stops due to a dependency stopping, therefore also causing the dependency to restart.
143 void test4()
144 {
145     service_set sset;
146
147     service_record *s1 = new service_record(&sset, "test-service-1", service_type_t::INTERNAL, {});
148     service_record *s2 = new service_record(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, REG}});
149     service_record *s3 = new service_record(&sset, "test-service-3", service_type_t::INTERNAL, {{s2, REG}});
150     s2->set_auto_restart(true);
151     sset.add_service(s1);
152     sset.add_service(s2);
153     sset.add_service(s3);
154
155     assert(sset.find_service("test-service-1") == s1);
156     assert(sset.find_service("test-service-2") == s2);
157     assert(sset.find_service("test-service-3") == s3);
158
159     // Start all three services:
160     sset.start_service(s3);
161
162     // Also explicitly activate s2:
163     sset.start_service(s2);
164
165     // Now stop s1, which should also force s2 and s3 to stop.
166     // s2 (and therefore s1) should restart:
167     sset.stop_service(s1);
168
169     assert(s3->get_state() == service_state_t::STOPPED);
170     assert(s2->get_state() == service_state_t::STARTED);
171     assert(s1->get_state() == service_state_t::STARTED);
172 }
173
174 // Test 5: test that services which do not start immediately correctly chain start of
175 // dependent services.
176 void test5()
177 {
178     service_set sset;
179
180     test_service *s1 = new test_service(&sset, "test-service-1", service_type_t::INTERNAL, {});
181     test_service *s2 = new test_service(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, REG}});
182     test_service *s3 = new test_service(&sset, "test-service-3", service_type_t::INTERNAL, {{s2, REG}});
183
184     sset.add_service(s1);
185     sset.add_service(s2);
186     sset.add_service(s3);
187
188     sset.start_service(s3);
189
190     // All three should transition to STARTING state:
191     assert(s3->get_state() == service_state_t::STARTING);
192     assert(s2->get_state() == service_state_t::STARTING);
193     assert(s1->get_state() == service_state_t::STARTING);
194
195     s1->started();
196     sset.process_queues();
197     assert(s3->get_state() == service_state_t::STARTING);
198     assert(s2->get_state() == service_state_t::STARTING);
199     assert(s1->get_state() == service_state_t::STARTED);
200
201     s2->started();
202     sset.process_queues();
203     assert(s3->get_state() == service_state_t::STARTING);
204     assert(s2->get_state() == service_state_t::STARTED);
205     assert(s1->get_state() == service_state_t::STARTED);
206
207     s3->started();
208     sset.process_queues();
209     assert(s3->get_state() == service_state_t::STARTED);
210     assert(s2->get_state() == service_state_t::STARTED);
211     assert(s1->get_state() == service_state_t::STARTED);
212 }
213
214 // Test that service pinned in start state is not stopped when its dependency stops.
215 void test_pin1()
216 {
217     service_set sset;
218
219     service_record *s1 = new service_record(&sset, "test-service-1", service_type_t::INTERNAL, {});
220     service_record *s2 = new service_record(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, REG}});
221     service_record *s3 = new service_record(&sset, "test-service-3", service_type_t::INTERNAL, {{s2, REG}});
222     s2->set_auto_restart(true);
223     sset.add_service(s1);
224     sset.add_service(s2);
225     sset.add_service(s3);
226
227     // Pin s3:
228     s3->pin_start();
229
230     // Start all three services:
231     sset.start_service(s3);
232
233     assert(s3->get_state() == service_state_t::STARTED);
234     assert(s2->get_state() == service_state_t::STARTED);
235     assert(s1->get_state() == service_state_t::STARTED);
236
237     // Stop s2:
238     s2->forced_stop();
239     s2->stop(true);
240     sset.process_queues();
241
242     // s3 should remain started due to pin:
243     assert(s3->get_state() == service_state_t::STARTED);
244     assert(s2->get_state() == service_state_t::STOPPING);
245     assert(s1->get_state() == service_state_t::STARTED);
246
247     // If we now unpin, s3 should stop:
248     s3->unpin();
249     sset.process_queues();
250     assert(s3->get_state() == service_state_t::STOPPED);
251     assert(s2->get_state() == service_state_t::STOPPED);
252     assert(s1->get_state() == service_state_t::STOPPED);
253 }
254
255 // Test that issuing a stop to a pinned-started service does not stop the service or its dependencies.
256 void test_pin2()
257 {
258     service_set sset;
259
260     service_record *s1 = new service_record(&sset, "test-service-1", service_type_t::INTERNAL, {});
261     service_record *s2 = new service_record(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, REG}});
262     service_record *s3 = new service_record(&sset, "test-service-3", service_type_t::INTERNAL, {{s2, REG}});
263     s2->set_auto_restart(true);
264     sset.add_service(s1);
265     sset.add_service(s2);
266     sset.add_service(s3);
267
268     // Pin s3:
269     s3->pin_start();
270
271     // Start all three services:
272     sset.start_service(s3);
273
274     assert(s3->get_state() == service_state_t::STARTED);
275     assert(s2->get_state() == service_state_t::STARTED);
276     assert(s1->get_state() == service_state_t::STARTED);
277
278     // Issue stop to s3:
279     s3->stop(true);
280     sset.process_queues();
281
282     // s3 should remain started due to pin, s1 and s2 not released:
283     assert(s3->get_state() == service_state_t::STARTED);
284     assert(s2->get_state() == service_state_t::STARTED);
285     assert(s1->get_state() == service_state_t::STARTED);
286 }
287
288 // Test that a STOPPING dependency of a pinned service stops when pin is released, even if pinned
289 // service is activated:
290 void test_pin3()
291 {
292     service_set sset;
293
294     service_record *s1 = new service_record(&sset, "test-service-1", service_type_t::INTERNAL, {});
295     service_record *s2 = new service_record(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, REG}});
296     service_record *s3 = new service_record(&sset, "test-service-3", service_type_t::INTERNAL, {{s2, REG}});
297     s2->set_auto_restart(true);
298     sset.add_service(s1);
299     sset.add_service(s2);
300     sset.add_service(s3);
301
302     // Pin s3:
303     s3->pin_start();
304
305     // Start all three services:
306     sset.start_service(s3);
307
308     assert(s3->get_state() == service_state_t::STARTED);
309     assert(s2->get_state() == service_state_t::STARTED);
310     assert(s1->get_state() == service_state_t::STARTED);
311
312     // Issue force stop to s2:
313     s2->stop(true);
314     s2->forced_stop();
315     sset.process_queues();
316
317     // s3 should remain started due to pin, but s1 and s2 are released and go STOPPING:
318     assert(s3->get_state() == service_state_t::STARTED);
319     assert(s2->get_state() == service_state_t::STOPPING);
320     assert(s1->get_state() == service_state_t::STARTED);
321
322     // If we now issue start, s2 still needs to stop (due to force stop):
323     s3->start(true);
324     sset.process_queues();
325
326     assert(s3->get_state() == service_state_t::STARTED);
327     assert(s2->get_state() == service_state_t::STOPPING);
328     assert(s1->get_state() == service_state_t::STARTED);
329
330     // When we unpin, s2 should STOP; s3 must stop as a result; s1 is released and so also stops:
331     s3->unpin();
332
333     assert(s3->get_state() == service_state_t::STOPPED);
334     assert(s2->get_state() == service_state_t::STOPPED);
335     assert(s1->get_state() == service_state_t::STOPPED);
336 }
337
338 // Test that service pinned started is released when stop issued and stops when unpinned
339 void test_pin4()
340 {
341     service_set sset;
342
343     service_record *s1 = new service_record(&sset, "test-service-1", service_type_t::INTERNAL, {});
344     sset.add_service(s1);
345
346     // Pin s1:
347     s1->pin_start();
348
349     // Start the service:
350     sset.start_service(s1);
351
352     assert(s1->get_state() == service_state_t::STARTED);
353
354     // Issue forced stop:
355     s1->stop(true);
356     s1->forced_stop();
357     sset.process_queues();
358
359     // s3 should remain started:
360     assert(s1->get_state() == service_state_t::STARTED);
361
362     // If we now unpin, s1 should stop:
363     s1->unpin();
364     sset.process_queues();
365     assert(s1->get_state() == service_state_t::STOPPED);
366 }
367
368 // Test 7: stopping a soft dependency doesn't cause the dependent to stop.
369 void test7()
370 {
371     service_set sset;
372
373     service_record *s1 = new service_record(&sset, "test-service-1", service_type_t::INTERNAL, {});
374     service_record *s2 = new service_record(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, REG}});
375     service_record *s3 = new service_record(&sset, "test-service-3", service_type_t::INTERNAL, {{s2, WAITS}});
376     sset.add_service(s1);
377     sset.add_service(s2);
378     sset.add_service(s3);
379
380     assert(sset.find_service("test-service-1") == s1);
381     assert(sset.find_service("test-service-2") == s2);
382     assert(sset.find_service("test-service-3") == s3);
383
384     // Start all three services:
385     sset.start_service(s3);
386
387     // Now stop s1, which should also force s2 but not s3 to stop:
388     sset.stop_service(s1);
389
390     assert(s3->get_state() == service_state_t::STARTED);
391     assert(s2->get_state() == service_state_t::STOPPED);
392     assert(s1->get_state() == service_state_t::STOPPED);
393 }
394
395 // Test 8: stopping a milestone dependency doesn't cause the dependent to stop
396 void test8()
397 {
398     service_set sset;
399
400     service_record *s1 = new service_record(&sset, "test-service-1", service_type_t::INTERNAL, {});
401     service_record *s2 = new service_record(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, MS}});
402     sset.add_service(s1);
403     sset.add_service(s2);
404
405     assert(sset.find_service("test-service-1") == s1);
406     assert(sset.find_service("test-service-2") == s2);
407
408     // Start the services:
409     sset.start_service(s2);
410
411     assert(s2->get_state() == service_state_t::STARTED);
412     assert(s1->get_state() == service_state_t::STARTED);
413
414     // Now stop s1, which should not stop s2:
415     sset.stop_service(s1);
416
417     assert(s2->get_state() == service_state_t::STARTED);
418     assert(s1->get_state() == service_state_t::STOPPED);
419 }
420
421 // Test 9: a failing milestone dependency causes the dependent to fail
422 void test9()
423 {
424     service_set sset;
425
426     test_service *s1 = new test_service(&sset, "test-service-1", service_type_t::INTERNAL, {});
427     test_service *s2 = new test_service(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, MS}});
428     sset.add_service(s1);
429     sset.add_service(s2);
430
431     assert(sset.find_service("test-service-1") == s1);
432     assert(sset.find_service("test-service-2") == s2);
433
434     // Start the services, but fail s1:
435     sset.start_service(s2);
436
437     assert(s1->get_state() == service_state_t::STARTING);
438     s1->failed_to_start();
439     sset.process_queues();
440
441     assert(s1->get_state() == service_state_t::STOPPED);
442     assert(s2->get_state() == service_state_t::STOPPED);
443 }
444
445 // Test 10: if start cancelled, remove from console queue
446 void test10()
447 {
448     service_set sset;
449
450     // Create s1 and s2. s2 depends on s1, and starts on the console.
451     test_service *s1 = new test_service(&sset, "test-service-1", service_type_t::INTERNAL, {});
452     test_service *s2 = new test_service(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, REG}});
453     service_flags_t s2_flags;
454     s2_flags.starts_on_console = true;
455     s2->set_flags(s2_flags);
456     sset.add_service(s1);
457     sset.add_service(s2);
458
459     // Create s3, which starts and runs on console:
460     test_service *s3 = new test_service(&sset, "test-service-3", service_type_t::INTERNAL, {});
461     service_flags_t s3_flags;
462     s3_flags.starts_on_console = true;
463     s3_flags.runs_on_console = true;
464     sset.add_service(s3);
465
466     assert(sset.find_service("test-service-1") == s1);
467     assert(sset.find_service("test-service-2") == s2);
468     assert(sset.find_service("test-service-3") == s3);
469
470     // Start the s3 service, so it gets console:
471     sset.start_service(s3);
472     sset.process_queues();
473     s3->started();
474     sset.process_queues();
475
476     assert(! sset.is_queued_for_console(s3)); // should not be queued, because already has acquired
477     assert(sset.is_console_queue_empty());
478
479     // Start s2, which starts s1 as a dependency:
480
481     sset.start_service(s2);
482     sset.process_queues();
483
484     assert(s1->get_state() == service_state_t::STARTING);
485     assert(s2->get_state() == service_state_t::STARTING);
486
487     s1->started();
488     sset.process_queues();
489
490     // s2 should now be waiting for console:
491     assert(s1->get_state() == service_state_t::STARTED);
492     assert(s2->get_state() == service_state_t::STARTING);
493     assert(sset.is_queued_for_console(s2));
494
495     // stop s1, should stop s2, s2 should unqueue:
496     s1->stop();
497     sset.process_queues();
498
499     assert(s1->get_state() == service_state_t::STOPPED);
500     assert(s2->get_state() == service_state_t::STOPPED);
501     assert(! sset.is_queued_for_console(s2));
502 }
503
504 // Test 11: if a milestone dependency doesn't start, dependent doesn't start.
505 void test11()
506 {
507     service_set sset;
508
509     test_service *s1 = new test_service(&sset, "test-service-1", service_type_t::INTERNAL, {});
510     service_record *s2 = new service_record(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, MS}});
511
512     sset.add_service(s1);
513     sset.add_service(s2);
514
515     assert(sset.find_service("test-service-1") == s1);
516     assert(sset.find_service("test-service-2") == s2);
517
518     // Request start of the s2 service:
519     sset.start_service(s2);
520     sset.process_queues();
521
522     assert(s1->get_state() == service_state_t::STARTING);
523     assert(s2->get_state() == service_state_t::STARTING);
524
525     s1->stop();
526     sset.process_queues();
527     s1->bring_down();
528     sset.process_queues();
529
530     assert(s1->get_state() == service_state_t::STOPPED);
531     assert(s2->get_state() == service_state_t::STOPPED);
532 }
533
534 // Test that active service count reaches 0 when stopping a service with different types of dependency
535 void test12()
536 {
537     service_set sset;
538
539     service_record *s4 = new service_record(&sset, "test-service-4", service_type_t::INTERNAL, {});
540     service_record *s3 = new service_record(&sset, "test-service-3", service_type_t::INTERNAL, {});
541     service_record *s2 = new service_record(&sset, "test-service-2", service_type_t::INTERNAL, {});
542
543     service_record *s1 = new service_record(&sset, "test-service-1", service_type_t::INTERNAL,
544             {{s2, WAITS}, {s3, REG}, {s4, MS}});
545
546     sset.add_service(s4);
547     sset.add_service(s3);
548     sset.add_service(s2);
549     sset.add_service(s1);
550
551     assert(sset.find_service("test-service-1") == s1);
552     assert(sset.find_service("test-service-2") == s2);
553     assert(sset.find_service("test-service-3") == s3);
554     assert(sset.find_service("test-service-4") == s4);
555
556     // Request start of the s2 service, should also start s1:
557     sset.start_service(s1);
558     sset.process_queues();
559
560     assert(s1->get_state() == service_state_t::STARTED);
561     assert(s2->get_state() == service_state_t::STARTED);
562     assert(s3->get_state() == service_state_t::STARTED);
563     assert(s4->get_state() == service_state_t::STARTED);
564
565     s1->stop();
566     sset.process_queues();
567
568     assert(s1->get_state() == service_state_t::STOPPED);
569     assert(s2->get_state() == service_state_t::STOPPED);
570     assert(s3->get_state() == service_state_t::STOPPED);
571     assert(s4->get_state() == service_state_t::STOPPED);
572
573     assert(sset.count_active_services() == 0);
574 }
575
576 // Tests for "restart" functionality.
577 void test13()
578 {
579     service_set sset;
580
581     test_service *s1 = new test_service(&sset, "test-service-1", service_type_t::INTERNAL, {});
582     test_service *s2 = new test_service(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, WAITS}});
583     test_service *s3 = new test_service(&sset, "test-service-3", service_type_t::INTERNAL, {{s2, REG}});
584
585     sset.add_service(s1);
586     sset.add_service(s2);
587     sset.add_service(s3);
588
589     // Start all services via s3
590     sset.start_service(s3);
591     s1->started();
592     sset.process_queues();
593     s2->started();
594     sset.process_queues();
595     s3->started();
596     sset.process_queues();
597
598     assert(s3->get_state() == service_state_t::STARTED);
599     assert(s2->get_state() == service_state_t::STARTED);
600     assert(s1->get_state() == service_state_t::STARTED);
601
602     test_listener tl;
603
604     s1->add_listener(&tl);
605
606     s1->restart();
607     s1->forced_stop();
608     sset.process_queues();
609
610     assert(s3->get_state() == service_state_t::STARTED);
611     assert(s2->get_state() == service_state_t::STARTED);
612     assert(s1->get_state() == service_state_t::STARTING);
613     assert(! tl.got_started);
614
615     s1->started();
616     sset.process_queues();
617
618     assert(s3->get_state() == service_state_t::STARTED);
619     assert(s2->get_state() == service_state_t::STARTED);
620     assert(s1->get_state() == service_state_t::STARTED);
621     assert(tl.got_started);
622 }
623
624 // Make sure a service only restarts once (i.e. restart flag doesn't get stuck)
625 void test14()
626 {
627     service_set sset;
628
629     test_service *s1 = new test_service(&sset, "test-service-1", service_type_t::INTERNAL, {});
630     test_service *s2 = new test_service(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, WAITS}});
631
632     sset.add_service(s1);
633     sset.add_service(s2);
634
635     // Start all services via s2
636     sset.start_service(s2);
637     s1->started();
638     sset.process_queues();
639     s2->started();
640     sset.process_queues();
641
642     assert(s2->get_state() == service_state_t::STARTED);
643     assert(s1->get_state() == service_state_t::STARTED);
644
645     s1->restart();
646     s1->forced_stop();
647     sset.process_queues();
648
649     assert(s2->get_state() == service_state_t::STARTED);
650     assert(s1->get_state() == service_state_t::STARTING);
651
652     s1->started();
653     sset.process_queues();
654
655     assert(s2->get_state() == service_state_t::STARTED);
656     assert(s1->get_state() == service_state_t::STARTED);
657
658     // Ok, we restarted s1. Now stop it:
659
660     s1->stop(true);
661     sset.process_queues();
662
663     assert(s2->get_state() == service_state_t::STARTED);
664     assert(s1->get_state() == service_state_t::STOPPED); // didn't restart
665 }
666
667 // Test that restart can be cancelled if dependents stop
668 void test15()
669 {
670     service_set sset;
671
672     test_service *s1 = new test_service(&sset, "test-service-1", service_type_t::INTERNAL, {});
673     test_service *s2 = new test_service(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, WAITS}});
674
675     sset.add_service(s1);
676     sset.add_service(s2);
677
678     // Start all services via s2
679     sset.start_service(s2);
680     s1->started();
681     sset.process_queues();
682     s2->started();
683     sset.process_queues();
684
685     assert(s2->get_state() == service_state_t::STARTED);
686     assert(s1->get_state() == service_state_t::STARTED);
687
688     test_listener tl;
689     s1->add_listener(&tl);
690
691     s1->auto_stop = false;
692
693     s1->restart();
694     s1->forced_stop();
695     sset.process_queues();
696
697     assert(s1->get_state() == service_state_t::STOPPING);
698
699     s2->stop();
700     sset.process_queues();
701     s1->stopped();
702     sset.process_queues();
703
704     assert(s2->get_state() == service_state_t::STOPPED);
705     assert(s1->get_state() == service_state_t::STOPPED);
706
707     assert(tl.start_cancelled);
708     assert(! tl.got_started);
709 }
710
711
712 #define RUN_TEST(name, spacing) \
713     std::cout << #name "..." spacing << std::flush; \
714     name(); \
715     std::cout << "PASSED" << std::endl;
716
717 int main(int argc, char **argv)
718 {
719     RUN_TEST(test1, "                     ");
720     RUN_TEST(test2, "                     ");
721     RUN_TEST(test3, "                     ");
722     RUN_TEST(test4, "                     ");
723     RUN_TEST(test5, "                     ");
724     RUN_TEST(test_pin1, "                 ");
725     RUN_TEST(test_pin2, "                 ");
726     RUN_TEST(test_pin3, "                 ");
727     RUN_TEST(test_pin4, "                 ");
728     RUN_TEST(test7, "                     ");
729     RUN_TEST(test8, "                     ");
730     RUN_TEST(test9, "                     ");
731     RUN_TEST(test10, "                    ");
732     RUN_TEST(test11, "                    ");
733     RUN_TEST(test12, "                    ");
734     RUN_TEST(test13, "                    ");
735     RUN_TEST(test14, "                    ");
736     RUN_TEST(test15, "                    ");
737 }