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