diff --git a/testsuite/README b/testsuite/README index 198bce24..e1d6d77a 100644 --- a/testsuite/README +++ b/testsuite/README @@ -39,27 +39,22 @@ pay attention when writing a test: 4 - Fill in the config vector. Setting any of these configuration will make testsuite to export LD_PRELOAD with the necessary override libs before - executing the test. If you are not exec'ing an external binary, you need to - pass "need_spawn = true" below, otherwise it will not work (LD_PRELOAD is - only applied when exec'ing a binary). See each config description in - testsuite.h + executing the test. See each config description in testsuite.h -5 - need_spawn: if testsuite will exec itself before running a test - -6 - expected_fail: if that test is expected to fail, i.e. the return code is +5 - expected_fail: if that test is expected to fail, i.e. the return code is expected not to be 0. -7 - The rootfs is populated by copying the entire contents of rootfs-pristine +6 - The rootfs is populated by copying the entire contents of rootfs-pristine through setup-rootfs.sh then running setup-modules.sh to copy generated modules from module-playground. Update the latter script to include any modules your test needs. -8 - Tests can be run individually, outside of 'meson test'. strace and gdb +7 - Tests can be run individually, outside of 'meson test'. strace and gdb work too, as long as you tell them to operate on child process. When running with sanitizers, make sure to 'source scripts/sanitizer-env.sh'. Sanitizers are not guaranteed to work well with other tools like strace and gdb. -9 - Make sure test passes when using "default" build flags, i.e. by running +8 - Make sure test passes when using "default" build flags, i.e. by running 'meson setup --native-file build-dev.ini ...', which by default enables the sanitizers. diff --git a/testsuite/test-blacklist.c b/testsuite/test-blacklist.c index 4c741d3c..580a259e 100644 --- a/testsuite/test-blacklist.c +++ b/testsuite/test-blacklist.c @@ -81,12 +81,9 @@ static int blacklist_1(const struct test *t) return EXIT_FAILURE; } -DEFINE_TEST(blacklist_1, - .description = "check if modules are correctly blacklisted", - .config = { - [TC_ROOTFS] = TESTSUITE_ROOTFS "test-blacklist/", - }, - .need_spawn = true, -); +DEFINE_TEST(blacklist_1, .description = "check if modules are correctly blacklisted", + .config = { + [TC_ROOTFS] = TESTSUITE_ROOTFS "test-blacklist/", + }); TESTSUITE_MAIN(); diff --git a/testsuite/test-dependencies.c b/testsuite/test-dependencies.c index 5358f7c2..f315af1b 100644 --- a/testsuite/test-dependencies.c +++ b/testsuite/test-dependencies.c @@ -67,11 +67,10 @@ static noreturn int test_dependencies(const struct test *t) exit(EXIT_SUCCESS); } DEFINE_TEST(test_dependencies, - .description = "test if kmod_module_get_dependencies works", - .config = { - [TC_UNAME_R] = TEST_UNAME, - [TC_ROOTFS] = TESTSUITE_ROOTFS "test-dependencies/", - }, - .need_spawn = true); + .description = "test if kmod_module_get_dependencies works", + .config = { + [TC_UNAME_R] = TEST_UNAME, + [TC_ROOTFS] = TESTSUITE_ROOTFS "test-dependencies/", + }); TESTSUITE_MAIN(); diff --git a/testsuite/test-init.c b/testsuite/test-init.c index 2c825dfb..d23e8a34 100644 --- a/testsuite/test-init.c +++ b/testsuite/test-init.c @@ -39,21 +39,24 @@ static noreturn int test_load_resources(const struct test *t) exit(EXIT_SUCCESS); } -DEFINE_TEST(test_load_resources, - .description = "test if kmod_load_resources works (recent modprobe on kernel without modules.builtin.modinfo)", - .config = { +DEFINE_TEST_WITH_FUNC( + test_load_resource1, test_load_resources, + .description = + "test if kmod_load_resources works (recent modprobe on kernel without modules.builtin.modinfo)", + .config = { [TC_ROOTFS] = TESTSUITE_ROOTFS "test-init-load-resources/", [TC_UNAME_R] = "5.6.0", - }, - .need_spawn = true); + }); -DEFINE_TEST(test_load_resources, - .description = "test if kmod_load_resources works with empty modules.builtin.aliases.bin (recent depmod on kernel without modules.builtin.modinfo)", - .config = { - [TC_ROOTFS] = TESTSUITE_ROOTFS "test-init-load-resources-empty-builtin-aliases-bin/", +DEFINE_TEST_WITH_FUNC( + test_load_resource2, test_load_resources, + .description = + "test if kmod_load_resources works with empty modules.builtin.aliases.bin (recent depmod on kernel without modules.builtin.modinfo)", + .config = { + [TC_ROOTFS] = TESTSUITE_ROOTFS + "test-init-load-resources-empty-builtin-aliases-bin/", [TC_UNAME_R] = "5.6.0", - }, - .need_spawn = true); + }); static noreturn int test_initlib(const struct test *t) { @@ -102,8 +105,7 @@ DEFINE_TEST(test_insert, [TC_ROOTFS] = TESTSUITE_ROOTFS "test-init/", [TC_INIT_MODULE_RETCODES] = "bla:1:20", }, - .modules_loaded = "mod_simple", - .need_spawn = true); + .modules_loaded = "mod_simple"); static noreturn int test_remove(const struct test *t) { @@ -144,13 +146,11 @@ static noreturn int test_remove(const struct test *t) exit(EXIT_SUCCESS); } -DEFINE_TEST(test_remove, - .description = "test if libkmod's remove_module returns ok", +DEFINE_TEST( + test_remove, .description = "test if libkmod's remove_module returns ok", .config = { [TC_ROOTFS] = TESTSUITE_ROOTFS "test-remove/", - [TC_DELETE_MODULE_RETCODES] = - "mod-simple:0:0:bla:-1:" STRINGIFY(ENOENT), - }, - .need_spawn = true); + [TC_DELETE_MODULE_RETCODES] = "mod-simple:0:0:bla:-1:" STRINGIFY(ENOENT), + }); TESTSUITE_MAIN(); diff --git a/testsuite/test-initstate.c b/testsuite/test-initstate.c index f29aced1..92ad0e37 100644 --- a/testsuite/test-initstate.c +++ b/testsuite/test-initstate.c @@ -57,13 +57,14 @@ static noreturn int test_initstate_from_lookup(const struct test *t) exit(EXIT_SUCCESS); } -DEFINE_TEST(test_initstate_from_lookup, - .description = "test if libkmod return correct initstate for builtin module from lookup", +DEFINE_TEST( + test_initstate_from_lookup, + .description = + "test if libkmod return correct initstate for builtin module from lookup", .config = { [TC_ROOTFS] = TESTSUITE_ROOTFS "test-initstate", [TC_UNAME_R] = "4.4.4", - }, - .need_spawn = true); + }); static noreturn int test_initstate_from_name(const struct test *t) { @@ -100,11 +101,11 @@ static noreturn int test_initstate_from_name(const struct test *t) exit(EXIT_SUCCESS); } DEFINE_TEST(test_initstate_from_name, - .description = "test if libkmod return correct initstate for builtin module from name", - .config = { - [TC_ROOTFS] = TESTSUITE_ROOTFS "test-initstate", - [TC_UNAME_R] = "4.4.4", - }, - .need_spawn = true); + .description = + "test if libkmod return correct initstate for builtin module from name", + .config = { + [TC_ROOTFS] = TESTSUITE_ROOTFS "test-initstate", + [TC_UNAME_R] = "4.4.4", + }); TESTSUITE_MAIN(); diff --git a/testsuite/test-loaded.c b/testsuite/test-loaded.c index 9bf8eb79..ad8e37e0 100644 --- a/testsuite/test-loaded.c +++ b/testsuite/test-loaded.c @@ -71,7 +71,6 @@ DEFINE_TEST(loaded_1, .config = { [TC_ROOTFS] = TESTSUITE_ROOTFS "test-loaded/", }, - .need_spawn = true, .output = { .out = TESTSUITE_ROOTFS "test-loaded/correct.txt", }); diff --git a/testsuite/test-modprobe.c b/testsuite/test-modprobe.c index cbdd9c75..8dc18311 100644 --- a/testsuite/test-modprobe.c +++ b/testsuite/test-modprobe.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -13,17 +14,13 @@ #include "testsuite.h" +#define EXEC_MODPROBE(...) \ + test_spawn_prog(TOOLS_DIR "/modprobe", \ + (const char *[]){ TOOLS_DIR "/modprobe", ##__VA_ARGS__, NULL }) + static noreturn int modprobe_show_depends(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "--show-depends", - "mod-loop-a", - NULL, - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("--show-depends", "mod-loop-a"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_show_depends, @@ -38,15 +35,7 @@ DEFINE_TEST(modprobe_show_depends, static noreturn int modprobe_show_depends2(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "--show-depends", - "mod-simple", - NULL, - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("--show-depends", "mod-simple"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_show_depends2, @@ -61,17 +50,7 @@ DEFINE_TEST(modprobe_show_depends2, static noreturn int modprobe_show_alias_to_none(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - // clang-format off - progname, - "--show-depends", "--ignore-install", "--quiet", - "mod-simple", - NULL, - // clang-format on - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("--show-depends", "--ignore-install", "--quiet", "mod-simple"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_show_alias_to_none, @@ -88,17 +67,7 @@ DEFINE_TEST(modprobe_show_alias_to_none, static noreturn int modprobe_show_exports(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - // clang-format off - progname, - "--show-exports", "--quiet", - "/mod-loop-a.ko", - NULL, - // clang-format on - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("--show-exports", "--quiet", "/mod-loop-a.ko"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_show_exports, @@ -113,14 +82,7 @@ DEFINE_TEST(modprobe_show_exports, static noreturn int modprobe_builtin(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "unix", - NULL, - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("unix"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_builtin, .description = "check if modprobe return 0 for builtin", @@ -131,15 +93,7 @@ DEFINE_TEST(modprobe_builtin, .description = "check if modprobe return 0 for bui static noreturn int modprobe_builtin_lookup_only(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "-R", - "unix", - NULL, - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("-R", "unix"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_builtin_lookup_only, @@ -154,14 +108,7 @@ DEFINE_TEST(modprobe_builtin_lookup_only, static noreturn int modprobe_softdep_loop(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "mod-loop-b", - NULL, - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("mod-loop-b"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_softdep_loop, @@ -176,14 +123,7 @@ DEFINE_TEST(modprobe_softdep_loop, static noreturn int modprobe_weakdep_loop(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "mod-loop-b", - NULL, - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("mod-loop-b"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_weakdep_loop, @@ -199,14 +139,7 @@ DEFINE_TEST(modprobe_weakdep_loop, static noreturn int modprobe_install_cmd_loop(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "mod-loop-a", - NULL, - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("mod-loop-a"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_install_cmd_loop, @@ -225,15 +158,7 @@ DEFINE_TEST(modprobe_install_cmd_loop, static noreturn int modprobe_param_kcmdline_show_deps(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "--show-depends", - "mod-simple", - NULL, - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("--show-depends", "mod-simple"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_param_kcmdline_show_deps, @@ -250,14 +175,7 @@ DEFINE_TEST(modprobe_param_kcmdline_show_deps, static noreturn int modprobe_param_kcmdline(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "-c", - NULL, - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("-c"); exit(EXIT_FAILURE); } DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline2, modprobe_param_kcmdline, @@ -346,15 +264,7 @@ DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline8, modprobe_param_kcmdline, static noreturn int modprobe_force(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "--force", - "mod-simple", - NULL, - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("--force", "mod-simple"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_force, @@ -369,14 +279,7 @@ DEFINE_TEST(modprobe_force, static noreturn int modprobe_oldkernel(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "mod-simple", - NULL, - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("mod-simple"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_oldkernel, @@ -391,15 +294,7 @@ DEFINE_TEST(modprobe_oldkernel, static noreturn int modprobe_oldkernel_force(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "--force", - "mod-simple", - NULL, - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("--force", "mod-simple"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_oldkernel_force, @@ -414,14 +309,7 @@ DEFINE_TEST(modprobe_oldkernel_force, static noreturn int modprobe_external(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "mod-simple", - NULL, - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("mod-simple"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_external, @@ -436,14 +324,7 @@ DEFINE_TEST(modprobe_external, static noreturn int modprobe_module_from_abspath(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "/home/foo/mod-simple.ko", - NULL, - }; - - test_spawn_prog(progname, args); + EXEC_MODPROBE("/home/foo/mod-simple.ko"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_module_from_abspath, @@ -458,19 +339,12 @@ DEFINE_TEST(modprobe_module_from_abspath, static noreturn int modprobe_module_from_relpath(const struct test *t) { - const char *progname = TOOLS_DIR "/modprobe"; - const char *const args[] = { - progname, - "./mod-simple.ko", - NULL, - }; - if (chdir("/home/foo") != 0) { perror("failed to change into /home/foo"); exit(EXIT_FAILURE); } - test_spawn_prog(progname, args); + EXEC_MODPROBE("./mod-simple.ko"); exit(EXIT_FAILURE); } DEFINE_TEST(modprobe_module_from_relpath, @@ -480,7 +354,6 @@ DEFINE_TEST(modprobe_module_from_relpath, [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/module-from-relpath", [TC_INIT_MODULE_RETCODES] = "", }, - .need_spawn = true, .modules_loaded = "mod-simple", ); diff --git a/testsuite/test-new-module.c b/testsuite/test-new-module.c index 866526de..ed051cae 100644 --- a/testsuite/test-new-module.c +++ b/testsuite/test-new-module.c @@ -55,7 +55,6 @@ DEFINE_TEST(from_name, .config = { [TC_ROOTFS] = TESTSUITE_ROOTFS "test-new-module/from_name/", }, - .need_spawn = true, .output = { .out = TESTSUITE_ROOTFS "test-new-module/from_name/correct.txt", }); @@ -100,7 +99,6 @@ DEFINE_TEST(from_alias, .config = { [TC_ROOTFS] = TESTSUITE_ROOTFS "test-new-module/from_alias/", }, - .need_spawn = true, .output = { .out = TESTSUITE_ROOTFS "test-new-module/from_alias/correct.txt", }); diff --git a/testsuite/test-testsuite.c b/testsuite/test-testsuite.c index eff911a7..42fcb6f2 100644 --- a/testsuite/test-testsuite.c +++ b/testsuite/test-testsuite.c @@ -38,12 +38,10 @@ static noreturn int testsuite_uname(const struct test *t) exit(EXIT_SUCCESS); } -DEFINE_TEST(testsuite_uname, - .description = "test if trap to uname() works", - .config = { - [TC_UNAME_R] = TEST_UNAME, - }, - .need_spawn = true); +DEFINE_TEST(testsuite_uname, .description = "test if trap to uname() works", + .config = { + [TC_UNAME_R] = TEST_UNAME, + }); static int testsuite_rootfs_fopen(const struct test *t) { @@ -64,12 +62,10 @@ static int testsuite_rootfs_fopen(const struct test *t) return EXIT_SUCCESS; } -DEFINE_TEST(testsuite_rootfs_fopen, - .description = "test if rootfs works - fopen()", - .config = { - [TC_ROOTFS] = TESTSUITE_ROOTFS "test-rootfs/", - }, - .need_spawn = true); +DEFINE_TEST(testsuite_rootfs_fopen, .description = "test if rootfs works - fopen()", + .config = { + [TC_ROOTFS] = TESTSUITE_ROOTFS "test-rootfs/", + }); static int testsuite_rootfs_open(const struct test *t) { @@ -97,12 +93,10 @@ static int testsuite_rootfs_open(const struct test *t) return EXIT_SUCCESS; } -DEFINE_TEST(testsuite_rootfs_open, - .description = "test if rootfs works - open()", - .config = { - [TC_ROOTFS] = TESTSUITE_ROOTFS "test-rootfs/", - }, - .need_spawn = true); +DEFINE_TEST(testsuite_rootfs_open, .description = "test if rootfs works - open()", + .config = { + [TC_ROOTFS] = TESTSUITE_ROOTFS "test-rootfs/", + }); static int testsuite_rootfs_stat(const struct test *t) { @@ -115,12 +109,10 @@ static int testsuite_rootfs_stat(const struct test *t) return EXIT_SUCCESS; } -DEFINE_TEST(testsuite_rootfs_stat, - .description = "test if rootfs works - stat()", - .config = { - [TC_ROOTFS] = TESTSUITE_ROOTFS "test-rootfs/", - }, - .need_spawn = true); +DEFINE_TEST(testsuite_rootfs_stat, .description = "test if rootfs works - stat()", + .config = { + [TC_ROOTFS] = TESTSUITE_ROOTFS "test-rootfs/", + }); static int testsuite_rootfs_opendir(const struct test *t) { @@ -135,11 +127,9 @@ static int testsuite_rootfs_opendir(const struct test *t) closedir(d); return EXIT_SUCCESS; } -DEFINE_TEST(testsuite_rootfs_opendir, - .description = "test if rootfs works - opendir()", - .config = { - [TC_ROOTFS] = TESTSUITE_ROOTFS "test-rootfs/", - }, - .need_spawn = true); +DEFINE_TEST(testsuite_rootfs_opendir, .description = "test if rootfs works - opendir()", + .config = { + [TC_ROOTFS] = TESTSUITE_ROOTFS "test-rootfs/", + }); TESTSUITE_MAIN(); diff --git a/testsuite/test-util.c b/testsuite/test-util.c index e38b9f83..84a04ad9 100644 --- a/testsuite/test-util.c +++ b/testsuite/test-util.c @@ -56,7 +56,6 @@ DEFINE_TEST(alias_1, .config = { [TC_ROOTFS] = TESTSUITE_ROOTFS "test-util/", }, - .need_spawn = true, .output = { .out = TESTSUITE_ROOTFS "test-util/alias-correct.txt", }); @@ -86,7 +85,6 @@ DEFINE_TEST(test_freadline_wrapped, .config = { [TC_ROOTFS] = TESTSUITE_ROOTFS "test-util/", }, - .need_spawn = true, .output = { .out = TESTSUITE_ROOTFS "test-util/freadline_wrapped-correct.txt", }); @@ -182,7 +180,6 @@ DEFINE_TEST(test_write_str_safe, .config = { [TC_ROOTFS] = TESTSUITE_ROOTFS "test-util2/", }, - .need_spawn = true, .output = { .files = (const struct keyval[]) { { TEST_WRITE_STR_SAFE_PATH ".txt", diff --git a/testsuite/test-weakdep.c b/testsuite/test-weakdep.c index 0c7aacd1..ca75349a 100644 --- a/testsuite/test-weakdep.c +++ b/testsuite/test-weakdep.c @@ -90,7 +90,6 @@ DEFINE_TEST(test_weakdep, [TC_ROOTFS] = TESTSUITE_ROOTFS "test-weakdep", [TC_INIT_MODULE_RETCODES] = "", }, - .need_spawn = true, .output = { .out = TESTSUITE_ROOTFS "test-weakdep/correct-weakdep.txt", }); diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index 6d1c1759..0490d5e7 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -264,10 +264,7 @@ static inline int test_run_child(const struct test *t, int fdout[2], int fderr[2 } } - if (t->need_spawn) - return test_spawn_test(t); - else - return test_run_spawned(t); + return test_spawn_test(t); } #define BUFSZ 4096 @@ -1018,7 +1015,7 @@ static inline int test_run_parent(const struct test *t, int fdout[2], int fderr[ if (t->skip) { LOG("%sSKIPPED%s: %s\n", ANSI_HIGHLIGHT_YELLOW_ON, ANSI_HIGHLIGHT_OFF, t->name); - err = EXIT_SUCCESS; + err = 77; goto exit; } @@ -1149,7 +1146,7 @@ int test_run(const struct test *t) int fderr[2]; int fdmonitor[2]; - if (t->need_spawn && oneshot) + if (oneshot) test_run_spawned(t); if (t->output.out != NULL) { diff --git a/testsuite/testsuite.h b/testsuite/testsuite.h index 59d29c13..161817e7 100644 --- a/testsuite/testsuite.h +++ b/testsuite/testsuite.h @@ -96,7 +96,6 @@ struct test { const char *config[_TC_LAST]; const char *path; const struct keyval *env_vars; - bool need_spawn; bool expected_fail; /* allow to skip tests that don't meet compile-time dependencies */ bool skip; @@ -143,7 +142,7 @@ int test_run(const struct test *t); int main(int argc, char *argv[]) \ { \ const struct test *t; \ - int arg; \ + int arg, ret = EXIT_SUCCESS; \ \ arg = test_init(__start_kmod_tests, __stop_kmod_tests, argc, argv); \ if (arg == 0) \ @@ -163,8 +162,8 @@ int test_run(const struct test *t); \ for (t = __start_kmod_tests; t < __stop_kmod_tests; t++) { \ if (test_run(t) != 0) \ - exit(EXIT_FAILURE); \ + ret = EXIT_FAILURE; \ } \ \ - exit(EXIT_SUCCESS); \ + exit(ret); \ }