0001
0002
0003 #include <linux/reboot.h>
0004 #include <kunit/test.h>
0005 #include <linux/glob.h>
0006 #include <linux/moduleparam.h>
0007
0008
0009
0010
0011
0012 extern struct kunit_suite * const __kunit_suites_start[];
0013 extern struct kunit_suite * const __kunit_suites_end[];
0014
0015 #if IS_BUILTIN(CONFIG_KUNIT)
0016
0017 static char *filter_glob_param;
0018 static char *action_param;
0019
0020 module_param_named(filter_glob, filter_glob_param, charp, 0);
0021 MODULE_PARM_DESC(filter_glob,
0022 "Filter which KUnit test suites/tests run at boot-time, e.g. list* or list*.*del_test");
0023 module_param_named(action, action_param, charp, 0);
0024 MODULE_PARM_DESC(action,
0025 "Changes KUnit executor behavior, valid values are:\n"
0026 "<none>: run the tests like normal\n"
0027 "'list' to list test names instead of running them.\n");
0028
0029
0030 struct kunit_test_filter {
0031 char *suite_glob;
0032 char *test_glob;
0033 };
0034
0035
0036 static void kunit_parse_filter_glob(struct kunit_test_filter *parsed,
0037 const char *filter_glob)
0038 {
0039 const int len = strlen(filter_glob);
0040 const char *period = strchr(filter_glob, '.');
0041
0042 if (!period) {
0043 parsed->suite_glob = kzalloc(len + 1, GFP_KERNEL);
0044 parsed->test_glob = NULL;
0045 strcpy(parsed->suite_glob, filter_glob);
0046 return;
0047 }
0048
0049 parsed->suite_glob = kzalloc(period - filter_glob + 1, GFP_KERNEL);
0050 parsed->test_glob = kzalloc(len - (period - filter_glob) + 1, GFP_KERNEL);
0051
0052 strncpy(parsed->suite_glob, filter_glob, period - filter_glob);
0053 strncpy(parsed->test_glob, period + 1, len - (period - filter_glob));
0054 }
0055
0056
0057 static struct kunit_suite *
0058 kunit_filter_tests(const struct kunit_suite *const suite, const char *test_glob)
0059 {
0060 int n = 0;
0061 struct kunit_case *filtered, *test_case;
0062 struct kunit_suite *copy;
0063
0064 kunit_suite_for_each_test_case(suite, test_case) {
0065 if (!test_glob || glob_match(test_glob, test_case->name))
0066 ++n;
0067 }
0068
0069 if (n == 0)
0070 return NULL;
0071
0072 copy = kmemdup(suite, sizeof(*copy), GFP_KERNEL);
0073 if (!copy)
0074 return ERR_PTR(-ENOMEM);
0075
0076 filtered = kcalloc(n + 1, sizeof(*filtered), GFP_KERNEL);
0077 if (!filtered) {
0078 kfree(copy);
0079 return ERR_PTR(-ENOMEM);
0080 }
0081
0082 n = 0;
0083 kunit_suite_for_each_test_case(suite, test_case) {
0084 if (!test_glob || glob_match(test_glob, test_case->name))
0085 filtered[n++] = *test_case;
0086 }
0087
0088 copy->test_cases = filtered;
0089 return copy;
0090 }
0091
0092 static char *kunit_shutdown;
0093 core_param(kunit_shutdown, kunit_shutdown, charp, 0644);
0094
0095
0096 struct suite_set {
0097 struct kunit_suite * const *start;
0098 struct kunit_suite * const *end;
0099 };
0100
0101 static void kunit_free_suite_set(struct suite_set suite_set)
0102 {
0103 struct kunit_suite * const *suites;
0104
0105 for (suites = suite_set.start; suites < suite_set.end; suites++)
0106 kfree(*suites);
0107 kfree(suite_set.start);
0108 }
0109
0110 static struct suite_set kunit_filter_suites(const struct suite_set *suite_set,
0111 const char *filter_glob,
0112 int *err)
0113 {
0114 int i;
0115 struct kunit_suite **copy, *filtered_suite;
0116 struct suite_set filtered;
0117 struct kunit_test_filter filter;
0118
0119 const size_t max = suite_set->end - suite_set->start;
0120
0121 copy = kmalloc_array(max, sizeof(*filtered.start), GFP_KERNEL);
0122 filtered.start = copy;
0123 if (!copy) {
0124 filtered.end = copy;
0125 return filtered;
0126 }
0127
0128 kunit_parse_filter_glob(&filter, filter_glob);
0129
0130 for (i = 0; &suite_set->start[i] != suite_set->end; i++) {
0131 if (!glob_match(filter.suite_glob, suite_set->start[i]->name))
0132 continue;
0133
0134 filtered_suite = kunit_filter_tests(suite_set->start[i], filter.test_glob);
0135 if (IS_ERR(filtered_suite)) {
0136 *err = PTR_ERR(filtered_suite);
0137 return filtered;
0138 }
0139 if (!filtered_suite)
0140 continue;
0141
0142 *copy++ = filtered_suite;
0143 }
0144 filtered.end = copy;
0145
0146 kfree(filter.suite_glob);
0147 kfree(filter.test_glob);
0148 return filtered;
0149 }
0150
0151 static void kunit_handle_shutdown(void)
0152 {
0153 if (!kunit_shutdown)
0154 return;
0155
0156 if (!strcmp(kunit_shutdown, "poweroff"))
0157 kernel_power_off();
0158 else if (!strcmp(kunit_shutdown, "halt"))
0159 kernel_halt();
0160 else if (!strcmp(kunit_shutdown, "reboot"))
0161 kernel_restart(NULL);
0162
0163 }
0164
0165 static void kunit_exec_run_tests(struct suite_set *suite_set)
0166 {
0167 size_t num_suites = suite_set->end - suite_set->start;
0168
0169 pr_info("TAP version 14\n");
0170 pr_info("1..%zu\n", num_suites);
0171
0172 __kunit_test_suites_init(suite_set->start, num_suites);
0173 }
0174
0175 static void kunit_exec_list_tests(struct suite_set *suite_set)
0176 {
0177 struct kunit_suite * const *suites;
0178 struct kunit_case *test_case;
0179
0180
0181 pr_info("TAP version 14\n");
0182
0183 for (suites = suite_set->start; suites < suite_set->end; suites++)
0184 kunit_suite_for_each_test_case((*suites), test_case) {
0185 pr_info("%s.%s\n", (*suites)->name, test_case->name);
0186 }
0187 }
0188
0189 int kunit_run_all_tests(void)
0190 {
0191 struct suite_set suite_set = {__kunit_suites_start, __kunit_suites_end};
0192 int err = 0;
0193
0194 if (filter_glob_param) {
0195 suite_set = kunit_filter_suites(&suite_set, filter_glob_param, &err);
0196 if (err) {
0197 pr_err("kunit executor: error filtering suites: %d\n", err);
0198 goto out;
0199 }
0200 }
0201
0202 if (!action_param)
0203 kunit_exec_run_tests(&suite_set);
0204 else if (strcmp(action_param, "list") == 0)
0205 kunit_exec_list_tests(&suite_set);
0206 else
0207 pr_err("kunit executor: unknown action '%s'\n", action_param);
0208
0209 if (filter_glob_param) {
0210 kunit_free_suite_set(suite_set);
0211 }
0212
0213 out:
0214 kunit_handle_shutdown();
0215 return err;
0216 }
0217
0218 #if IS_BUILTIN(CONFIG_KUNIT_TEST)
0219 #include "executor_test.c"
0220 #endif
0221
0222 #endif