3
* test_jobs.c - test suite for util/jobs.c
5
* Copyright © 2007 Canonical Ltd.
6
* Author: Scott James Remnant <scott@ubuntu.com>.
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
#include <sys/types.h>
26
#include <sys/socket.h>
32
#include <nih/macros.h>
33
#include <nih/alloc.h>
36
#include <nih/logging.h>
37
#include <nih/error.h>
38
#include <nih/errors.h>
40
#include <upstart/enum.h>
41
#include <upstart/message.h>
43
#include <util/jobs.h>
46
int control_sock = -1;
47
int destination_pid = 0;
49
extern int upstart_disable_safeties;
53
test_start_action (void)
61
int ret, sock, status;
64
TEST_FUNCTION ("start_action");
65
program_name = "test";
67
nih_error_push_context ();
68
nih_error_pop_context ();
72
sock = upstart_open ();
73
destination_pid = getpid ();
75
setenv ("UPSTART_JOB", "oops", TRUE);
78
/* Check that the start command sends the start job message to
79
* the server, and then receives a single status reply and outputs it.
81
TEST_FEATURE ("with start command");
82
cmd.command = "start";
87
TEST_DIVERT_STDOUT (output) {
88
upstart_disable_safeties = TRUE;
90
control_sock = upstart_open ();
91
ret = start_action (&cmd, args);
96
/* Should receive UPSTART_JOB_START */
97
assert (msg = nih_io_message_recv (NULL, sock, &len));
99
TEST_EQ (msg->data->len, 20);
100
TEST_EQ_MEM (msg->data->buf, "upstart\n\0\0\0\01s\0\0\0\03foo", 20);
105
/* Send back the status */
106
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "foo",
107
JOB_START, JOB_RUNNING, 1000);
108
assert (nih_io_message_send (msg, sock) > 0);
111
msg = upstart_message_new (NULL, pid, UPSTART_JOB_LIST_END);
112
assert (nih_io_message_send (msg, sock) > 0);
115
/* Reap the child, check the output */
116
waitpid (pid, &status, 0);
119
TEST_TRUE (WIFEXITED (status));
120
TEST_EQ (WEXITSTATUS (status), 0);
122
TEST_FILE_EQ (output, "foo (start) running, process 1000\n");
123
TEST_FILE_END (output);
124
TEST_FILE_RESET (output);
127
/* Check that the stop command sends the stop job message to
128
* the server, and then receives a single status reply and outputs it.
130
TEST_FEATURE ("with stop command");
131
cmd.command = "stop";
136
TEST_DIVERT_STDOUT (output) {
137
upstart_disable_safeties = TRUE;
139
control_sock = upstart_open ();
140
ret = start_action (&cmd, args);
145
/* Should receive UPSTART_JOB_STOP */
146
assert (msg = nih_io_message_recv (NULL, sock, &len));
148
TEST_EQ (msg->data->len, 20);
149
TEST_EQ_MEM (msg->data->buf, "upstart\n\0\0\0\02s\0\0\0\03foo", 20);
154
/* Send back the status */
155
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "foo",
156
JOB_STOP, JOB_KILLED, 1000);
157
assert (nih_io_message_send (msg, sock) > 0);
160
msg = upstart_message_new (NULL, pid, UPSTART_JOB_LIST_END);
161
assert (nih_io_message_send (msg, sock) > 0);
164
/* Reap the child, check the output */
165
waitpid (pid, &status, 0);
168
TEST_TRUE (WIFEXITED (status));
169
TEST_EQ (WEXITSTATUS (status), 0);
171
TEST_FILE_EQ (output, "foo (stop) killed, process 1000\n");
172
TEST_FILE_END (output);
173
TEST_FILE_RESET (output);
176
/* Check that the status command sends the query job message to
177
* the server, and then receives a single status reply and outputs it.
179
TEST_FEATURE ("with status command");
180
cmd.command = "status";
185
TEST_DIVERT_STDOUT (output) {
186
upstart_disable_safeties = TRUE;
188
control_sock = upstart_open ();
189
ret = start_action (&cmd, args);
194
/* Should receive UPSTART_JOB_QUERY */
195
assert (msg = nih_io_message_recv (NULL, sock, &len));
197
TEST_EQ (msg->data->len, 20);
198
TEST_EQ_MEM (msg->data->buf, "upstart\n\0\0\0\03s\0\0\0\03foo", 20);
203
/* Send back the status */
204
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "foo",
205
JOB_STOP, JOB_WAITING, 0);
206
assert (nih_io_message_send (msg, sock) > 0);
209
msg = upstart_message_new (NULL, pid, UPSTART_JOB_LIST_END);
210
assert (nih_io_message_send (msg, sock) > 0);
213
/* Reap the child, check the output */
214
waitpid (pid, &status, 0);
217
TEST_TRUE (WIFEXITED (status));
218
TEST_EQ (WEXITSTATUS (status), 0);
220
TEST_FILE_EQ (output, "foo (stop) waiting\n");
221
TEST_FILE_END (output);
222
TEST_FILE_RESET (output);
225
/* Check that the command accepts multiple named jobs and sends
226
* and receives a message for each one.
228
TEST_FEATURE ("with status command");
229
cmd.command = "status";
235
TEST_DIVERT_STDOUT (output) {
236
upstart_disable_safeties = TRUE;
238
control_sock = upstart_open ();
239
ret = start_action (&cmd, args);
244
/* Should receive UPSTART_JOB_QUERY */
245
assert (msg = nih_io_message_recv (NULL, sock, &len));
247
TEST_EQ (msg->data->len, 20);
248
TEST_EQ_MEM (msg->data->buf, "upstart\n\0\0\0\03s\0\0\0\03foo", 20);
252
/* Send back the status */
253
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "foo",
254
JOB_STOP, JOB_PRE_STOP, 1000);
255
assert (nih_io_message_send (msg, sock) > 0);
258
msg = upstart_message_new (NULL, pid, UPSTART_JOB_LIST_END);
259
assert (nih_io_message_send (msg, sock) > 0);
262
/* Should receive another UPSTART_JOB_QUERY */
263
assert (msg = nih_io_message_recv (NULL, sock, &len));
265
TEST_EQ (msg->data->len, 20);
266
TEST_EQ_MEM (msg->data->buf, "upstart\n\0\0\0\03s\0\0\0\03bar", 20);
270
/* Send back the status */
271
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "bar",
272
JOB_START, JOB_SPAWNED, 2000);
273
assert (nih_io_message_send (msg, sock) > 0);
276
msg = upstart_message_new (NULL, pid, UPSTART_JOB_LIST_END);
277
assert (nih_io_message_send (msg, sock) > 0);
280
/* Reap the child, check the output */
281
waitpid (pid, &status, 0);
284
TEST_TRUE (WIFEXITED (status));
285
TEST_EQ (WEXITSTATUS (status), 0);
287
TEST_FILE_EQ (output, "foo (stop) pre-stop, process 1000\n");
288
TEST_FILE_EQ (output, "bar (start) spawned, process 2000\n");
289
TEST_FILE_END (output);
290
TEST_FILE_RESET (output);
293
/* Check that if the command returns multiple replies, they are all
296
TEST_FEATURE ("with multiple replies");
297
cmd.command = "status";
302
TEST_DIVERT_STDOUT (output) {
303
upstart_disable_safeties = TRUE;
305
control_sock = upstart_open ();
306
ret = start_action (&cmd, args);
311
/* Should receive UPSTART_JOB_QUERY */
312
assert (msg = nih_io_message_recv (NULL, sock, &len));
314
TEST_EQ (msg->data->len, 20);
315
TEST_EQ_MEM (msg->data->buf, "upstart\n\0\0\0\03s\0\0\0\03foo", 20);
319
/* Send back the status */
320
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "foo",
321
JOB_STOP, JOB_WAITING, 0);
322
assert (nih_io_message_send (msg, sock) > 0);
325
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "foo",
326
JOB_START, JOB_PRE_START, 1000);
327
assert (nih_io_message_send (msg, sock) > 0);
330
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "foo",
331
JOB_STOP, JOB_PRE_STOP, 2000);
332
assert (nih_io_message_send (msg, sock) > 0);
335
msg = upstart_message_new (NULL, pid, UPSTART_JOB_LIST_END);
336
assert (nih_io_message_send (msg, sock) > 0);
339
/* Reap the child, check the output */
340
waitpid (pid, &status, 0);
343
TEST_TRUE (WIFEXITED (status));
344
TEST_EQ (WEXITSTATUS (status), 0);
346
TEST_FILE_EQ (output, "foo (stop) waiting\n");
347
TEST_FILE_EQ (output, "foo (start) pre-start, process 1000\n");
348
TEST_FILE_EQ (output, "foo (stop) pre-stop, process 2000\n");
349
TEST_FILE_END (output);
350
TEST_FILE_RESET (output);
353
/* Check that the command can respond to an unknown job message
354
* and output it properly.
356
TEST_FEATURE ("with unknown job");
357
cmd.command = "start";
362
TEST_DIVERT_STDERR (output) {
363
upstart_disable_safeties = TRUE;
365
control_sock = upstart_open ();
366
ret = start_action (&cmd, args);
371
/* Should receive UPSTART_JOB_START */
372
assert (msg = nih_io_message_recv (NULL, sock, &len));
374
TEST_EQ (msg->data->len, 20);
375
TEST_EQ_MEM (msg->data->buf, "upstart\n\0\0\0\01s\0\0\0\03foo", 20);
379
/* Send back unknown job */
380
msg = upstart_message_new (NULL, pid, UPSTART_JOB_UNKNOWN, "foo");
381
assert (nih_io_message_send (msg, sock) > 0);
384
/* Reap the child, check the output */
385
waitpid (pid, &status, 0);
388
TEST_TRUE (WIFEXITED (status));
389
TEST_EQ (WEXITSTATUS (status), 0);
391
TEST_FILE_EQ (output, "test: unknown job: foo\n");
392
TEST_FILE_END (output);
393
TEST_FILE_RESET (output);
396
/* Check that calling start without any argument results in an error
397
* being sent to stderr.
399
TEST_FEATURE ("with missing argument");
400
unsetenv ("UPSTART_JOB");
401
cmd.command = "start";
403
TEST_DIVERT_STDERR (output) {
404
ret = start_action (&cmd, args);
410
TEST_FILE_EQ (output, "test: missing job name\n");
411
TEST_FILE_EQ (output, "Try `test --help' for more information.\n");
412
TEST_FILE_END (output);
413
TEST_FILE_RESET (output);
416
/* Check that it's ok to call start without any arguments if the
417
* UPSTART_JOB environment variable is set, as that variable can
420
TEST_FEATURE ("with UPSTART_JOB in environment");
421
setenv ("UPSTART_JOB", "galen", TRUE);
424
TEST_DIVERT_STDOUT (output) {
425
upstart_disable_safeties = TRUE;
427
control_sock = upstart_open ();
428
ret = start_action (&cmd, args);
433
/* Should receive UPSTART_JOB_START */
434
assert (msg = nih_io_message_recv (NULL, sock, &len));
436
TEST_EQ (msg->data->len, 22);
437
TEST_EQ_MEM (msg->data->buf, "upstart\n\0\0\0\01s\0\0\0\05galen", 22);
442
/* Send back the status */
443
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "galen",
444
JOB_START, JOB_RUNNING, 1000);
445
assert (nih_io_message_send (msg, sock) > 0);
448
msg = upstart_message_new (NULL, pid, UPSTART_JOB_LIST_END);
449
assert (nih_io_message_send (msg, sock) > 0);
452
/* Reap the child, check the output */
453
waitpid (pid, &status, 0);
456
TEST_TRUE (WIFEXITED (status));
457
TEST_EQ (WEXITSTATUS (status), 0);
459
TEST_FILE_EQ (output, "galen (start) running, process 1000\n");
460
TEST_FILE_END (output);
461
TEST_FILE_RESET (output);
470
test_list_action (void)
478
int ret, sock, status;
481
/* Check that the list command sends the list jobs message to
482
* the server, and then receives all replies and outputs each job
485
TEST_FUNCTION ("list_action");
486
program_name = "test";
488
nih_error_push_context ();
489
nih_error_pop_context ();
493
sock = upstart_open ();
494
destination_pid = getpid ();
496
cmd.command = "list";
501
TEST_DIVERT_STDOUT (output) {
502
upstart_disable_safeties = TRUE;
504
control_sock = upstart_open ();
505
ret = list_action (&cmd, args);
510
/* Should receive UPSTART_JOB_LIST */
511
assert (msg = nih_io_message_recv (NULL, sock, &len));
513
TEST_EQ (msg->data->len, 12);
514
TEST_EQ_MEM (msg->data->buf, "upstart\n\0\0\0\06", 12);
519
/* Send back a couple of jobs */
520
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "frodo",
521
JOB_START, JOB_RUNNING, 1000);
522
assert (nih_io_message_send (msg, sock) > 0);
525
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "bilbo",
526
JOB_STOP, JOB_KILLED, 2000);
527
assert (nih_io_message_send (msg, sock) > 0);
530
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "merry",
531
JOB_STOP, JOB_STOPPING, 3000);
532
assert (nih_io_message_send (msg, sock) > 0);
535
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "pippin",
536
JOB_STOP, JOB_WAITING, 0);
537
assert (nih_io_message_send (msg, sock) > 0);
540
msg = upstart_message_new (NULL, pid, UPSTART_JOB_LIST_END);
541
assert (nih_io_message_send (msg, sock) > 0);
544
/* Reap the child, check the output */
545
waitpid (pid, &status, 0);
548
TEST_TRUE (WIFEXITED (status));
549
TEST_EQ (WEXITSTATUS (status), 0);
551
TEST_FILE_EQ (output, "frodo (start) running, process 1000\n");
552
TEST_FILE_EQ (output, "bilbo (stop) killed, process 2000\n");
553
TEST_FILE_EQ (output, "merry (stop) stopping, process 3000\n");
554
TEST_FILE_EQ (output, "pippin (stop) waiting\n");
555
TEST_FILE_END (output);
556
TEST_FILE_RESET (output);
566
term_handler (int signum)
572
test_jobs_action (void)
580
int ret, sock, status;
583
/* Check that the jobs command sends the watch jobs message to
584
* the server, and then receives all replies and outputs each job
587
TEST_FUNCTION ("jobs_action");
588
program_name = "test";
590
nih_error_push_context ();
591
nih_error_pop_context ();
595
sock = upstart_open ();
596
destination_pid = getpid ();
598
cmd.command = "jobs";
603
TEST_DIVERT_STDOUT (output) {
604
signal (SIGTERM, term_handler);
605
upstart_disable_safeties = TRUE;
607
control_sock = upstart_open ();
608
ret = jobs_action (&cmd, args);
613
/* Should receive UPSTART_WATCH_JOBS */
614
assert (msg = nih_io_message_recv (NULL, sock, &len));
616
TEST_EQ (msg->data->len, 12);
617
TEST_EQ_MEM (msg->data->buf, "upstart\n\0\0\0\xa", 12);
622
/* Send back a couple of jobs */
623
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "frodo",
624
JOB_START, JOB_RUNNING, 1000);
625
assert (nih_io_message_send (msg, sock) > 0);
628
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "frodo",
629
JOB_STOP, JOB_KILLED, 2000);
630
assert (nih_io_message_send (msg, sock) > 0);
633
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "frodo",
634
JOB_STOP, JOB_STOPPING, 3000);
635
assert (nih_io_message_send (msg, sock) > 0);
638
msg = upstart_message_new (NULL, pid, UPSTART_JOB_STATUS, "frodo",
639
JOB_STOP, JOB_WAITING, 0);
640
assert (nih_io_message_send (msg, sock) > 0);
644
/* Meh; no real way to know ... */
649
/* Reap the child, check the output */
650
waitpid (pid, &status, 0);
653
TEST_TRUE (WIFEXITED (status));
654
TEST_EQ (WEXITSTATUS (status), 0);
656
TEST_FILE_EQ (output, "frodo (start) running, process 1000\n");
657
TEST_FILE_EQ (output, "frodo (stop) killed, process 2000\n");
658
TEST_FILE_EQ (output, "frodo (stop) stopping, process 3000\n");
659
TEST_FILE_EQ (output, "frodo (stop) waiting\n");
660
TEST_FILE_END (output);
661
TEST_FILE_RESET (output);
674
test_start_action ();