45b96ab2f03b2d5d2145f9cdc6a3ae990778b528
[ccan] / ccan / pipecmd / test / run.c
1 #include <ccan/pipecmd/pipecmd.h>
2 /* Include the C files directly. */
3 #include <ccan/pipecmd/pipecmd.c>
4 #include <ccan/tap/tap.h>
5 #include <string.h>
6 #include <sys/types.h>
7 #include <sys/wait.h>
8
9 int main(int argc, char *argv[])
10 {
11         pid_t child;
12         int infd, outfd, errfd, status;
13         char buf[5] = "test";
14
15         /* We call ourselves, to test pipe. */
16         if (argc == 2) {
17                 if (strcmp(argv[1], "out") == 0) {
18                         if (write(STDOUT_FILENO, buf, sizeof(buf)) != sizeof(buf))
19                                 exit(1);
20                 } else if (strcmp(argv[1], "in") == 0) {
21                         if (read(STDIN_FILENO, buf, sizeof(buf)) != sizeof(buf))
22                                 exit(1);
23                         if (memcmp(buf, "test", sizeof(buf)) != 0)
24                                 exit(1);
25                 } else if (strcmp(argv[1], "inout") == 0) {
26                         if (read(STDIN_FILENO, buf, sizeof(buf)) != sizeof(buf))
27                                 exit(1);
28                         buf[0]++;
29                         if (write(STDOUT_FILENO, buf, sizeof(buf)) != sizeof(buf))
30                                 exit(1);
31                 } else if (strcmp(argv[1], "err") == 0) {
32                         if (write(STDERR_FILENO, buf, sizeof(buf)) != sizeof(buf))
33                                 exit(1);
34                 } else
35                         abort();
36                 exit(0);
37         }
38
39         /* We assume no fd leaks, so close them now. */
40         close(3);
41         close(4);
42         close(5);
43         close(6);
44         close(7);
45         close(8);
46         close(9);
47         close(10);
48         
49         /* This is how many tests you plan to run */
50         plan_tests(67);
51         child = pipecmd(&outfd, &infd, &errfd, argv[0], "inout", NULL);
52         if (!ok1(child > 0))
53                 exit(1);
54         ok1(write(infd, buf, sizeof(buf)) == sizeof(buf));
55         ok1(read(outfd, buf, sizeof(buf)) == sizeof(buf));
56         ok1(read(errfd, buf, sizeof(buf)) == 0);
57         ok1(close(infd) == 0);
58         ok1(close(outfd) == 0);
59         ok1(close(errfd) == 0);
60         buf[0]--;
61         ok1(memcmp(buf, "test", sizeof(buf)) == 0);
62         ok1(waitpid(child, &status, 0) == child);
63         ok1(WIFEXITED(status));
64         ok1(WEXITSTATUS(status) == 0);
65
66         child = pipecmd(NULL, &infd, NULL, argv[0], "in", NULL);
67         if (!ok1(child > 0))
68                 exit(1);
69         ok1(write(infd, buf, sizeof(buf)) == sizeof(buf));
70         ok1(close(infd) == 0);
71         ok1(waitpid(child, &status, 0) == child);
72         ok1(WIFEXITED(status));
73         ok1(WEXITSTATUS(status) == 0);
74
75         child = pipecmd(&outfd, NULL, NULL, argv[0], "out", NULL);
76         if (!ok1(child > 0))
77                 exit(1);
78         ok1(read(outfd, buf, sizeof(buf)) == sizeof(buf));
79         ok1(close(outfd) == 0);
80         ok1(memcmp(buf, "test", sizeof(buf)) == 0);
81         ok1(waitpid(child, &status, 0) == child);
82         ok1(WIFEXITED(status));
83         ok1(WEXITSTATUS(status) == 0);
84
85         /* Errfd only should be fine. */
86         child = pipecmd(NULL, NULL, &errfd, argv[0], "err", NULL);
87         if (!ok1(child > 0))
88                 exit(1);
89         ok1(read(errfd, buf, sizeof(buf)) == sizeof(buf));
90         ok1(close(errfd) == 0);
91         ok1(memcmp(buf, "test", sizeof(buf)) == 0);
92         ok1(waitpid(child, &status, 0) == child);
93         ok1(WIFEXITED(status));
94         ok1(WEXITSTATUS(status) == 0);
95
96         /* errfd == outfd should work with both. */
97         child = pipecmd(&errfd, NULL, &errfd, argv[0], "err", NULL);
98         if (!ok1(child > 0))
99                 exit(1);
100         ok1(read(errfd, buf, sizeof(buf)) == sizeof(buf));
101         ok1(close(errfd) == 0);
102         ok1(memcmp(buf, "test", sizeof(buf)) == 0);
103         ok1(waitpid(child, &status, 0) == child);
104         ok1(WIFEXITED(status));
105         ok1(WEXITSTATUS(status) == 0);
106
107         child = pipecmd(&outfd, NULL, &outfd, argv[0], "out", NULL);
108         if (!ok1(child > 0))
109                 exit(1);
110         ok1(read(outfd, buf, sizeof(buf)) == sizeof(buf));
111         ok1(close(outfd) == 0);
112         ok1(memcmp(buf, "test", sizeof(buf)) == 0);
113         ok1(waitpid(child, &status, 0) == child);
114         ok1(WIFEXITED(status));
115         ok1(WEXITSTATUS(status) == 0);
116
117         // Writing to /dev/null should be fine.
118         child = pipecmd(NULL, NULL, NULL, argv[0], "out", NULL);
119         if (!ok1(child > 0))
120                 exit(1);
121         ok1(waitpid(child, &status, 0) == child);
122         ok1(WIFEXITED(status));
123         ok1(WEXITSTATUS(status) == 0);
124
125         // Reading should fail.
126         child = pipecmd(NULL, NULL, NULL, argv[0], "in", NULL);
127         if (!ok1(child > 0))
128                 exit(1);
129         ok1(waitpid(child, &status, 0) == child);
130         ok1(WIFEXITED(status));
131         ok1(WEXITSTATUS(status) == 1);
132
133         child = pipecmd(NULL, NULL, NULL, argv[0], "err", NULL);
134         if (!ok1(child > 0))
135                 exit(1);
136         ok1(waitpid(child, &status, 0) == child);
137         ok1(WIFEXITED(status));
138         ok1(WEXITSTATUS(status) == 0);
139
140         // Can't run non-existent file, but errno set correctly.
141         child = pipecmd(NULL, NULL, NULL, "/doesnotexist", "in", NULL);
142         ok1(errno == ENOENT);
143         ok1(child < 0);
144
145         /* No fd leaks! */
146         ok1(close(3) == -1 && errno == EBADF);
147         ok1(close(4) == -1 && errno == EBADF);
148         ok1(close(5) == -1 && errno == EBADF);
149         ok1(close(6) == -1 && errno == EBADF);
150         ok1(close(7) == -1 && errno == EBADF);
151         ok1(close(8) == -1 && errno == EBADF);
152         ok1(close(9) == -1 && errno == EBADF);
153         ok1(close(10) == -1 && errno == EBADF);
154
155         /* This exits depending on whether all tests passed */
156         return exit_status();
157 }