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