From: Lucas De Marchi Date: Tue, 24 Jan 2012 22:59:54 +0000 (-0200) Subject: testsuite: add skeleton X-Git-Tag: v5~74 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80f9e02382fa9e65ec903dd53d62f949078205ee;p=thirdparty%2Fkmod.git testsuite: add skeleton --- diff --git a/Makefile.am b/Makefile.am index 0dd48ff1..857774ca 100644 --- a/Makefile.am +++ b/Makefile.am @@ -128,30 +128,10 @@ ${noinst_SCRIPTS}: tools/kmod-nolib $(LN_S) $(notdir $<) $@) endif -check_PROGRAMS = test/test-init test/test-loaded \ - test/test-insmod test/test-rmmod test/test-rmmod2 \ - test/test-lookup test/test-path-from-name \ - test/test-get-dependencies test/test-mod-double-ref \ - test/test-blacklist test/test-elf test/test-probe \ - test/test-invalidate-config test/test-state - -TESTS = test/test-init test/test-loaded - -test_test_init_LDADD = libkmod/libkmod-private.la -test_test_loaded_LDADD = libkmod/libkmod-private.la - -test_test_rmmod_LDADD = libkmod/libkmod-private.la -test_test_rmmod2_LDADD = libkmod/libkmod-private.la -test_test_insmod_LDADD = libkmod/libkmod-private.la -test_test_lookup_LDADD = libkmod/libkmod-private.la -test_test_path_from_name_LDADD = libkmod/libkmod-private.la -test_test_get_dependencies_LDADD = libkmod/libkmod-private.la -test_test_mod_double_ref_LDADD = libkmod/libkmod-private.la -test_test_blacklist_LDADD = libkmod/libkmod-private.la -test_test_elf_LDADD = libkmod/libkmod-private.la -test_test_probe_LDADD = libkmod/libkmod-private.la -test_test_invalidate_config_LDADD = libkmod/libkmod-private.la -test_test_state_LDADD = libkmod/libkmod-private.la +check_LTLIBRARIES = testsuite/libtestsuite.la +testsuite_libtestsuite_la_SOURCES = testsuite/testsuite.c \ + testsuite/testsuite.h +testsuite_libtestsuite_la_DEPENDENCIES = testsuite/uname.so DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc diff --git a/configure.ac b/configure.ac index 19f78d52..73d880ee 100644 --- a/configure.ac +++ b/configure.ac @@ -8,7 +8,7 @@ AC_INIT([kmod], AC_CONFIG_SRCDIR([libkmod/libkmod.c]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([check-news foreign 1.11 silent-rules - tar-pax no-dist-gzip dist-xz subdir-objects]) + tar-pax no-dist-gzip dist-xz subdir-objects color-tests]) AC_PROG_CC_STDC AC_USE_SYSTEM_EXTENSIONS AC_SYS_LARGEFILE diff --git a/test/.gitignore b/test/.gitignore deleted file mode 100644 index 61f27382..00000000 --- a/test/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -.dirstamp -test-init -test-loaded -test-rmmod -test-rmmod2 -test-insmod -test-lookup -test-path-from-name -test-get-dependencies -test-mod-double-ref -test-blacklist -test-elf -test-probe -test-invalidate-config -test-state diff --git a/testsuite/.gitignore b/testsuite/.gitignore new file mode 100644 index 00000000..f4fd00f3 --- /dev/null +++ b/testsuite/.gitignore @@ -0,0 +1,5 @@ +.dirstamp +*.lo +*.la +*.so +test-testsuite diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c new file mode 100644 index 00000000..dac79ac3 --- /dev/null +++ b/testsuite/testsuite.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "testsuite.h" + +static const char *progname; +int oneshot = 0; +static const char options_short[] = "lhn"; +static const struct option options[] = { + { "list", no_argument, 0, 'l' }, + { "help", no_argument, 0, 'h' }, + { NULL, 0, 0, 0 } +}; + +static void help(void) +{ + const struct option *itr; + const char *itr_short; + + printf("Usage:\n" + "\t%s [options] \n" + "Options:\n", basename(progname)); + + for (itr = options, itr_short = options_short; + itr->name != NULL; itr++, itr_short++) + printf("\t-%c, --%s\n", *itr_short, itr->name); +} + +static void test_list(const struct test *tests[]) +{ + size_t i; + + printf("Available tests:\n"); + for (i = 0; tests[i] != NULL; i++) + printf("\t%s, %s\n", tests[i]->name, tests[i]->description); +} + +int test_init(int argc, char *const argv[], const struct test *tests[]) +{ + progname = argv[0]; + + for (;;) { + int c, idx = 0; + c = getopt_long(argc, argv, options_short, options, &idx); + if (c == -1) + break; + switch (c) { + case 'l': + test_list(tests); + return 0; + case 'h': + help(); + return 0; + case 'n': + oneshot = 1; + break; + case '?': + return -1; + default: + ERR("unexpected getopt_long() value %c\n", c); + return -1; + } + } + + return optind; +} + +const struct test *test_find(const struct test *tests[], const char *name) +{ + size_t i; + + for (i = 0; tests[i] != NULL; i++) { + if (strcmp(tests[i]->name, name) == 0) + return tests[i]; + } + + return NULL; +} + +int test_spawn_test(const struct test *t) +{ + const char *const args[] = { progname, "-n", t->name, NULL }; + + execv(progname, (char *const *) args); + + ERR("failed to spawn %s for %s: %m\n", progname, t->name); + return EXIT_FAILURE; +} + +int test_spawn_prog(const char *prog, const char *args[]) +{ + execv(prog, (char *const *) args); + + ERR("failed to spawn %s ", prog); + return EXIT_FAILURE; +} + +int test_run_spawned(const struct test *t) +{ + int err = t->func(t); + exit(err); +} + +int test_run(const struct test *t) +{ + int err; + pid_t pid; + + LOG("running %s, in forked context\n", t->name); + + pid = fork(); + if (pid < 0) { + ERR("could not fork(): %m\n"); + LOG("FAILED: %s\n", t->name); + return EXIT_FAILURE; + } + + if (pid > 0) { + do { + pid = wait(&err); + if (pid == -1) { + ERR("error waitpid(): %m\n"); + return EXIT_FAILURE; + } + } while (!WIFEXITED(err) && !WIFSIGNALED(err)); + + if (err != 0) + ERR("error while running %s\n", t->name); + + LOG("%s: %s\n", err == 0 ? "PASSED" : "FAILED", t->name); + return err; + } + + /* kill child if parent dies */ + prctl(PR_SET_PDEATHSIG, SIGTERM); + test_run_spawned(t); +} diff --git a/testsuite/testsuite.h b/testsuite/testsuite.h new file mode 100644 index 00000000..919bc6e7 --- /dev/null +++ b/testsuite/testsuite.h @@ -0,0 +1,48 @@ +#ifndef _LIBKMOD_TESTSUITE_ +#define _LIBKMOD_TESTSUITE_ + +#include +#include + +struct test; +typedef int (*testfunc)(const struct test *t); + +enum test_config { + TC_ROOTFS = 0, + TC_UNAME_R, + _TC_LAST, +}; + +struct test { + const char *name; + const char *description; + testfunc func; + const char *config[_TC_LAST]; +}; + + +const struct test *test_find(const struct test *tests[], const char *name); +int test_init(int argc, char *const argv[], const struct test *tests[]); +int test_spawn_test(const struct test *t); +int test_spawn_prog(const char *prog, const char *args[]); + +int test_run(const struct test *t); +__attribute__((noreturn)) int test_run_spawned(const struct test *t); + +extern int oneshot; + +#define TS_EXPORT __attribute__ ((visibility("default"))) + +#define _LOG(prefix, fmt, ...) printf("TESTSUITE: " prefix fmt, ## __VA_ARGS__) +#define LOG(fmt, ...) _LOG("", fmt, ## __VA_ARGS__) +#define WARN(fmt, ...) _LOG("WARN: ", fmt, ## __VA_ARGS__) +#define ERR(fmt, ...) _LOG("ERR: ", fmt, ## __VA_ARGS__) + +/* Test definitions */ +#define DEFINE_TEST(_name) \ + struct test s_name = { \ + .name = #_name, \ + .func = _name, \ + } + +#endif