EPOLLRDHUP was introduced in Linux 2.6.17.
[beanstalkd.git] / integ-test.c
blob8b56d010f299435445bedbb7da73c9aa595ad436
1 #include <stdint.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <signal.h>
6 #include <sys/stat.h>
7 #include <sys/socket.h>
8 #include <netdb.h>
9 #include <netinet/ip.h>
10 #include <arpa/inet.h>
11 #include <fcntl.h>
12 #include <sys/wait.h>
13 #include <errno.h>
14 #include "ct/ct.h"
15 #include "dat.h"
17 static void testsrv(char*, char*, int);
18 static void forksrv(int*, int*);
19 static int copy(int, int, int);
20 static int diff(char*, int);
21 static int diallocal(int);
22 static void cleanup(int sig);
24 typedef struct T T;
25 struct T {
26 char *cmd;
27 char *exp;
30 static T ts[] = {
31 {"sh-tests/allow-underscore.commands", "sh-tests/allow-underscore.expected"},
32 {"sh-tests/delete_ready.commands", "sh-tests/delete_ready.expected"},
33 {"sh-tests/multi-tube.commands", "sh-tests/multi-tube.expected"},
34 {"sh-tests/no_negative_delays.commands", "sh-tests/no_negative_delays.expected"},
35 {"sh-tests/omit-time-left.commands", "sh-tests/omit-time-left.expected"},
36 {"sh-tests/pause-tube.commands", "sh-tests/pause-tube.expected"},
37 {"sh-tests/small_delay.commands", "sh-tests/small_delay.expected"},
38 {"sh-tests/stats_tube.commands", "sh-tests/stats_tube.expected"},
39 {"sh-tests/too-big.commands", "sh-tests/too-big.expected"},
40 {"sh-tests/ttr-large.commands", "sh-tests/ttr-large.expected"},
41 {"sh-tests/ttr-small.commands", "sh-tests/ttr-small.expected"},
42 {"sh-tests/zero_delay.commands", "sh-tests/zero_delay.expected"},
43 {},
46 static int srvpid;
49 void
50 cttestsrv()
52 int i;
54 for (i = 0; ts[i].cmd; i++) {
55 testsrv(ts[i].cmd, ts[i].exp, 4096);
56 testsrv(ts[i].cmd, ts[i].exp, 1);
61 static void
62 testsrv(char *cmd, char *exp, int bufsiz)
64 int diffst, srvst, port = 0, cfd, tfd, diffpid;
65 struct sigaction sa = {};
67 job_data_size_limit = 10;
69 progname = cmd;
70 puts(cmd);
71 forksrv(&port, &srvpid);
72 if (port == -1 || srvpid == -1) {
73 puts("forksrv failed");
74 exit(1);
77 // Fail if this test takes more than 10 seconds.
78 // If we have trouble installing the timeout,
79 // just proceed anyway.
80 sa.sa_handler = cleanup;
81 sigaction(SIGALRM, &sa, 0);
82 alarm(10);
84 cfd = diallocal(port);
85 if (cfd == -1) {
86 twarn("diallocal");
87 kill(srvpid, 9);
88 exit(1);
91 tfd = open(cmd, O_RDONLY, 0);
92 if (tfd == -1) {
93 twarn("open");
94 kill(srvpid, 9);
95 exit(1);
98 if (copy(cfd, tfd, bufsiz) == -1) {
99 twarn("copy");
100 kill(srvpid, 9);
101 exit(1);
104 diffpid = diff(exp, cfd);
105 if (diffpid == -1) {
106 twarn("diff");
107 kill(srvpid, 9);
108 exit(1);
111 waitpid(diffpid, &diffst, 0);
113 // wait until after diff has finished to kill srvpid
114 kill(srvpid, 9);
115 waitpid(srvpid, &srvst, 0);
116 assertf(WIFSIGNALED(srvst) && WTERMSIG(srvst) == 9,
117 "status %d, signal %d",
118 WEXITSTATUS(srvst),
119 WTERMSIG(srvst));
121 assertf(diffst == 0, "was %d", diffst);
125 static void
126 forksrv(int *port, int *pid)
128 int r, len;
129 Srv s = {};
130 struct sockaddr_in addr;
132 s.sock.fd = make_server_socket("127.0.0.1", "0");
133 if (s.sock.fd == -1) return;
135 len = sizeof(addr);
136 r = getsockname(s.sock.fd, (struct sockaddr*)&addr, (socklen_t*)&len);
137 if (r == -1 || len > sizeof(addr)) return;
139 *port = addr.sin_port;
141 *pid = fork();
142 if (*pid != 0) return;
144 /* now in child */
146 prot_init();
148 srv(&s); /* does not return */
149 exit(1); /* satisfy the compiler */
153 static int
154 diff(char *f0, int fd)
156 int pid;
158 pid = fork();
159 if (pid != 0) return pid;
161 /* now in child */
163 dup2(fd, 0);
164 close(fd);
166 execlp("diff", "diff", f0, "-", (char*)0);
167 /* not reached */
168 exit(1);
172 static int
173 copy(int dst, int src, int bs)
175 char buf[bs];
176 int r, w, c;
178 for (;;) {
179 r = read(src, buf, sizeof buf);
180 if (r == -1) return -1;
181 if (r == 0) break;
183 for (w = 0; w < r; w += c) {
184 c = write(dst, buf+w, r-w);
185 if (c == -1) return -1;
188 return 0;
192 static int
193 diallocal(int port)
195 int r, fd;
196 struct sockaddr_in addr = {};
198 addr.sin_family = AF_INET;
199 addr.sin_port = port;
200 r = inet_aton("127.0.0.1", &addr.sin_addr);
201 if (!r) {
202 errno = EINVAL;
203 return -1;
206 fd = socket(PF_INET, SOCK_STREAM, 0);
207 if (fd == -1) {
208 return -1;
211 r = connect(fd, (struct sockaddr*)&addr, sizeof addr);
212 if (r == -1) {
213 return -1;
216 return fd;
220 static void
221 cleanup(int sig)
223 puts("timed out");
224 if (srvpid > 0) {
225 kill(srvpid, 9);
227 exit(1);