]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
testsuite: Check the list of loaded modules after a test
authorMichal Marek <mmarek@suse.cz>
Fri, 28 Feb 2014 12:05:28 +0000 (13:05 +0100)
committerLucas De Marchi <lucas.demarchi@intel.com>
Wed, 5 Mar 2014 15:22:37 +0000 (12:22 -0300)
Add a ->modules_loaded member to struct test, which is a comma-separated
list of modules that should be present after the test finishes. Both
missing and excess modules cause an error.

testsuite/test-init.c
testsuite/test-modprobe.c
testsuite/testsuite.c
testsuite/testsuite.h

index 63b65013b0f755984ec358e65735ec81a27d3147..d2aa4bd393ffd6d3fe6d1eafdfd1eebb2a54b04b 100644 (file)
@@ -74,6 +74,7 @@ static DEFINE_TEST(test_insert,
                [TC_ROOTFS] = TESTSUITE_ROOTFS "test-init/",
                [TC_INIT_MODULE_RETCODES] = "bla:1:20",
        },
+       .modules_loaded = "ext4",
        .need_spawn = true);
 
 static noreturn int test_remove(const struct test *t)
index 637d363ea824cb1d08408358732e43c5b09b9b49..c3ef31e755e06b8b10ce7d32bbe116c3211cf621 100644 (file)
@@ -91,7 +91,9 @@ static DEFINE_TEST(modprobe_show_alias_to_none,
        },
        .output = {
                .out = TESTSUITE_ROOTFS "test-modprobe/show-depends/correct-psmouse.txt",
-       });
+       },
+       .modules_loaded = "",
+       );
 
 
 static noreturn int modprobe_builtin(const struct test *t)
@@ -131,7 +133,9 @@ static DEFINE_TEST(modprobe_softdep_loop,
                [TC_UNAME_R] = "4.4.4",
                [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/softdep-loop",
                [TC_INIT_MODULE_RETCODES] = "",
-       });
+       },
+       .modules_loaded = "btusb,bluetooth",
+       );
 
 static noreturn int modprobe_install_cmd_loop(const struct test *t)
 {
@@ -156,6 +160,7 @@ static DEFINE_TEST(modprobe_install_cmd_loop,
                { "MODPROBE", ABS_TOP_BUILDDIR "/tools/modprobe" },
                { }
                },
+       .modules_loaded = "snd,snd-pcm",
        );
 
 static noreturn int modprobe_param_kcmdline(const struct test *t)
@@ -178,7 +183,9 @@ static DEFINE_TEST(modprobe_param_kcmdline,
        },
        .output = {
                .out = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline/correct.txt",
-       });
+       },
+       .modules_loaded = "",
+       );
 
 
 static const struct test *tests[] = {
index 9877a64cd52827030777046e20c01d9f8e1254ac..c29ca7857e0d9fc6e31ce3a376a790ac33f48335 100644 (file)
@@ -20,6 +20,7 @@
 #include <fcntl.h>
 #include <getopt.h>
 #include <limits.h>
+#include <dirent.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <stdlib.h>
@@ -528,12 +529,189 @@ fail:
        return true;
 }
 
