ccan/io: initialize connection with an explicit I/O plan.
[ccan] / ccan / io / test / run-10-many.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 #define NUM 100
10 #define NUM_ITERS 1000
11
12 struct buffer {
13         int iters;
14         struct io_conn *reader, *writer;
15         char buf[32];
16 };
17
18 static struct io_plan poke_reader(struct io_conn *conn, struct buffer *buf);
19
20 static struct io_plan poke_writer(struct io_conn *conn, struct buffer *buf)
21 {
22         assert(conn == buf->reader);
23
24         if (buf->iters == NUM_ITERS)
25                 return io_close(conn, NULL);
26
27         /* You write. */
28         io_wake(buf->writer,
29                 io_write(&buf->buf, sizeof(buf->buf), poke_reader, buf));
30
31         /* I'll wait until you wake me. */
32         return io_idle();
33 }
34
35 static struct io_plan poke_reader(struct io_conn *conn, struct buffer *buf)
36 {
37         assert(conn == buf->writer);
38         /* You read. */
39         io_wake(buf->reader,
40                 io_read(&buf->buf, sizeof(buf->buf), poke_writer, buf));
41
42         if (++buf->iters == NUM_ITERS)
43                 return io_close(conn, NULL);
44
45         /* I'll wait until you tell me to write. */
46         return io_idle();
47 }
48
49 static struct buffer buf[NUM];
50
51 int main(void)
52 {
53         unsigned int i;
54         int fds[2], last_read, last_write;
55
56         plan_tests(5 + NUM);
57
58         ok1(pipe(fds) == 0);
59         last_read = fds[0];
60         last_write = fds[1];
61
62         for (i = 1; i < NUM; i++) {
63                 if (pipe(fds) < 0)
64                         break;
65                 memset(buf[i].buf, i, sizeof(buf[i].buf));
66                 sprintf(buf[i].buf, "%i-%i", i, i);
67
68                 /* Wait for writer to tell us to read. */
69                 buf[i].reader = io_new_conn(last_read, io_idle(), NULL, &buf[i]);
70                 if (!buf[i].reader)
71                         break;
72                 buf[i].writer = io_new_conn(fds[1],
73                                             io_write(&buf[i].buf,
74                                                      sizeof(buf[i].buf),
75                                                      poke_reader, &buf[i]),
76                                             NULL, &buf[i]);
77                 if (!buf[i].writer)
78                         break;
79                 last_read = fds[0];
80         }
81         if (!ok1(i == NUM))
82                 exit(exit_status());
83
84         /* Last one completes the cirle. */
85         i = 0;
86         sprintf(buf[i].buf, "%i-%i", i, i);
87         buf[i].reader = io_new_conn(last_read, io_idle(), NULL, NULL);
88         ok1(buf[i].reader);
89         buf[i].writer = io_new_conn(last_write,
90                                     io_write(&buf[i].buf, sizeof(buf[i].buf),
91                                              poke_reader, &buf[i]),
92                                     NULL, NULL);
93         ok1(buf[i].writer);
94
95         /* They should eventually exit */
96         ok1(io_loop() == NULL);
97
98         for (i = 0; i < NUM; i++) {
99                 char b[sizeof(buf[0].buf)];
100                 memset(b, i, sizeof(b));
101                 sprintf(b, "%i-%i", i, i);
102                 ok1(memcmp(b, buf[(i + NUM_ITERS) % NUM].buf, sizeof(b)) == 0);
103         }
104
105         /* This exits depending on whether all tests passed */
106         return exit_status();
107 }