This patch series makes two changes to how KUnit test suites are stored and executed: - The .kunit_test_suites section is now used for tests in modules (in lieu of a module_init funciton), as well as for built-in tests. The module loader will now trigger test execution. This frees up the module_init function for other uses. - Instead of storing an array of arrays of suites, have the kunit_test_suite() and kunit_test_suites() macros append to one global (or per-module) list of test suites. This removes a needless layer of indirection, and removes the need to NULL-terminate suite_sets.
The upshot of this is that it should now be possible to use the kunit_test_suite() and kunit_test_suites() macros to register test suites even from within modules which otherwise had module_init functions. This was proving to be quite a common issue, resulting in several modules calling into KUnit's private suite execution functions to run their tests (often introducing incompatibilities with the KUnit tooling).
This series also fixes the thunderbolt, nitro_enclaves, and sdhci-of-aspeed tests to use kunit_test_suite() now that it works. This is required, as otherwise the first two patches may break these tests entirely.
Huge thanks to Jeremy Kerr, who designed and implemented the module loader changes, and to Daniel Latypov for pushing the simplification of the nested arrays in .kunit_test_suites.
I've tested this series both with builtin tests, and with modules on x86_64, but there's always the possibility that there's something subtle and nasty on another architecture, so please test!
Cheers, -- David
Changes since v1: https://lore.kernel.org/linux-kselftest/20220618090310.1174932-1-davidgow@go... - Fix a compile issue when CONFIG_KUNIT=m (Thanks Christophe) - No longer NULL-terminate suite_sets. - Move the thunderbird Kconfig to the correct patch (Thanks Andra) - Add all the Tested-by and Acked-by tags.
--- Daniel Latypov (1): kunit: flatten kunit_suite*** to kunit_suite** in .kunit_test_suites
David Gow (3): thunderbolt: test: Use kunit_test_suite() macro nitro_enclaves: test: Use kunit_test_suite() macro mmc: sdhci-of-aspeed: test: Use kunit_test_suite() macro
Jeremy Kerr (1): kunit: unify module and builtin suite definitions
drivers/mmc/host/Kconfig | 5 +- drivers/mmc/host/sdhci-of-aspeed-test.c | 8 +- drivers/mmc/host/sdhci-of-aspeed.c | 27 ---- drivers/thunderbolt/Kconfig | 5 +- drivers/thunderbolt/domain.c | 3 - drivers/thunderbolt/tb.h | 8 - drivers/thunderbolt/test.c | 12 +- drivers/virt/nitro_enclaves/Kconfig | 5 +- drivers/virt/nitro_enclaves/ne_misc_dev.c | 27 ---- .../virt/nitro_enclaves/ne_misc_dev_test.c | 5 +- include/kunit/test.h | 60 ++------ include/linux/module.h | 5 + kernel/module/main.c | 6 + lib/kunit/executor.c | 115 ++++---------- lib/kunit/executor_test.c | 144 +++++------------- lib/kunit/test.c | 54 ++++++- 16 files changed, 152 insertions(+), 337 deletions(-)
From: Jeremy Kerr jk@codeconstruct.com.au
Currently, KUnit runs built-in tests and tests loaded from modules differently. For built-in tests, the kunit_test_suite{,s}() macro adds a list of suites in the .kunit_test_suites linker section. However, for kernel modules, a module_init() function is used to run the test suites.
This causes problems if tests are included in a module which already defines module_init/exit_module functions, as they'll conflict with the kunit-provided ones.
This change removes the kunit-defined module inits, and instead parses the kunit tests from their own section in the module. After module init, we call __kunit_test_suites_init() on the contents of that section, which prepares and runs the suite.
This essentially unifies the module- and non-module kunit init formats.
Tested-by: Maíra Canal maira.canal@usp.br Signed-off-by: Jeremy Kerr jk@codeconstruct.com.au Signed-off-by: Daniel Latypov dlatypov@google.com Signed-off-by: David Gow davidgow@google.com ---
Changes since v1: https://lore.kernel.org/linux-kselftest/20220618090310.1174932-2-davidgow@go... - Fix a compile error with CONFIG_KUNIT=m (Thanks Christophe Leroy, kernel test robot) - Add Maíra's Tested-by.
Changes since RFC: https://lore.kernel.org/linux-kselftest/101d12fc9250b7a445ff50a9e7a25cd74d0e... - I've basically just rebased it, tweaked some wording, and it made it still compile when CONFIG_MODULES is not set.
--- include/kunit/test.h | 47 ++++---------------------------------- include/linux/module.h | 5 ++++ kernel/module/main.c | 6 +++++ lib/kunit/test.c | 52 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 67 insertions(+), 43 deletions(-)
diff --git a/include/kunit/test.h b/include/kunit/test.h index 8ffcd7de9607..54306271cfbf 100644 --- a/include/kunit/test.h +++ b/include/kunit/test.h @@ -250,41 +250,8 @@ static inline int kunit_run_all_tests(void) } #endif /* IS_BUILTIN(CONFIG_KUNIT) */
-#ifdef MODULE -/** - * kunit_test_suites_for_module() - used to register one or more - * &struct kunit_suite with KUnit. - * - * @__suites: a statically allocated list of &struct kunit_suite. - * - * Registers @__suites with the test framework. See &struct kunit_suite for - * more information. - * - * If a test suite is built-in, module_init() gets translated into - * an initcall which we don't want as the idea is that for builtins - * the executor will manage execution. So ensure we do not define - * module_{init|exit} functions for the builtin case when registering - * suites via kunit_test_suites() below. - */ -#define kunit_test_suites_for_module(__suites) \ - static int __init kunit_test_suites_init(void) \ - { \ - return __kunit_test_suites_init(__suites); \ - } \ - module_init(kunit_test_suites_init); \ - \ - static void __exit kunit_test_suites_exit(void) \ - { \ - return __kunit_test_suites_exit(__suites); \ - } \ - module_exit(kunit_test_suites_exit) -#else -#define kunit_test_suites_for_module(__suites) -#endif /* MODULE */ - #define __kunit_test_suites(unique_array, unique_suites, ...) \ static struct kunit_suite *unique_array[] = { __VA_ARGS__, NULL }; \ - kunit_test_suites_for_module(unique_array); \ static struct kunit_suite **unique_suites \ __used __section(".kunit_test_suites") = unique_array
@@ -294,16 +261,12 @@ static inline int kunit_run_all_tests(void) * * @__suites: a statically allocated list of &struct kunit_suite. * - * Registers @suites with the test framework. See &struct kunit_suite for - * more information. - * - * When builtin, KUnit tests are all run via executor; this is done - * by placing the array of struct kunit_suite * in the .kunit_test_suites - * ELF section. + * Registers @suites with the test framework. + * This is done by placing the array of struct kunit_suite * in the + * .kunit_test_suites ELF section. * - * An alternative is to build the tests as a module. Because modules do not - * support multiple initcall()s, we need to initialize an array of suites for a - * module. + * When builtin, KUnit tests are all run via the executor at boot, and when + * built as a module, they run on module load. * */ #define kunit_test_suites(__suites...) \ diff --git a/include/linux/module.h b/include/linux/module.h index abd9fa916b7d..2490223c975d 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -505,6 +505,11 @@ struct module { int num_static_call_sites; struct static_call_site *static_call_sites; #endif +#if IS_ENABLED(CONFIG_KUNIT) + int num_kunit_suites; + struct kunit_suite ***kunit_suites; +#endif +
#ifdef CONFIG_LIVEPATCH bool klp; /* Is this a livepatch module? */ diff --git a/kernel/module/main.c b/kernel/module/main.c index fed58d30725d..4542db7cdf54 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -2087,6 +2087,12 @@ static int find_module_sections(struct module *mod, struct load_info *info) sizeof(*mod->static_call_sites), &mod->num_static_call_sites); #endif +#ifdef CONFIG_KUNIT + mod->kunit_suites = section_objs(info, ".kunit_test_suites", + sizeof(*mod->kunit_suites), + &mod->num_kunit_suites); +#endif + mod->extable = section_objs(info, "__ex_table", sizeof(*mod->extable), &mod->num_exentries);
diff --git a/lib/kunit/test.c b/lib/kunit/test.c index a5053a07409f..3052526b9b89 100644 --- a/lib/kunit/test.c +++ b/lib/kunit/test.c @@ -10,6 +10,7 @@ #include <kunit/test.h> #include <kunit/test-bug.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/moduleparam.h> #include <linux/sched/debug.h> #include <linux/sched.h> @@ -609,6 +610,49 @@ void __kunit_test_suites_exit(struct kunit_suite **suites) } EXPORT_SYMBOL_GPL(__kunit_test_suites_exit);
+#ifdef CONFIG_MODULES +static void kunit_module_init(struct module *mod) +{ + unsigned int i; + + for (i = 0; i < mod->num_kunit_suites; i++) + __kunit_test_suites_init(mod->kunit_suites[i]); +} + +static void kunit_module_exit(struct module *mod) +{ + unsigned int i; + + for (i = 0; i < mod->num_kunit_suites; i++) + __kunit_test_suites_exit(mod->kunit_suites[i]); +} + +static int kunit_module_notify(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct module *mod = data; + + switch (val) { + case MODULE_STATE_LIVE: + kunit_module_init(mod); + break; + case MODULE_STATE_GOING: + kunit_module_exit(mod); + break; + case MODULE_STATE_COMING: + case MODULE_STATE_UNFORMED: + break; + } + + return 0; +} + +static struct notifier_block kunit_mod_nb = { + .notifier_call = kunit_module_notify, + .priority = 0, +}; +#endif + struct kunit_kmalloc_array_params { size_t n; size_t size; @@ -703,13 +747,19 @@ EXPORT_SYMBOL_GPL(kunit_cleanup); static int __init kunit_init(void) { kunit_debugfs_init(); - +#ifdef CONFIG_MODULES + return register_module_notifier(&kunit_mod_nb); +#else return 0; +#endif } late_initcall(kunit_init);
static void __exit kunit_exit(void) { +#ifdef CONFIG_MODULES + unregister_module_notifier(&kunit_mod_nb); +#endif kunit_debugfs_cleanup(); } module_exit(kunit_exit);
From: Daniel Latypov dlatypov@google.com
We currently store kunit suites in the .kunit_test_suites ELF section as a `struct kunit_suite***` (modulo some `const`s). For every test file, we store a struct kunit_suite** NULL-terminated array.
This adds quite a bit of complexity to the test filtering code in the executor.
Instead, let's just make the .kunit_test_suites section contain a single giant array of struct kunit_suite pointers, which can then be directly manipulated. This array is not NULL-terminated, and so none of the test filtering code needs to NULL-terminate anything.
Tested-by: Maíra Canal maira.canal@usp.br Signed-off-by: Daniel Latypov dlatypov@google.com Co-developed-by: David Gow davidgow@google.com Signed-off-by: David Gow davidgow@google.com ---
Changes since v1: https://lore.kernel.org/linux-kselftest/20220618090310.1174932-3-davidgow@go... - No longer NULL-terminate generated suite_sets - Add Maíra's Tested-by tag.
Changes since RFC: https://lore.kernel.org/linux-kselftest/20211013191320.2490913-1-dlatypov@go... - Actually flatten the .kunit_test_suites ELF section, rather than constructing the flattened version at runtime. --- include/kunit/test.h | 13 ++-- include/linux/module.h | 2 +- lib/kunit/executor.c | 115 ++++++++---------------------- lib/kunit/executor_test.c | 144 +++++++++++--------------------------- lib/kunit/test.c | 18 ++--- 5 files changed, 82 insertions(+), 210 deletions(-)
diff --git a/include/kunit/test.h b/include/kunit/test.h index 54306271cfbf..bd8d772979a6 100644 --- a/include/kunit/test.h +++ b/include/kunit/test.h @@ -237,9 +237,9 @@ size_t kunit_suite_num_test_cases(struct kunit_suite *suite); unsigned int kunit_test_case_num(struct kunit_suite *suite, struct kunit_case *test_case);
-int __kunit_test_suites_init(struct kunit_suite * const * const suites); +int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_suites);
-void __kunit_test_suites_exit(struct kunit_suite **suites); +void __kunit_test_suites_exit(struct kunit_suite **suites, int num_suites);
#if IS_BUILTIN(CONFIG_KUNIT) int kunit_run_all_tests(void); @@ -250,10 +250,10 @@ static inline int kunit_run_all_tests(void) } #endif /* IS_BUILTIN(CONFIG_KUNIT) */
-#define __kunit_test_suites(unique_array, unique_suites, ...) \ - static struct kunit_suite *unique_array[] = { __VA_ARGS__, NULL }; \ - static struct kunit_suite **unique_suites \ - __used __section(".kunit_test_suites") = unique_array +#define __kunit_test_suites(unique_array, ...) \ + static struct kunit_suite *unique_array[] \ + __aligned(sizeof(struct kunit_suite *)) \ + __used __section(".kunit_test_suites") = { __VA_ARGS__ }
/** * kunit_test_suites() - used to register one or more &struct kunit_suite @@ -271,7 +271,6 @@ static inline int kunit_run_all_tests(void) */ #define kunit_test_suites(__suites...) \ __kunit_test_suites(__UNIQUE_ID(array), \ - __UNIQUE_ID(suites), \ ##__suites)
#define kunit_test_suite(suite) kunit_test_suites(&suite) diff --git a/include/linux/module.h b/include/linux/module.h index 2490223c975d..518296ea7f73 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -507,7 +507,7 @@ struct module { #endif #if IS_ENABLED(CONFIG_KUNIT) int num_kunit_suites; - struct kunit_suite ***kunit_suites; + struct kunit_suite **kunit_suites; #endif
diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c index 96f96e42ce06..2ae9a037a80f 100644 --- a/lib/kunit/executor.c +++ b/lib/kunit/executor.c @@ -9,8 +9,8 @@ * These symbols point to the .kunit_test_suites section and are defined in * include/asm-generic/vmlinux.lds.h, and consequently must be extern. */ -extern struct kunit_suite * const * const __kunit_suites_start[]; -extern struct kunit_suite * const * const __kunit_suites_end[]; +extern struct kunit_suite * const __kunit_suites_start[]; +extern struct kunit_suite * const __kunit_suites_end[];
#if IS_BUILTIN(CONFIG_KUNIT)
@@ -92,62 +92,18 @@ kunit_filter_tests(struct kunit_suite *const suite, const char *test_glob) static char *kunit_shutdown; core_param(kunit_shutdown, kunit_shutdown, charp, 0644);
-static struct kunit_suite * const * -kunit_filter_subsuite(struct kunit_suite * const * const subsuite, - struct kunit_test_filter *filter) -{ - int i, n = 0; - struct kunit_suite **filtered, *filtered_suite; - - n = 0; - for (i = 0; subsuite[i]; ++i) { - if (glob_match(filter->suite_glob, subsuite[i]->name)) - ++n; - } - - if (n == 0) - return NULL; - - filtered = kmalloc_array(n + 1, sizeof(*filtered), GFP_KERNEL); - if (!filtered) - return ERR_PTR(-ENOMEM); - - n = 0; - for (i = 0; subsuite[i] != NULL; ++i) { - if (!glob_match(filter->suite_glob, subsuite[i]->name)) - continue; - filtered_suite = kunit_filter_tests(subsuite[i], filter->test_glob); - if (IS_ERR(filtered_suite)) - return ERR_CAST(filtered_suite); - else if (filtered_suite) - filtered[n++] = filtered_suite; - } - filtered[n] = NULL; - - return filtered; -} - +/* Stores an array of suites, end points one past the end */ struct suite_set { - struct kunit_suite * const * const *start; - struct kunit_suite * const * const *end; + struct kunit_suite * const *start; + struct kunit_suite * const *end; };
-static void kunit_free_subsuite(struct kunit_suite * const *subsuite) -{ - unsigned int i; - - for (i = 0; subsuite[i]; i++) - kfree(subsuite[i]); - - kfree(subsuite); -} - static void kunit_free_suite_set(struct suite_set suite_set) { - struct kunit_suite * const * const *suites; + struct kunit_suite * const *suites;
for (suites = suite_set.start; suites < suite_set.end; suites++) - kunit_free_subsuite(*suites); + kfree(*suites); kfree(suite_set.start); }
@@ -156,7 +112,7 @@ static struct suite_set kunit_filter_suites(const struct suite_set *suite_set, int *err) { int i; - struct kunit_suite * const **copy, * const *filtered_subsuite; + struct kunit_suite **copy, *filtered_suite; struct suite_set filtered; struct kunit_test_filter filter;
@@ -171,14 +127,19 @@ static struct suite_set kunit_filter_suites(const struct suite_set *suite_set,
kunit_parse_filter_glob(&filter, filter_glob);
- for (i = 0; i < max; ++i) { - filtered_subsuite = kunit_filter_subsuite(suite_set->start[i], &filter); - if (IS_ERR(filtered_subsuite)) { - *err = PTR_ERR(filtered_subsuite); + for (i = 0; &suite_set->start[i] != suite_set->end; i++) { + if (!glob_match(filter.suite_glob, suite_set->start[i]->name)) + continue; + + filtered_suite = kunit_filter_tests(suite_set->start[i], filter.test_glob); + if (IS_ERR(filtered_suite)) { + *err = PTR_ERR(filtered_suite); return filtered; } - if (filtered_subsuite) - *copy++ = filtered_subsuite; + if (!filtered_suite) + continue; + + *copy++ = filtered_suite; } filtered.end = copy;
@@ -201,52 +162,33 @@ static void kunit_handle_shutdown(void)
}
-static void kunit_print_tap_header(struct suite_set *suite_set) -{ - struct kunit_suite * const * const *suites, * const *subsuite; - int num_of_suites = 0; - - for (suites = suite_set->start; suites < suite_set->end; suites++) - for (subsuite = *suites; *subsuite != NULL; subsuite++) - num_of_suites++; - - pr_info("TAP version 14\n"); - pr_info("1..%d\n", num_of_suites); -} - static void kunit_exec_run_tests(struct suite_set *suite_set) { - struct kunit_suite * const * const *suites; + size_t num_suites = suite_set->end - suite_set->start;
- kunit_print_tap_header(suite_set); + pr_info("TAP version 14\n"); + pr_info("1..%zu\n", num_suites);
- for (suites = suite_set->start; suites < suite_set->end; suites++) - __kunit_test_suites_init(*suites); + __kunit_test_suites_init(suite_set->start, num_suites); }
static void kunit_exec_list_tests(struct suite_set *suite_set) { - unsigned int i; - struct kunit_suite * const * const *suites; + struct kunit_suite * const *suites; struct kunit_case *test_case;
/* Hack: print a tap header so kunit.py can find the start of KUnit output. */ pr_info("TAP version 14\n");
for (suites = suite_set->start; suites < suite_set->end; suites++) - for (i = 0; (*suites)[i] != NULL; i++) { - kunit_suite_for_each_test_case((*suites)[i], test_case) { - pr_info("%s.%s\n", (*suites)[i]->name, test_case->name); - } + kunit_suite_for_each_test_case((*suites), test_case) { + pr_info("%s.%s\n", (*suites)->name, test_case->name); } }
int kunit_run_all_tests(void) { - struct suite_set suite_set = { - .start = __kunit_suites_start, - .end = __kunit_suites_end, - }; + struct suite_set suite_set = {__kunit_suites_start, __kunit_suites_end}; int err = 0;
if (filter_glob_param) { @@ -264,11 +206,10 @@ int kunit_run_all_tests(void) else pr_err("kunit executor: unknown action '%s'\n", action_param);
- if (filter_glob_param) { /* a copy was made of each array */ + if (filter_glob_param) { /* a copy was made of each suite */ kunit_free_suite_set(suite_set); }
- out: kunit_handle_shutdown(); return err; diff --git a/lib/kunit/executor_test.c b/lib/kunit/executor_test.c index eac6ff480273..0cea31c27b23 100644 --- a/lib/kunit/executor_test.c +++ b/lib/kunit/executor_test.c @@ -9,8 +9,6 @@ #include <kunit/test.h>
static void kfree_at_end(struct kunit *test, const void *to_free); -static void free_subsuite_at_end(struct kunit *test, - struct kunit_suite *const *to_free); static struct kunit_suite *alloc_fake_suite(struct kunit *test, const char *suite_name, struct kunit_case *test_cases); @@ -41,126 +39,80 @@ static void parse_filter_test(struct kunit *test) kfree(filter.test_glob); }
-static void filter_subsuite_test(struct kunit *test) +static void filter_suites_test(struct kunit *test) { - struct kunit_suite *subsuite[3] = {NULL, NULL, NULL}; - struct kunit_suite * const *filtered; - struct kunit_test_filter filter = { - .suite_glob = "suite2", - .test_glob = NULL, - }; + struct kunit_suite *subsuite[3] = {NULL, NULL}; + struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]}; + struct suite_set got; + int err = 0;
subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases);
/* Want: suite1, suite2, NULL -> suite2, NULL */ - filtered = kunit_filter_subsuite(subsuite, &filter); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered); - free_subsuite_at_end(test, filtered); + got = kunit_filter_suites(&suite_set, "suite2", &err); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start); + KUNIT_ASSERT_EQ(test, err, 0); + kfree_at_end(test, got.start);
/* Validate we just have suite2 */ - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered[0]); - KUNIT_EXPECT_STREQ(test, (const char *)filtered[0]->name, "suite2"); - KUNIT_EXPECT_FALSE(test, filtered[1]); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]); + KUNIT_EXPECT_STREQ(test, (const char *)got.start[0]->name, "suite2"); + + /* Contains one element (end is 1 past end) */ + KUNIT_ASSERT_EQ(test, got.end - got.start, 1); }
-static void filter_subsuite_test_glob_test(struct kunit *test) +static void filter_suites_test_glob_test(struct kunit *test) { - struct kunit_suite *subsuite[3] = {NULL, NULL, NULL}; - struct kunit_suite * const *filtered; - struct kunit_test_filter filter = { - .suite_glob = "suite2", - .test_glob = "test2", - }; + struct kunit_suite *subsuite[3] = {NULL, NULL}; + struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]}; + struct suite_set got; + int err = 0;
subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases);
/* Want: suite1, suite2, NULL -> suite2 (just test1), NULL */ - filtered = kunit_filter_subsuite(subsuite, &filter); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered); - free_subsuite_at_end(test, filtered); + got = kunit_filter_suites(&suite_set, "suite2.test2", &err); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start); + KUNIT_ASSERT_EQ(test, err, 0); + kfree_at_end(test, got.start);
/* Validate we just have suite2 */ - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered[0]); - KUNIT_EXPECT_STREQ(test, (const char *)filtered[0]->name, "suite2"); - KUNIT_EXPECT_FALSE(test, filtered[1]); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]); + KUNIT_EXPECT_STREQ(test, (const char *)got.start[0]->name, "suite2"); + KUNIT_ASSERT_EQ(test, got.end - got.start, 1);
/* Now validate we just have test2 */ - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered[0]->test_cases); - KUNIT_EXPECT_STREQ(test, (const char *)filtered[0]->test_cases[0].name, "test2"); - KUNIT_EXPECT_FALSE(test, filtered[0]->test_cases[1].name); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]->test_cases); + KUNIT_EXPECT_STREQ(test, (const char *)got.start[0]->test_cases[0].name, "test2"); + KUNIT_EXPECT_FALSE(test, got.start[0]->test_cases[1].name); }
-static void filter_subsuite_to_empty_test(struct kunit *test) +static void filter_suites_to_empty_test(struct kunit *test) { - struct kunit_suite *subsuite[3] = {NULL, NULL, NULL}; - struct kunit_suite * const *filtered; - struct kunit_test_filter filter = { - .suite_glob = "not_found", - .test_glob = NULL, - }; + struct kunit_suite *subsuite[3] = {NULL, NULL}; + struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]}; + struct suite_set got; + int err = 0;
subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases);
- filtered = kunit_filter_subsuite(subsuite, &filter); - free_subsuite_at_end(test, filtered); /* just in case */ + got = kunit_filter_suites(&suite_set, "not_found", &err); + KUNIT_ASSERT_EQ(test, err, 0); + kfree_at_end(test, got.start); /* just in case */
- KUNIT_EXPECT_FALSE_MSG(test, filtered, - "should be NULL to indicate no match"); -} - -static void kfree_subsuites_at_end(struct kunit *test, struct suite_set *suite_set) -{ - struct kunit_suite * const * const *suites; - - kfree_at_end(test, suite_set->start); - for (suites = suite_set->start; suites < suite_set->end; suites++) - free_subsuite_at_end(test, *suites); -} - -static void filter_suites_test(struct kunit *test) -{ - /* Suites per-file are stored as a NULL terminated array */ - struct kunit_suite *subsuites[2][2] = { - {NULL, NULL}, - {NULL, NULL}, - }; - /* Match the memory layout of suite_set */ - struct kunit_suite * const * const suites[2] = { - subsuites[0], subsuites[1], - }; - - const struct suite_set suite_set = { - .start = suites, - .end = suites + 2, - }; - struct suite_set filtered = {.start = NULL, .end = NULL}; - int err = 0; - - /* Emulate two files, each having one suite */ - subsuites[0][0] = alloc_fake_suite(test, "suite0", dummy_test_cases); - subsuites[1][0] = alloc_fake_suite(test, "suite1", dummy_test_cases); - - /* Filter out suite1 */ - filtered = kunit_filter_suites(&suite_set, "suite0", &err); - kfree_subsuites_at_end(test, &filtered); /* let us use ASSERTs without leaking */ - KUNIT_EXPECT_EQ(test, err, 0); - KUNIT_ASSERT_EQ(test, filtered.end - filtered.start, (ptrdiff_t)1); - - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start[0]); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start[0][0]); - KUNIT_EXPECT_STREQ(test, (const char *)filtered.start[0][0]->name, "suite0"); + KUNIT_EXPECT_PTR_EQ_MSG(test, got.start, got.end, + "should be empty to indicate no match"); }
static struct kunit_case executor_test_cases[] = { KUNIT_CASE(parse_filter_test), - KUNIT_CASE(filter_subsuite_test), - KUNIT_CASE(filter_subsuite_test_glob_test), - KUNIT_CASE(filter_subsuite_to_empty_test), KUNIT_CASE(filter_suites_test), + KUNIT_CASE(filter_suites_test_glob_test), + KUNIT_CASE(filter_suites_to_empty_test), {} };
@@ -190,20 +142,6 @@ static void kfree_at_end(struct kunit *test, const void *to_free) (void *)to_free); }
-static void free_subsuite_res_free(struct kunit_resource *res) -{ - kunit_free_subsuite(res->data); -} - -static void free_subsuite_at_end(struct kunit *test, - struct kunit_suite *const *to_free) -{ - if (IS_ERR_OR_NULL(to_free)) - return; - kunit_alloc_resource(test, NULL, free_subsuite_res_free, - GFP_KERNEL, (void *)to_free); -} - static struct kunit_suite *alloc_fake_suite(struct kunit *test, const char *suite_name, struct kunit_case *test_cases) diff --git a/lib/kunit/test.c b/lib/kunit/test.c index 3052526b9b89..b6495c7f9a7e 100644 --- a/lib/kunit/test.c +++ b/lib/kunit/test.c @@ -582,11 +582,11 @@ static void kunit_init_suite(struct kunit_suite *suite) suite->suite_init_err = 0; }
-int __kunit_test_suites_init(struct kunit_suite * const * const suites) +int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_suites) { unsigned int i;
- for (i = 0; suites[i] != NULL; i++) { + for (i = 0; i < num_suites; i++) { kunit_init_suite(suites[i]); kunit_run_tests(suites[i]); } @@ -599,11 +599,11 @@ static void kunit_exit_suite(struct kunit_suite *suite) kunit_debugfs_destroy_suite(suite); }
-void __kunit_test_suites_exit(struct kunit_suite **suites) +void __kunit_test_suites_exit(struct kunit_suite **suites, int num_suites) { unsigned int i;
- for (i = 0; suites[i] != NULL; i++) + for (i = 0; i < num_suites; i++) kunit_exit_suite(suites[i]);
kunit_suite_counter = 1; @@ -613,18 +613,12 @@ EXPORT_SYMBOL_GPL(__kunit_test_suites_exit); #ifdef CONFIG_MODULES static void kunit_module_init(struct module *mod) { - unsigned int i; - - for (i = 0; i < mod->num_kunit_suites; i++) - __kunit_test_suites_init(mod->kunit_suites[i]); + __kunit_test_suites_init(mod->kunit_suites, mod->num_kunit_suites); }
static void kunit_module_exit(struct module *mod) { - unsigned int i; - - for (i = 0; i < mod->num_kunit_suites; i++) - __kunit_test_suites_exit(mod->kunit_suites[i]); + __kunit_test_suites_exit(mod->kunit_suites, mod->num_kunit_suites); }
static int kunit_module_notify(struct notifier_block *nb, unsigned long val,
On Tue, Jun 21, 2022 at 1:54 AM 'David Gow' via KUnit Development kunit-dev@googlegroups.com wrote:
From: Daniel Latypov dlatypov@google.com
We currently store kunit suites in the .kunit_test_suites ELF section as a `struct kunit_suite***` (modulo some `const`s). For every test file, we store a struct kunit_suite** NULL-terminated array.
This adds quite a bit of complexity to the test filtering code in the executor.
Instead, let's just make the .kunit_test_suites section contain a single giant array of struct kunit_suite pointers, which can then be directly manipulated. This array is not NULL-terminated, and so none of the test filtering code needs to NULL-terminate anything.
Tested-by: Maíra Canal maira.canal@usp.br Signed-off-by: Daniel Latypov dlatypov@google.com Co-developed-by: David Gow davidgow@google.com Signed-off-by: David Gow davidgow@google.com
Changes since v1: https://lore.kernel.org/linux-kselftest/20220618090310.1174932-3-davidgow@go...
- No longer NULL-terminate generated suite_sets
Nice! Thanks for picking and cleaning this up!
Daniel
The new implementation of kunit_test_suite() for modules no longer conflicts with module_init, so can now be used by the thunderbolt tests.
Also update the Kconfig entry to enable the test when KUNIT_ALL_TESTS is enabled.
This means that kunit_tool can now successfully run and parse the test results with, for example: ./tools/testing/kunit/kunit.py run --arch=x86_64 \ --kconfig_add CONFIG_PCI=y --kconfig_add CONFIG_USB4=y \ 'thunderbolt'
Acked-by: Mika Westerberg mika.westerberg@linux.intel.com Signed-off-by: David Gow davidgow@google.com ---
Changes since v1: https://lore.kernel.org/linux-kselftest/20220618090310.1174932-4-davidgow@go... - Actually include the Kconfig changes, which were mistakenly added to the next patch in the series in v1. - Add Acked-by tag from Mika Westerberg
--- drivers/thunderbolt/Kconfig | 5 +++-- drivers/thunderbolt/domain.c | 3 --- drivers/thunderbolt/tb.h | 8 -------- drivers/thunderbolt/test.c | 12 +----------- 4 files changed, 4 insertions(+), 24 deletions(-)
diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig index 4bfec8a28064..2a063d344b94 100644 --- a/drivers/thunderbolt/Kconfig +++ b/drivers/thunderbolt/Kconfig @@ -28,8 +28,9 @@ config USB4_DEBUGFS_WRITE this for production systems or distro kernels.
config USB4_KUNIT_TEST - bool "KUnit tests" - depends on KUNIT=y + bool "KUnit tests" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS
config USB4_DMA_TEST tristate "DMA traffic test driver" diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c index 2889a214dadc..99211f35a5cd 100644 --- a/drivers/thunderbolt/domain.c +++ b/drivers/thunderbolt/domain.c @@ -872,7 +872,6 @@ int tb_domain_init(void) { int ret;
- tb_test_init(); tb_debugfs_init(); tb_acpi_init();
@@ -890,7 +889,6 @@ int tb_domain_init(void) err_acpi: tb_acpi_exit(); tb_debugfs_exit(); - tb_test_exit();
return ret; } @@ -903,5 +901,4 @@ void tb_domain_exit(void) tb_xdomain_exit(); tb_acpi_exit(); tb_debugfs_exit(); - tb_test_exit(); } diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 4602c69913fa..a831faa50f65 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -1271,12 +1271,4 @@ static inline void tb_service_debugfs_init(struct tb_service *svc) { } static inline void tb_service_debugfs_remove(struct tb_service *svc) { } #endif
-#ifdef CONFIG_USB4_KUNIT_TEST -int tb_test_init(void); -void tb_test_exit(void); -#else -static inline int tb_test_init(void) { return 0; } -static inline void tb_test_exit(void) { } -#endif - #endif diff --git a/drivers/thunderbolt/test.c b/drivers/thunderbolt/test.c index ee37f8b58f50..24c06e7354cd 100644 --- a/drivers/thunderbolt/test.c +++ b/drivers/thunderbolt/test.c @@ -2817,14 +2817,4 @@ static struct kunit_suite tb_test_suite = { .test_cases = tb_test_cases, };
-static struct kunit_suite *tb_test_suites[] = { &tb_test_suite, NULL }; - -int tb_test_init(void) -{ - return __kunit_test_suites_init(tb_test_suites); -} - -void tb_test_exit(void) -{ - return __kunit_test_suites_exit(tb_test_suites); -} +kunit_test_suite(tb_test_suite);
On Tue, Jun 21, 2022 at 1:54 AM David Gow davidgow@google.com wrote:
The new implementation of kunit_test_suite() for modules no longer conflicts with module_init, so can now be used by the thunderbolt tests.
Also update the Kconfig entry to enable the test when KUNIT_ALL_TESTS is enabled.
This means that kunit_tool can now successfully run and parse the test results with, for example: ./tools/testing/kunit/kunit.py run --arch=x86_64 \ --kconfig_add CONFIG_PCI=y --kconfig_add CONFIG_USB4=y \ 'thunderbolt'
With this, we can maybe revive https://lore.kernel.org/lkml/20220214184104.1710107-1-dlatypov@google.com by tacking it onto this series if a v3 goes out. There is the open question of whether we should put UML-specific config options in the file, though.
If we decide we don't want that, then we can defer it until I send out the patches for "repeatable --kunitconfig" and we can add the uml_pci.config file.
Acked-by: Mika Westerberg mika.westerberg@linux.intel.com Signed-off-by: David Gow davidgow@google.com
Acked-by: Daniel Latypov dlatypov@google.com
LGTM.
On Tue, Jun 21, 2022 at 4:54 PM David Gow davidgow@google.com wrote:
The new implementation of kunit_test_suite() for modules no longer conflicts with module_init, so can now be used by the thunderbolt tests.
Also update the Kconfig entry to enable the test when KUNIT_ALL_TESTS is enabled.
This means that kunit_tool can now successfully run and parse the test results with, for example: ./tools/testing/kunit/kunit.py run --arch=x86_64 \ --kconfig_add CONFIG_PCI=y --kconfig_add CONFIG_USB4=y \ 'thunderbolt'
Acked-by: Mika Westerberg mika.westerberg@linux.intel.com Signed-off-by: David Gow davidgow@google.com
Changes since v1: https://lore.kernel.org/linux-kselftest/20220618090310.1174932-4-davidgow@go...
- Actually include the Kconfig changes, which were mistakenly added to the next patch in the series in v1.
- Add Acked-by tag from Mika Westerberg
drivers/thunderbolt/Kconfig | 5 +++-- drivers/thunderbolt/domain.c | 3 --- drivers/thunderbolt/tb.h | 8 -------- drivers/thunderbolt/test.c | 12 +----------- 4 files changed, 4 insertions(+), 24 deletions(-)
diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig index 4bfec8a28064..2a063d344b94 100644 --- a/drivers/thunderbolt/Kconfig +++ b/drivers/thunderbolt/Kconfig @@ -28,8 +28,9 @@ config USB4_DEBUGFS_WRITE this for production systems or distro kernels.
config USB4_KUNIT_TEST
bool "KUnit tests"
depends on KUNIT=y
bool "KUnit tests" if !KUNIT_ALL_TESTS
depends on KUNIT
default KUNIT_ALL_TESTS
FYI: It turns out we can't just replace the "depends on KUNIT=y" with "depends on KUNIT" here, as it's still possible to have CONFIG_USB4=y and CONFIG_KUNIT=m, which would lead to missing KUnit symbols during link.
What does work is adding, in addition to "depends on KUNIT": depends on (USB4=m || KUNIT=y)
Which will prevent the tests from being enabled in this situation.
I'll wait another day or so before sending out a v3 with this fixed, in case there are any other issues which arise.
Cheers, -- David
The kunit_test_suite() macro previously conflicted with module_init, making it unsuitable for use in the nitro_enclaves test. Now that it's fixed, we can use it instead of a custom call into internal KUnit functions to run the test.
As a side-effect, this means that the test results are properly included with other suites when built-in. To celebrate, enable the test by default when KUNIT_ALL_TESTS is set (and NITRO_ENCLAVES enabled).
The nitro_enclave tests can now be run via kunit_tool with: ./tools/testing/kunit/kunit.py run --arch=x86_64 \ --kconfig_add CONFIG_PCI=y --kconfig_add CONFIG_SMP=y \ --kconfig_add CONFIG_HOTPLUG_CPU=y \ --kconfig_add CONFIG_VIRT_DRIVERS=y \ --kconfig_add CONFIG_NITRO_ENCLAVES=y \ 'ne_misc_dev_test'
(This is a pretty long command, so it may be worth adding a .kunitconfig file at some point, instead.)
Acked-by: Paraschiv, Andra-Irina andraprs@amazon.com Signed-off-by: David Gow davidgow@google.com ---
Changes since v1: https://lore.kernel.org/linux-kselftest/20220618090310.1174932-5-davidgow@go... - Move the mistakenly-added thunderbolt Kconfig to the previous patch (Thanks Andra) - Add Andra's Acked-by tag.
--- drivers/virt/nitro_enclaves/Kconfig | 5 ++-- drivers/virt/nitro_enclaves/ne_misc_dev.c | 27 ------------------- .../virt/nitro_enclaves/ne_misc_dev_test.c | 5 +--- 3 files changed, 4 insertions(+), 33 deletions(-)
diff --git a/drivers/virt/nitro_enclaves/Kconfig b/drivers/virt/nitro_enclaves/Kconfig index 2d3d98158121..ce91add81401 100644 --- a/drivers/virt/nitro_enclaves/Kconfig +++ b/drivers/virt/nitro_enclaves/Kconfig @@ -16,8 +16,9 @@ config NITRO_ENCLAVES The module will be called nitro_enclaves.
config NITRO_ENCLAVES_MISC_DEV_TEST - bool "Tests for the misc device functionality of the Nitro Enclaves" - depends on NITRO_ENCLAVES && KUNIT=y + bool "Tests for the misc device functionality of the Nitro Enclaves" if !KUNIT_ALL_TESTS + depends on NITRO_ENCLAVES && KUNIT + default KUNIT_ALL_TESTS help Enable KUnit tests for the misc device functionality of the Nitro Enclaves. Select this option only if you will boot the kernel for diff --git a/drivers/virt/nitro_enclaves/ne_misc_dev.c b/drivers/virt/nitro_enclaves/ne_misc_dev.c index 20c881b6a4b6..241b94f62e56 100644 --- a/drivers/virt/nitro_enclaves/ne_misc_dev.c +++ b/drivers/virt/nitro_enclaves/ne_misc_dev.c @@ -1759,35 +1759,10 @@ static long ne_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
#if defined(CONFIG_NITRO_ENCLAVES_MISC_DEV_TEST) #include "ne_misc_dev_test.c" - -static inline int ne_misc_dev_test_init(void) -{ - return __kunit_test_suites_init(ne_misc_dev_test_suites); -} - -static inline void ne_misc_dev_test_exit(void) -{ - __kunit_test_suites_exit(ne_misc_dev_test_suites); -} -#else -static inline int ne_misc_dev_test_init(void) -{ - return 0; -} - -static inline void ne_misc_dev_test_exit(void) -{ -} #endif
static int __init ne_init(void) { - int rc = 0; - - rc = ne_misc_dev_test_init(); - if (rc < 0) - return rc; - mutex_init(&ne_cpu_pool.mutex);
return pci_register_driver(&ne_pci_driver); @@ -1798,8 +1773,6 @@ static void __exit ne_exit(void) pci_unregister_driver(&ne_pci_driver);
ne_teardown_cpu_pool(); - - ne_misc_dev_test_exit(); }
module_init(ne_init); diff --git a/drivers/virt/nitro_enclaves/ne_misc_dev_test.c b/drivers/virt/nitro_enclaves/ne_misc_dev_test.c index 265797bed0ea..74df43b925be 100644 --- a/drivers/virt/nitro_enclaves/ne_misc_dev_test.c +++ b/drivers/virt/nitro_enclaves/ne_misc_dev_test.c @@ -151,7 +151,4 @@ static struct kunit_suite ne_misc_dev_test_suite = { .test_cases = ne_misc_dev_test_cases, };
-static struct kunit_suite *ne_misc_dev_test_suites[] = { - &ne_misc_dev_test_suite, - NULL -}; +kunit_test_suite(ne_misc_dev_test_suite);
On 21.06.2022 11:53, David Gow wrote:
The kunit_test_suite() macro previously conflicted with module_init, making it unsuitable for use in the nitro_enclaves test. Now that it's fixed, we can use it instead of a custom call into internal KUnit functions to run the test.
As a side-effect, this means that the test results are properly included with other suites when built-in. To celebrate, enable the test by default when KUNIT_ALL_TESTS is set (and NITRO_ENCLAVES enabled).
The nitro_enclave tests can now be run via kunit_tool with: ./tools/testing/kunit/kunit.py run --arch=x86_64 \ --kconfig_add CONFIG_PCI=y --kconfig_add CONFIG_SMP=y \ --kconfig_add CONFIG_HOTPLUG_CPU=y \ --kconfig_add CONFIG_VIRT_DRIVERS=y \ --kconfig_add CONFIG_NITRO_ENCLAVES=y \ 'ne_misc_dev_test'
(This is a pretty long command, so it may be worth adding a .kunitconfig file at some point, instead.)
Acked-by: Paraschiv, Andra-Irina andraprs@amazon.com Signed-off-by: David Gow davidgow@google.com
Changes since v1: https://lore.kernel.org/linux-kselftest/20220618090310.1174932-5-davidgow@go...
- Move the mistakenly-added thunderbolt Kconfig to the previous patch (Thanks Andra)
- Add Andra's Acked-by tag.
drivers/virt/nitro_enclaves/Kconfig | 5 ++-- drivers/virt/nitro_enclaves/ne_misc_dev.c | 27 ------------------- .../virt/nitro_enclaves/ne_misc_dev_test.c | 5 +--- 3 files changed, 4 insertions(+), 33 deletions(-)
Reviewed-by: Andra Paraschiv andraprs@amazon.com
Thank you, David, for the patch updates.
Added Greg to the list of mail recipients, to be aware of this patch changes, given that the Nitro Enclaves kernel driver is tracked via the char-misc tree.
Thanks, Andra
diff --git a/drivers/virt/nitro_enclaves/Kconfig b/drivers/virt/nitro_enclaves/Kconfig index 2d3d98158121..ce91add81401 100644 --- a/drivers/virt/nitro_enclaves/Kconfig +++ b/drivers/virt/nitro_enclaves/Kconfig @@ -16,8 +16,9 @@ config NITRO_ENCLAVES The module will be called nitro_enclaves.
config NITRO_ENCLAVES_MISC_DEV_TEST
bool "Tests for the misc device functionality of the Nitro Enclaves"
depends on NITRO_ENCLAVES && KUNIT=y
bool "Tests for the misc device functionality of the Nitro Enclaves" if !KUNIT_ALL_TESTS
depends on NITRO_ENCLAVES && KUNIT
default KUNIT_ALL_TESTS help Enable KUnit tests for the misc device functionality of the Nitro Enclaves. Select this option only if you will boot the kernel for
diff --git a/drivers/virt/nitro_enclaves/ne_misc_dev.c b/drivers/virt/nitro_enclaves/ne_misc_dev.c index 20c881b6a4b6..241b94f62e56 100644 --- a/drivers/virt/nitro_enclaves/ne_misc_dev.c +++ b/drivers/virt/nitro_enclaves/ne_misc_dev.c @@ -1759,35 +1759,10 @@ static long ne_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
#if defined(CONFIG_NITRO_ENCLAVES_MISC_DEV_TEST) #include "ne_misc_dev_test.c"
-static inline int ne_misc_dev_test_init(void) -{
return __kunit_test_suites_init(ne_misc_dev_test_suites);
-}
-static inline void ne_misc_dev_test_exit(void) -{
__kunit_test_suites_exit(ne_misc_dev_test_suites);
-} -#else -static inline int ne_misc_dev_test_init(void) -{
return 0;
-}
-static inline void ne_misc_dev_test_exit(void) -{ -} #endif
static int __init ne_init(void) {
int rc = 0;
rc = ne_misc_dev_test_init();
if (rc < 0)
return rc;
mutex_init(&ne_cpu_pool.mutex); return pci_register_driver(&ne_pci_driver);
@@ -1798,8 +1773,6 @@ static void __exit ne_exit(void) pci_unregister_driver(&ne_pci_driver);
ne_teardown_cpu_pool();
ne_misc_dev_test_exit();
}
module_init(ne_init);
diff --git a/drivers/virt/nitro_enclaves/ne_misc_dev_test.c b/drivers/virt/nitro_enclaves/ne_misc_dev_test.c index 265797bed0ea..74df43b925be 100644 --- a/drivers/virt/nitro_enclaves/ne_misc_dev_test.c +++ b/drivers/virt/nitro_enclaves/ne_misc_dev_test.c @@ -151,7 +151,4 @@ static struct kunit_suite ne_misc_dev_test_suite = { .test_cases = ne_misc_dev_test_cases, };
-static struct kunit_suite *ne_misc_dev_test_suites[] = {
&ne_misc_dev_test_suite,
NULL
-};
+kunit_test_suite(ne_misc_dev_test_suite);
2.37.0.rc0.104.g0611611a94-goog
Amazon Development Center (Romania) S.R.L. registered office: 27A Sf. Lazar Street, UBC5, floor 2, Iasi, Iasi County, 700045, Romania. Registered in Romania. Registration number J22/2621/2005.
The kunit_test_suite() macro is no-longer incompatible with module_add, so its use can be reinstated.
Since this fixes parsing with builtins and kunit_tool, also enable the test by default when KUNIT_ALL_TESTS is enabled.
The test can now be run via kunit_tool with: ./tools/testing/kunit/kunit.py run --arch=x86_64 \ --kconfig_add CONFIG_OF=y --kconfig_add CONFIG_OF_ADDRESS=y \ --kconfig_add CONFIG_MMC=y --kconfig_add CONFIG_MMC_SDHCI=y \ --kconfig_add CONFIG_MMC_SDHCI_PLTFM=y \ --kconfig_add CONFIG_MMC_SDHCI_OF_ASPEED=y \ 'sdhci-of-aspeed'
(It may be worth adding a .kunitconfig at some point, as there are enough dependencies to make that command scarily long.)
Signed-off-by: David Gow davidgow@google.com ---
No changes since v1: https://lore.kernel.org/linux-kselftest/20220618090310.1174932-6-davidgow@go...
--- drivers/mmc/host/Kconfig | 5 +++-- drivers/mmc/host/sdhci-of-aspeed-test.c | 8 +------- drivers/mmc/host/sdhci-of-aspeed.c | 27 ------------------------- 3 files changed, 4 insertions(+), 36 deletions(-)
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index d6144978e32d..10c563999d3d 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -169,8 +169,9 @@ config MMC_SDHCI_OF_ASPEED If unsure, say N.
config MMC_SDHCI_OF_ASPEED_TEST - bool "Tests for the ASPEED SDHCI driver" - depends on MMC_SDHCI_OF_ASPEED && KUNIT=y + bool "Tests for the ASPEED SDHCI driver" if !KUNIT_ALL_TESTS + depends on MMC_SDHCI_OF_ASPEED && KUNIT + default KUNIT_ALL_TESTS help Enable KUnit tests for the ASPEED SDHCI driver. Select this option only if you will boot the kernel for the purpose of running diff --git a/drivers/mmc/host/sdhci-of-aspeed-test.c b/drivers/mmc/host/sdhci-of-aspeed-test.c index 1ed4f86291f2..ecb502606c53 100644 --- a/drivers/mmc/host/sdhci-of-aspeed-test.c +++ b/drivers/mmc/host/sdhci-of-aspeed-test.c @@ -96,10 +96,4 @@ static struct kunit_suite aspeed_sdhci_test_suite = { .test_cases = aspeed_sdhci_test_cases, };
-static struct kunit_suite *aspeed_sdc_test_suite_array[] = { - &aspeed_sdhci_test_suite, - NULL, -}; - -static struct kunit_suite **aspeed_sdc_test_suites - __used __section(".kunit_test_suites") = aspeed_sdc_test_suite_array; +kunit_test_suite(aspeed_sdhci_test_suite); diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c index 6e4e132903a6..c10367946bc7 100644 --- a/drivers/mmc/host/sdhci-of-aspeed.c +++ b/drivers/mmc/host/sdhci-of-aspeed.c @@ -606,25 +606,6 @@ static struct platform_driver aspeed_sdc_driver = {
#if defined(CONFIG_MMC_SDHCI_OF_ASPEED_TEST) #include "sdhci-of-aspeed-test.c" - -static inline int aspeed_sdc_tests_init(void) -{ - return __kunit_test_suites_init(aspeed_sdc_test_suites); -} - -static inline void aspeed_sdc_tests_exit(void) -{ - __kunit_test_suites_exit(aspeed_sdc_test_suites); -} -#else -static inline int aspeed_sdc_tests_init(void) -{ - return 0; -} - -static inline void aspeed_sdc_tests_exit(void) -{ -} #endif
static int __init aspeed_sdc_init(void) @@ -639,12 +620,6 @@ static int __init aspeed_sdc_init(void) if (rc < 0) goto cleanup_sdhci;
- rc = aspeed_sdc_tests_init(); - if (rc < 0) { - platform_driver_unregister(&aspeed_sdc_driver); - goto cleanup_sdhci; - } - return 0;
cleanup_sdhci: @@ -656,8 +631,6 @@ module_init(aspeed_sdc_init);
static void __exit aspeed_sdc_exit(void) { - aspeed_sdc_tests_exit(); - platform_driver_unregister(&aspeed_sdc_driver); platform_driver_unregister(&aspeed_sdhci_driver); }
On Tue, Jun 21, 2022 at 1:54 AM David Gow davidgow@google.com wrote:
The kunit_test_suite() macro is no-longer incompatible with module_add, so its use can be reinstated.
Since this fixes parsing with builtins and kunit_tool, also enable the test by default when KUNIT_ALL_TESTS is enabled.
The test can now be run via kunit_tool with: ./tools/testing/kunit/kunit.py run --arch=x86_64 \ --kconfig_add CONFIG_OF=y --kconfig_add CONFIG_OF_ADDRESS=y \ --kconfig_add CONFIG_MMC=y --kconfig_add CONFIG_MMC_SDHCI=y \ --kconfig_add CONFIG_MMC_SDHCI_PLTFM=y \ --kconfig_add CONFIG_MMC_SDHCI_OF_ASPEED=y \ 'sdhci-of-aspeed'
(It may be worth adding a .kunitconfig at some point, as there are enough dependencies to make that command scarily long.)
Signed-off-by: David Gow davidgow@google.com
Acked-by: Daniel Latypov dlatypov@google.com
Minor, optional suggestion below.
static int __init aspeed_sdc_init(void) @@ -639,12 +620,6 @@ static int __init aspeed_sdc_init(void) if (rc < 0) goto cleanup_sdhci;
rc = aspeed_sdc_tests_init();
if (rc < 0) {
platform_driver_unregister(&aspeed_sdc_driver);
goto cleanup_sdhci;
}
return 0;
cleanup_sdhci:
This goto was added in 4af307f57426 ("mmc: sdhci-of-aspeed: Fix kunit-related build error") to allow for this extra call to aspeed_sdc_tests_init().
This could now be reverted back to what is rc = platform_driver_register(&aspeed_sdc_driver); if (rc < 0) platform_driver_unregister(&aspeed_sdhci_driver);
return rc;
but let's see what the maintainers think.
On Wed, 22 Jun 2022 at 00:19, Daniel Latypov dlatypov@google.com wrote:
On Tue, Jun 21, 2022 at 1:54 AM David Gow davidgow@google.com wrote:
The kunit_test_suite() macro is no-longer incompatible with module_add, so its use can be reinstated.
Since this fixes parsing with builtins and kunit_tool, also enable the test by default when KUNIT_ALL_TESTS is enabled.
The test can now be run via kunit_tool with: ./tools/testing/kunit/kunit.py run --arch=x86_64 \ --kconfig_add CONFIG_OF=y --kconfig_add CONFIG_OF_ADDRESS=y \ --kconfig_add CONFIG_MMC=y --kconfig_add CONFIG_MMC_SDHCI=y \ --kconfig_add CONFIG_MMC_SDHCI_PLTFM=y \ --kconfig_add CONFIG_MMC_SDHCI_OF_ASPEED=y \ 'sdhci-of-aspeed'
(It may be worth adding a .kunitconfig at some point, as there are enough dependencies to make that command scarily long.)
Signed-off-by: David Gow davidgow@google.com
Acked-by: Daniel Latypov dlatypov@google.com
Minor, optional suggestion below.
static int __init aspeed_sdc_init(void) @@ -639,12 +620,6 @@ static int __init aspeed_sdc_init(void) if (rc < 0) goto cleanup_sdhci;
rc = aspeed_sdc_tests_init();
if (rc < 0) {
platform_driver_unregister(&aspeed_sdc_driver);
goto cleanup_sdhci;
}
return 0;
cleanup_sdhci:
This goto was added in 4af307f57426 ("mmc: sdhci-of-aspeed: Fix kunit-related build error") to allow for this extra call to aspeed_sdc_tests_init().
This could now be reverted back to what is rc = platform_driver_register(&aspeed_sdc_driver); if (rc < 0) platform_driver_unregister(&aspeed_sdhci_driver);
return rc;
but let's see what the maintainers think.
I don't have a strong opinion on this, feel free to pick any of the options.
Acked-by: Ulf Hansson ulf.hansson@linaro.org
Kind regards Uffe
linux-kselftest-mirror@lists.linaro.org