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 */ 12 extern struct kunit_suite * const * const __kunit_suites_start[]; 13 extern struct kunit_suite * const * const __kunit_suites_end[]; 14 15 #if IS_BUILTIN(CONFIG_KUNIT) 16 17 static char *filter_glob_param; 18 static char *action_param; 19 20 module_param_named(filter_glob, filter_glob_param, charp, 0); 21 MODULE_PARM_DESC(filter_glob, 22 "Filter which KUnit test suites/tests run at boot-time, e.g. list* or list*.*del_test"); 23 module_param_named(action, action_param, charp, 0); 24 MODULE_PARM_DESC(action, 25 "Changes KUnit executor behavior, valid values are:\n" 26 "<none>: run the tests like normal\n" 27 "'list' to list test names instead of running them.\n"); 28 29 /* glob_match() needs NULL terminated strings, so we need a copy of filter_glob_param. */ 30 struct kunit_test_filter { 31 char *suite_glob; 32 char *test_glob; 33 }; 34 35 /* Split "suite_glob.test_glob" into two. Assumes filter_glob is not empty. */ 36 static void kunit_parse_filter_glob(struct kunit_test_filter *parsed, 37 const char *filter_glob) 38 { 39 const int len = strlen(filter_glob); 40 const char *period = strchr(filter_glob, '.'); 41 42 if (!period) { 43 parsed->suite_glob = kzalloc(len + 1, GFP_KERNEL); 44 parsed->test_glob = NULL; 45 strcpy(parsed->suite_glob, filter_glob); 46 return; 47 } 48 49 parsed->suite_glob = kzalloc(period - filter_glob + 1, GFP_KERNEL); 50 parsed->test_glob = kzalloc(len - (period - filter_glob) + 1, GFP_KERNEL); 51 52 strncpy(parsed->suite_glob, filter_glob, period - filter_glob); 53 strncpy(parsed->test_glob, period + 1, len - (period - filter_glob)); 54 } 55 56 /* Create a copy of suite with only tests that match test_glob. */ 57 static struct kunit_suite * 58 kunit_filter_tests(struct kunit_suite *const suite, const char *test_glob) 59 { 60 int n = 0; 61 struct kunit_case *filtered, *test_case; 62 struct kunit_suite *copy; 63 64 kunit_suite_for_each_test_case(suite, test_case) { 65 if (!test_glob || glob_match(test_glob, test_case->name)) 66 ++n; 67 } 68 69 if (n == 0) 70 return NULL; 71 72 /* Use memcpy to workaround copy->name being const. */ 73 copy = kmalloc(sizeof(*copy), GFP_KERNEL); 74 memcpy(copy, suite, sizeof(*copy)); 75 76 filtered = kcalloc(n + 1, sizeof(*filtered), GFP_KERNEL); 77 78 n = 0; 79 kunit_suite_for_each_test_case(suite, test_case) { 80 if (!test_glob || glob_match(test_glob, test_case->name)) 81 filtered[n++] = *test_case; 82 } 83 84 copy->test_cases = filtered; 85 return copy; 86 } 87 88 static char *kunit_shutdown; 89 core_param(kunit_shutdown, kunit_shutdown, charp, 0644); 90 91 static struct kunit_suite * const * 92 kunit_filter_subsuite(struct kunit_suite * const * const subsuite, 93 struct kunit_test_filter *filter) 94 { 95 int i, n = 0; 96 struct kunit_suite **filtered, *filtered_suite; 97 98 n = 0; 99 for (i = 0; subsuite[i]; ++i) { 100 if (glob_match(filter->suite_glob, subsuite[i]->name)) 101 ++n; 102 } 103 104 if (n == 0) 105 return NULL; 106 107 filtered = kmalloc_array(n + 1, sizeof(*filtered), GFP_KERNEL); 108 if (!filtered) 109 return NULL; 110 111 n = 0; 112 for (i = 0; subsuite[i] != NULL; ++i) { 113 if (!glob_match(filter->suite_glob, subsuite[i]->name)) 114 continue; 115 filtered_suite = kunit_filter_tests(subsuite[i], filter->test_glob); 116 if (filtered_suite) 117 filtered[n++] = filtered_suite; 118 } 119 filtered[n] = NULL; 120 121 return filtered; 122 } 123 124 struct suite_set { 125 struct kunit_suite * const * const *start; 126 struct kunit_suite * const * const *end; 127 }; 128 129 static void kunit_free_subsuite(struct kunit_suite * const *subsuite) 130 { 131 unsigned int i; 132 133 for (i = 0; subsuite[i]; i++) 134 kfree(subsuite[i]); 135 136 kfree(subsuite); 137 } 138 139 static void kunit_free_suite_set(struct suite_set suite_set) 140 { 141 struct kunit_suite * const * const *suites; 142 143 for (suites = suite_set.start; suites < suite_set.end; suites++) 144 kunit_free_subsuite(*suites); 145 kfree(suite_set.start); 146 } 147 148 static struct suite_set kunit_filter_suites(const struct suite_set *suite_set, 149 const char *filter_glob) 150 { 151 int i; 152 struct kunit_suite * const **copy, * const *filtered_subsuite; 153 struct suite_set filtered; 154 struct kunit_test_filter filter; 155 156 const size_t max = suite_set->end - suite_set->start; 157 158 copy = kmalloc_array(max, sizeof(*filtered.start), GFP_KERNEL); 159 filtered.start = copy; 160 if (!copy) { /* won't be able to run anything, return an empty set */ 161 filtered.end = copy; 162 return filtered; 163 } 164 165 kunit_parse_filter_glob(&filter, filter_glob); 166 167 for (i = 0; i < max; ++i) { 168 filtered_subsuite = kunit_filter_subsuite(suite_set->start[i], &filter); 169 if (filtered_subsuite) 170 *copy++ = filtered_subsuite; 171 } 172 filtered.end = copy; 173 174 kfree(filter.suite_glob); 175 kfree(filter.test_glob); 176 return filtered; 177 } 178 179 static void kunit_handle_shutdown(void) 180 { 181 if (!kunit_shutdown) 182 return; 183 184 if (!strcmp(kunit_shutdown, "poweroff")) 185 kernel_power_off(); 186 else if (!strcmp(kunit_shutdown, "halt")) 187 kernel_halt(); 188 else if (!strcmp(kunit_shutdown, "reboot")) 189 kernel_restart(NULL); 190 191 } 192 193 static void kunit_print_tap_header(struct suite_set *suite_set) 194 { 195 struct kunit_suite * const * const *suites, * const *subsuite; 196 int num_of_suites = 0; 197 198 for (suites = suite_set->start; suites < suite_set->end; suites++) 199 for (subsuite = *suites; *subsuite != NULL; subsuite++) 200 num_of_suites++; 201 202 pr_info("TAP version 14\n"); 203 pr_info("1..%d\n", num_of_suites); 204 } 205 206 static void kunit_exec_run_tests(struct suite_set *suite_set) 207 { 208 struct kunit_suite * const * const *suites; 209 210 kunit_print_tap_header(suite_set); 211 212 for (suites = suite_set->start; suites < suite_set->end; suites++) 213 __kunit_test_suites_init(*suites); 214 } 215 216 static void kunit_exec_list_tests(struct suite_set *suite_set) 217 { 218 unsigned int i; 219 struct kunit_suite * const * const *suites; 220 struct kunit_case *test_case; 221 222 /* Hack: print a tap header so kunit.py can find the start of KUnit output. */ 223 pr_info("TAP version 14\n"); 224 225 for (suites = suite_set->start; suites < suite_set->end; suites++) 226 for (i = 0; (*suites)[i] != NULL; i++) { 227 kunit_suite_for_each_test_case((*suites)[i], test_case) { 228 pr_info("%s.%s\n", (*suites)[i]->name, test_case->name); 229 } 230 } 231 } 232 233 int kunit_run_all_tests(void) 234 { 235 struct suite_set suite_set = { 236 .start = __kunit_suites_start, 237 .end = __kunit_suites_end, 238 }; 239 240 if (filter_glob_param) 241 suite_set = kunit_filter_suites(&suite_set, filter_glob_param); 242 243 if (!action_param) 244 kunit_exec_run_tests(&suite_set); 245 else if (strcmp(action_param, "list") == 0) 246 kunit_exec_list_tests(&suite_set); 247 else 248 pr_err("kunit executor: unknown action '%s'\n", action_param); 249 250 if (filter_glob_param) { /* a copy was made of each array */ 251 kunit_free_suite_set(suite_set); 252 } 253 254 kunit_handle_shutdown(); 255 256 return 0; 257 } 258 259 #if IS_BUILTIN(CONFIG_KUNIT_TEST) 260 #include "executor_test.c" 261 #endif 262 263 #endif /* IS_BUILTIN(CONFIG_KUNIT) */ 264