Skip to content

Commit 4b59300

Browse files
Marie Zhussupovashuahkh
authored andcommitted
kunit: Add parent kunit for parameterized test context
Currently, KUnit parameterized tests lack a mechanism to share resources across parameter runs because the same `struct kunit` instance is cleaned up and reused for each run. This patch introduces parameterized test context, enabling test users to share resources between parameter runs. It also allows setting up resources that need to be available for all parameter runs only once, which is helpful in cases where setup is expensive. To establish a parameterized test context, this patch adds a parent pointer field to `struct kunit`. This allows resources added to the parent `struct kunit` to be shared and accessible across all parameter runs. In kunit_run_tests(), the default `struct kunit` created is now designated to act as the parameterized test context whenever a test is parameterized. Subsequently, a new `struct kunit` is made for each parameter run, and its parent pointer is set to the `struct kunit` that holds the parameterized test context. Link: https://lore.kernel.org/r/20250826091341.1427123-2-davidgow@google.com Reviewed-by: David Gow <davidgow@google.com> Reviewed-by: Rae Moar <rmoar@google.com> Signed-off-by: Marie Zhussupova <marievic@google.com> Signed-off-by: David Gow <davidgow@google.com> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
1 parent 922d1dd commit 4b59300

File tree

2 files changed

+26
-16
lines changed

2 files changed

+26
-16
lines changed

include/kunit/test.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,14 +268,18 @@ struct kunit_suite_set {
268268
*
269269
* @priv: for user to store arbitrary data. Commonly used to pass data
270270
* created in the init function (see &struct kunit_suite).
271+
* @parent: reference to the parent context of type struct kunit that can
272+
* be used for storing shared resources.
271273
*
272274
* Used to store information about the current context under which the test
273275
* is running. Most of this data is private and should only be accessed
274-
* indirectly via public functions; the one exception is @priv which can be
275-
* used by the test writer to store arbitrary data.
276+
* indirectly via public functions; the two exceptions are @priv and @parent
277+
* which can be used by the test writer to store arbitrary data and access the
278+
* parent context, respectively.
276279
*/
277280
struct kunit {
278281
void *priv;
282+
struct kunit *parent;
279283

280284
/* private: internal use only. */
281285
const char *name; /* Read only after initialization! */

lib/kunit/test.c

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,7 @@ int kunit_run_tests(struct kunit_suite *suite)
647647
struct kunit_case *test_case;
648648
struct kunit_result_stats suite_stats = { 0 };
649649
struct kunit_result_stats total_stats = { 0 };
650+
const void *curr_param;
650651

651652
/* Taint the kernel so we know we've run tests. */
652653
add_taint(TAINT_TEST, LOCKDEP_STILL_OK);
@@ -679,37 +680,42 @@ int kunit_run_tests(struct kunit_suite *suite)
679680
} else {
680681
/* Get initial param. */
681682
param_desc[0] = '\0';
682-
test.param_value = test_case->generate_params(NULL, param_desc);
683+
/* TODO: Make generate_params try-catch */
684+
curr_param = test_case->generate_params(NULL, param_desc);
683685
test_case->status = KUNIT_SKIPPED;
684686
kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT
685687
"KTAP version 1\n");
686688
kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT
687689
"# Subtest: %s", test_case->name);
688690

689-
while (test.param_value) {
690-
kunit_run_case_catch_errors(suite, test_case, &test);
691+
while (curr_param) {
692+
struct kunit param_test = {
693+
.param_value = curr_param,
694+
.param_index = ++test.param_index,
695+
.parent = &test,
696+
};
697+
kunit_init_test(&param_test, test_case->name, test_case->log);
698+
kunit_run_case_catch_errors(suite, test_case, &param_test);
691699

692700
if (param_desc[0] == '\0') {
693701
snprintf(param_desc, sizeof(param_desc),
694-
"param-%d", test.param_index);
702+
"param-%d", param_test.param_index);
695703
}
696704

697-
kunit_print_ok_not_ok(&test, KUNIT_LEVEL_CASE_PARAM,
698-
test.status,
699-
test.param_index + 1,
705+
kunit_print_ok_not_ok(&param_test, KUNIT_LEVEL_CASE_PARAM,
706+
param_test.status,
707+
param_test.param_index,
700708
param_desc,
701-
test.status_comment);
709+
param_test.status_comment);
702710

703-
kunit_update_stats(&param_stats, test.status);
711+
kunit_update_stats(&param_stats, param_test.status);
704712

705713
/* Get next param. */
706714
param_desc[0] = '\0';
707-
test.param_value = test_case->generate_params(test.param_value, param_desc);
708-
test.param_index++;
709-
test.status = KUNIT_SUCCESS;
710-
test.status_comment[0] = '\0';
711-
test.priv = NULL;
715+
curr_param = test_case->generate_params(curr_param, param_desc);
712716
}
717+
/* TODO: Put this kunit_cleanup into a try-catch. */
718+
kunit_cleanup(&test);
713719
}
714720

715721
kunit_print_attr((void *)test_case, true, KUNIT_LEVEL_CASE);

0 commit comments

Comments
 (0)