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[2]; 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 int kunit_resource_test_init(struct kunit *test) 407 { 408 struct kunit_test_resource_context *ctx = 409 kzalloc(sizeof(*ctx), GFP_KERNEL); 410 411 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); 412 413 test->priv = ctx; 414 415 kunit_init_test(&ctx->test, "test_test_context", NULL); 416 417 return 0; 418 } 419 420 static void kunit_resource_test_exit(struct kunit *test) 421 { 422 struct kunit_test_resource_context *ctx = test->priv; 423 424 kunit_cleanup(&ctx->test); 425 kfree(ctx); 426 } 427 428 static struct kunit_case kunit_resource_test_cases[] = { 429 KUNIT_CASE(kunit_resource_test_init_resources), 430 KUNIT_CASE(kunit_resource_test_alloc_resource), 431 KUNIT_CASE(kunit_resource_test_destroy_resource), 432 KUNIT_CASE(kunit_resource_test_remove_resource), 433 KUNIT_CASE(kunit_resource_test_cleanup_resources), 434 KUNIT_CASE(kunit_resource_test_proper_free_ordering), 435 KUNIT_CASE(kunit_resource_test_static), 436 KUNIT_CASE(kunit_resource_test_named), 437 {} 438 }; 439 440 static struct kunit_suite kunit_resource_test_suite = { 441 .name = "kunit-resource-test", 442 .init = kunit_resource_test_init, 443 .exit = kunit_resource_test_exit, 444 .test_cases = kunit_resource_test_cases, 445 }; 446 447 static void kunit_log_test(struct kunit *test) 448 { 449 struct kunit_suite suite; 450 451 suite.log = kunit_kzalloc(test, KUNIT_LOG_SIZE, GFP_KERNEL); 452 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, suite.log); 453 454 kunit_log(KERN_INFO, test, "put this in log."); 455 kunit_log(KERN_INFO, test, "this too."); 456 kunit_log(KERN_INFO, &suite, "add to suite log."); 457 kunit_log(KERN_INFO, &suite, "along with this."); 458 459 #ifdef CONFIG_KUNIT_DEBUGFS 460 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, 461 strstr(test->log, "put this in log.")); 462 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, 463 strstr(test->log, "this too.")); 464 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, 465 strstr(suite.log, "add to suite log.")); 466 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, 467 strstr(suite.log, "along with this.")); 468 #else 469 KUNIT_EXPECT_NULL(test, test->log); 470 #endif 471 } 472 473 static void kunit_log_newline_test(struct kunit *test) 474 { 475 kunit_info(test, "Add newline\n"); 476 if (test->log) { 477 KUNIT_ASSERT_NOT_NULL_MSG(test, strstr(test->log, "Add newline\n"), 478 "Missing log line, full log:\n%s", test->log); 479 KUNIT_EXPECT_NULL(test, strstr(test->log, "Add newline\n\n")); 480 } else { 481 kunit_skip(test, "only useful when debugfs is enabled"); 482 } 483 } 484 485 static struct kunit_case kunit_log_test_cases[] = { 486 KUNIT_CASE(kunit_log_test), 487 KUNIT_CASE(kunit_log_newline_test), 488 {} 489 }; 490 491 static struct kunit_suite kunit_log_test_suite = { 492 .name = "kunit-log-test", 493 .test_cases = kunit_log_test_cases, 494 }; 495 496 static void kunit_status_set_failure_test(struct kunit *test) 497 { 498 struct kunit fake; 499 500 kunit_init_test(&fake, "fake test", NULL); 501 502 KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_SUCCESS); 503 kunit_set_failure(&fake); 504 KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_FAILURE); 505 } 506 507 static void kunit_status_mark_skipped_test(struct kunit *test) 508 { 509 struct kunit fake; 510 511 kunit_init_test(&fake, "fake test", NULL); 512 513 /* Before: Should be SUCCESS with no comment. */ 514 KUNIT_EXPECT_EQ(test, fake.status, KUNIT_SUCCESS); 515 KUNIT_EXPECT_STREQ(test, fake.status_comment, ""); 516 517 /* Mark the test as skipped. */ 518 kunit_mark_skipped(&fake, "Accepts format string: %s", "YES"); 519 520 /* After: Should be SKIPPED with our comment. */ 521 KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_SKIPPED); 522 KUNIT_EXPECT_STREQ(test, fake.status_comment, "Accepts format string: YES"); 523 } 524 525 static struct kunit_case kunit_status_test_cases[] = { 526 KUNIT_CASE(kunit_status_set_failure_test), 527 KUNIT_CASE(kunit_status_mark_skipped_test), 528 {} 529 }; 530 531 static struct kunit_suite kunit_status_test_suite = { 532 .name = "kunit_status", 533 .test_cases = kunit_status_test_cases, 534 }; 535 536 static void kunit_current_test(struct kunit *test) 537 { 538 /* Check results of both current->kunit_test and 539 * kunit_get_current_test() are equivalent to current test. 540 */ 541 KUNIT_EXPECT_PTR_EQ(test, test, current->kunit_test); 542 KUNIT_EXPECT_PTR_EQ(test, test, kunit_get_current_test()); 543 } 544 545 static void kunit_current_fail_test(struct kunit *test) 546 { 547 struct kunit fake; 548 549 kunit_init_test(&fake, "fake test", NULL); 550 KUNIT_EXPECT_EQ(test, fake.status, KUNIT_SUCCESS); 551 552 /* Set current->kunit_test to fake test. */ 553 current->kunit_test = &fake; 554 555 kunit_fail_current_test("This should make `fake` test fail."); 556 KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_FAILURE); 557 kunit_cleanup(&fake); 558 559 /* Reset current->kunit_test to current test. */ 560 current->kunit_test = test; 561 } 562 563 static struct kunit_case kunit_current_test_cases[] = { 564 KUNIT_CASE(kunit_current_test), 565 KUNIT_CASE(kunit_current_fail_test), 566 {} 567 }; 568 569 static struct kunit_suite kunit_current_test_suite = { 570 .name = "kunit_current", 571 .test_cases = kunit_current_test_cases, 572 }; 573 574 kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite, 575 &kunit_log_test_suite, &kunit_status_test_suite, 576 &kunit_current_test_suite); 577 578 MODULE_LICENSE("GPL v2"); 579