]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
testsuite: Improve fake_delete behavior
authorGongjun Song <gongjun.song@intel.com>
Fri, 7 Mar 2025 02:33:51 +0000 (10:33 +0800)
committerLucas De Marchi <lucas.de.marchi@gmail.com>
Fri, 7 Mar 2025 04:36:17 +0000 (22:36 -0600)
- When fake delete_module() succeeds, remove its entry from /sys/module.
- Add tests to ensure module is properly removed.

Co-developed-by: Qingqing Li <qingqing.li@intel.com>
Signed-off-by: Qingqing Li <qingqing.li@intel.com>
Signed-off-by: Dan He <dan.h.he@intel.com>
Signed-off-by: Gongjun Song <gongjun.song@intel.com>
Signed-off-by: Yuchi Chen <yuchi.chen@intel.com>
Signed-off-by: Wenjie Wang <wenjie2.wang@intel.com>
Link: https://github.com/kmod-project/kmod/pull/309
Signed-off-by: Lucas De Marchi <lucas.de.marchi@gmail.com>
testsuite/delete_module.c
testsuite/meson.build
testsuite/path.c
testsuite/test-remove.c [new file with mode: 0644]

index 25bfc1dc091559dd6c81f1680c62ed69c95a9536..64b5b1cd85aef627530766bf06673333110b5896 100644 (file)
@@ -19,6 +19,7 @@
 #include <unistd.h>
 
 #include <shared/util.h>
+#include <shared/strbuf.h>
 
 #include "testsuite.h"
 
@@ -122,24 +123,88 @@ static void init_retcodes(void)
        }
 }
 
-TS_EXPORT long delete_module(const char *name, unsigned int flags);
+static int remove_directory(const char *path)
+{
+       struct stat st;
+       DIR *dir;
+       struct dirent *entry;
+       char full_path[PATH_MAX];
+
+       if (stat(path, &st) != 0 || !S_ISDIR(st.st_mode)) {
+               LOG("Directory %s not found, skip remove.\n", path);
+               return 0;
+       }
+
+       dir = opendir(path);
+       if (!dir) {
+               ERR("Failed to open directory %s: %s (errno: %d)\n", path,
+                   strerror(errno), errno);
+               return -1;
+       }
+
+       while ((entry = readdir(dir)) != NULL) {
+               if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
+                       continue;
+
+               snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name);
+
+               if (entry->d_type == DT_DIR) {
+                       if (remove_directory(full_path) != 0) {
+                               ERR("Failed to remove directory %s: %m\n", full_path);
+                               goto fail;
+                       }
+               } else {
+                       if (remove(full_path) != 0) {
+                               ERR("Failed to remove file %s: %m\n", full_path);
+                               goto fail;
+                       }
+               }
+       }
+
+       closedir(dir);
+
+       if (rmdir(path) != 0) {
+               ERR("Failed to remove directory %s: %m\n", path);
+               return -1;
+       }
+
+       return 0;
+
+fail:
+       closedir(dir);
+
+       return -1;
+}
 
 /*
- * FIXME: change /sys/module/<modname> to fake-remove a module
- *
  * Default behavior is to exit successfully. If this is not the intended
  * behavior, set TESTSUITE_DELETE_MODULE_RETCODES env var.
  */
+TS_EXPORT long delete_module(const char *name, unsigned int flags);
+
 long delete_module(const char *modname, unsigned int flags)
 {
+       DECLARE_STRBUF_WITH_STACK(buf, PATH_MAX);
        struct mod *mod;
+       int ret = 0;
 
        init_retcodes();
        mod = find_module(modules, modname);
        if (mod == NULL)
                return 0;
 
+       if (!strbuf_pushchars(&buf, "/sys/module/") ||
+           !strbuf_pushchars(&buf, modname)) {
+               errno = ENOMEM;
+               return -1;
+       }
+
+       ret = remove_directory(strbuf_str(&buf));
+       if (ret != 0)
+               return ret;
+
        errno = mod->errcode;
+
        return mod->ret;
 }
 
index 1f49f69895da27c19adca65158c3d058f4022e5e..08e3cde92168a99f7239f16715f57687b44b5754 100644 (file)
@@ -95,6 +95,7 @@ _testsuite = [
   'test-testsuite',
   'test-util',
   'test-weakdep',
+  'test-remove'
 ]
 
 if get_option('b_sanitize') != 'none'
index b896885a00de143c91ccec7d53eb3e760cde4fe0..5acc1fd46276d81a4a15dd1887d2684621c66a23 100644 (file)
@@ -180,6 +180,8 @@ static void *get_libc_func(const char *f)
 
 WRAP_1ARG(DIR *, NULL, opendir);
 WRAP_1ARG(int, -1, chdir);
+WRAP_1ARG(int, -1, remove);
+WRAP_1ARG(int, -1, rmdir);
 
 WRAP_2ARGS(FILE *, NULL, fopen, const char *);
 WRAP_2ARGS(int, -1, mkdir, mode_t);
diff --git a/testsuite/test-remove.c b/testsuite/test-remove.c
new file mode 100644 (file)
index 0000000..a68a718
--- /dev/null
@@ -0,0 +1,61 @@
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <shared/macro.h>
+
+#include <libkmod/libkmod.h>
+
+#include "testsuite.h"
+
+static noreturn int test_remove(const struct test *t)
+{
+       struct kmod_ctx *ctx;
+       struct kmod_module *mod;
+       const char *null_config = NULL;
+       int err;
+       struct stat st;
+
+       ctx = kmod_new(NULL, &null_config);
+       if (ctx == NULL)
+               exit(EXIT_FAILURE);
+
+       err = kmod_module_new_from_path(ctx, "/mod-simple.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);
+       }
+
+       err = kmod_module_remove_module(mod, 0);
+       if (err != 0) {
+               ERR("could not remove module: %m\n");
+               exit(EXIT_FAILURE);
+       }
+
+       if (stat("/sys/module/mod_simple", &st) == 0 && S_ISDIR(st.st_mode)) {
+               ERR("could not remove module directory.\n");
+               exit(EXIT_FAILURE);
+       }
+       kmod_unref(ctx);
+
+       exit(EXIT_SUCCESS);
+}
+DEFINE_TEST(test_remove,
+           .description = "test if libkmod's delete_module removes module directory",
+           .config = {
+                   [TC_ROOTFS] = TESTSUITE_ROOTFS "test-remove/",
+                   [TC_INIT_MODULE_RETCODES] = "",
+                   [TC_DELETE_MODULE_RETCODES] = "mod_simple:0:0" STRINGIFY(ENOENT),
+           });
+
+TESTSUITE_MAIN();