Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Base unit test (KUnit) API.
4 *
5 * Copyright (C) 2019, Google LLC.
6 * Author: Brendan Higgins <brendanhiggins@google.com>
7 */
8
9#include <kunit/resource.h>
10#include <kunit/test.h>
11#include <kunit/test-bug.h>
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/panic.h>
16#include <linux/sched/debug.h>
17#include <linux/sched.h>
18
19#include "debugfs.h"
20#include "hooks-impl.h"
21#include "string-stream.h"
22#include "try-catch-impl.h"
23
24/*
25 * Hook to fail the current test and print an error message to the log.
26 */
27void __printf(3, 4) __kunit_fail_current_test_impl(const char *file, int line, const char *fmt, ...)
28{
29 va_list args;
30 int len;
31 char *buffer;
32
33 if (!current->kunit_test)
34 return;
35
36 kunit_set_failure(current->kunit_test);
37
38 /* kunit_err() only accepts literals, so evaluate the args first. */
39 va_start(args, fmt);
40 len = vsnprintf(NULL, 0, fmt, args) + 1;
41 va_end(args);
42
43 buffer = kunit_kmalloc(current->kunit_test, len, GFP_KERNEL);
44 if (!buffer)
45 return;
46
47 va_start(args, fmt);
48 vsnprintf(buffer, len, fmt, args);
49 va_end(args);
50
51 kunit_err(current->kunit_test, "%s:%d: %s", file, line, buffer);
52 kunit_kfree(current->kunit_test, buffer);
53}
54
55/*
56 * Enable KUnit tests to run.
57 */
58#ifdef CONFIG_KUNIT_DEFAULT_ENABLED
59static bool enable_param = true;
60#else
61static bool enable_param;
62#endif
63module_param_named(enable, enable_param, bool, 0);
64MODULE_PARM_DESC(enable, "Enable KUnit tests");
65
66/*
67 * KUnit statistic mode:
68 * 0 - disabled
69 * 1 - only when there is more than one subtest
70 * 2 - enabled
71 */
72static int kunit_stats_enabled = 1;
73module_param_named(stats_enabled, kunit_stats_enabled, int, 0644);
74MODULE_PARM_DESC(stats_enabled,
75 "Print test stats: never (0), only for multiple subtests (1), or always (2)");
76
77struct kunit_result_stats {
78 unsigned long passed;
79 unsigned long skipped;
80 unsigned long failed;
81 unsigned long total;
82};
83
84static bool kunit_should_print_stats(struct kunit_result_stats stats)
85{
86 if (kunit_stats_enabled == 0)
87 return false;
88
89 if (kunit_stats_enabled == 2)
90 return true;
91
92 return (stats.total > 1);
93}
94
95static void kunit_print_test_stats(struct kunit *test,
96 struct kunit_result_stats stats)
97{
98 if (!kunit_should_print_stats(stats))
99 return;
100
101 kunit_log(KERN_INFO, test,
102 KUNIT_SUBTEST_INDENT
103 "# %s: pass:%lu fail:%lu skip:%lu total:%lu",
104 test->name,
105 stats.passed,
106 stats.failed,
107 stats.skipped,
108 stats.total);
109}
110
111/*
112 * Append formatted message to log, size of which is limited to
113 * KUNIT_LOG_SIZE bytes (including null terminating byte).
114 */
115void kunit_log_append(char *log, const char *fmt, ...)
116{
117 char line[KUNIT_LOG_SIZE];
118 va_list args;
119 int len_left;
120
121 if (!log)
122 return;
123
124 len_left = KUNIT_LOG_SIZE - strlen(log) - 1;
125 if (len_left <= 0)
126 return;
127
128 va_start(args, fmt);
129 vsnprintf(line, sizeof(line), fmt, args);
130 va_end(args);
131
132 strncat(log, line, len_left);
133}
134EXPORT_SYMBOL_GPL(kunit_log_append);
135
136size_t kunit_suite_num_test_cases(struct kunit_suite *suite)
137{
138 struct kunit_case *test_case;
139 size_t len = 0;
140
141 kunit_suite_for_each_test_case(suite, test_case)
142 len++;
143
144 return len;
145}
146EXPORT_SYMBOL_GPL(kunit_suite_num_test_cases);
147
148static void kunit_print_suite_start(struct kunit_suite *suite)
149{
150 kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "KTAP version 1\n");
151 kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "# Subtest: %s",
152 suite->name);
153 kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "1..%zd",
154 kunit_suite_num_test_cases(suite));
155}
156
157static void kunit_print_ok_not_ok(void *test_or_suite,
158 bool is_test,
159 enum kunit_status status,
160 size_t test_number,
161 const char *description,
162 const char *directive)
163{
164 struct kunit_suite *suite = is_test ? NULL : test_or_suite;
165 struct kunit *test = is_test ? test_or_suite : NULL;
166 const char *directive_header = (status == KUNIT_SKIPPED) ? " # SKIP " : "";
167
168 /*
169 * We do not log the test suite results as doing so would
170 * mean debugfs display would consist of the test suite
171 * description and status prior to individual test results.
172 * Hence directly printk the suite status, and we will
173 * separately seq_printf() the suite status for the debugfs
174 * representation.
175 */
176 if (suite)
177 pr_info("%s %zd %s%s%s\n",
178 kunit_status_to_ok_not_ok(status),
179 test_number, description, directive_header,
180 (status == KUNIT_SKIPPED) ? directive : "");
181 else
182 kunit_log(KERN_INFO, test,
183 KUNIT_SUBTEST_INDENT "%s %zd %s%s%s",
184 kunit_status_to_ok_not_ok(status),
185 test_number, description, directive_header,
186 (status == KUNIT_SKIPPED) ? directive : "");
187}
188
189enum kunit_status kunit_suite_has_succeeded(struct kunit_suite *suite)
190{
191 const struct kunit_case *test_case;
192 enum kunit_status status = KUNIT_SKIPPED;
193
194 if (suite->suite_init_err)
195 return KUNIT_FAILURE;
196
197 kunit_suite_for_each_test_case(suite, test_case) {
198 if (test_case->status == KUNIT_FAILURE)
199 return KUNIT_FAILURE;
200 else if (test_case->status == KUNIT_SUCCESS)
201 status = KUNIT_SUCCESS;
202 }
203
204 return status;
205}
206EXPORT_SYMBOL_GPL(kunit_suite_has_succeeded);
207
208static size_t kunit_suite_counter = 1;
209
210static void kunit_print_suite_end(struct kunit_suite *suite)
211{
212 kunit_print_ok_not_ok((void *)suite, false,
213 kunit_suite_has_succeeded(suite),
214 kunit_suite_counter++,
215 suite->name,
216 suite->status_comment);
217}
218
219unsigned int kunit_test_case_num(struct kunit_suite *suite,
220 struct kunit_case *test_case)
221{
222 struct kunit_case *tc;
223 unsigned int i = 1;
224
225 kunit_suite_for_each_test_case(suite, tc) {
226 if (tc == test_case)
227 return i;
228 i++;
229 }
230
231 return 0;
232}
233EXPORT_SYMBOL_GPL(kunit_test_case_num);
234
235static void kunit_print_string_stream(struct kunit *test,
236 struct string_stream *stream)
237{
238 struct string_stream_fragment *fragment;
239 char *buf;
240
241 if (string_stream_is_empty(stream))
242 return;
243
244 buf = string_stream_get_string(stream);
245 if (!buf) {
246 kunit_err(test,
247 "Could not allocate buffer, dumping stream:\n");
248 list_for_each_entry(fragment, &stream->fragments, node) {
249 kunit_err(test, "%s", fragment->fragment);
250 }
251 kunit_err(test, "\n");
252 } else {
253 kunit_err(test, "%s", buf);
254 kunit_kfree(test, buf);
255 }
256}
257
258static void kunit_fail(struct kunit *test, const struct kunit_loc *loc,
259 enum kunit_assert_type type, const struct kunit_assert *assert,
260 assert_format_t assert_format, const struct va_format *message)
261{
262 struct string_stream *stream;
263
264 kunit_set_failure(test);
265
266 stream = alloc_string_stream(test, GFP_KERNEL);
267 if (IS_ERR(stream)) {
268 WARN(true,
269 "Could not allocate stream to print failed assertion in %s:%d\n",
270 loc->file,
271 loc->line);
272 return;
273 }
274
275 kunit_assert_prologue(loc, type, stream);
276 assert_format(assert, message, stream);
277
278 kunit_print_string_stream(test, stream);
279
280 string_stream_destroy(stream);
281}
282
283static void __noreturn kunit_abort(struct kunit *test)
284{
285 kunit_try_catch_throw(&test->try_catch); /* Does not return. */
286
287 /*
288 * Throw could not abort from test.
289 *
290 * XXX: we should never reach this line! As kunit_try_catch_throw is
291 * marked __noreturn.
292 */
293 WARN_ONCE(true, "Throw could not abort from test!\n");
294}
295
296void kunit_do_failed_assertion(struct kunit *test,
297 const struct kunit_loc *loc,
298 enum kunit_assert_type type,
299 const struct kunit_assert *assert,
300 assert_format_t assert_format,
301 const char *fmt, ...)
302{
303 va_list args;
304 struct va_format message;
305 va_start(args, fmt);
306
307 message.fmt = fmt;
308 message.va = &args;
309
310 kunit_fail(test, loc, type, assert, assert_format, &message);
311
312 va_end(args);
313
314 if (type == KUNIT_ASSERTION)
315 kunit_abort(test);
316}
317EXPORT_SYMBOL_GPL(kunit_do_failed_assertion);
318
319void kunit_init_test(struct kunit *test, const char *name, char *log)
320{
321 spin_lock_init(&test->lock);
322 INIT_LIST_HEAD(&test->resources);
323 test->name = name;
324 test->log = log;
325 if (test->log)
326 test->log[0] = '\0';
327 test->status = KUNIT_SUCCESS;
328 test->status_comment[0] = '\0';
329}
330EXPORT_SYMBOL_GPL(kunit_init_test);
331
332/*
333 * Initializes and runs test case. Does not clean up or do post validations.
334 */
335static void kunit_run_case_internal(struct kunit *test,
336 struct kunit_suite *suite,
337 struct kunit_case *test_case)
338{
339 if (suite->init) {
340 int ret;
341
342 ret = suite->init(test);
343 if (ret) {
344 kunit_err(test, "failed to initialize: %d\n", ret);
345 kunit_set_failure(test);
346 return;
347 }
348 }
349
350 test_case->run_case(test);
351}
352
353static void kunit_case_internal_cleanup(struct kunit *test)
354{
355 kunit_cleanup(test);
356}
357
358/*
359 * Performs post validations and cleanup after a test case was run.
360 * XXX: Should ONLY BE CALLED AFTER kunit_run_case_internal!
361 */
362static void kunit_run_case_cleanup(struct kunit *test,
363 struct kunit_suite *suite)
364{
365 if (suite->exit)
366 suite->exit(test);
367
368 kunit_case_internal_cleanup(test);
369}
370
371struct kunit_try_catch_context {
372 struct kunit *test;
373 struct kunit_suite *suite;
374 struct kunit_case *test_case;
375};
376
377static void kunit_try_run_case(void *data)
378{
379 struct kunit_try_catch_context *ctx = data;
380 struct kunit *test = ctx->test;
381 struct kunit_suite *suite = ctx->suite;
382 struct kunit_case *test_case = ctx->test_case;
383
384 current->kunit_test = test;
385
386 /*
387 * kunit_run_case_internal may encounter a fatal error; if it does,
388 * abort will be called, this thread will exit, and finally the parent
389 * thread will resume control and handle any necessary clean up.
390 */
391 kunit_run_case_internal(test, suite, test_case);
392 /* This line may never be reached. */
393 kunit_run_case_cleanup(test, suite);
394}
395
396static void kunit_catch_run_case(void *data)
397{
398 struct kunit_try_catch_context *ctx = data;
399 struct kunit *test = ctx->test;
400 struct kunit_suite *suite = ctx->suite;
401 int try_exit_code = kunit_try_catch_get_result(&test->try_catch);
402
403 if (try_exit_code) {
404 kunit_set_failure(test);
405 /*
406 * Test case could not finish, we have no idea what state it is
407 * in, so don't do clean up.
408 */
409 if (try_exit_code == -ETIMEDOUT) {
410 kunit_err(test, "test case timed out\n");
411 /*
412 * Unknown internal error occurred preventing test case from
413 * running, so there is nothing to clean up.
414 */
415 } else {
416 kunit_err(test, "internal error occurred preventing test case from running: %d\n",
417 try_exit_code);
418 }
419 return;
420 }
421
422 /*
423 * Test case was run, but aborted. It is the test case's business as to
424 * whether it failed or not, we just need to clean up.
425 */
426 kunit_run_case_cleanup(test, suite);
427}
428
429/*
430 * Performs all logic to run a test case. It also catches most errors that
431 * occur in a test case and reports them as failures.
432 */
433static void kunit_run_case_catch_errors(struct kunit_suite *suite,
434 struct kunit_case *test_case,
435 struct kunit *test)
436{
437 struct kunit_try_catch_context context;
438 struct kunit_try_catch *try_catch;
439
440 kunit_init_test(test, test_case->name, test_case->log);
441 try_catch = &test->try_catch;
442
443 kunit_try_catch_init(try_catch,
444 test,
445 kunit_try_run_case,
446 kunit_catch_run_case);
447 context.test = test;
448 context.suite = suite;
449 context.test_case = test_case;
450 kunit_try_catch_run(try_catch, &context);
451
452 /* Propagate the parameter result to the test case. */
453 if (test->status == KUNIT_FAILURE)
454 test_case->status = KUNIT_FAILURE;
455 else if (test_case->status != KUNIT_FAILURE && test->status == KUNIT_SUCCESS)
456 test_case->status = KUNIT_SUCCESS;
457}
458
459static void kunit_print_suite_stats(struct kunit_suite *suite,
460 struct kunit_result_stats suite_stats,
461 struct kunit_result_stats param_stats)
462{
463 if (kunit_should_print_stats(suite_stats)) {
464 kunit_log(KERN_INFO, suite,
465 "# %s: pass:%lu fail:%lu skip:%lu total:%lu",
466 suite->name,
467 suite_stats.passed,
468 suite_stats.failed,
469 suite_stats.skipped,
470 suite_stats.total);
471 }
472
473 if (kunit_should_print_stats(param_stats)) {
474 kunit_log(KERN_INFO, suite,
475 "# Totals: pass:%lu fail:%lu skip:%lu total:%lu",
476 param_stats.passed,
477 param_stats.failed,
478 param_stats.skipped,
479 param_stats.total);
480 }
481}
482
483static void kunit_update_stats(struct kunit_result_stats *stats,
484 enum kunit_status status)
485{
486 switch (status) {
487 case KUNIT_SUCCESS:
488 stats->passed++;
489 break;
490 case KUNIT_SKIPPED:
491 stats->skipped++;
492 break;
493 case KUNIT_FAILURE:
494 stats->failed++;
495 break;
496 }
497
498 stats->total++;
499}
500
501static void kunit_accumulate_stats(struct kunit_result_stats *total,
502 struct kunit_result_stats add)
503{
504 total->passed += add.passed;
505 total->skipped += add.skipped;
506 total->failed += add.failed;
507 total->total += add.total;
508}
509
510int kunit_run_tests(struct kunit_suite *suite)
511{
512 char param_desc[KUNIT_PARAM_DESC_SIZE];
513 struct kunit_case *test_case;
514 struct kunit_result_stats suite_stats = { 0 };
515 struct kunit_result_stats total_stats = { 0 };
516
517 /* Taint the kernel so we know we've run tests. */
518 add_taint(TAINT_TEST, LOCKDEP_STILL_OK);
519
520 if (suite->suite_init) {
521 suite->suite_init_err = suite->suite_init(suite);
522 if (suite->suite_init_err) {
523 kunit_err(suite, KUNIT_SUBTEST_INDENT
524 "# failed to initialize (%d)", suite->suite_init_err);
525 goto suite_end;
526 }
527 }
528
529 kunit_print_suite_start(suite);
530
531 kunit_suite_for_each_test_case(suite, test_case) {
532 struct kunit test = { .param_value = NULL, .param_index = 0 };
533 struct kunit_result_stats param_stats = { 0 };
534 test_case->status = KUNIT_SKIPPED;
535
536 if (!test_case->generate_params) {
537 /* Non-parameterised test. */
538 kunit_run_case_catch_errors(suite, test_case, &test);
539 kunit_update_stats(¶m_stats, test.status);
540 } else {
541 /* Get initial param. */
542 param_desc[0] = '\0';
543 test.param_value = test_case->generate_params(NULL, param_desc);
544 kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT
545 "KTAP version 1\n");
546 kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT
547 "# Subtest: %s", test_case->name);
548
549 while (test.param_value) {
550 kunit_run_case_catch_errors(suite, test_case, &test);
551
552 if (param_desc[0] == '\0') {
553 snprintf(param_desc, sizeof(param_desc),
554 "param-%d", test.param_index);
555 }
556
557 kunit_log(KERN_INFO, &test,
558 KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT
559 "%s %d %s",
560 kunit_status_to_ok_not_ok(test.status),
561 test.param_index + 1, param_desc);
562
563 /* Get next param. */
564 param_desc[0] = '\0';
565 test.param_value = test_case->generate_params(test.param_value, param_desc);
566 test.param_index++;
567
568 kunit_update_stats(¶m_stats, test.status);
569 }
570 }
571
572
573 kunit_print_test_stats(&test, param_stats);
574
575 kunit_print_ok_not_ok(&test, true, test_case->status,
576 kunit_test_case_num(suite, test_case),
577 test_case->name,
578 test.status_comment);
579
580 kunit_update_stats(&suite_stats, test_case->status);
581 kunit_accumulate_stats(&total_stats, param_stats);
582 }
583
584 if (suite->suite_exit)
585 suite->suite_exit(suite);
586
587 kunit_print_suite_stats(suite, suite_stats, total_stats);
588suite_end:
589 kunit_print_suite_end(suite);
590
591 return 0;
592}
593EXPORT_SYMBOL_GPL(kunit_run_tests);
594
595static void kunit_init_suite(struct kunit_suite *suite)
596{
597 kunit_debugfs_create_suite(suite);
598 suite->status_comment[0] = '\0';
599 suite->suite_init_err = 0;
600}
601
602bool kunit_enabled(void)
603{
604 return enable_param;
605}
606
607int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_suites)
608{
609 unsigned int i;
610
611 if (!kunit_enabled() && num_suites > 0) {
612 pr_info("kunit: disabled\n");
613 return 0;
614 }
615
616 static_branch_inc(&kunit_running);
617
618 for (i = 0; i < num_suites; i++) {
619 kunit_init_suite(suites[i]);
620 kunit_run_tests(suites[i]);
621 }
622
623 static_branch_dec(&kunit_running);
624 return 0;
625}
626EXPORT_SYMBOL_GPL(__kunit_test_suites_init);
627
628static void kunit_exit_suite(struct kunit_suite *suite)
629{
630 kunit_debugfs_destroy_suite(suite);
631}
632
633void __kunit_test_suites_exit(struct kunit_suite **suites, int num_suites)
634{
635 unsigned int i;
636
637 if (!kunit_enabled())
638 return;
639
640 for (i = 0; i < num_suites; i++)
641 kunit_exit_suite(suites[i]);
642
643 kunit_suite_counter = 1;
644}
645EXPORT_SYMBOL_GPL(__kunit_test_suites_exit);
646
647#ifdef CONFIG_MODULES
648static void kunit_module_init(struct module *mod)
649{
650 __kunit_test_suites_init(mod->kunit_suites, mod->num_kunit_suites);
651}
652
653static void kunit_module_exit(struct module *mod)
654{
655 __kunit_test_suites_exit(mod->kunit_suites, mod->num_kunit_suites);
656}
657
658static int kunit_module_notify(struct notifier_block *nb, unsigned long val,
659 void *data)
660{
661 struct module *mod = data;
662
663 switch (val) {
664 case MODULE_STATE_LIVE:
665 kunit_module_init(mod);
666 break;
667 case MODULE_STATE_GOING:
668 kunit_module_exit(mod);
669 break;
670 case MODULE_STATE_COMING:
671 case MODULE_STATE_UNFORMED:
672 break;
673 }
674
675 return 0;
676}
677
678static struct notifier_block kunit_mod_nb = {
679 .notifier_call = kunit_module_notify,
680 .priority = 0,
681};
682#endif
683
684struct kunit_kmalloc_array_params {
685 size_t n;
686 size_t size;
687 gfp_t gfp;
688};
689
690static int kunit_kmalloc_array_init(struct kunit_resource *res, void *context)
691{
692 struct kunit_kmalloc_array_params *params = context;
693
694 res->data = kmalloc_array(params->n, params->size, params->gfp);
695 if (!res->data)
696 return -ENOMEM;
697
698 return 0;
699}
700
701static void kunit_kmalloc_array_free(struct kunit_resource *res)
702{
703 kfree(res->data);
704}
705
706void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp)
707{
708 struct kunit_kmalloc_array_params params = {
709 .size = size,
710 .n = n,
711 .gfp = gfp
712 };
713
714 return kunit_alloc_resource(test,
715 kunit_kmalloc_array_init,
716 kunit_kmalloc_array_free,
717 gfp,
718 ¶ms);
719}
720EXPORT_SYMBOL_GPL(kunit_kmalloc_array);
721
722static inline bool kunit_kfree_match(struct kunit *test,
723 struct kunit_resource *res, void *match_data)
724{
725 /* Only match resources allocated with kunit_kmalloc() and friends. */
726 return res->free == kunit_kmalloc_array_free && res->data == match_data;
727}
728
729void kunit_kfree(struct kunit *test, const void *ptr)
730{
731 if (!ptr)
732 return;
733
734 if (kunit_destroy_resource(test, kunit_kfree_match, (void *)ptr))
735 KUNIT_FAIL(test, "kunit_kfree: %px already freed or not allocated by kunit", ptr);
736}
737EXPORT_SYMBOL_GPL(kunit_kfree);
738
739void kunit_cleanup(struct kunit *test)
740{
741 struct kunit_resource *res;
742 unsigned long flags;
743
744 /*
745 * test->resources is a stack - each allocation must be freed in the
746 * reverse order from which it was added since one resource may depend
747 * on another for its entire lifetime.
748 * Also, we cannot use the normal list_for_each constructs, even the
749 * safe ones because *arbitrary* nodes may be deleted when
750 * kunit_resource_free is called; the list_for_each_safe variants only
751 * protect against the current node being deleted, not the next.
752 */
753 while (true) {
754 spin_lock_irqsave(&test->lock, flags);
755 if (list_empty(&test->resources)) {
756 spin_unlock_irqrestore(&test->lock, flags);
757 break;
758 }
759 res = list_last_entry(&test->resources,
760 struct kunit_resource,
761 node);
762 /*
763 * Need to unlock here as a resource may remove another
764 * resource, and this can't happen if the test->lock
765 * is held.
766 */
767 spin_unlock_irqrestore(&test->lock, flags);
768 kunit_remove_resource(test, res);
769 }
770 current->kunit_test = NULL;
771}
772EXPORT_SYMBOL_GPL(kunit_cleanup);
773
774static int __init kunit_init(void)
775{
776 /* Install the KUnit hook functions. */
777 kunit_install_hooks();
778
779 kunit_debugfs_init();
780#ifdef CONFIG_MODULES
781 return register_module_notifier(&kunit_mod_nb);
782#else
783 return 0;
784#endif
785}
786late_initcall(kunit_init);
787
788static void __exit kunit_exit(void)
789{
790 memset(&kunit_hooks, 0, sizeof(kunit_hooks));
791#ifdef CONFIG_MODULES
792 unregister_module_notifier(&kunit_mod_nb);
793#endif
794 kunit_debugfs_cleanup();
795}
796module_exit(kunit_exit);
797
798MODULE_LICENSE("GPL v2");