]> git.ozlabs.org Git - ccan/blob - ccan/io/test/run-12-bidir.c
io: fix maybe-uninitialized warning in test (-O2)
[ccan] / ccan / io / test / run-12-bidir.c
1 #include <ccan/io/io.h>
2 /* Include the C files directly. */
3 #include <ccan/io/poll.c>
4 #include <ccan/io/io.c>
5 #include <ccan/tap/tap.h>
6 #include <sys/wait.h>
7 #include <stdio.h>
8
9 #ifdef DEBUG_CONN
10 #define PORT "64012"
11 #else
12 #define PORT "65012"
13 #endif
14
15 struct data {
16         struct io_listener *l;
17         int state;
18         char buf[4];
19         char wbuf[32];
20 };
21
22 static void finish_ok(struct io_conn *conn, struct data *d)
23 {
24         d->state++;
25 }
26
27 static struct io_plan *r_done(struct io_conn *conn, struct data *d)
28 {
29         d->state++;
30         if (d->state == 3)
31                 return io_close(conn);
32         return io_wait(conn, NULL, io_never, NULL);
33 }
34
35 static struct io_plan *w_done(struct io_conn *conn, struct data *d)
36 {
37         d->state++;
38         if (d->state == 3)
39                 return io_close(conn);
40         return io_out_wait(conn, NULL, io_never, NULL);
41 }
42
43 static struct io_plan *init_conn(struct io_conn *conn, struct data *d)
44 {
45 #ifdef DEBUG_CONN
46         io_set_debug(conn, true);
47 #endif
48         ok1(d->state == 0);
49         d->state++;
50
51         io_close_listener(d->l);
52
53         memset(d->wbuf, 7, sizeof(d->wbuf));
54         io_set_finish(conn, finish_ok, d);
55
56         return io_duplex(conn,
57                          io_read(conn, d->buf, sizeof(d->buf), r_done, d),
58                          io_write(conn, d->wbuf, sizeof(d->wbuf), w_done, d));
59 }
60
61 static int make_listen_fd(const char *port, struct addrinfo **info)
62 {
63         int fd, on = 1;
64         struct addrinfo *addrinfo, hints;
65
66         memset(&hints, 0, sizeof(hints));
67         hints.ai_family = AF_UNSPEC;
68         hints.ai_socktype = SOCK_STREAM;
69         hints.ai_flags = AI_PASSIVE;
70         hints.ai_protocol = 0;
71
72         if (getaddrinfo(NULL, port, &hints, &addrinfo) != 0)
73                 return -1;
74
75         fd = socket(addrinfo->ai_family, addrinfo->ai_socktype,
76                     addrinfo->ai_protocol);
77         if (fd < 0)
78                 return -1;
79
80         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
81         if (bind(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0) {
82                 close(fd);
83                 return -1;
84         }
85         if (listen(fd, 1) != 0) {
86                 close(fd);
87                 return -1;
88         }
89         *info = addrinfo;
90         return fd;
91 }
92
93 int main(void)
94 {
95         struct data *d = malloc(sizeof(*d));
96         struct addrinfo *addrinfo;
97         int fd, status;
98
99         /* This is how many tests you plan to run */
100         plan_tests(9);
101         d->state = 0;
102         fd = make_listen_fd(PORT, &addrinfo);
103         ok1(fd >= 0);
104         d->l = io_new_listener(NULL, fd, init_conn, d);
105         ok1(d->l);
106         fflush(stdout);
107         if (!fork()) {
108                 int i;
109                 char buf[32];
110
111                 io_close_listener(d->l);
112                 free(d);
113                 fd = socket(addrinfo->ai_family, addrinfo->ai_socktype,
114                             addrinfo->ai_protocol);
115                 if (fd < 0)
116                         exit(1);
117                 if (connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0)
118                         exit(2);
119                 signal(SIGPIPE, SIG_IGN);
120                 for (i = 0; i < 32; i++) {
121                         if (read(fd, buf+i, 1) != 1)
122                                 break;
123                 }
124                 for (i = 0; i < strlen("hellothere"); i++) {
125                         if (write(fd, "hellothere" + i, 1) != 1)
126                                 break;
127                 }
128                 close(fd);
129                 freeaddrinfo(addrinfo);
130                 exit(0);
131         }
132         freeaddrinfo(addrinfo);
133         ok1(io_loop(NULL, NULL) == NULL);
134         ok1(d->state == 4);
135         ok1(memcmp(d->buf, "hellothere", sizeof(d->buf)) == 0);
136         free(d);
137
138         ok1(wait(&status));
139         ok1(WIFEXITED(status));
140         ok1(WEXITSTATUS(status) == 0);
141
142         /* This exits depending on whether all tests passed */
143         return exit_status();
144 }