kunit-test.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  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 <[email protected]>
  7. */
  8. #include <kunit/test.h>
  9. #include "try-catch-impl.h"
  10. struct kunit_try_catch_test_context {
  11. struct kunit_try_catch *try_catch;
  12. bool function_called;
  13. };
  14. static void kunit_test_successful_try(void *data)
  15. {
  16. struct kunit *test = data;
  17. struct kunit_try_catch_test_context *ctx = test->priv;
  18. ctx->function_called = true;
  19. }
  20. static void kunit_test_no_catch(void *data)
  21. {
  22. struct kunit *test = data;
  23. KUNIT_FAIL(test, "Catch should not be called\n");
  24. }
  25. static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test)
  26. {
  27. struct kunit_try_catch_test_context *ctx = test->priv;
  28. struct kunit_try_catch *try_catch = ctx->try_catch;
  29. kunit_try_catch_init(try_catch,
  30. test,
  31. kunit_test_successful_try,
  32. kunit_test_no_catch);
  33. kunit_try_catch_run(try_catch, test);
  34. KUNIT_EXPECT_TRUE(test, ctx->function_called);
  35. }
  36. static void kunit_test_unsuccessful_try(void *data)
  37. {
  38. struct kunit *test = data;
  39. struct kunit_try_catch_test_context *ctx = test->priv;
  40. struct kunit_try_catch *try_catch = ctx->try_catch;
  41. kunit_try_catch_throw(try_catch);
  42. KUNIT_FAIL(test, "This line should never be reached\n");
  43. }
  44. static void kunit_test_catch(void *data)
  45. {
  46. struct kunit *test = data;
  47. struct kunit_try_catch_test_context *ctx = test->priv;
  48. ctx->function_called = true;
  49. }
  50. static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit *test)
  51. {
  52. struct kunit_try_catch_test_context *ctx = test->priv;
  53. struct kunit_try_catch *try_catch = ctx->try_catch;
  54. kunit_try_catch_init(try_catch,
  55. test,
  56. kunit_test_unsuccessful_try,
  57. kunit_test_catch);
  58. kunit_try_catch_run(try_catch, test);
  59. KUNIT_EXPECT_TRUE(test, ctx->function_called);
  60. }
  61. static int kunit_try_catch_test_init(struct kunit *test)
  62. {
  63. struct kunit_try_catch_test_context *ctx;
  64. ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
  65. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
  66. test->priv = ctx;
  67. ctx->try_catch = kunit_kmalloc(test,
  68. sizeof(*ctx->try_catch),
  69. GFP_KERNEL);
  70. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->try_catch);
  71. return 0;
  72. }
  73. static struct kunit_case kunit_try_catch_test_cases[] = {
  74. KUNIT_CASE(kunit_test_try_catch_successful_try_no_catch),
  75. KUNIT_CASE(kunit_test_try_catch_unsuccessful_try_does_catch),
  76. {}
  77. };
  78. static struct kunit_suite kunit_try_catch_test_suite = {
  79. .name = "kunit-try-catch-test",
  80. .init = kunit_try_catch_test_init,
  81. .test_cases = kunit_try_catch_test_cases,
  82. };
  83. /*
  84. * Context for testing test managed resources
  85. * is_resource_initialized is used to test arbitrary resources
  86. */
  87. struct kunit_test_resource_context {
  88. struct kunit test;
  89. bool is_resource_initialized;
  90. int allocate_order[2];
  91. int free_order[2];
  92. };
  93. static int fake_resource_init(struct kunit_resource *res, void *context)
  94. {
  95. struct kunit_test_resource_context *ctx = context;
  96. res->data = &ctx->is_resource_initialized;
  97. ctx->is_resource_initialized = true;
  98. return 0;
  99. }
  100. static void fake_resource_free(struct kunit_resource *res)
  101. {
  102. bool *is_resource_initialized = res->data;
  103. *is_resource_initialized = false;
  104. }
  105. static void kunit_resource_test_init_resources(struct kunit *test)
  106. {
  107. struct kunit_test_resource_context *ctx = test->priv;
  108. kunit_init_test(&ctx->test, "testing_test_init_test", NULL);
  109. KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
  110. }
  111. static void kunit_resource_test_alloc_resource(struct kunit *test)
  112. {
  113. struct kunit_test_resource_context *ctx = test->priv;
  114. struct kunit_resource *res;
  115. kunit_resource_free_t free = fake_resource_free;
  116. res = kunit_alloc_and_get_resource(&ctx->test,
  117. fake_resource_init,
  118. fake_resource_free,
  119. GFP_KERNEL,
  120. ctx);
  121. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res);
  122. KUNIT_EXPECT_PTR_EQ(test,
  123. &ctx->is_resource_initialized,
  124. (bool *)res->data);
  125. KUNIT_EXPECT_TRUE(test, list_is_last(&res->node, &ctx->test.resources));
  126. KUNIT_EXPECT_PTR_EQ(test, free, res->free);
  127. kunit_put_resource(res);
  128. }
  129. static inline bool kunit_resource_instance_match(struct kunit *test,
  130. struct kunit_resource *res,
  131. void *match_data)
  132. {
  133. return res->data == match_data;
  134. }
  135. /*
  136. * Note: tests below use kunit_alloc_and_get_resource(), so as a consequence
  137. * they have a reference to the associated resource that they must release
  138. * via kunit_put_resource(). In normal operation, users will only
  139. * have to do this for cases where they use kunit_find_resource(), and the
  140. * kunit_alloc_resource() function will be used (which does not take a
  141. * resource reference).
  142. */
  143. static void kunit_resource_test_destroy_resource(struct kunit *test)
  144. {
  145. struct kunit_test_resource_context *ctx = test->priv;
  146. struct kunit_resource *res = kunit_alloc_and_get_resource(
  147. &ctx->test,
  148. fake_resource_init,
  149. fake_resource_free,
  150. GFP_KERNEL,
  151. ctx);
  152. kunit_put_resource(res);
  153. KUNIT_ASSERT_FALSE(test,
  154. kunit_destroy_resource(&ctx->test,
  155. kunit_resource_instance_match,
  156. res->data));
  157. KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized);
  158. KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
  159. }
  160. static void kunit_resource_test_remove_resource(struct kunit *test)
  161. {
  162. struct kunit_test_resource_context *ctx = test->priv;
  163. struct kunit_resource *res = kunit_alloc_and_get_resource(
  164. &ctx->test,
  165. fake_resource_init,
  166. fake_resource_free,
  167. GFP_KERNEL,
  168. ctx);
  169. /* The resource is in the list */
  170. KUNIT_EXPECT_FALSE(test, list_empty(&ctx->test.resources));
  171. /* Remove the resource. The pointer is still valid, but it can't be
  172. * found.
  173. */
  174. kunit_remove_resource(test, res);
  175. KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
  176. /* We haven't been freed yet. */
  177. KUNIT_EXPECT_TRUE(test, ctx->is_resource_initialized);
  178. /* Removing the resource multiple times is valid. */
  179. kunit_remove_resource(test, res);
  180. KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
  181. /* Despite having been removed twice (from only one reference), the
  182. * resource still has not been freed.
  183. */
  184. KUNIT_EXPECT_TRUE(test, ctx->is_resource_initialized);
  185. /* Free the resource. */
  186. kunit_put_resource(res);
  187. KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized);
  188. }
  189. static void kunit_resource_test_cleanup_resources(struct kunit *test)
  190. {
  191. int i;
  192. struct kunit_test_resource_context *ctx = test->priv;
  193. struct kunit_resource *resources[5];
  194. for (i = 0; i < ARRAY_SIZE(resources); i++) {
  195. resources[i] = kunit_alloc_and_get_resource(&ctx->test,
  196. fake_resource_init,
  197. fake_resource_free,
  198. GFP_KERNEL,
  199. ctx);
  200. kunit_put_resource(resources[i]);
  201. }
  202. kunit_cleanup(&ctx->test);
  203. KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
  204. }
  205. static void kunit_resource_test_mark_order(int order_array[],
  206. size_t order_size,
  207. int key)
  208. {
  209. int i;
  210. for (i = 0; i < order_size && order_array[i]; i++)
  211. ;
  212. order_array[i] = key;
  213. }
  214. #define KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, order_field, key) \
  215. kunit_resource_test_mark_order(ctx->order_field, \
  216. ARRAY_SIZE(ctx->order_field), \
  217. key)
  218. static int fake_resource_2_init(struct kunit_resource *res, void *context)
  219. {
  220. struct kunit_test_resource_context *ctx = context;
  221. KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 2);
  222. res->data = ctx;
  223. return 0;
  224. }
  225. static void fake_resource_2_free(struct kunit_resource *res)
  226. {
  227. struct kunit_test_resource_context *ctx = res->data;
  228. KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 2);
  229. }
  230. static int fake_resource_1_init(struct kunit_resource *res, void *context)
  231. {
  232. struct kunit_test_resource_context *ctx = context;
  233. struct kunit_resource *res2;
  234. res2 = kunit_alloc_and_get_resource(&ctx->test,
  235. fake_resource_2_init,
  236. fake_resource_2_free,
  237. GFP_KERNEL,
  238. ctx);
  239. KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 1);
  240. res->data = ctx;
  241. kunit_put_resource(res2);
  242. return 0;
  243. }
  244. static void fake_resource_1_free(struct kunit_resource *res)
  245. {
  246. struct kunit_test_resource_context *ctx = res->data;
  247. KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 1);
  248. }
  249. /*
  250. * TODO([email protected]): replace the arrays that keep track of the
  251. * order of allocation and freeing with strict mocks using the IN_SEQUENCE macro
  252. * to assert allocation and freeing order when the feature becomes available.
  253. */
  254. static void kunit_resource_test_proper_free_ordering(struct kunit *test)
  255. {
  256. struct kunit_test_resource_context *ctx = test->priv;
  257. struct kunit_resource *res;
  258. /* fake_resource_1 allocates a fake_resource_2 in its init. */
  259. res = kunit_alloc_and_get_resource(&ctx->test,
  260. fake_resource_1_init,
  261. fake_resource_1_free,
  262. GFP_KERNEL,
  263. ctx);
  264. /*
  265. * Since fake_resource_2_init calls KUNIT_RESOURCE_TEST_MARK_ORDER
  266. * before returning to fake_resource_1_init, it should be the first to
  267. * put its key in the allocate_order array.
  268. */
  269. KUNIT_EXPECT_EQ(test, ctx->allocate_order[0], 2);
  270. KUNIT_EXPECT_EQ(test, ctx->allocate_order[1], 1);
  271. kunit_put_resource(res);
  272. kunit_cleanup(&ctx->test);
  273. /*
  274. * Because fake_resource_2 finishes allocation before fake_resource_1,
  275. * fake_resource_1 should be freed first since it could depend on
  276. * fake_resource_2.
  277. */
  278. KUNIT_EXPECT_EQ(test, ctx->free_order[0], 1);
  279. KUNIT_EXPECT_EQ(test, ctx->free_order[1], 2);
  280. }
  281. static void kunit_resource_test_static(struct kunit *test)
  282. {
  283. struct kunit_test_resource_context ctx;
  284. struct kunit_resource res;
  285. KUNIT_EXPECT_EQ(test, kunit_add_resource(test, NULL, NULL, &res, &ctx),
  286. 0);
  287. KUNIT_EXPECT_PTR_EQ(test, res.data, (void *)&ctx);
  288. kunit_cleanup(test);
  289. KUNIT_EXPECT_TRUE(test, list_empty(&test->resources));
  290. }
  291. static void kunit_resource_test_named(struct kunit *test)
  292. {
  293. struct kunit_resource res1, res2, *found = NULL;
  294. struct kunit_test_resource_context ctx;
  295. KUNIT_EXPECT_EQ(test,
  296. kunit_add_named_resource(test, NULL, NULL, &res1,
  297. "resource_1", &ctx),
  298. 0);
  299. KUNIT_EXPECT_PTR_EQ(test, res1.data, (void *)&ctx);
  300. KUNIT_EXPECT_EQ(test,
  301. kunit_add_named_resource(test, NULL, NULL, &res1,
  302. "resource_1", &ctx),
  303. -EEXIST);
  304. KUNIT_EXPECT_EQ(test,
  305. kunit_add_named_resource(test, NULL, NULL, &res2,
  306. "resource_2", &ctx),
  307. 0);
  308. found = kunit_find_named_resource(test, "resource_1");
  309. KUNIT_EXPECT_PTR_EQ(test, found, &res1);
  310. if (found)
  311. kunit_put_resource(&res1);
  312. KUNIT_EXPECT_EQ(test, kunit_destroy_named_resource(test, "resource_2"),
  313. 0);
  314. kunit_cleanup(test);
  315. KUNIT_EXPECT_TRUE(test, list_empty(&test->resources));
  316. }
  317. static int kunit_resource_test_init(struct kunit *test)
  318. {
  319. struct kunit_test_resource_context *ctx =
  320. kzalloc(sizeof(*ctx), GFP_KERNEL);
  321. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
  322. test->priv = ctx;
  323. kunit_init_test(&ctx->test, "test_test_context", NULL);
  324. return 0;
  325. }
  326. static void kunit_resource_test_exit(struct kunit *test)
  327. {
  328. struct kunit_test_resource_context *ctx = test->priv;
  329. kunit_cleanup(&ctx->test);
  330. kfree(ctx);
  331. }
  332. static struct kunit_case kunit_resource_test_cases[] = {
  333. KUNIT_CASE(kunit_resource_test_init_resources),
  334. KUNIT_CASE(kunit_resource_test_alloc_resource),
  335. KUNIT_CASE(kunit_resource_test_destroy_resource),
  336. KUNIT_CASE(kunit_resource_test_remove_resource),
  337. KUNIT_CASE(kunit_resource_test_cleanup_resources),
  338. KUNIT_CASE(kunit_resource_test_proper_free_ordering),
  339. KUNIT_CASE(kunit_resource_test_static),
  340. KUNIT_CASE(kunit_resource_test_named),
  341. {}
  342. };
  343. static struct kunit_suite kunit_resource_test_suite = {
  344. .name = "kunit-resource-test",
  345. .init = kunit_resource_test_init,
  346. .exit = kunit_resource_test_exit,
  347. .test_cases = kunit_resource_test_cases,
  348. };
  349. static void kunit_log_test(struct kunit *test);
  350. static struct kunit_case kunit_log_test_cases[] = {
  351. KUNIT_CASE(kunit_log_test),
  352. {}
  353. };
  354. static struct kunit_suite kunit_log_test_suite = {
  355. .name = "kunit-log-test",
  356. .test_cases = kunit_log_test_cases,
  357. };
  358. static void kunit_log_test(struct kunit *test)
  359. {
  360. struct kunit_suite suite;
  361. suite.log = kunit_kzalloc(test, KUNIT_LOG_SIZE, GFP_KERNEL);
  362. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, suite.log);
  363. kunit_log(KERN_INFO, test, "put this in log.");
  364. kunit_log(KERN_INFO, test, "this too.");
  365. kunit_log(KERN_INFO, &suite, "add to suite log.");
  366. kunit_log(KERN_INFO, &suite, "along with this.");
  367. #ifdef CONFIG_KUNIT_DEBUGFS
  368. KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
  369. strstr(test->log, "put this in log."));
  370. KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
  371. strstr(test->log, "this too."));
  372. KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
  373. strstr(suite.log, "add to suite log."));
  374. KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
  375. strstr(suite.log, "along with this."));
  376. #else
  377. KUNIT_EXPECT_NULL(test, test->log);
  378. #endif
  379. }
  380. static void kunit_status_set_failure_test(struct kunit *test)
  381. {
  382. struct kunit fake;
  383. kunit_init_test(&fake, "fake test", NULL);
  384. KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_SUCCESS);
  385. kunit_set_failure(&fake);
  386. KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_FAILURE);
  387. }
  388. static void kunit_status_mark_skipped_test(struct kunit *test)
  389. {
  390. struct kunit fake;
  391. kunit_init_test(&fake, "fake test", NULL);
  392. /* Before: Should be SUCCESS with no comment. */
  393. KUNIT_EXPECT_EQ(test, fake.status, KUNIT_SUCCESS);
  394. KUNIT_EXPECT_STREQ(test, fake.status_comment, "");
  395. /* Mark the test as skipped. */
  396. kunit_mark_skipped(&fake, "Accepts format string: %s", "YES");
  397. /* After: Should be SKIPPED with our comment. */
  398. KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_SKIPPED);
  399. KUNIT_EXPECT_STREQ(test, fake.status_comment, "Accepts format string: YES");
  400. }
  401. static struct kunit_case kunit_status_test_cases[] = {
  402. KUNIT_CASE(kunit_status_set_failure_test),
  403. KUNIT_CASE(kunit_status_mark_skipped_test),
  404. {}
  405. };
  406. static struct kunit_suite kunit_status_test_suite = {
  407. .name = "kunit_status",
  408. .test_cases = kunit_status_test_cases,
  409. };
  410. kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite,
  411. &kunit_log_test_suite, &kunit_status_test_suite);
  412. MODULE_LICENSE("GPL v2");