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