LCOV - code coverage report
Current view: top level - lib/kunit - test.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 176 230 76.5 %
Date: 2022-12-09 01:23:36 Functions: 20 28 71.4 %

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

Generated by: LCOV version 1.14