Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.9.
  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) */