]> git.ozlabs.org Git - ccan-lca-2011.git/blob - ccan/oserver/test/run.c
lca2011: make our server parrot the last answer it got.
[ccan-lca-2011.git] / ccan / oserver / test / run.c
1 #include <ccan/oserver/oserver.c>
2 #include <ccan/oserver/oserver.h>
3 #include <ccan/str/str.h>
4 #include <ccan/tap/tap.h>
5 #include <sys/types.h>
6 #include <sys/select.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <string.h>
10
11 static void exit_quietly(struct tevent_context *ev,
12                          struct tevent_fd *fde, uint16_t flags, void *unused)
13 {
14         talloc_free(ev);
15         exit(0);
16 }
17
18 static void run_server(int readyfd, int exitfd)
19 {
20         struct tevent_context *ev = tevent_context_init(NULL);
21
22         if (oserver_setup(ev, OSERVER_PORT) == NULL)
23                 exit(1);
24
25         tevent_add_fd(ev, ev, exitfd, TEVENT_FD_READ, exit_quietly, NULL);
26         /* Tell parent we are ready to go. */
27         write(readyfd, "", 1);
28
29         while (tevent_loop_wait(ev) == 0);
30 }       
31
32 static bool write_sall(int fd, const char *str)
33 {
34         while (str[0]) {
35                 ssize_t len = write(fd, str, strlen(str));
36                 if (len < 0)
37                         return false;
38                 str += len;
39         }
40         return true;
41 }
42
43 static bool input_is(int fd, const char *str)
44 {
45         while (str[0]) {
46                 char buffer[1000];
47                 ssize_t len = read(fd, buffer, strlen(str));
48                 if (len < 0)
49                         return false;
50                 if (strncmp(str, buffer, len) != 0)
51                         return false;
52                 str += len;
53         }
54         return true;
55 }
56
57 static bool no_input(int fd)
58 {
59         fd_set set;
60         struct timeval t = { 0, 0 };
61
62         FD_ZERO(&set);
63         FD_SET(fd, &set);
64         return (select(fd+1, &set, NULL, NULL, &t) == 0);
65 }
66
67 int main(int argc, char *argv[])
68 {
69         int readyfd[2], exitfd[2];
70         union {
71                 struct sockaddr addr;
72                 struct sockaddr_in in;
73         } u;
74         int sfd1, sfd2;
75         char c;
76
77         /* This is how many tests you plan to run */
78         plan_tests(15);
79
80         pipe(readyfd);
81         pipe(exitfd);
82         if (fork() == 0) {
83                 close(exitfd[1]);
84                 close(readyfd[0]);
85                 run_server(readyfd[1], exitfd[0]);
86                 err(1, "Event loop failed");
87         }
88         close(exitfd[0]);
89         close(readyfd[1]);
90
91         sfd1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
92         sfd2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
93
94         u.in.sin_family = AF_INET;
95         u.in.sin_port = htons(OSERVER_PORT);
96         u.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
97
98         /* Wait until child is ready... */
99         if (read(readyfd[0], &c, 1) != 1)
100                 errx(1, "Child problems");
101
102         /* Go! */
103         ok1(connect(sfd1, &u.addr, sizeof(u.in)) == 0);
104         ok1(connect(sfd2, &u.addr, sizeof(u.in)) == 0);
105
106         ok1(input_is(sfd1, "Welcome.  Please ask your question.\n"));
107         ok1(input_is(sfd2, "Welcome.  Please ask your question.\n"));
108
109         ok1(write_sall(sfd1, "question"));
110         ok1(write_sall(sfd2, "question"));
111         /* It shouldn't say anything until we've finished! */
112         ok1(no_input(sfd1));
113         ok1(no_input(sfd2));
114
115         ok1(write_sall(sfd1, " 1\n"));
116         /* Make sure that arrives first! */
117         sleep(1);
118         ok1(write_sall(sfd2, " 2\n"));
119
120         ok1(input_is(sfd1, "I believe a better question is how many manly men mendaciously mention mending mansions?\n"));
121         ok1(input_is(sfd2, "I believe a better question is question 1\n"));
122
123         /* Sockets should be dead now. */
124         ok1(read(sfd1, &c, 1) == 0);
125         ok1(read(sfd2, &c, 1) == 0);
126
127         /* Shut down server. */
128         write(exitfd[1], "", 1);
129
130         /* This will close once it's shut down, and return. */
131         ok1(read(readyfd[0], &c, 1) == 0);
132
133         /* This exits depending on whether all tests passed */
134         return exit_status();
135 }