Message ID | 20230807102352.4607-5-janusz.krzysztofik@linux.intel.com |
---|---|
Headers | show |
Series | kunit: Expose some built-in features to modules | expand |
On Mon, Aug 7, 2023 at 6:28 AM Janusz Krzysztofik <janusz.krzysztofik@linux.intel.com> wrote: > > According to KTAP specification[1], results should always start from a > header that provides a TAP protocol version, followed by a test plan with > a count of items to be executed. That pattern should be followed at each > nesting level. In the current implementation of the top-most, i.e., test > suite level, those rules apply only for test suites built into the kernel, > executed and reported on boot. Results submitted to dmesg from kunit test > modules loaded later are missing those top-level headers. > > As a consequence, if a kunit test module provides more than one test suite > then, without the top level test plan, external tools that are parsing > dmesg for kunit test output are not able to tell how many test suites > should be expected and whether to continue parsing after complete output > from the first test suite is collected. > > Submit the top-level headers also from the kunit test module notifier > initialization callback. > > v3: Fix new name of a structure moved to kunit namespace not updated in > executor_test functions (lkp@intel.com). > v2: Use kunit_exec_run_tests() (Mauro, Rae), but prevent it from > emitting the headers when called on load of non-test modules. > Hello! This patch looks good. This series also applies cleanly for me now. I have tested this patch and it works well. I realize this is a bigger change by exposing the executor function but I think it is overall cleaner. I am interested in what David Gow thinks about the change. Reviewed-by: Rae Moar <rmoar@google.com> Thanks! Rae > [1] https://docs.kernel.org/dev-tools/ktap.html# > > Signed-off-by: Janusz Krzysztofik <janusz.krzysztofik@linux.intel.com> > Cc: Mauro Carvalho Chehab <mchehab@kernel.org> > Cc: Rae Moar <rmoar@google.com> > --- > include/kunit/test.h | 8 ++++++++ > lib/kunit/executor.c | 42 +++++++++++++++++++++------------------ > lib/kunit/executor_test.c | 36 ++++++++++++++++++++++----------- > lib/kunit/test.c | 6 +++++- > 4 files changed, 60 insertions(+), 32 deletions(-) > > diff --git a/include/kunit/test.h b/include/kunit/test.h > index 011e0d6bb506c..3d002e6b252f2 100644 > --- a/include/kunit/test.h > +++ b/include/kunit/test.h > @@ -256,6 +256,12 @@ struct kunit_suite { > int suite_init_err; > }; > > +/* Stores an array of suites, end points one past the end */ > +struct kunit_suite_set { > + struct kunit_suite * const *start; > + struct kunit_suite * const *end; > +}; > + > /** > * struct kunit - represents a running instance of a test. > * > @@ -317,6 +323,8 @@ int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_ > > void __kunit_test_suites_exit(struct kunit_suite **suites, int num_suites); > > +void kunit_exec_run_tests(struct kunit_suite_set *suite_set, bool builtin); > + > #if IS_BUILTIN(CONFIG_KUNIT) > int kunit_run_all_tests(void); > #else > diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c > index dc295150c4e57..5ef90c334eb0f 100644 > --- a/lib/kunit/executor.c > +++ b/lib/kunit/executor.c > @@ -104,13 +104,7 @@ kunit_filter_glob_tests(const struct kunit_suite *const suite, const char *test_ > static char *kunit_shutdown; > core_param(kunit_shutdown, kunit_shutdown, charp, 0644); > > -/* Stores an array of suites, end points one past the end */ > -struct suite_set { > - struct kunit_suite * const *start; > - struct kunit_suite * const *end; > -}; > - > -static void kunit_free_suite_set(struct suite_set suite_set) > +static void kunit_free_suite_set(struct kunit_suite_set suite_set) > { > struct kunit_suite * const *suites; > > @@ -119,16 +113,17 @@ static void kunit_free_suite_set(struct suite_set suite_set) > kfree(suite_set.start); > } > > -static struct suite_set kunit_filter_suites(const struct suite_set *suite_set, > - const char *filter_glob, > - char *filters, > - char *filter_action, > - int *err) > +static struct kunit_suite_set > +kunit_filter_suites(const struct kunit_suite_set *suite_set, > + const char *filter_glob, > + char *filters, > + char *filter_action, > + int *err) > { > int i, j, k; > int filter_count = 0; > struct kunit_suite **copy, **copy_start, *filtered_suite, *new_filtered_suite; > - struct suite_set filtered = {NULL, NULL}; > + struct kunit_suite_set filtered = {NULL, NULL}; > struct kunit_glob_filter parsed_glob; > struct kunit_attr_filter *parsed_filters = NULL; > > @@ -230,17 +225,24 @@ static void kunit_handle_shutdown(void) > > } > > -static void kunit_exec_run_tests(struct suite_set *suite_set) > +#endif > + > +void kunit_exec_run_tests(struct kunit_suite_set *suite_set, bool builtin) > { > size_t num_suites = suite_set->end - suite_set->start; > > - pr_info("KTAP version 1\n"); > - pr_info("1..%zu\n", num_suites); > + if (builtin || num_suites) { > + pr_info("KTAP version 1\n"); > + pr_info("1..%zu\n", num_suites); > + } > > __kunit_test_suites_init(suite_set->start, num_suites); > } > > -static void kunit_exec_list_tests(struct suite_set *suite_set, bool include_attr) > +#if IS_BUILTIN(CONFIG_KUNIT) > + > +static void kunit_exec_list_tests(struct kunit_suite_set *suite_set, > + bool include_attr) > { > struct kunit_suite * const *suites; > struct kunit_case *test_case; > @@ -265,7 +267,9 @@ static void kunit_exec_list_tests(struct suite_set *suite_set, bool include_attr > > int kunit_run_all_tests(void) > { > - struct suite_set suite_set = {__kunit_suites_start, __kunit_suites_end}; > + struct kunit_suite_set suite_set = { > + __kunit_suites_start, __kunit_suites_end, > + }; > int err = 0; > if (!kunit_enabled()) { > pr_info("kunit: disabled\n"); > @@ -282,7 +286,7 @@ int kunit_run_all_tests(void) > } > > if (!action_param) > - kunit_exec_run_tests(&suite_set); > + kunit_exec_run_tests(&suite_set, true); > else if (strcmp(action_param, "list") == 0) > kunit_exec_list_tests(&suite_set, false); > else if (strcmp(action_param, "list_attr") == 0) > diff --git a/lib/kunit/executor_test.c b/lib/kunit/executor_test.c > index 3e0a1c99cb4e8..4084071d0eb5b 100644 > --- a/lib/kunit/executor_test.c > +++ b/lib/kunit/executor_test.c > @@ -43,8 +43,10 @@ static void parse_filter_test(struct kunit *test) > static void filter_suites_test(struct kunit *test) > { > struct kunit_suite *subsuite[3] = {NULL, NULL}; > - struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]}; > - struct suite_set got; > + struct kunit_suite_set suite_set = { > + .start = subsuite, .end = &subsuite[2], > + }; > + struct kunit_suite_set got; > int err = 0; > > subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); > @@ -67,8 +69,10 @@ static void filter_suites_test(struct kunit *test) > static void filter_suites_test_glob_test(struct kunit *test) > { > struct kunit_suite *subsuite[3] = {NULL, NULL}; > - struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]}; > - struct suite_set got; > + struct kunit_suite_set suite_set = { > + .start = subsuite, .end = &subsuite[2], > + }; > + struct kunit_suite_set got; > int err = 0; > > subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); > @@ -94,8 +98,10 @@ static void filter_suites_test_glob_test(struct kunit *test) > static void filter_suites_to_empty_test(struct kunit *test) > { > struct kunit_suite *subsuite[3] = {NULL, NULL}; > - struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]}; > - struct suite_set got; > + struct kunit_suite_set suite_set = { > + .start = subsuite, .end = &subsuite[2], > + }; > + struct kunit_suite_set got; > int err = 0; > > subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); > @@ -144,8 +150,10 @@ static struct kunit_case dummy_attr_test_cases[] = { > static void filter_attr_test(struct kunit *test) > { > struct kunit_suite *subsuite[3] = {NULL, NULL}; > - struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]}; > - struct suite_set got; > + struct kunit_suite_set suite_set = { > + .start = subsuite, .end = &subsuite[2], > + }; > + struct kunit_suite_set got; > int err = 0; > > subsuite[0] = alloc_fake_suite(test, "normal_suite", dummy_attr_test_cases); > @@ -179,8 +187,10 @@ static void filter_attr_test(struct kunit *test) > static void filter_attr_empty_test(struct kunit *test) > { > struct kunit_suite *subsuite[3] = {NULL, NULL}; > - struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]}; > - struct suite_set got; > + struct kunit_suite_set suite_set = { > + .start = subsuite, .end = &subsuite[2], > + }; > + struct kunit_suite_set got; > int err = 0; > > subsuite[0] = alloc_fake_suite(test, "suite1", dummy_attr_test_cases); > @@ -197,8 +207,10 @@ static void filter_attr_empty_test(struct kunit *test) > static void filter_attr_skip_test(struct kunit *test) > { > struct kunit_suite *subsuite[2] = {NULL}; > - struct suite_set suite_set = {.start = subsuite, .end = &subsuite[1]}; > - struct suite_set got; > + struct kunit_suite_set suite_set = { > + .start = subsuite, .end = &subsuite[1], > + }; > + struct kunit_suite_set got; > int err = 0; > > subsuite[0] = alloc_fake_suite(test, "suite", dummy_attr_test_cases); > diff --git a/lib/kunit/test.c b/lib/kunit/test.c > index cb9797fa6303f..8b2808068497f 100644 > --- a/lib/kunit/test.c > +++ b/lib/kunit/test.c > @@ -736,7 +736,11 @@ EXPORT_SYMBOL_GPL(__kunit_test_suites_exit); > #ifdef CONFIG_MODULES > static void kunit_module_init(struct module *mod) > { > - __kunit_test_suites_init(mod->kunit_suites, mod->num_kunit_suites); > + struct kunit_suite_set suite_set = { > + mod->kunit_suites, mod->kunit_suites + mod->num_kunit_suites, > + }; > + > + kunit_exec_run_tests(&suite_set, false); > } > > static void kunit_module_exit(struct module *mod) > -- > 2.41.0 >
On Mon, 7 Aug 2023 at 18:28, Janusz Krzysztofik <janusz.krzysztofik@linux.intel.com> wrote: > > According to KTAP specification[1], results should always start from a > header that provides a TAP protocol version, followed by a test plan with > a count of items to be executed. That pattern should be followed at each > nesting level. In the current implementation of the top-most, i.e., test > suite level, those rules apply only for test suites built into the kernel, > executed and reported on boot. Results submitted to dmesg from kunit test > modules loaded later are missing those top-level headers. > > As a consequence, if a kunit test module provides more than one test suite > then, without the top level test plan, external tools that are parsing > dmesg for kunit test output are not able to tell how many test suites > should be expected and whether to continue parsing after complete output > from the first test suite is collected. > > Submit the top-level headers also from the kunit test module notifier > initialization callback. > > v3: Fix new name of a structure moved to kunit namespace not updated in > executor_test functions (lkp@intel.com). > v2: Use kunit_exec_run_tests() (Mauro, Rae), but prevent it from > emitting the headers when called on load of non-test modules. > > [1] https://docs.kernel.org/dev-tools/ktap.html# > > Signed-off-by: Janusz Krzysztofik <janusz.krzysztofik@linux.intel.com> > Cc: Mauro Carvalho Chehab <mchehab@kernel.org> > Cc: Rae Moar <rmoar@google.com> > --- Thanks! This is a long overdue feature, and it seems to work well here. Reviewed-by: David Gow <davidgow@google.com> Cheers, -- David > include/kunit/test.h | 8 ++++++++ > lib/kunit/executor.c | 42 +++++++++++++++++++++------------------ > lib/kunit/executor_test.c | 36 ++++++++++++++++++++++----------- > lib/kunit/test.c | 6 +++++- > 4 files changed, 60 insertions(+), 32 deletions(-) > > diff --git a/include/kunit/test.h b/include/kunit/test.h > index 011e0d6bb506c..3d002e6b252f2 100644 > --- a/include/kunit/test.h > +++ b/include/kunit/test.h > @@ -256,6 +256,12 @@ struct kunit_suite { > int suite_init_err; > }; > > +/* Stores an array of suites, end points one past the end */ > +struct kunit_suite_set { > + struct kunit_suite * const *start; > + struct kunit_suite * const *end; > +}; > + > /** > * struct kunit - represents a running instance of a test. > * > @@ -317,6 +323,8 @@ int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_ > > void __kunit_test_suites_exit(struct kunit_suite **suites, int num_suites); > > +void kunit_exec_run_tests(struct kunit_suite_set *suite_set, bool builtin); > + > #if IS_BUILTIN(CONFIG_KUNIT) > int kunit_run_all_tests(void); > #else > diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c > index dc295150c4e57..5ef90c334eb0f 100644 > --- a/lib/kunit/executor.c > +++ b/lib/kunit/executor.c > @@ -104,13 +104,7 @@ kunit_filter_glob_tests(const struct kunit_suite *const suite, const char *test_ > static char *kunit_shutdown; > core_param(kunit_shutdown, kunit_shutdown, charp, 0644); > > -/* Stores an array of suites, end points one past the end */ > -struct suite_set { > - struct kunit_suite * const *start; > - struct kunit_suite * const *end; > -}; > - > -static void kunit_free_suite_set(struct suite_set suite_set) > +static void kunit_free_suite_set(struct kunit_suite_set suite_set) > { > struct kunit_suite * const *suites; > > @@ -119,16 +113,17 @@ static void kunit_free_suite_set(struct suite_set suite_set) > kfree(suite_set.start); > } > > -static struct suite_set kunit_filter_suites(const struct suite_set *suite_set, > - const char *filter_glob, > - char *filters, > - char *filter_action, > - int *err) > +static struct kunit_suite_set > +kunit_filter_suites(const struct kunit_suite_set *suite_set, > + const char *filter_glob, > + char *filters, > + char *filter_action, > + int *err) > { > int i, j, k; > int filter_count = 0; > struct kunit_suite **copy, **copy_start, *filtered_suite, *new_filtered_suite; > - struct suite_set filtered = {NULL, NULL}; > + struct kunit_suite_set filtered = {NULL, NULL}; > struct kunit_glob_filter parsed_glob; > struct kunit_attr_filter *parsed_filters = NULL; > > @@ -230,17 +225,24 @@ static void kunit_handle_shutdown(void) > > } > > -static void kunit_exec_run_tests(struct suite_set *suite_set) > +#endif > + > +void kunit_exec_run_tests(struct kunit_suite_set *suite_set, bool builtin) > { > size_t num_suites = suite_set->end - suite_set->start; > > - pr_info("KTAP version 1\n"); > - pr_info("1..%zu\n", num_suites); > + if (builtin || num_suites) { > + pr_info("KTAP version 1\n"); > + pr_info("1..%zu\n", num_suites); > + } > > __kunit_test_suites_init(suite_set->start, num_suites); > } > > -static void kunit_exec_list_tests(struct suite_set *suite_set, bool include_attr) > +#if IS_BUILTIN(CONFIG_KUNIT) > + > +static void kunit_exec_list_tests(struct kunit_suite_set *suite_set, > + bool include_attr) > { > struct kunit_suite * const *suites; > struct kunit_case *test_case; > @@ -265,7 +267,9 @@ static void kunit_exec_list_tests(struct suite_set *suite_set, bool include_attr > > int kunit_run_all_tests(void) > { > - struct suite_set suite_set = {__kunit_suites_start, __kunit_suites_end}; > + struct kunit_suite_set suite_set = { > + __kunit_suites_start, __kunit_suites_end, > + }; > int err = 0; > if (!kunit_enabled()) { > pr_info("kunit: disabled\n"); > @@ -282,7 +286,7 @@ int kunit_run_all_tests(void) > } > > if (!action_param) > - kunit_exec_run_tests(&suite_set); > + kunit_exec_run_tests(&suite_set, true); > else if (strcmp(action_param, "list") == 0) > kunit_exec_list_tests(&suite_set, false); > else if (strcmp(action_param, "list_attr") == 0) > diff --git a/lib/kunit/executor_test.c b/lib/kunit/executor_test.c > index 3e0a1c99cb4e8..4084071d0eb5b 100644 > --- a/lib/kunit/executor_test.c > +++ b/lib/kunit/executor_test.c > @@ -43,8 +43,10 @@ static void parse_filter_test(struct kunit *test) > static void filter_suites_test(struct kunit *test) > { > struct kunit_suite *subsuite[3] = {NULL, NULL}; > - struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]}; > - struct suite_set got; > + struct kunit_suite_set suite_set = { > + .start = subsuite, .end = &subsuite[2], > + }; > + struct kunit_suite_set got; > int err = 0; > > subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); > @@ -67,8 +69,10 @@ static void filter_suites_test(struct kunit *test) > static void filter_suites_test_glob_test(struct kunit *test) > { > struct kunit_suite *subsuite[3] = {NULL, NULL}; > - struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]}; > - struct suite_set got; > + struct kunit_suite_set suite_set = { > + .start = subsuite, .end = &subsuite[2], > + }; > + struct kunit_suite_set got; > int err = 0; > > subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); > @@ -94,8 +98,10 @@ static void filter_suites_test_glob_test(struct kunit *test) > static void filter_suites_to_empty_test(struct kunit *test) > { > struct kunit_suite *subsuite[3] = {NULL, NULL}; > - struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]}; > - struct suite_set got; > + struct kunit_suite_set suite_set = { > + .start = subsuite, .end = &subsuite[2], > + }; > + struct kunit_suite_set got; > int err = 0; > > subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); > @@ -144,8 +150,10 @@ static struct kunit_case dummy_attr_test_cases[] = { > static void filter_attr_test(struct kunit *test) > { > struct kunit_suite *subsuite[3] = {NULL, NULL}; > - struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]}; > - struct suite_set got; > + struct kunit_suite_set suite_set = { > + .start = subsuite, .end = &subsuite[2], > + }; > + struct kunit_suite_set got; > int err = 0; > > subsuite[0] = alloc_fake_suite(test, "normal_suite", dummy_attr_test_cases); > @@ -179,8 +187,10 @@ static void filter_attr_test(struct kunit *test) > static void filter_attr_empty_test(struct kunit *test) > { > struct kunit_suite *subsuite[3] = {NULL, NULL}; > - struct suite_set suite_set = {.start = subsuite, .end = &subsuite[2]}; > - struct suite_set got; > + struct kunit_suite_set suite_set = { > + .start = subsuite, .end = &subsuite[2], > + }; > + struct kunit_suite_set got; > int err = 0; > > subsuite[0] = alloc_fake_suite(test, "suite1", dummy_attr_test_cases); > @@ -197,8 +207,10 @@ static void filter_attr_empty_test(struct kunit *test) > static void filter_attr_skip_test(struct kunit *test) > { > struct kunit_suite *subsuite[2] = {NULL}; > - struct suite_set suite_set = {.start = subsuite, .end = &subsuite[1]}; > - struct suite_set got; > + struct kunit_suite_set suite_set = { > + .start = subsuite, .end = &subsuite[1], > + }; > + struct kunit_suite_set got; > int err = 0; > > subsuite[0] = alloc_fake_suite(test, "suite", dummy_attr_test_cases); > diff --git a/lib/kunit/test.c b/lib/kunit/test.c > index cb9797fa6303f..8b2808068497f 100644 > --- a/lib/kunit/test.c > +++ b/lib/kunit/test.c > @@ -736,7 +736,11 @@ EXPORT_SYMBOL_GPL(__kunit_test_suites_exit); > #ifdef CONFIG_MODULES > static void kunit_module_init(struct module *mod) > { > - __kunit_test_suites_init(mod->kunit_suites, mod->num_kunit_suites); > + struct kunit_suite_set suite_set = { > + mod->kunit_suites, mod->kunit_suites + mod->num_kunit_suites, > + }; > + > + kunit_exec_run_tests(&suite_set, false); > } > > static void kunit_module_exit(struct module *mod) > -- > 2.41.0 >
On Mon, 7 Aug 2023 at 18:28, Janusz Krzysztofik <janusz.krzysztofik@linux.intel.com> wrote: > > External tools, e.g., Intel GPU tools (IGT), support execution of > individual selftests provided by kernel modules. That could be also > applicable to kunit test modules if they provided test filtering. But > test filtering is now possible only when kunit code is built into the > kernel. Moreover, a filter can be specified only at boot time, then > reboot is required each time a different filter is needed. > > Build the test filtering code also when kunit is configured as a module, > expose test filtering functions to other kunit source files, and use them > in kunit module notifier callback functions. Userspace can then reload > the kunit module with a value of the filter_glob parameter tuned to a > specific kunit test module every time it wants to limit the scope of tests > executed on that module load. Make the kunit.filter* parameters visible > in sysfs for user convenience. > > v5: Refresh on tpp of attributes filtering fix > v4: Refresh on top of newly applied attributes patches and changes > introdced by new versions of other patches submitted in series with > this one. > v3: Fix CONFIG_GLOB, required by filtering functions, not selected when > building as a module (lkp@intel.com). > v2: Fix new name of a structure moved to kunit namespace not updated > across all uses (lkp@intel.com). > > Signed-off-by: Janusz Krzysztofik <janusz.krzysztofik@linux.intel.com> > --- This works a treat here. It's a bit annoying to have to unload / reload the module to change the filter, which might be something for us to consider in the future (maybe via a debugfs entry?), but this is nevertheless an improvement. Reviewed-by: David Gow <davidgow@google.com> Cheers, -- David > include/kunit/test.h | 11 ++++++++ > lib/kunit/Kconfig | 2 +- > lib/kunit/executor.c | 63 ++++++++++++++++++++++++++------------------ > lib/kunit/test.c | 17 ++++++++++++ > 4 files changed, 66 insertions(+), 27 deletions(-) > > diff --git a/include/kunit/test.h b/include/kunit/test.h > index 6a338a3267ed5..d33114097d0d0 100644 > --- a/include/kunit/test.h > +++ b/include/kunit/test.h > @@ -310,6 +310,9 @@ static inline void kunit_set_failure(struct kunit *test) > > bool kunit_enabled(void); > const char *kunit_action(void); > +const char *kunit_filter_glob(void); > +char *kunit_filter(void); > +char *kunit_filter_action(void); > > void kunit_init_test(struct kunit *test, const char *name, char *log); > > @@ -320,6 +323,14 @@ 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); > > +struct kunit_suite_set > +kunit_filter_suites(const struct kunit_suite_set *suite_set, > + const char *filter_glob, > + char *filters, > + char *filter_action, > + int *err); > +void kunit_free_suite_set(struct kunit_suite_set suite_set); > + > int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_suites); > > void __kunit_test_suites_exit(struct kunit_suite **suites, int num_suites); > diff --git a/lib/kunit/Kconfig b/lib/kunit/Kconfig > index 626719b95badd..68a6daec0aef1 100644 > --- a/lib/kunit/Kconfig > +++ b/lib/kunit/Kconfig > @@ -4,7 +4,7 @@ > > menuconfig KUNIT > tristate "KUnit - Enable support for unit tests" > - select GLOB if KUNIT=y > + select GLOB > help > Enables support for kernel unit tests (KUnit), a lightweight unit > testing and mocking framework for the Linux kernel. These tests are > diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c > index e877c1f1e75c8..5181aa2e760b6 100644 > --- a/lib/kunit/executor.c > +++ b/lib/kunit/executor.c > @@ -27,24 +27,37 @@ const char *kunit_action(void) > return action_param; > } > > -#if IS_BUILTIN(CONFIG_KUNIT) > - > static char *filter_glob_param; > static char *filter_param; > static char *filter_action_param; > > -module_param_named(filter_glob, filter_glob_param, charp, 0); > +module_param_named(filter_glob, filter_glob_param, charp, 0400); > MODULE_PARM_DESC(filter_glob, > "Filter which KUnit test suites/tests run at boot-time, e.g. list* or list*.*del_test"); > -module_param_named(filter, filter_param, charp, 0); > +module_param_named(filter, filter_param, charp, 0400); > MODULE_PARM_DESC(filter, > "Filter which KUnit test suites/tests run at boot-time using attributes, e.g. speed>slow"); > -module_param_named(filter_action, filter_action_param, charp, 0); > +module_param_named(filter_action, filter_action_param, charp, 0400); > MODULE_PARM_DESC(filter_action, > "Changes behavior of filtered tests using attributes, valid values are:\n" > "<none>: do not run filtered tests as normal\n" > "'skip': skip all filtered tests instead so tests will appear in output\n"); > > +const char *kunit_filter_glob(void) > +{ > + return filter_glob_param; > +} > + > +char *kunit_filter(void) > +{ > + return filter_param; > +} > + > +char *kunit_filter_action(void) > +{ > + return filter_action_param; > +} > + > /* glob_match() needs NULL terminated strings, so we need a copy of filter_glob_param. */ > struct kunit_glob_filter { > char *suite_glob; > @@ -108,10 +121,7 @@ kunit_filter_glob_tests(const struct kunit_suite *const suite, const char *test_ > return copy; > } > > -static char *kunit_shutdown; > -core_param(kunit_shutdown, kunit_shutdown, charp, 0644); > - > -static void kunit_free_suite_set(struct kunit_suite_set suite_set) > +void kunit_free_suite_set(struct kunit_suite_set suite_set) > { > struct kunit_suite * const *suites; > > @@ -120,7 +130,7 @@ static void kunit_free_suite_set(struct kunit_suite_set suite_set) > kfree(suite_set.start); > } > > -static struct kunit_suite_set > +struct kunit_suite_set > kunit_filter_suites(const struct kunit_suite_set *suite_set, > const char *filter_glob, > char *filters, > @@ -218,22 +228,6 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set, > return filtered; > } > > -static void kunit_handle_shutdown(void) > -{ > - if (!kunit_shutdown) > - return; > - > - if (!strcmp(kunit_shutdown, "poweroff")) > - kernel_power_off(); > - else if (!strcmp(kunit_shutdown, "halt")) > - kernel_halt(); > - else if (!strcmp(kunit_shutdown, "reboot")) > - kernel_restart(NULL); > - > -} > - > -#endif > - > void kunit_exec_run_tests(struct kunit_suite_set *suite_set, bool builtin) > { > size_t num_suites = suite_set->end - suite_set->start; > @@ -271,6 +265,23 @@ void kunit_exec_list_tests(struct kunit_suite_set *suite_set, bool include_attr) > > #if IS_BUILTIN(CONFIG_KUNIT) > > +static char *kunit_shutdown; > +core_param(kunit_shutdown, kunit_shutdown, charp, 0644); > + > +static void kunit_handle_shutdown(void) > +{ > + if (!kunit_shutdown) > + return; > + > + if (!strcmp(kunit_shutdown, "poweroff")) > + kernel_power_off(); > + else if (!strcmp(kunit_shutdown, "halt")) > + kernel_halt(); > + else if (!strcmp(kunit_shutdown, "reboot")) > + kernel_restart(NULL); > + > +} > + > int kunit_run_all_tests(void) > { > struct kunit_suite_set suite_set = { > diff --git a/lib/kunit/test.c b/lib/kunit/test.c > index 5232a43737826..49698a168437a 100644 > --- a/lib/kunit/test.c > +++ b/lib/kunit/test.c > @@ -740,6 +740,17 @@ static void kunit_module_init(struct module *mod) > mod->kunit_suites, mod->kunit_suites + mod->num_kunit_suites, > }; > const char *action = kunit_action(); > + int err = 0; > + > + suite_set = kunit_filter_suites(&suite_set, > + kunit_filter_glob() ?: "*.*", I've just learnt a new gcc extension! A bit scary, but it works on clang as well, so I'm fine with it. > + kunit_filter(), kunit_filter_action(), > + &err); > + if (err) > + pr_err("kunit module: error filtering suites: %d\n", err); > + > + mod->kunit_suites = (struct kunit_suite **)suite_set.start; > + mod->num_kunit_suites = suite_set.end - suite_set.start; > > if (!action) > kunit_exec_run_tests(&suite_set, false); > @@ -753,11 +764,17 @@ static void kunit_module_init(struct module *mod) > > static void kunit_module_exit(struct module *mod) > { > + struct kunit_suite_set suite_set = { > + mod->kunit_suites, mod->kunit_suites + mod->num_kunit_suites, > + }; > const char *action = kunit_action(); > > if (!action) > __kunit_test_suites_exit(mod->kunit_suites, > mod->num_kunit_suites); > + > + if (suite_set.start) > + kunit_free_suite_set(suite_set); > } > > static int kunit_module_notify(struct notifier_block *nb, unsigned long val, > -- > 2.41.0 >