1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Base unit test (KUnit) API. |
4 | * |
5 | * Copyright (C) 2019, Google LLC. |
6 | * Author: Brendan Higgins <brendanhiggins@google.com> |
7 | */ |
8 | |
9 | #include <kunit/resource.h> |
10 | #include <kunit/test.h> |
11 | #include <kunit/test-bug.h> |
12 | #include <kunit/attributes.h> |
13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> |
15 | #include <linux/moduleparam.h> |
16 | #include <linux/mutex.h> |
17 | #include <linux/panic.h> |
18 | #include <linux/sched/debug.h> |
19 | #include <linux/sched.h> |
20 | #include <linux/mm.h> |
21 | |
22 | #include "debugfs.h" |
23 | #include "device-impl.h" |
24 | #include "hooks-impl.h" |
25 | #include "string-stream.h" |
26 | #include "try-catch-impl.h" |
27 | |
28 | static DEFINE_MUTEX(kunit_run_lock); |
29 | |
30 | /* |
31 | * Hook to fail the current test and print an error message to the log. |
32 | */ |
33 | void __printf(3, 4) __kunit_fail_current_test_impl(const char *file, int line, const char *fmt, ...) |
34 | { |
35 | va_list args; |
36 | int len; |
37 | char *buffer; |
38 | |
39 | if (!current->kunit_test) |
40 | return; |
41 | |
42 | kunit_set_failure(current->kunit_test); |
43 | |
44 | /* kunit_err() only accepts literals, so evaluate the args first. */ |
45 | va_start(args, fmt); |
46 | len = vsnprintf(NULL, size: 0, fmt, args) + 1; |
47 | va_end(args); |
48 | |
49 | buffer = kunit_kmalloc(current->kunit_test, size: len, GFP_KERNEL); |
50 | if (!buffer) |
51 | return; |
52 | |
53 | va_start(args, fmt); |
54 | vsnprintf(buf: buffer, size: len, fmt, args); |
55 | va_end(args); |
56 | |
57 | kunit_err(current->kunit_test, "%s:%d: %s" , file, line, buffer); |
58 | kunit_kfree(current->kunit_test, ptr: buffer); |
59 | } |
60 | |
61 | /* |
62 | * Enable KUnit tests to run. |
63 | */ |
64 | #ifdef CONFIG_KUNIT_DEFAULT_ENABLED |
65 | static bool enable_param = true; |
66 | #else |
67 | static bool enable_param; |
68 | #endif |
69 | module_param_named(enable, enable_param, bool, 0); |
70 | MODULE_PARM_DESC(enable, "Enable KUnit tests" ); |
71 | |
72 | /* |
73 | * KUnit statistic mode: |
74 | * 0 - disabled |
75 | * 1 - only when there is more than one subtest |
76 | * 2 - enabled |
77 | */ |
78 | static int kunit_stats_enabled = 1; |
79 | module_param_named(stats_enabled, kunit_stats_enabled, int, 0644); |
80 | MODULE_PARM_DESC(stats_enabled, |
81 | "Print test stats: never (0), only for multiple subtests (1), or always (2)" ); |
82 | |
83 | struct kunit_result_stats { |
84 | unsigned long passed; |
85 | unsigned long skipped; |
86 | unsigned long failed; |
87 | unsigned long total; |
88 | }; |
89 | |
90 | static bool kunit_should_print_stats(struct kunit_result_stats stats) |
91 | { |
92 | if (kunit_stats_enabled == 0) |
93 | return false; |
94 | |
95 | if (kunit_stats_enabled == 2) |
96 | return true; |
97 | |
98 | return (stats.total > 1); |
99 | } |
100 | |
101 | static void kunit_print_test_stats(struct kunit *test, |
102 | struct kunit_result_stats stats) |
103 | { |
104 | if (!kunit_should_print_stats(stats)) |
105 | return; |
106 | |
107 | kunit_log(KERN_INFO, test, |
108 | KUNIT_SUBTEST_INDENT |
109 | "# %s: pass:%lu fail:%lu skip:%lu total:%lu" , |
110 | test->name, |
111 | stats.passed, |
112 | stats.failed, |
113 | stats.skipped, |
114 | stats.total); |
115 | } |
116 | |
117 | /* Append formatted message to log. */ |
118 | void kunit_log_append(struct string_stream *log, const char *fmt, ...) |
119 | { |
120 | va_list args; |
121 | |
122 | if (!log) |
123 | return; |
124 | |
125 | va_start(args, fmt); |
126 | string_stream_vadd(stream: log, fmt, args); |
127 | va_end(args); |
128 | } |
129 | EXPORT_SYMBOL_GPL(kunit_log_append); |
130 | |
131 | size_t kunit_suite_num_test_cases(struct kunit_suite *suite) |
132 | { |
133 | struct kunit_case *test_case; |
134 | size_t len = 0; |
135 | |
136 | kunit_suite_for_each_test_case(suite, test_case) |
137 | len++; |
138 | |
139 | return len; |
140 | } |
141 | EXPORT_SYMBOL_GPL(kunit_suite_num_test_cases); |
142 | |
143 | /* Currently supported test levels */ |
144 | enum { |
145 | KUNIT_LEVEL_SUITE = 0, |
146 | KUNIT_LEVEL_CASE, |
147 | KUNIT_LEVEL_CASE_PARAM, |
148 | }; |
149 | |
150 | static void kunit_print_suite_start(struct kunit_suite *suite) |
151 | { |
152 | /* |
153 | * We do not log the test suite header as doing so would |
154 | * mean debugfs display would consist of the test suite |
155 | * header prior to individual test results. |
156 | * Hence directly printk the suite status, and we will |
157 | * separately seq_printf() the suite header for the debugfs |
158 | * representation. |
159 | */ |
160 | pr_info(KUNIT_SUBTEST_INDENT "KTAP version 1\n" ); |
161 | pr_info(KUNIT_SUBTEST_INDENT "# Subtest: %s\n" , |
162 | suite->name); |
163 | kunit_print_attr(test_or_suite: (void *)suite, is_test: false, test_level: KUNIT_LEVEL_CASE); |
164 | pr_info(KUNIT_SUBTEST_INDENT "1..%zd\n" , |
165 | kunit_suite_num_test_cases(suite)); |
166 | } |
167 | |
168 | static void kunit_print_ok_not_ok(struct kunit *test, |
169 | unsigned int test_level, |
170 | enum kunit_status status, |
171 | size_t test_number, |
172 | const char *description, |
173 | const char *directive) |
174 | { |
175 | const char * = (status == KUNIT_SKIPPED) ? " # SKIP " : "" ; |
176 | const char *directive_body = (status == KUNIT_SKIPPED) ? directive : "" ; |
177 | |
178 | /* |
179 | * When test is NULL assume that results are from the suite |
180 | * and today suite results are expected at level 0 only. |
181 | */ |
182 | WARN(!test && test_level, "suite test level can't be %u!\n" , test_level); |
183 | |
184 | /* |
185 | * We do not log the test suite results as doing so would |
186 | * mean debugfs display would consist of an incorrect test |
187 | * number. Hence directly printk the suite result, and we will |
188 | * separately seq_printf() the suite results for the debugfs |
189 | * representation. |
190 | */ |
191 | if (!test) |
192 | pr_info("%s %zd %s%s%s\n" , |
193 | kunit_status_to_ok_not_ok(status), |
194 | test_number, description, directive_header, |
195 | directive_body); |
196 | else |
197 | kunit_log(KERN_INFO, test, |
198 | "%*s%s %zd %s%s%s" , |
199 | KUNIT_INDENT_LEN * test_level, "" , |
200 | kunit_status_to_ok_not_ok(status), |
201 | test_number, description, directive_header, |
202 | directive_body); |
203 | } |
204 | |
205 | enum kunit_status kunit_suite_has_succeeded(struct kunit_suite *suite) |
206 | { |
207 | const struct kunit_case *test_case; |
208 | enum kunit_status status = KUNIT_SKIPPED; |
209 | |
210 | if (suite->suite_init_err) |
211 | return KUNIT_FAILURE; |
212 | |
213 | kunit_suite_for_each_test_case(suite, test_case) { |
214 | if (test_case->status == KUNIT_FAILURE) |
215 | return KUNIT_FAILURE; |
216 | else if (test_case->status == KUNIT_SUCCESS) |
217 | status = KUNIT_SUCCESS; |
218 | } |
219 | |
220 | return status; |
221 | } |
222 | EXPORT_SYMBOL_GPL(kunit_suite_has_succeeded); |
223 | |
224 | static size_t kunit_suite_counter = 1; |
225 | |
226 | static void kunit_print_suite_end(struct kunit_suite *suite) |
227 | { |
228 | kunit_print_ok_not_ok(NULL, test_level: KUNIT_LEVEL_SUITE, |
229 | status: kunit_suite_has_succeeded(suite), |
230 | test_number: kunit_suite_counter++, |
231 | description: suite->name, |
232 | directive: suite->status_comment); |
233 | } |
234 | |
235 | unsigned int kunit_test_case_num(struct kunit_suite *suite, |
236 | struct kunit_case *test_case) |
237 | { |
238 | struct kunit_case *tc; |
239 | unsigned int i = 1; |
240 | |
241 | kunit_suite_for_each_test_case(suite, tc) { |
242 | if (tc == test_case) |
243 | return i; |
244 | i++; |
245 | } |
246 | |
247 | return 0; |
248 | } |
249 | EXPORT_SYMBOL_GPL(kunit_test_case_num); |
250 | |
251 | static void kunit_print_string_stream(struct kunit *test, |
252 | struct string_stream *stream) |
253 | { |
254 | struct string_stream_fragment *fragment; |
255 | char *buf; |
256 | |
257 | if (string_stream_is_empty(stream)) |
258 | return; |
259 | |
260 | buf = string_stream_get_string(stream); |
261 | if (!buf) { |
262 | kunit_err(test, |
263 | "Could not allocate buffer, dumping stream:\n" ); |
264 | list_for_each_entry(fragment, &stream->fragments, node) { |
265 | kunit_err(test, "%s" , fragment->fragment); |
266 | } |
267 | kunit_err(test, "\n" ); |
268 | } else { |
269 | kunit_err(test, "%s" , buf); |
270 | kfree(objp: buf); |
271 | } |
272 | } |
273 | |
274 | static void kunit_fail(struct kunit *test, const struct kunit_loc *loc, |
275 | enum kunit_assert_type type, const struct kunit_assert *assert, |
276 | assert_format_t assert_format, const struct va_format *message) |
277 | { |
278 | struct string_stream *stream; |
279 | |
280 | kunit_set_failure(test); |
281 | |
282 | stream = kunit_alloc_string_stream(test, GFP_KERNEL); |
283 | if (IS_ERR(ptr: stream)) { |
284 | WARN(true, |
285 | "Could not allocate stream to print failed assertion in %s:%d\n" , |
286 | loc->file, |
287 | loc->line); |
288 | return; |
289 | } |
290 | |
291 | kunit_assert_prologue(loc, type, stream); |
292 | assert_format(assert, message, stream); |
293 | |
294 | kunit_print_string_stream(test, stream); |
295 | |
296 | kunit_free_string_stream(test, stream); |
297 | } |
298 | |
299 | void __noreturn __kunit_abort(struct kunit *test) |
300 | { |
301 | kunit_try_catch_throw(try_catch: &test->try_catch); /* Does not return. */ |
302 | |
303 | /* |
304 | * Throw could not abort from test. |
305 | * |
306 | * XXX: we should never reach this line! As kunit_try_catch_throw is |
307 | * marked __noreturn. |
308 | */ |
309 | WARN_ONCE(true, "Throw could not abort from test!\n" ); |
310 | } |
311 | EXPORT_SYMBOL_GPL(__kunit_abort); |
312 | |
313 | void __kunit_do_failed_assertion(struct kunit *test, |
314 | const struct kunit_loc *loc, |
315 | enum kunit_assert_type type, |
316 | const struct kunit_assert *assert, |
317 | assert_format_t assert_format, |
318 | const char *fmt, ...) |
319 | { |
320 | va_list args; |
321 | struct va_format message; |
322 | va_start(args, fmt); |
323 | |
324 | message.fmt = fmt; |
325 | message.va = &args; |
326 | |
327 | kunit_fail(test, loc, type, assert, assert_format, message: &message); |
328 | |
329 | va_end(args); |
330 | } |
331 | EXPORT_SYMBOL_GPL(__kunit_do_failed_assertion); |
332 | |
333 | void kunit_init_test(struct kunit *test, const char *name, struct string_stream *log) |
334 | { |
335 | spin_lock_init(&test->lock); |
336 | INIT_LIST_HEAD(list: &test->resources); |
337 | test->name = name; |
338 | test->log = log; |
339 | if (test->log) |
340 | string_stream_clear(stream: log); |
341 | test->status = KUNIT_SUCCESS; |
342 | test->status_comment[0] = '\0'; |
343 | } |
344 | EXPORT_SYMBOL_GPL(kunit_init_test); |
345 | |
346 | /* Only warn when a test takes more than twice the threshold */ |
347 | #define KUNIT_SPEED_WARNING_MULTIPLIER 2 |
348 | |
349 | /* Slow tests are defined as taking more than 1s */ |
350 | #define KUNIT_SPEED_SLOW_THRESHOLD_S 1 |
351 | |
352 | #define KUNIT_SPEED_SLOW_WARNING_THRESHOLD_S \ |
353 | (KUNIT_SPEED_WARNING_MULTIPLIER * KUNIT_SPEED_SLOW_THRESHOLD_S) |
354 | |
355 | #define s_to_timespec64(s) ns_to_timespec64((s) * NSEC_PER_SEC) |
356 | |
357 | static void kunit_run_case_check_speed(struct kunit *test, |
358 | struct kunit_case *test_case, |
359 | struct timespec64 duration) |
360 | { |
361 | struct timespec64 slow_thr = |
362 | s_to_timespec64(KUNIT_SPEED_SLOW_WARNING_THRESHOLD_S); |
363 | enum kunit_speed speed = test_case->attr.speed; |
364 | |
365 | if (timespec64_compare(lhs: &duration, rhs: &slow_thr) < 0) |
366 | return; |
367 | |
368 | if (speed == KUNIT_SPEED_VERY_SLOW || speed == KUNIT_SPEED_SLOW) |
369 | return; |
370 | |
371 | kunit_warn(test, |
372 | "Test should be marked slow (runtime: %lld.%09lds)" , |
373 | duration.tv_sec, duration.tv_nsec); |
374 | } |
375 | |
376 | /* |
377 | * Initializes and runs test case. Does not clean up or do post validations. |
378 | */ |
379 | static void kunit_run_case_internal(struct kunit *test, |
380 | struct kunit_suite *suite, |
381 | struct kunit_case *test_case) |
382 | { |
383 | struct timespec64 start, end; |
384 | |
385 | if (suite->init) { |
386 | int ret; |
387 | |
388 | ret = suite->init(test); |
389 | if (ret) { |
390 | kunit_err(test, "failed to initialize: %d\n" , ret); |
391 | kunit_set_failure(test); |
392 | return; |
393 | } |
394 | } |
395 | |
396 | ktime_get_ts64(ts: &start); |
397 | |
398 | test_case->run_case(test); |
399 | |
400 | ktime_get_ts64(ts: &end); |
401 | |
402 | kunit_run_case_check_speed(test, test_case, duration: timespec64_sub(lhs: end, rhs: start)); |
403 | } |
404 | |
405 | static void kunit_case_internal_cleanup(struct kunit *test) |
406 | { |
407 | kunit_cleanup(test); |
408 | } |
409 | |
410 | /* |
411 | * Performs post validations and cleanup after a test case was run. |
412 | * XXX: Should ONLY BE CALLED AFTER kunit_run_case_internal! |
413 | */ |
414 | static void kunit_run_case_cleanup(struct kunit *test, |
415 | struct kunit_suite *suite) |
416 | { |
417 | if (suite->exit) |
418 | suite->exit(test); |
419 | |
420 | kunit_case_internal_cleanup(test); |
421 | } |
422 | |
423 | struct kunit_try_catch_context { |
424 | struct kunit *test; |
425 | struct kunit_suite *suite; |
426 | struct kunit_case *test_case; |
427 | }; |
428 | |
429 | static void kunit_try_run_case(void *data) |
430 | { |
431 | struct kunit_try_catch_context *ctx = data; |
432 | struct kunit *test = ctx->test; |
433 | struct kunit_suite *suite = ctx->suite; |
434 | struct kunit_case *test_case = ctx->test_case; |
435 | |
436 | current->kunit_test = test; |
437 | |
438 | /* |
439 | * kunit_run_case_internal may encounter a fatal error; if it does, |
440 | * abort will be called, this thread will exit, and finally the parent |
441 | * thread will resume control and handle any necessary clean up. |
442 | */ |
443 | kunit_run_case_internal(test, suite, test_case); |
444 | } |
445 | |
446 | static void kunit_try_run_case_cleanup(void *data) |
447 | { |
448 | struct kunit_try_catch_context *ctx = data; |
449 | struct kunit *test = ctx->test; |
450 | struct kunit_suite *suite = ctx->suite; |
451 | |
452 | current->kunit_test = test; |
453 | |
454 | kunit_run_case_cleanup(test, suite); |
455 | } |
456 | |
457 | static void kunit_catch_run_case_cleanup(void *data) |
458 | { |
459 | struct kunit_try_catch_context *ctx = data; |
460 | struct kunit *test = ctx->test; |
461 | int try_exit_code = kunit_try_catch_get_result(try_catch: &test->try_catch); |
462 | |
463 | /* It is always a failure if cleanup aborts. */ |
464 | kunit_set_failure(test); |
465 | |
466 | if (try_exit_code) { |
467 | /* |
468 | * Test case could not finish, we have no idea what state it is |
469 | * in, so don't do clean up. |
470 | */ |
471 | if (try_exit_code == -ETIMEDOUT) { |
472 | kunit_err(test, "test case cleanup timed out\n" ); |
473 | /* |
474 | * Unknown internal error occurred preventing test case from |
475 | * running, so there is nothing to clean up. |
476 | */ |
477 | } else { |
478 | kunit_err(test, "internal error occurred during test case cleanup: %d\n" , |
479 | try_exit_code); |
480 | } |
481 | return; |
482 | } |
483 | |
484 | kunit_err(test, "test aborted during cleanup. continuing without cleaning up\n" ); |
485 | } |
486 | |
487 | |
488 | static void kunit_catch_run_case(void *data) |
489 | { |
490 | struct kunit_try_catch_context *ctx = data; |
491 | struct kunit *test = ctx->test; |
492 | int try_exit_code = kunit_try_catch_get_result(try_catch: &test->try_catch); |
493 | |
494 | if (try_exit_code) { |
495 | kunit_set_failure(test); |
496 | /* |
497 | * Test case could not finish, we have no idea what state it is |
498 | * in, so don't do clean up. |
499 | */ |
500 | if (try_exit_code == -ETIMEDOUT) { |
501 | kunit_err(test, "test case timed out\n" ); |
502 | /* |
503 | * Unknown internal error occurred preventing test case from |
504 | * running, so there is nothing to clean up. |
505 | */ |
506 | } else { |
507 | kunit_err(test, "internal error occurred preventing test case from running: %d\n" , |
508 | try_exit_code); |
509 | } |
510 | return; |
511 | } |
512 | } |
513 | |
514 | /* |
515 | * Performs all logic to run a test case. It also catches most errors that |
516 | * occur in a test case and reports them as failures. |
517 | */ |
518 | static void kunit_run_case_catch_errors(struct kunit_suite *suite, |
519 | struct kunit_case *test_case, |
520 | struct kunit *test) |
521 | { |
522 | struct kunit_try_catch_context context; |
523 | struct kunit_try_catch *try_catch; |
524 | |
525 | try_catch = &test->try_catch; |
526 | |
527 | kunit_try_catch_init(try_catch, |
528 | test, |
529 | try: kunit_try_run_case, |
530 | catch: kunit_catch_run_case); |
531 | context.test = test; |
532 | context.suite = suite; |
533 | context.test_case = test_case; |
534 | kunit_try_catch_run(try_catch, context: &context); |
535 | |
536 | /* Now run the cleanup */ |
537 | kunit_try_catch_init(try_catch, |
538 | test, |
539 | try: kunit_try_run_case_cleanup, |
540 | catch: kunit_catch_run_case_cleanup); |
541 | kunit_try_catch_run(try_catch, context: &context); |
542 | |
543 | /* Propagate the parameter result to the test case. */ |
544 | if (test->status == KUNIT_FAILURE) |
545 | test_case->status = KUNIT_FAILURE; |
546 | else if (test_case->status != KUNIT_FAILURE && test->status == KUNIT_SUCCESS) |
547 | test_case->status = KUNIT_SUCCESS; |
548 | } |
549 | |
550 | static void kunit_print_suite_stats(struct kunit_suite *suite, |
551 | struct kunit_result_stats suite_stats, |
552 | struct kunit_result_stats param_stats) |
553 | { |
554 | if (kunit_should_print_stats(stats: suite_stats)) { |
555 | kunit_log(KERN_INFO, suite, |
556 | "# %s: pass:%lu fail:%lu skip:%lu total:%lu" , |
557 | suite->name, |
558 | suite_stats.passed, |
559 | suite_stats.failed, |
560 | suite_stats.skipped, |
561 | suite_stats.total); |
562 | } |
563 | |
564 | if (kunit_should_print_stats(stats: param_stats)) { |
565 | kunit_log(KERN_INFO, suite, |
566 | "# Totals: pass:%lu fail:%lu skip:%lu total:%lu" , |
567 | param_stats.passed, |
568 | param_stats.failed, |
569 | param_stats.skipped, |
570 | param_stats.total); |
571 | } |
572 | } |
573 | |
574 | static void kunit_update_stats(struct kunit_result_stats *stats, |
575 | enum kunit_status status) |
576 | { |
577 | switch (status) { |
578 | case KUNIT_SUCCESS: |
579 | stats->passed++; |
580 | break; |
581 | case KUNIT_SKIPPED: |
582 | stats->skipped++; |
583 | break; |
584 | case KUNIT_FAILURE: |
585 | stats->failed++; |
586 | break; |
587 | } |
588 | |
589 | stats->total++; |
590 | } |
591 | |
592 | static void kunit_accumulate_stats(struct kunit_result_stats *total, |
593 | struct kunit_result_stats add) |
594 | { |
595 | total->passed += add.passed; |
596 | total->skipped += add.skipped; |
597 | total->failed += add.failed; |
598 | total->total += add.total; |
599 | } |
600 | |
601 | int kunit_run_tests(struct kunit_suite *suite) |
602 | { |
603 | char param_desc[KUNIT_PARAM_DESC_SIZE]; |
604 | struct kunit_case *test_case; |
605 | struct kunit_result_stats suite_stats = { 0 }; |
606 | struct kunit_result_stats total_stats = { 0 }; |
607 | |
608 | /* Taint the kernel so we know we've run tests. */ |
609 | add_taint(TAINT_TEST, LOCKDEP_STILL_OK); |
610 | |
611 | if (suite->suite_init) { |
612 | suite->suite_init_err = suite->suite_init(suite); |
613 | if (suite->suite_init_err) { |
614 | kunit_err(suite, KUNIT_SUBTEST_INDENT |
615 | "# failed to initialize (%d)" , suite->suite_init_err); |
616 | goto suite_end; |
617 | } |
618 | } |
619 | |
620 | kunit_print_suite_start(suite); |
621 | |
622 | kunit_suite_for_each_test_case(suite, test_case) { |
623 | struct kunit test = { .param_value = NULL, .param_index = 0 }; |
624 | struct kunit_result_stats param_stats = { 0 }; |
625 | |
626 | kunit_init_test(&test, test_case->name, test_case->log); |
627 | if (test_case->status == KUNIT_SKIPPED) { |
628 | /* Test marked as skip */ |
629 | test.status = KUNIT_SKIPPED; |
630 | kunit_update_stats(stats: ¶m_stats, status: test.status); |
631 | } else if (!test_case->generate_params) { |
632 | /* Non-parameterised test. */ |
633 | test_case->status = KUNIT_SKIPPED; |
634 | kunit_run_case_catch_errors(suite, test_case, test: &test); |
635 | kunit_update_stats(stats: ¶m_stats, status: test.status); |
636 | } else { |
637 | /* Get initial param. */ |
638 | param_desc[0] = '\0'; |
639 | test.param_value = test_case->generate_params(NULL, param_desc); |
640 | test_case->status = KUNIT_SKIPPED; |
641 | kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT |
642 | "KTAP version 1\n" ); |
643 | kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT |
644 | "# Subtest: %s" , test_case->name); |
645 | |
646 | while (test.param_value) { |
647 | kunit_run_case_catch_errors(suite, test_case, test: &test); |
648 | |
649 | if (param_desc[0] == '\0') { |
650 | snprintf(buf: param_desc, size: sizeof(param_desc), |
651 | fmt: "param-%d" , test.param_index); |
652 | } |
653 | |
654 | kunit_print_ok_not_ok(test: &test, test_level: KUNIT_LEVEL_CASE_PARAM, |
655 | status: test.status, |
656 | test_number: test.param_index + 1, |
657 | description: param_desc, |
658 | directive: test.status_comment); |
659 | |
660 | kunit_update_stats(stats: ¶m_stats, status: test.status); |
661 | |
662 | /* Get next param. */ |
663 | param_desc[0] = '\0'; |
664 | test.param_value = test_case->generate_params(test.param_value, param_desc); |
665 | test.param_index++; |
666 | test.status = KUNIT_SUCCESS; |
667 | test.status_comment[0] = '\0'; |
668 | test.priv = NULL; |
669 | } |
670 | } |
671 | |
672 | kunit_print_attr(test_or_suite: (void *)test_case, is_test: true, test_level: KUNIT_LEVEL_CASE); |
673 | |
674 | kunit_print_test_stats(test: &test, stats: param_stats); |
675 | |
676 | kunit_print_ok_not_ok(test: &test, test_level: KUNIT_LEVEL_CASE, status: test_case->status, |
677 | test_number: kunit_test_case_num(suite, test_case), |
678 | description: test_case->name, |
679 | directive: test.status_comment); |
680 | |
681 | kunit_update_stats(stats: &suite_stats, status: test_case->status); |
682 | kunit_accumulate_stats(total: &total_stats, add: param_stats); |
683 | } |
684 | |
685 | if (suite->suite_exit) |
686 | suite->suite_exit(suite); |
687 | |
688 | kunit_print_suite_stats(suite, suite_stats, param_stats: total_stats); |
689 | suite_end: |
690 | kunit_print_suite_end(suite); |
691 | |
692 | return 0; |
693 | } |
694 | EXPORT_SYMBOL_GPL(kunit_run_tests); |
695 | |
696 | static void kunit_init_suite(struct kunit_suite *suite) |
697 | { |
698 | kunit_debugfs_create_suite(suite); |
699 | suite->status_comment[0] = '\0'; |
700 | suite->suite_init_err = 0; |
701 | |
702 | if (suite->log) |
703 | string_stream_clear(stream: suite->log); |
704 | } |
705 | |
706 | bool kunit_enabled(void) |
707 | { |
708 | return enable_param; |
709 | } |
710 | |
711 | int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_suites) |
712 | { |
713 | unsigned int i; |
714 | |
715 | if (!kunit_enabled() && num_suites > 0) { |
716 | pr_info("kunit: disabled\n" ); |
717 | return 0; |
718 | } |
719 | |
720 | kunit_suite_counter = 1; |
721 | |
722 | /* Use mutex lock to guard against running tests concurrently. */ |
723 | if (mutex_lock_interruptible(&kunit_run_lock)) { |
724 | pr_err("kunit: test interrupted\n" ); |
725 | return -EINTR; |
726 | } |
727 | static_branch_inc(&kunit_running); |
728 | |
729 | for (i = 0; i < num_suites; i++) { |
730 | kunit_init_suite(suite: suites[i]); |
731 | kunit_run_tests(suites[i]); |
732 | } |
733 | |
734 | static_branch_dec(&kunit_running); |
735 | mutex_unlock(lock: &kunit_run_lock); |
736 | return 0; |
737 | } |
738 | EXPORT_SYMBOL_GPL(__kunit_test_suites_init); |
739 | |
740 | static void kunit_exit_suite(struct kunit_suite *suite) |
741 | { |
742 | kunit_debugfs_destroy_suite(suite); |
743 | } |
744 | |
745 | void __kunit_test_suites_exit(struct kunit_suite **suites, int num_suites) |
746 | { |
747 | unsigned int i; |
748 | |
749 | if (!kunit_enabled()) |
750 | return; |
751 | |
752 | for (i = 0; i < num_suites; i++) |
753 | kunit_exit_suite(suite: suites[i]); |
754 | } |
755 | EXPORT_SYMBOL_GPL(__kunit_test_suites_exit); |
756 | |
757 | #ifdef CONFIG_MODULES |
758 | static void kunit_module_init(struct module *mod) |
759 | { |
760 | struct kunit_suite_set suite_set, filtered_set; |
761 | struct kunit_suite_set normal_suite_set = { |
762 | mod->kunit_suites, mod->kunit_suites + mod->num_kunit_suites, |
763 | }; |
764 | struct kunit_suite_set init_suite_set = { |
765 | mod->kunit_init_suites, mod->kunit_init_suites + mod->num_kunit_init_suites, |
766 | }; |
767 | const char *action = kunit_action(); |
768 | int err = 0; |
769 | |
770 | if (mod->num_kunit_init_suites > 0) |
771 | suite_set = kunit_merge_suite_sets(init_suite_set, suite_set: normal_suite_set); |
772 | else |
773 | suite_set = normal_suite_set; |
774 | |
775 | filtered_set = kunit_filter_suites(suite_set: &suite_set, |
776 | filter_glob: kunit_filter_glob() ?: "*.*" , |
777 | filters: kunit_filter(), filter_action: kunit_filter_action(), |
778 | err: &err); |
779 | if (err) |
780 | pr_err("kunit module: error filtering suites: %d\n" , err); |
781 | |
782 | mod->kunit_suites = (struct kunit_suite **)filtered_set.start; |
783 | mod->num_kunit_suites = filtered_set.end - filtered_set.start; |
784 | |
785 | if (mod->num_kunit_init_suites > 0) |
786 | kfree(objp: suite_set.start); |
787 | |
788 | if (!action) |
789 | kunit_exec_run_tests(suite_set: &filtered_set, builtin: false); |
790 | else if (!strcmp(action, "list" )) |
791 | kunit_exec_list_tests(suite_set: &filtered_set, include_attr: false); |
792 | else if (!strcmp(action, "list_attr" )) |
793 | kunit_exec_list_tests(suite_set: &filtered_set, include_attr: true); |
794 | else |
795 | pr_err("kunit: unknown action '%s'\n" , action); |
796 | } |
797 | |
798 | static void kunit_module_exit(struct module *mod) |
799 | { |
800 | struct kunit_suite_set suite_set = { |
801 | mod->kunit_suites, mod->kunit_suites + mod->num_kunit_suites, |
802 | }; |
803 | const char *action = kunit_action(); |
804 | |
805 | /* |
806 | * Check if the start address is a valid virtual address to detect |
807 | * if the module load sequence has failed and the suite set has not |
808 | * been initialized and filtered. |
809 | */ |
810 | if (!suite_set.start || !virt_addr_valid(suite_set.start)) |
811 | return; |
812 | |
813 | if (!action) |
814 | __kunit_test_suites_exit(mod->kunit_suites, |
815 | mod->num_kunit_suites); |
816 | |
817 | kunit_free_suite_set(suite_set); |
818 | } |
819 | |
820 | static int kunit_module_notify(struct notifier_block *nb, unsigned long val, |
821 | void *data) |
822 | { |
823 | struct module *mod = data; |
824 | |
825 | switch (val) { |
826 | case MODULE_STATE_LIVE: |
827 | kunit_module_init(mod); |
828 | break; |
829 | case MODULE_STATE_GOING: |
830 | kunit_module_exit(mod); |
831 | break; |
832 | case MODULE_STATE_COMING: |
833 | break; |
834 | case MODULE_STATE_UNFORMED: |
835 | break; |
836 | } |
837 | |
838 | return 0; |
839 | } |
840 | |
841 | static struct notifier_block kunit_mod_nb = { |
842 | .notifier_call = kunit_module_notify, |
843 | .priority = 0, |
844 | }; |
845 | #endif |
846 | |
847 | KUNIT_DEFINE_ACTION_WRAPPER(kfree_action_wrapper, kfree, const void *) |
848 | |
849 | void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp) |
850 | { |
851 | void *data; |
852 | |
853 | data = kmalloc_array(n, size, flags: gfp); |
854 | |
855 | if (!data) |
856 | return NULL; |
857 | |
858 | if (kunit_add_action_or_reset(test, action: kfree_action_wrapper, ctx: data) != 0) |
859 | return NULL; |
860 | |
861 | return data; |
862 | } |
863 | EXPORT_SYMBOL_GPL(kunit_kmalloc_array); |
864 | |
865 | void kunit_kfree(struct kunit *test, const void *ptr) |
866 | { |
867 | if (!ptr) |
868 | return; |
869 | |
870 | kunit_release_action(test, action: kfree_action_wrapper, ctx: (void *)ptr); |
871 | } |
872 | EXPORT_SYMBOL_GPL(kunit_kfree); |
873 | |
874 | void kunit_cleanup(struct kunit *test) |
875 | { |
876 | struct kunit_resource *res; |
877 | unsigned long flags; |
878 | |
879 | /* |
880 | * test->resources is a stack - each allocation must be freed in the |
881 | * reverse order from which it was added since one resource may depend |
882 | * on another for its entire lifetime. |
883 | * Also, we cannot use the normal list_for_each constructs, even the |
884 | * safe ones because *arbitrary* nodes may be deleted when |
885 | * kunit_resource_free is called; the list_for_each_safe variants only |
886 | * protect against the current node being deleted, not the next. |
887 | */ |
888 | while (true) { |
889 | spin_lock_irqsave(&test->lock, flags); |
890 | if (list_empty(head: &test->resources)) { |
891 | spin_unlock_irqrestore(lock: &test->lock, flags); |
892 | break; |
893 | } |
894 | res = list_last_entry(&test->resources, |
895 | struct kunit_resource, |
896 | node); |
897 | /* |
898 | * Need to unlock here as a resource may remove another |
899 | * resource, and this can't happen if the test->lock |
900 | * is held. |
901 | */ |
902 | spin_unlock_irqrestore(lock: &test->lock, flags); |
903 | kunit_remove_resource(test, res); |
904 | } |
905 | current->kunit_test = NULL; |
906 | } |
907 | EXPORT_SYMBOL_GPL(kunit_cleanup); |
908 | |
909 | static int __init kunit_init(void) |
910 | { |
911 | /* Install the KUnit hook functions. */ |
912 | kunit_install_hooks(); |
913 | |
914 | kunit_debugfs_init(); |
915 | |
916 | kunit_bus_init(); |
917 | #ifdef CONFIG_MODULES |
918 | return register_module_notifier(nb: &kunit_mod_nb); |
919 | #else |
920 | return 0; |
921 | #endif |
922 | } |
923 | late_initcall(kunit_init); |
924 | |
925 | static void __exit kunit_exit(void) |
926 | { |
927 | memset(&kunit_hooks, 0, sizeof(kunit_hooks)); |
928 | #ifdef CONFIG_MODULES |
929 | unregister_module_notifier(nb: &kunit_mod_nb); |
930 | #endif |
931 | |
932 | kunit_bus_shutdown(); |
933 | |
934 | kunit_debugfs_cleanup(); |
935 | } |
936 | module_exit(kunit_exit); |
937 | |
938 | MODULE_LICENSE("GPL v2" ); |
939 | |