1*86d7f5d3SJohn Marino /* $NetBSD: harness.c,v 1.1.1.1 2009/12/02 00:25:58 haad Exp $ */
2*86d7f5d3SJohn Marino
3*86d7f5d3SJohn Marino #include <fcntl.h>
4*86d7f5d3SJohn Marino #include <string.h>
5*86d7f5d3SJohn Marino #include <stdio.h>
6*86d7f5d3SJohn Marino #include <sys/socket.h>
7*86d7f5d3SJohn Marino #include <sys/wait.h>
8*86d7f5d3SJohn Marino #include <unistd.h>
9*86d7f5d3SJohn Marino #include <stdlib.h>
10*86d7f5d3SJohn Marino
11*86d7f5d3SJohn Marino pid_t pid;
12*86d7f5d3SJohn Marino int fds[2];
13*86d7f5d3SJohn Marino int *status;
14*86d7f5d3SJohn Marino int nfailed = 0;
15*86d7f5d3SJohn Marino int nskipped = 0;
16*86d7f5d3SJohn Marino int npassed = 0;
17*86d7f5d3SJohn Marino
18*86d7f5d3SJohn Marino char *readbuf = NULL;
19*86d7f5d3SJohn Marino int readbuf_sz = 0, readbuf_used = 0;
20*86d7f5d3SJohn Marino
21*86d7f5d3SJohn Marino int die = 0;
22*86d7f5d3SJohn Marino
23*86d7f5d3SJohn Marino #define PASSED 0
24*86d7f5d3SJohn Marino #define SKIPPED 1
25*86d7f5d3SJohn Marino #define FAILED 2
26*86d7f5d3SJohn Marino
handler(int s)27*86d7f5d3SJohn Marino void handler( int s ) {
28*86d7f5d3SJohn Marino signal( s, SIG_DFL );
29*86d7f5d3SJohn Marino kill( pid, s );
30*86d7f5d3SJohn Marino die = s;
31*86d7f5d3SJohn Marino }
32*86d7f5d3SJohn Marino
dump()33*86d7f5d3SJohn Marino void dump() {
34*86d7f5d3SJohn Marino write(1, readbuf, readbuf_used);
35*86d7f5d3SJohn Marino }
36*86d7f5d3SJohn Marino
clear()37*86d7f5d3SJohn Marino void clear() {
38*86d7f5d3SJohn Marino readbuf_used = 0;
39*86d7f5d3SJohn Marino }
40*86d7f5d3SJohn Marino
drain()41*86d7f5d3SJohn Marino void drain() {
42*86d7f5d3SJohn Marino int sz;
43*86d7f5d3SJohn Marino char buf[2048];
44*86d7f5d3SJohn Marino while (1) {
45*86d7f5d3SJohn Marino sz = read(fds[1], buf, 2048);
46*86d7f5d3SJohn Marino if (sz <= 0)
47*86d7f5d3SJohn Marino return;
48*86d7f5d3SJohn Marino if (readbuf_used + sz >= readbuf_sz) {
49*86d7f5d3SJohn Marino readbuf_sz = readbuf_sz ? 2 * readbuf_sz : 4096;
50*86d7f5d3SJohn Marino readbuf = realloc(readbuf, readbuf_sz);
51*86d7f5d3SJohn Marino }
52*86d7f5d3SJohn Marino if (!readbuf)
53*86d7f5d3SJohn Marino exit(205);
54*86d7f5d3SJohn Marino memcpy(readbuf + readbuf_used, buf, sz);
55*86d7f5d3SJohn Marino readbuf_used += sz;
56*86d7f5d3SJohn Marino }
57*86d7f5d3SJohn Marino }
58*86d7f5d3SJohn Marino
passed(int i,char * f)59*86d7f5d3SJohn Marino void passed(int i, char *f) {
60*86d7f5d3SJohn Marino ++ npassed;
61*86d7f5d3SJohn Marino status[i] = PASSED;
62*86d7f5d3SJohn Marino printf("passed.\n");
63*86d7f5d3SJohn Marino }
64*86d7f5d3SJohn Marino
skipped(int i,char * f)65*86d7f5d3SJohn Marino void skipped(int i, char *f) {
66*86d7f5d3SJohn Marino ++ nskipped;
67*86d7f5d3SJohn Marino status[i] = SKIPPED;
68*86d7f5d3SJohn Marino printf("skipped.\n");
69*86d7f5d3SJohn Marino }
70*86d7f5d3SJohn Marino
failed(int i,char * f,int st)71*86d7f5d3SJohn Marino void failed(int i, char *f, int st) {
72*86d7f5d3SJohn Marino ++ nfailed;
73*86d7f5d3SJohn Marino status[i] = FAILED;
74*86d7f5d3SJohn Marino if(die == 2) {
75*86d7f5d3SJohn Marino printf("interrupted.\n");
76*86d7f5d3SJohn Marino return;
77*86d7f5d3SJohn Marino }
78*86d7f5d3SJohn Marino printf("FAILED.\n");
79*86d7f5d3SJohn Marino printf("-- FAILED %s ------------------------------------\n", f);
80*86d7f5d3SJohn Marino dump();
81*86d7f5d3SJohn Marino printf("-- FAILED %s (end) ------------------------------\n", f);
82*86d7f5d3SJohn Marino }
83*86d7f5d3SJohn Marino
run(int i,char * f)84*86d7f5d3SJohn Marino void run(int i, char *f) {
85*86d7f5d3SJohn Marino pid = fork();
86*86d7f5d3SJohn Marino if (pid < 0) {
87*86d7f5d3SJohn Marino perror("Fork failed.");
88*86d7f5d3SJohn Marino exit(201);
89*86d7f5d3SJohn Marino } else if (pid == 0) {
90*86d7f5d3SJohn Marino close(0);
91*86d7f5d3SJohn Marino dup2(fds[0], 1);
92*86d7f5d3SJohn Marino dup2(fds[0], 2);
93*86d7f5d3SJohn Marino execlp("bash", "bash", f, NULL);
94*86d7f5d3SJohn Marino perror("execlp");
95*86d7f5d3SJohn Marino fflush(stderr);
96*86d7f5d3SJohn Marino _exit(202);
97*86d7f5d3SJohn Marino } else {
98*86d7f5d3SJohn Marino char buf[128];
99*86d7f5d3SJohn Marino snprintf(buf, 128, "%s ...", f);
100*86d7f5d3SJohn Marino buf[127] = 0;
101*86d7f5d3SJohn Marino printf("Running %-40s ", buf);
102*86d7f5d3SJohn Marino fflush(stdout);
103*86d7f5d3SJohn Marino int st, w;
104*86d7f5d3SJohn Marino while ((w = waitpid(pid, &st, WNOHANG)) == 0) {
105*86d7f5d3SJohn Marino drain();
106*86d7f5d3SJohn Marino usleep(20000);
107*86d7f5d3SJohn Marino }
108*86d7f5d3SJohn Marino if (w != pid) {
109*86d7f5d3SJohn Marino perror("waitpid");
110*86d7f5d3SJohn Marino exit(206);
111*86d7f5d3SJohn Marino }
112*86d7f5d3SJohn Marino drain();
113*86d7f5d3SJohn Marino if (WIFEXITED(st)) {
114*86d7f5d3SJohn Marino if (WEXITSTATUS(st) == 0) {
115*86d7f5d3SJohn Marino passed(i, f);
116*86d7f5d3SJohn Marino } else if (WEXITSTATUS(st) == 200) {
117*86d7f5d3SJohn Marino skipped(i, f);
118*86d7f5d3SJohn Marino } else {
119*86d7f5d3SJohn Marino failed(i, f, st);
120*86d7f5d3SJohn Marino }
121*86d7f5d3SJohn Marino } else {
122*86d7f5d3SJohn Marino failed(i, f, st);
123*86d7f5d3SJohn Marino }
124*86d7f5d3SJohn Marino clear();
125*86d7f5d3SJohn Marino }
126*86d7f5d3SJohn Marino }
127*86d7f5d3SJohn Marino
main(int argc,char ** argv)128*86d7f5d3SJohn Marino int main(int argc, char **argv) {
129*86d7f5d3SJohn Marino int i;
130*86d7f5d3SJohn Marino status = alloca(sizeof(int)*argc);
131*86d7f5d3SJohn Marino
132*86d7f5d3SJohn Marino if (socketpair(PF_UNIX, SOCK_STREAM, 0, fds)) {
133*86d7f5d3SJohn Marino perror("socketpair");
134*86d7f5d3SJohn Marino return 201;
135*86d7f5d3SJohn Marino }
136*86d7f5d3SJohn Marino
137*86d7f5d3SJohn Marino if ( fcntl( fds[1], F_SETFL, O_NONBLOCK ) == -1 ) {
138*86d7f5d3SJohn Marino perror("fcntl on socket");
139*86d7f5d3SJohn Marino return 202;
140*86d7f5d3SJohn Marino }
141*86d7f5d3SJohn Marino
142*86d7f5d3SJohn Marino /* set up signal handlers */
143*86d7f5d3SJohn Marino for (i = 0; i <= 32; ++i) {
144*86d7f5d3SJohn Marino if (i == SIGCHLD || i == SIGWINCH || i == SIGURG)
145*86d7f5d3SJohn Marino continue;
146*86d7f5d3SJohn Marino signal(i, handler);
147*86d7f5d3SJohn Marino }
148*86d7f5d3SJohn Marino
149*86d7f5d3SJohn Marino /* run the tests */
150*86d7f5d3SJohn Marino for (i = 1; i < argc; ++ i) {
151*86d7f5d3SJohn Marino run(i, argv[i]);
152*86d7f5d3SJohn Marino if (die)
153*86d7f5d3SJohn Marino break;
154*86d7f5d3SJohn Marino }
155*86d7f5d3SJohn Marino
156*86d7f5d3SJohn Marino printf("\n## %d tests: %d OK, %d failed, %d skipped\n",
157*86d7f5d3SJohn Marino npassed + nfailed + nskipped, npassed, nfailed, nskipped);
158*86d7f5d3SJohn Marino
159*86d7f5d3SJohn Marino /* print out a summary */
160*86d7f5d3SJohn Marino if (nfailed || nskipped) {
161*86d7f5d3SJohn Marino for (i = 1; i < argc; ++ i) {
162*86d7f5d3SJohn Marino switch (status[i]) {
163*86d7f5d3SJohn Marino case FAILED:
164*86d7f5d3SJohn Marino printf("FAILED: %s\n", argv[i]);
165*86d7f5d3SJohn Marino break;
166*86d7f5d3SJohn Marino case SKIPPED:
167*86d7f5d3SJohn Marino printf("skipped: %s\n", argv[i]);
168*86d7f5d3SJohn Marino break;
169*86d7f5d3SJohn Marino }
170*86d7f5d3SJohn Marino }
171*86d7f5d3SJohn Marino printf("\n");
172*86d7f5d3SJohn Marino return nfailed > 0 || die;
173*86d7f5d3SJohn Marino }
174*86d7f5d3SJohn Marino return !die;
175*86d7f5d3SJohn Marino }
176