update to newest ct; fixes #60
[beanstalkd.git] / integ-test.c
blobc7de1b495ed7b53c7b24a7ae3179feff2f7c59a9
1 /* integration tests */
3 #include <stdint.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 <errno.h>
16 #include "ct/ct.h"
17 #include "dat.h"
19 static void testsrv(char*, char*, int);
20 static void forksrv(int*, int*);
21 static int copy(int, int, int);
22 static int diff(char*, int);
23 static int diallocal(int);
24 static void cleanup(int sig);
26 typedef struct T T;
27 struct T {
28 char *cmd;
29 char *exp;
32 static T ts[] = {
33 {"sh-tests/allow-underscore.commands", "sh-tests/allow-underscore.expected"},
34 {"sh-tests/delete_ready.commands", "sh-tests/delete_ready.expected"},
35 {"sh-tests/multi-tube.commands", "sh-tests/multi-tube.expected"},
36 {"sh-tests/no_negative_delays.commands", "sh-tests/no_negative_delays.expected"},
37 {"sh-tests/omit-time-left.commands", "sh-tests/omit-time-left.expected"},
38 {"sh-tests/pause-tube.commands", "sh-tests/pause-tube.expected"},
39 {"sh-tests/small_delay.commands", "sh-tests/small_delay.expected"},
40 {"sh-tests/too-big.commands", "sh-tests/too-big.expected"},
41 {"sh-tests/ttr-large.commands", "sh-tests/ttr-large.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 printf("srv status %d, signal %d\n", WEXITSTATUS(srvst), WTERMSIG(srvst));
117 assertf(WIFSIGNALED(srvst) && WTERMSIG(srvst) == 9, "srv status");
119 printf("diff status %d\n", diffst);
120 assertf(diffst == 0, "diff status");
124 static void
125 forksrv(int *port, int *pid)
127 int r, len;
128 Srv s = {};
129 struct sockaddr_in addr;
131 s.sock.fd = make_server_socket("127.0.0.1", "0");
132 if (s.sock.fd == -1) return;
134 len = sizeof(addr);
135 r = getsockname(s.sock.fd, (struct sockaddr*)&addr, (socklen_t*)&len);
136 if (r == -1 || len > sizeof(addr)) return;
138 *port = addr.sin_port;
140 *pid = fork();
141 if (*pid != 0) return;
143 /* now in child */
145 prot_init();
147 srv(&s); /* does not return */
148 exit(1); /* satisfy the compiler */
152 static int
153 diff(char *f0, int fd)
155 int pid;
157 pid = fork();
158 if (pid != 0) return pid;
160 /* now in child */
162 dup2(fd, 0);
163 close(fd);
165 execlp("diff", "diff", f0, "-", (char*)0);
166 /* not reached */
167 exit(1);
171 static int
172 copy(int dst, int src, int bs)
174 char buf[bs];
175 int r, w, c;
177 for (;;) {
178 r = read(src, buf, sizeof buf);
179 if (r == -1) return -1;
180 if (r == 0) break;
182 for (w = 0; w < r; w += c) {
183 c = write(dst, buf+w, r-w);
184 if (c == -1) return -1;
187 return 0;
191 static int
192 diallocal(int port)
194 int r, fd;
195 struct sockaddr_in addr = {};
197 addr.sin_family = AF_INET;
198 addr.sin_port = port;
199 r = inet_aton("127.0.0.1", &addr.sin_addr);
200 if (!r) {
201 errno = EINVAL;
202 return -1;
205 fd = socket(PF_INET, SOCK_STREAM, 0);
206 if (fd == -1) {
207 return -1;
210 r = connect(fd, (struct sockaddr*)&addr, sizeof addr);
211 if (r == -1) {
212 return -1;
215 return fd;
219 static void
220 cleanup(int sig)
222 puts("timed out");
223 if (srvpid > 0) {
224 kill(srvpid, 9);
226 exit(1);