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