Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Marie Zhussupova and committed by
Shuah Khan
4b59300b 922d1dde

+26 -16
+6 -2
include/kunit/test.h
··· 268 268 * 269 269 * @priv: for user to store arbitrary data. Commonly used to pass data 270 270 * 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. 271 273 * 272 274 * Used to store information about the current context under which the test 273 275 * 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. 276 279 */ 277 280 struct kunit { 278 281 void *priv; 282 + struct kunit *parent; 279 283 280 284 /* private: internal use only. */ 281 285 const char *name; /* Read only after initialization! */
+20 -14
lib/kunit/test.c
··· 647 647 struct kunit_case *test_case; 648 648 struct kunit_result_stats suite_stats = { 0 }; 649 649 struct kunit_result_stats total_stats = { 0 }; 650 + const void *curr_param; 650 651 651 652 /* Taint the kernel so we know we've run tests. */ 652 653 add_taint(TAINT_TEST, LOCKDEP_STILL_OK); ··· 680 679 } else { 681 680 /* Get initial param. */ 682 681 param_desc[0] = '\0'; 683 - test.param_value = test_case->generate_params(NULL, param_desc); 682 + /* TODO: Make generate_params try-catch */ 683 + curr_param = test_case->generate_params(NULL, param_desc); 684 684 test_case->status = KUNIT_SKIPPED; 685 685 kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT 686 686 "KTAP version 1\n"); 687 687 kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT 688 688 "# Subtest: %s", test_case->name); 689 689 690 - while (test.param_value) { 691 - kunit_run_case_catch_errors(suite, test_case, &test); 690 + while (curr_param) { 691 + struct kunit param_test = { 692 + .param_value = curr_param, 693 + .param_index = ++test.param_index, 694 + .parent = &test, 695 + }; 696 + kunit_init_test(&param_test, test_case->name, test_case->log); 697 + kunit_run_case_catch_errors(suite, test_case, &param_test); 692 698 693 699 if (param_desc[0] == '\0') { 694 700 snprintf(param_desc, sizeof(param_desc), 695 - "param-%d", test.param_index); 701 + "param-%d", param_test.param_index); 696 702 } 697 703 698 - kunit_print_ok_not_ok(&test, KUNIT_LEVEL_CASE_PARAM, 699 - test.status, 700 - test.param_index + 1, 704 + kunit_print_ok_not_ok(&param_test, KUNIT_LEVEL_CASE_PARAM, 705 + param_test.status, 706 + param_test.param_index, 701 707 param_desc, 702 - test.status_comment); 708 + param_test.status_comment); 703 709 704 - kunit_update_stats(&param_stats, test.status); 710 + kunit_update_stats(&param_stats, param_test.status); 705 711 706 712 /* Get next param. */ 707 713 param_desc[0] = '\0'; 708 - test.param_value = test_case->generate_params(test.param_value, param_desc); 709 - test.param_index++; 710 - test.status = KUNIT_SUCCESS; 711 - test.status_comment[0] = '\0'; 712 - test.priv = NULL; 714 + curr_param = test_case->generate_params(curr_param, param_desc); 713 715 } 716 + /* TODO: Put this kunit_cleanup into a try-catch. */ 717 + kunit_cleanup(&test); 714 718 } 715 719 716 720 kunit_print_attr((void *)test_case, true, KUNIT_LEVEL_CASE);