962 lines · c
1// SPDX-License-Identifier: GPL-2.02/*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 <kunit/attributes.h>13#include <linux/kernel.h>14#include <linux/module.h>15#include <linux/moduleparam.h>16#include <linux/mutex.h>17#include <linux/panic.h>18#include <linux/sched/debug.h>19#include <linux/sched.h>20#include <linux/mm.h>21 22#include "debugfs.h"23#include "device-impl.h"24#include "hooks-impl.h"25#include "string-stream.h"26#include "try-catch-impl.h"27 28static DEFINE_MUTEX(kunit_run_lock);29 30/*31 * Hook to fail the current test and print an error message to the log.32 */33void __printf(3, 4) __kunit_fail_current_test_impl(const char *file, int line, const char *fmt, ...)34{35 va_list args;36 int len;37 char *buffer;38 39 if (!current->kunit_test)40 return;41 42 kunit_set_failure(current->kunit_test);43 44 /* kunit_err() only accepts literals, so evaluate the args first. */45 va_start(args, fmt);46 len = vsnprintf(NULL, 0, fmt, args) + 1;47 va_end(args);48 49 buffer = kunit_kmalloc(current->kunit_test, len, GFP_KERNEL);50 if (!buffer)51 return;52 53 va_start(args, fmt);54 vsnprintf(buffer, len, fmt, args);55 va_end(args);56 57 kunit_err(current->kunit_test, "%s:%d: %s", file, line, buffer);58 kunit_kfree(current->kunit_test, buffer);59}60 61/*62 * Enable KUnit tests to run.63 */64#ifdef CONFIG_KUNIT_DEFAULT_ENABLED65static bool enable_param = true;66#else67static bool enable_param;68#endif69module_param_named(enable, enable_param, bool, 0);70MODULE_PARM_DESC(enable, "Enable KUnit tests");71 72/*73 * KUnit statistic mode:74 * 0 - disabled75 * 1 - only when there is more than one subtest76 * 2 - enabled77 */78static int kunit_stats_enabled = 1;79module_param_named(stats_enabled, kunit_stats_enabled, int, 0644);80MODULE_PARM_DESC(stats_enabled,81 "Print test stats: never (0), only for multiple subtests (1), or always (2)");82 83struct kunit_result_stats {84 unsigned long passed;85 unsigned long skipped;86 unsigned long failed;87 unsigned long total;88};89 90static bool kunit_should_print_stats(struct kunit_result_stats stats)91{92 if (kunit_stats_enabled == 0)93 return false;94 95 if (kunit_stats_enabled == 2)96 return true;97 98 return (stats.total > 1);99}100 101static void kunit_print_test_stats(struct kunit *test,102 struct kunit_result_stats stats)103{104 if (!kunit_should_print_stats(stats))105 return;106 107 kunit_log(KERN_INFO, test,108 KUNIT_SUBTEST_INDENT109 "# %s: pass:%lu fail:%lu skip:%lu total:%lu",110 test->name,111 stats.passed,112 stats.failed,113 stats.skipped,114 stats.total);115}116 117/* Append formatted message to log. */118void kunit_log_append(struct string_stream *log, const char *fmt, ...)119{120 va_list args;121 122 if (!log)123 return;124 125 va_start(args, fmt);126 string_stream_vadd(log, fmt, args);127 va_end(args);128}129EXPORT_SYMBOL_GPL(kunit_log_append);130 131size_t kunit_suite_num_test_cases(struct kunit_suite *suite)132{133 struct kunit_case *test_case;134 size_t len = 0;135 136 kunit_suite_for_each_test_case(suite, test_case)137 len++;138 139 return len;140}141EXPORT_SYMBOL_GPL(kunit_suite_num_test_cases);142 143/* Currently supported test levels */144enum {145 KUNIT_LEVEL_SUITE = 0,146 KUNIT_LEVEL_CASE,147 KUNIT_LEVEL_CASE_PARAM,148};149 150static void kunit_print_suite_start(struct kunit_suite *suite)151{152 /*153 * We do not log the test suite header as doing so would154 * mean debugfs display would consist of the test suite155 * header prior to individual test results.156 * Hence directly printk the suite status, and we will157 * separately seq_printf() the suite header for the debugfs158 * representation.159 */160 pr_info(KUNIT_SUBTEST_INDENT "KTAP version 1\n");161 pr_info(KUNIT_SUBTEST_INDENT "# Subtest: %s\n",162 suite->name);163 kunit_print_attr((void *)suite, false, KUNIT_LEVEL_CASE);164 pr_info(KUNIT_SUBTEST_INDENT "1..%zd\n",165 kunit_suite_num_test_cases(suite));166}167 168static void kunit_print_ok_not_ok(struct kunit *test,169 unsigned int test_level,170 enum kunit_status status,171 size_t test_number,172 const char *description,173 const char *directive)174{175 const char *directive_header = (status == KUNIT_SKIPPED) ? " # SKIP " : "";176 const char *directive_body = (status == KUNIT_SKIPPED) ? directive : "";177 178 /*179 * When test is NULL assume that results are from the suite180 * and today suite results are expected at level 0 only.181 */182 WARN(!test && test_level, "suite test level can't be %u!\n", test_level);183 184 /*185 * We do not log the test suite results as doing so would186 * mean debugfs display would consist of an incorrect test187 * number. Hence directly printk the suite result, and we will188 * separately seq_printf() the suite results for the debugfs189 * representation.190 */191 if (!test)192 pr_info("%s %zd %s%s%s\n",193 kunit_status_to_ok_not_ok(status),194 test_number, description, directive_header,195 directive_body);196 else197 kunit_log(KERN_INFO, test,198 "%*s%s %zd %s%s%s",199 KUNIT_INDENT_LEN * test_level, "",200 kunit_status_to_ok_not_ok(status),201 test_number, description, directive_header,202 directive_body);203}204 205enum kunit_status kunit_suite_has_succeeded(struct kunit_suite *suite)206{207 const struct kunit_case *test_case;208 enum kunit_status status = KUNIT_SKIPPED;209 210 if (suite->suite_init_err)211 return KUNIT_FAILURE;212 213 kunit_suite_for_each_test_case(suite, test_case) {214 if (test_case->status == KUNIT_FAILURE)215 return KUNIT_FAILURE;216 else if (test_case->status == KUNIT_SUCCESS)217 status = KUNIT_SUCCESS;218 }219 220 return status;221}222EXPORT_SYMBOL_GPL(kunit_suite_has_succeeded);223 224static size_t kunit_suite_counter = 1;225 226static void kunit_print_suite_end(struct kunit_suite *suite)227{228 kunit_print_ok_not_ok(NULL, KUNIT_LEVEL_SUITE,229 kunit_suite_has_succeeded(suite),230 kunit_suite_counter++,231 suite->name,232 suite->status_comment);233}234 235unsigned int kunit_test_case_num(struct kunit_suite *suite,236 struct kunit_case *test_case)237{238 struct kunit_case *tc;239 unsigned int i = 1;240 241 kunit_suite_for_each_test_case(suite, tc) {242 if (tc == test_case)243 return i;244 i++;245 }246 247 return 0;248}249EXPORT_SYMBOL_GPL(kunit_test_case_num);250 251static void kunit_print_string_stream(struct kunit *test,252 struct string_stream *stream)253{254 struct string_stream_fragment *fragment;255 char *buf;256 257 if (string_stream_is_empty(stream))258 return;259 260 buf = string_stream_get_string(stream);261 if (!buf) {262 kunit_err(test,263 "Could not allocate buffer, dumping stream:\n");264 list_for_each_entry(fragment, &stream->fragments, node) {265 kunit_err(test, "%s", fragment->fragment);266 }267 kunit_err(test, "\n");268 } else {269 kunit_err(test, "%s", buf);270 kfree(buf);271 }272}273 274static void kunit_fail(struct kunit *test, const struct kunit_loc *loc,275 enum kunit_assert_type type, const struct kunit_assert *assert,276 assert_format_t assert_format, const struct va_format *message)277{278 struct string_stream *stream;279 280 kunit_set_failure(test);281 282 stream = kunit_alloc_string_stream(test, GFP_KERNEL);283 if (IS_ERR(stream)) {284 WARN(true,285 "Could not allocate stream to print failed assertion in %s:%d\n",286 loc->file,287 loc->line);288 return;289 }290 291 kunit_assert_prologue(loc, type, stream);292 assert_format(assert, message, stream);293 294 kunit_print_string_stream(test, stream);295 296 kunit_free_string_stream(test, stream);297}298 299void __noreturn __kunit_abort(struct kunit *test)300{301 kunit_try_catch_throw(&test->try_catch); /* Does not return. */302 303 /*304 * Throw could not abort from test.305 *306 * XXX: we should never reach this line! As kunit_try_catch_throw is307 * marked __noreturn.308 */309 WARN_ONCE(true, "Throw could not abort from test!\n");310}311EXPORT_SYMBOL_GPL(__kunit_abort);312 313void __kunit_do_failed_assertion(struct kunit *test,314 const struct kunit_loc *loc,315 enum kunit_assert_type type,316 const struct kunit_assert *assert,317 assert_format_t assert_format,318 const char *fmt, ...)319{320 va_list args;321 struct va_format message;322 va_start(args, fmt);323 324 message.fmt = fmt;325 message.va = &args;326 327 kunit_fail(test, loc, type, assert, assert_format, &message);328 329 va_end(args);330}331EXPORT_SYMBOL_GPL(__kunit_do_failed_assertion);332 333void kunit_init_test(struct kunit *test, const char *name, struct string_stream *log)334{335 spin_lock_init(&test->lock);336 INIT_LIST_HEAD(&test->resources);337 test->name = name;338 test->log = log;339 if (test->log)340 string_stream_clear(log);341 test->status = KUNIT_SUCCESS;342 test->status_comment[0] = '\0';343}344EXPORT_SYMBOL_GPL(kunit_init_test);345 346/* Only warn when a test takes more than twice the threshold */347#define KUNIT_SPEED_WARNING_MULTIPLIER 2348 349/* Slow tests are defined as taking more than 1s */350#define KUNIT_SPEED_SLOW_THRESHOLD_S 1351 352#define KUNIT_SPEED_SLOW_WARNING_THRESHOLD_S \353 (KUNIT_SPEED_WARNING_MULTIPLIER * KUNIT_SPEED_SLOW_THRESHOLD_S)354 355#define s_to_timespec64(s) ns_to_timespec64((s) * NSEC_PER_SEC)356 357static void kunit_run_case_check_speed(struct kunit *test,358 struct kunit_case *test_case,359 struct timespec64 duration)360{361 struct timespec64 slow_thr =362 s_to_timespec64(KUNIT_SPEED_SLOW_WARNING_THRESHOLD_S);363 enum kunit_speed speed = test_case->attr.speed;364 365 if (timespec64_compare(&duration, &slow_thr) < 0)366 return;367 368 if (speed == KUNIT_SPEED_VERY_SLOW || speed == KUNIT_SPEED_SLOW)369 return;370 371 kunit_warn(test,372 "Test should be marked slow (runtime: %lld.%09lds)",373 duration.tv_sec, duration.tv_nsec);374}375 376/*377 * Initializes and runs test case. Does not clean up or do post validations.378 */379static void kunit_run_case_internal(struct kunit *test,380 struct kunit_suite *suite,381 struct kunit_case *test_case)382{383 struct timespec64 start, end;384 385 if (suite->init) {386 int ret;387 388 ret = suite->init(test);389 if (ret) {390 kunit_err(test, "failed to initialize: %d\n", ret);391 kunit_set_failure(test);392 return;393 }394 }395 396 ktime_get_ts64(&start);397 398 test_case->run_case(test);399 400 ktime_get_ts64(&end);401 402 kunit_run_case_check_speed(test, test_case, timespec64_sub(end, start));403}404 405static void kunit_case_internal_cleanup(struct kunit *test)406{407 kunit_cleanup(test);408}409 410/*411 * Performs post validations and cleanup after a test case was run.412 * XXX: Should ONLY BE CALLED AFTER kunit_run_case_internal!413 */414static void kunit_run_case_cleanup(struct kunit *test,415 struct kunit_suite *suite)416{417 if (suite->exit)418 suite->exit(test);419 420 kunit_case_internal_cleanup(test);421}422 423struct kunit_try_catch_context {424 struct kunit *test;425 struct kunit_suite *suite;426 struct kunit_case *test_case;427};428 429static void kunit_try_run_case(void *data)430{431 struct kunit_try_catch_context *ctx = data;432 struct kunit *test = ctx->test;433 struct kunit_suite *suite = ctx->suite;434 struct kunit_case *test_case = ctx->test_case;435 436 current->kunit_test = test;437 438 /*439 * kunit_run_case_internal may encounter a fatal error; if it does,440 * abort will be called, this thread will exit, and finally the parent441 * thread will resume control and handle any necessary clean up.442 */443 kunit_run_case_internal(test, suite, test_case);444}445 446static void kunit_try_run_case_cleanup(void *data)447{448 struct kunit_try_catch_context *ctx = data;449 struct kunit *test = ctx->test;450 struct kunit_suite *suite = ctx->suite;451 452 current->kunit_test = test;453 454 kunit_run_case_cleanup(test, suite);455}456 457static void kunit_catch_run_case_cleanup(void *data)458{459 struct kunit_try_catch_context *ctx = data;460 struct kunit *test = ctx->test;461 int try_exit_code = kunit_try_catch_get_result(&test->try_catch);462 463 /* It is always a failure if cleanup aborts. */464 kunit_set_failure(test);465 466 if (try_exit_code) {467 /*468 * Test case could not finish, we have no idea what state it is469 * in, so don't do clean up.470 */471 if (try_exit_code == -ETIMEDOUT) {472 kunit_err(test, "test case cleanup timed out\n");473 /*474 * Unknown internal error occurred preventing test case from475 * running, so there is nothing to clean up.476 */477 } else {478 kunit_err(test, "internal error occurred during test case cleanup: %d\n",479 try_exit_code);480 }481 return;482 }483 484 kunit_err(test, "test aborted during cleanup. continuing without cleaning up\n");485}486 487 488static void kunit_catch_run_case(void *data)489{490 struct kunit_try_catch_context *ctx = data;491 struct kunit *test = ctx->test;492 int try_exit_code = kunit_try_catch_get_result(&test->try_catch);493 494 if (try_exit_code) {495 kunit_set_failure(test);496 /*497 * Test case could not finish, we have no idea what state it is498 * in, so don't do clean up.499 */500 if (try_exit_code == -ETIMEDOUT) {501 kunit_err(test, "test case timed out\n");502 /*503 * Unknown internal error occurred preventing test case from504 * running, so there is nothing to clean up.505 */506 } else {507 kunit_err(test, "internal error occurred preventing test case from running: %d\n",508 try_exit_code);509 }510 return;511 }512}513 514/*515 * Performs all logic to run a test case. It also catches most errors that516 * occur in a test case and reports them as failures.517 */518static void kunit_run_case_catch_errors(struct kunit_suite *suite,519 struct kunit_case *test_case,520 struct kunit *test)521{522 struct kunit_try_catch_context context;523 struct kunit_try_catch *try_catch;524 525 try_catch = &test->try_catch;526 527 kunit_try_catch_init(try_catch,528 test,529 kunit_try_run_case,530 kunit_catch_run_case);531 context.test = test;532 context.suite = suite;533 context.test_case = test_case;534 kunit_try_catch_run(try_catch, &context);535 536 /* Now run the cleanup */537 kunit_try_catch_init(try_catch,538 test,539 kunit_try_run_case_cleanup,540 kunit_catch_run_case_cleanup);541 kunit_try_catch_run(try_catch, &context);542 543 /* Propagate the parameter result to the test case. */544 if (test->status == KUNIT_FAILURE)545 test_case->status = KUNIT_FAILURE;546 else if (test_case->status != KUNIT_FAILURE && test->status == KUNIT_SUCCESS)547 test_case->status = KUNIT_SUCCESS;548}549 550static void kunit_print_suite_stats(struct kunit_suite *suite,551 struct kunit_result_stats suite_stats,552 struct kunit_result_stats param_stats)553{554 if (kunit_should_print_stats(suite_stats)) {555 kunit_log(KERN_INFO, suite,556 "# %s: pass:%lu fail:%lu skip:%lu total:%lu",557 suite->name,558 suite_stats.passed,559 suite_stats.failed,560 suite_stats.skipped,561 suite_stats.total);562 }563 564 if (kunit_should_print_stats(param_stats)) {565 kunit_log(KERN_INFO, suite,566 "# Totals: pass:%lu fail:%lu skip:%lu total:%lu",567 param_stats.passed,568 param_stats.failed,569 param_stats.skipped,570 param_stats.total);571 }572}573 574static void kunit_update_stats(struct kunit_result_stats *stats,575 enum kunit_status status)576{577 switch (status) {578 case KUNIT_SUCCESS:579 stats->passed++;580 break;581 case KUNIT_SKIPPED:582 stats->skipped++;583 break;584 case KUNIT_FAILURE:585 stats->failed++;586 break;587 }588 589 stats->total++;590}591 592static void kunit_accumulate_stats(struct kunit_result_stats *total,593 struct kunit_result_stats add)594{595 total->passed += add.passed;596 total->skipped += add.skipped;597 total->failed += add.failed;598 total->total += add.total;599}600 601int kunit_run_tests(struct kunit_suite *suite)602{603 char param_desc[KUNIT_PARAM_DESC_SIZE];604 struct kunit_case *test_case;605 struct kunit_result_stats suite_stats = { 0 };606 struct kunit_result_stats total_stats = { 0 };607 608 /* Taint the kernel so we know we've run tests. */609 add_taint(TAINT_TEST, LOCKDEP_STILL_OK);610 611 if (suite->suite_init) {612 suite->suite_init_err = suite->suite_init(suite);613 if (suite->suite_init_err) {614 kunit_err(suite, KUNIT_SUBTEST_INDENT615 "# failed to initialize (%d)", suite->suite_init_err);616 goto suite_end;617 }618 }619 620 kunit_print_suite_start(suite);621 622 kunit_suite_for_each_test_case(suite, test_case) {623 struct kunit test = { .param_value = NULL, .param_index = 0 };624 struct kunit_result_stats param_stats = { 0 };625 626 kunit_init_test(&test, test_case->name, test_case->log);627 if (test_case->status == KUNIT_SKIPPED) {628 /* Test marked as skip */629 test.status = KUNIT_SKIPPED;630 kunit_update_stats(¶m_stats, test.status);631 } else if (!test_case->generate_params) {632 /* Non-parameterised test. */633 test_case->status = KUNIT_SKIPPED;634 kunit_run_case_catch_errors(suite, test_case, &test);635 kunit_update_stats(¶m_stats, test.status);636 } else {637 /* Get initial param. */638 param_desc[0] = '\0';639 test.param_value = test_case->generate_params(NULL, param_desc);640 test_case->status = KUNIT_SKIPPED;641 kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT642 "KTAP version 1\n");643 kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT644 "# Subtest: %s", test_case->name);645 646 while (test.param_value) {647 kunit_run_case_catch_errors(suite, test_case, &test);648 649 if (param_desc[0] == '\0') {650 snprintf(param_desc, sizeof(param_desc),651 "param-%d", test.param_index);652 }653 654 kunit_print_ok_not_ok(&test, KUNIT_LEVEL_CASE_PARAM,655 test.status,656 test.param_index + 1,657 param_desc,658 test.status_comment);659 660 kunit_update_stats(¶m_stats, test.status);661 662 /* Get next param. */663 param_desc[0] = '\0';664 test.param_value = test_case->generate_params(test.param_value, param_desc);665 test.param_index++;666 test.status = KUNIT_SUCCESS;667 test.status_comment[0] = '\0';668 test.priv = NULL;669 }670 }671 672 kunit_print_attr((void *)test_case, true, KUNIT_LEVEL_CASE);673 674 kunit_print_test_stats(&test, param_stats);675 676 kunit_print_ok_not_ok(&test, KUNIT_LEVEL_CASE, test_case->status,677 kunit_test_case_num(suite, test_case),678 test_case->name,679 test.status_comment);680 681 kunit_update_stats(&suite_stats, test_case->status);682 kunit_accumulate_stats(&total_stats, param_stats);683 }684 685 if (suite->suite_exit)686 suite->suite_exit(suite);687 688 kunit_print_suite_stats(suite, suite_stats, total_stats);689suite_end:690 kunit_print_suite_end(suite);691 692 return 0;693}694EXPORT_SYMBOL_GPL(kunit_run_tests);695 696static void kunit_init_suite(struct kunit_suite *suite)697{698 kunit_debugfs_create_suite(suite);699 suite->status_comment[0] = '\0';700 suite->suite_init_err = 0;701 702 if (suite->log)703 string_stream_clear(suite->log);704}705 706bool kunit_enabled(void)707{708 return enable_param;709}710 711int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_suites)712{713 unsigned int i;714 715 if (num_suites == 0)716 return 0;717 718 if (!kunit_enabled() && num_suites > 0) {719 pr_info("kunit: disabled\n");720 return 0;721 }722 723 kunit_suite_counter = 1;724 725 /* Use mutex lock to guard against running tests concurrently. */726 if (mutex_lock_interruptible(&kunit_run_lock)) {727 pr_err("kunit: test interrupted\n");728 return -EINTR;729 }730 static_branch_inc(&kunit_running);731 732 for (i = 0; i < num_suites; i++) {733 kunit_init_suite(suites[i]);734 kunit_run_tests(suites[i]);735 }736 737 static_branch_dec(&kunit_running);738 mutex_unlock(&kunit_run_lock);739 return 0;740}741EXPORT_SYMBOL_GPL(__kunit_test_suites_init);742 743static void kunit_exit_suite(struct kunit_suite *suite)744{745 kunit_debugfs_destroy_suite(suite);746}747 748void __kunit_test_suites_exit(struct kunit_suite **suites, int num_suites)749{750 unsigned int i;751 752 if (!kunit_enabled())753 return;754 755 for (i = 0; i < num_suites; i++)756 kunit_exit_suite(suites[i]);757}758EXPORT_SYMBOL_GPL(__kunit_test_suites_exit);759 760#ifdef CONFIG_MODULES761static void kunit_module_init(struct module *mod)762{763 struct kunit_suite_set suite_set, filtered_set;764 struct kunit_suite_set normal_suite_set = {765 mod->kunit_suites, mod->kunit_suites + mod->num_kunit_suites,766 };767 struct kunit_suite_set init_suite_set = {768 mod->kunit_init_suites, mod->kunit_init_suites + mod->num_kunit_init_suites,769 };770 const char *action = kunit_action();771 int err = 0;772 773 if (mod->num_kunit_init_suites > 0)774 suite_set = kunit_merge_suite_sets(init_suite_set, normal_suite_set);775 else776 suite_set = normal_suite_set;777 778 filtered_set = kunit_filter_suites(&suite_set,779 kunit_filter_glob() ?: "*.*",780 kunit_filter(), kunit_filter_action(),781 &err);782 if (err)783 pr_err("kunit module: error filtering suites: %d\n", err);784 785 mod->kunit_suites = (struct kunit_suite **)filtered_set.start;786 mod->num_kunit_suites = filtered_set.end - filtered_set.start;787 788 if (mod->num_kunit_init_suites > 0)789 kfree(suite_set.start);790 791 if (!action)792 kunit_exec_run_tests(&filtered_set, false);793 else if (!strcmp(action, "list"))794 kunit_exec_list_tests(&filtered_set, false);795 else if (!strcmp(action, "list_attr"))796 kunit_exec_list_tests(&filtered_set, true);797 else798 pr_err("kunit: unknown action '%s'\n", action);799}800 801static void kunit_module_exit(struct module *mod)802{803 struct kunit_suite_set suite_set = {804 mod->kunit_suites, mod->kunit_suites + mod->num_kunit_suites,805 };806 const char *action = kunit_action();807 808 /*809 * Check if the start address is a valid virtual address to detect810 * if the module load sequence has failed and the suite set has not811 * been initialized and filtered.812 */813 if (!suite_set.start || !virt_addr_valid(suite_set.start))814 return;815 816 if (!action)817 __kunit_test_suites_exit(mod->kunit_suites,818 mod->num_kunit_suites);819 820 kunit_free_suite_set(suite_set);821}822 823static int kunit_module_notify(struct notifier_block *nb, unsigned long val,824 void *data)825{826 struct module *mod = data;827 828 switch (val) {829 case MODULE_STATE_LIVE:830 kunit_module_init(mod);831 break;832 case MODULE_STATE_GOING:833 kunit_module_exit(mod);834 break;835 case MODULE_STATE_COMING:836 break;837 case MODULE_STATE_UNFORMED:838 break;839 }840 841 return 0;842}843 844static struct notifier_block kunit_mod_nb = {845 .notifier_call = kunit_module_notify,846 .priority = 0,847};848#endif849 850KUNIT_DEFINE_ACTION_WRAPPER(kfree_action_wrapper, kfree, const void *)851 852void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp)853{854 void *data;855 856 data = kmalloc_array(n, size, gfp);857 858 if (!data)859 return NULL;860 861 if (kunit_add_action_or_reset(test, kfree_action_wrapper, data) != 0)862 return NULL;863 864 return data;865}866EXPORT_SYMBOL_GPL(kunit_kmalloc_array);867 868void kunit_kfree(struct kunit *test, const void *ptr)869{870 if (!ptr)871 return;872 873 kunit_release_action(test, kfree_action_wrapper, (void *)ptr);874}875EXPORT_SYMBOL_GPL(kunit_kfree);876 877void kunit_kfree_const(struct kunit *test, const void *x)878{879#if !IS_MODULE(CONFIG_KUNIT)880 if (!is_kernel_rodata((unsigned long)x))881#endif882 kunit_kfree(test, x);883}884EXPORT_SYMBOL_GPL(kunit_kfree_const);885 886const char *kunit_kstrdup_const(struct kunit *test, const char *str, gfp_t gfp)887{888#if !IS_MODULE(CONFIG_KUNIT)889 if (is_kernel_rodata((unsigned long)str))890 return str;891#endif892 return kunit_kstrdup(test, str, gfp);893}894EXPORT_SYMBOL_GPL(kunit_kstrdup_const);895 896void kunit_cleanup(struct kunit *test)897{898 struct kunit_resource *res;899 unsigned long flags;900 901 /*902 * test->resources is a stack - each allocation must be freed in the903 * reverse order from which it was added since one resource may depend904 * on another for its entire lifetime.905 * Also, we cannot use the normal list_for_each constructs, even the906 * safe ones because *arbitrary* nodes may be deleted when907 * kunit_resource_free is called; the list_for_each_safe variants only908 * protect against the current node being deleted, not the next.909 */910 while (true) {911 spin_lock_irqsave(&test->lock, flags);912 if (list_empty(&test->resources)) {913 spin_unlock_irqrestore(&test->lock, flags);914 break;915 }916 res = list_last_entry(&test->resources,917 struct kunit_resource,918 node);919 /*920 * Need to unlock here as a resource may remove another921 * resource, and this can't happen if the test->lock922 * is held.923 */924 spin_unlock_irqrestore(&test->lock, flags);925 kunit_remove_resource(test, res);926 }927 current->kunit_test = NULL;928}929EXPORT_SYMBOL_GPL(kunit_cleanup);930 931static int __init kunit_init(void)932{933 /* Install the KUnit hook functions. */934 kunit_install_hooks();935 936 kunit_debugfs_init();937 938 kunit_bus_init();939#ifdef CONFIG_MODULES940 return register_module_notifier(&kunit_mod_nb);941#else942 return 0;943#endif944}945late_initcall(kunit_init);946 947static void __exit kunit_exit(void)948{949 memset(&kunit_hooks, 0, sizeof(kunit_hooks));950#ifdef CONFIG_MODULES951 unregister_module_notifier(&kunit_mod_nb);952#endif953 954 kunit_bus_shutdown();955 956 kunit_debugfs_cleanup();957}958module_exit(kunit_exit);959 960MODULE_DESCRIPTION("Base unit test (KUnit) API");961MODULE_LICENSE("GPL v2");962