test.c (17622B)
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 <linux/kernel.h> 13#include <linux/moduleparam.h> 14#include <linux/sched/debug.h> 15#include <linux/sched.h> 16 17#include "debugfs.h" 18#include "string-stream.h" 19#include "try-catch-impl.h" 20 21#if IS_BUILTIN(CONFIG_KUNIT) 22/* 23 * Fail the current test and print an error message to the log. 24 */ 25void __kunit_fail_current_test(const char *file, int line, const char *fmt, ...) 26{ 27 va_list args; 28 int len; 29 char *buffer; 30 31 if (!current->kunit_test) 32 return; 33 34 kunit_set_failure(current->kunit_test); 35 36 /* kunit_err() only accepts literals, so evaluate the args first. */ 37 va_start(args, fmt); 38 len = vsnprintf(NULL, 0, fmt, args) + 1; 39 va_end(args); 40 41 buffer = kunit_kmalloc(current->kunit_test, len, GFP_KERNEL); 42 if (!buffer) 43 return; 44 45 va_start(args, fmt); 46 vsnprintf(buffer, len, fmt, args); 47 va_end(args); 48 49 kunit_err(current->kunit_test, "%s:%d: %s", file, line, buffer); 50 kunit_kfree(current->kunit_test, buffer); 51} 52EXPORT_SYMBOL_GPL(__kunit_fail_current_test); 53#endif 54 55/* 56 * KUnit statistic mode: 57 * 0 - disabled 58 * 1 - only when there is more than one subtest 59 * 2 - enabled 60 */ 61static int kunit_stats_enabled = 1; 62module_param_named(stats_enabled, kunit_stats_enabled, int, 0644); 63MODULE_PARM_DESC(stats_enabled, 64 "Print test stats: never (0), only for multiple subtests (1), or always (2)"); 65 66struct kunit_result_stats { 67 unsigned long passed; 68 unsigned long skipped; 69 unsigned long failed; 70 unsigned long total; 71}; 72 73static bool kunit_should_print_stats(struct kunit_result_stats stats) 74{ 75 if (kunit_stats_enabled == 0) 76 return false; 77 78 if (kunit_stats_enabled == 2) 79 return true; 80 81 return (stats.total > 1); 82} 83 84static void kunit_print_test_stats(struct kunit *test, 85 struct kunit_result_stats stats) 86{ 87 if (!kunit_should_print_stats(stats)) 88 return; 89 90 kunit_log(KERN_INFO, test, 91 KUNIT_SUBTEST_INDENT 92 "# %s: pass:%lu fail:%lu skip:%lu total:%lu", 93 test->name, 94 stats.passed, 95 stats.failed, 96 stats.skipped, 97 stats.total); 98} 99 100/* 101 * Append formatted message to log, size of which is limited to 102 * KUNIT_LOG_SIZE bytes (including null terminating byte). 103 */ 104void kunit_log_append(char *log, const char *fmt, ...) 105{ 106 char line[KUNIT_LOG_SIZE]; 107 va_list args; 108 int len_left; 109 110 if (!log) 111 return; 112 113 len_left = KUNIT_LOG_SIZE - strlen(log) - 1; 114 if (len_left <= 0) 115 return; 116 117 va_start(args, fmt); 118 vsnprintf(line, sizeof(line), fmt, args); 119 va_end(args); 120 121 strncat(log, line, len_left); 122} 123EXPORT_SYMBOL_GPL(kunit_log_append); 124 125size_t kunit_suite_num_test_cases(struct kunit_suite *suite) 126{ 127 struct kunit_case *test_case; 128 size_t len = 0; 129 130 kunit_suite_for_each_test_case(suite, test_case) 131 len++; 132 133 return len; 134} 135EXPORT_SYMBOL_GPL(kunit_suite_num_test_cases); 136 137static void kunit_print_suite_start(struct kunit_suite *suite) 138{ 139 kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "# Subtest: %s", 140 suite->name); 141 kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "1..%zd", 142 kunit_suite_num_test_cases(suite)); 143} 144 145static void kunit_print_ok_not_ok(void *test_or_suite, 146 bool is_test, 147 enum kunit_status status, 148 size_t test_number, 149 const char *description, 150 const char *directive) 151{ 152 struct kunit_suite *suite = is_test ? NULL : test_or_suite; 153 struct kunit *test = is_test ? test_or_suite : NULL; 154 const char *directive_header = (status == KUNIT_SKIPPED) ? " # SKIP " : ""; 155 156 /* 157 * We do not log the test suite results as doing so would 158 * mean debugfs display would consist of the test suite 159 * description and status prior to individual test results. 160 * Hence directly printk the suite status, and we will 161 * separately seq_printf() the suite status for the debugfs 162 * representation. 163 */ 164 if (suite) 165 pr_info("%s %zd - %s%s%s\n", 166 kunit_status_to_ok_not_ok(status), 167 test_number, description, directive_header, 168 (status == KUNIT_SKIPPED) ? directive : ""); 169 else 170 kunit_log(KERN_INFO, test, 171 KUNIT_SUBTEST_INDENT "%s %zd - %s%s%s", 172 kunit_status_to_ok_not_ok(status), 173 test_number, description, directive_header, 174 (status == KUNIT_SKIPPED) ? directive : ""); 175} 176 177enum kunit_status kunit_suite_has_succeeded(struct kunit_suite *suite) 178{ 179 const struct kunit_case *test_case; 180 enum kunit_status status = KUNIT_SKIPPED; 181 182 if (suite->suite_init_err) 183 return KUNIT_FAILURE; 184 185 kunit_suite_for_each_test_case(suite, test_case) { 186 if (test_case->status == KUNIT_FAILURE) 187 return KUNIT_FAILURE; 188 else if (test_case->status == KUNIT_SUCCESS) 189 status = KUNIT_SUCCESS; 190 } 191 192 return status; 193} 194EXPORT_SYMBOL_GPL(kunit_suite_has_succeeded); 195 196static size_t kunit_suite_counter = 1; 197 198static void kunit_print_suite_end(struct kunit_suite *suite) 199{ 200 kunit_print_ok_not_ok((void *)suite, false, 201 kunit_suite_has_succeeded(suite), 202 kunit_suite_counter++, 203 suite->name, 204 suite->status_comment); 205} 206 207unsigned int kunit_test_case_num(struct kunit_suite *suite, 208 struct kunit_case *test_case) 209{ 210 struct kunit_case *tc; 211 unsigned int i = 1; 212 213 kunit_suite_for_each_test_case(suite, tc) { 214 if (tc == test_case) 215 return i; 216 i++; 217 } 218 219 return 0; 220} 221EXPORT_SYMBOL_GPL(kunit_test_case_num); 222 223static void kunit_print_string_stream(struct kunit *test, 224 struct string_stream *stream) 225{ 226 struct string_stream_fragment *fragment; 227 char *buf; 228 229 if (string_stream_is_empty(stream)) 230 return; 231 232 buf = string_stream_get_string(stream); 233 if (!buf) { 234 kunit_err(test, 235 "Could not allocate buffer, dumping stream:\n"); 236 list_for_each_entry(fragment, &stream->fragments, node) { 237 kunit_err(test, "%s", fragment->fragment); 238 } 239 kunit_err(test, "\n"); 240 } else { 241 kunit_err(test, "%s", buf); 242 kunit_kfree(test, buf); 243 } 244} 245 246static void kunit_fail(struct kunit *test, const struct kunit_loc *loc, 247 enum kunit_assert_type type, const struct kunit_assert *assert, 248 const struct va_format *message) 249{ 250 struct string_stream *stream; 251 252 kunit_set_failure(test); 253 254 stream = alloc_string_stream(test, GFP_KERNEL); 255 if (!stream) { 256 WARN(true, 257 "Could not allocate stream to print failed assertion in %s:%d\n", 258 loc->file, 259 loc->line); 260 return; 261 } 262 263 kunit_assert_prologue(loc, type, stream); 264 assert->format(assert, message, stream); 265 266 kunit_print_string_stream(test, stream); 267 268 WARN_ON(string_stream_destroy(stream)); 269} 270 271static void __noreturn kunit_abort(struct kunit *test) 272{ 273 kunit_try_catch_throw(&test->try_catch); /* Does not return. */ 274 275 /* 276 * Throw could not abort from test. 277 * 278 * XXX: we should never reach this line! As kunit_try_catch_throw is 279 * marked __noreturn. 280 */ 281 WARN_ONCE(true, "Throw could not abort from test!\n"); 282} 283 284void kunit_do_failed_assertion(struct kunit *test, 285 const struct kunit_loc *loc, 286 enum kunit_assert_type type, 287 const struct kunit_assert *assert, 288 const char *fmt, ...) 289{ 290 va_list args; 291 struct va_format message; 292 va_start(args, fmt); 293 294 message.fmt = fmt; 295 message.va = &args; 296 297 kunit_fail(test, loc, type, assert, &message); 298 299 va_end(args); 300 301 if (type == KUNIT_ASSERTION) 302 kunit_abort(test); 303} 304EXPORT_SYMBOL_GPL(kunit_do_failed_assertion); 305 306void kunit_init_test(struct kunit *test, const char *name, char *log) 307{ 308 spin_lock_init(&test->lock); 309 INIT_LIST_HEAD(&test->resources); 310 test->name = name; 311 test->log = log; 312 if (test->log) 313 test->log[0] = '\0'; 314 test->status = KUNIT_SUCCESS; 315 test->status_comment[0] = '\0'; 316} 317EXPORT_SYMBOL_GPL(kunit_init_test); 318 319/* 320 * Initializes and runs test case. Does not clean up or do post validations. 321 */ 322static void kunit_run_case_internal(struct kunit *test, 323 struct kunit_suite *suite, 324 struct kunit_case *test_case) 325{ 326 if (suite->init) { 327 int ret; 328 329 ret = suite->init(test); 330 if (ret) { 331 kunit_err(test, "failed to initialize: %d\n", ret); 332 kunit_set_failure(test); 333 return; 334 } 335 } 336 337 test_case->run_case(test); 338} 339 340static void kunit_case_internal_cleanup(struct kunit *test) 341{ 342 kunit_cleanup(test); 343} 344 345/* 346 * Performs post validations and cleanup after a test case was run. 347 * XXX: Should ONLY BE CALLED AFTER kunit_run_case_internal! 348 */ 349static void kunit_run_case_cleanup(struct kunit *test, 350 struct kunit_suite *suite) 351{ 352 if (suite->exit) 353 suite->exit(test); 354 355 kunit_case_internal_cleanup(test); 356} 357 358struct kunit_try_catch_context { 359 struct kunit *test; 360 struct kunit_suite *suite; 361 struct kunit_case *test_case; 362}; 363 364static void kunit_try_run_case(void *data) 365{ 366 struct kunit_try_catch_context *ctx = data; 367 struct kunit *test = ctx->test; 368 struct kunit_suite *suite = ctx->suite; 369 struct kunit_case *test_case = ctx->test_case; 370 371 current->kunit_test = test; 372 373 /* 374 * kunit_run_case_internal may encounter a fatal error; if it does, 375 * abort will be called, this thread will exit, and finally the parent 376 * thread will resume control and handle any necessary clean up. 377 */ 378 kunit_run_case_internal(test, suite, test_case); 379 /* This line may never be reached. */ 380 kunit_run_case_cleanup(test, suite); 381} 382 383static void kunit_catch_run_case(void *data) 384{ 385 struct kunit_try_catch_context *ctx = data; 386 struct kunit *test = ctx->test; 387 struct kunit_suite *suite = ctx->suite; 388 int try_exit_code = kunit_try_catch_get_result(&test->try_catch); 389 390 if (try_exit_code) { 391 kunit_set_failure(test); 392 /* 393 * Test case could not finish, we have no idea what state it is 394 * in, so don't do clean up. 395 */ 396 if (try_exit_code == -ETIMEDOUT) { 397 kunit_err(test, "test case timed out\n"); 398 /* 399 * Unknown internal error occurred preventing test case from 400 * running, so there is nothing to clean up. 401 */ 402 } else { 403 kunit_err(test, "internal error occurred preventing test case from running: %d\n", 404 try_exit_code); 405 } 406 return; 407 } 408 409 /* 410 * Test case was run, but aborted. It is the test case's business as to 411 * whether it failed or not, we just need to clean up. 412 */ 413 kunit_run_case_cleanup(test, suite); 414} 415 416/* 417 * Performs all logic to run a test case. It also catches most errors that 418 * occur in a test case and reports them as failures. 419 */ 420static void kunit_run_case_catch_errors(struct kunit_suite *suite, 421 struct kunit_case *test_case, 422 struct kunit *test) 423{ 424 struct kunit_try_catch_context context; 425 struct kunit_try_catch *try_catch; 426 427 kunit_init_test(test, test_case->name, test_case->log); 428 try_catch = &test->try_catch; 429 430 kunit_try_catch_init(try_catch, 431 test, 432 kunit_try_run_case, 433 kunit_catch_run_case); 434 context.test = test; 435 context.suite = suite; 436 context.test_case = test_case; 437 kunit_try_catch_run(try_catch, &context); 438 439 /* Propagate the parameter result to the test case. */ 440 if (test->status == KUNIT_FAILURE) 441 test_case->status = KUNIT_FAILURE; 442 else if (test_case->status != KUNIT_FAILURE && test->status == KUNIT_SUCCESS) 443 test_case->status = KUNIT_SUCCESS; 444} 445 446static void kunit_print_suite_stats(struct kunit_suite *suite, 447 struct kunit_result_stats suite_stats, 448 struct kunit_result_stats param_stats) 449{ 450 if (kunit_should_print_stats(suite_stats)) { 451 kunit_log(KERN_INFO, suite, 452 "# %s: pass:%lu fail:%lu skip:%lu total:%lu", 453 suite->name, 454 suite_stats.passed, 455 suite_stats.failed, 456 suite_stats.skipped, 457 suite_stats.total); 458 } 459 460 if (kunit_should_print_stats(param_stats)) { 461 kunit_log(KERN_INFO, suite, 462 "# Totals: pass:%lu fail:%lu skip:%lu total:%lu", 463 param_stats.passed, 464 param_stats.failed, 465 param_stats.skipped, 466 param_stats.total); 467 } 468} 469 470static void kunit_update_stats(struct kunit_result_stats *stats, 471 enum kunit_status status) 472{ 473 switch (status) { 474 case KUNIT_SUCCESS: 475 stats->passed++; 476 break; 477 case KUNIT_SKIPPED: 478 stats->skipped++; 479 break; 480 case KUNIT_FAILURE: 481 stats->failed++; 482 break; 483 } 484 485 stats->total++; 486} 487 488static void kunit_accumulate_stats(struct kunit_result_stats *total, 489 struct kunit_result_stats add) 490{ 491 total->passed += add.passed; 492 total->skipped += add.skipped; 493 total->failed += add.failed; 494 total->total += add.total; 495} 496 497int kunit_run_tests(struct kunit_suite *suite) 498{ 499 char param_desc[KUNIT_PARAM_DESC_SIZE]; 500 struct kunit_case *test_case; 501 struct kunit_result_stats suite_stats = { 0 }; 502 struct kunit_result_stats total_stats = { 0 }; 503 504 if (suite->suite_init) { 505 suite->suite_init_err = suite->suite_init(suite); 506 if (suite->suite_init_err) { 507 kunit_err(suite, KUNIT_SUBTEST_INDENT 508 "# failed to initialize (%d)", suite->suite_init_err); 509 goto suite_end; 510 } 511 } 512 513 kunit_print_suite_start(suite); 514 515 kunit_suite_for_each_test_case(suite, test_case) { 516 struct kunit test = { .param_value = NULL, .param_index = 0 }; 517 struct kunit_result_stats param_stats = { 0 }; 518 test_case->status = KUNIT_SKIPPED; 519 520 if (!test_case->generate_params) { 521 /* Non-parameterised test. */ 522 kunit_run_case_catch_errors(suite, test_case, &test); 523 kunit_update_stats(¶m_stats, test.status); 524 } else { 525 /* Get initial param. */ 526 param_desc[0] = '\0'; 527 test.param_value = test_case->generate_params(NULL, param_desc); 528 kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT 529 "# Subtest: %s", test_case->name); 530 531 while (test.param_value) { 532 kunit_run_case_catch_errors(suite, test_case, &test); 533 534 if (param_desc[0] == '\0') { 535 snprintf(param_desc, sizeof(param_desc), 536 "param-%d", test.param_index); 537 } 538 539 kunit_log(KERN_INFO, &test, 540 KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT 541 "%s %d - %s", 542 kunit_status_to_ok_not_ok(test.status), 543 test.param_index + 1, param_desc); 544 545 /* Get next param. */ 546 param_desc[0] = '\0'; 547 test.param_value = test_case->generate_params(test.param_value, param_desc); 548 test.param_index++; 549 550 kunit_update_stats(¶m_stats, test.status); 551 } 552 } 553 554 555 kunit_print_test_stats(&test, param_stats); 556 557 kunit_print_ok_not_ok(&test, true, test_case->status, 558 kunit_test_case_num(suite, test_case), 559 test_case->name, 560 test.status_comment); 561 562 kunit_update_stats(&suite_stats, test_case->status); 563 kunit_accumulate_stats(&total_stats, param_stats); 564 } 565 566 if (suite->suite_exit) 567 suite->suite_exit(suite); 568 569 kunit_print_suite_stats(suite, suite_stats, total_stats); 570suite_end: 571 kunit_print_suite_end(suite); 572 573 return 0; 574} 575EXPORT_SYMBOL_GPL(kunit_run_tests); 576 577static void kunit_init_suite(struct kunit_suite *suite) 578{ 579 kunit_debugfs_create_suite(suite); 580 suite->status_comment[0] = '\0'; 581 suite->suite_init_err = 0; 582} 583 584int __kunit_test_suites_init(struct kunit_suite * const * const suites) 585{ 586 unsigned int i; 587 588 for (i = 0; suites[i] != NULL; i++) { 589 kunit_init_suite(suites[i]); 590 kunit_run_tests(suites[i]); 591 } 592 return 0; 593} 594EXPORT_SYMBOL_GPL(__kunit_test_suites_init); 595 596static void kunit_exit_suite(struct kunit_suite *suite) 597{ 598 kunit_debugfs_destroy_suite(suite); 599} 600 601void __kunit_test_suites_exit(struct kunit_suite **suites) 602{ 603 unsigned int i; 604 605 for (i = 0; suites[i] != NULL; i++) 606 kunit_exit_suite(suites[i]); 607 608 kunit_suite_counter = 1; 609} 610EXPORT_SYMBOL_GPL(__kunit_test_suites_exit); 611 612struct kunit_kmalloc_array_params { 613 size_t n; 614 size_t size; 615 gfp_t gfp; 616}; 617 618static int kunit_kmalloc_array_init(struct kunit_resource *res, void *context) 619{ 620 struct kunit_kmalloc_array_params *params = context; 621 622 res->data = kmalloc_array(params->n, params->size, params->gfp); 623 if (!res->data) 624 return -ENOMEM; 625 626 return 0; 627} 628 629static void kunit_kmalloc_array_free(struct kunit_resource *res) 630{ 631 kfree(res->data); 632} 633 634void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp) 635{ 636 struct kunit_kmalloc_array_params params = { 637 .size = size, 638 .n = n, 639 .gfp = gfp 640 }; 641 642 return kunit_alloc_resource(test, 643 kunit_kmalloc_array_init, 644 kunit_kmalloc_array_free, 645 gfp, 646 ¶ms); 647} 648EXPORT_SYMBOL_GPL(kunit_kmalloc_array); 649 650void kunit_kfree(struct kunit *test, const void *ptr) 651{ 652 struct kunit_resource *res; 653 654 res = kunit_find_resource(test, kunit_resource_instance_match, 655 (void *)ptr); 656 657 /* 658 * Removing the resource from the list of resources drops the 659 * reference count to 1; the final put will trigger the free. 660 */ 661 kunit_remove_resource(test, res); 662 663 kunit_put_resource(res); 664 665} 666EXPORT_SYMBOL_GPL(kunit_kfree); 667 668void kunit_cleanup(struct kunit *test) 669{ 670 struct kunit_resource *res; 671 unsigned long flags; 672 673 /* 674 * test->resources is a stack - each allocation must be freed in the 675 * reverse order from which it was added since one resource may depend 676 * on another for its entire lifetime. 677 * Also, we cannot use the normal list_for_each constructs, even the 678 * safe ones because *arbitrary* nodes may be deleted when 679 * kunit_resource_free is called; the list_for_each_safe variants only 680 * protect against the current node being deleted, not the next. 681 */ 682 while (true) { 683 spin_lock_irqsave(&test->lock, flags); 684 if (list_empty(&test->resources)) { 685 spin_unlock_irqrestore(&test->lock, flags); 686 break; 687 } 688 res = list_last_entry(&test->resources, 689 struct kunit_resource, 690 node); 691 /* 692 * Need to unlock here as a resource may remove another 693 * resource, and this can't happen if the test->lock 694 * is held. 695 */ 696 spin_unlock_irqrestore(&test->lock, flags); 697 kunit_remove_resource(test, res); 698 } 699 current->kunit_test = NULL; 700} 701EXPORT_SYMBOL_GPL(kunit_cleanup); 702 703static int __init kunit_init(void) 704{ 705 kunit_debugfs_init(); 706 707 return 0; 708} 709late_initcall(kunit_init); 710 711static void __exit kunit_exit(void) 712{ 713 kunit_debugfs_cleanup(); 714} 715module_exit(kunit_exit); 716 717MODULE_LICENSE("GPL v2");