1 // SPDX-License-Identifier: GPL-2.0
3 * KUnit test for core test infrastructure.
5 * Copyright (C) 2019, Google LLC.
6 * Author: Brendan Higgins <brendanhiggins@google.com>
8 #include <kunit/test.h>
10 struct kunit_try_catch_test_context {
11 struct kunit_try_catch *try_catch;
15 static void kunit_test_successful_try(void *data)
17 struct kunit *test = data;
18 struct kunit_try_catch_test_context *ctx = test->priv;
20 ctx->function_called = true;
23 static void kunit_test_no_catch(void *data)
25 struct kunit *test = data;
27 KUNIT_FAIL(test, "Catch should not be called\n");
30 static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test)
32 struct kunit_try_catch_test_context *ctx = test->priv;
33 struct kunit_try_catch *try_catch = ctx->try_catch;
35 kunit_try_catch_init(try_catch,
37 kunit_test_successful_try,
39 kunit_try_catch_run(try_catch, test);
41 KUNIT_EXPECT_TRUE(test, ctx->function_called);
44 static void kunit_test_unsuccessful_try(void *data)
46 struct kunit *test = data;
47 struct kunit_try_catch_test_context *ctx = test->priv;
48 struct kunit_try_catch *try_catch = ctx->try_catch;
50 kunit_try_catch_throw(try_catch);
51 KUNIT_FAIL(test, "This line should never be reached\n");
54 static void kunit_test_catch(void *data)
56 struct kunit *test = data;
57 struct kunit_try_catch_test_context *ctx = test->priv;
59 ctx->function_called = true;
62 static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit *test)
64 struct kunit_try_catch_test_context *ctx = test->priv;
65 struct kunit_try_catch *try_catch = ctx->try_catch;
67 kunit_try_catch_init(try_catch,
69 kunit_test_unsuccessful_try,
71 kunit_try_catch_run(try_catch, test);
73 KUNIT_EXPECT_TRUE(test, ctx->function_called);
76 static int kunit_try_catch_test_init(struct kunit *test)
78 struct kunit_try_catch_test_context *ctx;
80 ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
81 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
84 ctx->try_catch = kunit_kmalloc(test,
85 sizeof(*ctx->try_catch),
87 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->try_catch);
92 static struct kunit_case kunit_try_catch_test_cases[] = {
93 KUNIT_CASE(kunit_test_try_catch_successful_try_no_catch),
94 KUNIT_CASE(kunit_test_try_catch_unsuccessful_try_does_catch),
98 static struct kunit_suite kunit_try_catch_test_suite = {
99 .name = "kunit-try-catch-test",
100 .init = kunit_try_catch_test_init,
101 .test_cases = kunit_try_catch_test_cases,
103 kunit_test_suite(kunit_try_catch_test_suite);
106 * Context for testing test managed resources
107 * is_resource_initialized is used to test arbitrary resources
109 struct kunit_test_resource_context {
111 bool is_resource_initialized;
112 int allocate_order[2];
116 static int fake_resource_init(struct kunit_resource *res, void *context)
118 struct kunit_test_resource_context *ctx = context;
120 res->allocation = &ctx->is_resource_initialized;
121 ctx->is_resource_initialized = true;
125 static void fake_resource_free(struct kunit_resource *res)
127 bool *is_resource_initialized = res->allocation;
129 *is_resource_initialized = false;
132 static void kunit_resource_test_init_resources(struct kunit *test)
134 struct kunit_test_resource_context *ctx = test->priv;
136 kunit_init_test(&ctx->test, "testing_test_init_test");
138 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
141 static void kunit_resource_test_alloc_resource(struct kunit *test)
143 struct kunit_test_resource_context *ctx = test->priv;
144 struct kunit_resource *res;
145 kunit_resource_free_t free = fake_resource_free;
147 res = kunit_alloc_and_get_resource(&ctx->test,
153 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res);
154 KUNIT_EXPECT_PTR_EQ(test,
155 &ctx->is_resource_initialized,
156 (bool *) res->allocation);
157 KUNIT_EXPECT_TRUE(test, list_is_last(&res->node, &ctx->test.resources));
158 KUNIT_EXPECT_PTR_EQ(test, free, res->free);
161 static void kunit_resource_test_destroy_resource(struct kunit *test)
163 struct kunit_test_resource_context *ctx = test->priv;
164 struct kunit_resource *res = kunit_alloc_and_get_resource(
171 KUNIT_ASSERT_FALSE(test,
172 kunit_resource_destroy(&ctx->test,
173 kunit_resource_instance_match,
177 KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized);
178 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
181 static void kunit_resource_test_cleanup_resources(struct kunit *test)
184 struct kunit_test_resource_context *ctx = test->priv;
185 struct kunit_resource *resources[5];
187 for (i = 0; i < ARRAY_SIZE(resources); i++) {
188 resources[i] = kunit_alloc_and_get_resource(&ctx->test,
195 kunit_cleanup(&ctx->test);
197 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
200 static void kunit_resource_test_mark_order(int order_array[],
206 for (i = 0; i < order_size && order_array[i]; i++)
209 order_array[i] = key;
212 #define KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, order_field, key) \
213 kunit_resource_test_mark_order(ctx->order_field, \
214 ARRAY_SIZE(ctx->order_field), \
217 static int fake_resource_2_init(struct kunit_resource *res, void *context)
219 struct kunit_test_resource_context *ctx = context;
221 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 2);
223 res->allocation = ctx;
228 static void fake_resource_2_free(struct kunit_resource *res)
230 struct kunit_test_resource_context *ctx = res->allocation;
232 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 2);
235 static int fake_resource_1_init(struct kunit_resource *res, void *context)
237 struct kunit_test_resource_context *ctx = context;
239 kunit_alloc_and_get_resource(&ctx->test,
240 fake_resource_2_init,
241 fake_resource_2_free,
245 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 1);
247 res->allocation = ctx;
252 static void fake_resource_1_free(struct kunit_resource *res)
254 struct kunit_test_resource_context *ctx = res->allocation;
256 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 1);
260 * TODO(brendanhiggins@google.com): replace the arrays that keep track of the
261 * order of allocation and freeing with strict mocks using the IN_SEQUENCE macro
262 * to assert allocation and freeing order when the feature becomes available.
264 static void kunit_resource_test_proper_free_ordering(struct kunit *test)
266 struct kunit_test_resource_context *ctx = test->priv;
268 /* fake_resource_1 allocates a fake_resource_2 in its init. */
269 kunit_alloc_and_get_resource(&ctx->test,
270 fake_resource_1_init,
271 fake_resource_1_free,
276 * Since fake_resource_2_init calls KUNIT_RESOURCE_TEST_MARK_ORDER
277 * before returning to fake_resource_1_init, it should be the first to
278 * put its key in the allocate_order array.
280 KUNIT_EXPECT_EQ(test, ctx->allocate_order[0], 2);
281 KUNIT_EXPECT_EQ(test, ctx->allocate_order[1], 1);
283 kunit_cleanup(&ctx->test);
286 * Because fake_resource_2 finishes allocation before fake_resource_1,
287 * fake_resource_1 should be freed first since it could depend on
290 KUNIT_EXPECT_EQ(test, ctx->free_order[0], 1);
291 KUNIT_EXPECT_EQ(test, ctx->free_order[1], 2);
294 static int kunit_resource_test_init(struct kunit *test)
296 struct kunit_test_resource_context *ctx =
297 kzalloc(sizeof(*ctx), GFP_KERNEL);
299 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
303 kunit_init_test(&ctx->test, "test_test_context");
308 static void kunit_resource_test_exit(struct kunit *test)
310 struct kunit_test_resource_context *ctx = test->priv;
312 kunit_cleanup(&ctx->test);
316 static struct kunit_case kunit_resource_test_cases[] = {
317 KUNIT_CASE(kunit_resource_test_init_resources),
318 KUNIT_CASE(kunit_resource_test_alloc_resource),
319 KUNIT_CASE(kunit_resource_test_destroy_resource),
320 KUNIT_CASE(kunit_resource_test_cleanup_resources),
321 KUNIT_CASE(kunit_resource_test_proper_free_ordering),
325 static struct kunit_suite kunit_resource_test_suite = {
326 .name = "kunit-resource-test",
327 .init = kunit_resource_test_init,
328 .exit = kunit_resource_test_exit,
329 .test_cases = kunit_resource_test_cases,
331 kunit_test_suite(kunit_resource_test_suite);