blob: 2b488384cab07015efb393d785c8f85f564a0adf [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001// 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/test.h>
10#include <linux/kernel.h>
11#include <linux/sched/debug.h>
12
13#include "debugfs.h"
14#include "string-stream.h"
15#include "try-catch-impl.h"
16
17static void kunit_set_failure(struct kunit *test)
18{
19 WRITE_ONCE(test->success, false);
20}
21
22static void kunit_print_tap_version(void)
23{
24 static bool kunit_has_printed_tap_version;
25
26 if (!kunit_has_printed_tap_version) {
27 pr_info("TAP version 14\n");
28 kunit_has_printed_tap_version = true;
29 }
30}
31
32/*
33 * Append formatted message to log, size of which is limited to
34 * KUNIT_LOG_SIZE bytes (including null terminating byte).
35 */
36void kunit_log_append(char *log, const char *fmt, ...)
37{
38 char line[KUNIT_LOG_SIZE];
39 va_list args;
40 int len_left;
41
42 if (!log)
43 return;
44
45 len_left = KUNIT_LOG_SIZE - strlen(log) - 1;
46 if (len_left <= 0)
47 return;
48
49 va_start(args, fmt);
50 vsnprintf(line, sizeof(line), fmt, args);
51 va_end(args);
52
53 strncat(log, line, len_left);
54}
55EXPORT_SYMBOL_GPL(kunit_log_append);
56
57size_t kunit_suite_num_test_cases(struct kunit_suite *suite)
58{
59 struct kunit_case *test_case;
60 size_t len = 0;
61
62 kunit_suite_for_each_test_case(suite, test_case)
63 len++;
64
65 return len;
66}
67EXPORT_SYMBOL_GPL(kunit_suite_num_test_cases);
68
69static void kunit_print_subtest_start(struct kunit_suite *suite)
70{
71 kunit_print_tap_version();
72 kunit_log(KERN_INFO, suite, "\t# Subtest: %s", suite->name);
73 kunit_log(KERN_INFO, suite, "\t1..%zd",
74 kunit_suite_num_test_cases(suite));
75}
76
77static void kunit_print_ok_not_ok(void *test_or_suite,
78 bool is_test,
79 bool is_ok,
80 size_t test_number,
81 const char *description)
82{
83 struct kunit_suite *suite = is_test ? NULL : test_or_suite;
84 struct kunit *test = is_test ? test_or_suite : NULL;
85
86 /*
87 * We do not log the test suite results as doing so would
88 * mean debugfs display would consist of the test suite
89 * description and status prior to individual test results.
90 * Hence directly printk the suite status, and we will
91 * separately seq_printf() the suite status for the debugfs
92 * representation.
93 */
94 if (suite)
95 pr_info("%s %zd - %s\n",
96 kunit_status_to_string(is_ok),
97 test_number, description);
98 else
99 kunit_log(KERN_INFO, test, "\t%s %zd - %s",
100 kunit_status_to_string(is_ok),
101 test_number, description);
102}
103
104bool kunit_suite_has_succeeded(struct kunit_suite *suite)
105{
106 const struct kunit_case *test_case;
107
108 kunit_suite_for_each_test_case(suite, test_case) {
109 if (!test_case->success)
110 return false;
111 }
112
113 return true;
114}
115EXPORT_SYMBOL_GPL(kunit_suite_has_succeeded);
116
117static void kunit_print_subtest_end(struct kunit_suite *suite)
118{
119 static size_t kunit_suite_counter = 1;
120
121 kunit_print_ok_not_ok((void *)suite, false,
122 kunit_suite_has_succeeded(suite),
123 kunit_suite_counter++,
124 suite->name);
125}
126
127unsigned int kunit_test_case_num(struct kunit_suite *suite,
128 struct kunit_case *test_case)
129{
130 struct kunit_case *tc;
131 unsigned int i = 1;
132
133 kunit_suite_for_each_test_case(suite, tc) {
134 if (tc == test_case)
135 return i;
136 i++;
137 }
138
139 return 0;
140}
141EXPORT_SYMBOL_GPL(kunit_test_case_num);
142
143static void kunit_print_string_stream(struct kunit *test,
144 struct string_stream *stream)
145{
146 struct string_stream_fragment *fragment;
147 char *buf;
148
149 if (string_stream_is_empty(stream))
150 return;
151
152 buf = string_stream_get_string(stream);
153 if (!buf) {
154 kunit_err(test,
155 "Could not allocate buffer, dumping stream:\n");
156 list_for_each_entry(fragment, &stream->fragments, node) {
157 kunit_err(test, "%s", fragment->fragment);
158 }
159 kunit_err(test, "\n");
160 } else {
161 kunit_err(test, "%s", buf);
162 kunit_kfree(test, buf);
163 }
164}
165
166static void kunit_fail(struct kunit *test, struct kunit_assert *assert)
167{
168 struct string_stream *stream;
169
170 kunit_set_failure(test);
171
172 stream = alloc_string_stream(test, GFP_KERNEL);
173 if (!stream) {
174 WARN(true,
175 "Could not allocate stream to print failed assertion in %s:%d\n",
176 assert->file,
177 assert->line);
178 return;
179 }
180
181 assert->format(assert, stream);
182
183 kunit_print_string_stream(test, stream);
184
185 WARN_ON(string_stream_destroy(stream));
186}
187
188static void __noreturn kunit_abort(struct kunit *test)
189{
190 kunit_try_catch_throw(&test->try_catch); /* Does not return. */
191
192 /*
193 * Throw could not abort from test.
194 *
195 * XXX: we should never reach this line! As kunit_try_catch_throw is
196 * marked __noreturn.
197 */
198 WARN_ONCE(true, "Throw could not abort from test!\n");
199}
200
201void kunit_do_assertion(struct kunit *test,
202 struct kunit_assert *assert,
203 bool pass,
204 const char *fmt, ...)
205{
206 va_list args;
207
208 if (pass)
209 return;
210
211 va_start(args, fmt);
212
213 assert->message.fmt = fmt;
214 assert->message.va = &args;
215
216 kunit_fail(test, assert);
217
218 va_end(args);
219
220 if (assert->type == KUNIT_ASSERTION)
221 kunit_abort(test);
222}
223EXPORT_SYMBOL_GPL(kunit_do_assertion);
224
225void kunit_init_test(struct kunit *test, const char *name, char *log)
226{
227 spin_lock_init(&test->lock);
228 INIT_LIST_HEAD(&test->resources);
229 test->name = name;
230 test->log = log;
231 if (test->log)
232 test->log[0] = '\0';
233 test->success = true;
234}
235EXPORT_SYMBOL_GPL(kunit_init_test);
236
237/*
238 * Initializes and runs test case. Does not clean up or do post validations.
239 */
240static void kunit_run_case_internal(struct kunit *test,
241 struct kunit_suite *suite,
242 struct kunit_case *test_case)
243{
244 if (suite->init) {
245 int ret;
246
247 ret = suite->init(test);
248 if (ret) {
249 kunit_err(test, "failed to initialize: %d\n", ret);
250 kunit_set_failure(test);
251 return;
252 }
253 }
254
255 test_case->run_case(test);
256}
257
258static void kunit_case_internal_cleanup(struct kunit *test)
259{
260 kunit_cleanup(test);
261}
262
263/*
264 * Performs post validations and cleanup after a test case was run.
265 * XXX: Should ONLY BE CALLED AFTER kunit_run_case_internal!
266 */
267static void kunit_run_case_cleanup(struct kunit *test,
268 struct kunit_suite *suite)
269{
270 if (suite->exit)
271 suite->exit(test);
272
273 kunit_case_internal_cleanup(test);
274}
275
276struct kunit_try_catch_context {
277 struct kunit *test;
278 struct kunit_suite *suite;
279 struct kunit_case *test_case;
280};
281
282static void kunit_try_run_case(void *data)
283{
284 struct kunit_try_catch_context *ctx = data;
285 struct kunit *test = ctx->test;
286 struct kunit_suite *suite = ctx->suite;
287 struct kunit_case *test_case = ctx->test_case;
288
289 /*
290 * kunit_run_case_internal may encounter a fatal error; if it does,
291 * abort will be called, this thread will exit, and finally the parent
292 * thread will resume control and handle any necessary clean up.
293 */
294 kunit_run_case_internal(test, suite, test_case);
295 /* This line may never be reached. */
296 kunit_run_case_cleanup(test, suite);
297}
298
299static void kunit_catch_run_case(void *data)
300{
301 struct kunit_try_catch_context *ctx = data;
302 struct kunit *test = ctx->test;
303 struct kunit_suite *suite = ctx->suite;
304 int try_exit_code = kunit_try_catch_get_result(&test->try_catch);
305
306 if (try_exit_code) {
307 kunit_set_failure(test);
308 /*
309 * Test case could not finish, we have no idea what state it is
310 * in, so don't do clean up.
311 */
312 if (try_exit_code == -ETIMEDOUT) {
313 kunit_err(test, "test case timed out\n");
314 /*
315 * Unknown internal error occurred preventing test case from
316 * running, so there is nothing to clean up.
317 */
318 } else {
319 kunit_err(test, "internal error occurred preventing test case from running: %d\n",
320 try_exit_code);
321 }
322 return;
323 }
324
325 /*
326 * Test case was run, but aborted. It is the test case's business as to
327 * whether it failed or not, we just need to clean up.
328 */
329 kunit_run_case_cleanup(test, suite);
330}
331
332/*
333 * Performs all logic to run a test case. It also catches most errors that
334 * occur in a test case and reports them as failures.
335 */
336static void kunit_run_case_catch_errors(struct kunit_suite *suite,
337 struct kunit_case *test_case)
338{
339 struct kunit_try_catch_context context;
340 struct kunit_try_catch *try_catch;
341 struct kunit test;
342
343 kunit_init_test(&test, test_case->name, test_case->log);
344 try_catch = &test.try_catch;
345
346 kunit_try_catch_init(try_catch,
347 &test,
348 kunit_try_run_case,
349 kunit_catch_run_case);
350 context.test = &test;
351 context.suite = suite;
352 context.test_case = test_case;
353 kunit_try_catch_run(try_catch, &context);
354
355 test_case->success = test.success;
356
357 kunit_print_ok_not_ok(&test, true, test_case->success,
358 kunit_test_case_num(suite, test_case),
359 test_case->name);
360}
361
362int kunit_run_tests(struct kunit_suite *suite)
363{
364 struct kunit_case *test_case;
365
366 kunit_print_subtest_start(suite);
367
368 kunit_suite_for_each_test_case(suite, test_case)
369 kunit_run_case_catch_errors(suite, test_case);
370
371 kunit_print_subtest_end(suite);
372
373 return 0;
374}
375EXPORT_SYMBOL_GPL(kunit_run_tests);
376
377static void kunit_init_suite(struct kunit_suite *suite)
378{
379 kunit_debugfs_create_suite(suite);
380}
381
382int __kunit_test_suites_init(struct kunit_suite **suites)
383{
384 unsigned int i;
385
386 for (i = 0; suites[i] != NULL; i++) {
387 kunit_init_suite(suites[i]);
388 kunit_run_tests(suites[i]);
389 }
390 return 0;
391}
392EXPORT_SYMBOL_GPL(__kunit_test_suites_init);
393
394static void kunit_exit_suite(struct kunit_suite *suite)
395{
396 kunit_debugfs_destroy_suite(suite);
397}
398
399void __kunit_test_suites_exit(struct kunit_suite **suites)
400{
401 unsigned int i;
402
403 for (i = 0; suites[i] != NULL; i++)
404 kunit_exit_suite(suites[i]);
405}
406EXPORT_SYMBOL_GPL(__kunit_test_suites_exit);
407
408struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
409 kunit_resource_init_t init,
410 kunit_resource_free_t free,
411 gfp_t internal_gfp,
412 void *context)
413{
414 struct kunit_resource *res;
415 int ret;
416
417 res = kzalloc(sizeof(*res), internal_gfp);
418 if (!res)
419 return NULL;
420
421 ret = init(res, context);
422 if (ret)
423 return NULL;
424
425 res->free = free;
426 spin_lock(&test->lock);
427 list_add_tail(&res->node, &test->resources);
428 spin_unlock(&test->lock);
429
430 return res;
431}
432EXPORT_SYMBOL_GPL(kunit_alloc_and_get_resource);
433
434static void kunit_resource_free(struct kunit *test, struct kunit_resource *res)
435{
436 res->free(res);
437 kfree(res);
438}
439
440static struct kunit_resource *kunit_resource_find(struct kunit *test,
441 kunit_resource_match_t match,
442 kunit_resource_free_t free,
443 void *match_data)
444{
445 struct kunit_resource *resource;
446
447 lockdep_assert_held(&test->lock);
448
449 list_for_each_entry_reverse(resource, &test->resources, node) {
450 if (resource->free != free)
451 continue;
452 if (match(test, resource->allocation, match_data))
453 return resource;
454 }
455
456 return NULL;
457}
458
459static struct kunit_resource *kunit_resource_remove(
460 struct kunit *test,
461 kunit_resource_match_t match,
462 kunit_resource_free_t free,
463 void *match_data)
464{
465 struct kunit_resource *resource;
466
467 spin_lock(&test->lock);
468 resource = kunit_resource_find(test, match, free, match_data);
469 if (resource)
470 list_del(&resource->node);
471 spin_unlock(&test->lock);
472
473 return resource;
474}
475
476int kunit_resource_destroy(struct kunit *test,
477 kunit_resource_match_t match,
478 kunit_resource_free_t free,
479 void *match_data)
480{
481 struct kunit_resource *resource;
482
483 resource = kunit_resource_remove(test, match, free, match_data);
484
485 if (!resource)
486 return -ENOENT;
487
488 kunit_resource_free(test, resource);
489 return 0;
490}
491EXPORT_SYMBOL_GPL(kunit_resource_destroy);
492
493struct kunit_kmalloc_params {
494 size_t size;
495 gfp_t gfp;
496};
497
498static int kunit_kmalloc_init(struct kunit_resource *res, void *context)
499{
500 struct kunit_kmalloc_params *params = context;
501
502 res->allocation = kmalloc(params->size, params->gfp);
503 if (!res->allocation)
504 return -ENOMEM;
505
506 return 0;
507}
508
509static void kunit_kmalloc_free(struct kunit_resource *res)
510{
511 kfree(res->allocation);
512}
513
514void *kunit_kmalloc(struct kunit *test, size_t size, gfp_t gfp)
515{
516 struct kunit_kmalloc_params params = {
517 .size = size,
518 .gfp = gfp
519 };
520
521 return kunit_alloc_resource(test,
522 kunit_kmalloc_init,
523 kunit_kmalloc_free,
524 gfp,
525 &params);
526}
527EXPORT_SYMBOL_GPL(kunit_kmalloc);
528
529void kunit_kfree(struct kunit *test, const void *ptr)
530{
531 int rc;
532
533 rc = kunit_resource_destroy(test,
534 kunit_resource_instance_match,
535 kunit_kmalloc_free,
536 (void *)ptr);
537
538 WARN_ON(rc);
539}
540EXPORT_SYMBOL_GPL(kunit_kfree);
541
542void kunit_cleanup(struct kunit *test)
543{
544 struct kunit_resource *resource;
545
546 /*
547 * test->resources is a stack - each allocation must be freed in the
548 * reverse order from which it was added since one resource may depend
549 * on another for its entire lifetime.
550 * Also, we cannot use the normal list_for_each constructs, even the
551 * safe ones because *arbitrary* nodes may be deleted when
552 * kunit_resource_free is called; the list_for_each_safe variants only
553 * protect against the current node being deleted, not the next.
554 */
555 while (true) {
556 spin_lock(&test->lock);
557 if (list_empty(&test->resources)) {
558 spin_unlock(&test->lock);
559 break;
560 }
561 resource = list_last_entry(&test->resources,
562 struct kunit_resource,
563 node);
564 list_del(&resource->node);
565 spin_unlock(&test->lock);
566
567 kunit_resource_free(test, resource);
568 }
569}
570EXPORT_SYMBOL_GPL(kunit_cleanup);
571
572static int __init kunit_init(void)
573{
574 kunit_debugfs_init();
575
576 return 0;
577}
578late_initcall(kunit_init);
579
580static void __exit kunit_exit(void)
581{
582 kunit_debugfs_cleanup();
583}
584module_exit(kunit_exit);
585
586MODULE_LICENSE("GPL v2");