linux/lib/kunit/executor.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3#include <linux/reboot.h>
   4#include <kunit/test.h>
   5#include <linux/glob.h>
   6#include <linux/moduleparam.h>
   7
   8/*
   9 * These symbols point to the .kunit_test_suites section and are defined in
  10 * include/asm-generic/vmlinux.lds.h, and consequently must be extern.
  11 */
  12extern struct kunit_suite * const * const __kunit_suites_start[];
  13extern struct kunit_suite * const * const __kunit_suites_end[];
  14
  15#if IS_BUILTIN(CONFIG_KUNIT)
  16
  17static char *filter_glob_param;
  18module_param_named(filter_glob, filter_glob_param, charp, 0);
  19MODULE_PARM_DESC(filter_glob,
  20                "Filter which KUnit test suites run at boot-time, e.g. list*");
  21
  22static char *kunit_shutdown;
  23core_param(kunit_shutdown, kunit_shutdown, charp, 0644);
  24
  25static struct kunit_suite * const *
  26kunit_filter_subsuite(struct kunit_suite * const * const subsuite,
  27                        const char *filter_glob)
  28{
  29        int i, n = 0;
  30        struct kunit_suite **filtered;
  31
  32        n = 0;
  33        for (i = 0; subsuite[i] != NULL; ++i) {
  34                if (glob_match(filter_glob, subsuite[i]->name))
  35                        ++n;
  36        }
  37
  38        if (n == 0)
  39                return NULL;
  40
  41        filtered = kmalloc_array(n + 1, sizeof(*filtered), GFP_KERNEL);
  42        if (!filtered)
  43                return NULL;
  44
  45        n = 0;
  46        for (i = 0; subsuite[i] != NULL; ++i) {
  47                if (glob_match(filter_glob, subsuite[i]->name))
  48                        filtered[n++] = subsuite[i];
  49        }
  50        filtered[n] = NULL;
  51
  52        return filtered;
  53}
  54
  55struct suite_set {
  56        struct kunit_suite * const * const *start;
  57        struct kunit_suite * const * const *end;
  58};
  59
  60static struct suite_set kunit_filter_suites(const struct suite_set *suite_set,
  61                                            const char *filter_glob)
  62{
  63        int i;
  64        struct kunit_suite * const **copy, * const *filtered_subsuite;
  65        struct suite_set filtered;
  66
  67        const size_t max = suite_set->end - suite_set->start;
  68
  69        copy = kmalloc_array(max, sizeof(*filtered.start), GFP_KERNEL);
  70        filtered.start = copy;
  71        if (!copy) { /* won't be able to run anything, return an empty set */
  72                filtered.end = copy;
  73                return filtered;
  74        }
  75
  76        for (i = 0; i < max; ++i) {
  77                filtered_subsuite = kunit_filter_subsuite(suite_set->start[i], filter_glob);
  78                if (filtered_subsuite)
  79                        *copy++ = filtered_subsuite;
  80        }
  81        filtered.end = copy;
  82        return filtered;
  83}
  84
  85static void kunit_handle_shutdown(void)
  86{
  87        if (!kunit_shutdown)
  88                return;
  89
  90        if (!strcmp(kunit_shutdown, "poweroff"))
  91                kernel_power_off();
  92        else if (!strcmp(kunit_shutdown, "halt"))
  93                kernel_halt();
  94        else if (!strcmp(kunit_shutdown, "reboot"))
  95                kernel_restart(NULL);
  96
  97}
  98
  99static void kunit_print_tap_header(struct suite_set *suite_set)
 100{
 101        struct kunit_suite * const * const *suites, * const *subsuite;
 102        int num_of_suites = 0;
 103
 104        for (suites = suite_set->start; suites < suite_set->end; suites++)
 105                for (subsuite = *suites; *subsuite != NULL; subsuite++)
 106                        num_of_suites++;
 107
 108        pr_info("TAP version 14\n");
 109        pr_info("1..%d\n", num_of_suites);
 110}
 111
 112int kunit_run_all_tests(void)
 113{
 114        struct kunit_suite * const * const *suites;
 115        struct suite_set suite_set = {
 116                .start = __kunit_suites_start,
 117                .end = __kunit_suites_end,
 118        };
 119
 120        if (filter_glob_param)
 121                suite_set = kunit_filter_suites(&suite_set, filter_glob_param);
 122
 123        kunit_print_tap_header(&suite_set);
 124
 125        for (suites = suite_set.start; suites < suite_set.end; suites++)
 126                __kunit_test_suites_init(*suites);
 127
 128        if (filter_glob_param) { /* a copy was made of each array */
 129                for (suites = suite_set.start; suites < suite_set.end; suites++)
 130                        kfree(*suites);
 131                kfree(suite_set.start);
 132        }
 133
 134        kunit_handle_shutdown();
 135
 136        return 0;
 137}
 138
 139#if IS_BUILTIN(CONFIG_KUNIT_TEST)
 140#include "executor_test.c"
 141#endif
 142
 143#endif /* IS_BUILTIN(CONFIG_KUNIT) */
 144