1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/reboot.h>
4 #include <kunit/test.h>
5 #include <kunit/attributes.h>
6 #include <linux/glob.h>
7 #include <linux/moduleparam.h>
10 * These symbols point to the .kunit_test_suites section and are defined in
11 * include/asm-generic/vmlinux.lds.h, and consequently must be extern.
13 extern struct kunit_suite
* const __kunit_suites_start
[];
14 extern struct kunit_suite
* const __kunit_suites_end
[];
15 extern struct kunit_suite
* const __kunit_init_suites_start
[];
16 extern struct kunit_suite
* const __kunit_init_suites_end
[];
18 static char *action_param
;
20 module_param_named(action
, action_param
, charp
, 0400);
21 MODULE_PARM_DESC(action
,
22 "Changes KUnit executor behavior, valid values are:\n"
23 "<none>: run the tests like normal\n"
24 "'list' to list test names instead of running them.\n"
25 "'list_attr' to list test names and attributes instead of running them.\n");
27 const char *kunit_action(void)
32 static char *filter_glob_param
;
33 static char *filter_param
;
34 static char *filter_action_param
;
36 module_param_named(filter_glob
, filter_glob_param
, charp
, 0600);
37 MODULE_PARM_DESC(filter_glob
,
38 "Filter which KUnit test suites/tests run at boot-time, e.g. list* or list*.*del_test");
39 module_param_named(filter
, filter_param
, charp
, 0600);
40 MODULE_PARM_DESC(filter
,
41 "Filter which KUnit test suites/tests run at boot-time using attributes, e.g. speed>slow");
42 module_param_named(filter_action
, filter_action_param
, charp
, 0600);
43 MODULE_PARM_DESC(filter_action
,
44 "Changes behavior of filtered tests using attributes, valid values are:\n"
45 "<none>: do not run filtered tests as normal\n"
46 "'skip': skip all filtered tests instead so tests will appear in output\n");
48 const char *kunit_filter_glob(void)
50 return filter_glob_param
;
53 char *kunit_filter(void)
58 char *kunit_filter_action(void)
60 return filter_action_param
;
63 /* glob_match() needs NULL terminated strings, so we need a copy of filter_glob_param. */
64 struct kunit_glob_filter
{
69 /* Split "suite_glob.test_glob" into two. Assumes filter_glob is not empty. */
70 static int kunit_parse_glob_filter(struct kunit_glob_filter
*parsed
,
71 const char *filter_glob
)
73 const char *period
= strchr(filter_glob
, '.');
76 parsed
->suite_glob
= kstrdup(filter_glob
, GFP_KERNEL
);
77 if (!parsed
->suite_glob
)
79 parsed
->test_glob
= NULL
;
83 parsed
->suite_glob
= kstrndup(filter_glob
, period
- filter_glob
, GFP_KERNEL
);
84 if (!parsed
->suite_glob
)
87 parsed
->test_glob
= kstrdup(period
+ 1, GFP_KERNEL
);
88 if (!parsed
->test_glob
) {
89 kfree(parsed
->suite_glob
);
96 /* Create a copy of suite with only tests that match test_glob. */
97 static struct kunit_suite
*
98 kunit_filter_glob_tests(const struct kunit_suite
*const suite
, const char *test_glob
)
101 struct kunit_case
*filtered
, *test_case
;
102 struct kunit_suite
*copy
;
104 kunit_suite_for_each_test_case(suite
, test_case
) {
105 if (!test_glob
|| glob_match(test_glob
, test_case
->name
))
112 copy
= kmemdup(suite
, sizeof(*copy
), GFP_KERNEL
);
114 return ERR_PTR(-ENOMEM
);
116 filtered
= kcalloc(n
+ 1, sizeof(*filtered
), GFP_KERNEL
);
119 return ERR_PTR(-ENOMEM
);
123 kunit_suite_for_each_test_case(suite
, test_case
) {
124 if (!test_glob
|| glob_match(test_glob
, test_case
->name
))
125 filtered
[n
++] = *test_case
;
128 copy
->test_cases
= filtered
;
132 void kunit_free_suite_set(struct kunit_suite_set suite_set
)
134 struct kunit_suite
* const *suites
;
136 for (suites
= suite_set
.start
; suites
< suite_set
.end
; suites
++) {
137 kfree((*suites
)->test_cases
);
140 kfree(suite_set
.start
);
144 * Filter and reallocate test suites. Must return the filtered test suites set
145 * allocated at a valid virtual address or NULL in case of error.
147 struct kunit_suite_set
148 kunit_filter_suites(const struct kunit_suite_set
*suite_set
,
149 const char *filter_glob
,
155 int filter_count
= 0;
156 struct kunit_suite
**copy
, **copy_start
, *filtered_suite
, *new_filtered_suite
;
157 struct kunit_suite_set filtered
= {NULL
, NULL
};
158 struct kunit_glob_filter parsed_glob
;
159 struct kunit_attr_filter
*parsed_filters
= NULL
;
160 struct kunit_suite
* const *suites
;
162 const size_t max
= suite_set
->end
- suite_set
->start
;
164 copy
= kcalloc(max
, sizeof(*filtered
.start
), GFP_KERNEL
);
165 if (!copy
) { /* won't be able to run anything, return an empty set */
171 *err
= kunit_parse_glob_filter(&parsed_glob
, filter_glob
);
176 /* Parse attribute filters */
178 filter_count
= kunit_get_filter_count(filters
);
179 parsed_filters
= kcalloc(filter_count
, sizeof(*parsed_filters
), GFP_KERNEL
);
180 if (!parsed_filters
) {
182 goto free_parsed_glob
;
184 for (j
= 0; j
< filter_count
; j
++)
185 parsed_filters
[j
] = kunit_next_attr_filter(&filters
, err
);
187 goto free_parsed_filters
;
190 for (i
= 0; &suite_set
->start
[i
] != suite_set
->end
; i
++) {
191 filtered_suite
= suite_set
->start
[i
];
193 if (!glob_match(parsed_glob
.suite_glob
, filtered_suite
->name
))
195 filtered_suite
= kunit_filter_glob_tests(filtered_suite
,
196 parsed_glob
.test_glob
);
197 if (IS_ERR(filtered_suite
)) {
198 *err
= PTR_ERR(filtered_suite
);
199 goto free_filtered_suite
;
202 if (filter_count
> 0 && parsed_filters
!= NULL
) {
203 for (k
= 0; k
< filter_count
; k
++) {
204 new_filtered_suite
= kunit_filter_attr_tests(filtered_suite
,
205 parsed_filters
[k
], filter_action
, err
);
207 /* Free previous copy of suite */
208 if (k
> 0 || filter_glob
) {
209 kfree(filtered_suite
->test_cases
);
210 kfree(filtered_suite
);
213 filtered_suite
= new_filtered_suite
;
216 goto free_filtered_suite
;
218 if (IS_ERR(filtered_suite
)) {
219 *err
= PTR_ERR(filtered_suite
);
220 goto free_filtered_suite
;
230 *copy
++ = filtered_suite
;
232 filtered
.start
= copy_start
;
237 for (suites
= copy_start
; suites
< copy
; suites
++) {
238 kfree((*suites
)->test_cases
);
245 kfree(parsed_filters
);
249 kfree(parsed_glob
.suite_glob
);
250 kfree(parsed_glob
.test_glob
);
260 void kunit_exec_run_tests(struct kunit_suite_set
*suite_set
, bool builtin
)
262 size_t num_suites
= suite_set
->end
- suite_set
->start
;
264 if (builtin
|| num_suites
) {
265 pr_info("KTAP version 1\n");
266 pr_info("1..%zu\n", num_suites
);
269 __kunit_test_suites_init(suite_set
->start
, num_suites
);
272 void kunit_exec_list_tests(struct kunit_suite_set
*suite_set
, bool include_attr
)
274 struct kunit_suite
* const *suites
;
275 struct kunit_case
*test_case
;
277 /* Hack: print a ktap header so kunit.py can find the start of KUnit output. */
278 pr_info("KTAP version 1\n");
280 for (suites
= suite_set
->start
; suites
< suite_set
->end
; suites
++) {
281 /* Print suite name and suite attributes */
282 pr_info("%s\n", (*suites
)->name
);
284 kunit_print_attr((void *)(*suites
), false, 0);
286 /* Print test case name and attributes in suite */
287 kunit_suite_for_each_test_case((*suites
), test_case
) {
288 pr_info("%s.%s\n", (*suites
)->name
, test_case
->name
);
290 kunit_print_attr((void *)test_case
, true, 0);
295 struct kunit_suite_set
kunit_merge_suite_sets(struct kunit_suite_set init_suite_set
,
296 struct kunit_suite_set suite_set
)
298 struct kunit_suite_set total_suite_set
= {NULL
, NULL
};
299 struct kunit_suite
**total_suite_start
= NULL
;
300 size_t init_num_suites
, num_suites
, suite_size
;
303 init_num_suites
= init_suite_set
.end
- init_suite_set
.start
;
304 num_suites
= suite_set
.end
- suite_set
.start
;
305 suite_size
= sizeof(suite_set
.start
);
307 /* Allocate memory for array of all kunit suites */
308 total_suite_start
= kmalloc_array(init_num_suites
+ num_suites
, suite_size
, GFP_KERNEL
);
309 if (!total_suite_start
)
310 return total_suite_set
;
312 /* Append and mark init suites and then append all other kunit suites */
313 memcpy(total_suite_start
, init_suite_set
.start
, init_num_suites
* suite_size
);
314 for (i
= 0; i
< init_num_suites
; i
++)
315 total_suite_start
[i
]->is_init
= true;
317 memcpy(total_suite_start
+ init_num_suites
, suite_set
.start
, num_suites
* suite_size
);
319 /* Set kunit suite set start and end */
320 total_suite_set
.start
= total_suite_start
;
321 total_suite_set
.end
= total_suite_start
+ (init_num_suites
+ num_suites
);
323 return total_suite_set
;
326 #if IS_BUILTIN(CONFIG_KUNIT)
328 static char *kunit_shutdown
;
329 core_param(kunit_shutdown
, kunit_shutdown
, charp
, 0644);
331 static void kunit_handle_shutdown(void)
336 if (!strcmp(kunit_shutdown
, "poweroff"))
338 else if (!strcmp(kunit_shutdown
, "halt"))
340 else if (!strcmp(kunit_shutdown
, "reboot"))
341 kernel_restart(NULL
);
345 int kunit_run_all_tests(void)
347 struct kunit_suite_set suite_set
= {NULL
, NULL
};
348 struct kunit_suite_set filtered_suite_set
= {NULL
, NULL
};
349 struct kunit_suite_set init_suite_set
= {
350 __kunit_init_suites_start
, __kunit_init_suites_end
,
352 struct kunit_suite_set normal_suite_set
= {
353 __kunit_suites_start
, __kunit_suites_end
,
355 size_t init_num_suites
= init_suite_set
.end
- init_suite_set
.start
;
358 if (init_num_suites
> 0) {
359 suite_set
= kunit_merge_suite_sets(init_suite_set
, normal_suite_set
);
360 if (!suite_set
.start
)
363 suite_set
= normal_suite_set
;
365 if (!kunit_enabled()) {
366 pr_info("kunit: disabled\n");
370 if (filter_glob_param
|| filter_param
) {
371 filtered_suite_set
= kunit_filter_suites(&suite_set
, filter_glob_param
,
372 filter_param
, filter_action_param
, &err
);
374 /* Free original suite set before using filtered suite set */
375 if (init_num_suites
> 0)
376 kfree(suite_set
.start
);
377 suite_set
= filtered_suite_set
;
380 pr_err("kunit executor: error filtering suites: %d\n", err
);
386 kunit_exec_run_tests(&suite_set
, true);
387 else if (strcmp(action_param
, "list") == 0)
388 kunit_exec_list_tests(&suite_set
, false);
389 else if (strcmp(action_param
, "list_attr") == 0)
390 kunit_exec_list_tests(&suite_set
, true);
392 pr_err("kunit executor: unknown action '%s'\n", action_param
);
395 if (filter_glob_param
|| filter_param
)
396 kunit_free_suite_set(suite_set
);
397 else if (init_num_suites
> 0)
398 /* Don't use kunit_free_suite_set because suites aren't individually allocated */
399 kfree(suite_set
.start
);
402 kunit_handle_shutdown();
406 #if IS_BUILTIN(CONFIG_KUNIT_TEST)
407 #include "executor_test.c"
410 #endif /* IS_BUILTIN(CONFIG_KUNIT) */