ctdb-tests: Fix some harmless CIDs
[Samba.git] / ctdb / tests / src / sock_daemon_test.c
blob95045d175ffe3f598e388289bd215523bd800f53
1 /*
2 sock daemon tests
4 Copyright (C) Amitay Isaacs 2016
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "replace.h"
21 #include "system/filesys.h"
22 #include "system/network.h"
23 #include "system/wait.h"
25 #include <assert.h>
27 #include "common/logging.c"
28 #include "common/pkt_read.c"
29 #include "common/pkt_write.c"
30 #include "common/comm.c"
31 #include "common/pidfile.c"
32 #include "common/sock_daemon.c"
33 #include "common/sock_io.c"
35 struct dummy_wait_state {
38 static struct tevent_req *dummy_wait_send(TALLOC_CTX *mem_ctx,
39 struct tevent_context *ev,
40 void *private_data)
42 struct tevent_req *req;
43 struct dummy_wait_state *state;
44 const char *sockpath = (const char *)private_data;
45 struct stat st;
46 int ret;
48 ret = stat(sockpath, &st);
49 assert(ret == 0);
50 assert(S_ISSOCK(st.st_mode));
52 req = tevent_req_create(mem_ctx, &state, struct dummy_wait_state);
53 if (req == NULL) {
54 return NULL;
57 tevent_req_done(req);
58 return tevent_req_post(req, ev);
61 static bool dummy_wait_recv(struct tevent_req *req, int *perr)
63 return true;
66 static struct sock_daemon_funcs test1_funcs = {
67 .wait_send = dummy_wait_send,
68 .wait_recv = dummy_wait_recv,
71 static struct tevent_req *dummy_read_send(TALLOC_CTX *mem_ctx,
72 struct tevent_context *ev,
73 struct sock_client_context *client,
74 uint8_t *buf, size_t buflen,
75 void *private_data)
77 return NULL;
80 static bool dummy_read_recv(struct tevent_req *req, int *perr)
82 if (perr != NULL) {
83 *perr = EINVAL;
85 return false;
88 static struct sock_socket_funcs dummy_socket_funcs = {
89 .read_send = dummy_read_send,
90 .read_recv = dummy_read_recv,
94 * test1
96 * Check setup without actually running daemon
99 static void test1(TALLOC_CTX *mem_ctx, const char *pidfile,
100 const char *sockpath)
102 struct tevent_context *ev;
103 struct sock_daemon_context *sockd;
104 struct stat st;
105 int ret;
107 ret = sock_daemon_setup(mem_ctx, "test1", "file:", "NOTICE",
108 &test1_funcs, discard_const(sockpath), &sockd);
109 assert(ret == 0);
110 assert(sockd != NULL);
112 ret = stat(pidfile, &st);
113 assert(ret == -1);
115 ret = sock_daemon_add_unix(sockd, sockpath, &dummy_socket_funcs, NULL);
116 assert(ret == 0);
118 ret = stat(sockpath, &st);
119 assert(ret == -1);
121 ev = tevent_context_init(mem_ctx);
122 assert(ev != NULL);
124 ret = sock_daemon_run(ev, sockd, NULL, false, false, -1);
125 assert(ret == 0);
127 talloc_free(mem_ctx);
131 * test2
133 * Start daemon, check PID file, sock daemon functions, termination,
134 * exit code
137 static void test2_startup(void *private_data)
139 int fd = *(int *)private_data;
140 int ret = 1;
141 ssize_t nwritten;
143 nwritten = write(fd, &ret, sizeof(ret));
144 assert(nwritten == sizeof(ret));
147 static void test2_reconfigure(void *private_data)
149 int fd = *(int *)private_data;
150 int ret = 2;
151 ssize_t nwritten;
153 nwritten = write(fd, &ret, sizeof(ret));
154 assert(nwritten == sizeof(ret));
157 static void test2_shutdown(void *private_data)
159 int fd = *(int *)private_data;
160 int ret = 3;
161 ssize_t nwritten;
163 nwritten = write(fd, &ret, sizeof(ret));
164 assert(nwritten == sizeof(ret));
167 static struct sock_daemon_funcs test2_funcs = {
168 .startup = test2_startup,
169 .reconfigure = test2_reconfigure,
170 .shutdown = test2_shutdown,
173 static void test2(TALLOC_CTX *mem_ctx, const char *pidfile,
174 const char *sockpath)
176 struct stat st;
177 int fd[2];
178 pid_t pid, pid2;
179 int ret;
180 ssize_t n;
181 int pidfile_fd;
182 char pidstr[20] = { 0 };
184 ret = pipe(fd);
185 assert(ret == 0);
187 pid = fork();
188 assert(pid != -1);
190 if (pid == 0) {
191 struct tevent_context *ev;
192 struct sock_daemon_context *sockd;
194 close(fd[0]);
196 ev = tevent_context_init(mem_ctx);
197 assert(ev != NULL);
199 ret = sock_daemon_setup(mem_ctx, "test2", "file:", "NOTICE",
200 &test2_funcs, &fd[1], &sockd);
201 assert(ret == 0);
203 ret = sock_daemon_add_unix(sockd, sockpath,
204 &dummy_socket_funcs, NULL);
205 assert(ret == 0);
207 ret = sock_daemon_run(ev, sockd, pidfile, false, false, -1);
208 assert(ret == EINTR);
210 exit(0);
213 close(fd[1]);
215 n = read(fd[0], &ret, sizeof(ret));
216 assert(n == sizeof(ret));
217 assert(ret == 1);
219 pidfile_fd = open(pidfile, O_RDONLY, 0644);
220 assert(pidfile_fd != -1);
221 ret = fstat(pidfile_fd, &st);
222 assert(ret == 0);
223 assert(S_ISREG(st.st_mode));
224 n = read(pidfile_fd, pidstr, sizeof(pidstr)-1);
225 assert(n != -1);
226 pid2 = (pid_t)atoi(pidstr);
227 assert(pid == pid2);
228 close(pidfile_fd);
230 ret = kill(pid, SIGHUP);
231 assert(ret == 0);
233 n = read(fd[0], &ret, sizeof(ret));
234 assert(n == sizeof(ret));
235 assert(ret == 2);
237 ret = kill(pid, SIGUSR1);
238 assert(ret == 0);
240 n = read(fd[0], &ret, sizeof(ret));
241 assert(n == sizeof(ret));
242 assert(ret == 2);
244 ret = kill(pid, SIGTERM);
245 assert(ret == 0);
247 n = read(fd[0], &ret, sizeof(ret));
248 assert(n == sizeof(ret));
249 assert(ret == 3);
251 pid2 = waitpid(pid, &ret, 0);
252 assert(pid2 == pid);
253 assert(WEXITSTATUS(ret) == 0);
255 close(fd[0]);
257 ret = stat(pidfile, &st);
258 assert(ret == -1);
260 ret = stat(sockpath, &st);
261 assert(ret == -1);
265 * test3
267 * Start daemon, test watching of (parent) PID
270 static void test3(TALLOC_CTX *mem_ctx, const char *pidfile,
271 const char *sockpath)
273 struct stat st;
274 pid_t pid_watch, pid, pid2;
275 int ret;
277 pid_watch = fork();
278 assert(pid_watch != -1);
280 if (pid_watch == 0) {
281 sleep(10);
282 exit(0);
285 pid = fork();
286 assert(pid != -1);
288 if (pid == 0) {
289 struct tevent_context *ev;
290 struct sock_daemon_context *sockd;
292 ev = tevent_context_init(mem_ctx);
293 assert(ev != NULL);
295 ret = sock_daemon_setup(mem_ctx, "test3", "file:", "NOTICE",
296 NULL, NULL, &sockd);
297 assert(ret == 0);
299 ret = sock_daemon_add_unix(sockd, sockpath,
300 &dummy_socket_funcs, NULL);
301 assert(ret == 0);
303 ret = sock_daemon_run(ev, sockd, NULL, false, false, pid_watch);
304 assert(ret == ESRCH);
306 exit(0);
309 pid2 = waitpid(pid_watch, &ret, 0);
310 assert(pid2 == pid_watch);
311 assert(WEXITSTATUS(ret) == 0);
313 pid2 = waitpid(pid, &ret, 0);
314 assert(pid2 == pid);
315 assert(WEXITSTATUS(ret) == 0);
317 ret = stat(pidfile, &st);
318 assert(ret == -1);
320 ret = stat(sockpath, &st);
321 assert(ret == -1);
325 * test4
327 * Start daemon, test termination via wait_send function
330 struct test4_wait_state {
333 static void test4_wait_done(struct tevent_req *subreq);
335 static struct tevent_req *test4_wait_send(TALLOC_CTX *mem_ctx,
336 struct tevent_context *ev,
337 void *private_data)
339 struct tevent_req *req, *subreq;
340 struct test4_wait_state *state;
342 req = tevent_req_create(mem_ctx, &state, struct test4_wait_state);
343 if (req == NULL) {
344 return NULL;
347 subreq = tevent_wakeup_send(state, ev,
348 tevent_timeval_current_ofs(10,0));
349 if (tevent_req_nomem(subreq, req)) {
350 return tevent_req_post(req, ev);
352 tevent_req_set_callback(subreq, test4_wait_done, req);
354 return req;
357 static void test4_wait_done(struct tevent_req *subreq)
359 struct tevent_req *req = tevent_req_callback_data(
360 subreq, struct tevent_req);
361 bool status;
363 status = tevent_wakeup_recv(subreq);
364 TALLOC_FREE(subreq);
366 if (! status) {
367 tevent_req_error(req, EIO);
368 } else {
369 tevent_req_done(req);
373 static bool test4_wait_recv(struct tevent_req *req, int *perr)
375 int ret;
377 if (tevent_req_is_unix_error(req, &ret)) {
378 if (perr != NULL) {
379 *perr = ret;
381 return false;
384 return true;
387 static struct sock_daemon_funcs test4_funcs = {
388 .wait_send = test4_wait_send,
389 .wait_recv = test4_wait_recv,
392 static void test4(TALLOC_CTX *mem_ctx, const char *pidfile,
393 const char *sockpath)
395 struct stat st;
396 pid_t pid, pid2;
397 int ret;
399 pid = fork();
400 assert(pid != -1);
402 if (pid == 0) {
403 struct tevent_context *ev;
404 struct sock_daemon_context *sockd;
406 ev = tevent_context_init(mem_ctx);
407 assert(ev != NULL);
409 ret = sock_daemon_setup(mem_ctx, "test4", "file:", "NOTICE",
410 &test4_funcs, NULL, &sockd);
411 assert(ret == 0);
413 ret = sock_daemon_run(ev, sockd, pidfile, false, false, -1);
414 assert(ret == 0);
416 exit(0);
419 pid2 = waitpid(pid, &ret, 0);
420 assert(pid2 == pid);
421 assert(WEXITSTATUS(ret) == 0);
423 ret = stat(pidfile, &st);
424 assert(ret == -1);
426 ret = stat(sockpath, &st);
427 assert(ret == -1);
431 * test5
433 * Start daemon, multiple client connects, requests, disconnects
436 #define TEST5_MAX_CLIENTS 10
438 struct test5_pkt {
439 uint32_t len;
440 int data;
443 struct test5_client_state {
444 int id;
445 int fd;
446 bool done;
449 static void test5_client_callback(uint8_t *buf, size_t buflen,
450 void *private_data)
452 struct test5_client_state *state =
453 (struct test5_client_state *)private_data;
454 struct test5_pkt *pkt;
455 ssize_t n;
456 int ret;
458 if (buf == NULL) {
459 assert(buflen == 0);
461 ret = 0;
462 } else {
463 assert(buflen == sizeof(struct test5_pkt));
464 pkt = (struct test5_pkt *)buf;
465 assert(pkt->len == sizeof(struct test5_pkt));
467 ret = pkt->data;
470 assert(state->fd != -1);
472 n = write(state->fd, (void *)&ret, sizeof(int));
473 assert(n == sizeof(int));
475 state->done = true;
478 static int test5_client(const char *sockpath, int id)
480 pid_t pid;
481 int fd[2];
482 int ret;
483 ssize_t n;
485 ret = pipe(fd);
486 assert(ret == 0);
488 pid = fork();
489 assert(pid != -1);
491 if (pid == 0) {
492 struct tevent_context *ev;
493 struct test5_client_state state;
494 struct sock_queue *queue;
495 struct test5_pkt pkt;
496 int conn;
498 close(fd[0]);
500 ev = tevent_context_init(NULL);
501 assert(ev != NULL);
503 conn = sock_connect(sockpath);
504 assert(conn != -1);
506 state.id = id;
507 state.fd = fd[1];
508 state.done = false;
510 queue = sock_queue_setup(ev, ev, conn,
511 test5_client_callback, &state);
512 assert(queue != NULL);
514 pkt.len = 8;
515 pkt.data = 0xbaba;
517 ret = sock_queue_write(queue, (uint8_t *)&pkt,
518 sizeof(struct test5_pkt));
519 assert(ret == 0);
521 while (! state.done) {
522 tevent_loop_once(ev);
525 close(fd[0]);
526 state.fd = -1;
528 sleep(10);
529 exit(0);
532 close(fd[1]);
534 ret = 0;
535 n = read(fd[0], &ret, sizeof(ret));
536 if (n == 0) {
537 fprintf(stderr, "client id %d read 0 bytes\n", id);
539 assert(n == 0 || n == sizeof(ret));
541 close(fd[0]);
543 return ret;
546 struct test5_server_state {
547 int num_clients;
550 static bool test5_connect(struct sock_client_context *client,
551 void *private_data)
553 struct test5_server_state *state =
554 (struct test5_server_state *)private_data;
556 if (state->num_clients == TEST5_MAX_CLIENTS) {
557 return false;
560 state->num_clients += 1;
561 assert(state->num_clients <= TEST5_MAX_CLIENTS);
562 return true;
565 static void test5_disconnect(struct sock_client_context *client,
566 void *private_data)
568 struct test5_server_state *state =
569 (struct test5_server_state *)private_data;
571 state->num_clients -= 1;
572 assert(state->num_clients >= 0);
575 struct test5_read_state {
576 struct test5_pkt reply;
579 static void test5_read_done(struct tevent_req *subreq);
581 static struct tevent_req *test5_read_send(TALLOC_CTX *mem_ctx,
582 struct tevent_context *ev,
583 struct sock_client_context *client,
584 uint8_t *buf, size_t buflen,
585 void *private_data)
587 struct test5_server_state *server_state =
588 (struct test5_server_state *)private_data;
589 struct tevent_req *req, *subreq;
590 struct test5_read_state *state;
591 struct test5_pkt *pkt;
593 req = tevent_req_create(mem_ctx, &state, struct test5_read_state);
594 assert(req != NULL);
596 assert(buflen == sizeof(struct test5_pkt));
598 pkt = (struct test5_pkt *)buf;
599 assert(pkt->data == 0xbaba);
601 state->reply.len = sizeof(struct test5_pkt);
602 state->reply.data = server_state->num_clients;
604 subreq = sock_socket_write_send(state, ev, client,
605 (uint8_t *)&state->reply,
606 state->reply.len);
607 assert(subreq != NULL);
609 tevent_req_set_callback(subreq, test5_read_done, req);
611 return req;
614 static void test5_read_done(struct tevent_req *subreq)
616 struct tevent_req *req = tevent_req_callback_data(
617 subreq, struct tevent_req);
618 int ret;
619 bool status;
621 status = sock_socket_write_recv(subreq, &ret);
622 TALLOC_FREE(subreq);
623 if (! status) {
624 tevent_req_error(req, ret);
625 return;
628 tevent_req_done(req);
631 static bool test5_read_recv(struct tevent_req *req, int *perr)
633 int ret;
635 if (tevent_req_is_unix_error(req, &ret)) {
636 if (perr != NULL) {
637 *perr = ret;
639 return false;
642 return true;
645 static struct sock_socket_funcs test5_client_funcs = {
646 .connect = test5_connect,
647 .disconnect = test5_disconnect,
648 .read_send = test5_read_send,
649 .read_recv = test5_read_recv,
652 static void test5_startup(void *private_data)
654 int fd = *(int *)private_data;
655 int ret = 1;
656 ssize_t nwritten;
658 nwritten = write(fd, &ret, sizeof(ret));
659 assert(nwritten == sizeof(ret));
660 close(fd);
663 static struct sock_daemon_funcs test5_funcs = {
664 .startup = test5_startup,
667 static void test5(TALLOC_CTX *mem_ctx, const char *pidfile,
668 const char *sockpath)
670 pid_t pid_server, pid;
671 int fd[2], ret, i;
672 ssize_t n;
674 pid = getpid();
676 ret = pipe(fd);
677 assert(ret == 0);
679 pid_server = fork();
680 assert(pid_server != -1);
682 if (pid_server == 0) {
683 struct tevent_context *ev;
684 struct sock_daemon_context *sockd;
685 struct test5_server_state state;
687 close(fd[0]);
689 ev = tevent_context_init(mem_ctx);
690 assert(ev != NULL);
692 ret = sock_daemon_setup(mem_ctx, "test5", "file:", "NOTICE",
693 &test5_funcs, &fd[1], &sockd);
694 assert(ret == 0);
696 state.num_clients = 0;
698 ret = sock_daemon_add_unix(sockd, sockpath,
699 &test5_client_funcs, &state);
700 assert(ret == 0);
702 ret = sock_daemon_run(ev, sockd, pidfile, false, false, pid);
703 assert(ret == EINTR);
705 exit(0);
708 close(fd[1]);
710 n = read(fd[0], &ret, sizeof(ret));
711 assert(n == sizeof(ret));
712 assert(ret == 1);
714 close(fd[0]);
716 for (i=0; i<100; i++) {
717 ret = test5_client(sockpath, i);
718 if (i < TEST5_MAX_CLIENTS) {
719 assert(ret == i+1);
720 } else {
721 assert(ret == 0);
725 for (i=0; i<100; i++) {
726 pid = wait(&ret);
727 assert(pid != -1);
730 ret = kill(pid_server, SIGTERM);
731 assert(ret == 0);
735 * test6
737 * Start daemon, test client connects, requests, replies, disconnects
740 struct test6_pkt {
741 uint32_t len;
742 uint32_t data;
745 struct test6_client_state {
746 bool done;
749 static void test6_client_callback(uint8_t *buf, size_t buflen,
750 void *private_data)
752 struct test6_client_state *state =
753 (struct test6_client_state *)private_data;
754 struct test6_pkt *pkt;
756 assert(buflen == sizeof(struct test6_pkt));
757 pkt = (struct test6_pkt *)buf;
758 assert(pkt->len == sizeof(struct test6_pkt));
759 assert(pkt->data == 0xffeeddcc);
761 state->done = true;
764 static void test6_client(const char *sockpath)
766 struct tevent_context *ev;
767 struct test6_client_state state;
768 struct sock_queue *queue;
769 struct test6_pkt pkt;
770 int conn, ret;
772 ev = tevent_context_init(NULL);
773 assert(ev != NULL);
775 conn = sock_connect(sockpath);
776 assert(conn != -1);
778 state.done = false;
780 queue = sock_queue_setup(ev, ev, conn,
781 test6_client_callback, &state);
782 assert(queue != NULL);
784 pkt.len = 8;
785 pkt.data = 0xaabbccdd;
787 ret = sock_queue_write(queue, (uint8_t *)&pkt,
788 sizeof(struct test6_pkt));
789 assert(ret == 0);
791 while (! state.done) {
792 tevent_loop_once(ev);
795 talloc_free(ev);
798 struct test6_server_state {
799 struct sock_daemon_context *sockd;
800 int fd, done;
803 struct test6_read_state {
804 struct test6_server_state *server_state;
805 struct test6_pkt reply;
808 static void test6_read_done(struct tevent_req *subreq);
810 static struct tevent_req *test6_read_send(TALLOC_CTX *mem_ctx,
811 struct tevent_context *ev,
812 struct sock_client_context *client,
813 uint8_t *buf, size_t buflen,
814 void *private_data)
816 struct test6_server_state *server_state =
817 (struct test6_server_state *)private_data;
818 struct tevent_req *req, *subreq;
819 struct test6_read_state *state;
820 struct test6_pkt *pkt;
822 req = tevent_req_create(mem_ctx, &state, struct test6_read_state);
823 assert(req != NULL);
825 state->server_state = server_state;
827 assert(buflen == sizeof(struct test6_pkt));
829 pkt = (struct test6_pkt *)buf;
830 assert(pkt->data == 0xaabbccdd);
832 state->reply.len = sizeof(struct test6_pkt);
833 state->reply.data = 0xffeeddcc;
835 subreq = sock_socket_write_send(state, ev, client,
836 (uint8_t *)&state->reply,
837 state->reply.len);
838 assert(subreq != NULL);
840 tevent_req_set_callback(subreq, test6_read_done, req);
842 return req;
845 static void test6_read_done(struct tevent_req *subreq)
847 struct tevent_req *req = tevent_req_callback_data(
848 subreq, struct tevent_req);
849 struct test6_read_state *state = tevent_req_data(
850 req, struct test6_read_state);
851 int ret;
852 bool status;
854 status = sock_socket_write_recv(subreq, &ret);
855 TALLOC_FREE(subreq);
856 if (! status) {
857 tevent_req_error(req, ret);
858 return;
861 state->server_state->done = 1;
862 tevent_req_done(req);
865 static bool test6_read_recv(struct tevent_req *req, int *perr)
867 int ret;
869 if (tevent_req_is_unix_error(req, &ret)) {
870 if (perr != NULL) {
871 *perr = ret;
873 return false;
876 return true;
879 static struct sock_socket_funcs test6_client_funcs = {
880 .read_send = test6_read_send,
881 .read_recv = test6_read_recv,
884 static void test6_startup(void *private_data)
886 struct test6_server_state *server_state =
887 (struct test6_server_state *)private_data;
888 int ret = 1;
889 ssize_t nwritten;
891 nwritten = write(server_state->fd, &ret, sizeof(ret));
892 assert(nwritten == sizeof(ret));
893 close(server_state->fd);
894 server_state->fd = -1;
897 struct test6_wait_state {
898 struct test6_server_state *server_state;
901 static void test6_wait_done(struct tevent_req *subreq);
903 static struct tevent_req *test6_wait_send(TALLOC_CTX *mem_ctx,
904 struct tevent_context *ev,
905 void *private_data)
907 struct tevent_req *req, *subreq;
908 struct test6_wait_state *state;
910 req = tevent_req_create(mem_ctx, &state, struct test6_wait_state);
911 if (req == NULL) {
912 return NULL;
915 state->server_state = (struct test6_server_state *)private_data;
917 subreq = tevent_wakeup_send(state, ev,
918 tevent_timeval_current_ofs(10,0));
919 if (tevent_req_nomem(subreq, req)) {
920 return tevent_req_post(req, ev);
922 tevent_req_set_callback(subreq, test6_wait_done, req);
924 return req;
927 static void test6_wait_done(struct tevent_req *subreq)
929 struct tevent_req *req = tevent_req_callback_data(
930 subreq, struct tevent_req);
931 struct test6_wait_state *state = tevent_req_data(
932 req, struct test6_wait_state);
933 bool status;
935 status = tevent_wakeup_recv(subreq);
936 TALLOC_FREE(subreq);
937 if (! status) {
938 tevent_req_error(req, EIO);
939 return;
942 if (state->server_state->done == 0) {
943 tevent_req_error(req, EIO);
944 return;
947 tevent_req_done(req);
950 static bool test6_wait_recv(struct tevent_req *req, int *perr)
952 int ret;
954 if (tevent_req_is_unix_error(req, &ret)) {
955 if (perr != NULL) {
956 *perr = ret;
958 return false;
961 return true;
964 static struct sock_daemon_funcs test6_funcs = {
965 .startup = test6_startup,
966 .wait_send = test6_wait_send,
967 .wait_recv = test6_wait_recv,
970 static void test6(TALLOC_CTX *mem_ctx, const char *pidfile,
971 const char *sockpath)
973 pid_t pid_server, pid;
974 int fd[2], ret;
975 ssize_t n;
977 pid = getpid();
979 ret = pipe(fd);
980 assert(ret == 0);
982 pid_server = fork();
983 assert(pid_server != -1);
985 if (pid_server == 0) {
986 struct tevent_context *ev;
987 struct sock_daemon_context *sockd;
988 struct test6_server_state server_state = { 0 };
990 close(fd[0]);
992 ev = tevent_context_init(mem_ctx);
993 assert(ev != NULL);
995 server_state.fd = fd[1];
997 ret = sock_daemon_setup(mem_ctx, "test6", "file:", "NOTICE",
998 &test6_funcs, &server_state,
999 &sockd);
1000 assert(ret == 0);
1002 server_state.sockd = sockd;
1003 server_state.done = 0;
1005 ret = sock_daemon_add_unix(sockd, sockpath,
1006 &test6_client_funcs, &server_state);
1007 assert(ret == 0);
1009 ret = sock_daemon_run(ev, sockd, pidfile, false, false, pid);
1010 assert(ret == 0);
1012 exit(0);
1015 close(fd[1]);
1017 n = read(fd[0], &ret, sizeof(ret));
1018 assert(n == sizeof(ret));
1019 assert(ret == 1);
1021 close(fd[0]);
1023 test6_client(sockpath);
1025 pid = wait(&ret);
1026 assert(pid != -1);
1030 * test7
1032 * Start daemon twice, confirm PID file contention
1035 static void test7(TALLOC_CTX *mem_ctx, const char *pidfile,
1036 const char *sockpath)
1038 struct stat st;
1039 int fd[2];
1040 pid_t pid, pid2;
1041 int ret;
1042 struct tevent_context *ev;
1043 struct sock_daemon_context *sockd;
1044 ssize_t n;
1046 ret = pipe(fd);
1047 assert(ret == 0);
1049 pid = fork();
1050 assert(pid != -1);
1052 if (pid == 0) {
1053 close(fd[0]);
1055 ev = tevent_context_init(mem_ctx);
1056 assert(ev != NULL);
1058 /* Reuse test2 funcs for the startup synchronisation */
1059 ret = sock_daemon_setup(mem_ctx, "test7", "file:", "NOTICE",
1060 &test2_funcs, &fd[1], &sockd);
1061 assert(ret == 0);
1063 ret = sock_daemon_run(ev, sockd, pidfile, false, false, -1);
1064 assert(ret == EINTR);
1066 exit(0);
1069 close(fd[1]);
1071 n = read(fd[0], &ret, sizeof(ret));
1072 assert(n == sizeof(ret));
1073 assert(ret == 1);
1075 ret = stat(pidfile, &st);
1076 assert(ret == 0);
1077 assert(S_ISREG(st.st_mode));
1079 ev = tevent_context_init(mem_ctx);
1080 assert(ev != NULL);
1082 /* Reuse test2 funcs for the startup synchronisation */
1083 ret = sock_daemon_setup(mem_ctx, "test7-parent", "file:", "NOTICE",
1084 &test2_funcs, &fd[1], &sockd);
1085 assert(ret == 0);
1087 ret = sock_daemon_run(ev, sockd, pidfile, false, false, -1);
1088 assert(ret == EEXIST);
1090 ret = kill(pid, SIGTERM);
1091 assert(ret == 0);
1093 n = read(fd[0], &ret, sizeof(ret));
1094 assert(n == sizeof(ret));
1095 assert(ret == 3);
1097 pid2 = waitpid(pid, &ret, 0);
1098 assert(pid2 == pid);
1099 assert(WEXITSTATUS(ret) == 0);
1101 close(fd[0]);
1105 * test8
1107 * Start daemon, confirm that create_session argument works as expected
1110 static void test8(TALLOC_CTX *mem_ctx, const char *pidfile,
1111 const char *sockpath)
1113 int fd[2];
1114 pid_t pid, pid2, sid;
1115 int ret;
1116 struct tevent_context *ev;
1117 struct sock_daemon_context *sockd;
1118 ssize_t n;
1120 ret = pipe(fd);
1121 assert(ret == 0);
1123 pid = fork();
1124 assert(pid != -1);
1126 if (pid == 0) {
1127 close(fd[0]);
1129 ev = tevent_context_init(mem_ctx);
1130 assert(ev != NULL);
1132 /* Reuse test2 funcs for the startup synchronisation */
1133 ret = sock_daemon_setup(mem_ctx, "test8", "file:", "NOTICE",
1134 &test2_funcs, &fd[1], &sockd);
1135 assert(ret == 0);
1137 ret = sock_daemon_run(ev, sockd, pidfile, false, false, -1);
1138 assert(ret == EINTR);
1140 exit(0);
1143 close(fd[1]);
1145 n = read(fd[0], &ret, sizeof(ret));
1146 assert(n == sizeof(ret));
1147 assert(ret == 1);
1149 /* create_session false above, so pid != sid */
1150 sid = getsid(pid);
1151 assert(pid != sid);
1153 ret = kill(pid, SIGTERM);
1154 assert(ret == 0);
1156 n = read(fd[0], &ret, sizeof(ret));
1157 assert(n == sizeof(ret));
1158 assert(ret == 3);
1160 pid2 = waitpid(pid, &ret, 0);
1161 assert(pid2 == pid);
1162 assert(WEXITSTATUS(ret) == 0);
1164 close(fd[0]);
1166 ret = pipe(fd);
1167 assert(ret == 0);
1169 pid = fork();
1170 assert(pid != -1);
1172 if (pid == 0) {
1173 close(fd[0]);
1175 ev = tevent_context_init(mem_ctx);
1176 assert(ev != NULL);
1178 /* Reuse test2 funcs for the startup synchronisation */
1179 ret = sock_daemon_setup(mem_ctx, "test8", "file:", "NOTICE",
1180 &test2_funcs, &fd[1], &sockd);
1181 assert(ret == 0);
1183 ret = sock_daemon_run(ev, sockd, pidfile, false, true, -1);
1184 assert(ret == EINTR);
1186 exit(0);
1189 close(fd[1]);
1191 n = read(fd[0], &ret, sizeof(ret));
1192 assert(n == sizeof(ret));
1193 assert(ret == 1);
1195 /* create_session true above, so pid == sid */
1196 sid = getsid(pid);
1197 assert(pid == sid);
1199 ret = kill(pid, SIGTERM);
1200 assert(ret == 0);
1202 n = read(fd[0], &ret, sizeof(ret));
1203 assert(n == sizeof(ret));
1204 assert(ret == 3);
1206 pid2 = waitpid(pid, &ret, 0);
1207 assert(pid2 == pid);
1208 assert(WEXITSTATUS(ret) == 0);
1210 close(fd[0]);
1214 * test9
1216 * Confirm that do_fork causes the daemon to be forked as a separate child
1219 static void test9(TALLOC_CTX *mem_ctx, const char *pidfile,
1220 const char *sockpath)
1222 int fd[2];
1223 pid_t pid, pid2;
1224 int ret;
1225 struct tevent_context *ev;
1226 struct sock_daemon_context *sockd;
1227 ssize_t n;
1228 int pidfile_fd;
1229 char pidstr[20] = { 0 };
1230 struct stat st;
1232 ret = pipe(fd);
1233 assert(ret == 0);
1235 pid = fork();
1236 assert(pid != -1);
1238 if (pid == 0) {
1239 close(fd[0]);
1241 ev = tevent_context_init(mem_ctx);
1242 assert(ev != NULL);
1244 /* Reuse test2 funcs for the startup synchronisation */
1245 ret = sock_daemon_setup(mem_ctx, "test9", "file:", "NOTICE",
1246 &test2_funcs, &fd[1], &sockd);
1247 assert(ret == 0);
1249 ret = sock_daemon_run(ev, sockd, pidfile, false, false, -1);
1250 assert(ret == EINTR);
1252 exit(0);
1255 close(fd[1]);
1257 n = read(fd[0], &ret, sizeof(ret));
1258 assert(n == sizeof(ret));
1259 assert(ret == 1);
1261 /* do_fork false above, so pid should be active */
1262 ret = kill(pid, 0);
1263 assert(ret == 0);
1265 ret = kill(pid, SIGTERM);
1266 assert(ret == 0);
1268 n = read(fd[0], &ret, sizeof(ret));
1269 assert(n == sizeof(ret));
1270 assert(ret == 3);
1272 pid2 = waitpid(pid, &ret, 0);
1273 assert(pid2 == pid);
1274 assert(WEXITSTATUS(ret) == 0);
1276 close(fd[0]);
1278 ret = pipe(fd);
1279 assert(ret == 0);
1281 pid = fork();
1282 assert(pid != -1);
1284 if (pid == 0) {
1285 close(fd[0]);
1287 ev = tevent_context_init(mem_ctx);
1288 assert(ev != NULL);
1290 /* Reuse test2 funcs for the startup synchronisation */
1291 ret = sock_daemon_setup(mem_ctx, "test9", "file:", "NOTICE",
1292 &test2_funcs, &fd[1], &sockd);
1293 assert(ret == 0);
1295 ret = sock_daemon_run(ev, sockd, pidfile, true, false, -1);
1296 assert(ret == EINTR);
1298 exit(0);
1301 close(fd[1]);
1303 n = read(fd[0], &ret, sizeof(ret));
1304 assert(n == sizeof(ret));
1305 assert(ret == 1);
1307 /* do_fork true above, so pid should have exited */
1308 pid2 = waitpid(pid, &ret, 0);
1309 assert(pid2 == pid);
1310 assert(WEXITSTATUS(ret) == 0);
1312 pidfile_fd = open(pidfile, O_RDONLY, 0644);
1313 assert(pidfile_fd != -1);
1314 n = read(pidfile_fd, pidstr, sizeof(pidstr)-1);
1315 assert(n != -1);
1316 pid2 = (pid_t)atoi(pidstr);
1317 assert(pid != pid2);
1318 close(pidfile_fd);
1320 ret = kill(pid2, SIGTERM);
1321 assert(ret == 0);
1323 n = read(fd[0], &ret, sizeof(ret));
1324 assert(n == sizeof(ret));
1325 assert(ret == 3);
1328 * pid2 isn't our child, so can't call waitpid(). kill(pid2, 0)
1329 * is unreliable - pid2 may have been recycled. Above indicates
1330 * that the shutdown function was called, so just do 1 final
1331 * check to see if pidfile has been removed.
1333 ret = stat(sockpath, &st);
1334 assert(ret == -1);
1336 close(fd[0]);
1340 * test10
1342 * Confirm that the daemon starts successfully if there is a stale socket
1345 static void test10(TALLOC_CTX *mem_ctx, const char *pidfile,
1346 const char *sockpath)
1348 struct stat st;
1349 int fd[2];
1350 pid_t pid, pid2;
1351 int ret;
1352 ssize_t n;
1353 int pidfile_fd;
1354 char pidstr[20] = { 0 };
1356 ret = pipe(fd);
1357 assert(ret == 0);
1359 pid = fork();
1360 assert(pid != -1);
1362 if (pid == 0) {
1363 struct tevent_context *ev;
1364 struct sock_daemon_context *sockd;
1366 close(fd[0]);
1368 ev = tevent_context_init(mem_ctx);
1369 assert(ev != NULL);
1371 ret = sock_daemon_setup(mem_ctx, "test10", "file:", "NOTICE",
1372 &test2_funcs, &fd[1], &sockd);
1373 assert(ret == 0);
1375 ret = sock_daemon_add_unix(sockd, sockpath,
1376 &dummy_socket_funcs, NULL);
1377 assert(ret == 0);
1379 ret = sock_daemon_run(ev, sockd, pidfile, false, false, -1);
1380 assert(ret == EINTR);
1382 exit(0);
1385 close(fd[1]);
1387 n = read(fd[0], &ret, sizeof(ret));
1388 assert(n == sizeof(ret));
1389 assert(ret == 1);
1391 /* KILL will leave PID file and socket behind */
1392 ret = kill (pid, SIGKILL);
1393 assert(ret == 0);
1395 ret = stat(sockpath, &st);
1396 assert(ret == 0);
1398 close(fd[0]);
1400 ret = pipe(fd);
1401 assert(ret == 0);
1403 pid = fork();
1404 assert(pid != -1);
1406 if (pid == 0) {
1407 struct tevent_context *ev;
1408 struct sock_daemon_context *sockd;
1410 close(fd[0]);
1412 ev = tevent_context_init(mem_ctx);
1413 assert(ev != NULL);
1415 ret = sock_daemon_setup(mem_ctx, "test10", "file:", "NOTICE",
1416 &test2_funcs, &fd[1], &sockd);
1417 assert(ret == 0);
1419 ret = sock_daemon_add_unix(sockd, sockpath,
1420 &dummy_socket_funcs, NULL);
1421 assert(ret == 0);
1423 ret = sock_daemon_run(ev, sockd, pidfile, false, false, -1);
1424 assert(ret == EINTR);
1426 exit(0);
1429 close(fd[1]);
1431 n = read(fd[0], &ret, sizeof(ret));
1432 assert(n == sizeof(ret));
1433 assert(ret == 1);
1435 pidfile_fd = open(pidfile, O_RDONLY, 0644);
1436 assert(pidfile_fd != -1);
1437 n = read(pidfile_fd, pidstr, sizeof(pidstr)-1);
1438 assert(n != -1);
1439 pid2 = (pid_t)atoi(pidstr);
1440 assert(pid == pid2);
1441 close(pidfile_fd);
1443 ret = kill(pid, SIGTERM);
1444 assert(ret == 0);
1446 n = read(fd[0], &ret, sizeof(ret));
1447 assert(n == sizeof(ret));
1448 assert(ret == 3);
1450 pid2 = waitpid(pid, &ret, 0);
1451 assert(pid2 == pid);
1452 assert(WEXITSTATUS(ret) == 0);
1454 close(fd[0]);
1456 ret = stat(pidfile, &st);
1457 assert(ret == -1);
1459 ret = stat(sockpath, &st);
1460 assert(ret == -1);
1463 int main(int argc, const char **argv)
1465 TALLOC_CTX *mem_ctx;
1466 const char *pidfile, *sockpath;
1467 int num;
1469 if (argc != 4) {
1470 fprintf(stderr, "%s <pidfile> <sockpath> <testnum>\n", argv[0]);
1471 exit(1);
1474 pidfile = argv[1];
1475 sockpath = argv[2];
1476 num = atoi(argv[3]);
1478 mem_ctx = talloc_new(NULL);
1479 assert(mem_ctx != NULL);
1481 switch (num) {
1482 case 1:
1483 test1(mem_ctx, pidfile, sockpath);
1484 break;
1486 case 2:
1487 test2(mem_ctx, pidfile, sockpath);
1488 break;
1490 case 3:
1491 test3(mem_ctx, pidfile, sockpath);
1492 break;
1494 case 4:
1495 test4(mem_ctx, pidfile, sockpath);
1496 break;
1498 case 5:
1499 test5(mem_ctx, pidfile, sockpath);
1500 break;
1502 case 6:
1503 test6(mem_ctx, pidfile, sockpath);
1504 break;
1506 case 7:
1507 test7(mem_ctx, pidfile, sockpath);
1508 break;
1510 case 8:
1511 test8(mem_ctx, pidfile, sockpath);
1512 break;
1514 case 9:
1515 test9(mem_ctx, pidfile, sockpath);
1516 break;
1518 case 10:
1519 test10(mem_ctx, pidfile, sockpath);
1520 break;
1522 default:
1523 fprintf(stderr, "Unknown test number %d\n", num);
1526 return 0;