1 #include <ccan/oserver/oserver.c>
2 #include <ccan/oserver/oserver_cdump.c>
3 #include <ccan/oserver/oserver.h>
4 #include <ccan/str/str.h>
5 #include <ccan/tap/tap.h>
7 #include <sys/select.h>
13 static bool write_sall(int fd, const char *str)
16 ssize_t len = write(fd, str, strlen(str));
24 static bool input_is(int fd, const char *str)
28 ssize_t len = read(fd, buffer, strlen(str));
31 if (strncmp(str, buffer, len) != 0)
38 static void run_client(int readyfd, bool die)
42 struct sockaddr_in in;
44 int sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
47 u.in.sin_family = AF_INET;
48 u.in.sin_port = htons(OSERVER_PORT);
49 u.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
50 if (connect(sfd, &u.addr, sizeof(u.in)) != 0)
53 if (!input_is(sfd, "Welcome. Please ask your question.\n"))
57 if (!write_sall(sfd, "Question?\n"))
60 if (!input_is(sfd, "While the Oracle ponders, please answer the following question:\nQuestion?\n"))
67 if (!write_sall(sfd, "Answer?\n"))
70 /* Since other died, oracle won't say any more. */
75 static void set_flag(struct tevent_context *ev,
76 struct tevent_signal *se,
86 static unsigned int count_clients(struct oserver *oserver)
88 unsigned int i, count = 0;
90 for (i = 0; i < oserver->max_clients; i++) {
91 if (oserver->clients[i])
97 int main(int argc, char *argv[])
100 struct tevent_context *ev = tevent_context_init(NULL);
101 struct oserver *oserver;
105 /* This is how many tests you plan to run */
108 oserver = oserver_setup(ev, OSERVER_PORT, NULL, NULL);
110 err(1, "Failed to set up server");
112 tevent_add_signal(ev, ev, SIGCHLD, 0, set_flag, &done);
116 /* This child will exit, doesn't need fd. */
119 run_client(-1, true);
123 run_client(ready[0], false);
126 /* Wait for dead child to exit... */
128 tevent_loop_once(ev);
130 /* Wait for client to be freed. */
131 while (count_clients(oserver) == 2)
132 tevent_loop_once(ev);
134 /* One child should be dead... */
135 ok1(waitpid(-1, &status, 0) > 0);
137 /* Tell other child to write answer. */
138 write(ready[1], &status, 1);
141 tevent_loop_once(ev);
143 /* Other child should be hung... */
144 ok1(waitpid(-1, &status, WNOHANG) == 0);
147 return exit_status();