ctdb-tests: Add comments describing sock daemon tests
[vlendec/samba-autobuild/.git] / ctdb / tests / src / sock_daemon_test.c
1 /*
2    sock daemon tests
3
4    Copyright (C) Amitay Isaacs  2016
5
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.
10
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.
15
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/>.
18 */
19
20 #include "replace.h"
21 #include "system/filesys.h"
22 #include "system/network.h"
23 #include "system/wait.h"
24
25 #include <assert.h>
26
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"
34
35 static struct tevent_req *dummy_read_send(TALLOC_CTX *mem_ctx,
36                                           struct tevent_context *ev,
37                                           struct sock_client_context *client,
38                                           uint8_t *buf, size_t buflen,
39                                           void *private_data)
40 {
41         return NULL;
42 }
43
44 static bool dummy_read_recv(struct tevent_req *req, int *perr)
45 {
46         if (perr != NULL) {
47                 *perr = EINVAL;
48         }
49         return false;
50 }
51
52 static struct sock_socket_funcs dummy_socket_funcs = {
53         .read_send = dummy_read_send,
54         .read_recv = dummy_read_recv,
55 };
56
57 /*
58  * test1
59  *
60  * Check setup without actually running daemon
61  */
62
63 static void test1(TALLOC_CTX *mem_ctx, const char *pidfile,
64                   const char *sockpath)
65 {
66         struct sock_daemon_context *sockd;
67         struct stat st;
68         int ret;
69
70         ret = sock_daemon_setup(mem_ctx, "test1", "file:", "NOTICE", pidfile,
71                                 NULL, NULL, &sockd);
72         assert(ret == 0);
73         assert(sockd != NULL);
74
75         ret = stat(pidfile, &st);
76         assert(ret == 0);
77         assert(S_ISREG(st.st_mode));
78
79         ret = sock_daemon_add_unix(sockd, sockpath, &dummy_socket_funcs, NULL);
80         assert(ret == 0);
81
82         ret = stat(sockpath, &st);
83         assert(ret == 0);
84         assert(S_ISSOCK(st.st_mode));
85
86         talloc_free(sockd);
87
88         ret = stat(pidfile, &st);
89         assert(ret == -1);
90
91         ret = stat(sockpath, &st);
92         assert(ret == -1);
93 }
94
95 /*
96  * test2
97  *
98  * Start daemon, check PID file, sock daemon functions, termination,
99  * exit code
100  */
101
102 static void test2_startup(void *private_data)
103 {
104         int fd = *(int *)private_data;
105         int ret = 1;
106         ssize_t nwritten;
107
108         nwritten = write(fd, &ret, sizeof(ret));
109         assert(nwritten == sizeof(ret));
110 }
111
112 static void test2_reconfigure(void *private_data)
113 {
114         int fd = *(int *)private_data;
115         int ret = 2;
116         ssize_t nwritten;
117
118         nwritten = write(fd, &ret, sizeof(ret));
119         assert(nwritten == sizeof(ret));
120 }
121
122 static void test2_shutdown(void *private_data)
123 {
124         int fd = *(int *)private_data;
125         int ret = 3;
126         ssize_t nwritten;
127
128         nwritten = write(fd, &ret, sizeof(ret));
129         assert(nwritten == sizeof(ret));
130 }
131
132 static struct sock_daemon_funcs test2_funcs = {
133         .startup = test2_startup,
134         .reconfigure = test2_reconfigure,
135         .shutdown = test2_shutdown,
136 };
137
138 static void test2(TALLOC_CTX *mem_ctx, const char *pidfile,
139                   const char *sockpath)
140 {
141         struct stat st;
142         int fd[2];
143         pid_t pid, pid2;
144         int ret;
145         ssize_t n;
146
147         ret = pipe(fd);
148         assert(ret == 0);
149
150         pid = fork();
151         assert(pid != -1);
152
153         if (pid == 0) {
154                 struct tevent_context *ev;
155                 struct sock_daemon_context *sockd;
156
157                 close(fd[0]);
158
159                 ev = tevent_context_init(mem_ctx);
160                 assert(ev != NULL);
161
162                 ret = sock_daemon_setup(mem_ctx, "test2", "file:", "NOTICE",
163                                         pidfile, &test2_funcs, &fd[1], &sockd);
164                 assert(ret == 0);
165
166                 ret = sock_daemon_add_unix(sockd, sockpath,
167                                            &dummy_socket_funcs, NULL);
168                 assert(ret == 0);
169
170                 ret = sock_daemon_run(ev, sockd, -1);
171                 assert(ret == EINTR);
172
173                 exit(0);
174         }
175
176         close(fd[1]);
177
178         n = read(fd[0], &ret, sizeof(ret));
179         assert(n == sizeof(ret));
180         assert(ret == 1);
181
182         ret = kill(pid, SIGHUP);
183         assert(ret == 0);
184
185         n = read(fd[0], &ret, sizeof(ret));
186         assert(n == sizeof(ret));
187         assert(ret == 2);
188
189         ret = kill(pid, SIGUSR1);
190         assert(ret == 0);
191
192         n = read(fd[0], &ret, sizeof(ret));
193         assert(n == sizeof(ret));
194         assert(ret == 2);
195
196         ret = kill(pid, SIGTERM);
197         assert(ret == 0);
198
199         n = read(fd[0], &ret, sizeof(ret));
200         assert(n == sizeof(ret));
201         assert(ret == 3);
202
203         pid2 = waitpid(pid, &ret, 0);
204         assert(pid2 == pid);
205         assert(WEXITSTATUS(ret) == 0);
206
207         close(fd[0]);
208
209         ret = stat(pidfile, &st);
210         assert(ret == -1);
211
212         ret = stat(sockpath, &st);
213         assert(ret == -1);
214 }
215
216 /*
217  * test3
218  *
219  * Start daemon, test watching of (parent) PID
220  */
221
222 static void test3(TALLOC_CTX *mem_ctx, const char *pidfile,
223                   const char *sockpath)
224 {
225         struct stat st;
226         pid_t pid_watch, pid, pid2;
227         int ret;
228
229         pid_watch = fork();
230         assert(pid_watch != -1);
231
232         if (pid_watch == 0) {
233                 sleep(10);
234                 exit(0);
235         }
236
237         pid = fork();
238         assert(pid != -1);
239
240         if (pid == 0) {
241                 struct tevent_context *ev;
242                 struct sock_daemon_context *sockd;
243
244                 ev = tevent_context_init(mem_ctx);
245                 assert(ev != NULL);
246
247                 ret = sock_daemon_setup(mem_ctx, "test3", "file:", "NOTICE",
248                                         NULL, NULL, NULL, &sockd);
249                 assert(ret == 0);
250
251                 ret = sock_daemon_add_unix(sockd, sockpath,
252                                            &dummy_socket_funcs, NULL);
253                 assert(ret == 0);
254
255                 ret = sock_daemon_run(ev, sockd, pid_watch);
256                 assert(ret == ESRCH);
257
258                 exit(0);
259         }
260
261         pid2 = waitpid(pid_watch, &ret, 0);
262         assert(pid2 == pid_watch);
263         assert(WEXITSTATUS(ret) == 0);
264
265         pid2 = waitpid(pid, &ret, 0);
266         assert(pid2 == pid);
267         assert(WEXITSTATUS(ret) == 0);
268
269         ret = stat(pidfile, &st);
270         assert(ret == -1);
271
272         ret = stat(sockpath, &st);
273         assert(ret == -1);
274 }
275
276 /*
277  * test4
278  *
279  * Start daemon, test termination via wait_send function
280  */
281
282 struct test4_wait_state {
283 };
284
285 static void test4_wait_done(struct tevent_req *subreq);
286
287 static struct tevent_req *test4_wait_send(TALLOC_CTX *mem_ctx,
288                                           struct tevent_context *ev,
289                                           void *private_data)
290 {
291         struct tevent_req *req, *subreq;
292         struct test4_wait_state *state;
293
294         req = tevent_req_create(mem_ctx, &state, struct test4_wait_state);
295         if (req == NULL) {
296                 return NULL;
297         }
298
299         subreq = tevent_wakeup_send(state, ev,
300                                     tevent_timeval_current_ofs(10,0));
301         if (tevent_req_nomem(subreq, req)) {
302                 return tevent_req_post(req, ev);
303         }
304         tevent_req_set_callback(subreq, test4_wait_done, req);
305
306         return req;
307 }
308
309 static void test4_wait_done(struct tevent_req *subreq)
310 {
311         struct tevent_req *req = tevent_req_callback_data(
312                 subreq, struct tevent_req);
313         bool status;
314
315         status = tevent_wakeup_recv(subreq);
316         TALLOC_FREE(subreq);
317
318         if (! status) {
319                 tevent_req_error(req, EIO);
320         } else {
321                 tevent_req_done(req);
322         }
323 }
324
325 static bool test4_wait_recv(struct tevent_req *req, int *perr)
326 {
327         int ret;
328
329         if (tevent_req_is_unix_error(req, &ret)) {
330                 if (perr != NULL) {
331                         *perr = ret;
332                 }
333                 return false;
334         }
335
336         return true;
337 }
338
339 static struct sock_daemon_funcs test4_funcs = {
340         .wait_send = test4_wait_send,
341         .wait_recv = test4_wait_recv,
342 };
343
344 static void test4(TALLOC_CTX *mem_ctx, const char *pidfile,
345                   const char *sockpath)
346 {
347         struct stat st;
348         pid_t pid, pid2;
349         int ret;
350
351         pid = fork();
352         assert(pid != -1);
353
354         if (pid == 0) {
355                 struct tevent_context *ev;
356                 struct sock_daemon_context *sockd;
357
358                 ev = tevent_context_init(mem_ctx);
359                 assert(ev != NULL);
360
361                 ret = sock_daemon_setup(mem_ctx, "test4", "file:", "NOTICE",
362                                         pidfile, &test4_funcs, NULL, &sockd);
363                 assert(ret == 0);
364
365                 ret = sock_daemon_run(ev, sockd, -1);
366                 assert(ret == 0);
367
368                 exit(0);
369         }
370
371         pid2 = waitpid(pid, &ret, 0);
372         assert(pid2 == pid);
373         assert(WEXITSTATUS(ret) == 0);
374
375         ret = stat(pidfile, &st);
376         assert(ret == -1);
377
378         ret = stat(sockpath, &st);
379         assert(ret == -1);
380 }
381
382 /*
383  * test5
384  *
385  * Start daemon, multiple client connects, requests, disconnects
386  */
387
388 #define TEST5_MAX_CLIENTS       10
389
390 struct test5_pkt {
391         uint32_t len;
392         int data;
393 };
394
395 struct test5_client_state {
396         int id;
397         int fd;
398         bool done;
399 };
400
401 static void test5_client_callback(uint8_t *buf, size_t buflen,
402                                   void *private_data)
403 {
404         struct test5_client_state *state =
405                 (struct test5_client_state *)private_data;
406         struct test5_pkt *pkt;
407         ssize_t n;
408         int ret;
409
410         if (buf == NULL) {
411                 assert(buflen == 0);
412
413                 ret = 0;
414         } else {
415                 assert(buflen == sizeof(struct test5_pkt));
416                 pkt = (struct test5_pkt *)buf;
417                 assert(pkt->len == sizeof(struct test5_pkt));
418
419                 ret = pkt->data;
420         }
421
422         assert(state->fd != -1);
423
424         n = write(state->fd, (void *)&ret, sizeof(int));
425         assert(n == sizeof(int));
426
427         state->done = true;
428 }
429
430 static int test5_client(const char *sockpath, int id)
431 {
432         pid_t pid;
433         int fd[2];
434         int ret;
435         ssize_t n;
436
437         ret = pipe(fd);
438         assert(ret == 0);
439
440         pid = fork();
441         assert(pid != -1);
442
443         if (pid == 0) {
444                 struct tevent_context *ev;
445                 struct test5_client_state state;
446                 struct sock_queue *queue;
447                 struct test5_pkt pkt;
448                 int conn;
449
450                 close(fd[0]);
451
452                 ev = tevent_context_init(NULL);
453                 assert(ev != NULL);
454
455                 conn = sock_connect(sockpath);
456                 assert(conn != -1);
457
458                 state.id = id;
459                 state.fd = fd[1];
460                 state.done = false;
461
462                 queue = sock_queue_setup(ev, ev, conn,
463                                          test5_client_callback, &state);
464                 assert(queue != NULL);
465
466                 pkt.len = 8;
467                 pkt.data = 0xbaba;
468
469                 ret = sock_queue_write(queue, (uint8_t *)&pkt,
470                                        sizeof(struct test5_pkt));
471                 assert(ret == 0);
472
473                 while (! state.done) {
474                         tevent_loop_once(ev);
475                 }
476
477                 close(fd[0]);
478                 state.fd = -1;
479
480                 sleep(10);
481                 exit(0);
482         }
483
484         close(fd[1]);
485
486         ret = 0;
487         n = read(fd[0], &ret, sizeof(ret));
488         if (n == 0) {
489                 fprintf(stderr, "client id %d read 0 bytes\n", id);
490         }
491         assert(n == 0 || n == sizeof(ret));
492
493         close(fd[0]);
494
495         return ret;
496 }
497
498 struct test5_server_state {
499         int num_clients;
500 };
501
502 static bool test5_connect(struct sock_client_context *client,
503                           void *private_data)
504 {
505         struct test5_server_state *state =
506                 (struct test5_server_state *)private_data;
507
508         if (state->num_clients == TEST5_MAX_CLIENTS) {
509                 return false;
510         }
511
512         state->num_clients += 1;
513         assert(state->num_clients <= TEST5_MAX_CLIENTS);
514         return true;
515 }
516
517 static void test5_disconnect(struct sock_client_context *client,
518                              void *private_data)
519 {
520         struct test5_server_state *state =
521                 (struct test5_server_state *)private_data;
522
523         state->num_clients -= 1;
524         assert(state->num_clients >= 0);
525 }
526
527 struct test5_read_state {
528         struct test5_pkt reply;
529 };
530
531 static void test5_read_done(struct tevent_req *subreq);
532
533 static struct tevent_req *test5_read_send(TALLOC_CTX *mem_ctx,
534                                           struct tevent_context *ev,
535                                           struct sock_client_context *client,
536                                           uint8_t *buf, size_t buflen,
537                                           void *private_data)
538 {
539         struct test5_server_state *server_state =
540                 (struct test5_server_state *)private_data;
541         struct tevent_req *req, *subreq;
542         struct test5_read_state *state;
543         struct test5_pkt *pkt;
544
545         req = tevent_req_create(mem_ctx, &state, struct test5_read_state);
546         assert(req != NULL);
547
548         assert(buflen == sizeof(struct test5_pkt));
549
550         pkt = (struct test5_pkt *)buf;
551         assert(pkt->data == 0xbaba);
552
553         state->reply.len = sizeof(struct test5_pkt);
554         state->reply.data = server_state->num_clients;
555
556         subreq = sock_socket_write_send(state, ev, client,
557                                         (uint8_t *)&state->reply,
558                                         state->reply.len);
559         assert(subreq != NULL);
560
561         tevent_req_set_callback(subreq, test5_read_done, req);
562
563         return req;
564 }
565
566 static void test5_read_done(struct tevent_req *subreq)
567 {
568         struct tevent_req *req = tevent_req_callback_data(
569                 subreq, struct tevent_req);
570         int ret;
571         bool status;
572
573         status = sock_socket_write_recv(subreq, &ret);
574         TALLOC_FREE(subreq);
575         if (! status) {
576                 tevent_req_error(req, ret);
577                 return;
578         }
579
580         tevent_req_done(req);
581 }
582
583 static bool test5_read_recv(struct tevent_req *req, int *perr)
584 {
585         int ret;
586
587         if (tevent_req_is_unix_error(req, &ret)) {
588                 if (perr != NULL) {
589                         *perr = ret;
590                 }
591                 return false;
592         }
593
594         return true;
595 }
596
597 static struct sock_socket_funcs test5_client_funcs = {
598         .connect = test5_connect,
599         .disconnect = test5_disconnect,
600         .read_send = test5_read_send,
601         .read_recv = test5_read_recv,
602 };
603
604 static void test5_startup(void *private_data)
605 {
606         int fd = *(int *)private_data;
607         int ret = 1;
608         ssize_t nwritten;
609
610         nwritten = write(fd, &ret, sizeof(ret));
611         assert(nwritten == sizeof(ret));
612         close(fd);
613 }
614
615 static struct sock_daemon_funcs test5_funcs = {
616         .startup = test5_startup,
617 };
618
619 static void test5(TALLOC_CTX *mem_ctx, const char *pidfile,
620                   const char *sockpath)
621 {
622         pid_t pid_server, pid;
623         int fd[2], ret, i;
624         ssize_t n;
625
626         pid = getpid();
627
628         ret = pipe(fd);
629         assert(ret == 0);
630
631         pid_server = fork();
632         assert(pid_server != -1);
633
634         if (pid_server == 0) {
635                 struct tevent_context *ev;
636                 struct sock_daemon_context *sockd;
637                 struct test5_server_state state;
638
639                 close(fd[0]);
640
641                 ev = tevent_context_init(mem_ctx);
642                 assert(ev != NULL);
643
644                 ret = sock_daemon_setup(mem_ctx, "test5", "file:", "NOTICE",
645                                         pidfile, &test5_funcs, &fd[1], &sockd);
646                 assert(ret == 0);
647
648                 state.num_clients = 0;
649
650                 ret = sock_daemon_add_unix(sockd, sockpath,
651                                            &test5_client_funcs, &state);
652                 assert(ret == 0);
653
654                 ret = sock_daemon_run(ev, sockd, pid);
655                 assert(ret == EINTR);
656
657                 exit(0);
658         }
659
660         close(fd[1]);
661
662         n = read(fd[0], &ret, sizeof(ret));
663         assert(n == sizeof(ret));
664         assert(ret == 1);
665
666         close(fd[0]);
667
668         for (i=0; i<100; i++) {
669                 ret = test5_client(sockpath, i);
670                 if (i < TEST5_MAX_CLIENTS) {
671                         assert(ret == i+1);
672                 } else {
673                         assert(ret == 0);
674                 }
675         }
676
677         for (i=0; i<100; i++) {
678                 pid = wait(&ret);
679                 assert(pid != -1);
680         }
681
682         ret = kill(pid_server, SIGTERM);
683         assert(ret == 0);
684 }
685
686 /*
687  * test6
688  *
689  * Start daemon, test client connects, requests, replies, disconnects
690  */
691
692 struct test6_pkt {
693         uint32_t len;
694         uint32_t data;
695 };
696
697 struct test6_client_state {
698         bool done;
699 };
700
701 static void test6_client_callback(uint8_t *buf, size_t buflen,
702                                   void *private_data)
703 {
704         struct test6_client_state *state =
705                 (struct test6_client_state *)private_data;
706         struct test6_pkt *pkt;
707
708         assert(buflen == sizeof(struct test6_pkt));
709         pkt = (struct test6_pkt *)buf;
710         assert(pkt->len == sizeof(struct test6_pkt));
711         assert(pkt->data == 0xffeeddcc);
712
713         state->done = true;
714 }
715
716 static void test6_client(const char *sockpath)
717 {
718         struct tevent_context *ev;
719         struct test6_client_state state;
720         struct sock_queue *queue;
721         struct test6_pkt pkt;
722         int conn, ret;
723
724         ev = tevent_context_init(NULL);
725         assert(ev != NULL);
726
727         conn = sock_connect(sockpath);
728         assert(conn != -1);
729
730         state.done = false;
731
732         queue = sock_queue_setup(ev, ev, conn,
733                                  test6_client_callback, &state);
734         assert(queue != NULL);
735
736         pkt.len = 8;
737         pkt.data = 0xaabbccdd;
738
739         ret = sock_queue_write(queue, (uint8_t *)&pkt,
740                                sizeof(struct test6_pkt));
741         assert(ret == 0);
742
743         while (! state.done) {
744                 tevent_loop_once(ev);
745         }
746
747         talloc_free(ev);
748 }
749
750 struct test6_server_state {
751         struct sock_daemon_context *sockd;
752         int fd, done;
753 };
754
755 struct test6_read_state {
756         struct test6_server_state *server_state;
757         struct test6_pkt reply;
758 };
759
760 static void test6_read_done(struct tevent_req *subreq);
761
762 static struct tevent_req *test6_read_send(TALLOC_CTX *mem_ctx,
763                                           struct tevent_context *ev,
764                                           struct sock_client_context *client,
765                                           uint8_t *buf, size_t buflen,
766                                           void *private_data)
767 {
768         struct test6_server_state *server_state =
769                 (struct test6_server_state *)private_data;
770         struct tevent_req *req, *subreq;
771         struct test6_read_state *state;
772         struct test6_pkt *pkt;
773
774         req = tevent_req_create(mem_ctx, &state, struct test6_read_state);
775         assert(req != NULL);
776
777         state->server_state = server_state;
778
779         assert(buflen == sizeof(struct test6_pkt));
780
781         pkt = (struct test6_pkt *)buf;
782         assert(pkt->data == 0xaabbccdd);
783
784         state->reply.len = sizeof(struct test6_pkt);
785         state->reply.data = 0xffeeddcc;
786
787         subreq = sock_socket_write_send(state, ev, client,
788                                         (uint8_t *)&state->reply,
789                                         state->reply.len);
790         assert(subreq != NULL);
791
792         tevent_req_set_callback(subreq, test6_read_done, req);
793
794         return req;
795 }
796
797 static void test6_read_done(struct tevent_req *subreq)
798 {
799         struct tevent_req *req = tevent_req_callback_data(
800                 subreq, struct tevent_req);
801         struct test6_read_state *state = tevent_req_data(
802                 req, struct test6_read_state);
803         int ret;
804         bool status;
805
806         status = sock_socket_write_recv(subreq, &ret);
807         TALLOC_FREE(subreq);
808         if (! status) {
809                 tevent_req_error(req, ret);
810                 return;
811         }
812
813         state->server_state->done = 1;
814         tevent_req_done(req);
815 }
816
817 static bool test6_read_recv(struct tevent_req *req, int *perr)
818 {
819         int ret;
820
821         if (tevent_req_is_unix_error(req, &ret)) {
822                 if (perr != NULL) {
823                         *perr = ret;
824                 }
825                 return false;
826         }
827
828         return true;
829 }
830
831 static struct sock_socket_funcs test6_client_funcs = {
832         .read_send = test6_read_send,
833         .read_recv = test6_read_recv,
834 };
835
836 static void test6_startup(void *private_data)
837 {
838         struct test6_server_state *server_state =
839                 (struct test6_server_state *)private_data;
840         int ret = 1;
841         ssize_t nwritten;
842
843         nwritten = write(server_state->fd, &ret, sizeof(ret));
844         assert(nwritten == sizeof(ret));
845         close(server_state->fd);
846         server_state->fd = -1;
847 }
848
849 struct test6_wait_state {
850         struct test6_server_state *server_state;
851 };
852
853 static void test6_wait_done(struct tevent_req *subreq);
854
855 static struct tevent_req *test6_wait_send(TALLOC_CTX *mem_ctx,
856                                           struct tevent_context *ev,
857                                           void *private_data)
858 {
859         struct tevent_req *req, *subreq;
860         struct test6_wait_state *state;
861
862         req = tevent_req_create(mem_ctx, &state, struct test6_wait_state);
863         if (req == NULL) {
864                 return NULL;
865         }
866
867         state->server_state = (struct test6_server_state *)private_data;
868
869         subreq = tevent_wakeup_send(state, ev,
870                                     tevent_timeval_current_ofs(10,0));
871         if (tevent_req_nomem(subreq, req)) {
872                 return tevent_req_post(req, ev);
873         }
874         tevent_req_set_callback(subreq, test6_wait_done, req);
875
876         return req;
877 }
878
879 static void test6_wait_done(struct tevent_req *subreq)
880 {
881         struct tevent_req *req = tevent_req_callback_data(
882                 subreq, struct tevent_req);
883         struct test6_wait_state *state = tevent_req_data(
884                 req, struct test6_wait_state);
885         bool status;
886
887         status = tevent_wakeup_recv(subreq);
888         TALLOC_FREE(subreq);
889         if (! status) {
890                 tevent_req_error(req, EIO);
891                 return;
892         }
893
894         if (state->server_state->done == 0) {
895                 tevent_req_error(req, EIO);
896                 return;
897         }
898
899         tevent_req_done(req);
900 }
901
902 static bool test6_wait_recv(struct tevent_req *req, int *perr)
903 {
904         int ret;
905
906         if (tevent_req_is_unix_error(req, &ret)) {
907                 if (perr != NULL) {
908                         *perr = ret;
909                 }
910                 return false;
911         }
912
913         return true;
914 }
915
916 static struct sock_daemon_funcs test6_funcs = {
917         .startup = test6_startup,
918         .wait_send = test6_wait_send,
919         .wait_recv = test6_wait_recv,
920 };
921
922 static void test6(TALLOC_CTX *mem_ctx, const char *pidfile,
923                   const char *sockpath)
924 {
925         pid_t pid_server, pid;
926         int fd[2], ret;
927         ssize_t n;
928
929         pid = getpid();
930
931         ret = pipe(fd);
932         assert(ret == 0);
933
934         pid_server = fork();
935         assert(pid_server != -1);
936
937         if (pid_server == 0) {
938                 struct tevent_context *ev;
939                 struct sock_daemon_context *sockd;
940                 struct test6_server_state server_state = { 0 };
941
942                 close(fd[0]);
943
944                 ev = tevent_context_init(mem_ctx);
945                 assert(ev != NULL);
946
947                 server_state.fd = fd[1];
948
949                 ret = sock_daemon_setup(mem_ctx, "test6", "file:", "NOTICE",
950                                         pidfile, &test6_funcs, &server_state,
951                                         &sockd);
952                 assert(ret == 0);
953
954                 server_state.sockd = sockd;
955                 server_state.done = 0;
956
957                 ret = sock_daemon_add_unix(sockd, sockpath,
958                                            &test6_client_funcs, &server_state);
959                 assert(ret == 0);
960
961                 ret = sock_daemon_run(ev, sockd, pid);
962                 assert(ret == 0);
963
964                 exit(0);
965         }
966
967         close(fd[1]);
968
969         n = read(fd[0], &ret, sizeof(ret));
970         assert(n == sizeof(ret));
971         assert(ret == 1);
972
973         close(fd[0]);
974
975         test6_client(sockpath);
976
977         pid = wait(&ret);
978         assert(pid != -1);
979 }
980
981 int main(int argc, const char **argv)
982 {
983         TALLOC_CTX *mem_ctx;
984         const char *pidfile, *sockpath;
985         int num;
986
987         if (argc != 4) {
988                 fprintf(stderr, "%s <pidfile> <sockpath> <testnum>\n", argv[0]);
989                 exit(1);
990         }
991
992         pidfile = argv[1];
993         sockpath = argv[2];
994         num = atoi(argv[3]);
995
996         mem_ctx = talloc_new(NULL);
997         assert(mem_ctx != NULL);
998
999         switch (num) {
1000         case 1:
1001                 test1(mem_ctx, pidfile, sockpath);
1002                 break;
1003
1004         case 2:
1005                 test2(mem_ctx, pidfile, sockpath);
1006                 break;
1007
1008         case 3:
1009                 test3(mem_ctx, pidfile, sockpath);
1010                 break;
1011
1012         case 4:
1013                 test4(mem_ctx, pidfile, sockpath);
1014                 break;
1015
1016         case 5:
1017                 test5(mem_ctx, pidfile, sockpath);
1018                 break;
1019
1020         case 6:
1021                 test6(mem_ctx, pidfile, sockpath);
1022                 break;
1023
1024         default:
1025                 fprintf(stderr, "Unknown test number %d\n", num);
1026         }
1027
1028         return 0;
1029 }