read_write_all: use calloc instead of huge stack var in tests.
[ccan] / ccan / read_write_all / test / run-read_all.c
1 /* FIXME: Do something tricky to ensure we really do loop in read_all. */
2
3 #include <ccan/read_write_all/read_write_all.h>
4 #include <ccan/read_write_all/read_write_all.c>
5 #include <ccan/tap/tap.h>
6 #include <unistd.h>
7 #include <sys/types.h>
8 #include <signal.h>
9 #include <sys/wait.h>
10 #include <limits.h>
11 #include <err.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 static volatile int sigcount;
16 static int p2c[2], c2p[2];
17 static void got_signal(int sig)
18 {
19         char c = 0;
20         if (write(p2c[1], &c, 1) == 1)
21                 sigcount++;
22 }
23
24 /* < PIPE_BUF *will* be atomic.  But > PIPE_BUF only *might* be non-atomic. */
25 #define BUFSZ (1024*1024)
26
27 int main(int argc, char *argv[])
28 {
29         char *buffer;
30         char c = 0;
31         int status;
32         pid_t child;
33
34         buffer = calloc(BUFSZ, 2);
35         plan_tests(6);
36
37         /* We fork and torture parent. */
38         if (pipe(p2c) != 0 || pipe(c2p) != 0)
39                 err(1, "pipe");
40         child = fork();
41
42         if (!child) {
43                 close(p2c[1]);
44                 close(c2p[0]);
45                 /* Child.  Make sure parent ready, then write in two parts. */
46                 if (read(p2c[0], &c, 1) != 1)
47                         exit(1);
48                 memset(buffer, 0xff, BUFSZ*2);
49                 if (!write_all(c2p[1], buffer, BUFSZ))
50                         exit(2);
51                 if (kill(getppid(), SIGUSR1) != 0)
52                         exit(3);
53                 /* Make sure they get signal. */
54                 if (read(p2c[0], &c, 1) != 1)
55                         exit(4);
56                 if (write(c2p[1], buffer, BUFSZ) != BUFSZ)
57                         exit(5);
58                 exit(0);
59         }
60         if (child == -1)
61                 err(1, "forking");
62
63         close(p2c[0]);
64         close(c2p[1]);
65         signal(SIGUSR1, got_signal);
66         ok1(write(p2c[1], &c, 1) == 1);
67         ok1(read_all(c2p[0], buffer, BUFSZ*2));
68         ok1(memchr(buffer, 0, BUFSZ*2) == NULL);
69         ok1(sigcount == 1);
70         ok1(wait(&status) == child);
71         ok(WIFEXITED(status) && WEXITSTATUS(status) == 0,
72            "WIFEXITED(status) = %u, WEXITSTATUS(status) = %u",
73            WIFEXITED(status), WEXITSTATUS(status));
74         return exit_status();
75 }