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