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 #include "try-catch-impl.h"
12 struct kunit_try_catch_test_context {
13 struct kunit_try_catch *try_catch;
17 static void kunit_test_successful_try(void *data)
19 struct kunit *test = data;
20 struct kunit_try_catch_test_context *ctx = test->priv;
22 ctx->function_called = true;
25 static void kunit_test_no_catch(void *data)
27 struct kunit *test = data;
29 KUNIT_FAIL(test, "Catch should not be called\n");
32 static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test)
34 struct kunit_try_catch_test_context *ctx = test->priv;
35 struct kunit_try_catch *try_catch = ctx->try_catch;
37 kunit_try_catch_init(try_catch,
39 kunit_test_successful_try,
41 kunit_try_catch_run(try_catch, test);
43 KUNIT_EXPECT_TRUE(test, ctx->function_called);
46 static void kunit_test_unsuccessful_try(void *data)
48 struct kunit *test = data;
49 struct kunit_try_catch_test_context *ctx = test->priv;
50 struct kunit_try_catch *try_catch = ctx->try_catch;
52 kunit_try_catch_throw(try_catch);
53 KUNIT_FAIL(test, "This line should never be reached\n");
56 static void kunit_test_catch(void *data)
58 struct kunit *test = data;
59 struct kunit_try_catch_test_context *ctx = test->priv;
61 ctx->function_called = true;
64 static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit *test)
66 struct kunit_try_catch_test_context *ctx = test->priv;
67 struct kunit_try_catch *try_catch = ctx->try_catch;
69 kunit_try_catch_init(try_catch,
71 kunit_test_unsuccessful_try,
73 kunit_try_catch_run(try_catch, test);
75 KUNIT_EXPECT_TRUE(test, ctx->function_called);
78 static int kunit_try_catch_test_init(struct kunit *test)
80 struct kunit_try_catch_test_context *ctx;
82 ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
83 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
86 ctx->try_catch = kunit_kmalloc(test,
87 sizeof(*ctx->try_catch),
89 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->try_catch);
94 static struct kunit_case kunit_try_catch_test_cases[] = {
95 KUNIT_CASE(kunit_test_try_catch_successful_try_no_catch),
96 KUNIT_CASE(kunit_test_try_catch_unsuccessful_try_does_catch),
100 static struct kunit_suite kunit_try_catch_test_suite = {
101 .name = "kunit-try-catch-test",
102 .init = kunit_try_catch_test_init,
103 .test_cases = kunit_try_catch_test_cases,
105 kunit_test_suite(kunit_try_catch_test_suite);
108 * Context for testing test managed resources
109 * is_resource_initialized is used to test arbitrary resources
111 struct kunit_test_resource_context {
113 bool is_resource_initialized;
114 int allocate_order[2];
118 static int fake_resource_init(struct kunit_resource *res, void *context)
120 struct kunit_test_resource_context *ctx = context;
122 res->allocation = &ctx->is_resource_initialized;
123 ctx->is_resource_initialized = true;
127 static void fake_resource_free(struct kunit_resource *res)
129 bool *is_resource_initialized = res->allocation;
131 *is_resource_initialized = false;
134 static void kunit_resource_test_init_resources(struct kunit *test)
136 struct kunit_test_resource_context *ctx = test->priv;
138 kunit_init_test(&ctx->test, "testing_test_init_test");
140 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
143 static void kunit_resource_test_alloc_resource(struct kunit *test)
145 struct kunit_test_resource_context *ctx = test->priv;
146 struct kunit_resource *res;
147 kunit_resource_free_t free = fake_resource_free;
149 res = kunit_alloc_and_get_resource(&ctx->test,
155 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res);
156 KUNIT_EXPECT_PTR_EQ(test,
157 &ctx->is_resource_initialized,
158 (bool *) res->allocation);
159 KUNIT_EXPECT_TRUE(test, list_is_last(&res->node, &ctx->test.resources));
160 KUNIT_EXPECT_PTR_EQ(test, free, res->free);
163 static void kunit_resource_test_destroy_resource(struct kunit *test)
165 struct kunit_test_resource_context *ctx = test->priv;
166 struct kunit_resource *res = kunit_alloc_and_get_resource(
173 KUNIT_ASSERT_FALSE(test,
174 kunit_resource_destroy(&ctx->test,
175 kunit_resource_instance_match,
179 KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized);
180 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
183 static void kunit_resource_test_cleanup_resources(struct kunit *test)
186 struct kunit_test_resource_context *ctx = test->priv;
187 struct kunit_resource *resources[5];
189 for (i = 0; i < ARRAY_SIZE(resources); i++) {
190 resources[i] = kunit_alloc_and_get_resource(&ctx->test,
197 kunit_cleanup(&ctx->test);
199 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
202 static void kunit_resource_test_mark_order(int order_array[],
208 for (i = 0; i < order_size && order_array[i]; i++)
211 order_array[i] = key;
214 #define KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, order_field, key) \
215 kunit_resource_test_mark_order(ctx->order_field, \
216 ARRAY_SIZE(ctx->order_field), \
219 static int fake_resource_2_init(struct kunit_resource *res, void *context)
221 struct kunit_test_resource_context *ctx = context;
223 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 2);
225 res->allocation = ctx;
230 static void fake_resource_2_free(struct kunit_resource *res)
232 struct kunit_test_resource_context *ctx = res->allocation;
234 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 2);
237 static int fake_resource_1_init(struct kunit_resource *res, void *context)
239 struct kunit_test_resource_context *ctx = context;
241 kunit_alloc_and_get_resource(&ctx->test,
242 fake_resource_2_init,
243 fake_resource_2_free,
247 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 1);
249 res->allocation = ctx;
254 static void fake_resource_1_free(struct kunit_resource *res)
256 struct kunit_test_resource_context *ctx = res->allocation;
258 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 1);
262 * TODO(brendanhiggins@google.com): replace the arrays that keep track of the
263 * order of allocation and freeing with strict mocks using the IN_SEQUENCE macro
264 * to assert allocation and freeing order when the feature becomes available.
266 static void kunit_resource_test_proper_free_ordering(struct kunit *test)
268 struct kunit_test_resource_context *ctx = test->priv;
270 /* fake_resource_1 allocates a fake_resource_2 in its init. */
271 kunit_alloc_and_get_resource(&ctx->test,
272 fake_resource_1_init,
273 fake_resource_1_free,
278 * Since fake_resource_2_init calls KUNIT_RESOURCE_TEST_MARK_ORDER
279 * before returning to fake_resource_1_init, it should be the first to
280 * put its key in the allocate_order array.
282 KUNIT_EXPECT_EQ(test, ctx->allocate_order[0], 2);
283 KUNIT_EXPECT_EQ(test, ctx->allocate_order[1], 1);
285 kunit_cleanup(&ctx->test);
288 * Because fake_resource_2 finishes allocation before fake_resource_1,
289 * fake_resource_1 should be freed first since it could depend on
292 KUNIT_EXPECT_EQ(test, ctx->free_order[0], 1);
293 KUNIT_EXPECT_EQ(test, ctx->free_order[1], 2);
296 static int kunit_resource_test_init(struct kunit *test)
298 struct kunit_test_resource_context *ctx =
299 kzalloc(sizeof(*ctx), GFP_KERNEL);
301 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
305 kunit_init_test(&ctx->test, "test_test_context");
310 static void kunit_resource_test_exit(struct kunit *test)
312 struct kunit_test_resource_context *ctx = test->priv;
314 kunit_cleanup(&ctx->test);
318 static struct kunit_case kunit_resource_test_cases[] = {
319 KUNIT_CASE(kunit_resource_test_init_resources),
320 KUNIT_CASE(kunit_resource_test_alloc_resource),
321 KUNIT_CASE(kunit_resource_test_destroy_resource),
322 KUNIT_CASE(kunit_resource_test_cleanup_resources),
323 KUNIT_CASE(kunit_resource_test_proper_free_ordering),
327 static struct kunit_suite kunit_resource_test_suite = {
328 .name = "kunit-resource-test",
329 .init = kunit_resource_test_init,
330 .exit = kunit_resource_test_exit,
331 .test_cases = kunit_resource_test_cases,
333 kunit_test_suite(kunit_resource_test_suite);