From: Lucas De Marchi Date: Thu, 26 Jan 2012 04:09:28 +0000 (-0200) Subject: testsuite: add trap to init_module() including simple test X-Git-Tag: v5~56 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=53646fc56f32b7e3e7a2a8cd1e24aeb6b3422dbc;p=thirdparty%2Fkmod.git testsuite: add trap to init_module() including simple test --- diff --git a/Makefile.am b/Makefile.am index a6f6bcc3..0ccad623 100644 --- a/Makefile.am +++ b/Makefile.am @@ -145,8 +145,11 @@ testsuite/uname.so: testsuite/uname.c testsuite/path.so: testsuite/path.c $(CREATE_SHARED_OVERRIDE_LIB) -EXTRA_DIST += testsuite/uname.c testsuite/path.c -CLEANFILES += testsuite/uname.so testsuite/path.so +testsuite/init_module.so: testsuite/init_module.c $(abs_top_builddir)/libkmod/.libs/libkmod-private.a + $(CREATE_SHARED_OVERRIDE_LIB) + +EXTRA_DIST += testsuite/uname.c testsuite/path.c testsuite/init_module.c +CLEANFILES += testsuite/uname.so testsuite/path.so testsuite/init_module.so testsuite/rootfs: $(AM_V_GEN) tar -C testsuite/ \ @@ -167,6 +170,7 @@ testsuite_libtestsuite_la_SOURCES = testsuite/testsuite.c \ testsuite/testsuite.h testsuite_libtestsuite_la_DEPENDENCIES = testsuite/uname.so \ testsuite/path.so \ + testsuite/init_module.so \ testsuite/rootfs testsuite_libtestsuite_la_CPPFLAGS = $(TESTSUITE_CPPFLAGS) diff --git a/testsuite/init_module.c b/testsuite/init_module.c new file mode 100644 index 00000000..fd20c027 --- /dev/null +++ b/testsuite/init_module.c @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* kmod_elf_get_section() is not exported, we need the private header */ +#include + +/* FIXME: hack, change name so we don't clash */ +#undef ERR +#include "testsuite.h" +#include "stripped-module.h" + +struct mod { + struct mod *next; + int ret; + int errcode; + char name[]; +}; + +static struct mod *modules; +static bool need_init = true; + +static void parse_retcodes(struct mod *_modules, const char *s) +{ + const char *p; + + if (s == NULL) + return; + + for (p = s;;) { + struct mod *mod; + const char *modname; + char *end; + size_t modnamelen; + int ret, errcode; + long l; + + modname = p; + if (modname == NULL || modname[0] == '\0') + break; + + modnamelen = strcspn(s, ":"); + if (modname[modnamelen] != ':') + break; + + p = modname + modnamelen + 1; + if (p == NULL) + break; + + l = strtol(p, &end, 0); + if (end == p || *end != ':') + break; + ret = (int) l; + p = end + 1; + + l = strtol(p, &end, 0); + if (*end == ':') + p = end + 1; + else if (*end != '\0') + break; + + errcode = (int) l; + + mod = malloc(sizeof(*mod) + modnamelen + 1); + if (mod == NULL) + break; + + memcpy(mod->name, modname, modnamelen); + mod->name[modnamelen] = '\0'; + mod->ret = ret; + mod->errcode = errcode; + mod->next = _modules; + _modules = mod; + } +} + +static struct mod *find_module(struct mod *_modules, const char *modname) +{ + struct mod *mod; + + for (mod = _modules; mod != NULL; mod = mod->next) { + if (strcmp(mod->name, modname)) + return mod; + } + + return NULL; +} + +static void init_retcodes(void) +{ + const char *s; + + if (!need_init) + return; + + need_init = false; + s = getenv(S_TC_INIT_MODULE_RETCODES); + if (s == NULL) { + fprintf(stderr, "TRAP init_module(): missing export %s?\n", + S_TC_INIT_MODULE_RETCODES); + } + + parse_retcodes(modules, s); +} + +TS_EXPORT long init_module(void *mem, unsigned long len, const char *args); + +/* + * FIXME: change /sys/module/ to fake-insert a module + * + * Default behavior is to exit successfully. If this is not the intended + * behavior, set TESTSUITE_INIT_MODULE_RETCODES env var. + */ +long init_module(void *mem, unsigned long len, const char *args) +{ + const char *modname; + struct kmod_elf *elf; + struct mod *mod; + const void *buf; + uint64_t bufsize; + int err; + + init_retcodes(); + + elf = kmod_elf_new(mem, len); + if (elf == NULL) + return 0; + + err = kmod_elf_get_section(elf, ".gnu.linkonce.this_module", &buf, + &bufsize); + kmod_elf_unref(elf); + + /* + * We couldn't find the module's name inside the ELF file. Just exit + * as if it was successful + */ + if (err < 0) + return 0; + + modname = (char *)buf + offsetof(struct module, name); + mod = find_module(modules, modname); + if (mod == NULL) + return 0; + + errno = mod->errcode; + return mod->ret; +} + +/* the test is going away anyway, but lets keep valgrind happy */ +void free_resources(void) __attribute__((destructor)); +void free_resources(void) +{ + while (modules) { + struct mod *mod = modules->next; + free(modules); + modules = mod; + } +} diff --git a/testsuite/stripped-module.h b/testsuite/stripped-module.h new file mode 100644 index 00000000..9f97daeb --- /dev/null +++ b/testsuite/stripped-module.h @@ -0,0 +1,27 @@ +#ifndef _TESTSUITE_STRIPPED_MODULE_H +#define _TESTSUITE_STRIPPED_MODULE_H + +enum module_state +{ + MODULE_STATE_LIVE, + MODULE_STATE_COMING, + MODULE_STATE_GOING, +}; + +struct list_head { + struct list_head *next, *prev; +}; + +#define MODULE_NAME_LEN (64 - sizeof(unsigned long)) +struct module +{ + enum module_state state; + + /* Member of list of modules */ + struct list_head list; + + /* Unique handle for this module */ + char name[MODULE_NAME_LEN]; +}; + +#endif diff --git a/testsuite/test-init.c b/testsuite/test-init.c index 38011f81..ade1bde8 100644 --- a/testsuite/test-init.c +++ b/testsuite/test-init.c @@ -8,7 +8,7 @@ #include "testsuite.h" -static int testsuite_init(const struct test *t) +static int test_initlib(const struct test *t) { struct kmod_ctx *ctx; const char *null_config = NULL; @@ -21,14 +21,52 @@ static int testsuite_init(const struct test *t) exit(EXIT_SUCCESS); } -static const struct test stestsuite_init = { - .name = "testsuite_init", +static const struct test stest_initlib = { + .name = "test_initlib", .description = "test if libkmod's init function work", - .func = testsuite_init, + .func = test_initlib, +}; + +static int test_insert(const struct test *t) +{ + struct kmod_ctx *ctx; + struct kmod_module *mod; + const char *null_config = NULL; + int err; + + ctx = kmod_new(NULL, &null_config); + if (ctx == NULL) + exit(EXIT_FAILURE); + + err = kmod_module_new_from_path(ctx, "/ext4-x86_64.ko", &mod); + if (err != 0) { + ERR("could not create module from path: %m\n"); + exit(EXIT_FAILURE); + } + + err = kmod_module_insert_module(mod, 0, NULL); + if (err != 0) { + ERR("could not insert module: %m\n"); + exit(EXIT_FAILURE); + } + kmod_unref(ctx); + + exit(EXIT_SUCCESS); +} +static const struct test stest_insert = { + .name = "test_insert", + .description = "test if libkmod's insert_module returns ok", + .func = test_insert, + .config = { + [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modinfo/", + [TC_INIT_MODULE_RETCODES] = "bla:1:20", + }, + .need_spawn = true, }; static const struct test *tests[] = { - &stestsuite_init, + &stest_initlib, + &stest_insert, NULL, }; diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index bb0dacdb..7788b988 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -32,6 +32,7 @@ struct _env_config { } env_config[_TC_LAST] = { [TC_UNAME_R] = { S_TC_UNAME_R, ABS_TOP_BUILDDIR "/testsuite/uname.so" }, [TC_ROOTFS] = { S_TC_ROOTFS, ABS_TOP_BUILDDIR "/testsuite/path.so" }, + [TC_INIT_MODULE_RETCODES] = { S_TC_INIT_MODULE_RETCODES, ABS_TOP_BUILDDIR "/testsuite/init_module.so" }, }; static void help(void) diff --git a/testsuite/testsuite.h b/testsuite/testsuite.h index 4259b21b..68c82bb9 100644 --- a/testsuite/testsuite.h +++ b/testsuite/testsuite.h @@ -10,11 +10,13 @@ typedef int (*testfunc)(const struct test *t); enum test_config { TC_ROOTFS = 0, TC_UNAME_R, + TC_INIT_MODULE_RETCODES, _TC_LAST, }; #define S_TC_ROOTFS "TESTSUITE_ROOTFS" #define S_TC_UNAME_R "TESTSUITE_UNAME_R" +#define S_TC_INIT_MODULE_RETCODES "TESTSUITE_INIT_MODULE_RETCODES" struct test {