[PATCH 7/9] kunit: Add example parameterized test with shared resources and direct static parameter array setup
Marie Zhussupova
marievic at google.com
Wed Aug 6 17:50:31 UTC 2025
On Sat, Aug 2, 2025 at 5:45 AM David Gow <davidgow at google.com> wrote:
>
> On Wed, 30 Jul 2025 at 03:37, Marie Zhussupova <marievic at google.com> wrote:
> >
> > Add `example_params_test_with_init` to illustrate how to manage
> > shared resources across parameterized KUnit tests. This example
> > showcases the use of the new `param_init` function and its registration
> > to a test using the `KUNIT_CASE_PARAM_WITH_INIT` macro.
> >
> > Additionally, the test demonstrates:
> > - How to directly assign a static parameter array to a test via
> > `kunit_register_params_array`.
> > - Leveraging the Resource API for test resource management.
> >
> > Signed-off-by: Marie Zhussupova <marievic at google.com>
> > ---
>
> Thanks for writing some examples! This is great, and makes the rest of
> the series much easier to understand.
>
> (It also reminds me how much I hate the verbose parts of the resource
> API, but it's definitely out of scope to refactor that here. :-))
>
> It does seem like this is a lot of effort to go through for one shared
> integer, though. In the real world, I'd suggest using
> kunit->parent->priv here. As an example, though, it's fine (though
> maybe using a named resource or even kunit_kzalloc() or similar would
> give a better example of how convenient this could be.
>
> It's also not entirely clear why we're using
> kunit_register_params_array() for a static array, when
> KUNIT_ARRAY_PARAM() exists. (This is clearly because the latter
> doesn't support init functions; and I see why we don't necessarily
> want to make the number of macros explode through adding
> KUNIT_ARRAY_PARAM_WITH_INIT() et al, but maybe we should note that in
> the commit description, either here or before.)
>
> Actual test looks fine, though:
>
> Reviewed-by: David Gow <davidgow at google.com>
>
> Cheers,
> -- David
>
Hello David,
I agree that using the Resource API for a single integer is a bit extra.
My idea behind this test was to demonstrate that the Resource API
could be used for managing shared resources and to have the
style of the existing example tests that do simple things with integers.
Using kunit_kzalloc() would be a great simplification. As for a named
resource, we don't have a function to allocate named resources yet
as would be needed here, but that sounds like a great future patch.
We can actually use the KUNIT_ARRAY_PARAM() macro with
KUNIT_CASE_PARAM_WITH_INIT(). We would just pass that created
`*_gen_params` function to KUNIT_CASE_PARAM_WITH_INIT()
instead of NULL. The reason I used kunit_register_params_array() with
the static array was to show that test users can pass a static array
this way, as well, and also to avoid making the test too long with the
dynamic array
creation. But I do like the consistency of using KUNIT_ARRAY_PARAM()
for static arrays and kunit_register_params_array() only for
dynamic ones.
Thank you,
-Marie
>
> > lib/kunit/kunit-example-test.c | 112 +++++++++++++++++++++++++++++++++
> > 1 file changed, 112 insertions(+)
> >
> > diff --git a/lib/kunit/kunit-example-test.c b/lib/kunit/kunit-example-test.c
> > index 3056d6bc705d..5bf559e243f6 100644
> > --- a/lib/kunit/kunit-example-test.c
> > +++ b/lib/kunit/kunit-example-test.c
> > @@ -277,6 +277,116 @@ static void example_slow_test(struct kunit *test)
> > KUNIT_EXPECT_EQ(test, 1 + 1, 2);
> > }
> >
> > +/*
> > + * This custom function allocates memory for the kunit_resource data field.
> > + * The function is passed to kunit_alloc_resource() and executed once
> > + * by the internal helper __kunit_add_resource().
> > + */
> > +static int example_resource_init(struct kunit_resource *res, void *context)
> > +{
> > + int *info = kmalloc(sizeof(*info), GFP_KERNEL);
> > +
> > + if (!info)
> > + return -ENOMEM;
> > + *info = *(int *)context;
> > + res->data = info;
> > + return 0;
> > +}
> > +
> > +/*
> > + * This function deallocates memory for the 'kunit_resource' data field.
> > + * The function is passed to kunit_alloc_resource() and automatically
> > + * executes within kunit_release_resource() when the resource's reference
> > + * count, via kunit_put_resource(), drops to zero. KUnit uses reference
> > + * counting to ensure that resources are not freed prematurely.
> > + */
> > +static void example_resource_free(struct kunit_resource *res)
> > +{
> > + kfree(res->data);
> > +}
> > +
> > +/*
> > + * This match function is invoked by kunit_find_resource() to locate
> > + * a test resource based on defined criteria. The current example
> > + * uniquely identifies the resource by its free function; however,
> > + * alternative custom criteria can be implemented. Refer to
> > + * lib/kunit/platform.c and lib/kunit/static_stub.c for further examples.
> > + */
> > +static bool example_resource_alloc_match(struct kunit *test,
> > + struct kunit_resource *res,
> > + void *match_data)
> > +{
> > + return res->data && res->free == example_resource_free;
> > +}
> > +
> > +/*
> > + * This is an example of a function that provides a description for each of the
> > + * parameters.
> > + */
> > +static void example_param_array_get_desc(const void *p, char *desc)
> > +{
> > + const struct example_param *param = p;
> > +
> > + snprintf(desc, KUNIT_PARAM_DESC_SIZE,
> > + "example check if %d is less than or equal to 3", param->value);
> > +}
> > +
> > +/*
> > + * Initializes the parent kunit struct for parameterized KUnit tests.
> > + * This function enables sharing resources across all parameterized
> > + * tests by adding them to the `parent` kunit test struct. It also supports
> > + * registering either static or dynamic arrays of test parameters.
> > + */
> > +static int example_param_init(struct kunit *test)
> > +{
> > + int ctx = 3; /* Data to be stored. */
> > + int arr_size = ARRAY_SIZE(example_params_array);
> > +
> > + /*
> > + * This allocates a struct kunit_resource, sets its data field to
> > + * ctx, and adds it to the kunit struct's resources list. Note that
> > + * this is test managed so we don't need to have a custom exit function
> > + * to free it.
> > + */
> > + void *data = kunit_alloc_resource(test, example_resource_init, example_resource_free,
> > + GFP_KERNEL, &ctx);
> > +
> > + if (!data)
> > + return -ENOMEM;
> > + /* Pass the static param array information to the parent struct kunit. */
> > + kunit_register_params_array(test, example_params_array, arr_size,
> > + example_param_array_get_desc);
> > + return 0;
> > +}
> > +
> > +/*
> > + * This is an example of a parameterized test that uses shared resources
> > + * available from the struct kunit parent field of the kunit struct.
> > + */
> > +static void example_params_test_with_init(struct kunit *test)
> > +{
> > + int threshold;
> > + struct kunit_resource *res;
> > + const struct example_param *param = test->param_value;
> > +
> > + /* By design, param pointer will not be NULL. */
> > + KUNIT_ASSERT_NOT_NULL(test, param);
> > +
> > + /* Here we access the parent pointer of the test to find the shared resource. */
> > + res = kunit_find_resource(test->parent, example_resource_alloc_match, NULL);
> > +
> > + KUNIT_ASSERT_NOT_NULL(test, res);
> > +
> > + /* Since the data field in kunit_resource is a void pointer we need to typecast it. */
> > + threshold = *((int *)res->data);
> > +
> > + /* Assert that the parameter is less than or equal to a certain threshold. */
> > + KUNIT_ASSERT_LE(test, param->value, threshold);
> > +
> > + /* This decreases the reference count after calling kunit_find_resource(). */
> > + kunit_put_resource(res);
> > +}
> > +
> > /*
> > * Here we make a list of all the test cases we want to add to the test suite
> > * below.
> > @@ -296,6 +406,8 @@ static struct kunit_case example_test_cases[] = {
> > KUNIT_CASE(example_static_stub_using_fn_ptr_test),
> > KUNIT_CASE(example_priv_test),
> > KUNIT_CASE_PARAM(example_params_test, example_gen_params),
> > + KUNIT_CASE_PARAM_WITH_INIT(example_params_test_with_init, NULL,
> > + example_param_init, NULL),
> > KUNIT_CASE_SLOW(example_slow_test),
> > {}
> > };
> > --
> > 2.50.1.552.g942d659e1b-goog
> >
More information about the dri-devel
mailing list