1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * KUnit test for core test infrastructure. 4 * 5 * Copyright (C) 2019, Google LLC. 6 * Author: Brendan Higgins <brendanhiggins@google.com> 7 */ 8 #include <kunit/test.h> 9 #include <kunit/test-bug.h> 10 11 #include "try-catch-impl.h" 12 13 struct kunit_try_catch_test_context { 14 struct kunit_try_catch *try_catch; 15 bool function_called; 16 }; 17 18 static void kunit_test_successful_try(void *data) 19 { 20 struct kunit *test = data; 21 struct kunit_try_catch_test_context *ctx = test->priv; 22 23 ctx->function_called = true; 24 } 25 26 static void kunit_test_no_catch(void *data) 27 { 28 struct kunit *test = data; 29 30 KUNIT_FAIL(test, "Catch should not be called\n"); 31 } 32 33 static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test) 34 { 35 struct kunit_try_catch_test_context *ctx = test->priv; 36 struct kunit_try_catch *try_catch = ctx->try_catch; 37 38 kunit_try_catch_init(try_catch, 39 test, 40 kunit_test_successful_try, 41 kunit_test_no_catch); 42 kunit_try_catch_run(try_catch, test); 43 44 KUNIT_EXPECT_TRUE(test, ctx->function_called); 45 } 46 47 static void kunit_test_unsuccessful_try(void *data) 48 { 49 struct kunit *test = data; 50 struct kunit_try_catch_test_context *ctx = test->priv; 51 struct kunit_try_catch *try_catch = ctx->try_catch; 52 53 kunit_try_catch_throw(try_catch); 54 KUNIT_FAIL(test, "This line should never be reached\n"); 55 } 56 57 static void kunit_test_catch(void *data) 58 { 59 struct kunit *test = data; 60 struct kunit_try_catch_test_context *ctx = test->priv; 61 62 ctx->function_called = true; 63 } 64 65 static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit *test) 66 { 67 struct kunit_try_catch_test_context *ctx = test->priv; 68 struct kunit_try_catch *try_catch = ctx->try_catch; 69 70 kunit_try_catch_init(try_catch, 71 test, 72 kunit_test_unsuccessful_try, 73 kunit_test_catch); 74 kunit_try_catch_run(try_catch, test); 75 76 KUNIT_EXPECT_TRUE(test, ctx->function_called); 77 } 78 79 static int kunit_try_catch_test_init(struct kunit *test) 80 { 81 struct kunit_try_catch_test_context *ctx; 82 83 ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 84 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); 85 test->priv = ctx; 86 87 ctx->try_catch = kunit_kmalloc(test, 88 sizeof(*ctx->try_catch), 89 GFP_KERNEL); 90 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->try_catch); 91 92 return 0; 93 } 94 95 static struct kunit_case kunit_try_catch_test_cases[] = { 96 KUNIT_CASE(kunit_test_try_catch_successful_try_no_catch), 97 KUNIT_CASE(kunit_test_try_catch_unsuccessful_try_does_catch), 98 {} 99 }; 100 101 static struct kunit_suite kunit_try_catch_test_suite = { 102 .name = "kunit-try-catch-test", 103 .init = kunit_try_catch_test_init, 104 .test_cases = kunit_try_catch_test_cases, 105 }; 106 107 /* 108 * Context for testing test managed resources 109 * is_resource_initialized is used to test arbitrary resources 110 */ 111 struct kunit_test_resource_context { 112 struct kunit test; 113 bool is_resource_initialized; 114 int allocate_order[2]; 115 int free_order[4]; 116 }; 117 118 static int fake_resource_init(struct kunit_resource *res, void *context) 119 { 120 struct kunit_test_resource_context *ctx = context; 121 122 res->data = &ctx->is_resource_initialized; 123 ctx->is_resource_initialized = true; 124 return 0; 125 } 126 127 static void fake_resource_free(struct kunit_resource *res) 128 { 129 bool *is_resource_initialized = res->data; 130 131 *is_resource_initialized = false; 132 } 133 134 static void kunit_resource_test_init_resources(struct kunit *test) 135 { 136 struct kunit_test_resource_context *ctx = test->priv; 137 138 kunit_init_test(&ctx->test, "testing_test_init_test", NULL); 139 140 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources)); 141 } 142 143 static void kunit_resource_test_alloc_resource(struct kunit *test) 144 { 145 struct kunit_test_resource_context *ctx = test->priv; 146 struct kunit_resource *res; 147 kunit_resource_free_t free = fake_resource_free; 148 149 res = kunit_alloc_and_get_resource(&ctx->test, 150 fake_resource_init, 151 fake_resource_free, 152 GFP_KERNEL, 153 ctx); 154 155 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res); 156 KUNIT_EXPECT_PTR_EQ(test, 157 &ctx->is_resource_initialized, 158 (bool *)res->data); 159 KUNIT_EXPECT_TRUE(test, list_is_last(&res->node, &ctx->test.resources)); 160 KUNIT_EXPECT_PTR_EQ(test, free, res->free); 161 162 kunit_put_resource(res); 163 } 164 165 static inline bool kunit_resource_instance_match(struct kunit *test, 166 struct kunit_resource *res, 167 void *match_data) 168 { 169 return res->data == match_data; 170 } 171 172 /* 173 * Note: tests below use kunit_alloc_and_get_resource(), so as a consequence 174 * they have a reference to the associated resource that they must release 175 * via kunit_put_resource(). In normal operation, users will only 176 * have to do this for cases where they use kunit_find_resource(), and the 177 * kunit_alloc_resource() function will be used (which does not take a 178 * resource reference). 179 */ 180 static void kunit_resource_test_destroy_resource(struct kunit *test) 181 { 182 struct kunit_test_resource_context *ctx = test->priv; 183 struct kunit_resource *res = kunit_alloc_and_get_resource( 184 &ctx->test, 185 fake_resource_init, 186 fake_resource_free, 187 GFP_KERNEL, 188 ctx); 189 190 kunit_put_resource(res); 191 192 KUNIT_ASSERT_FALSE(test, 193 kunit_destroy_resource(&ctx->test, 194 kunit_resource_instance_match, 195 res->data)); 196 197 KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized); 198 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources)); 199 } 200 201 static void kunit_resource_test_remove_resource(struct kunit *test) 202 { 203 struct kunit_test_resource_context *ctx = test->priv; 204 struct kunit_resource *res = kunit_alloc_and_get_resource( 205 &ctx->test, 206 fake_resource_init, 207 fake_resource_free, 208 GFP_KERNEL, 209 ctx); 210 211 /* The resource is in the list */ 212 KUNIT_EXPECT_FALSE(test, list_empty(&ctx->test.resources)); 213 214 /* Remove the resource. The pointer is still valid, but it can't be 215 * found. 216 */ 217 kunit_remove_resource(test, res); 218 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources)); 219 /* We haven't been freed yet. */ 220 KUNIT_EXPECT_TRUE(test, ctx->is_resource_initialized); 221 222 /* Removing the resource multiple times is valid. */ 223 kunit_remove_resource(test, res); 224 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources)); 225 /* Despite having been removed twice (from only one reference), the 226 * resource still has not been freed. 227 */ 228 KUNIT_EXPECT_TRUE(test, ctx->is_resource_initialized); 229 230 /* Free the resource. */ 231 kunit_put_resource(res); 232 KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized); 233 } 234 235 static void kunit_resource_test_cleanup_resources(struct kunit *test) 236 { 237 int i; 238 struct kunit_test_resource_context *ctx = test->priv; 239 struct kunit_resource *resources[5]; 240 241 for (i = 0; i < ARRAY_SIZE(resources); i++) { 242 resources[i] = kunit_alloc_and_get_resource(&ctx->test, 243 fake_resource_init, 244 fake_resource_free, 245 GFP_KERNEL, 246 ctx); 247 kunit_put_resource(resources[i]); 248 } 249 250 kunit_cleanup(&ctx->test); 251 252 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources)); 253 } 254 255 static void kunit_resource_test_mark_order(int order_array[], 256 size_t order_size, 257 int key) 258 { 259 int i; 260 261 for (i = 0; i < order_size && order_array[i]; i++) 262 ; 263 264 order_array[i] = key; 265 } 266 267 #define KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, order_field, key) \ 268 kunit_resource_test_mark_order(ctx->order_field, \ 269 ARRAY_SIZE(ctx->order_field), \ 270 key) 271 272 static int fake_resource_2_init(struct kunit_resource *res, void *context) 273 { 274 struct kunit_test_resource_context *ctx = context; 275 276 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 2); 277 278 res->data = ctx; 279 280 return 0; 281 } 282 283 static void fake_resource_2_free(struct kunit_resource *res) 284 { 285 struct kunit_test_resource_context *ctx = res->data; 286 287 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 2); 288 } 289 290 static int fake_resource_1_init(struct kunit_resource *res, void *context) 291 { 292 struct kunit_test_resource_context *ctx = context; 293 struct kunit_resource *res2; 294 295 res2 = kunit_alloc_and_get_resource(&ctx->test, 296 fake_resource_2_init, 297 fake_resource_2_free, 298 GFP_KERNEL, 299 ctx); 300 301 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 1); 302 303 res->data = ctx; 304 305 kunit_put_resource(res2); 306 307 return 0; 308 } 309 310 static void fake_resource_1_free(struct kunit_resource *res) 311 { 312 struct kunit_test_resource_context *ctx = res->data; 313 314 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 1); 315 } 316 317 /* 318 * TODO(brendanhiggins@google.com): replace the arrays that keep track of the 319 * order of allocation and freeing with strict mocks using the IN_SEQUENCE macro 320 * to assert allocation and freeing order when the feature becomes available. 321 */ 322 static void kunit_resource_test_proper_free_ordering(struct kunit *test) 323 { 324 struct kunit_test_resource_context *ctx = test->priv; 325 struct kunit_resource *res; 326 327 /* fake_resource_1 allocates a fake_resource_2 in its init. */ 328 res = kunit_alloc_and_get_resource(&ctx->test, 329 fake_resource_1_init, 330 fake_resource_1_free, 331 GFP_KERNEL, 332 ctx); 333 334 /* 335 * Since fake_resource_2_init calls KUNIT_RESOURCE_TEST_MARK_ORDER 336 * before returning to fake_resource_1_init, it should be the first to 337 * put its key in the allocate_order array. 338 */ 339 KUNIT_EXPECT_EQ(test, ctx->allocate_order[0], 2); 340 KUNIT_EXPECT_EQ(test, ctx->allocate_order[1], 1); 341 342 kunit_put_resource(res); 343 344 kunit_cleanup(&ctx->test); 345 346 /* 347 * Because fake_resource_2 finishes allocation before fake_resource_1, 348 * fake_resource_1 should be freed first since it could depend on 349 * fake_resource_2. 350 */ 351 KUNIT_EXPECT_EQ(test, ctx->free_order[0], 1); 352 KUNIT_EXPECT_EQ(test, ctx->free_order[1], 2); 353 } 354 355 static void kunit_resource_test_static(struct kunit *test) 356 { 357 struct kunit_test_resource_context ctx; 358 struct kunit_resource res; 359 360 KUNIT_EXPECT_EQ(test, kunit_add_resource(test, NULL, NULL, &res, &ctx), 361 0); 362 363 KUNIT_EXPECT_PTR_EQ(test, res.data, (void *)&ctx); 364 365 kunit_cleanup(test); 366 367 KUNIT_EXPECT_TRUE(test, list_empty(&test->resources)); 368 } 369 370 static void kunit_resource_test_named(struct kunit *test) 371 { 372 struct kunit_resource res1, res2, *found = NULL; 373 struct kunit_test_resource_context ctx; 374 375 KUNIT_EXPECT_EQ(test, 376 kunit_add_named_resource(test, NULL, NULL, &res1, 377 "resource_1", &ctx), 378 0); 379 KUNIT_EXPECT_PTR_EQ(test, res1.data, (void *)&ctx); 380 381 KUNIT_EXPECT_EQ(test, 382 kunit_add_named_resource(test, NULL, NULL, &res1, 383 "resource_1", &ctx), 384 -EEXIST); 385 386 KUNIT_EXPECT_EQ(test, 387 kunit_add_named_resource(test, NULL, NULL, &res2, 388 "resource_2", &ctx), 389 0); 390 391 found = kunit_find_named_resource(test, "resource_1"); 392 393 KUNIT_EXPECT_PTR_EQ(test, found, &res1); 394 395 if (found) 396 kunit_put_resource(&res1); 397 398 KUNIT_EXPECT_EQ(test, kunit_destroy_named_resource(test, "resource_2"), 399 0); 400 401 kunit_cleanup(test); 402 403 KUNIT_EXPECT_TRUE(test, list_empty(&test->resources)); 404 } 405 406 static void increment_int(void *ctx) 407 { 408 int *i = (int *)ctx; 409 (*i)++; 410 } 411 412 static void kunit_resource_test_action(struct kunit *test) 413 { 414 int num_actions = 0; 415 416 kunit_add_action(test, increment_int, &num_actions); 417 KUNIT_EXPECT_EQ(test, num_actions, 0); 418 kunit_cleanup(test); 419 KUNIT_EXPECT_EQ(test, num_actions, 1); 420 421 /* Once we've cleaned up, the action queue is empty. */ 422 kunit_cleanup(test); 423 KUNIT_EXPECT_EQ(test, num_actions, 1); 424 425 /* Check the same function can be deferred multiple times. */ 426 kunit_add_action(test, increment_int, &num_actions); 427 kunit_add_action(test, increment_int, &num_actions); 428 kunit_cleanup(test); 429 KUNIT_EXPECT_EQ(test, num_actions, 3); 430 } 431 static void kunit_resource_test_remove_action(struct kunit *test) 432 { 433 int num_actions = 0; 434 435 kunit_add_action(test, increment_int, &num_actions); 436 KUNIT_EXPECT_EQ(test, num_actions, 0); 437 438 kunit_remove_action(test, increment_int, &num_actions); 439 kunit_cleanup(test); 440 KUNIT_EXPECT_EQ(test, num_actions, 0); 441 } 442 static void kunit_resource_test_release_action(struct kunit *test) 443 { 444 int num_actions = 0; 445 446 kunit_add_action(test, increment_int, &num_actions); 447 KUNIT_EXPECT_EQ(test, num_actions, 0); 448 /* Runs immediately on trigger. */ 449 kunit_release_action(test, increment_int, &num_actions); 450 KUNIT_EXPECT_EQ(test, num_actions, 1); 451 452 /* Doesn't run again on test exit. */ 453 kunit_cleanup(test); 454 KUNIT_EXPECT_EQ(test, num_actions, 1); 455 } 456 static void action_order_1(void *ctx) 457 { 458 struct kunit_test_resource_context *res_ctx = (struct kunit_test_resource_context *)ctx; 459 460 KUNIT_RESOURCE_TEST_MARK_ORDER(res_ctx, free_order, 1); 461 kunit_log(KERN_INFO, current->kunit_test, "action_order_1"); 462 } 463 static void action_order_2(void *ctx) 464 { 465 struct kunit_test_resource_context *res_ctx = (struct kunit_test_resource_context *)ctx; 466 467 KUNIT_RESOURCE_TEST_MARK_ORDER(res_ctx, free_order, 2); 468 kunit_log(KERN_INFO, current->kunit_test, "action_order_2"); 469 } 470 static void kunit_resource_test_action_ordering(struct kunit *test) 471 { 472 struct kunit_test_resource_context *ctx = test->priv; 473 474 kunit_add_action(test, action_order_1, ctx); 475 kunit_add_action(test, action_order_2, ctx); 476 kunit_add_action(test, action_order_1, ctx); 477 kunit_add_action(test, action_order_2, ctx); 478 kunit_remove_action(test, action_order_1, ctx); 479 kunit_release_action(test, action_order_2, ctx); 480 kunit_cleanup(test); 481 482 /* [2 is triggered] [2], [(1 is cancelled)] [1] */ 483 KUNIT_EXPECT_EQ(test, ctx->free_order[0], 2); 484 KUNIT_EXPECT_EQ(test, ctx->free_order[1], 2); 485 KUNIT_EXPECT_EQ(test, ctx->free_order[2], 1); 486 } 487 488 static int kunit_resource_test_init(struct kunit *test) 489 { 490 struct kunit_test_resource_context *ctx = 491 kzalloc(sizeof(*ctx), GFP_KERNEL); 492 493 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); 494 495 test->priv = ctx; 496 497 kunit_init_test(&ctx->test, "test_test_context", NULL); 498 499 return 0; 500 } 501 502 static void kunit_resource_test_exit(struct kunit *test) 503 { 504 struct kunit_test_resource_context *ctx = test->priv; 505 506 kunit_cleanup(&ctx->test); 507 kfree(ctx); 508 } 509 510 static struct kunit_case kunit_resource_test_cases[] = { 511 KUNIT_CASE(kunit_resource_test_init_resources), 512 KUNIT_CASE(kunit_resource_test_alloc_resource), 513 KUNIT_CASE(kunit_resource_test_destroy_resource), 514 KUNIT_CASE(kunit_resource_test_remove_resource), 515 KUNIT_CASE(kunit_resource_test_cleanup_resources), 516 KUNIT_CASE(kunit_resource_test_proper_free_ordering), 517 KUNIT_CASE(kunit_resource_test_static), 518 KUNIT_CASE(kunit_resource_test_named), 519 KUNIT_CASE(kunit_resource_test_action), 520 KUNIT_CASE(kunit_resource_test_remove_action), 521 KUNIT_CASE(kunit_resource_test_release_action), 522 KUNIT_CASE(kunit_resource_test_action_ordering), 523 {} 524 }; 525 526 static struct kunit_suite kunit_resource_test_suite = { 527 .name = "kunit-resource-test", 528 .init = kunit_resource_test_init, 529 .exit = kunit_resource_test_exit, 530 .test_cases = kunit_resource_test_cases, 531 }; 532 533 static void kunit_log_test(struct kunit *test) 534 { 535 struct kunit_suite suite; 536 537 suite.log = kunit_kzalloc(test, KUNIT_LOG_SIZE, GFP_KERNEL); 538 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, suite.log); 539 540 kunit_log(KERN_INFO, test, "put this in log."); 541 kunit_log(KERN_INFO, test, "this too."); 542 kunit_log(KERN_INFO, &suite, "add to suite log."); 543 kunit_log(KERN_INFO, &suite, "along with this."); 544 545 #ifdef CONFIG_KUNIT_DEBUGFS 546 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, 547 strstr(test->log, "put this in log.")); 548 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, 549 strstr(test->log, "this too.")); 550 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, 551 strstr(suite.log, "add to suite log.")); 552 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, 553 strstr(suite.log, "along with this.")); 554 #else 555 KUNIT_EXPECT_NULL(test, test->log); 556 #endif 557 } 558 559 static void kunit_log_newline_test(struct kunit *test) 560 { 561 kunit_info(test, "Add newline\n"); 562 if (test->log) { 563 KUNIT_ASSERT_NOT_NULL_MSG(test, strstr(test->log, "Add newline\n"), 564 "Missing log line, full log:\n%s", test->log); 565 KUNIT_EXPECT_NULL(test, strstr(test->log, "Add newline\n\n")); 566 } else { 567 kunit_skip(test, "only useful when debugfs is enabled"); 568 } 569 } 570 571 static struct kunit_case kunit_log_test_cases[] = { 572 KUNIT_CASE(kunit_log_test), 573 KUNIT_CASE(kunit_log_newline_test), 574 {} 575 }; 576 577 static struct kunit_suite kunit_log_test_suite = { 578 .name = "kunit-log-test", 579 .test_cases = kunit_log_test_cases, 580 }; 581 582 static void kunit_status_set_failure_test(struct kunit *test) 583 { 584 struct kunit fake; 585 586 kunit_init_test(&fake, "fake test", NULL); 587 588 KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_SUCCESS); 589 kunit_set_failure(&fake); 590 KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_FAILURE); 591 } 592 593 static void kunit_status_mark_skipped_test(struct kunit *test) 594 { 595 struct kunit fake; 596 597 kunit_init_test(&fake, "fake test", NULL); 598 599 /* Before: Should be SUCCESS with no comment. */ 600 KUNIT_EXPECT_EQ(test, fake.status, KUNIT_SUCCESS); 601 KUNIT_EXPECT_STREQ(test, fake.status_comment, ""); 602 603 /* Mark the test as skipped. */ 604 kunit_mark_skipped(&fake, "Accepts format string: %s", "YES"); 605 606 /* After: Should be SKIPPED with our comment. */ 607 KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_SKIPPED); 608 KUNIT_EXPECT_STREQ(test, fake.status_comment, "Accepts format string: YES"); 609 } 610 611 static struct kunit_case kunit_status_test_cases[] = { 612 KUNIT_CASE(kunit_status_set_failure_test), 613 KUNIT_CASE(kunit_status_mark_skipped_test), 614 {} 615 }; 616 617 static struct kunit_suite kunit_status_test_suite = { 618 .name = "kunit_status", 619 .test_cases = kunit_status_test_cases, 620 }; 621 622 static void kunit_current_test(struct kunit *test) 623 { 624 /* Check results of both current->kunit_test and 625 * kunit_get_current_test() are equivalent to current test. 626 */ 627 KUNIT_EXPECT_PTR_EQ(test, test, current->kunit_test); 628 KUNIT_EXPECT_PTR_EQ(test, test, kunit_get_current_test()); 629 } 630 631 static void kunit_current_fail_test(struct kunit *test) 632 { 633 struct kunit fake; 634 635 kunit_init_test(&fake, "fake test", NULL); 636 KUNIT_EXPECT_EQ(test, fake.status, KUNIT_SUCCESS); 637 638 /* Set current->kunit_test to fake test. */ 639 current->kunit_test = &fake; 640 641 kunit_fail_current_test("This should make `fake` test fail."); 642 KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_FAILURE); 643 kunit_cleanup(&fake); 644 645 /* Reset current->kunit_test to current test. */ 646 current->kunit_test = test; 647 } 648 649 static struct kunit_case kunit_current_test_cases[] = { 650 KUNIT_CASE(kunit_current_test), 651 KUNIT_CASE(kunit_current_fail_test), 652 {} 653 }; 654 655 static struct kunit_suite kunit_current_test_suite = { 656 .name = "kunit_current", 657 .test_cases = kunit_current_test_cases, 658 }; 659 660 kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite, 661 &kunit_log_test_suite, &kunit_status_test_suite, 662 &kunit_current_test_suite); 663 664 MODULE_LICENSE("GPL v2"); 665