xref: /linux-6.15/lib/kunit/executor.c (revision 31691914)
1aac35468SAlan Maguire // SPDX-License-Identifier: GPL-2.0
2aac35468SAlan Maguire 
3b6d5799bSDavid Gow #include <linux/reboot.h>
4aac35468SAlan Maguire #include <kunit/test.h>
539e92cb1SRae Moar #include <kunit/attributes.h>
65d31f71eSDaniel Latypov #include <linux/glob.h>
75d31f71eSDaniel Latypov #include <linux/moduleparam.h>
8aac35468SAlan Maguire 
9aac35468SAlan Maguire /*
10aac35468SAlan Maguire  * These symbols point to the .kunit_test_suites section and are defined in
11aac35468SAlan Maguire  * include/asm-generic/vmlinux.lds.h, and consequently must be extern.
12aac35468SAlan Maguire  */
13e5857d39SDaniel Latypov extern struct kunit_suite * const __kunit_suites_start[];
14e5857d39SDaniel Latypov extern struct kunit_suite * const __kunit_suites_end[];
15d81f0d7bSRae Moar extern struct kunit_suite * const __kunit_init_suites_start[];
16d81f0d7bSRae Moar extern struct kunit_suite * const __kunit_init_suites_end[];
17aac35468SAlan Maguire 
1818258c60SJanusz Krzysztofik static char *action_param;
1918258c60SJanusz Krzysztofik 
2018258c60SJanusz Krzysztofik module_param_named(action, action_param, charp, 0400);
2118258c60SJanusz Krzysztofik MODULE_PARM_DESC(action,
2218258c60SJanusz Krzysztofik 		 "Changes KUnit executor behavior, valid values are:\n"
2318258c60SJanusz Krzysztofik 		 "<none>: run the tests like normal\n"
2418258c60SJanusz Krzysztofik 		 "'list' to list test names instead of running them.\n"
2518258c60SJanusz Krzysztofik 		 "'list_attr' to list test names and attributes instead of running them.\n");
2618258c60SJanusz Krzysztofik 
kunit_action(void)2718258c60SJanusz Krzysztofik const char *kunit_action(void)
2818258c60SJanusz Krzysztofik {
2918258c60SJanusz Krzysztofik 	return action_param;
3018258c60SJanusz Krzysztofik }
3118258c60SJanusz Krzysztofik 
32*31691914SStanislav Kinsburskii /*
33*31691914SStanislav Kinsburskii  * Run KUnit tests after initialization
34*31691914SStanislav Kinsburskii  */
35*31691914SStanislav Kinsburskii #ifdef CONFIG_KUNIT_AUTORUN_ENABLED
36*31691914SStanislav Kinsburskii static bool autorun_param = true;
37*31691914SStanislav Kinsburskii #else
38*31691914SStanislav Kinsburskii static bool autorun_param;
39*31691914SStanislav Kinsburskii #endif
40*31691914SStanislav Kinsburskii module_param_named(autorun, autorun_param, bool, 0);
41*31691914SStanislav Kinsburskii MODULE_PARM_DESC(autorun, "Run KUnit tests after initialization");
42*31691914SStanislav Kinsburskii 
kunit_autorun(void)43*31691914SStanislav Kinsburskii bool kunit_autorun(void)
44*31691914SStanislav Kinsburskii {
45*31691914SStanislav Kinsburskii 	return autorun_param;
46*31691914SStanislav Kinsburskii }
47*31691914SStanislav Kinsburskii 
481d71307aSDaniel Latypov static char *filter_glob_param;
49529534e8SRae Moar static char *filter_param;
50529534e8SRae Moar static char *filter_action_param;
519c6b0e1dSDaniel Latypov 
52a0dd82d6SLucas De Marchi module_param_named(filter_glob, filter_glob_param, charp, 0600);
535d31f71eSDaniel Latypov MODULE_PARM_DESC(filter_glob,
54a127b154SDaniel Latypov 		"Filter which KUnit test suites/tests run at boot-time, e.g. list* or list*.*del_test");
55a0dd82d6SLucas De Marchi module_param_named(filter, filter_param, charp, 0600);
56529534e8SRae Moar MODULE_PARM_DESC(filter,
57529534e8SRae Moar 		"Filter which KUnit test suites/tests run at boot-time using attributes, e.g. speed>slow");
58a0dd82d6SLucas De Marchi module_param_named(filter_action, filter_action_param, charp, 0600);
59529534e8SRae Moar MODULE_PARM_DESC(filter_action,
60529534e8SRae Moar 		"Changes behavior of filtered tests using attributes, valid values are:\n"
61529534e8SRae Moar 		"<none>: do not run filtered tests as normal\n"
62529534e8SRae Moar 		"'skip': skip all filtered tests instead so tests will appear in output\n");
63a127b154SDaniel Latypov 
kunit_filter_glob(void)64b67abaadSJanusz Krzysztofik const char *kunit_filter_glob(void)
65b67abaadSJanusz Krzysztofik {
66b67abaadSJanusz Krzysztofik 	return filter_glob_param;
67b67abaadSJanusz Krzysztofik }
68b67abaadSJanusz Krzysztofik 
kunit_filter(void)69b67abaadSJanusz Krzysztofik char *kunit_filter(void)
70b67abaadSJanusz Krzysztofik {
71b67abaadSJanusz Krzysztofik 	return filter_param;
72b67abaadSJanusz Krzysztofik }
73b67abaadSJanusz Krzysztofik 
kunit_filter_action(void)74b67abaadSJanusz Krzysztofik char *kunit_filter_action(void)
75b67abaadSJanusz Krzysztofik {
76b67abaadSJanusz Krzysztofik 	return filter_action_param;
77b67abaadSJanusz Krzysztofik }
78b67abaadSJanusz Krzysztofik 
79a127b154SDaniel Latypov /* glob_match() needs NULL terminated strings, so we need a copy of filter_glob_param. */
80529534e8SRae Moar struct kunit_glob_filter {
81a127b154SDaniel Latypov 	char *suite_glob;
82a127b154SDaniel Latypov 	char *test_glob;
83a127b154SDaniel Latypov };
84a127b154SDaniel Latypov 
85a127b154SDaniel Latypov /* Split "suite_glob.test_glob" into two. Assumes filter_glob is not empty. */
kunit_parse_glob_filter(struct kunit_glob_filter * parsed,const char * filter_glob)862b56a4b7SJinjie Ruan static int kunit_parse_glob_filter(struct kunit_glob_filter *parsed,
87a127b154SDaniel Latypov 				    const char *filter_glob)
88a127b154SDaniel Latypov {
89a127b154SDaniel Latypov 	const char *period = strchr(filter_glob, '.');
90a127b154SDaniel Latypov 
91a127b154SDaniel Latypov 	if (!period) {
927554a7b9SKees Cook 		parsed->suite_glob = kstrdup(filter_glob, GFP_KERNEL);
932b56a4b7SJinjie Ruan 		if (!parsed->suite_glob)
942b56a4b7SJinjie Ruan 			return -ENOMEM;
95a127b154SDaniel Latypov 		parsed->test_glob = NULL;
962b56a4b7SJinjie Ruan 		return 0;
97a127b154SDaniel Latypov 	}
98a127b154SDaniel Latypov 
997554a7b9SKees Cook 	parsed->suite_glob = kstrndup(filter_glob, period - filter_glob, GFP_KERNEL);
1002b56a4b7SJinjie Ruan 	if (!parsed->suite_glob)
1012b56a4b7SJinjie Ruan 		return -ENOMEM;
1022b56a4b7SJinjie Ruan 
1037554a7b9SKees Cook 	parsed->test_glob = kstrdup(period + 1, GFP_KERNEL);
1042b56a4b7SJinjie Ruan 	if (!parsed->test_glob) {
1052b56a4b7SJinjie Ruan 		kfree(parsed->suite_glob);
1062b56a4b7SJinjie Ruan 		return -ENOMEM;
1072b56a4b7SJinjie Ruan 	}
108a127b154SDaniel Latypov 
1092b56a4b7SJinjie Ruan 	return 0;
110a127b154SDaniel Latypov }
111a127b154SDaniel Latypov 
112a127b154SDaniel Latypov /* Create a copy of suite with only tests that match test_glob. */
113a127b154SDaniel Latypov static struct kunit_suite *
kunit_filter_glob_tests(const struct kunit_suite * const suite,const char * test_glob)114529534e8SRae Moar kunit_filter_glob_tests(const struct kunit_suite *const suite, const char *test_glob)
115a127b154SDaniel Latypov {
116a127b154SDaniel Latypov 	int n = 0;
117a127b154SDaniel Latypov 	struct kunit_case *filtered, *test_case;
118a127b154SDaniel Latypov 	struct kunit_suite *copy;
119a127b154SDaniel Latypov 
120a127b154SDaniel Latypov 	kunit_suite_for_each_test_case(suite, test_case) {
121a127b154SDaniel Latypov 		if (!test_glob || glob_match(test_glob, test_case->name))
122a127b154SDaniel Latypov 			++n;
123a127b154SDaniel Latypov 	}
124a127b154SDaniel Latypov 
125a127b154SDaniel Latypov 	if (n == 0)
126a127b154SDaniel Latypov 		return NULL;
127a127b154SDaniel Latypov 
128d2fbdde8SDaniel Latypov 	copy = kmemdup(suite, sizeof(*copy), GFP_KERNEL);
129a02353f4SDaniel Latypov 	if (!copy)
130a02353f4SDaniel Latypov 		return ERR_PTR(-ENOMEM);
131a127b154SDaniel Latypov 
132a127b154SDaniel Latypov 	filtered = kcalloc(n + 1, sizeof(*filtered), GFP_KERNEL);
13394681e28SDavid Gow 	if (!filtered) {
13494681e28SDavid Gow 		kfree(copy);
135a02353f4SDaniel Latypov 		return ERR_PTR(-ENOMEM);
13694681e28SDavid Gow 	}
137a127b154SDaniel Latypov 
138a127b154SDaniel Latypov 	n = 0;
139a127b154SDaniel Latypov 	kunit_suite_for_each_test_case(suite, test_case) {
140a127b154SDaniel Latypov 		if (!test_glob || glob_match(test_glob, test_case->name))
141a127b154SDaniel Latypov 			filtered[n++] = *test_case;
142a127b154SDaniel Latypov 	}
143a127b154SDaniel Latypov 
144a127b154SDaniel Latypov 	copy->test_cases = filtered;
145a127b154SDaniel Latypov 	return copy;
146a127b154SDaniel Latypov }
1475d31f71eSDaniel Latypov 
kunit_free_suite_set(struct kunit_suite_set suite_set)148b67abaadSJanusz Krzysztofik void kunit_free_suite_set(struct kunit_suite_set suite_set)
149a127b154SDaniel Latypov {
150e5857d39SDaniel Latypov 	struct kunit_suite * const *suites;
151a127b154SDaniel Latypov 
152a6074cf0SJinjie Ruan 	for (suites = suite_set.start; suites < suite_set.end; suites++) {
153a6074cf0SJinjie Ruan 		kfree((*suites)->test_cases);
154e5857d39SDaniel Latypov 		kfree(*suites);
155a6074cf0SJinjie Ruan 	}
156a127b154SDaniel Latypov 	kfree(suite_set.start);
157a127b154SDaniel Latypov }
158a127b154SDaniel Latypov 
159a1af6a2bSMarco Pagani /*
160a1af6a2bSMarco Pagani  * Filter and reallocate test suites. Must return the filtered test suites set
161a1af6a2bSMarco Pagani  * allocated at a valid virtual address or NULL in case of error.
162a1af6a2bSMarco Pagani  */
163b67abaadSJanusz Krzysztofik struct kunit_suite_set
kunit_filter_suites(const struct kunit_suite_set * suite_set,const char * filter_glob,char * filters,char * filter_action,int * err)164c95e7c05SJanusz Krzysztofik kunit_filter_suites(const struct kunit_suite_set *suite_set,
165a02353f4SDaniel Latypov 		    const char *filter_glob,
166529534e8SRae Moar 		    char *filters,
167529534e8SRae Moar 		    char *filter_action,
168a02353f4SDaniel Latypov 		    int *err)
1695d31f71eSDaniel Latypov {
1705a175d36SRuan Jinjie 	int i, j, k;
1715a175d36SRuan Jinjie 	int filter_count = 0;
1721c9fd080SRae Moar 	struct kunit_suite **copy, **copy_start, *filtered_suite, *new_filtered_suite;
173c95e7c05SJanusz Krzysztofik 	struct kunit_suite_set filtered = {NULL, NULL};
174529534e8SRae Moar 	struct kunit_glob_filter parsed_glob;
1751c9fd080SRae Moar 	struct kunit_attr_filter *parsed_filters = NULL;
17624de14c9SJinjie Ruan 	struct kunit_suite * const *suites;
1775d31f71eSDaniel Latypov 
1781d71307aSDaniel Latypov 	const size_t max = suite_set->end - suite_set->start;
1795d31f71eSDaniel Latypov 
18024de14c9SJinjie Ruan 	copy = kcalloc(max, sizeof(*filtered.start), GFP_KERNEL);
1815d31f71eSDaniel Latypov 	if (!copy) { /* won't be able to run anything, return an empty set */
1825d31f71eSDaniel Latypov 		return filtered;
1835d31f71eSDaniel Latypov 	}
1841c9fd080SRae Moar 	copy_start = copy;
1855d31f71eSDaniel Latypov 
1862b56a4b7SJinjie Ruan 	if (filter_glob) {
1872b56a4b7SJinjie Ruan 		*err = kunit_parse_glob_filter(&parsed_glob, filter_glob);
1882b56a4b7SJinjie Ruan 		if (*err)
1892b56a4b7SJinjie Ruan 			goto free_copy;
1902b56a4b7SJinjie Ruan 	}
191529534e8SRae Moar 
192529534e8SRae Moar 	/* Parse attribute filters */
193529534e8SRae Moar 	if (filters) {
194529534e8SRae Moar 		filter_count = kunit_get_filter_count(filters);
1951c9fd080SRae Moar 		parsed_filters = kcalloc(filter_count, sizeof(*parsed_filters), GFP_KERNEL);
1961c9fd080SRae Moar 		if (!parsed_filters) {
1979076bc47SJinjie Ruan 			*err = -ENOMEM;
1989076bc47SJinjie Ruan 			goto free_parsed_glob;
1991c9fd080SRae Moar 		}
200529534e8SRae Moar 		for (j = 0; j < filter_count; j++)
201529534e8SRae Moar 			parsed_filters[j] = kunit_next_attr_filter(&filters, err);
202529534e8SRae Moar 		if (*err)
2034b00920dSJinjie Ruan 			goto free_parsed_filters;
204529534e8SRae Moar 	}
205a127b154SDaniel Latypov 
206e5857d39SDaniel Latypov 	for (i = 0; &suite_set->start[i] != suite_set->end; i++) {
207529534e8SRae Moar 		filtered_suite = suite_set->start[i];
208529534e8SRae Moar 		if (filter_glob) {
209529534e8SRae Moar 			if (!glob_match(parsed_glob.suite_glob, filtered_suite->name))
210e5857d39SDaniel Latypov 				continue;
211529534e8SRae Moar 			filtered_suite = kunit_filter_glob_tests(filtered_suite,
212529534e8SRae Moar 					parsed_glob.test_glob);
213e5857d39SDaniel Latypov 			if (IS_ERR(filtered_suite)) {
214e5857d39SDaniel Latypov 				*err = PTR_ERR(filtered_suite);
21524de14c9SJinjie Ruan 				goto free_filtered_suite;
216a02353f4SDaniel Latypov 			}
217529534e8SRae Moar 		}
2181c9fd080SRae Moar 		if (filter_count > 0 && parsed_filters != NULL) {
219529534e8SRae Moar 			for (k = 0; k < filter_count; k++) {
220529534e8SRae Moar 				new_filtered_suite = kunit_filter_attr_tests(filtered_suite,
221529534e8SRae Moar 						parsed_filters[k], filter_action, err);
222529534e8SRae Moar 
223529534e8SRae Moar 				/* Free previous copy of suite */
224abbf7381SRuan Jinjie 				if (k > 0 || filter_glob) {
225abbf7381SRuan Jinjie 					kfree(filtered_suite->test_cases);
226529534e8SRae Moar 					kfree(filtered_suite);
227abbf7381SRuan Jinjie 				}
228abbf7381SRuan Jinjie 
229529534e8SRae Moar 				filtered_suite = new_filtered_suite;
230529534e8SRae Moar 
231529534e8SRae Moar 				if (*err)
23224de14c9SJinjie Ruan 					goto free_filtered_suite;
2334b00920dSJinjie Ruan 
234529534e8SRae Moar 				if (IS_ERR(filtered_suite)) {
235529534e8SRae Moar 					*err = PTR_ERR(filtered_suite);
23624de14c9SJinjie Ruan 					goto free_filtered_suite;
237529534e8SRae Moar 				}
238529534e8SRae Moar 				if (!filtered_suite)
239529534e8SRae Moar 					break;
240529534e8SRae Moar 			}
241529534e8SRae Moar 		}
242529534e8SRae Moar 
243e5857d39SDaniel Latypov 		if (!filtered_suite)
244e5857d39SDaniel Latypov 			continue;
245e5857d39SDaniel Latypov 
246e5857d39SDaniel Latypov 		*copy++ = filtered_suite;
2475d31f71eSDaniel Latypov 	}
2481c9fd080SRae Moar 	filtered.start = copy_start;
2495d31f71eSDaniel Latypov 	filtered.end = copy;
250a127b154SDaniel Latypov 
25124de14c9SJinjie Ruan free_filtered_suite:
25224de14c9SJinjie Ruan 	if (*err) {
25324de14c9SJinjie Ruan 		for (suites = copy_start; suites < copy; suites++) {
25424de14c9SJinjie Ruan 			kfree((*suites)->test_cases);
25524de14c9SJinjie Ruan 			kfree(*suites);
25624de14c9SJinjie Ruan 		}
25724de14c9SJinjie Ruan 	}
25824de14c9SJinjie Ruan 
2594b00920dSJinjie Ruan free_parsed_filters:
2604b00920dSJinjie Ruan 	if (filter_count)
2614b00920dSJinjie Ruan 		kfree(parsed_filters);
262abbf7381SRuan Jinjie 
2634b00920dSJinjie Ruan free_parsed_glob:
264529534e8SRae Moar 	if (filter_glob) {
265529534e8SRae Moar 		kfree(parsed_glob.suite_glob);
266529534e8SRae Moar 		kfree(parsed_glob.test_glob);
267529534e8SRae Moar 	}
268529534e8SRae Moar 
2694b00920dSJinjie Ruan free_copy:
2704b00920dSJinjie Ruan 	if (*err)
271e4467951SJinjie Ruan 		kfree(copy_start);
272529534e8SRae Moar 
2735d31f71eSDaniel Latypov 	return filtered;
2745d31f71eSDaniel Latypov }
2755d31f71eSDaniel Latypov 
kunit_exec_run_tests(struct kunit_suite_set * suite_set,bool builtin)276c95e7c05SJanusz Krzysztofik void kunit_exec_run_tests(struct kunit_suite_set *suite_set, bool builtin)
277aac35468SAlan Maguire {
278e5857d39SDaniel Latypov 	size_t num_suites = suite_set->end - suite_set->start;
279*31691914SStanislav Kinsburskii 	bool autorun = kunit_autorun();
2809c6b0e1dSDaniel Latypov 
281*31691914SStanislav Kinsburskii 	if (autorun && (builtin || num_suites)) {
2826c738b52SRae Moar 		pr_info("KTAP version 1\n");
283e5857d39SDaniel Latypov 		pr_info("1..%zu\n", num_suites);
284c95e7c05SJanusz Krzysztofik 	}
2859c6b0e1dSDaniel Latypov 
286*31691914SStanislav Kinsburskii 	__kunit_test_suites_init(suite_set->start, num_suites, autorun);
2879c6b0e1dSDaniel Latypov }
2889c6b0e1dSDaniel Latypov 
kunit_exec_list_tests(struct kunit_suite_set * suite_set,bool include_attr)28918258c60SJanusz Krzysztofik void kunit_exec_list_tests(struct kunit_suite_set *suite_set, bool include_attr)
2909c6b0e1dSDaniel Latypov {
291e5857d39SDaniel Latypov 	struct kunit_suite * const *suites;
2929c6b0e1dSDaniel Latypov 	struct kunit_case *test_case;
2939c6b0e1dSDaniel Latypov 
2946c738b52SRae Moar 	/* Hack: print a ktap header so kunit.py can find the start of KUnit output. */
2956c738b52SRae Moar 	pr_info("KTAP version 1\n");
2969c6b0e1dSDaniel Latypov 
29739e92cb1SRae Moar 	for (suites = suite_set->start; suites < suite_set->end; suites++) {
29839e92cb1SRae Moar 		/* Print suite name and suite attributes */
29939e92cb1SRae Moar 		pr_info("%s\n", (*suites)->name);
30039e92cb1SRae Moar 		if (include_attr)
30139e92cb1SRae Moar 			kunit_print_attr((void *)(*suites), false, 0);
30239e92cb1SRae Moar 
30339e92cb1SRae Moar 		/* Print test case name and attributes in suite */
304e5857d39SDaniel Latypov 		kunit_suite_for_each_test_case((*suites), test_case) {
305e5857d39SDaniel Latypov 			pr_info("%s.%s\n", (*suites)->name, test_case->name);
30639e92cb1SRae Moar 			if (include_attr)
30739e92cb1SRae Moar 				kunit_print_attr((void *)test_case, true, 0);
30839e92cb1SRae Moar 		}
3099c6b0e1dSDaniel Latypov 	}
3109c6b0e1dSDaniel Latypov }
3119c6b0e1dSDaniel Latypov 
kunit_merge_suite_sets(struct kunit_suite_set init_suite_set,struct kunit_suite_set suite_set)312d81f0d7bSRae Moar struct kunit_suite_set kunit_merge_suite_sets(struct kunit_suite_set init_suite_set,
313d81f0d7bSRae Moar 		struct kunit_suite_set suite_set)
314d81f0d7bSRae Moar {
315d81f0d7bSRae Moar 	struct kunit_suite_set total_suite_set = {NULL, NULL};
316d81f0d7bSRae Moar 	struct kunit_suite **total_suite_start = NULL;
317d81f0d7bSRae Moar 	size_t init_num_suites, num_suites, suite_size;
3186c4ea2f4SRae Moar 	int i = 0;
319d81f0d7bSRae Moar 
320d81f0d7bSRae Moar 	init_num_suites = init_suite_set.end - init_suite_set.start;
321d81f0d7bSRae Moar 	num_suites = suite_set.end - suite_set.start;
322d81f0d7bSRae Moar 	suite_size = sizeof(suite_set.start);
323d81f0d7bSRae Moar 
324d81f0d7bSRae Moar 	/* Allocate memory for array of all kunit suites */
325d81f0d7bSRae Moar 	total_suite_start = kmalloc_array(init_num_suites + num_suites, suite_size, GFP_KERNEL);
326d81f0d7bSRae Moar 	if (!total_suite_start)
327d81f0d7bSRae Moar 		return total_suite_set;
328d81f0d7bSRae Moar 
3296c4ea2f4SRae Moar 	/* Append and mark init suites and then append all other kunit suites */
330d81f0d7bSRae Moar 	memcpy(total_suite_start, init_suite_set.start, init_num_suites * suite_size);
3316c4ea2f4SRae Moar 	for (i = 0; i < init_num_suites; i++)
3326c4ea2f4SRae Moar 		total_suite_start[i]->is_init = true;
3336c4ea2f4SRae Moar 
334d81f0d7bSRae Moar 	memcpy(total_suite_start + init_num_suites, suite_set.start, num_suites * suite_size);
335d81f0d7bSRae Moar 
336d81f0d7bSRae Moar 	/* Set kunit suite set start and end */
337d81f0d7bSRae Moar 	total_suite_set.start = total_suite_start;
338d81f0d7bSRae Moar 	total_suite_set.end = total_suite_start + (init_num_suites + num_suites);
339d81f0d7bSRae Moar 
340d81f0d7bSRae Moar 	return total_suite_set;
341d81f0d7bSRae Moar }
342d81f0d7bSRae Moar 
34318258c60SJanusz Krzysztofik #if IS_BUILTIN(CONFIG_KUNIT)
34418258c60SJanusz Krzysztofik 
345b67abaadSJanusz Krzysztofik static char *kunit_shutdown;
346b67abaadSJanusz Krzysztofik core_param(kunit_shutdown, kunit_shutdown, charp, 0644);
347b67abaadSJanusz Krzysztofik 
kunit_handle_shutdown(void)348b67abaadSJanusz Krzysztofik static void kunit_handle_shutdown(void)
349b67abaadSJanusz Krzysztofik {
350b67abaadSJanusz Krzysztofik 	if (!kunit_shutdown)
351b67abaadSJanusz Krzysztofik 		return;
352b67abaadSJanusz Krzysztofik 
353b67abaadSJanusz Krzysztofik 	if (!strcmp(kunit_shutdown, "poweroff"))
354b67abaadSJanusz Krzysztofik 		kernel_power_off();
355b67abaadSJanusz Krzysztofik 	else if (!strcmp(kunit_shutdown, "halt"))
356b67abaadSJanusz Krzysztofik 		kernel_halt();
357b67abaadSJanusz Krzysztofik 	else if (!strcmp(kunit_shutdown, "reboot"))
358b67abaadSJanusz Krzysztofik 		kernel_restart(NULL);
359b67abaadSJanusz Krzysztofik 
360b67abaadSJanusz Krzysztofik }
361b67abaadSJanusz Krzysztofik 
kunit_run_all_tests(void)3629c6b0e1dSDaniel Latypov int kunit_run_all_tests(void)
3639c6b0e1dSDaniel Latypov {
364d81f0d7bSRae Moar 	struct kunit_suite_set suite_set = {NULL, NULL};
365d81f0d7bSRae Moar 	struct kunit_suite_set filtered_suite_set = {NULL, NULL};
366d81f0d7bSRae Moar 	struct kunit_suite_set init_suite_set = {
367d81f0d7bSRae Moar 		__kunit_init_suites_start, __kunit_init_suites_end,
368d81f0d7bSRae Moar 	};
369d81f0d7bSRae Moar 	struct kunit_suite_set normal_suite_set = {
370c95e7c05SJanusz Krzysztofik 		__kunit_suites_start, __kunit_suites_end,
371c95e7c05SJanusz Krzysztofik 	};
372d81f0d7bSRae Moar 	size_t init_num_suites = init_suite_set.end - init_suite_set.start;
3731b11063dSDaniel Latypov 	int err = 0;
374d81f0d7bSRae Moar 
375d81f0d7bSRae Moar 	if (init_num_suites > 0) {
376d81f0d7bSRae Moar 		suite_set = kunit_merge_suite_sets(init_suite_set, normal_suite_set);
377d81f0d7bSRae Moar 		if (!suite_set.start)
378d81f0d7bSRae Moar 			goto out;
379d81f0d7bSRae Moar 	} else
380d81f0d7bSRae Moar 		suite_set = normal_suite_set;
381d81f0d7bSRae Moar 
382d20a6ba5SJoe Fradley 	if (!kunit_enabled()) {
383d20a6ba5SJoe Fradley 		pr_info("kunit: disabled\n");
384d81f0d7bSRae Moar 		goto free_out;
385d20a6ba5SJoe Fradley 	}
386aac35468SAlan Maguire 
387529534e8SRae Moar 	if (filter_glob_param || filter_param) {
388d81f0d7bSRae Moar 		filtered_suite_set = kunit_filter_suites(&suite_set, filter_glob_param,
389529534e8SRae Moar 				filter_param, filter_action_param, &err);
390d81f0d7bSRae Moar 
391d81f0d7bSRae Moar 		/* Free original suite set before using filtered suite set */
392d81f0d7bSRae Moar 		if (init_num_suites > 0)
393d81f0d7bSRae Moar 			kfree(suite_set.start);
394d81f0d7bSRae Moar 		suite_set = filtered_suite_set;
395d81f0d7bSRae Moar 
396a02353f4SDaniel Latypov 		if (err) {
397a02353f4SDaniel Latypov 			pr_err("kunit executor: error filtering suites: %d\n", err);
398d81f0d7bSRae Moar 			goto free_out;
399a02353f4SDaniel Latypov 		}
400a02353f4SDaniel Latypov 	}
40145dcbb6fSBrendan Higgins 
4029c6b0e1dSDaniel Latypov 	if (!action_param)
403c95e7c05SJanusz Krzysztofik 		kunit_exec_run_tests(&suite_set, true);
4049c6b0e1dSDaniel Latypov 	else if (strcmp(action_param, "list") == 0)
40539e92cb1SRae Moar 		kunit_exec_list_tests(&suite_set, false);
40639e92cb1SRae Moar 	else if (strcmp(action_param, "list_attr") == 0)
40739e92cb1SRae Moar 		kunit_exec_list_tests(&suite_set, true);
4089c6b0e1dSDaniel Latypov 	else
4099c6b0e1dSDaniel Latypov 		pr_err("kunit executor: unknown action '%s'\n", action_param);
410aac35468SAlan Maguire 
411d81f0d7bSRae Moar free_out:
412d81f0d7bSRae Moar 	if (filter_glob_param || filter_param)
413a127b154SDaniel Latypov 		kunit_free_suite_set(suite_set);
414d81f0d7bSRae Moar 	else if (init_num_suites > 0)
415d81f0d7bSRae Moar 		/* Don't use kunit_free_suite_set because suites aren't individually allocated */
416d81f0d7bSRae Moar 		kfree(suite_set.start);
4175d31f71eSDaniel Latypov 
4181b11063dSDaniel Latypov out:
4191b11063dSDaniel Latypov 	kunit_handle_shutdown();
4201b11063dSDaniel Latypov 	return err;
421aac35468SAlan Maguire }
422aac35468SAlan Maguire 
4231d71307aSDaniel Latypov #if IS_BUILTIN(CONFIG_KUNIT_TEST)
4241d71307aSDaniel Latypov #include "executor_test.c"
4251d71307aSDaniel Latypov #endif
4261d71307aSDaniel Latypov 
427aac35468SAlan Maguire #endif /* IS_BUILTIN(CONFIG_KUNIT) */
428