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