]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
testsuite: add trap to init_module() including simple test
authorLucas De Marchi <lucas.demarchi@profusion.mobi>
Thu, 26 Jan 2012 04:09:28 +0000 (02:09 -0200)
committerLucas De Marchi <lucas.demarchi@profusion.mobi>
Thu, 26 Jan 2012 18:05:05 +0000 (16:05 -0200)
Makefile.am
testsuite/init_module.c [new file with mode: 0644]
testsuite/stripped-module.h [new file with mode: 0644]
testsuite/test-init.c
testsuite/testsuite.c
testsuite/testsuite.h

index a6f6bcc341850f31da0d7b7897fc152fa205c01c..0ccad6231e27f7c708a8eef67ab8af272cd4021b 100644 (file)
@@ -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 (file)
index 0000000..fd20c02
--- /dev/null
@@ -0,0 +1,169 @@
+#include <assert.h>
+#include <errno.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* kmod_elf_get_section() is not exported, we need the private header */
+#include <libkmod-private.h>
+
+/* 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/<modname> 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 (file)
index 0000000..9f97dae
--- /dev/null
@@ -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
index 38011f81c822326ae587953bee363eacff3957ac..ade1bde86f0cf145387e008b1274925b3c36d5db 100644 (file)
@@ -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,
 };
 
index bb0dacdb0ad48aae94126820a0559ef1ed0cb34f..7788b98876bcc102c6f3ba22b91afbc0839a1136 100644 (file)
@@ -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)
index 4259b21be21e9545ca76796181f87e271ba344cc..68c82bb9950a09e86e4242f113c05ce3ca577088 100644 (file)
@@ -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 {