kunit: tool: update riscv QEMU config with new serial dependency
[linux-block.git] / lib / kunit / kunit-test.c
CommitLineData
e4eb117f
BH
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * KUnit test for core test infrastructure.
4 *
5 * Copyright (C) 2019, Google LLC.
6 * Author: Brendan Higgins <brendanhiggins@google.com>
7 */
8#include <kunit/test.h>
9
9bbb11c6
AM
10#include "try-catch-impl.h"
11
e4eb117f
BH
12struct kunit_try_catch_test_context {
13 struct kunit_try_catch *try_catch;
14 bool function_called;
15};
16
17static void kunit_test_successful_try(void *data)
18{
19 struct kunit *test = data;
20 struct kunit_try_catch_test_context *ctx = test->priv;
21
22 ctx->function_called = true;
23}
24
25static void kunit_test_no_catch(void *data)
26{
27 struct kunit *test = data;
28
29 KUNIT_FAIL(test, "Catch should not be called\n");
30}
31
32static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test)
33{
34 struct kunit_try_catch_test_context *ctx = test->priv;
35 struct kunit_try_catch *try_catch = ctx->try_catch;
36
37 kunit_try_catch_init(try_catch,
38 test,
39 kunit_test_successful_try,
40 kunit_test_no_catch);
41 kunit_try_catch_run(try_catch, test);
42
43 KUNIT_EXPECT_TRUE(test, ctx->function_called);
44}
45
46static void kunit_test_unsuccessful_try(void *data)
47{
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;
51
52 kunit_try_catch_throw(try_catch);
53 KUNIT_FAIL(test, "This line should never be reached\n");
54}
55
56static void kunit_test_catch(void *data)
57{
58 struct kunit *test = data;
59 struct kunit_try_catch_test_context *ctx = test->priv;
60
61 ctx->function_called = true;
62}
63
64static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit *test)
65{
66 struct kunit_try_catch_test_context *ctx = test->priv;
67 struct kunit_try_catch *try_catch = ctx->try_catch;
68
69 kunit_try_catch_init(try_catch,
70 test,
71 kunit_test_unsuccessful_try,
72 kunit_test_catch);
73 kunit_try_catch_run(try_catch, test);
74
75 KUNIT_EXPECT_TRUE(test, ctx->function_called);
76}
77
78static int kunit_try_catch_test_init(struct kunit *test)
79{
80 struct kunit_try_catch_test_context *ctx;
81
82 ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
e4aea8f8 83 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
e4eb117f
BH
84 test->priv = ctx;
85
86 ctx->try_catch = kunit_kmalloc(test,
87 sizeof(*ctx->try_catch),
88 GFP_KERNEL);
e4aea8f8 89 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->try_catch);
e4eb117f
BH
90
91 return 0;
92}
93
94static 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),
97 {}
98};
99
100static 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,
104};
73ba5aaf
AK
105
106/*
107 * Context for testing test managed resources
108 * is_resource_initialized is used to test arbitrary resources
109 */
110struct kunit_test_resource_context {
111 struct kunit test;
112 bool is_resource_initialized;
113 int allocate_order[2];
114 int free_order[2];
115};
116
117static int fake_resource_init(struct kunit_resource *res, void *context)
118{
119 struct kunit_test_resource_context *ctx = context;
120
d4cdd146 121 res->data = &ctx->is_resource_initialized;
73ba5aaf
AK
122 ctx->is_resource_initialized = true;
123 return 0;
124}
125
126static void fake_resource_free(struct kunit_resource *res)
127{
d4cdd146 128 bool *is_resource_initialized = res->data;
73ba5aaf
AK
129
130 *is_resource_initialized = false;
131}
132
133static void kunit_resource_test_init_resources(struct kunit *test)
134{
135 struct kunit_test_resource_context *ctx = test->priv;
136
e2219db2 137 kunit_init_test(&ctx->test, "testing_test_init_test", NULL);
73ba5aaf
AK
138
139 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
140}
141
142static void kunit_resource_test_alloc_resource(struct kunit *test)
143{
144 struct kunit_test_resource_context *ctx = test->priv;
145 struct kunit_resource *res;
146 kunit_resource_free_t free = fake_resource_free;
147
148 res = kunit_alloc_and_get_resource(&ctx->test,
149 fake_resource_init,
150 fake_resource_free,
151 GFP_KERNEL,
152 ctx);
153
154 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res);
155 KUNIT_EXPECT_PTR_EQ(test,
156 &ctx->is_resource_initialized,
d4cdd146 157 (bool *)res->data);
73ba5aaf
AK
158 KUNIT_EXPECT_TRUE(test, list_is_last(&res->node, &ctx->test.resources));
159 KUNIT_EXPECT_PTR_EQ(test, free, res->free);
d4cdd146
AM
160
161 kunit_put_resource(res);
73ba5aaf
AK
162}
163
d4cdd146
AM
164/*
165 * Note: tests below use kunit_alloc_and_get_resource(), so as a consequence
166 * they have a reference to the associated resource that they must release
167 * via kunit_put_resource(). In normal operation, users will only
168 * have to do this for cases where they use kunit_find_resource(), and the
169 * kunit_alloc_resource() function will be used (which does not take a
170 * resource reference).
171 */
73ba5aaf
AK
172static void kunit_resource_test_destroy_resource(struct kunit *test)
173{
174 struct kunit_test_resource_context *ctx = test->priv;
175 struct kunit_resource *res = kunit_alloc_and_get_resource(
176 &ctx->test,
177 fake_resource_init,
178 fake_resource_free,
179 GFP_KERNEL,
180 ctx);
181
d4cdd146
AM
182 kunit_put_resource(res);
183
73ba5aaf 184 KUNIT_ASSERT_FALSE(test,
d4cdd146 185 kunit_destroy_resource(&ctx->test,
73ba5aaf 186 kunit_resource_instance_match,
d4cdd146 187 res->data));
73ba5aaf
AK
188
189 KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized);
190 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
191}
192
59729170
DG
193static void kunit_resource_test_remove_resource(struct kunit *test)
194{
195 struct kunit_test_resource_context *ctx = test->priv;
196 struct kunit_resource *res = kunit_alloc_and_get_resource(
197 &ctx->test,
198 fake_resource_init,
199 fake_resource_free,
200 GFP_KERNEL,
201 ctx);
202
203 /* The resource is in the list */
204 KUNIT_EXPECT_FALSE(test, list_empty(&ctx->test.resources));
205
206 /* Remove the resource. The pointer is still valid, but it can't be
207 * found.
208 */
209 kunit_remove_resource(test, res);
210 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
211 /* We haven't been freed yet. */
212 KUNIT_EXPECT_TRUE(test, ctx->is_resource_initialized);
213
214 /* Removing the resource multiple times is valid. */
215 kunit_remove_resource(test, res);
216 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
217 /* Despite having been removed twice (from only one reference), the
218 * resource still has not been freed.
219 */
220 KUNIT_EXPECT_TRUE(test, ctx->is_resource_initialized);
221
222 /* Free the resource. */
223 kunit_put_resource(res);
224 KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized);
225}
226
73ba5aaf
AK
227static void kunit_resource_test_cleanup_resources(struct kunit *test)
228{
229 int i;
230 struct kunit_test_resource_context *ctx = test->priv;
231 struct kunit_resource *resources[5];
232
233 for (i = 0; i < ARRAY_SIZE(resources); i++) {
234 resources[i] = kunit_alloc_and_get_resource(&ctx->test,
235 fake_resource_init,
236 fake_resource_free,
237 GFP_KERNEL,
238 ctx);
d4cdd146 239 kunit_put_resource(resources[i]);
73ba5aaf
AK
240 }
241
242 kunit_cleanup(&ctx->test);
243
244 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
245}
246
247static void kunit_resource_test_mark_order(int order_array[],
248 size_t order_size,
249 int key)
250{
251 int i;
252
253 for (i = 0; i < order_size && order_array[i]; i++)
254 ;
255
256 order_array[i] = key;
257}
258
259#define KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, order_field, key) \
260 kunit_resource_test_mark_order(ctx->order_field, \
261 ARRAY_SIZE(ctx->order_field), \
262 key)
263
264static int fake_resource_2_init(struct kunit_resource *res, void *context)
265{
266 struct kunit_test_resource_context *ctx = context;
267
268 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 2);
269
d4cdd146 270 res->data = ctx;
73ba5aaf
AK
271
272 return 0;
273}
274
275static void fake_resource_2_free(struct kunit_resource *res)
276{
d4cdd146 277 struct kunit_test_resource_context *ctx = res->data;
73ba5aaf
AK
278
279 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 2);
280}
281
282static int fake_resource_1_init(struct kunit_resource *res, void *context)
283{
284 struct kunit_test_resource_context *ctx = context;
d4cdd146 285 struct kunit_resource *res2;
73ba5aaf 286
d4cdd146
AM
287 res2 = kunit_alloc_and_get_resource(&ctx->test,
288 fake_resource_2_init,
289 fake_resource_2_free,
290 GFP_KERNEL,
291 ctx);
73ba5aaf
AK
292
293 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 1);
294
d4cdd146
AM
295 res->data = ctx;
296
297 kunit_put_resource(res2);
73ba5aaf
AK
298
299 return 0;
300}
301
302static void fake_resource_1_free(struct kunit_resource *res)
303{
d4cdd146 304 struct kunit_test_resource_context *ctx = res->data;
73ba5aaf
AK
305
306 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 1);
307}
308
309/*
310 * TODO(brendanhiggins@google.com): replace the arrays that keep track of the
311 * order of allocation and freeing with strict mocks using the IN_SEQUENCE macro
312 * to assert allocation and freeing order when the feature becomes available.
313 */
314static void kunit_resource_test_proper_free_ordering(struct kunit *test)
315{
316 struct kunit_test_resource_context *ctx = test->priv;
d4cdd146 317 struct kunit_resource *res;
73ba5aaf
AK
318
319 /* fake_resource_1 allocates a fake_resource_2 in its init. */
d4cdd146
AM
320 res = kunit_alloc_and_get_resource(&ctx->test,
321 fake_resource_1_init,
322 fake_resource_1_free,
323 GFP_KERNEL,
324 ctx);
73ba5aaf
AK
325
326 /*
327 * Since fake_resource_2_init calls KUNIT_RESOURCE_TEST_MARK_ORDER
328 * before returning to fake_resource_1_init, it should be the first to
329 * put its key in the allocate_order array.
330 */
331 KUNIT_EXPECT_EQ(test, ctx->allocate_order[0], 2);
332 KUNIT_EXPECT_EQ(test, ctx->allocate_order[1], 1);
333
d4cdd146
AM
334 kunit_put_resource(res);
335
73ba5aaf
AK
336 kunit_cleanup(&ctx->test);
337
338 /*
339 * Because fake_resource_2 finishes allocation before fake_resource_1,
340 * fake_resource_1 should be freed first since it could depend on
341 * fake_resource_2.
342 */
343 KUNIT_EXPECT_EQ(test, ctx->free_order[0], 1);
344 KUNIT_EXPECT_EQ(test, ctx->free_order[1], 2);
345}
346
d4cdd146
AM
347static void kunit_resource_test_static(struct kunit *test)
348{
349 struct kunit_test_resource_context ctx;
350 struct kunit_resource res;
351
352 KUNIT_EXPECT_EQ(test, kunit_add_resource(test, NULL, NULL, &res, &ctx),
353 0);
354
355 KUNIT_EXPECT_PTR_EQ(test, res.data, (void *)&ctx);
356
357 kunit_cleanup(test);
358
359 KUNIT_EXPECT_TRUE(test, list_empty(&test->resources));
360}
361
725aca95
AM
362static void kunit_resource_test_named(struct kunit *test)
363{
364 struct kunit_resource res1, res2, *found = NULL;
365 struct kunit_test_resource_context ctx;
366
367 KUNIT_EXPECT_EQ(test,
368 kunit_add_named_resource(test, NULL, NULL, &res1,
369 "resource_1", &ctx),
370 0);
371 KUNIT_EXPECT_PTR_EQ(test, res1.data, (void *)&ctx);
372
373 KUNIT_EXPECT_EQ(test,
374 kunit_add_named_resource(test, NULL, NULL, &res1,
375 "resource_1", &ctx),
376 -EEXIST);
377
378 KUNIT_EXPECT_EQ(test,
379 kunit_add_named_resource(test, NULL, NULL, &res2,
380 "resource_2", &ctx),
381 0);
382
383 found = kunit_find_named_resource(test, "resource_1");
384
385 KUNIT_EXPECT_PTR_EQ(test, found, &res1);
386
387 if (found)
388 kunit_put_resource(&res1);
389
390 KUNIT_EXPECT_EQ(test, kunit_destroy_named_resource(test, "resource_2"),
391 0);
392
393 kunit_cleanup(test);
394
395 KUNIT_EXPECT_TRUE(test, list_empty(&test->resources));
396}
397
73ba5aaf
AK
398static int kunit_resource_test_init(struct kunit *test)
399{
400 struct kunit_test_resource_context *ctx =
401 kzalloc(sizeof(*ctx), GFP_KERNEL);
402
403 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
404
405 test->priv = ctx;
406
e2219db2 407 kunit_init_test(&ctx->test, "test_test_context", NULL);
73ba5aaf
AK
408
409 return 0;
410}
411
412static void kunit_resource_test_exit(struct kunit *test)
413{
414 struct kunit_test_resource_context *ctx = test->priv;
415
416 kunit_cleanup(&ctx->test);
417 kfree(ctx);
418}
419
420static struct kunit_case kunit_resource_test_cases[] = {
421 KUNIT_CASE(kunit_resource_test_init_resources),
422 KUNIT_CASE(kunit_resource_test_alloc_resource),
423 KUNIT_CASE(kunit_resource_test_destroy_resource),
59729170 424 KUNIT_CASE(kunit_resource_test_remove_resource),
73ba5aaf
AK
425 KUNIT_CASE(kunit_resource_test_cleanup_resources),
426 KUNIT_CASE(kunit_resource_test_proper_free_ordering),
d4cdd146 427 KUNIT_CASE(kunit_resource_test_static),
725aca95 428 KUNIT_CASE(kunit_resource_test_named),
73ba5aaf
AK
429 {}
430};
431
432static struct kunit_suite kunit_resource_test_suite = {
433 .name = "kunit-resource-test",
434 .init = kunit_resource_test_init,
435 .exit = kunit_resource_test_exit,
436 .test_cases = kunit_resource_test_cases,
437};
eda8e324
AM
438
439static void kunit_log_test(struct kunit *test);
440
441static struct kunit_case kunit_log_test_cases[] = {
442 KUNIT_CASE(kunit_log_test),
443 {}
444};
445
446static struct kunit_suite kunit_log_test_suite = {
447 .name = "kunit-log-test",
448 .test_cases = kunit_log_test_cases,
449};
450
451static void kunit_log_test(struct kunit *test)
452{
b7cbaef3
DL
453 struct kunit_suite suite;
454
455 suite.log = kunit_kzalloc(test, KUNIT_LOG_SIZE, GFP_KERNEL);
456 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, suite.log);
eda8e324
AM
457
458 kunit_log(KERN_INFO, test, "put this in log.");
459 kunit_log(KERN_INFO, test, "this too.");
b7cbaef3
DL
460 kunit_log(KERN_INFO, &suite, "add to suite log.");
461 kunit_log(KERN_INFO, &suite, "along with this.");
eda8e324
AM
462
463#ifdef CONFIG_KUNIT_DEBUGFS
464 KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
465 strstr(test->log, "put this in log."));
466 KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
467 strstr(test->log, "this too."));
468 KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
b7cbaef3 469 strstr(suite.log, "add to suite log."));
eda8e324 470 KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
b7cbaef3 471 strstr(suite.log, "along with this."));
eda8e324 472#else
de82c15d 473 KUNIT_EXPECT_NULL(test, test->log);
eda8e324
AM
474#endif
475}
476
6d2426b2
DG
477static void kunit_status_set_failure_test(struct kunit *test)
478{
479 struct kunit fake;
480
481 kunit_init_test(&fake, "fake test", NULL);
482
483 KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_SUCCESS);
484 kunit_set_failure(&fake);
485 KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_FAILURE);
486}
487
488static void kunit_status_mark_skipped_test(struct kunit *test)
489{
490 struct kunit fake;
491
492 kunit_init_test(&fake, "fake test", NULL);
493
494 /* Before: Should be SUCCESS with no comment. */
495 KUNIT_EXPECT_EQ(test, fake.status, KUNIT_SUCCESS);
496 KUNIT_EXPECT_STREQ(test, fake.status_comment, "");
497
498 /* Mark the test as skipped. */
499 kunit_mark_skipped(&fake, "Accepts format string: %s", "YES");
500
501 /* After: Should be SKIPPED with our comment. */
502 KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_SKIPPED);
503 KUNIT_EXPECT_STREQ(test, fake.status_comment, "Accepts format string: YES");
504}
505
506static struct kunit_case kunit_status_test_cases[] = {
507 KUNIT_CASE(kunit_status_set_failure_test),
508 KUNIT_CASE(kunit_status_mark_skipped_test),
509 {}
510};
511
512static struct kunit_suite kunit_status_test_suite = {
513 .name = "kunit_status",
514 .test_cases = kunit_status_test_cases,
515};
516
eda8e324 517kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite,
6d2426b2 518 &kunit_log_test_suite, &kunit_status_test_suite);
c475c77d
AM
519
520MODULE_LICENSE("GPL v2");