We are going to make use of kunit test case filtering feature, now also available to modular builds. That means we will no longer need to load a kunit test module in background and parse its all test cases KTAP output in parallel, only wait for the module to load with a filter for a specific test case, then parse its KTAP output containing only result of that single test case. We already have a piece of code that just collects all results from KTAP report, used for fetching the list of test cases from the module. Move that code to a separate function, ready for reuse as a parser of complete results of a single test case. Signed-off-by: Janusz Krzysztofik <janusz.krzysztofik@xxxxxxxxxxxxxxx> --- lib/igt_kmod.c | 127 +++++++++++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 47 deletions(-) diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c index e967c9bcdc..37591b7389 100644 --- a/lib/igt_kmod.c +++ b/lib/igt_kmod.c @@ -953,6 +953,73 @@ static void kunit_results_free(struct igt_list_head *results, free(*suite_name); } +static int kunit_kmsg_get_results(struct igt_list_head *results, + struct igt_ktest *tst, + const char *filter, + const char *opts) +{ + char *suite_name = NULL, *case_name = NULL; + struct igt_ktap_results *ktap; + int flags, err; + + if (igt_debug_on(tst->kmsg < 0)) + return tst->kmsg; + + if (igt_debug_on((flags = fcntl(tst->kmsg, F_GETFL, 0), flags < 0))) + return flags; + + if (flags & O_NONBLOCK && + igt_debug_on((err = fcntl(tst->kmsg, F_SETFL, flags & ~O_NONBLOCK), + err == -1))) + return -errno; + + errno = 0; + if (igt_debug_on(lseek(tst->kmsg, 0, SEEK_END) == -1 && errno)) + return -errno; + + err = igt_debug_on(igt_kmod_load("kunit", filter)); + if (err) { + /* + * TODO: drop the following workaround, which is required by LTS + * kernel v6.1 not capable of listing nor filtering test + * cases when built as a module. + * If loading the kunit module with required parameters fails + * then assume that we are running on a kernel with missing test + * case listing and filtering capabilities. Don't fail but just + * return with empty list of test cases, that should tell the + * caller to use a legacy method of iterating over KTAP results + * collected from blind execution of all Kunit test cases + * provided by a Kunit test module. + */ + return 0; + } + + err = igt_debug_on(modprobe(tst->kmod, opts)); + if (err) + goto out_kmod_unload; + + ktap = igt_ktap_alloc(results); + if (igt_debug_on(!ktap)) { + err = -ENOMEM; + goto out_remove_module; + } + + do + igt_debug_on((err = kunit_kmsg_result_get(results, NULL, tst->kmsg, ktap), + err && err != -EINPROGRESS)); + while (err == -EINPROGRESS); + + igt_ktap_free(ktap); + + if (err) + kunit_results_free(results, &case_name, &suite_name); + +out_remove_module: + igt_debug_on(kmod_module_remove_module(tst->kmod, KMOD_REMOVE_FORCE)); +out_kmod_unload: + return igt_debug_on(igt_kmod_unload("kunit", KMOD_REMOVE_FORCE)) ?: err; +} + static void __igt_kunit_legacy(struct igt_ktest *tst, const char *name, const char *opts) @@ -1094,16 +1161,7 @@ static void kunit_get_tests(struct igt_list_head *tests, { char *suite_name = NULL, *case_name = NULL; struct igt_ktap_result *r, *rn; - struct igt_ktap_results *ktap; - int flags, err; - - igt_skip_on_f(tst->kmsg < 0, "Could not open /dev/kmsg\n"); - - igt_skip_on((flags = fcntl(tst->kmsg, F_GETFL, 0), flags < 0)); - igt_skip_on_f(fcntl(tst->kmsg, F_SETFL, flags & ~O_NONBLOCK) == -1, - "Could not set /dev/kmsg to blocking mode\n"); - - igt_skip_on(lseek(tst->kmsg, 0, SEEK_END) < 0); + int err = 0; /* * To get a list of test cases provided by a kunit test module, ask the @@ -1112,44 +1170,22 @@ static void kunit_get_tests(struct igt_list_head *tests, * however, parsing a KTAP report -- something that we already can do * perfectly -- seems to be more safe than extracting a test case list * of unknown length from /dev/kmsg. - * - * TODO: drop the following workaround, which is required by LTS kernel - * v6.1 not capable of listing test cases when built as a module. - * If loading the kunit module with required parameters fails then - * assume that we are running on a kernel with missing test case listing - * capabilities. Dont's skip but just return with empty list of test - * cases, that should tell the caller to use a legacy method of - * iterating over KTAP results collected from blind execution of all - * Kunit test cases provided by a Kunit test module. */ - if (igt_debug_on(igt_kmod_load("kunit", - "filter=module=none filter_action=skip"))) - return; - - igt_skip_on(modprobe(tst->kmod, opts)); + igt_skip_on(kunit_kmsg_get_results(tests, tst, + "filter=module=none filter_action=skip", opts)); - ktap = igt_ktap_alloc(tests); - igt_require(ktap); - - do - err = kunit_kmsg_result_get(tests, NULL, tst->kmsg, ktap); - while (err == -EINPROGRESS); - - igt_ktap_free(ktap); - - if (!err) - igt_list_for_each_entry_safe(r, rn, tests, link) { - if (igt_debug_on(r->code != IGT_EXIT_SKIP)) { - err = r->code ?: -EPROTO; - break; - } + igt_list_for_each_entry_safe(r, rn, tests, link) { + if (igt_debug_on(r->code != IGT_EXIT_SKIP)) { + err = r->code ?: -EPROTO; + break; + } - if (!filter) - continue; + if (!filter) + continue; - if (strcmp(r->suite_name, filter)) - kunit_result_free(&r, &case_name, &suite_name); - } + if (strcmp(r->suite_name, filter)) + kunit_result_free(&r, &case_name, &suite_name); + } if (err) { kunit_results_free(tests, &case_name, &suite_name); @@ -1158,9 +1194,6 @@ static void kunit_get_tests(struct igt_list_head *tests, free(case_name); } - igt_skip_on(kmod_module_remove_module(tst->kmod, KMOD_REMOVE_FORCE)); - igt_skip_on(igt_kmod_unload("kunit", KMOD_REMOVE_FORCE)); - igt_skip_on_f(err, "KTAP parser failed while getting a list of test cases\n"); } -- 2.42.0