From: Lucas De Marchi Date: Wed, 6 Jun 2012 04:03:15 +0000 (-0300) Subject: testsuite: add timeout for each test X-Git-Tag: v9~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b8e344a6d2c9526a7476b78255185a96097f2629;p=thirdparty%2Fkmod.git testsuite: add timeout for each test Each test must run under 2 seconds. Ideally they should run in much less than this; just give an arbitrary number so we don't wait forever in case we reached an infinite loop somewhere. --- diff --git a/Makefile.am b/Makefile.am index 5751dbd5..faad5b8b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -169,6 +169,7 @@ testsuite_libtestsuite_la_SOURCES = testsuite/testsuite.c \ testsuite_libtestsuite_la_DEPENDENCIES = $(ROOTFS) \ $(TESTSUITE_OVERRIDE_LIBS) testsuite_libtestsuite_la_CPPFLAGS = $(TESTSUITE_CPPFLAGS) +testsuite_libtestsuite_la_LIBADD = -lrt TESTSUITE = testsuite/test-init testsuite/test-testsuite testsuite/test-loaded \ testsuite/test-modinfo testsuite/test-alias testsuite/test-new-module \ diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index de1a0fad..14af73ed 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,19 @@ struct _env_config { [TC_DELETE_MODULE_RETCODES] = { S_TC_DELETE_MODULE_RETCODES, OVERRIDE_LIBDIR "delete_module.so" }, }; +#define USEC_PER_SEC 1000000ULL +#define USEC_PER_MSEC 1000ULL +#define TEST_TIMEOUT_USEC 2 * USEC_PER_SEC +static unsigned long long now_usec(void) +{ + struct timespec ts; + + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) + return 0; + + return ts_usec(&ts); +} + static void help(void) { const struct option *itr; @@ -251,10 +265,11 @@ static inline int test_run_child(const struct test *t, int fdout[2], } static inline bool test_run_parent_check_outputs(const struct test *t, - int fdout, int fderr, int fdmonitor) + int fdout, int fderr, int fdmonitor, pid_t child) { struct epoll_event ep_outpipe, ep_errpipe, ep_monitor; int err, fd_ep, fd_matchout = -1, fd_matcherr = -1; + unsigned long long end_usec, start_usec; fd_ep = epoll_create1(EPOLL_CLOEXEC); if (fd_ep < 0) { @@ -310,11 +325,19 @@ static inline bool test_run_parent_check_outputs(const struct test *t, goto out; } + start_usec = now_usec(); + end_usec = start_usec + TEST_TIMEOUT_USEC; + for (err = 0; fdmonitor >= 0 || fdout >= 0 || fderr >= 0;) { - int fdcount, i; + int fdcount, i, timeout; struct epoll_event ev[4]; + unsigned long long curr_usec = now_usec(); - fdcount = epoll_wait(fd_ep, ev, 4, -1); + if (curr_usec > end_usec) + break; + + timeout = (end_usec - curr_usec) / USEC_PER_MSEC; + fdcount = epoll_wait(fd_ep, ev, 4, timeout); if (fdcount < 0) { if (errno == EINTR) continue; @@ -388,8 +411,14 @@ static inline bool test_run_parent_check_outputs(const struct test *t, *fd = -1; } } + } + if (err == 0 && fdmonitor >= 0) { + err = -EINVAL; + ERR("Test '%s' timed out, killing %d\n", t->name, child); + kill(child, SIGKILL); } + out: if (fd_matchout >= 0) close(fd_matchout); @@ -401,7 +430,7 @@ out: } static inline int test_run_parent(const struct test *t, int fdout[2], - int fderr[2], int fdmonitor[2]) + int fderr[2], int fdmonitor[2], pid_t child) { pid_t pid; int err; @@ -415,7 +444,7 @@ static inline int test_run_parent(const struct test *t, int fdout[2], close(fdmonitor[1]); matchout = test_run_parent_check_outputs(t, fdout[0], fderr[0], - fdmonitor[0]); + fdmonitor[0], child); /* * break pipe on the other end: either child already closed or we want @@ -445,6 +474,7 @@ static inline int test_run_parent(const struct test *t, int fdout[2], } else if (WIFSIGNALED(err)) { ERR("'%s' [%u] terminated by signal %d (%s)\n", t->name, pid, WTERMSIG(err), strsignal(WTERMSIG(err))); + return EXIT_FAILURE; } if (t->expected_fail == false) { @@ -552,7 +582,7 @@ int test_run(const struct test *t) } if (pid > 0) - return test_run_parent(t, fdout, fderr, fdmonitor); + return test_run_parent(t, fdout, fderr, fdmonitor, pid); return test_run_child(t, fdout, fderr, fdmonitor); }