xref: /aosp_15_r20/external/kmod/testsuite/testsuite.c (revision cc4ad7da8cefe208cb129ac2aa9a357c7c72deb2)
1*cc4ad7daSAndroid Build Coastguard Worker /*
2*cc4ad7daSAndroid Build Coastguard Worker  * Copyright (C) 2012-2013  ProFUSION embedded systems
3*cc4ad7daSAndroid Build Coastguard Worker  *
4*cc4ad7daSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or
5*cc4ad7daSAndroid Build Coastguard Worker  * modify it under the terms of the GNU Lesser General Public
6*cc4ad7daSAndroid Build Coastguard Worker  * License as published by the Free Software Foundation; either
7*cc4ad7daSAndroid Build Coastguard Worker  * version 2.1 of the License, or (at your option) any later version.
8*cc4ad7daSAndroid Build Coastguard Worker  *
9*cc4ad7daSAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
10*cc4ad7daSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*cc4ad7daSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12*cc4ad7daSAndroid Build Coastguard Worker  * Lesser General Public License for more details.
13*cc4ad7daSAndroid Build Coastguard Worker  *
14*cc4ad7daSAndroid Build Coastguard Worker  * You should have received a copy of the GNU Lesser General Public
15*cc4ad7daSAndroid Build Coastguard Worker  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16*cc4ad7daSAndroid Build Coastguard Worker  */
17*cc4ad7daSAndroid Build Coastguard Worker 
18*cc4ad7daSAndroid Build Coastguard Worker #include <dirent.h>
19*cc4ad7daSAndroid Build Coastguard Worker #include <errno.h>
20*cc4ad7daSAndroid Build Coastguard Worker #include <fcntl.h>
21*cc4ad7daSAndroid Build Coastguard Worker #include <getopt.h>
22*cc4ad7daSAndroid Build Coastguard Worker #include <limits.h>
23*cc4ad7daSAndroid Build Coastguard Worker #include <regex.h>
24*cc4ad7daSAndroid Build Coastguard Worker #include <stdarg.h>
25*cc4ad7daSAndroid Build Coastguard Worker #include <stdio.h>
26*cc4ad7daSAndroid Build Coastguard Worker #include <stdlib.h>
27*cc4ad7daSAndroid Build Coastguard Worker #include <string.h>
28*cc4ad7daSAndroid Build Coastguard Worker #include <time.h>
29*cc4ad7daSAndroid Build Coastguard Worker #include <unistd.h>
30*cc4ad7daSAndroid Build Coastguard Worker #include <sys/epoll.h>
31*cc4ad7daSAndroid Build Coastguard Worker #include <sys/prctl.h>
32*cc4ad7daSAndroid Build Coastguard Worker #include <sys/stat.h>
33*cc4ad7daSAndroid Build Coastguard Worker #include <sys/wait.h>
34*cc4ad7daSAndroid Build Coastguard Worker 
35*cc4ad7daSAndroid Build Coastguard Worker #include <shared/util.h>
36*cc4ad7daSAndroid Build Coastguard Worker 
37*cc4ad7daSAndroid Build Coastguard Worker #include "testsuite.h"
38*cc4ad7daSAndroid Build Coastguard Worker 
39*cc4ad7daSAndroid Build Coastguard Worker static const char *ANSI_HIGHLIGHT_GREEN_ON = "\x1B[1;32m";
40*cc4ad7daSAndroid Build Coastguard Worker static const char *ANSI_HIGHLIGHT_YELLOW_ON = "\x1B[1;33m";
41*cc4ad7daSAndroid Build Coastguard Worker static const char *ANSI_HIGHLIGHT_RED_ON =  "\x1B[1;31m";
42*cc4ad7daSAndroid Build Coastguard Worker static const char *ANSI_HIGHLIGHT_OFF = "\x1B[0m";
43*cc4ad7daSAndroid Build Coastguard Worker 
44*cc4ad7daSAndroid Build Coastguard Worker static const char *progname;
45*cc4ad7daSAndroid Build Coastguard Worker static int oneshot = 0;
46*cc4ad7daSAndroid Build Coastguard Worker static const char options_short[] = "lhn";
47*cc4ad7daSAndroid Build Coastguard Worker static const struct option options[] = {
48*cc4ad7daSAndroid Build Coastguard Worker 	{ "list", no_argument, 0, 'l' },
49*cc4ad7daSAndroid Build Coastguard Worker 	{ "help", no_argument, 0, 'h' },
50*cc4ad7daSAndroid Build Coastguard Worker 	{ NULL, 0, 0, 0 }
51*cc4ad7daSAndroid Build Coastguard Worker };
52*cc4ad7daSAndroid Build Coastguard Worker 
53*cc4ad7daSAndroid Build Coastguard Worker #define OVERRIDE_LIBDIR ABS_TOP_BUILDDIR "/testsuite/.libs/"
54*cc4ad7daSAndroid Build Coastguard Worker #define TEST_TIMEOUT_USEC 2 * USEC_PER_SEC
55*cc4ad7daSAndroid Build Coastguard Worker 
56*cc4ad7daSAndroid Build Coastguard Worker static const struct {
57*cc4ad7daSAndroid Build Coastguard Worker 	const char *key;
58*cc4ad7daSAndroid Build Coastguard Worker 	const char *ldpreload;
59*cc4ad7daSAndroid Build Coastguard Worker } env_config[_TC_LAST] = {
60*cc4ad7daSAndroid Build Coastguard Worker 	[TC_UNAME_R] = { S_TC_UNAME_R, OVERRIDE_LIBDIR  "uname.so" },
61*cc4ad7daSAndroid Build Coastguard Worker 	[TC_ROOTFS] = { S_TC_ROOTFS, OVERRIDE_LIBDIR "path.so" },
62*cc4ad7daSAndroid Build Coastguard Worker 	[TC_INIT_MODULE_RETCODES] = { S_TC_INIT_MODULE_RETCODES, OVERRIDE_LIBDIR "init_module.so" },
63*cc4ad7daSAndroid Build Coastguard Worker 	[TC_DELETE_MODULE_RETCODES] = { S_TC_DELETE_MODULE_RETCODES, OVERRIDE_LIBDIR "delete_module.so" },
64*cc4ad7daSAndroid Build Coastguard Worker };
65*cc4ad7daSAndroid Build Coastguard Worker 
help(void)66*cc4ad7daSAndroid Build Coastguard Worker static void help(void)
67*cc4ad7daSAndroid Build Coastguard Worker {
68*cc4ad7daSAndroid Build Coastguard Worker 	const struct option *itr;
69*cc4ad7daSAndroid Build Coastguard Worker 	const char *itr_short;
70*cc4ad7daSAndroid Build Coastguard Worker 
71*cc4ad7daSAndroid Build Coastguard Worker 	printf("Usage:\n"
72*cc4ad7daSAndroid Build Coastguard Worker 	       "\t%s [options] <test>\n"
73*cc4ad7daSAndroid Build Coastguard Worker 	       "Options:\n", basename(progname));
74*cc4ad7daSAndroid Build Coastguard Worker 
75*cc4ad7daSAndroid Build Coastguard Worker 	for (itr = options, itr_short = options_short;
76*cc4ad7daSAndroid Build Coastguard Worker 				itr->name != NULL; itr++, itr_short++)
77*cc4ad7daSAndroid Build Coastguard Worker 		printf("\t-%c, --%s\n", *itr_short, itr->name);
78*cc4ad7daSAndroid Build Coastguard Worker }
79*cc4ad7daSAndroid Build Coastguard Worker 
test_list(const struct test * start,const struct test * stop)80*cc4ad7daSAndroid Build Coastguard Worker static void test_list(const struct test *start, const struct test *stop)
81*cc4ad7daSAndroid Build Coastguard Worker {
82*cc4ad7daSAndroid Build Coastguard Worker 	const struct test *t;
83*cc4ad7daSAndroid Build Coastguard Worker 
84*cc4ad7daSAndroid Build Coastguard Worker 	printf("Available tests:\n");
85*cc4ad7daSAndroid Build Coastguard Worker 	for (t = start; t < stop; t++)
86*cc4ad7daSAndroid Build Coastguard Worker 		printf("\t%s, %s\n", t->name, t->description);
87*cc4ad7daSAndroid Build Coastguard Worker }
88*cc4ad7daSAndroid Build Coastguard Worker 
test_init(const struct test * start,const struct test * stop,int argc,char * const argv[])89*cc4ad7daSAndroid Build Coastguard Worker int test_init(const struct test *start, const struct test *stop,
90*cc4ad7daSAndroid Build Coastguard Worker 	      int argc, char *const argv[])
91*cc4ad7daSAndroid Build Coastguard Worker {
92*cc4ad7daSAndroid Build Coastguard Worker 	progname = argv[0];
93*cc4ad7daSAndroid Build Coastguard Worker 
94*cc4ad7daSAndroid Build Coastguard Worker 	for (;;) {
95*cc4ad7daSAndroid Build Coastguard Worker 		int c, idx = 0;
96*cc4ad7daSAndroid Build Coastguard Worker 		c = getopt_long(argc, argv, options_short, options, &idx);
97*cc4ad7daSAndroid Build Coastguard Worker 		if (c == -1)
98*cc4ad7daSAndroid Build Coastguard Worker 			break;
99*cc4ad7daSAndroid Build Coastguard Worker 		switch (c) {
100*cc4ad7daSAndroid Build Coastguard Worker 		case 'l':
101*cc4ad7daSAndroid Build Coastguard Worker 			test_list(start, stop);
102*cc4ad7daSAndroid Build Coastguard Worker 			return 0;
103*cc4ad7daSAndroid Build Coastguard Worker 		case 'h':
104*cc4ad7daSAndroid Build Coastguard Worker 			help();
105*cc4ad7daSAndroid Build Coastguard Worker 			return 0;
106*cc4ad7daSAndroid Build Coastguard Worker 		case 'n':
107*cc4ad7daSAndroid Build Coastguard Worker 			oneshot = 1;
108*cc4ad7daSAndroid Build Coastguard Worker 			break;
109*cc4ad7daSAndroid Build Coastguard Worker 		case '?':
110*cc4ad7daSAndroid Build Coastguard Worker 			return -1;
111*cc4ad7daSAndroid Build Coastguard Worker 		default:
112*cc4ad7daSAndroid Build Coastguard Worker 			ERR("unexpected getopt_long() value %c\n", c);
113*cc4ad7daSAndroid Build Coastguard Worker 			return -1;
114*cc4ad7daSAndroid Build Coastguard Worker 		}
115*cc4ad7daSAndroid Build Coastguard Worker 	}
116*cc4ad7daSAndroid Build Coastguard Worker 
117*cc4ad7daSAndroid Build Coastguard Worker 	if (isatty(STDOUT_FILENO) == 0) {
118*cc4ad7daSAndroid Build Coastguard Worker 		ANSI_HIGHLIGHT_OFF = "";
119*cc4ad7daSAndroid Build Coastguard Worker 		ANSI_HIGHLIGHT_RED_ON = "";
120*cc4ad7daSAndroid Build Coastguard Worker 		ANSI_HIGHLIGHT_GREEN_ON = "";
121*cc4ad7daSAndroid Build Coastguard Worker 	}
122*cc4ad7daSAndroid Build Coastguard Worker 
123*cc4ad7daSAndroid Build Coastguard Worker 	return optind;
124*cc4ad7daSAndroid Build Coastguard Worker }
125*cc4ad7daSAndroid Build Coastguard Worker 
test_find(const struct test * start,const struct test * stop,const char * name)126*cc4ad7daSAndroid Build Coastguard Worker const struct test *test_find(const struct test *start,
127*cc4ad7daSAndroid Build Coastguard Worker 			     const struct test *stop, const char *name)
128*cc4ad7daSAndroid Build Coastguard Worker {
129*cc4ad7daSAndroid Build Coastguard Worker 	const struct test *t;
130*cc4ad7daSAndroid Build Coastguard Worker 
131*cc4ad7daSAndroid Build Coastguard Worker 	for (t = start; t < stop; t++) {
132*cc4ad7daSAndroid Build Coastguard Worker 		if (streq(t->name, name))
133*cc4ad7daSAndroid Build Coastguard Worker 			return t;
134*cc4ad7daSAndroid Build Coastguard Worker 	}
135*cc4ad7daSAndroid Build Coastguard Worker 
136*cc4ad7daSAndroid Build Coastguard Worker 	return NULL;
137*cc4ad7daSAndroid Build Coastguard Worker }
138*cc4ad7daSAndroid Build Coastguard Worker 
test_spawn_test(const struct test * t)139*cc4ad7daSAndroid Build Coastguard Worker static int test_spawn_test(const struct test *t)
140*cc4ad7daSAndroid Build Coastguard Worker {
141*cc4ad7daSAndroid Build Coastguard Worker 	const char *const args[] = { progname, "-n", t->name, NULL };
142*cc4ad7daSAndroid Build Coastguard Worker 
143*cc4ad7daSAndroid Build Coastguard Worker 	execv(progname, (char *const *) args);
144*cc4ad7daSAndroid Build Coastguard Worker 
145*cc4ad7daSAndroid Build Coastguard Worker 	ERR("failed to spawn %s for %s: %m\n", progname, t->name);
146*cc4ad7daSAndroid Build Coastguard Worker 	return EXIT_FAILURE;
147*cc4ad7daSAndroid Build Coastguard Worker }
148*cc4ad7daSAndroid Build Coastguard Worker 
test_run_spawned(const struct test * t)149*cc4ad7daSAndroid Build Coastguard Worker static int test_run_spawned(const struct test *t)
150*cc4ad7daSAndroid Build Coastguard Worker {
151*cc4ad7daSAndroid Build Coastguard Worker 	int err = t->func(t);
152*cc4ad7daSAndroid Build Coastguard Worker 	exit(err);
153*cc4ad7daSAndroid Build Coastguard Worker 
154*cc4ad7daSAndroid Build Coastguard Worker 	return EXIT_FAILURE;
155*cc4ad7daSAndroid Build Coastguard Worker }
156*cc4ad7daSAndroid Build Coastguard Worker 
test_spawn_prog(const char * prog,const char * const args[])157*cc4ad7daSAndroid Build Coastguard Worker int test_spawn_prog(const char *prog, const char *const args[])
158*cc4ad7daSAndroid Build Coastguard Worker {
159*cc4ad7daSAndroid Build Coastguard Worker 	execv(prog, (char *const *) args);
160*cc4ad7daSAndroid Build Coastguard Worker 
161*cc4ad7daSAndroid Build Coastguard Worker 	ERR("failed to spawn %s\n", prog);
162*cc4ad7daSAndroid Build Coastguard Worker 	ERR("did you forget to build tools?\n");
163*cc4ad7daSAndroid Build Coastguard Worker 	return EXIT_FAILURE;
164*cc4ad7daSAndroid Build Coastguard Worker }
165*cc4ad7daSAndroid Build Coastguard Worker 
test_export_environ(const struct test * t)166*cc4ad7daSAndroid Build Coastguard Worker static void test_export_environ(const struct test *t)
167*cc4ad7daSAndroid Build Coastguard Worker {
168*cc4ad7daSAndroid Build Coastguard Worker 	char *preload = NULL;
169*cc4ad7daSAndroid Build Coastguard Worker 	size_t preloadlen = 0;
170*cc4ad7daSAndroid Build Coastguard Worker 	size_t i;
171*cc4ad7daSAndroid Build Coastguard Worker 	const struct keyval *env;
172*cc4ad7daSAndroid Build Coastguard Worker 
173*cc4ad7daSAndroid Build Coastguard Worker 	unsetenv("LD_PRELOAD");
174*cc4ad7daSAndroid Build Coastguard Worker 
175*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0; i < _TC_LAST; i++) {
176*cc4ad7daSAndroid Build Coastguard Worker 		const char *ldpreload;
177*cc4ad7daSAndroid Build Coastguard Worker 		size_t ldpreloadlen;
178*cc4ad7daSAndroid Build Coastguard Worker 		char *tmp;
179*cc4ad7daSAndroid Build Coastguard Worker 
180*cc4ad7daSAndroid Build Coastguard Worker 		if (t->config[i] == NULL)
181*cc4ad7daSAndroid Build Coastguard Worker 			continue;
182*cc4ad7daSAndroid Build Coastguard Worker 
183*cc4ad7daSAndroid Build Coastguard Worker 		setenv(env_config[i].key, t->config[i], 1);
184*cc4ad7daSAndroid Build Coastguard Worker 
185*cc4ad7daSAndroid Build Coastguard Worker 		ldpreload = env_config[i].ldpreload;
186*cc4ad7daSAndroid Build Coastguard Worker 		ldpreloadlen = strlen(ldpreload);
187*cc4ad7daSAndroid Build Coastguard Worker 		tmp = realloc(preload, preloadlen + 2 + ldpreloadlen);
188*cc4ad7daSAndroid Build Coastguard Worker 		if (tmp == NULL) {
189*cc4ad7daSAndroid Build Coastguard Worker 			ERR("oom: test_export_environ()\n");
190*cc4ad7daSAndroid Build Coastguard Worker 			return;
191*cc4ad7daSAndroid Build Coastguard Worker 		}
192*cc4ad7daSAndroid Build Coastguard Worker 		preload = tmp;
193*cc4ad7daSAndroid Build Coastguard Worker 
194*cc4ad7daSAndroid Build Coastguard Worker 		if (preloadlen > 0)
195*cc4ad7daSAndroid Build Coastguard Worker 			preload[preloadlen++] = ' ';
196*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(preload + preloadlen, ldpreload, ldpreloadlen);
197*cc4ad7daSAndroid Build Coastguard Worker 		preloadlen += ldpreloadlen;
198*cc4ad7daSAndroid Build Coastguard Worker 		preload[preloadlen] = '\0';
199*cc4ad7daSAndroid Build Coastguard Worker 	}
200*cc4ad7daSAndroid Build Coastguard Worker 
201*cc4ad7daSAndroid Build Coastguard Worker 	if (preload != NULL)
202*cc4ad7daSAndroid Build Coastguard Worker 		setenv("LD_PRELOAD", preload, 1);
203*cc4ad7daSAndroid Build Coastguard Worker 
204*cc4ad7daSAndroid Build Coastguard Worker 	free(preload);
205*cc4ad7daSAndroid Build Coastguard Worker 
206*cc4ad7daSAndroid Build Coastguard Worker 	for (env = t->env_vars; env && env->key; env++)
207*cc4ad7daSAndroid Build Coastguard Worker 		setenv(env->key, env->val, 1);
208*cc4ad7daSAndroid Build Coastguard Worker }
209*cc4ad7daSAndroid Build Coastguard Worker 
test_run_child(const struct test * t,int fdout[2],int fderr[2],int fdmonitor[2])210*cc4ad7daSAndroid Build Coastguard Worker static inline int test_run_child(const struct test *t, int fdout[2],
211*cc4ad7daSAndroid Build Coastguard Worker 						int fderr[2], int fdmonitor[2])
212*cc4ad7daSAndroid Build Coastguard Worker {
213*cc4ad7daSAndroid Build Coastguard Worker 	/* kill child if parent dies */
214*cc4ad7daSAndroid Build Coastguard Worker 	prctl(PR_SET_PDEATHSIG, SIGTERM);
215*cc4ad7daSAndroid Build Coastguard Worker 
216*cc4ad7daSAndroid Build Coastguard Worker 	test_export_environ(t);
217*cc4ad7daSAndroid Build Coastguard Worker 
218*cc4ad7daSAndroid Build Coastguard Worker 	/* Close read-fds and redirect std{out,err} to the write-fds */
219*cc4ad7daSAndroid Build Coastguard Worker 	if (t->output.out != NULL) {
220*cc4ad7daSAndroid Build Coastguard Worker 		close(fdout[0]);
221*cc4ad7daSAndroid Build Coastguard Worker 		if (dup2(fdout[1], STDOUT_FILENO) < 0) {
222*cc4ad7daSAndroid Build Coastguard Worker 			ERR("could not redirect stdout to pipe: %m\n");
223*cc4ad7daSAndroid Build Coastguard Worker 			exit(EXIT_FAILURE);
224*cc4ad7daSAndroid Build Coastguard Worker 		}
225*cc4ad7daSAndroid Build Coastguard Worker 	}
226*cc4ad7daSAndroid Build Coastguard Worker 
227*cc4ad7daSAndroid Build Coastguard Worker 	if (t->output.err != NULL) {
228*cc4ad7daSAndroid Build Coastguard Worker 		close(fderr[0]);
229*cc4ad7daSAndroid Build Coastguard Worker 		if (dup2(fderr[1], STDERR_FILENO) < 0) {
230*cc4ad7daSAndroid Build Coastguard Worker 			ERR("could not redirect stderr to pipe: %m\n");
231*cc4ad7daSAndroid Build Coastguard Worker 			exit(EXIT_FAILURE);
232*cc4ad7daSAndroid Build Coastguard Worker 		}
233*cc4ad7daSAndroid Build Coastguard Worker 	}
234*cc4ad7daSAndroid Build Coastguard Worker 
235*cc4ad7daSAndroid Build Coastguard Worker 	close(fdmonitor[0]);
236*cc4ad7daSAndroid Build Coastguard Worker 
237*cc4ad7daSAndroid Build Coastguard Worker 	if (t->config[TC_ROOTFS] != NULL) {
238*cc4ad7daSAndroid Build Coastguard Worker 		const char *stamp = TESTSUITE_ROOTFS "../stamp-rootfs";
239*cc4ad7daSAndroid Build Coastguard Worker 		const char *rootfs = t->config[TC_ROOTFS];
240*cc4ad7daSAndroid Build Coastguard Worker 		struct stat rootfsst, stampst;
241*cc4ad7daSAndroid Build Coastguard Worker 
242*cc4ad7daSAndroid Build Coastguard Worker 		if (stat(stamp, &stampst) != 0) {
243*cc4ad7daSAndroid Build Coastguard Worker 			ERR("could not stat %s\n - %m", stamp);
244*cc4ad7daSAndroid Build Coastguard Worker 			exit(EXIT_FAILURE);
245*cc4ad7daSAndroid Build Coastguard Worker 		}
246*cc4ad7daSAndroid Build Coastguard Worker 
247*cc4ad7daSAndroid Build Coastguard Worker 		if (stat(rootfs, &rootfsst) != 0) {
248*cc4ad7daSAndroid Build Coastguard Worker 			ERR("could not stat %s\n - %m", rootfs);
249*cc4ad7daSAndroid Build Coastguard Worker 			exit(EXIT_FAILURE);
250*cc4ad7daSAndroid Build Coastguard Worker 		}
251*cc4ad7daSAndroid Build Coastguard Worker 
252*cc4ad7daSAndroid Build Coastguard Worker 		if (stat_mstamp(&rootfsst) > stat_mstamp(&stampst)) {
253*cc4ad7daSAndroid Build Coastguard Worker 			ERR("rootfs %s is dirty, please run 'make rootfs' before runnning this test\n",
254*cc4ad7daSAndroid Build Coastguard Worker 								rootfs);
255*cc4ad7daSAndroid Build Coastguard Worker 			exit(EXIT_FAILURE);
256*cc4ad7daSAndroid Build Coastguard Worker 		}
257*cc4ad7daSAndroid Build Coastguard Worker 	}
258*cc4ad7daSAndroid Build Coastguard Worker 
259*cc4ad7daSAndroid Build Coastguard Worker 	if (t->need_spawn)
260*cc4ad7daSAndroid Build Coastguard Worker 		return test_spawn_test(t);
261*cc4ad7daSAndroid Build Coastguard Worker 	else
262*cc4ad7daSAndroid Build Coastguard Worker 		return test_run_spawned(t);
263*cc4ad7daSAndroid Build Coastguard Worker }
264*cc4ad7daSAndroid Build Coastguard Worker 
265*cc4ad7daSAndroid Build Coastguard Worker #define BUFSZ 4096
266*cc4ad7daSAndroid Build Coastguard Worker 
267*cc4ad7daSAndroid Build Coastguard Worker enum fd_cmp_type {
268*cc4ad7daSAndroid Build Coastguard Worker 	FD_CMP_MONITOR,
269*cc4ad7daSAndroid Build Coastguard Worker 	FD_CMP_OUT,
270*cc4ad7daSAndroid Build Coastguard Worker 	FD_CMP_ERR,
271*cc4ad7daSAndroid Build Coastguard Worker 	FD_CMP_MAX = FD_CMP_ERR,
272*cc4ad7daSAndroid Build Coastguard Worker };
273*cc4ad7daSAndroid Build Coastguard Worker 
274*cc4ad7daSAndroid Build Coastguard Worker struct fd_cmp {
275*cc4ad7daSAndroid Build Coastguard Worker 	enum fd_cmp_type type;
276*cc4ad7daSAndroid Build Coastguard Worker 	int fd;
277*cc4ad7daSAndroid Build Coastguard Worker 	int fd_match;
278*cc4ad7daSAndroid Build Coastguard Worker 	bool activity;
279*cc4ad7daSAndroid Build Coastguard Worker 	const char *path;
280*cc4ad7daSAndroid Build Coastguard Worker 	const char *name;
281*cc4ad7daSAndroid Build Coastguard Worker 	char buf[BUFSZ];
282*cc4ad7daSAndroid Build Coastguard Worker 	char buf_match[BUFSZ];
283*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int head;
284*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int head_match;
285*cc4ad7daSAndroid Build Coastguard Worker };
286*cc4ad7daSAndroid Build Coastguard Worker 
fd_cmp_check_activity(struct fd_cmp * fd_cmp)287*cc4ad7daSAndroid Build Coastguard Worker static int fd_cmp_check_activity(struct fd_cmp *fd_cmp)
288*cc4ad7daSAndroid Build Coastguard Worker {
289*cc4ad7daSAndroid Build Coastguard Worker 	struct stat st;
290*cc4ad7daSAndroid Build Coastguard Worker 
291*cc4ad7daSAndroid Build Coastguard Worker 	/* not monitoring or monitoring and it has activity */
292*cc4ad7daSAndroid Build Coastguard Worker 	if (fd_cmp == NULL || fd_cmp->fd < 0 || fd_cmp->activity)
293*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
294*cc4ad7daSAndroid Build Coastguard Worker 
295*cc4ad7daSAndroid Build Coastguard Worker 	/* monitoring, there was no activity and size matches */
296*cc4ad7daSAndroid Build Coastguard Worker 	if (stat(fd_cmp->path, &st) == 0 && st.st_size == 0)
297*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
298*cc4ad7daSAndroid Build Coastguard Worker 
299*cc4ad7daSAndroid Build Coastguard Worker 	ERR("Expecting output on %s, but test didn't produce any\n",
300*cc4ad7daSAndroid Build Coastguard Worker 	    fd_cmp->name);
301*cc4ad7daSAndroid Build Coastguard Worker 
302*cc4ad7daSAndroid Build Coastguard Worker 	return -1;
303*cc4ad7daSAndroid Build Coastguard Worker }
304*cc4ad7daSAndroid Build Coastguard Worker 
fd_cmp_is_active(struct fd_cmp * fd_cmp)305*cc4ad7daSAndroid Build Coastguard Worker static bool fd_cmp_is_active(struct fd_cmp *fd_cmp)
306*cc4ad7daSAndroid Build Coastguard Worker {
307*cc4ad7daSAndroid Build Coastguard Worker 	return fd_cmp->fd != -1;
308*cc4ad7daSAndroid Build Coastguard Worker }
309*cc4ad7daSAndroid Build Coastguard Worker 
fd_cmp_open_monitor(struct fd_cmp * fd_cmp,int fd,int fd_ep)310*cc4ad7daSAndroid Build Coastguard Worker static int fd_cmp_open_monitor(struct fd_cmp *fd_cmp, int fd, int fd_ep)
311*cc4ad7daSAndroid Build Coastguard Worker {
312*cc4ad7daSAndroid Build Coastguard Worker 	struct epoll_event ep = {};
313*cc4ad7daSAndroid Build Coastguard Worker 
314*cc4ad7daSAndroid Build Coastguard Worker 	ep.events = EPOLLHUP;
315*cc4ad7daSAndroid Build Coastguard Worker 	ep.data.ptr = fd_cmp;
316*cc4ad7daSAndroid Build Coastguard Worker 	if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd, &ep) < 0) {
317*cc4ad7daSAndroid Build Coastguard Worker 		ERR("could not add monitor fd to epoll: %m\n");
318*cc4ad7daSAndroid Build Coastguard Worker 		return -errno;
319*cc4ad7daSAndroid Build Coastguard Worker 	}
320*cc4ad7daSAndroid Build Coastguard Worker 
321*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
322*cc4ad7daSAndroid Build Coastguard Worker }
323*cc4ad7daSAndroid Build Coastguard Worker 
fd_cmp_open_std(struct fd_cmp * fd_cmp,const char * fn,int fd,int fd_ep)324*cc4ad7daSAndroid Build Coastguard Worker static int fd_cmp_open_std(struct fd_cmp *fd_cmp,
325*cc4ad7daSAndroid Build Coastguard Worker 			   const char *fn, int fd, int fd_ep)
326*cc4ad7daSAndroid Build Coastguard Worker {
327*cc4ad7daSAndroid Build Coastguard Worker 	struct epoll_event ep = {};
328*cc4ad7daSAndroid Build Coastguard Worker 	int fd_match;
329*cc4ad7daSAndroid Build Coastguard Worker 
330*cc4ad7daSAndroid Build Coastguard Worker 	fd_match = open(fn, O_RDONLY);
331*cc4ad7daSAndroid Build Coastguard Worker 	if (fd_match < 0) {
332*cc4ad7daSAndroid Build Coastguard Worker 		ERR("could not open %s for read: %m\n", fn);
333*cc4ad7daSAndroid Build Coastguard Worker 		return -errno;
334*cc4ad7daSAndroid Build Coastguard Worker 	}
335*cc4ad7daSAndroid Build Coastguard Worker 	ep.events = EPOLLIN;
336*cc4ad7daSAndroid Build Coastguard Worker 	ep.data.ptr = fd_cmp;
337*cc4ad7daSAndroid Build Coastguard Worker 	if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd, &ep) < 0) {
338*cc4ad7daSAndroid Build Coastguard Worker 		ERR("could not add fd to epoll: %m\n");
339*cc4ad7daSAndroid Build Coastguard Worker 		close(fd_match);
340*cc4ad7daSAndroid Build Coastguard Worker 		return -errno;
341*cc4ad7daSAndroid Build Coastguard Worker 	}
342*cc4ad7daSAndroid Build Coastguard Worker 
343*cc4ad7daSAndroid Build Coastguard Worker 	return fd_match;
344*cc4ad7daSAndroid Build Coastguard Worker }
345*cc4ad7daSAndroid Build Coastguard Worker 
346*cc4ad7daSAndroid Build Coastguard Worker /* opens output file AND adds descriptor to epoll */
fd_cmp_open(struct fd_cmp ** fd_cmp_out,enum fd_cmp_type type,const char * fn,int fd,int fd_ep)347*cc4ad7daSAndroid Build Coastguard Worker static int fd_cmp_open(struct fd_cmp **fd_cmp_out,
348*cc4ad7daSAndroid Build Coastguard Worker 		       enum fd_cmp_type type, const char *fn, int fd,
349*cc4ad7daSAndroid Build Coastguard Worker 		       int fd_ep)
350*cc4ad7daSAndroid Build Coastguard Worker {
351*cc4ad7daSAndroid Build Coastguard Worker 	int err = 0;
352*cc4ad7daSAndroid Build Coastguard Worker 	struct fd_cmp *fd_cmp;
353*cc4ad7daSAndroid Build Coastguard Worker 
354*cc4ad7daSAndroid Build Coastguard Worker 	fd_cmp = calloc(1, sizeof(*fd_cmp));
355*cc4ad7daSAndroid Build Coastguard Worker 	if (fd_cmp == NULL) {
356*cc4ad7daSAndroid Build Coastguard Worker 		ERR("could not allocate fd_cmp\n");
357*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
358*cc4ad7daSAndroid Build Coastguard Worker 	}
359*cc4ad7daSAndroid Build Coastguard Worker 
360*cc4ad7daSAndroid Build Coastguard Worker 	switch (type) {
361*cc4ad7daSAndroid Build Coastguard Worker 	case FD_CMP_MONITOR:
362*cc4ad7daSAndroid Build Coastguard Worker 		err = fd_cmp_open_monitor(fd_cmp, fd, fd_ep);
363*cc4ad7daSAndroid Build Coastguard Worker 		break;
364*cc4ad7daSAndroid Build Coastguard Worker 	case FD_CMP_OUT:
365*cc4ad7daSAndroid Build Coastguard Worker 		fd_cmp->name = "STDOUT";
366*cc4ad7daSAndroid Build Coastguard Worker 		err = fd_cmp_open_std(fd_cmp, fn, fd, fd_ep);
367*cc4ad7daSAndroid Build Coastguard Worker 		break;
368*cc4ad7daSAndroid Build Coastguard Worker 	case FD_CMP_ERR:
369*cc4ad7daSAndroid Build Coastguard Worker 		fd_cmp->name = "STDERR";
370*cc4ad7daSAndroid Build Coastguard Worker 		err = fd_cmp_open_std(fd_cmp, fn, fd, fd_ep);
371*cc4ad7daSAndroid Build Coastguard Worker 		break;
372*cc4ad7daSAndroid Build Coastguard Worker 	default:
373*cc4ad7daSAndroid Build Coastguard Worker 		ERR("unknown fd type %d\n", type);
374*cc4ad7daSAndroid Build Coastguard Worker 		err = -1;
375*cc4ad7daSAndroid Build Coastguard Worker 	}
376*cc4ad7daSAndroid Build Coastguard Worker 
377*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0) {
378*cc4ad7daSAndroid Build Coastguard Worker 		free(fd_cmp);
379*cc4ad7daSAndroid Build Coastguard Worker 		return err;
380*cc4ad7daSAndroid Build Coastguard Worker 	}
381*cc4ad7daSAndroid Build Coastguard Worker 
382*cc4ad7daSAndroid Build Coastguard Worker 	fd_cmp->fd_match = err;
383*cc4ad7daSAndroid Build Coastguard Worker 	fd_cmp->fd = fd;
384*cc4ad7daSAndroid Build Coastguard Worker 	fd_cmp->type = type;
385*cc4ad7daSAndroid Build Coastguard Worker 	fd_cmp->path = fn;
386*cc4ad7daSAndroid Build Coastguard Worker 
387*cc4ad7daSAndroid Build Coastguard Worker 	*fd_cmp_out = fd_cmp;
388*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
389*cc4ad7daSAndroid Build Coastguard Worker }
390*cc4ad7daSAndroid Build Coastguard Worker 
fd_cmp_check_ev_in(struct fd_cmp * fd_cmp)391*cc4ad7daSAndroid Build Coastguard Worker static int fd_cmp_check_ev_in(struct fd_cmp *fd_cmp)
392*cc4ad7daSAndroid Build Coastguard Worker {
393*cc4ad7daSAndroid Build Coastguard Worker 	if (fd_cmp->type == FD_CMP_MONITOR) {
394*cc4ad7daSAndroid Build Coastguard Worker 		ERR("Unexpected activity on monitor pipe\n");
395*cc4ad7daSAndroid Build Coastguard Worker 		return -EINVAL;
396*cc4ad7daSAndroid Build Coastguard Worker 	}
397*cc4ad7daSAndroid Build Coastguard Worker 	fd_cmp->activity = true;
398*cc4ad7daSAndroid Build Coastguard Worker 
399*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
400*cc4ad7daSAndroid Build Coastguard Worker }
401*cc4ad7daSAndroid Build Coastguard Worker 
fd_cmp_delete_ep(struct fd_cmp * fd_cmp,int fd_ep)402*cc4ad7daSAndroid Build Coastguard Worker static void fd_cmp_delete_ep(struct fd_cmp *fd_cmp, int fd_ep)
403*cc4ad7daSAndroid Build Coastguard Worker {
404*cc4ad7daSAndroid Build Coastguard Worker 	if (epoll_ctl(fd_ep, EPOLL_CTL_DEL, fd_cmp->fd, NULL) < 0) {
405*cc4ad7daSAndroid Build Coastguard Worker 		ERR("could not remove fd %d from epoll: %m\n", fd_cmp->fd);
406*cc4ad7daSAndroid Build Coastguard Worker 	}
407*cc4ad7daSAndroid Build Coastguard Worker 	fd_cmp->fd = -1;
408*cc4ad7daSAndroid Build Coastguard Worker }
409*cc4ad7daSAndroid Build Coastguard Worker 
fd_cmp_close(struct fd_cmp * fd_cmp)410*cc4ad7daSAndroid Build Coastguard Worker static void fd_cmp_close(struct fd_cmp *fd_cmp)
411*cc4ad7daSAndroid Build Coastguard Worker {
412*cc4ad7daSAndroid Build Coastguard Worker 	if (fd_cmp == NULL)
413*cc4ad7daSAndroid Build Coastguard Worker 		return;
414*cc4ad7daSAndroid Build Coastguard Worker 
415*cc4ad7daSAndroid Build Coastguard Worker 	if (fd_cmp->fd >= 0)
416*cc4ad7daSAndroid Build Coastguard Worker 		close(fd_cmp->fd);
417*cc4ad7daSAndroid Build Coastguard Worker 	free(fd_cmp);
418*cc4ad7daSAndroid Build Coastguard Worker }
419*cc4ad7daSAndroid Build Coastguard Worker 
fd_cmp_regex_one(const char * pattern,const char * s)420*cc4ad7daSAndroid Build Coastguard Worker static bool fd_cmp_regex_one(const char *pattern, const char *s)
421*cc4ad7daSAndroid Build Coastguard Worker {
422*cc4ad7daSAndroid Build Coastguard Worker 	_cleanup_(regfree) regex_t re = { };
423*cc4ad7daSAndroid Build Coastguard Worker 
424*cc4ad7daSAndroid Build Coastguard Worker 	return !regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) &&
425*cc4ad7daSAndroid Build Coastguard Worker 	       !regexec(&re, s, 0, NULL, 0);
426*cc4ad7daSAndroid Build Coastguard Worker }
427*cc4ad7daSAndroid Build Coastguard Worker 
428*cc4ad7daSAndroid Build Coastguard Worker /*
429*cc4ad7daSAndroid Build Coastguard Worker  * read fd and fd_match, checking the first matches the regex of the second,
430*cc4ad7daSAndroid Build Coastguard Worker  * line by line
431*cc4ad7daSAndroid Build Coastguard Worker  */
fd_cmp_regex(struct fd_cmp * fd_cmp,const struct test * t)432*cc4ad7daSAndroid Build Coastguard Worker static bool fd_cmp_regex(struct fd_cmp *fd_cmp, const struct test *t)
433*cc4ad7daSAndroid Build Coastguard Worker {
434*cc4ad7daSAndroid Build Coastguard Worker 	char *p, *p_match;
435*cc4ad7daSAndroid Build Coastguard Worker 	int done = 0, done_match = 0, r;
436*cc4ad7daSAndroid Build Coastguard Worker 
437*cc4ad7daSAndroid Build Coastguard Worker 	if (fd_cmp->head >= sizeof(fd_cmp->buf)) {
438*cc4ad7daSAndroid Build Coastguard Worker 		ERR("Read %zu bytes without a newline\n", sizeof(fd_cmp->buf));
439*cc4ad7daSAndroid Build Coastguard Worker 		ERR("output: %.*s", (int)sizeof(fd_cmp->buf), fd_cmp->buf);
440*cc4ad7daSAndroid Build Coastguard Worker 		return false;
441*cc4ad7daSAndroid Build Coastguard Worker 	}
442*cc4ad7daSAndroid Build Coastguard Worker 
443*cc4ad7daSAndroid Build Coastguard Worker 	r = read(fd_cmp->fd, fd_cmp->buf + fd_cmp->head,
444*cc4ad7daSAndroid Build Coastguard Worker 		 sizeof(fd_cmp->buf) - fd_cmp->head);
445*cc4ad7daSAndroid Build Coastguard Worker 	if (r <= 0)
446*cc4ad7daSAndroid Build Coastguard Worker 		return true;
447*cc4ad7daSAndroid Build Coastguard Worker 
448*cc4ad7daSAndroid Build Coastguard Worker 	fd_cmp->head += r;
449*cc4ad7daSAndroid Build Coastguard Worker 
450*cc4ad7daSAndroid Build Coastguard Worker 	/*
451*cc4ad7daSAndroid Build Coastguard Worker 	 * Process as many lines as read from fd and that fits in the buffer -
452*cc4ad7daSAndroid Build Coastguard Worker 	 * it's assumed that if we get N lines from fd, we should be able to
453*cc4ad7daSAndroid Build Coastguard Worker 	 * get the same amount from fd_match
454*cc4ad7daSAndroid Build Coastguard Worker 	 */
455*cc4ad7daSAndroid Build Coastguard Worker 	for (;;) {
456*cc4ad7daSAndroid Build Coastguard Worker 		p = memchr(fd_cmp->buf + done, '\n', fd_cmp->head - done);
457*cc4ad7daSAndroid Build Coastguard Worker 		if (!p)
458*cc4ad7daSAndroid Build Coastguard Worker 			break;
459*cc4ad7daSAndroid Build Coastguard Worker 		*p = '\0';
460*cc4ad7daSAndroid Build Coastguard Worker 
461*cc4ad7daSAndroid Build Coastguard Worker 		p_match = memchr(fd_cmp->buf_match + done_match, '\n',
462*cc4ad7daSAndroid Build Coastguard Worker 				 fd_cmp->head_match - done_match);
463*cc4ad7daSAndroid Build Coastguard Worker 		if (!p_match) {
464*cc4ad7daSAndroid Build Coastguard Worker 			if (fd_cmp->head_match >= sizeof(fd_cmp->buf_match)) {
465*cc4ad7daSAndroid Build Coastguard Worker 				ERR("Read %zu bytes without a match\n", sizeof(fd_cmp->buf_match));
466*cc4ad7daSAndroid Build Coastguard Worker 				ERR("output: %.*s", (int)sizeof(fd_cmp->buf_match), fd_cmp->buf_match);
467*cc4ad7daSAndroid Build Coastguard Worker 				return false;
468*cc4ad7daSAndroid Build Coastguard Worker 			}
469*cc4ad7daSAndroid Build Coastguard Worker 
470*cc4ad7daSAndroid Build Coastguard Worker 			/* pump more data from file */
471*cc4ad7daSAndroid Build Coastguard Worker 			r = read(fd_cmp->fd_match, fd_cmp->buf_match + fd_cmp->head_match,
472*cc4ad7daSAndroid Build Coastguard Worker 				 sizeof(fd_cmp->buf_match) - fd_cmp->head_match);
473*cc4ad7daSAndroid Build Coastguard Worker 			if (r <= 0) {
474*cc4ad7daSAndroid Build Coastguard Worker 				ERR("could not read match fd %d\n", fd_cmp->fd_match);
475*cc4ad7daSAndroid Build Coastguard Worker 				return false;
476*cc4ad7daSAndroid Build Coastguard Worker 			}
477*cc4ad7daSAndroid Build Coastguard Worker 			fd_cmp->head_match += r;
478*cc4ad7daSAndroid Build Coastguard Worker 			p_match = memchr(fd_cmp->buf_match + done_match, '\n',
479*cc4ad7daSAndroid Build Coastguard Worker 					 fd_cmp->head_match - done_match);
480*cc4ad7daSAndroid Build Coastguard Worker 			if (!p_match) {
481*cc4ad7daSAndroid Build Coastguard Worker 				ERR("could not find match line from fd %d\n", fd_cmp->fd_match);
482*cc4ad7daSAndroid Build Coastguard Worker 				return false;
483*cc4ad7daSAndroid Build Coastguard Worker 			}
484*cc4ad7daSAndroid Build Coastguard Worker 		}
485*cc4ad7daSAndroid Build Coastguard Worker 		*p_match = '\0';
486*cc4ad7daSAndroid Build Coastguard Worker 
487*cc4ad7daSAndroid Build Coastguard Worker 		if (!fd_cmp_regex_one(fd_cmp->buf_match + done_match, fd_cmp->buf + done)) {
488*cc4ad7daSAndroid Build Coastguard Worker 			ERR("Output does not match pattern on %s:\n", fd_cmp->name);
489*cc4ad7daSAndroid Build Coastguard Worker 			ERR("pattern: %s\n", fd_cmp->buf_match + done_match);
490*cc4ad7daSAndroid Build Coastguard Worker 			ERR("output : %s\n", fd_cmp->buf + done);
491*cc4ad7daSAndroid Build Coastguard Worker 			return false;
492*cc4ad7daSAndroid Build Coastguard Worker 		}
493*cc4ad7daSAndroid Build Coastguard Worker 
494*cc4ad7daSAndroid Build Coastguard Worker 		done = p - fd_cmp->buf + 1;
495*cc4ad7daSAndroid Build Coastguard Worker 		done_match = p_match - fd_cmp->buf_match + 1;
496*cc4ad7daSAndroid Build Coastguard Worker 	}
497*cc4ad7daSAndroid Build Coastguard Worker 
498*cc4ad7daSAndroid Build Coastguard Worker 	/*
499*cc4ad7daSAndroid Build Coastguard Worker 	 * Prepare for the next call: anything we processed we remove from the
500*cc4ad7daSAndroid Build Coastguard Worker 	 * buffer by memmoving the remaining bytes up to the beginning
501*cc4ad7daSAndroid Build Coastguard Worker 	 */
502*cc4ad7daSAndroid Build Coastguard Worker 	if (done) {
503*cc4ad7daSAndroid Build Coastguard Worker 		if (fd_cmp->head - done)
504*cc4ad7daSAndroid Build Coastguard Worker 			memmove(fd_cmp->buf, fd_cmp->buf + done, fd_cmp->head - done);
505*cc4ad7daSAndroid Build Coastguard Worker 		fd_cmp->head -= done;
506*cc4ad7daSAndroid Build Coastguard Worker 	}
507*cc4ad7daSAndroid Build Coastguard Worker 
508*cc4ad7daSAndroid Build Coastguard Worker 	if (done_match) {
509*cc4ad7daSAndroid Build Coastguard Worker 		if (fd_cmp->head_match - done_match)
510*cc4ad7daSAndroid Build Coastguard Worker 			memmove(fd_cmp->buf_match, fd_cmp->buf_match + done_match,
511*cc4ad7daSAndroid Build Coastguard Worker 				fd_cmp->head_match - done_match);
512*cc4ad7daSAndroid Build Coastguard Worker 		fd_cmp->head_match -= done_match;
513*cc4ad7daSAndroid Build Coastguard Worker 	}
514*cc4ad7daSAndroid Build Coastguard Worker 
515*cc4ad7daSAndroid Build Coastguard Worker 	return true;
516*cc4ad7daSAndroid Build Coastguard Worker }
517*cc4ad7daSAndroid Build Coastguard Worker 
518*cc4ad7daSAndroid Build Coastguard Worker /* read fd and fd_match, checking they match exactly */
fd_cmp_exact(struct fd_cmp * fd_cmp,const struct test * t)519*cc4ad7daSAndroid Build Coastguard Worker static bool fd_cmp_exact(struct fd_cmp *fd_cmp, const struct test *t)
520*cc4ad7daSAndroid Build Coastguard Worker {
521*cc4ad7daSAndroid Build Coastguard Worker 	int r, rmatch, done = 0;
522*cc4ad7daSAndroid Build Coastguard Worker 
523*cc4ad7daSAndroid Build Coastguard Worker 	r = read(fd_cmp->fd, fd_cmp->buf, sizeof(fd_cmp->buf) - 1);
524*cc4ad7daSAndroid Build Coastguard Worker 	if (r <= 0)
525*cc4ad7daSAndroid Build Coastguard Worker 		/* try again later */
526*cc4ad7daSAndroid Build Coastguard Worker 		return true;
527*cc4ad7daSAndroid Build Coastguard Worker 
528*cc4ad7daSAndroid Build Coastguard Worker 	/* read as much data from fd_match as we read from fd */
529*cc4ad7daSAndroid Build Coastguard Worker 	for (;;) {
530*cc4ad7daSAndroid Build Coastguard Worker 		rmatch = read(fd_cmp->fd_match, fd_cmp->buf_match + done, r - done);
531*cc4ad7daSAndroid Build Coastguard Worker 		if (rmatch == 0)
532*cc4ad7daSAndroid Build Coastguard Worker 			break;
533*cc4ad7daSAndroid Build Coastguard Worker 
534*cc4ad7daSAndroid Build Coastguard Worker 		if (rmatch < 0) {
535*cc4ad7daSAndroid Build Coastguard Worker 			if (errno == EINTR)
536*cc4ad7daSAndroid Build Coastguard Worker 				continue;
537*cc4ad7daSAndroid Build Coastguard Worker 			ERR("could not read match fd %d\n", fd_cmp->fd_match);
538*cc4ad7daSAndroid Build Coastguard Worker 			return false;
539*cc4ad7daSAndroid Build Coastguard Worker 		}
540*cc4ad7daSAndroid Build Coastguard Worker 
541*cc4ad7daSAndroid Build Coastguard Worker 		done += rmatch;
542*cc4ad7daSAndroid Build Coastguard Worker 	}
543*cc4ad7daSAndroid Build Coastguard Worker 
544*cc4ad7daSAndroid Build Coastguard Worker 	fd_cmp->buf[r] = '\0';
545*cc4ad7daSAndroid Build Coastguard Worker 	fd_cmp->buf_match[r] = '\0';
546*cc4ad7daSAndroid Build Coastguard Worker 
547*cc4ad7daSAndroid Build Coastguard Worker 	if (t->print_outputs)
548*cc4ad7daSAndroid Build Coastguard Worker 		printf("%s: %s\n", fd_cmp->name, fd_cmp->buf);
549*cc4ad7daSAndroid Build Coastguard Worker 
550*cc4ad7daSAndroid Build Coastguard Worker 	if (!streq(fd_cmp->buf, fd_cmp->buf_match)) {
551*cc4ad7daSAndroid Build Coastguard Worker 		ERR("Outputs do not match on %s:\n", fd_cmp->name);
552*cc4ad7daSAndroid Build Coastguard Worker 		ERR("correct:\n%s\n", fd_cmp->buf_match);
553*cc4ad7daSAndroid Build Coastguard Worker 		ERR("wrong:\n%s\n", fd_cmp->buf);
554*cc4ad7daSAndroid Build Coastguard Worker 		return false;
555*cc4ad7daSAndroid Build Coastguard Worker 	}
556*cc4ad7daSAndroid Build Coastguard Worker 
557*cc4ad7daSAndroid Build Coastguard Worker 	return true;
558*cc4ad7daSAndroid Build Coastguard Worker }
559*cc4ad7daSAndroid Build Coastguard Worker 
test_run_parent_check_outputs(const struct test * t,int fdout,int fderr,int fdmonitor,pid_t child)560*cc4ad7daSAndroid Build Coastguard Worker static bool test_run_parent_check_outputs(const struct test *t,
561*cc4ad7daSAndroid Build Coastguard Worker 					  int fdout, int fderr, int fdmonitor,
562*cc4ad7daSAndroid Build Coastguard Worker 					  pid_t child)
563*cc4ad7daSAndroid Build Coastguard Worker {
564*cc4ad7daSAndroid Build Coastguard Worker 	int err, fd_ep;
565*cc4ad7daSAndroid Build Coastguard Worker 	unsigned long long end_usec, start_usec;
566*cc4ad7daSAndroid Build Coastguard Worker 	struct fd_cmp *fd_cmp_out = NULL;
567*cc4ad7daSAndroid Build Coastguard Worker 	struct fd_cmp *fd_cmp_err = NULL;
568*cc4ad7daSAndroid Build Coastguard Worker 	struct fd_cmp *fd_cmp_monitor = NULL;
569*cc4ad7daSAndroid Build Coastguard Worker 	int n_fd = 0;
570*cc4ad7daSAndroid Build Coastguard Worker 
571*cc4ad7daSAndroid Build Coastguard Worker 	fd_ep = epoll_create1(EPOLL_CLOEXEC);
572*cc4ad7daSAndroid Build Coastguard Worker 	if (fd_ep < 0) {
573*cc4ad7daSAndroid Build Coastguard Worker 		ERR("could not create epoll fd: %m\n");
574*cc4ad7daSAndroid Build Coastguard Worker 		return false;
575*cc4ad7daSAndroid Build Coastguard Worker 	}
576*cc4ad7daSAndroid Build Coastguard Worker 
577*cc4ad7daSAndroid Build Coastguard Worker 	if (t->output.out != NULL) {
578*cc4ad7daSAndroid Build Coastguard Worker 		err = fd_cmp_open(&fd_cmp_out,
579*cc4ad7daSAndroid Build Coastguard Worker 				  FD_CMP_OUT, t->output.out, fdout, fd_ep);
580*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0)
581*cc4ad7daSAndroid Build Coastguard Worker 			goto out;
582*cc4ad7daSAndroid Build Coastguard Worker 		n_fd++;
583*cc4ad7daSAndroid Build Coastguard Worker 	}
584*cc4ad7daSAndroid Build Coastguard Worker 
585*cc4ad7daSAndroid Build Coastguard Worker 	if (t->output.err != NULL) {
586*cc4ad7daSAndroid Build Coastguard Worker 		err = fd_cmp_open(&fd_cmp_err,
587*cc4ad7daSAndroid Build Coastguard Worker 				  FD_CMP_ERR, t->output.err, fderr, fd_ep);
588*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0)
589*cc4ad7daSAndroid Build Coastguard Worker 			goto out;
590*cc4ad7daSAndroid Build Coastguard Worker 		n_fd++;
591*cc4ad7daSAndroid Build Coastguard Worker 	}
592*cc4ad7daSAndroid Build Coastguard Worker 
593*cc4ad7daSAndroid Build Coastguard Worker 	err = fd_cmp_open(&fd_cmp_monitor, FD_CMP_MONITOR, NULL, fdmonitor, fd_ep);
594*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0)
595*cc4ad7daSAndroid Build Coastguard Worker 		goto out;
596*cc4ad7daSAndroid Build Coastguard Worker 	n_fd++;
597*cc4ad7daSAndroid Build Coastguard Worker 
598*cc4ad7daSAndroid Build Coastguard Worker 	start_usec = now_usec();
599*cc4ad7daSAndroid Build Coastguard Worker 	end_usec = start_usec + TEST_TIMEOUT_USEC;
600*cc4ad7daSAndroid Build Coastguard Worker 
601*cc4ad7daSAndroid Build Coastguard Worker 	for (err = 0; n_fd > 0;) {
602*cc4ad7daSAndroid Build Coastguard Worker 		int fdcount, i, timeout;
603*cc4ad7daSAndroid Build Coastguard Worker 		struct epoll_event ev[4];
604*cc4ad7daSAndroid Build Coastguard Worker 		unsigned long long curr_usec = now_usec();
605*cc4ad7daSAndroid Build Coastguard Worker 
606*cc4ad7daSAndroid Build Coastguard Worker 		if (curr_usec > end_usec)
607*cc4ad7daSAndroid Build Coastguard Worker 			break;
608*cc4ad7daSAndroid Build Coastguard Worker 
609*cc4ad7daSAndroid Build Coastguard Worker 		timeout = (end_usec - curr_usec) / USEC_PER_MSEC;
610*cc4ad7daSAndroid Build Coastguard Worker 		fdcount = epoll_wait(fd_ep, ev, 4, timeout);
611*cc4ad7daSAndroid Build Coastguard Worker 		if (fdcount < 0) {
612*cc4ad7daSAndroid Build Coastguard Worker 			if (errno == EINTR)
613*cc4ad7daSAndroid Build Coastguard Worker 				continue;
614*cc4ad7daSAndroid Build Coastguard Worker 			err = -errno;
615*cc4ad7daSAndroid Build Coastguard Worker 			ERR("could not poll: %m\n");
616*cc4ad7daSAndroid Build Coastguard Worker 			goto out;
617*cc4ad7daSAndroid Build Coastguard Worker 		}
618*cc4ad7daSAndroid Build Coastguard Worker 
619*cc4ad7daSAndroid Build Coastguard Worker 		for (i = 0;  i < fdcount; i++) {
620*cc4ad7daSAndroid Build Coastguard Worker 			struct fd_cmp *fd_cmp = ev[i].data.ptr;
621*cc4ad7daSAndroid Build Coastguard Worker 			bool ret;
622*cc4ad7daSAndroid Build Coastguard Worker 
623*cc4ad7daSAndroid Build Coastguard Worker 			if (ev[i].events & EPOLLIN) {
624*cc4ad7daSAndroid Build Coastguard Worker 				err = fd_cmp_check_ev_in(fd_cmp);
625*cc4ad7daSAndroid Build Coastguard Worker 				if (err < 0)
626*cc4ad7daSAndroid Build Coastguard Worker 					goto out;
627*cc4ad7daSAndroid Build Coastguard Worker 
628*cc4ad7daSAndroid Build Coastguard Worker 				if (t->output.regex)
629*cc4ad7daSAndroid Build Coastguard Worker 					ret = fd_cmp_regex(fd_cmp, t);
630*cc4ad7daSAndroid Build Coastguard Worker 				else
631*cc4ad7daSAndroid Build Coastguard Worker 					ret = fd_cmp_exact(fd_cmp, t);
632*cc4ad7daSAndroid Build Coastguard Worker 
633*cc4ad7daSAndroid Build Coastguard Worker 				if (!ret) {
634*cc4ad7daSAndroid Build Coastguard Worker 					err = -1;
635*cc4ad7daSAndroid Build Coastguard Worker 					goto out;
636*cc4ad7daSAndroid Build Coastguard Worker 				}
637*cc4ad7daSAndroid Build Coastguard Worker 			} else if (ev[i].events & EPOLLHUP) {
638*cc4ad7daSAndroid Build Coastguard Worker 				fd_cmp_delete_ep(fd_cmp, fd_ep);
639*cc4ad7daSAndroid Build Coastguard Worker 				n_fd--;
640*cc4ad7daSAndroid Build Coastguard Worker 			}
641*cc4ad7daSAndroid Build Coastguard Worker 		}
642*cc4ad7daSAndroid Build Coastguard Worker 	}
643*cc4ad7daSAndroid Build Coastguard Worker 
644*cc4ad7daSAndroid Build Coastguard Worker 	err = fd_cmp_check_activity(fd_cmp_out);
645*cc4ad7daSAndroid Build Coastguard Worker 	err |= fd_cmp_check_activity(fd_cmp_err);
646*cc4ad7daSAndroid Build Coastguard Worker 
647*cc4ad7daSAndroid Build Coastguard Worker 	if (err == 0 && fd_cmp_is_active(fd_cmp_monitor)) {
648*cc4ad7daSAndroid Build Coastguard Worker 		err = -EINVAL;
649*cc4ad7daSAndroid Build Coastguard Worker 		ERR("Test '%s' timed out, killing %d\n", t->name, child);
650*cc4ad7daSAndroid Build Coastguard Worker 		kill(child, SIGKILL);
651*cc4ad7daSAndroid Build Coastguard Worker 	}
652*cc4ad7daSAndroid Build Coastguard Worker 
653*cc4ad7daSAndroid Build Coastguard Worker out:
654*cc4ad7daSAndroid Build Coastguard Worker 	fd_cmp_close(fd_cmp_out);
655*cc4ad7daSAndroid Build Coastguard Worker 	fd_cmp_close(fd_cmp_err);
656*cc4ad7daSAndroid Build Coastguard Worker 	fd_cmp_close(fd_cmp_monitor);
657*cc4ad7daSAndroid Build Coastguard Worker 	close(fd_ep);
658*cc4ad7daSAndroid Build Coastguard Worker 
659*cc4ad7daSAndroid Build Coastguard Worker 	return err == 0;
660*cc4ad7daSAndroid Build Coastguard Worker }
661*cc4ad7daSAndroid Build Coastguard Worker 
safe_read(int fd,void * buf,size_t count)662*cc4ad7daSAndroid Build Coastguard Worker static inline int safe_read(int fd, void *buf, size_t count)
663*cc4ad7daSAndroid Build Coastguard Worker {
664*cc4ad7daSAndroid Build Coastguard Worker 	int r;
665*cc4ad7daSAndroid Build Coastguard Worker 
666*cc4ad7daSAndroid Build Coastguard Worker 	while (1) {
667*cc4ad7daSAndroid Build Coastguard Worker 		r = read(fd, buf, count);
668*cc4ad7daSAndroid Build Coastguard Worker 		if (r == -1 && errno == EINTR)
669*cc4ad7daSAndroid Build Coastguard Worker 			continue;
670*cc4ad7daSAndroid Build Coastguard Worker 		break;
671*cc4ad7daSAndroid Build Coastguard Worker 	}
672*cc4ad7daSAndroid Build Coastguard Worker 
673*cc4ad7daSAndroid Build Coastguard Worker 	return r;
674*cc4ad7daSAndroid Build Coastguard Worker }
675*cc4ad7daSAndroid Build Coastguard Worker 
check_generated_files(const struct test * t)676*cc4ad7daSAndroid Build Coastguard Worker static bool check_generated_files(const struct test *t)
677*cc4ad7daSAndroid Build Coastguard Worker {
678*cc4ad7daSAndroid Build Coastguard Worker 	const struct keyval *k;
679*cc4ad7daSAndroid Build Coastguard Worker 
680*cc4ad7daSAndroid Build Coastguard Worker 	/* This is not meant to be a diff replacement, just stupidly check if
681*cc4ad7daSAndroid Build Coastguard Worker 	 * the files match. Bear in mind they can be binary files */
682*cc4ad7daSAndroid Build Coastguard Worker 	for (k = t->output.files; k && k->key; k++) {
683*cc4ad7daSAndroid Build Coastguard Worker 		struct stat sta, stb;
684*cc4ad7daSAndroid Build Coastguard Worker 		int fda = -1, fdb = -1;
685*cc4ad7daSAndroid Build Coastguard Worker 		char bufa[4096];
686*cc4ad7daSAndroid Build Coastguard Worker 		char bufb[4096];
687*cc4ad7daSAndroid Build Coastguard Worker 
688*cc4ad7daSAndroid Build Coastguard Worker 		fda = open(k->key, O_RDONLY);
689*cc4ad7daSAndroid Build Coastguard Worker 		if (fda < 0) {
690*cc4ad7daSAndroid Build Coastguard Worker 			ERR("could not open %s\n - %m\n", k->key);
691*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
692*cc4ad7daSAndroid Build Coastguard Worker 		}
693*cc4ad7daSAndroid Build Coastguard Worker 
694*cc4ad7daSAndroid Build Coastguard Worker 		fdb = open(k->val, O_RDONLY);
695*cc4ad7daSAndroid Build Coastguard Worker 		if (fdb < 0) {
696*cc4ad7daSAndroid Build Coastguard Worker 			ERR("could not open %s\n - %m\n", k->val);
697*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
698*cc4ad7daSAndroid Build Coastguard Worker 		}
699*cc4ad7daSAndroid Build Coastguard Worker 
700*cc4ad7daSAndroid Build Coastguard Worker 		if (fstat(fda, &sta) != 0) {
701*cc4ad7daSAndroid Build Coastguard Worker 			ERR("could not fstat %d %s\n - %m\n", fda, k->key);
702*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
703*cc4ad7daSAndroid Build Coastguard Worker 		}
704*cc4ad7daSAndroid Build Coastguard Worker 
705*cc4ad7daSAndroid Build Coastguard Worker 		if (fstat(fdb, &stb) != 0) {
706*cc4ad7daSAndroid Build Coastguard Worker 			ERR("could not fstat %d %s\n - %m\n", fdb, k->key);
707*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
708*cc4ad7daSAndroid Build Coastguard Worker 		}
709*cc4ad7daSAndroid Build Coastguard Worker 
710*cc4ad7daSAndroid Build Coastguard Worker 		if (sta.st_size != stb.st_size) {
711*cc4ad7daSAndroid Build Coastguard Worker 			ERR("sizes do not match %s %s\n", k->key, k->val);
712*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
713*cc4ad7daSAndroid Build Coastguard Worker 		}
714*cc4ad7daSAndroid Build Coastguard Worker 
715*cc4ad7daSAndroid Build Coastguard Worker 		for (;;) {
716*cc4ad7daSAndroid Build Coastguard Worker 			int r, done;
717*cc4ad7daSAndroid Build Coastguard Worker 
718*cc4ad7daSAndroid Build Coastguard Worker 			r = safe_read(fda, bufa, sizeof(bufa));
719*cc4ad7daSAndroid Build Coastguard Worker 			if (r < 0)
720*cc4ad7daSAndroid Build Coastguard Worker 				goto fail;
721*cc4ad7daSAndroid Build Coastguard Worker 
722*cc4ad7daSAndroid Build Coastguard Worker 			if (r == 0)
723*cc4ad7daSAndroid Build Coastguard Worker 				/* size is already checked, go to next file */
724*cc4ad7daSAndroid Build Coastguard Worker 				goto next;
725*cc4ad7daSAndroid Build Coastguard Worker 
726*cc4ad7daSAndroid Build Coastguard Worker 			for (done = 0; done < r;) {
727*cc4ad7daSAndroid Build Coastguard Worker 				int r2 = safe_read(fdb, bufb + done, r - done);
728*cc4ad7daSAndroid Build Coastguard Worker 
729*cc4ad7daSAndroid Build Coastguard Worker 				if (r2 <= 0)
730*cc4ad7daSAndroid Build Coastguard Worker 					goto fail;
731*cc4ad7daSAndroid Build Coastguard Worker 
732*cc4ad7daSAndroid Build Coastguard Worker 				done += r2;
733*cc4ad7daSAndroid Build Coastguard Worker 			}
734*cc4ad7daSAndroid Build Coastguard Worker 
735*cc4ad7daSAndroid Build Coastguard Worker 			if (memcmp(bufa, bufb, r) != 0)
736*cc4ad7daSAndroid Build Coastguard Worker 				goto fail;
737*cc4ad7daSAndroid Build Coastguard Worker 		}
738*cc4ad7daSAndroid Build Coastguard Worker 
739*cc4ad7daSAndroid Build Coastguard Worker next:
740*cc4ad7daSAndroid Build Coastguard Worker 		close(fda);
741*cc4ad7daSAndroid Build Coastguard Worker 		close(fdb);
742*cc4ad7daSAndroid Build Coastguard Worker 		continue;
743*cc4ad7daSAndroid Build Coastguard Worker 
744*cc4ad7daSAndroid Build Coastguard Worker fail:
745*cc4ad7daSAndroid Build Coastguard Worker 		if (fda >= 0)
746*cc4ad7daSAndroid Build Coastguard Worker 			close(fda);
747*cc4ad7daSAndroid Build Coastguard Worker 		if (fdb >= 0)
748*cc4ad7daSAndroid Build Coastguard Worker 			close(fdb);
749*cc4ad7daSAndroid Build Coastguard Worker 
750*cc4ad7daSAndroid Build Coastguard Worker 		return false;
751*cc4ad7daSAndroid Build Coastguard Worker 	}
752*cc4ad7daSAndroid Build Coastguard Worker 
753*cc4ad7daSAndroid Build Coastguard Worker 	return true;
754*cc4ad7daSAndroid Build Coastguard Worker }
755*cc4ad7daSAndroid Build Coastguard Worker 
cmp_modnames(const void * m1,const void * m2)756*cc4ad7daSAndroid Build Coastguard Worker static int cmp_modnames(const void *m1, const void *m2)
757*cc4ad7daSAndroid Build Coastguard Worker {
758*cc4ad7daSAndroid Build Coastguard Worker 	const char *s1 = *(char *const *)m1;
759*cc4ad7daSAndroid Build Coastguard Worker 	const char *s2 = *(char *const *)m2;
760*cc4ad7daSAndroid Build Coastguard Worker 	int i;
761*cc4ad7daSAndroid Build Coastguard Worker 
762*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0; s1[i] || s2[i]; i++) {
763*cc4ad7daSAndroid Build Coastguard Worker 		char c1 = s1[i], c2 = s2[i];
764*cc4ad7daSAndroid Build Coastguard Worker 		if (c1 == '-')
765*cc4ad7daSAndroid Build Coastguard Worker 			c1 = '_';
766*cc4ad7daSAndroid Build Coastguard Worker 		if (c2 == '-')
767*cc4ad7daSAndroid Build Coastguard Worker 			c2 = '_';
768*cc4ad7daSAndroid Build Coastguard Worker 		if (c1 != c2)
769*cc4ad7daSAndroid Build Coastguard Worker 			return c1 - c2;
770*cc4ad7daSAndroid Build Coastguard Worker 	}
771*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
772*cc4ad7daSAndroid Build Coastguard Worker }
773*cc4ad7daSAndroid Build Coastguard Worker 
774*cc4ad7daSAndroid Build Coastguard Worker /*
775*cc4ad7daSAndroid Build Coastguard Worker  * Store the expected module names in buf and return a list of pointers to
776*cc4ad7daSAndroid Build Coastguard Worker  * them.
777*cc4ad7daSAndroid Build Coastguard Worker  */
read_expected_modules(const struct test * t,char ** buf,int * count)778*cc4ad7daSAndroid Build Coastguard Worker static const char **read_expected_modules(const struct test *t,
779*cc4ad7daSAndroid Build Coastguard Worker 		char **buf, int *count)
780*cc4ad7daSAndroid Build Coastguard Worker {
781*cc4ad7daSAndroid Build Coastguard Worker 	const char **res;
782*cc4ad7daSAndroid Build Coastguard Worker 	int len;
783*cc4ad7daSAndroid Build Coastguard Worker 	int i;
784*cc4ad7daSAndroid Build Coastguard Worker 	char *p;
785*cc4ad7daSAndroid Build Coastguard Worker 
786*cc4ad7daSAndroid Build Coastguard Worker 	if (t->modules_loaded[0] == '\0') {
787*cc4ad7daSAndroid Build Coastguard Worker 		*count = 0;
788*cc4ad7daSAndroid Build Coastguard Worker 		*buf = NULL;
789*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
790*cc4ad7daSAndroid Build Coastguard Worker 	}
791*cc4ad7daSAndroid Build Coastguard Worker 	*buf = strdup(t->modules_loaded);
792*cc4ad7daSAndroid Build Coastguard Worker 	if (!*buf) {
793*cc4ad7daSAndroid Build Coastguard Worker 		*count = -1;
794*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
795*cc4ad7daSAndroid Build Coastguard Worker 	}
796*cc4ad7daSAndroid Build Coastguard Worker 	len = 1;
797*cc4ad7daSAndroid Build Coastguard Worker 	for (p = *buf; *p; p++)
798*cc4ad7daSAndroid Build Coastguard Worker 		if (*p == ',')
799*cc4ad7daSAndroid Build Coastguard Worker 			len++;
800*cc4ad7daSAndroid Build Coastguard Worker 	res = malloc(sizeof(char *) * len);
801*cc4ad7daSAndroid Build Coastguard Worker 	if (!res) {
802*cc4ad7daSAndroid Build Coastguard Worker 		perror("malloc");
803*cc4ad7daSAndroid Build Coastguard Worker 		*count = -1;
804*cc4ad7daSAndroid Build Coastguard Worker 		free(*buf);
805*cc4ad7daSAndroid Build Coastguard Worker 		*buf = NULL;
806*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
807*cc4ad7daSAndroid Build Coastguard Worker 	}
808*cc4ad7daSAndroid Build Coastguard Worker 	i = 0;
809*cc4ad7daSAndroid Build Coastguard Worker 	res[i++] = *buf;
810*cc4ad7daSAndroid Build Coastguard Worker 	for (p = *buf; i < len; p++)
811*cc4ad7daSAndroid Build Coastguard Worker 		if (*p == ',') {
812*cc4ad7daSAndroid Build Coastguard Worker 			*p = '\0';
813*cc4ad7daSAndroid Build Coastguard Worker 			res[i++] = p + 1;
814*cc4ad7daSAndroid Build Coastguard Worker 		}
815*cc4ad7daSAndroid Build Coastguard Worker 	*count = len;
816*cc4ad7daSAndroid Build Coastguard Worker 	return res;
817*cc4ad7daSAndroid Build Coastguard Worker }
818*cc4ad7daSAndroid Build Coastguard Worker 
read_loaded_modules(const struct test * t,char ** buf,int * count)819*cc4ad7daSAndroid Build Coastguard Worker static char **read_loaded_modules(const struct test *t, char **buf, int *count)
820*cc4ad7daSAndroid Build Coastguard Worker {
821*cc4ad7daSAndroid Build Coastguard Worker 	char dirname[PATH_MAX];
822*cc4ad7daSAndroid Build Coastguard Worker 	DIR *dir;
823*cc4ad7daSAndroid Build Coastguard Worker 	struct dirent *dirent;
824*cc4ad7daSAndroid Build Coastguard Worker 	int i;
825*cc4ad7daSAndroid Build Coastguard Worker 	int len = 0, bufsz;
826*cc4ad7daSAndroid Build Coastguard Worker 	char **res = NULL;
827*cc4ad7daSAndroid Build Coastguard Worker 	char *p;
828*cc4ad7daSAndroid Build Coastguard Worker 	const char *rootfs = t->config[TC_ROOTFS] ? t->config[TC_ROOTFS] : "";
829*cc4ad7daSAndroid Build Coastguard Worker 
830*cc4ad7daSAndroid Build Coastguard Worker 	/* Store the entries in /sys/module to res */
831*cc4ad7daSAndroid Build Coastguard Worker 	if (snprintf(dirname, sizeof(dirname), "%s/sys/module", rootfs)
832*cc4ad7daSAndroid Build Coastguard Worker 			>= (int)sizeof(dirname)) {
833*cc4ad7daSAndroid Build Coastguard Worker 		ERR("rootfs path too long: %s\n", rootfs);
834*cc4ad7daSAndroid Build Coastguard Worker 		*buf = NULL;
835*cc4ad7daSAndroid Build Coastguard Worker 		len = -1;
836*cc4ad7daSAndroid Build Coastguard Worker 		goto out;
837*cc4ad7daSAndroid Build Coastguard Worker 	}
838*cc4ad7daSAndroid Build Coastguard Worker 	dir = opendir(dirname);
839*cc4ad7daSAndroid Build Coastguard Worker 	/* not an error, simply return empty list */
840*cc4ad7daSAndroid Build Coastguard Worker 	if (!dir) {
841*cc4ad7daSAndroid Build Coastguard Worker 		*buf = NULL;
842*cc4ad7daSAndroid Build Coastguard Worker 		goto out;
843*cc4ad7daSAndroid Build Coastguard Worker 	}
844*cc4ad7daSAndroid Build Coastguard Worker 	bufsz = 0;
845*cc4ad7daSAndroid Build Coastguard Worker 	while ((dirent = readdir(dir))) {
846*cc4ad7daSAndroid Build Coastguard Worker 		if (dirent->d_name[0] == '.')
847*cc4ad7daSAndroid Build Coastguard Worker 			continue;
848*cc4ad7daSAndroid Build Coastguard Worker 		len++;
849*cc4ad7daSAndroid Build Coastguard Worker 		bufsz += strlen(dirent->d_name) + 1;
850*cc4ad7daSAndroid Build Coastguard Worker 	}
851*cc4ad7daSAndroid Build Coastguard Worker 	res = malloc(sizeof(char *) * len);
852*cc4ad7daSAndroid Build Coastguard Worker 	if (!res) {
853*cc4ad7daSAndroid Build Coastguard Worker 		perror("malloc");
854*cc4ad7daSAndroid Build Coastguard Worker 		len = -1;
855*cc4ad7daSAndroid Build Coastguard Worker 		goto out_dir;
856*cc4ad7daSAndroid Build Coastguard Worker 	}
857*cc4ad7daSAndroid Build Coastguard Worker 	*buf = malloc(bufsz);
858*cc4ad7daSAndroid Build Coastguard Worker 	if (!*buf) {
859*cc4ad7daSAndroid Build Coastguard Worker 		perror("malloc");
860*cc4ad7daSAndroid Build Coastguard Worker 		free(res);
861*cc4ad7daSAndroid Build Coastguard Worker 		res = NULL;
862*cc4ad7daSAndroid Build Coastguard Worker 		len = -1;
863*cc4ad7daSAndroid Build Coastguard Worker 		goto out_dir;
864*cc4ad7daSAndroid Build Coastguard Worker 	}
865*cc4ad7daSAndroid Build Coastguard Worker 	rewinddir(dir);
866*cc4ad7daSAndroid Build Coastguard Worker 	i = 0;
867*cc4ad7daSAndroid Build Coastguard Worker 	p = *buf;
868*cc4ad7daSAndroid Build Coastguard Worker 	while ((dirent = readdir(dir))) {
869*cc4ad7daSAndroid Build Coastguard Worker 		int size;
870*cc4ad7daSAndroid Build Coastguard Worker 
871*cc4ad7daSAndroid Build Coastguard Worker 		if (dirent->d_name[0] == '.')
872*cc4ad7daSAndroid Build Coastguard Worker 			continue;
873*cc4ad7daSAndroid Build Coastguard Worker 		size = strlen(dirent->d_name) + 1;
874*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(p, dirent->d_name, size);
875*cc4ad7daSAndroid Build Coastguard Worker 		res[i++] = p;
876*cc4ad7daSAndroid Build Coastguard Worker 		p += size;
877*cc4ad7daSAndroid Build Coastguard Worker 	}
878*cc4ad7daSAndroid Build Coastguard Worker out_dir:
879*cc4ad7daSAndroid Build Coastguard Worker 	closedir(dir);
880*cc4ad7daSAndroid Build Coastguard Worker out:
881*cc4ad7daSAndroid Build Coastguard Worker 	*count = len;
882*cc4ad7daSAndroid Build Coastguard Worker 	return res;
883*cc4ad7daSAndroid Build Coastguard Worker }
884*cc4ad7daSAndroid Build Coastguard Worker 
check_loaded_modules(const struct test * t)885*cc4ad7daSAndroid Build Coastguard Worker static int check_loaded_modules(const struct test *t)
886*cc4ad7daSAndroid Build Coastguard Worker {
887*cc4ad7daSAndroid Build Coastguard Worker 	int l1, l2, i1, i2;
888*cc4ad7daSAndroid Build Coastguard Worker 	const char **a1;
889*cc4ad7daSAndroid Build Coastguard Worker 	char **a2;
890*cc4ad7daSAndroid Build Coastguard Worker 	char *buf1, *buf2;
891*cc4ad7daSAndroid Build Coastguard Worker 	int err = false;
892*cc4ad7daSAndroid Build Coastguard Worker 
893*cc4ad7daSAndroid Build Coastguard Worker 	a1 = read_expected_modules(t, &buf1, &l1);
894*cc4ad7daSAndroid Build Coastguard Worker 	if (l1 < 0)
895*cc4ad7daSAndroid Build Coastguard Worker 		return err;
896*cc4ad7daSAndroid Build Coastguard Worker 	a2 = read_loaded_modules(t, &buf2, &l2);
897*cc4ad7daSAndroid Build Coastguard Worker 	if (l2 < 0)
898*cc4ad7daSAndroid Build Coastguard Worker 		goto out_a1;
899*cc4ad7daSAndroid Build Coastguard Worker 	qsort(a1, l1, sizeof(char *), cmp_modnames);
900*cc4ad7daSAndroid Build Coastguard Worker 	qsort(a2, l2, sizeof(char *), cmp_modnames);
901*cc4ad7daSAndroid Build Coastguard Worker 	i1 = i2 = 0;
902*cc4ad7daSAndroid Build Coastguard Worker 	err = true;
903*cc4ad7daSAndroid Build Coastguard Worker 	while (i1 < l1 || i2 < l2) {
904*cc4ad7daSAndroid Build Coastguard Worker 		int cmp;
905*cc4ad7daSAndroid Build Coastguard Worker 
906*cc4ad7daSAndroid Build Coastguard Worker 		if (i1 >= l1)
907*cc4ad7daSAndroid Build Coastguard Worker 			cmp = 1;
908*cc4ad7daSAndroid Build Coastguard Worker 		else if (i2 >= l2)
909*cc4ad7daSAndroid Build Coastguard Worker 			cmp = -1;
910*cc4ad7daSAndroid Build Coastguard Worker 		else
911*cc4ad7daSAndroid Build Coastguard Worker 			cmp = cmp_modnames(&a1[i1], &a2[i2]);
912*cc4ad7daSAndroid Build Coastguard Worker 		if (cmp == 0) {
913*cc4ad7daSAndroid Build Coastguard Worker 			i1++;
914*cc4ad7daSAndroid Build Coastguard Worker 			i2++;
915*cc4ad7daSAndroid Build Coastguard Worker 		} else if (cmp < 0) {
916*cc4ad7daSAndroid Build Coastguard Worker 			err = false;
917*cc4ad7daSAndroid Build Coastguard Worker 			ERR("module %s not loaded\n", a1[i1]);
918*cc4ad7daSAndroid Build Coastguard Worker 			i1++;
919*cc4ad7daSAndroid Build Coastguard Worker 		} else  {
920*cc4ad7daSAndroid Build Coastguard Worker 			err = false;
921*cc4ad7daSAndroid Build Coastguard Worker 			ERR("module %s is loaded but should not be \n", a2[i2]);
922*cc4ad7daSAndroid Build Coastguard Worker 			i2++;
923*cc4ad7daSAndroid Build Coastguard Worker 		}
924*cc4ad7daSAndroid Build Coastguard Worker 	}
925*cc4ad7daSAndroid Build Coastguard Worker 	free(a2);
926*cc4ad7daSAndroid Build Coastguard Worker 	free(buf2);
927*cc4ad7daSAndroid Build Coastguard Worker out_a1:
928*cc4ad7daSAndroid Build Coastguard Worker 	free(a1);
929*cc4ad7daSAndroid Build Coastguard Worker 	free(buf1);
930*cc4ad7daSAndroid Build Coastguard Worker 	return err;
931*cc4ad7daSAndroid Build Coastguard Worker }
932*cc4ad7daSAndroid Build Coastguard Worker 
test_run_parent(const struct test * t,int fdout[2],int fderr[2],int fdmonitor[2],pid_t child)933*cc4ad7daSAndroid Build Coastguard Worker static inline int test_run_parent(const struct test *t, int fdout[2],
934*cc4ad7daSAndroid Build Coastguard Worker 				int fderr[2], int fdmonitor[2], pid_t child)
935*cc4ad7daSAndroid Build Coastguard Worker {
936*cc4ad7daSAndroid Build Coastguard Worker 	pid_t pid;
937*cc4ad7daSAndroid Build Coastguard Worker 	int err;
938*cc4ad7daSAndroid Build Coastguard Worker 	bool matchout, match_modules;
939*cc4ad7daSAndroid Build Coastguard Worker 
940*cc4ad7daSAndroid Build Coastguard Worker 	if (t->skip) {
941*cc4ad7daSAndroid Build Coastguard Worker 		LOG("%sSKIPPED%s: %s\n",
942*cc4ad7daSAndroid Build Coastguard Worker 			ANSI_HIGHLIGHT_YELLOW_ON, ANSI_HIGHLIGHT_OFF,
943*cc4ad7daSAndroid Build Coastguard Worker 			t->name);
944*cc4ad7daSAndroid Build Coastguard Worker 		err = EXIT_SUCCESS;
945*cc4ad7daSAndroid Build Coastguard Worker 		goto exit;
946*cc4ad7daSAndroid Build Coastguard Worker 	}
947*cc4ad7daSAndroid Build Coastguard Worker 
948*cc4ad7daSAndroid Build Coastguard Worker 	/* Close write-fds */
949*cc4ad7daSAndroid Build Coastguard Worker 	if (t->output.out != NULL)
950*cc4ad7daSAndroid Build Coastguard Worker 		close(fdout[1]);
951*cc4ad7daSAndroid Build Coastguard Worker 	if (t->output.err != NULL)
952*cc4ad7daSAndroid Build Coastguard Worker 		close(fderr[1]);
953*cc4ad7daSAndroid Build Coastguard Worker 	close(fdmonitor[1]);
954*cc4ad7daSAndroid Build Coastguard Worker 
955*cc4ad7daSAndroid Build Coastguard Worker 	matchout = test_run_parent_check_outputs(t, fdout[0], fderr[0],
956*cc4ad7daSAndroid Build Coastguard Worker 							fdmonitor[0], child);
957*cc4ad7daSAndroid Build Coastguard Worker 
958*cc4ad7daSAndroid Build Coastguard Worker 	/*
959*cc4ad7daSAndroid Build Coastguard Worker 	 * break pipe on the other end: either child already closed or we want
960*cc4ad7daSAndroid Build Coastguard Worker 	 * to stop it
961*cc4ad7daSAndroid Build Coastguard Worker 	 */
962*cc4ad7daSAndroid Build Coastguard Worker 	if (t->output.out != NULL)
963*cc4ad7daSAndroid Build Coastguard Worker 		close(fdout[0]);
964*cc4ad7daSAndroid Build Coastguard Worker 	if (t->output.err != NULL)
965*cc4ad7daSAndroid Build Coastguard Worker 		close(fderr[0]);
966*cc4ad7daSAndroid Build Coastguard Worker 	close(fdmonitor[0]);
967*cc4ad7daSAndroid Build Coastguard Worker 
968*cc4ad7daSAndroid Build Coastguard Worker 	do {
969*cc4ad7daSAndroid Build Coastguard Worker 		pid = wait(&err);
970*cc4ad7daSAndroid Build Coastguard Worker 		if (pid == -1) {
971*cc4ad7daSAndroid Build Coastguard Worker 			ERR("error waitpid(): %m\n");
972*cc4ad7daSAndroid Build Coastguard Worker 			err = EXIT_FAILURE;
973*cc4ad7daSAndroid Build Coastguard Worker 			goto exit;
974*cc4ad7daSAndroid Build Coastguard Worker 		}
975*cc4ad7daSAndroid Build Coastguard Worker 	} while (!WIFEXITED(err) && !WIFSIGNALED(err));
976*cc4ad7daSAndroid Build Coastguard Worker 
977*cc4ad7daSAndroid Build Coastguard Worker 	if (WIFEXITED(err)) {
978*cc4ad7daSAndroid Build Coastguard Worker 		if (WEXITSTATUS(err) != 0)
979*cc4ad7daSAndroid Build Coastguard Worker 			ERR("'%s' [%u] exited with return code %d\n",
980*cc4ad7daSAndroid Build Coastguard Worker 					t->name, pid, WEXITSTATUS(err));
981*cc4ad7daSAndroid Build Coastguard Worker 		else
982*cc4ad7daSAndroid Build Coastguard Worker 			LOG("'%s' [%u] exited with return code %d\n",
983*cc4ad7daSAndroid Build Coastguard Worker 					t->name, pid, WEXITSTATUS(err));
984*cc4ad7daSAndroid Build Coastguard Worker 	} else if (WIFSIGNALED(err)) {
985*cc4ad7daSAndroid Build Coastguard Worker 		ERR("'%s' [%u] terminated by signal %d (%s)\n", t->name, pid,
986*cc4ad7daSAndroid Build Coastguard Worker 				WTERMSIG(err), strsignal(WTERMSIG(err)));
987*cc4ad7daSAndroid Build Coastguard Worker 		err = t->expected_fail ? EXIT_SUCCESS : EXIT_FAILURE;
988*cc4ad7daSAndroid Build Coastguard Worker 		goto exit;
989*cc4ad7daSAndroid Build Coastguard Worker 	}
990*cc4ad7daSAndroid Build Coastguard Worker 
991*cc4ad7daSAndroid Build Coastguard Worker 	if (matchout)
992*cc4ad7daSAndroid Build Coastguard Worker 		matchout = check_generated_files(t);
993*cc4ad7daSAndroid Build Coastguard Worker 	if (t->modules_loaded)
994*cc4ad7daSAndroid Build Coastguard Worker 		match_modules = check_loaded_modules(t);
995*cc4ad7daSAndroid Build Coastguard Worker 	else
996*cc4ad7daSAndroid Build Coastguard Worker 		match_modules = true;
997*cc4ad7daSAndroid Build Coastguard Worker 
998*cc4ad7daSAndroid Build Coastguard Worker 	if (t->expected_fail == false) {
999*cc4ad7daSAndroid Build Coastguard Worker 		if (err == 0) {
1000*cc4ad7daSAndroid Build Coastguard Worker 			if (matchout && match_modules)
1001*cc4ad7daSAndroid Build Coastguard Worker 				LOG("%sPASSED%s: %s\n",
1002*cc4ad7daSAndroid Build Coastguard Worker 					ANSI_HIGHLIGHT_GREEN_ON, ANSI_HIGHLIGHT_OFF,
1003*cc4ad7daSAndroid Build Coastguard Worker 					t->name);
1004*cc4ad7daSAndroid Build Coastguard Worker 			else {
1005*cc4ad7daSAndroid Build Coastguard Worker 				ERR("%sFAILED%s: exit ok but %s do not match: %s\n",
1006*cc4ad7daSAndroid Build Coastguard Worker 					ANSI_HIGHLIGHT_RED_ON, ANSI_HIGHLIGHT_OFF,
1007*cc4ad7daSAndroid Build Coastguard Worker 					matchout ? "loaded modules" : "outputs",
1008*cc4ad7daSAndroid Build Coastguard Worker 					t->name);
1009*cc4ad7daSAndroid Build Coastguard Worker 				err = EXIT_FAILURE;
1010*cc4ad7daSAndroid Build Coastguard Worker 			}
1011*cc4ad7daSAndroid Build Coastguard Worker 		} else {
1012*cc4ad7daSAndroid Build Coastguard Worker 			ERR("%sFAILED%s: %s\n",
1013*cc4ad7daSAndroid Build Coastguard Worker 					ANSI_HIGHLIGHT_RED_ON, ANSI_HIGHLIGHT_OFF,
1014*cc4ad7daSAndroid Build Coastguard Worker 					t->name);
1015*cc4ad7daSAndroid Build Coastguard Worker 		}
1016*cc4ad7daSAndroid Build Coastguard Worker 	} else {
1017*cc4ad7daSAndroid Build Coastguard Worker 		if (err == 0) {
1018*cc4ad7daSAndroid Build Coastguard Worker 			if (matchout) {
1019*cc4ad7daSAndroid Build Coastguard Worker 				ERR("%sUNEXPECTED PASS%s: exit with 0: %s\n",
1020*cc4ad7daSAndroid Build Coastguard Worker 					ANSI_HIGHLIGHT_RED_ON, ANSI_HIGHLIGHT_OFF,
1021*cc4ad7daSAndroid Build Coastguard Worker 					t->name);
1022*cc4ad7daSAndroid Build Coastguard Worker 				err = EXIT_FAILURE;
1023*cc4ad7daSAndroid Build Coastguard Worker 			} else {
1024*cc4ad7daSAndroid Build Coastguard Worker 				ERR("%sUNEXPECTED PASS%s: exit with 0 and outputs do not match: %s\n",
1025*cc4ad7daSAndroid Build Coastguard Worker 					ANSI_HIGHLIGHT_RED_ON, ANSI_HIGHLIGHT_OFF,
1026*cc4ad7daSAndroid Build Coastguard Worker 					t->name);
1027*cc4ad7daSAndroid Build Coastguard Worker 				err = EXIT_FAILURE;
1028*cc4ad7daSAndroid Build Coastguard Worker 			}
1029*cc4ad7daSAndroid Build Coastguard Worker 		} else {
1030*cc4ad7daSAndroid Build Coastguard Worker 			if (matchout) {
1031*cc4ad7daSAndroid Build Coastguard Worker 				LOG("%sEXPECTED FAIL%s: %s\n",
1032*cc4ad7daSAndroid Build Coastguard Worker 					ANSI_HIGHLIGHT_GREEN_ON, ANSI_HIGHLIGHT_OFF,
1033*cc4ad7daSAndroid Build Coastguard Worker 					t->name);
1034*cc4ad7daSAndroid Build Coastguard Worker 				err = EXIT_SUCCESS;
1035*cc4ad7daSAndroid Build Coastguard Worker 			} else {
1036*cc4ad7daSAndroid Build Coastguard Worker 				LOG("%sEXPECTED FAIL%s: exit with %d but outputs do not match: %s\n",
1037*cc4ad7daSAndroid Build Coastguard Worker 					ANSI_HIGHLIGHT_GREEN_ON, ANSI_HIGHLIGHT_OFF,
1038*cc4ad7daSAndroid Build Coastguard Worker 					WEXITSTATUS(err), t->name);
1039*cc4ad7daSAndroid Build Coastguard Worker 				err = EXIT_FAILURE;
1040*cc4ad7daSAndroid Build Coastguard Worker 			}
1041*cc4ad7daSAndroid Build Coastguard Worker 		}
1042*cc4ad7daSAndroid Build Coastguard Worker 	}
1043*cc4ad7daSAndroid Build Coastguard Worker 
1044*cc4ad7daSAndroid Build Coastguard Worker exit:
1045*cc4ad7daSAndroid Build Coastguard Worker 	LOG("------\n");
1046*cc4ad7daSAndroid Build Coastguard Worker 	return err;
1047*cc4ad7daSAndroid Build Coastguard Worker }
1048*cc4ad7daSAndroid Build Coastguard Worker 
prepend_path(const char * extra)1049*cc4ad7daSAndroid Build Coastguard Worker static int prepend_path(const char *extra)
1050*cc4ad7daSAndroid Build Coastguard Worker {
1051*cc4ad7daSAndroid Build Coastguard Worker 	char *oldpath, *newpath;
1052*cc4ad7daSAndroid Build Coastguard Worker 	int r;
1053*cc4ad7daSAndroid Build Coastguard Worker 
1054*cc4ad7daSAndroid Build Coastguard Worker 	if (extra == NULL)
1055*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
1056*cc4ad7daSAndroid Build Coastguard Worker 
1057*cc4ad7daSAndroid Build Coastguard Worker 	oldpath = getenv("PATH");
1058*cc4ad7daSAndroid Build Coastguard Worker 	if (oldpath == NULL)
1059*cc4ad7daSAndroid Build Coastguard Worker 		return setenv("PATH", extra, 1);
1060*cc4ad7daSAndroid Build Coastguard Worker 
1061*cc4ad7daSAndroid Build Coastguard Worker 	if (asprintf(&newpath, "%s:%s", extra, oldpath) < 0) {
1062*cc4ad7daSAndroid Build Coastguard Worker 		ERR("failed to allocate memory to new PATH\n");
1063*cc4ad7daSAndroid Build Coastguard Worker 		return -1;
1064*cc4ad7daSAndroid Build Coastguard Worker 	}
1065*cc4ad7daSAndroid Build Coastguard Worker 
1066*cc4ad7daSAndroid Build Coastguard Worker 	r = setenv("PATH", newpath, 1);
1067*cc4ad7daSAndroid Build Coastguard Worker 	free(newpath);
1068*cc4ad7daSAndroid Build Coastguard Worker 
1069*cc4ad7daSAndroid Build Coastguard Worker 	return r;
1070*cc4ad7daSAndroid Build Coastguard Worker }
1071*cc4ad7daSAndroid Build Coastguard Worker 
test_run(const struct test * t)1072*cc4ad7daSAndroid Build Coastguard Worker int test_run(const struct test *t)
1073*cc4ad7daSAndroid Build Coastguard Worker {
1074*cc4ad7daSAndroid Build Coastguard Worker 	pid_t pid;
1075*cc4ad7daSAndroid Build Coastguard Worker 	int fdout[2];
1076*cc4ad7daSAndroid Build Coastguard Worker 	int fderr[2];
1077*cc4ad7daSAndroid Build Coastguard Worker 	int fdmonitor[2];
1078*cc4ad7daSAndroid Build Coastguard Worker 
1079*cc4ad7daSAndroid Build Coastguard Worker 	if (t->need_spawn && oneshot)
1080*cc4ad7daSAndroid Build Coastguard Worker 		test_run_spawned(t);
1081*cc4ad7daSAndroid Build Coastguard Worker 
1082*cc4ad7daSAndroid Build Coastguard Worker 	if (t->output.out != NULL) {
1083*cc4ad7daSAndroid Build Coastguard Worker 		if (pipe(fdout) != 0) {
1084*cc4ad7daSAndroid Build Coastguard Worker 			ERR("could not create out pipe for %s\n", t->name);
1085*cc4ad7daSAndroid Build Coastguard Worker 			return EXIT_FAILURE;
1086*cc4ad7daSAndroid Build Coastguard Worker 		}
1087*cc4ad7daSAndroid Build Coastguard Worker 	}
1088*cc4ad7daSAndroid Build Coastguard Worker 
1089*cc4ad7daSAndroid Build Coastguard Worker 	if (t->output.err != NULL) {
1090*cc4ad7daSAndroid Build Coastguard Worker 		if (pipe(fderr) != 0) {
1091*cc4ad7daSAndroid Build Coastguard Worker 			ERR("could not create err pipe for %s\n", t->name);
1092*cc4ad7daSAndroid Build Coastguard Worker 			return EXIT_FAILURE;
1093*cc4ad7daSAndroid Build Coastguard Worker 		}
1094*cc4ad7daSAndroid Build Coastguard Worker 	}
1095*cc4ad7daSAndroid Build Coastguard Worker 
1096*cc4ad7daSAndroid Build Coastguard Worker 	if (pipe(fdmonitor) != 0) {
1097*cc4ad7daSAndroid Build Coastguard Worker 		ERR("could not create monitor pipe for %s\n", t->name);
1098*cc4ad7daSAndroid Build Coastguard Worker 		return EXIT_FAILURE;
1099*cc4ad7daSAndroid Build Coastguard Worker 	}
1100*cc4ad7daSAndroid Build Coastguard Worker 
1101*cc4ad7daSAndroid Build Coastguard Worker 	if (prepend_path(t->path) < 0) {
1102*cc4ad7daSAndroid Build Coastguard Worker 		ERR("failed to prepend '%s' to PATH\n", t->path);
1103*cc4ad7daSAndroid Build Coastguard Worker 		return EXIT_FAILURE;
1104*cc4ad7daSAndroid Build Coastguard Worker 	}
1105*cc4ad7daSAndroid Build Coastguard Worker 
1106*cc4ad7daSAndroid Build Coastguard Worker 	LOG("running %s, in forked context\n", t->name);
1107*cc4ad7daSAndroid Build Coastguard Worker 
1108*cc4ad7daSAndroid Build Coastguard Worker 	pid = fork();
1109*cc4ad7daSAndroid Build Coastguard Worker 	if (pid < 0) {
1110*cc4ad7daSAndroid Build Coastguard Worker 		ERR("could not fork(): %m\n");
1111*cc4ad7daSAndroid Build Coastguard Worker 		LOG("FAILED: %s\n", t->name);
1112*cc4ad7daSAndroid Build Coastguard Worker 		return EXIT_FAILURE;
1113*cc4ad7daSAndroid Build Coastguard Worker 	}
1114*cc4ad7daSAndroid Build Coastguard Worker 
1115*cc4ad7daSAndroid Build Coastguard Worker 	if (pid > 0)
1116*cc4ad7daSAndroid Build Coastguard Worker 		return test_run_parent(t, fdout, fderr, fdmonitor, pid);
1117*cc4ad7daSAndroid Build Coastguard Worker 
1118*cc4ad7daSAndroid Build Coastguard Worker 	return test_run_child(t, fdout, fderr, fdmonitor);
1119*cc4ad7daSAndroid Build Coastguard Worker }
1120