[igt-dev] [PATCH i-g-t 1/2] lib/kunit: Split out reusable part of test case list gathering
Janusz Krzysztofik
janusz.krzysztofik at linux.intel.com
Mon Nov 6 09:59:37 UTC 2023
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 at linux.intel.com>
---
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
More information about the igt-dev
mailing list