+static int cmp_modnames(const void *m1, const void *m2)
+{
+       const char *s1 = *(char *const *)m1;
+       const char *s2 = *(char *const *)m2;
+       int i;
+
+       for (i = 0; s1[i] || s2[i]; i++) {
+               char c1 = s1[i], c2 = s2[i];
+               if (c1 == '-')
+                       c1 = '_';
+               if (c2 == '-')
+                       c2 = '_';
+               if (c1 != c2)
+                       return c1 - c2;
+       }
+       return 0;
+}
+
+/*
+ * Store the expected module names in buf and return a list of pointers to
+ * them.
+ */
+static const char **read_expected_modules(const struct test *t,
+               char **buf, int *count)
+{
+       const char **res;
+       int len;
+       int i;
+       char *p;
+
+       if (t->modules_loaded[0] == '\0') {
+               *count = 0;
+               *buf = NULL;
+               return NULL;
+       }
+       *buf = strdup(t->modules_loaded);
+       if (!*buf) {
+               *count = -1;
+               return NULL;
+       }
+       len = 1;
+       for (p = *buf; *p; p++)
+               if (*p == ',')
+                       len++;
+       res = malloc(sizeof(char *) * len);
+       if (!res) {
+               perror("malloc");
+               *count = -1;
+               free(*buf);
+               *buf = NULL;
+               return NULL;
+       }
+       i = 0;
+       res[i++] = *buf;
+       for (p = *buf; i < len; p++)
+               if (*p == ',') {
+                       *p = '\0';
+                       res[i++] = p + 1;
+               }
+       *count = len;
+       return res;
+}
+
+static char **read_loaded_modules(const struct test *t, char **buf, int *count)
+{
+       char dirname[PATH_MAX];
+       DIR *dir;
+       struct dirent *dirent;
+       int i;
+       int len = 0, bufsz;
+       char **res = NULL;
+       char *p;
+       const char *rootfs = t->config[TC_ROOTFS] ? t->config[TC_ROOTFS] : "";
+
+       /* Store the entries in /sys/module to res */
+       if (snprintf(dirname, sizeof(dirname), "%s/sys/module", rootfs)
+                       >= (int)sizeof(dirname)) {
+               ERR("rootfs path too long: %s\n", rootfs);
+               *buf = NULL;
+               len = -1;
+               goto out;
+       }
+       dir = opendir(dirname);
+       /* not an error, simply return empty list */
+       if (!dir) {
+               *buf = NULL;
+               goto out;
+       }
+       bufsz = 0;
+       while ((dirent = readdir(dir))) {
+               if (dirent->d_name[0] == '.')
+                       continue;
+               len++;
+               bufsz += strlen(dirent->d_name) + 1;
+       }
+       res = malloc(sizeof(char *) * len);
+       if (!res) {
+               perror("malloc");
+               len = -1;
+               goto out_dir;
+       }
+       *buf = malloc(bufsz);
+       if (!*buf) {
+               perror("malloc");
+               free(res);
+               res = NULL;
+               len = -1;
+               goto out_dir;
+       }
+       rewinddir(dir);
+       i = 0;
+       p = *buf;
+       while ((dirent = readdir(dir))) {
+               int size;
+
+               if (dirent->d_name[0] == '.')
+                       continue;
+               size = strlen(dirent->d_name) + 1;
+               memcpy(p, dirent->d_name, size);
+               res[i++] = p;
+               p += size;
+       }
+out_dir:
+       closedir(dir);
+out:
+       *count = len;
+       return res;
+}
+
+static int check_loaded_modules(const struct test *t)
+{
+       int l1, l2, i1, i2;
+       const char **a1;
+       char **a2;
+       char *buf1, *buf2;
+       int err = false;
+
+       a1 = read_expected_modules(t, &buf1, &l1);
+       if (l1 < 0)
+               return err;
+       a2 = read_loaded_modules(t, &buf2, &l2);
+       if (l2 < 0)
+               goto out_a1;
+       qsort(a1, l1, sizeof(char *), cmp_modnames);
+       qsort(a2, l2, sizeof(char *), cmp_modnames);
+       i1 = i2 = 0;
+       err = true;
+       while (i1 < l1 || i2 < l2) {
+               int cmp;
+
+               if (i1 >= l1)
+                       cmp = 1;
+               else if (i2 >= l2)
+                       cmp = -1;
+               else
+                       cmp = cmp_modnames(&a1[i1], &a2[i2]);
+               if (cmp == 0) {
+                       i1++;
+                       i2++;
+               } else if (cmp < 0) {
+                       err = false;
+                       ERR("module %s not loaded\n", a1[i1]);
+                       i1++;
+               } else  {
+                       err = false;
+                       ERR("module %s is loaded but should not be \n", a2[i2]);
+                       i2++;
+               }
+       }
+       free(a2);
+       free(buf2);
+out_a1:
+       free(a1);
+       free(buf1);
+       return err;
+}
+
 static inline int test_run_parent(const struct test *t, int fdout[2],
                                int fderr[2], int fdmonitor[2], pid_t child)
 {
        pid_t pid;
        int err;
-       bool matchout;
+       bool matchout, match_modules;
 
        /* Close write-fds */
        if (t->output.out != NULL)
@@ -578,16 +756,21 @@ static inline int test_run_parent(const struct test *t, int fdout[2],
 
        if (matchout)
                matchout = check_generated_files(t);
+       if (t->modules_loaded)
+               match_modules = check_loaded_modules(t);
+       else
+               match_modules = true;
 
        if (t->expected_fail == false) {
                if (err == 0) {
-                       if (matchout)
+                       if (matchout && match_modules)
                                LOG("%sPASSED%s: %s\n",
                                        ANSI_HIGHLIGHT_GREEN_ON, ANSI_HIGHLIGHT_OFF,
                                        t->name);
                        else {
-                               ERR("%sFAILED%s: exit ok but outputs do not match: %s\n",
+                               ERR("%sFAILED%s: exit ok but %s do not match: %s\n",
                                        ANSI_HIGHLIGHT_RED_ON, ANSI_HIGHLIGHT_OFF,
+                                       matchout ? "loaded modules" : "outputs",
                                        t->name);
                                err = EXIT_FAILURE;
                        }
index 97183cdedea81e0f37771caff0770ac364dbabc1..f2a75e5dd44266b19935861ca044c5ebff5f8733 100644 (file)
@@ -95,6 +95,8 @@ struct test {
                 */
                const struct keyval *files;
        } output;
+       /* comma-separated list of loaded modules at the end of the test */
+       const char *modules_loaded;
        testfunc func;
        const char *config[_TC_LAST];
        const char *path;