kunit-test.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  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 "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. /*
  130. * Note: tests below use kunit_alloc_and_get_resource(), so as a consequence
  131. * they have a reference to the associated resource that they must release
  132. * via kunit_put_resource(). In normal operation, users will only
  133. * have to do this for cases where they use kunit_find_resource(), and the
  134. * kunit_alloc_resource() function will be used (which does not take a
  135. * resource reference).
  136. */
  137. static void kunit_resource_test_destroy_resource(struct kunit *test)
  138. {
  139. struct kunit_test_resource_context *ctx = test->priv;
  140. struct kunit_resource *res = kunit_alloc_and_get_resource(
  141. &ctx->test,
  142. fake_resource_init,
  143. fake_resource_free,
  144. GFP_KERNEL,
  145. ctx);
  146. kunit_put_resource(res);
  147. KUNIT_ASSERT_FALSE(test,
  148. kunit_destroy_resource(&ctx->test,
  149. kunit_resource_instance_match,
  150. res->data));
  151. KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized);
  152. KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
  153. }
  154. static void kunit_resource_test_cleanup_resources(struct kunit *test)
  155. {
  156. int i;
  157. struct kunit_test_resource_context *ctx = test->priv;
  158. struct kunit_resource *resources[5];
  159. for (i = 0; i < ARRAY_SIZE(resources); i++) {
  160. resources[i] = kunit_alloc_and_get_resource(&ctx->test,
  161. fake_resource_init,
  162. fake_resource_free,
  163. GFP_KERNEL,
  164. ctx);
  165. kunit_put_resource(resources[i]);
  166. }
  167. kunit_cleanup(&ctx->test);
  168. KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
  169. }
  170. static void kunit_resource_test_mark_order(int order_array[],
  171. size_t order_size,
  172. int key)
  173. {
  174. int i;
  175. for (i = 0; i < order_size && order_array[i]; i++)
  176. ;
  177. order_array[i] = key;
  178. }
  179. #define KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, order_field, key) \
  180. kunit_resource_test_mark_order(ctx->order_field, \
  181. ARRAY_SIZE(ctx->order_field), \
  182. key)
  183. static int fake_resource_2_init(struct kunit_resource *res, void *context)
  184. {
  185. struct kunit_test_resource_context *ctx = context;
  186. KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 2);
  187. res->data = ctx;
  188. return 0;
  189. }
  190. static void fake_resource_2_free(struct kunit_resource *res)
  191. {
  192. struct kunit_test_resource_context *ctx = res->data;
  193. KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 2);
  194. }
  195. static int fake_resource_1_init(struct kunit_resource *res, void *context)
  196. {
  197. struct kunit_test_resource_context *ctx = context;
  198. struct kunit_resource *res2;
  199. res2 = kunit_alloc_and_get_resource(&ctx->test,
  200. fake_resource_2_init,
  201. fake_resource_2_free,
  202. GFP_KERNEL,
  203. ctx);
  204. KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 1);
  205. res->data = ctx;
  206. kunit_put_resource(res2);
  207. return 0;
  208. }
  209. static void fake_resource_1_free(struct kunit_resource *res)
  210. {
  211. struct kunit_test_resource_context *ctx = res->data;
  212. KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 1);
  213. }
  214. /*
  215. * TODO(brendanhiggins@google.com): replace the arrays that keep track of the
  216. * order of allocation and freeing with strict mocks using the IN_SEQUENCE macro
  217. * to assert allocation and freeing order when the feature becomes available.
  218. */
  219. static void kunit_resource_test_proper_free_ordering(struct kunit *test)
  220. {
  221. struct kunit_test_resource_context *ctx = test->priv;
  222. struct kunit_resource *res;
  223. /* fake_resource_1 allocates a fake_resource_2 in its init. */
  224. res = kunit_alloc_and_get_resource(&ctx->test,
  225. fake_resource_1_init,
  226. fake_resource_1_free,
  227. GFP_KERNEL,
  228. ctx);
  229. /*
  230. * Since fake_resource_2_init calls KUNIT_RESOURCE_TEST_MARK_ORDER
  231. * before returning to fake_resource_1_init, it should be the first to
  232. * put its key in the allocate_order array.
  233. */
  234. KUNIT_EXPECT_EQ(test, ctx->allocate_order[0], 2);
  235. KUNIT_EXPECT_EQ(test, ctx->allocate_order[1], 1);
  236. kunit_put_resource(res);
  237. kunit_cleanup(&ctx->test);
  238. /*
  239. * Because fake_resource_2 finishes allocation before fake_resource_1,
  240. * fake_resource_1 should be freed first since it could depend on
  241. * fake_resource_2.
  242. */
  243. KUNIT_EXPECT_EQ(test, ctx->free_order[0], 1);
  244. KUNIT_EXPECT_EQ(test, ctx->free_order[1], 2);
  245. }
  246. static void kunit_resource_test_static(struct kunit *test)
  247. {
  248. struct kunit_test_resource_context ctx;
  249. struct kunit_resource res;
  250. KUNIT_EXPECT_EQ(test, kunit_add_resource(test, NULL, NULL, &res, &ctx),
  251. 0);
  252. KUNIT_EXPECT_PTR_EQ(test, res.data, (void *)&ctx);
  253. kunit_cleanup(test);
  254. KUNIT_EXPECT_TRUE(test, list_empty(&test->resources));
  255. }
  256. static void kunit_resource_test_named(struct kunit *test)
  257. {
  258. struct kunit_resource res1, res2, *found = NULL;
  259. struct kunit_test_resource_context ctx;
  260. KUNIT_EXPECT_EQ(test,
  261. kunit_add_named_resource(test, NULL, NULL, &res1,
  262. "resource_1", &ctx),
  263. 0);
  264. KUNIT_EXPECT_PTR_EQ(test, res1.data, (void *)&ctx);
  265. KUNIT_EXPECT_EQ(test,
  266. kunit_add_named_resource(test, NULL, NULL, &res1,
  267. "resource_1", &ctx),
  268. -EEXIST);
  269. KUNIT_EXPECT_EQ(test,
  270. kunit_add_named_resource(test, NULL, NULL, &res2,
  271. "resource_2", &ctx),
  272. 0);
  273. found = kunit_find_named_resource(test, "resource_1");
  274. KUNIT_EXPECT_PTR_EQ(test, found, &res1);
  275. if (found)
  276. kunit_put_resource(&res1);
  277. KUNIT_EXPECT_EQ(test, kunit_destroy_named_resource(test, "resource_2"),
  278. 0);
  279. kunit_cleanup(test);
  280. KUNIT_EXPECT_TRUE(test, list_empty(&test->resources));
  281. }
  282. static int kunit_resource_test_init(struct kunit *test)
  283. {
  284. struct kunit_test_resource_context *ctx =
  285. kzalloc(sizeof(*ctx), GFP_KERNEL);
  286. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
  287. test->priv = ctx;
  288. kunit_init_test(&ctx->test, "test_test_context", NULL);
  289. return 0;
  290. }
  291. static void kunit_resource_test_exit(struct kunit *test)
  292. {
  293. struct kunit_test_resource_context *ctx = test->priv;
  294. kunit_cleanup(&ctx->test);
  295. kfree(ctx);
  296. }
  297. static struct kunit_case kunit_resource_test_cases[] = {
  298. KUNIT_CASE(kunit_resource_test_init_resources),
  299. KUNIT_CASE(kunit_resource_test_alloc_resource),
  300. KUNIT_CASE(kunit_resource_test_destroy_resource),
  301. KUNIT_CASE(kunit_resource_test_cleanup_resources),
  302. KUNIT_CASE(kunit_resource_test_proper_free_ordering),
  303. KUNIT_CASE(kunit_resource_test_static),
  304. KUNIT_CASE(kunit_resource_test_named),
  305. {}
  306. };
  307. static struct kunit_suite kunit_resource_test_suite = {
  308. .name = "kunit-resource-test",
  309. .init = kunit_resource_test_init,
  310. .exit = kunit_resource_test_exit,
  311. .test_cases = kunit_resource_test_cases,
  312. };
  313. static void kunit_log_test(struct kunit *test);
  314. static struct kunit_case kunit_log_test_cases[] = {
  315. KUNIT_CASE(kunit_log_test),
  316. {}
  317. };
  318. static struct kunit_suite kunit_log_test_suite = {
  319. .name = "kunit-log-test",
  320. .test_cases = kunit_log_test_cases,
  321. };
  322. static void kunit_log_test(struct kunit *test)
  323. {
  324. struct kunit_suite *suite = &kunit_log_test_suite;
  325. kunit_log(KERN_INFO, test, "put this in log.");
  326. kunit_log(KERN_INFO, test, "this too.");
  327. kunit_log(KERN_INFO, suite, "add to suite log.");
  328. kunit_log(KERN_INFO, suite, "along with this.");
  329. #ifdef CONFIG_KUNIT_DEBUGFS
  330. KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
  331. strstr(test->log, "put this in log."));
  332. KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
  333. strstr(test->log, "this too."));
  334. KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
  335. strstr(suite->log, "add to suite log."));
  336. KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
  337. strstr(suite->log, "along with this."));
  338. #else
  339. KUNIT_EXPECT_PTR_EQ(test, test->log, (char *)NULL);
  340. KUNIT_EXPECT_PTR_EQ(test, suite->log, (char *)NULL);
  341. #endif
  342. }
  343. kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite,
  344. &kunit_log_test_suite);
  345. MODULE_LICENSE("GPL v2");