LCOV - code coverage report
Current view: top level - lib/kunit - test.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 161 250 64.4 %
Date: 2023-04-06 08:38:28 Functions: 17 30 56.7 %

          Line data    Source code
       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             :  */
      27           0 : void __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           0 :         if (!current->kunit_test)
      34           0 :                 return;
      35             : 
      36           0 :         kunit_set_failure(current->kunit_test);
      37             : 
      38             :         /* kunit_err() only accepts literals, so evaluate the args first. */
      39           0 :         va_start(args, fmt);
      40           0 :         len = vsnprintf(NULL, 0, fmt, args) + 1;
      41           0 :         va_end(args);
      42             : 
      43           0 :         buffer = kunit_kmalloc(current->kunit_test, len, GFP_KERNEL);
      44           0 :         if (!buffer)
      45             :                 return;
      46             : 
      47           0 :         va_start(args, fmt);
      48           0 :         vsnprintf(buffer, len, fmt, args);
      49           0 :         va_end(args);
      50             : 
      51           0 :         kunit_err(current->kunit_test, "%s:%d: %s", file, line, buffer);
      52           0 :         kunit_kfree(current->kunit_test, buffer);
      53             : }
      54             : 
      55             : /*
      56             :  * Enable KUnit tests to run.
      57             :  */
      58             : #ifdef CONFIG_KUNIT_DEFAULT_ENABLED
      59             : static bool enable_param = true;
      60             : #else
      61             : static bool enable_param;
      62             : #endif
      63             : module_param_named(enable, enable_param, bool, 0);
      64             : MODULE_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             :  */
      72             : static int kunit_stats_enabled = 1;
      73             : module_param_named(stats_enabled, kunit_stats_enabled, int, 0644);
      74             : MODULE_PARM_DESC(stats_enabled,
      75             :                   "Print test stats: never (0), only for multiple subtests (1), or always (2)");
      76             : 
      77             : struct kunit_result_stats {
      78             :         unsigned long passed;
      79             :         unsigned long skipped;
      80             :         unsigned long failed;
      81             :         unsigned long total;
      82             : };
      83             : 
      84             : static bool kunit_should_print_stats(struct kunit_result_stats stats)
      85             : {
      86         169 :         if (kunit_stats_enabled == 0)
      87             :                 return false;
      88             : 
      89         169 :         if (kunit_stats_enabled == 2)
      90             :                 return true;
      91             : 
      92         169 :         return (stats.total > 1);
      93             : }
      94             : 
      95         139 : static void kunit_print_test_stats(struct kunit *test,
      96             :                                    struct kunit_result_stats stats)
      97             : {
      98         278 :         if (!kunit_should_print_stats(stats))
      99             :                 return;
     100             : 
     101          26 :         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             :  */
     115         512 : void 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         512 :         if (!log)
     122         512 :                 return;
     123             : 
     124           0 :         len_left = KUNIT_LOG_SIZE - strlen(log) - 1;
     125           0 :         if (len_left <= 0)
     126             :                 return;
     127             : 
     128           0 :         va_start(args, fmt);
     129           0 :         vsnprintf(line, sizeof(line), fmt, args);
     130           0 :         va_end(args);
     131             : 
     132           0 :         strncat(log, line, len_left);
     133             : }
     134             : EXPORT_SYMBOL_GPL(kunit_log_append);
     135             : 
     136           0 : size_t kunit_suite_num_test_cases(struct kunit_suite *suite)
     137             : {
     138             :         struct kunit_case *test_case;
     139          30 :         size_t len = 0;
     140             : 
     141         308 :         kunit_suite_for_each_test_case(suite, test_case)
     142         278 :                 len++;
     143             : 
     144           0 :         return len;
     145             : }
     146             : EXPORT_SYMBOL_GPL(kunit_suite_num_test_cases);
     147             : 
     148          15 : static void kunit_print_suite_start(struct kunit_suite *suite)
     149             : {
     150          15 :         kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "KTAP version 1\n");
     151          15 :         kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "# Subtest: %s",
     152             :                   suite->name);
     153          30 :         kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "1..%zd",
     154             :                   kunit_suite_num_test_cases(suite));
     155          15 : }
     156             : 
     157         154 : static 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         154 :         struct kunit_suite *suite = is_test ? NULL : test_or_suite;
     165         154 :         struct kunit *test = is_test ? test_or_suite : NULL;
     166         154 :         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         154 :         if (suite)
     177          30 :                 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         417 :                 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         154 : }
     188             : 
     189           0 : enum kunit_status kunit_suite_has_succeeded(struct kunit_suite *suite)
     190             : {
     191             :         const struct kunit_case *test_case;
     192          15 :         enum kunit_status status = KUNIT_SKIPPED;
     193             : 
     194          15 :         if (suite->suite_init_err)
     195             :                 return KUNIT_FAILURE;
     196             : 
     197         154 :         kunit_suite_for_each_test_case(suite, test_case) {
     198         139 :                 if (test_case->status == KUNIT_FAILURE)
     199             :                         return KUNIT_FAILURE;
     200         139 :                 else if (test_case->status == KUNIT_SUCCESS)
     201         139 :                         status = KUNIT_SUCCESS;
     202             :         }
     203             : 
     204             :         return status;
     205             : }
     206             : EXPORT_SYMBOL_GPL(kunit_suite_has_succeeded);
     207             : 
     208             : static size_t kunit_suite_counter = 1;
     209             : 
     210          15 : static void kunit_print_suite_end(struct kunit_suite *suite)
     211             : {
     212          30 :         kunit_print_ok_not_ok((void *)suite, false,
     213             :                               kunit_suite_has_succeeded(suite),
     214             :                               kunit_suite_counter++,
     215          15 :                               suite->name,
     216          15 :                               suite->status_comment);
     217          15 : }
     218             : 
     219           0 : unsigned int kunit_test_case_num(struct kunit_suite *suite,
     220             :                                  struct kunit_case *test_case)
     221             : {
     222             :         struct kunit_case *tc;
     223         139 :         unsigned int i = 1;
     224             : 
     225        1569 :         kunit_suite_for_each_test_case(suite, tc) {
     226        1569 :                 if (tc == test_case)
     227             :                         return i;
     228        1430 :                 i++;
     229             :         }
     230             : 
     231             :         return 0;
     232             : }
     233             : EXPORT_SYMBOL_GPL(kunit_test_case_num);
     234             : 
     235           0 : static 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           0 :         if (string_stream_is_empty(stream))
     242             :                 return;
     243             : 
     244           0 :         buf = string_stream_get_string(stream);
     245           0 :         if (!buf) {
     246           0 :                 kunit_err(test,
     247             :                           "Could not allocate buffer, dumping stream:\n");
     248           0 :                 list_for_each_entry(fragment, &stream->fragments, node) {
     249           0 :                         kunit_err(test, "%s", fragment->fragment);
     250             :                 }
     251           0 :                 kunit_err(test, "\n");
     252             :         } else {
     253           0 :                 kunit_err(test, "%s", buf);
     254           0 :                 kunit_kfree(test, buf);
     255             :         }
     256             : }
     257             : 
     258           0 : static 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           0 :         kunit_set_failure(test);
     265             : 
     266           0 :         stream = alloc_string_stream(test, GFP_KERNEL);
     267           0 :         if (IS_ERR(stream)) {
     268           0 :                 WARN(true,
     269             :                      "Could not allocate stream to print failed assertion in %s:%d\n",
     270             :                      loc->file,
     271             :                      loc->line);
     272           0 :                 return;
     273             :         }
     274             : 
     275           0 :         kunit_assert_prologue(loc, type, stream);
     276           0 :         assert_format(assert, message, stream);
     277             : 
     278           0 :         kunit_print_string_stream(test, stream);
     279             : 
     280           0 :         string_stream_destroy(stream);
     281             : }
     282             : 
     283             : static void __noreturn kunit_abort(struct kunit *test)
     284             : {
     285           0 :         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             : 
     296           0 : void 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           0 :         va_start(args, fmt);
     306             : 
     307           0 :         message.fmt = fmt;
     308           0 :         message.va = &args;
     309             : 
     310           0 :         kunit_fail(test, loc, type, assert, assert_format, &message);
     311             : 
     312           0 :         va_end(args);
     313             : 
     314           0 :         if (type == KUNIT_ASSERTION)
     315             :                 kunit_abort(test);
     316           0 : }
     317             : EXPORT_SYMBOL_GPL(kunit_do_failed_assertion);
     318             : 
     319           0 : void kunit_init_test(struct kunit *test, const char *name, char *log)
     320             : {
     321         333 :         spin_lock_init(&test->lock);
     322         666 :         INIT_LIST_HEAD(&test->resources);
     323         333 :         test->name = name;
     324         333 :         test->log = log;
     325         333 :         if (test->log)
     326           0 :                 test->log[0] = '\0';
     327         333 :         test->status = KUNIT_SUCCESS;
     328         333 :         test->status_comment[0] = '\0';
     329           0 : }
     330             : EXPORT_SYMBOL_GPL(kunit_init_test);
     331             : 
     332             : /*
     333             :  * Initializes and runs test case. Does not clean up or do post validations.
     334             :  */
     335         333 : static void kunit_run_case_internal(struct kunit *test,
     336             :                                     struct kunit_suite *suite,
     337             :                                     struct kunit_case *test_case)
     338             : {
     339         333 :         if (suite->init) {
     340             :                 int ret;
     341             : 
     342          96 :                 ret = suite->init(test);
     343          96 :                 if (ret) {
     344           0 :                         kunit_err(test, "failed to initialize: %d\n", ret);
     345             :                         kunit_set_failure(test);
     346             :                         return;
     347             :                 }
     348             :         }
     349             : 
     350         333 :         test_case->run_case(test);
     351             : }
     352             : 
     353             : static void kunit_case_internal_cleanup(struct kunit *test)
     354             : {
     355         333 :         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             :  */
     362             : static void kunit_run_case_cleanup(struct kunit *test,
     363             :                                    struct kunit_suite *suite)
     364             : {
     365         333 :         if (suite->exit)
     366          16 :                 suite->exit(test);
     367             : 
     368         333 :         kunit_case_internal_cleanup(test);
     369             : }
     370             : 
     371             : struct kunit_try_catch_context {
     372             :         struct kunit *test;
     373             :         struct kunit_suite *suite;
     374             :         struct kunit_case *test_case;
     375             : };
     376             : 
     377         333 : static void kunit_try_run_case(void *data)
     378             : {
     379         333 :         struct kunit_try_catch_context *ctx = data;
     380         333 :         struct kunit *test = ctx->test;
     381         333 :         struct kunit_suite *suite = ctx->suite;
     382         333 :         struct kunit_case *test_case = ctx->test_case;
     383             : 
     384         333 :         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         333 :         kunit_run_case_internal(test, suite, test_case);
     392             :         /* This line may never be reached. */
     393         666 :         kunit_run_case_cleanup(test, suite);
     394         333 : }
     395             : 
     396           0 : static void kunit_catch_run_case(void *data)
     397             : {
     398           0 :         struct kunit_try_catch_context *ctx = data;
     399           0 :         struct kunit *test = ctx->test;
     400           0 :         struct kunit_suite *suite = ctx->suite;
     401           0 :         int try_exit_code = kunit_try_catch_get_result(&test->try_catch);
     402             : 
     403           0 :         if (try_exit_code) {
     404           0 :                 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           0 :                 if (try_exit_code == -ETIMEDOUT) {
     410           0 :                         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           0 :                         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           0 :         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             :  */
     433         333 : static 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         666 :         kunit_init_test(test, test_case->name, test_case->log);
     441         333 :         try_catch = &test->try_catch;
     442             : 
     443         333 :         kunit_try_catch_init(try_catch,
     444             :                              test,
     445             :                              kunit_try_run_case,
     446             :                              kunit_catch_run_case);
     447         333 :         context.test = test;
     448         333 :         context.suite = suite;
     449         333 :         context.test_case = test_case;
     450         333 :         kunit_try_catch_run(try_catch, &context);
     451             : 
     452             :         /* Propagate the parameter result to the test case. */
     453         333 :         if (test->status == KUNIT_FAILURE)
     454           0 :                 test_case->status = KUNIT_FAILURE;
     455         333 :         else if (test_case->status != KUNIT_FAILURE && test->status == KUNIT_SUCCESS)
     456         333 :                 test_case->status = KUNIT_SUCCESS;
     457         333 : }
     458             : 
     459          15 : static 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          30 :         if (kunit_should_print_stats(suite_stats)) {
     464          12 :                 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          30 :         if (kunit_should_print_stats(param_stats)) {
     474          14 :                 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          15 : }
     482             : 
     483             : static void kunit_update_stats(struct kunit_result_stats *stats,
     484             :                                enum kunit_status status)
     485             : {
     486         472 :         switch (status) {
     487             :         case KUNIT_SUCCESS:
     488         472 :                 stats->passed++;
     489             :                 break;
     490             :         case KUNIT_SKIPPED:
     491           0 :                 stats->skipped++;
     492             :                 break;
     493             :         case KUNIT_FAILURE:
     494           0 :                 stats->failed++;
     495             :                 break;
     496             :         }
     497             : 
     498         359 :         stats->total++;
     499             : }
     500             : 
     501             : static void kunit_accumulate_stats(struct kunit_result_stats *total,
     502             :                                    struct kunit_result_stats add)
     503             : {
     504         139 :         total->passed += add.passed;
     505         139 :         total->skipped += add.skipped;
     506         139 :         total->failed += add.failed;
     507         139 :         total->total += add.total;
     508             : }
     509             : 
     510          15 : int kunit_run_tests(struct kunit_suite *suite)
     511             : {
     512             :         char param_desc[KUNIT_PARAM_DESC_SIZE];
     513             :         struct kunit_case *test_case;
     514          15 :         struct kunit_result_stats suite_stats = { 0 };
     515          15 :         struct kunit_result_stats total_stats = { 0 };
     516             : 
     517             :         /* Taint the kernel so we know we've run tests. */
     518          15 :         add_taint(TAINT_TEST, LOCKDEP_STILL_OK);
     519             : 
     520          15 :         if (suite->suite_init) {
     521           2 :                 suite->suite_init_err = suite->suite_init(suite);
     522           2 :                 if (suite->suite_init_err) {
     523           0 :                         kunit_err(suite, KUNIT_SUBTEST_INDENT
     524             :                                   "# failed to initialize (%d)", suite->suite_init_err);
     525           0 :                         goto suite_end;
     526             :                 }
     527             :         }
     528             : 
     529          15 :         kunit_print_suite_start(suite);
     530             : 
     531         154 :         kunit_suite_for_each_test_case(suite, test_case) {
     532         139 :                 struct kunit test = { .param_value = NULL, .param_index = 0 };
     533         139 :                 struct kunit_result_stats param_stats = { 0 };
     534         139 :                 test_case->status = KUNIT_SKIPPED;
     535             : 
     536         139 :                 if (!test_case->generate_params) {
     537             :                         /* Non-parameterised test. */
     538         113 :                         kunit_run_case_catch_errors(suite, test_case, &test);
     539         113 :                         kunit_update_stats(&param_stats, test.status);
     540             :                 } else {
     541             :                         /* Get initial param. */
     542          26 :                         param_desc[0] = '\0';
     543          26 :                         test.param_value = test_case->generate_params(NULL, param_desc);
     544          26 :                         kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT
     545             :                                   "KTAP version 1\n");
     546          26 :                         kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT
     547             :                                   "# Subtest: %s", test_case->name);
     548             : 
     549         272 :                         while (test.param_value) {
     550         220 :                                 kunit_run_case_catch_errors(suite, test_case, &test);
     551             : 
     552         220 :                                 if (param_desc[0] == '\0') {
     553           0 :                                         snprintf(param_desc, sizeof(param_desc),
     554             :                                                  "param-%d", test.param_index);
     555             :                                 }
     556             : 
     557         660 :                                 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         220 :                                 param_desc[0] = '\0';
     565         220 :                                 test.param_value = test_case->generate_params(test.param_value, param_desc);
     566         220 :                                 test.param_index++;
     567             : 
     568         220 :                                 kunit_update_stats(&param_stats, test.status);
     569             :                         }
     570             :                 }
     571             : 
     572             : 
     573         139 :                 kunit_print_test_stats(&test, param_stats);
     574             : 
     575         278 :                 kunit_print_ok_not_ok(&test, true, test_case->status,
     576         139 :                                       kunit_test_case_num(suite, test_case),
     577             :                                       test_case->name,
     578             :                                       test.status_comment);
     579             : 
     580         278 :                 kunit_update_stats(&suite_stats, test_case->status);
     581         139 :                 kunit_accumulate_stats(&total_stats, param_stats);
     582             :         }
     583             : 
     584          15 :         if (suite->suite_exit)
     585           0 :                 suite->suite_exit(suite);
     586             : 
     587          15 :         kunit_print_suite_stats(suite, suite_stats, total_stats);
     588             : suite_end:
     589          15 :         kunit_print_suite_end(suite);
     590             : 
     591          15 :         return 0;
     592             : }
     593             : EXPORT_SYMBOL_GPL(kunit_run_tests);
     594             : 
     595             : static void kunit_init_suite(struct kunit_suite *suite)
     596             : {
     597          15 :         kunit_debugfs_create_suite(suite);
     598          15 :         suite->status_comment[0] = '\0';
     599          15 :         suite->suite_init_err = 0;
     600             : }
     601             : 
     602           1 : bool kunit_enabled(void)
     603             : {
     604           2 :         return enable_param;
     605             : }
     606             : 
     607           1 : int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_suites)
     608             : {
     609             :         unsigned int i;
     610             : 
     611           1 :         if (!kunit_enabled() && num_suites > 0) {
     612           0 :                 pr_info("kunit: disabled\n");
     613           0 :                 return 0;
     614             :         }
     615             : 
     616           1 :         static_branch_inc(&kunit_running);
     617             : 
     618          16 :         for (i = 0; i < num_suites; i++) {
     619          15 :                 kunit_init_suite(suites[i]);
     620          15 :                 kunit_run_tests(suites[i]);
     621             :         }
     622             : 
     623           1 :         static_branch_dec(&kunit_running);
     624           1 :         return 0;
     625             : }
     626             : EXPORT_SYMBOL_GPL(__kunit_test_suites_init);
     627             : 
     628             : static void kunit_exit_suite(struct kunit_suite *suite)
     629             : {
     630             :         kunit_debugfs_destroy_suite(suite);
     631             : }
     632             : 
     633           0 : void __kunit_test_suites_exit(struct kunit_suite **suites, int num_suites)
     634             : {
     635             :         unsigned int i;
     636             : 
     637           0 :         if (!kunit_enabled())
     638             :                 return;
     639             : 
     640             :         for (i = 0; i < num_suites; i++)
     641             :                 kunit_exit_suite(suites[i]);
     642             : 
     643           0 :         kunit_suite_counter = 1;
     644             : }
     645             : EXPORT_SYMBOL_GPL(__kunit_test_suites_exit);
     646             : 
     647             : #ifdef CONFIG_MODULES
     648             : static void kunit_module_init(struct module *mod)
     649             : {
     650             :         __kunit_test_suites_init(mod->kunit_suites, mod->num_kunit_suites);
     651             : }
     652             : 
     653             : static void kunit_module_exit(struct module *mod)
     654             : {
     655             :         __kunit_test_suites_exit(mod->kunit_suites, mod->num_kunit_suites);
     656             : }
     657             : 
     658             : static 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             : 
     678             : static struct notifier_block kunit_mod_nb = {
     679             :         .notifier_call = kunit_module_notify,
     680             :         .priority = 0,
     681             : };
     682             : #endif
     683             : 
     684             : struct kunit_kmalloc_array_params {
     685             :         size_t n;
     686             :         size_t size;
     687             :         gfp_t gfp;
     688             : };
     689             : 
     690         312 : static int kunit_kmalloc_array_init(struct kunit_resource *res, void *context)
     691             : {
     692         312 :         struct kunit_kmalloc_array_params *params = context;
     693             : 
     694         312 :         res->data = kmalloc_array(params->n, params->size, params->gfp);
     695         312 :         if (!res->data)
     696             :                 return -ENOMEM;
     697             : 
     698         312 :         return 0;
     699             : }
     700             : 
     701         312 : static void kunit_kmalloc_array_free(struct kunit_resource *res)
     702             : {
     703         312 :         kfree(res->data);
     704         312 : }
     705             : 
     706         312 : void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp)
     707             : {
     708         312 :         struct kunit_kmalloc_array_params params = {
     709             :                 .size = size,
     710             :                 .n = n,
     711             :                 .gfp = gfp
     712             :         };
     713             : 
     714         312 :         return kunit_alloc_resource(test,
     715             :                                     kunit_kmalloc_array_init,
     716             :                                     kunit_kmalloc_array_free,
     717             :                                     gfp,
     718             :                                     &params);
     719             : }
     720             : EXPORT_SYMBOL_GPL(kunit_kmalloc_array);
     721             : 
     722           0 : static 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           0 :         return res->free == kunit_kmalloc_array_free && res->data == match_data;
     727             : }
     728             : 
     729           0 : void kunit_kfree(struct kunit *test, const void *ptr)
     730             : {
     731           0 :         if (!ptr)
     732             :                 return;
     733             : 
     734           0 :         if (kunit_destroy_resource(test, kunit_kfree_match, (void *)ptr))
     735           0 :                 KUNIT_FAIL(test, "kunit_kfree: %px already freed or not allocated by kunit", ptr);
     736             : }
     737             : EXPORT_SYMBOL_GPL(kunit_kfree);
     738             : 
     739         333 : void 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         957 :                 spin_lock_irqsave(&test->lock, flags);
     755        1290 :                 if (list_empty(&test->resources)) {
     756         666 :                         spin_unlock_irqrestore(&test->lock, flags);
     757             :                         break;
     758             :                 }
     759         312 :                 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         624 :                 spin_unlock_irqrestore(&test->lock, flags);
     768         312 :                 kunit_remove_resource(test, res);
     769             :         }
     770         333 :         current->kunit_test = NULL;
     771         333 : }
     772             : EXPORT_SYMBOL_GPL(kunit_cleanup);
     773             : 
     774           1 : static 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           1 :         return 0;
     784             : #endif
     785             : }
     786             : late_initcall(kunit_init);
     787             : 
     788           0 : static void __exit kunit_exit(void)
     789             : {
     790           0 :         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           0 : }
     796             : module_exit(kunit_exit);
     797             : 
     798             : MODULE_LICENSE("GPL v2");

Generated by: LCOV version 1.14