correctly handle slowly-arriving incoming data
[beanstalkd.git] / tests / test_int.c
blob6f1a509aa8103a646c081567b236c2b9da4636d4
1 /* integration tests */
3 #include "../t.h"
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <signal.h>
8 #include <sys/stat.h>
9 #include <sys/socket.h>
10 #include <netdb.h>
11 #include <netinet/ip.h>
12 #include <arpa/inet.h>
13 #include <fcntl.h>
14 #include <sys/wait.h>
15 #include <event.h>
16 #include <errno.h>
17 #include "../cut.h"
18 #include "../dat.h"
20 static void testsrv(char*, char*, int);
21 static void forksrv(int*, int*);
22 static int copy(int, int, int);
23 static int diff(char*, int);
24 static int diallocal(int);
25 static void cleanup(int sig);
27 typedef struct T T;
28 struct T {
29 char *cmd;
30 char *exp;
33 static T ts[] = {
34 {"sh-tests/allow-underscore.commands", "sh-tests/allow-underscore.expected"},
35 {"sh-tests/delete_ready.commands", "sh-tests/delete_ready.expected"},
36 {"sh-tests/multi-tube.commands", "sh-tests/multi-tube.expected"},
37 {"sh-tests/no_negative_delays.commands", "sh-tests/no_negative_delays.expected"},
38 {"sh-tests/omit-time-left.commands", "sh-tests/omit-time-left.expected"},
39 {"sh-tests/pause-tube.commands", "sh-tests/pause-tube.expected"},
40 {"sh-tests/small_delay.commands", "sh-tests/small_delay.expected"},
41 {"sh-tests/too-big.commands", "sh-tests/too-big.expected"},
42 {"sh-tests/ttr-large.commands", "sh-tests/ttr-large.expected"},
43 {"sh-tests/zero_delay.commands", "sh-tests/zero_delay.expected"},
44 {},
47 static int srvpid;
50 void
51 __CUT_BRINGUP__srv()
56 void
57 __CUT__srv_test()
59 int i;
61 for (i = 0; ts[i].cmd; i++) {
62 testsrv(ts[i].cmd, ts[i].exp, 4096);
63 testsrv(ts[i].cmd, ts[i].exp, 1);
68 void
69 __CUT_TAKEDOWN__srv()
74 static void
75 testsrv(char *cmd, char *exp, int bufsiz)
77 int status, port = 0, cfd, tfd, diffpid;
78 struct sigaction sa = {};
80 job_data_size_limit = 10;
82 progname = cmd;
83 puts(cmd);
84 forksrv(&port, &srvpid);
85 if (port == -1 || srvpid == -1) {
86 puts("forksrv failed");
87 exit(1);
90 // Fail if this test takes more than 10 seconds.
91 // If we have trouble installing the timeout,
92 // just proceed anyway.
93 sa.sa_handler = cleanup;
94 sigaction(SIGALRM, &sa, 0);
95 alarm(10);
97 cfd = diallocal(port);
98 if (cfd == -1) {
99 twarn("diallocal");
100 kill(srvpid, 9);
101 exit(1);
104 tfd = open(cmd, O_RDONLY, 0);
105 if (tfd == -1) {
106 twarn("open");
107 kill(srvpid, 9);
108 exit(1);
111 if (copy(cfd, tfd, bufsiz) == -1) {
112 twarn("copy");
113 kill(srvpid, 9);
114 exit(1);
117 diffpid = diff(exp, cfd);
118 if (diffpid == -1) {
119 twarn("diff");
120 kill(srvpid, 9);
121 exit(1);
124 waitpid(diffpid, &status, 0);
126 // wait until after diff has finished to kill srvpid
127 kill(srvpid, 9);
129 printf("diff status %d\n", status);
130 ASSERT(status == 0, "diff status");
134 static void
135 forksrv(int *port, int *pid)
137 int r, srvfd, len;
138 struct sockaddr_in addr;
139 struct event_base *ev_base;
141 srvfd = make_server_socket("127.0.0.1", "0");
142 if (srvfd == -1) return;
144 len = sizeof(addr);
145 r = getsockname(srvfd, (struct sockaddr*)&addr, (socklen_t*)&len);
146 if (r == -1 || len > sizeof(addr)) return;
148 *port = addr.sin_port;
150 *pid = fork();
151 if (*pid != 0) return;
153 /* now in child */
155 prot_init();
156 ev_base = event_init();
158 srv(srvfd); /* does not return */
159 exit(1); /* satisfy the compiler */
163 static int
164 diff(char *f0, int fd)
166 int pid;
168 pid = fork();
169 if (pid != 0) return pid;
171 /* now in child */
173 dup2(fd, 0);
174 close(fd);
176 execlp("diff", "diff", f0, "-", (char*)0);
177 /* not reached */
178 exit(1);
182 static int
183 copy(int dst, int src, int bs)
185 char buf[bs];
186 int r, w, c;
188 for (;;) {
189 r = read(src, buf, sizeof buf);
190 if (r == -1) return -1;
191 if (r == 0) break;
193 for (w = 0; w < r; w += c) {
194 c = write(dst, buf+w, r-w);
195 if (c == -1) return -1;
198 return 0;
202 static int
203 diallocal(int port)
205 int r, fd;
206 struct sockaddr_in addr = {AF_INET, port};
208 r = inet_aton("127.0.0.1", &addr.sin_addr);
209 if (!r) {
210 errno = EINVAL;
211 return -1;
214 fd = socket(AF_INET, SOCK_STREAM, 0);
215 if (fd == -1) {
216 return -1;
219 r = connect(fd, (struct sockaddr*)&addr, sizeof addr);
220 if (r == -1) {
221 return -1;
224 return fd;
228 static void
229 cleanup(int sig)
231 puts("timed out");
232 if (srvpid > 0) {
233 kill(srvpid, 9);
235 exit(1);