common-mocks.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Common KUnit mock call arg matchers and formatters.
  4. *
  5. * Copyright (C) 2020, Google LLC.
  6. * Author: Brendan Higgins <[email protected]>
  7. */
  8. #include <linux/kernel.h>
  9. #include <kunit/mock.h>
  10. static bool match_any(struct mock_param_matcher *pmatcher,
  11. struct kunit_stream *stream,
  12. const void *actual)
  13. {
  14. kunit_stream_add(stream, "don't care");
  15. return true;
  16. }
  17. static struct mock_param_matcher any_matcher = {
  18. .match = match_any,
  19. };
  20. struct mock_param_matcher *kunit_any(struct kunit *test)
  21. {
  22. return &any_matcher;
  23. }
  24. #define DEFINE_MATCHER_STRUCT(type_name, type) \
  25. struct mock_##type_name##_matcher { \
  26. struct mock_param_matcher matcher; \
  27. type expected; \
  28. }
  29. #define DEFINE_TO_MATCHER_STRUCT(type_name) \
  30. struct mock_##type_name##_matcher * \
  31. to_mock_##type_name##_matcher( \
  32. struct mock_param_matcher *matcher) \
  33. { \
  34. return container_of(matcher, \
  35. struct mock_##type_name##_matcher, \
  36. matcher); \
  37. }
  38. #define TYPE_FRMT(type_name) FORMAT_##type_name
  39. #define FORMAT_u8 "%hu"
  40. #define FORMAT_u16 "%hu"
  41. #define FORMAT_u32 "%u"
  42. #define FORMAT_u64 "%llu"
  43. #define FORMAT_char "%c"
  44. #define FORMAT_uchar "%c"
  45. #define FORMAT_schar "%c"
  46. #define FORMAT_short "%hd"
  47. #define FORMAT_ushort "%hu"
  48. #define FORMAT_int "%d"
  49. #define FORMAT_uint "%u"
  50. #define FORMAT_long "%ld"
  51. #define FORMAT_ulong "%lu"
  52. #define FORMAT_longlong "%lld"
  53. #define FORMAT_ulonglong "%llu"
  54. #define FORMAT_ptr "%pK"
  55. #define CMP_FORMAT(type_name, msg, op) \
  56. TYPE_FRMT(type_name) msg " " #op " " TYPE_FRMT(type_name)
  57. #define DEFINE_MATCH_FUNC(type_name, type, op_name, op) \
  58. static bool match_##type_name##_##op_name( \
  59. struct mock_param_matcher *pmatcher, \
  60. struct kunit_stream *stream, \
  61. const void *pactual) \
  62. { \
  63. struct mock_##type_name##_matcher *matcher = \
  64. to_mock_##type_name##_matcher(pmatcher); \
  65. type actual = *((type *) pactual); \
  66. bool matches = actual op matcher->expected; \
  67. \
  68. if (matches) \
  69. kunit_stream_add(stream, \
  70. CMP_FORMAT(type_name, "", op),\
  71. actual, \
  72. matcher->expected); \
  73. else \
  74. kunit_stream_add(stream, \
  75. CMP_FORMAT(type_name, " not", op), \
  76. actual, \
  77. matcher->expected); \
  78. \
  79. return matches; \
  80. }
  81. #define DEFINE_MATCH_FACTORY(type_name, type, op_name) \
  82. struct mock_param_matcher *kunit_##type_name##_##op_name( \
  83. struct kunit *test, type expected) \
  84. { \
  85. struct mock_##type_name##_matcher *matcher; \
  86. \
  87. matcher = kunit_kmalloc(test, \
  88. sizeof(*matcher), \
  89. GFP_KERNEL); \
  90. if (!matcher) \
  91. return NULL; \
  92. \
  93. matcher->matcher.match = match_##type_name##_##op_name;\
  94. matcher->expected = expected; \
  95. return &matcher->matcher; \
  96. }
  97. #define DEFINE_MATCHER_WITH_TYPENAME(type_name, type) \
  98. DEFINE_MATCHER_STRUCT(type_name, type); \
  99. DEFINE_TO_MATCHER_STRUCT(type_name) \
  100. DEFINE_MATCH_FUNC(type_name, type, eq, ==) \
  101. DEFINE_MATCH_FACTORY(type_name, type, eq) \
  102. DEFINE_MATCH_FUNC(type_name, type, ne, !=) \
  103. DEFINE_MATCH_FACTORY(type_name, type, ne) \
  104. DEFINE_MATCH_FUNC(type_name, type, le, <=) \
  105. DEFINE_MATCH_FACTORY(type_name, type, le) \
  106. DEFINE_MATCH_FUNC(type_name, type, lt, <) \
  107. DEFINE_MATCH_FACTORY(type_name, type, lt) \
  108. DEFINE_MATCH_FUNC(type_name, type, ge, >=) \
  109. DEFINE_MATCH_FACTORY(type_name, type, ge) \
  110. DEFINE_MATCH_FUNC(type_name, type, gt, >) \
  111. DEFINE_MATCH_FACTORY(type_name, type, gt)
  112. #define DEFINE_MATCHER(type) DEFINE_MATCHER_WITH_TYPENAME(type, type)
  113. DEFINE_MATCHER(u8);
  114. DEFINE_MATCHER(u16);
  115. DEFINE_MATCHER(u32);
  116. DEFINE_MATCHER(u64);
  117. DEFINE_MATCHER(char);
  118. DEFINE_MATCHER_WITH_TYPENAME(uchar, unsigned char);
  119. DEFINE_MATCHER_WITH_TYPENAME(schar, signed char);
  120. DEFINE_MATCHER(short);
  121. DEFINE_MATCHER_WITH_TYPENAME(ushort, unsigned short);
  122. DEFINE_MATCHER(int);
  123. DEFINE_MATCHER_WITH_TYPENAME(uint, unsigned int);
  124. DEFINE_MATCHER(long);
  125. DEFINE_MATCHER_WITH_TYPENAME(ulong, unsigned long);
  126. DEFINE_MATCHER_WITH_TYPENAME(longlong, long long);
  127. DEFINE_MATCHER_WITH_TYPENAME(ulonglong, unsigned long long);
  128. DEFINE_MATCHER_WITH_TYPENAME(ptr, void *);
  129. struct mock_memeq_matcher {
  130. struct mock_param_matcher matcher;
  131. const void *expected;
  132. size_t size;
  133. };
  134. static bool match_memeq(struct mock_param_matcher *pmatcher,
  135. struct kunit_stream *stream,
  136. const void *pactual)
  137. {
  138. struct mock_memeq_matcher *matcher =
  139. container_of(pmatcher,
  140. struct mock_memeq_matcher,
  141. matcher);
  142. const void *actual = CONVERT_TO_ACTUAL_TYPE(const void *, pactual);
  143. bool matches = !memcmp(actual, matcher->expected, matcher->size);
  144. int i;
  145. for (i = 0; i < matcher->size; i++)
  146. kunit_stream_add(stream, "%02x, ", ((const char *) actual)[i]);
  147. if (matches)
  148. kunit_stream_add(stream, "== ");
  149. else
  150. kunit_stream_add(stream, "!= ");
  151. for (i = 0; i < matcher->size; i++)
  152. kunit_stream_add(stream,
  153. "%02x, ",
  154. ((const char *) matcher->expected)[i]);
  155. return matches;
  156. }
  157. struct mock_param_matcher *kunit_memeq(struct kunit *test,
  158. const void *buf,
  159. size_t size)
  160. {
  161. struct mock_memeq_matcher *matcher;
  162. matcher = kunit_kzalloc(test, sizeof(*matcher), GFP_KERNEL);
  163. if (!matcher)
  164. return NULL;
  165. matcher->matcher.match = match_memeq;
  166. matcher->expected = buf;
  167. matcher->size = size;
  168. return &matcher->matcher;
  169. }
  170. struct mock_streq_matcher {
  171. struct mock_param_matcher matcher;
  172. const char *expected;
  173. };
  174. static bool match_streq(struct mock_param_matcher *pmatcher,
  175. struct kunit_stream *stream,
  176. const void *pactual)
  177. {
  178. struct mock_streq_matcher *matcher =
  179. container_of(pmatcher,
  180. struct mock_streq_matcher,
  181. matcher);
  182. const char *actual = CONVERT_TO_ACTUAL_TYPE(const char *, pactual);
  183. bool matches = !strcmp(actual, matcher->expected);
  184. if (matches)
  185. kunit_stream_add(stream, "%s == %s", actual, matcher->expected);
  186. else
  187. kunit_stream_add(stream, "%s != %s", actual, matcher->expected);
  188. return matches;
  189. }
  190. struct mock_param_matcher *kunit_streq(struct kunit *test, const char *str)
  191. {
  192. struct mock_streq_matcher *matcher;
  193. matcher = kunit_kzalloc(test, sizeof(*matcher), GFP_KERNEL);
  194. if (!matcher)
  195. return NULL;
  196. matcher->matcher.match = match_streq;
  197. matcher->expected = str;
  198. return &matcher->matcher;
  199. }
  200. struct mock_str_contains_matcher {
  201. struct mock_param_matcher matcher;
  202. const char *needle;
  203. };
  204. static bool match_str_contains(struct mock_param_matcher *pmatcher,
  205. struct kunit_stream *stream,
  206. const void *phaystack)
  207. {
  208. struct mock_str_contains_matcher *matcher =
  209. container_of(pmatcher,
  210. struct mock_str_contains_matcher,
  211. matcher);
  212. const char *haystack = CONVERT_TO_ACTUAL_TYPE(const char *, phaystack);
  213. bool matches = strstr(haystack, matcher->needle);
  214. if (matches)
  215. kunit_stream_add(stream,
  216. "'%s' found in '%s'",
  217. matcher->needle,
  218. haystack);
  219. else
  220. kunit_stream_add(stream,
  221. "'%s' not found in '%s'",
  222. matcher->needle,
  223. haystack);
  224. return matches;
  225. }
  226. struct mock_param_matcher *kunit_str_contains(struct kunit *test,
  227. const char *str)
  228. {
  229. struct mock_str_contains_matcher *matcher;
  230. matcher = kunit_kzalloc(test, sizeof(*matcher), GFP_KERNEL);
  231. if (!matcher)
  232. return NULL;
  233. matcher->matcher.match = match_str_contains;
  234. matcher->needle = str;
  235. return &matcher->matcher;
  236. }
  237. struct mock_param_matcher *kunit_va_format_cmp(
  238. struct kunit *test,
  239. struct mock_param_matcher *fmt_matcher,
  240. struct mock_param_matcher *va_matcher)
  241. {
  242. struct mock_struct_matcher_entry *entries;
  243. entries = kunit_kzalloc(test, sizeof(*entries) * 3, GFP_KERNEL);
  244. if (!entries)
  245. return NULL;
  246. INIT_MOCK_STRUCT_MATCHER_ENTRY(&entries[0],
  247. struct va_format,
  248. fmt,
  249. fmt_matcher);
  250. INIT_MOCK_STRUCT_MATCHER_ENTRY(&entries[1],
  251. struct va_format,
  252. va,
  253. va_matcher);
  254. INIT_MOCK_STRUCT_MATCHER_ENTRY_LAST(&entries[2]);
  255. return kunit_struct_cmp(test, "va_format", entries);
  256. }
  257. struct mock_struct_matcher {
  258. struct mock_param_matcher matcher;
  259. const char *struct_name;
  260. struct mock_struct_matcher_entry *entries;
  261. };
  262. static bool match_struct(struct mock_param_matcher *pmatcher,
  263. struct kunit_stream *stream,
  264. const void *pactual)
  265. {
  266. struct mock_struct_matcher *matcher =
  267. container_of(pmatcher,
  268. struct mock_struct_matcher,
  269. matcher);
  270. struct mock_struct_matcher_entry *entry;
  271. const char *actual = CONVERT_TO_ACTUAL_TYPE(const char *, pactual);
  272. const char *member_ptr;
  273. bool matches = true, tmp;
  274. kunit_stream_add(stream, "struct %s {", matcher->struct_name);
  275. for (entry = matcher->entries; entry->matcher; entry++) {
  276. member_ptr = actual + entry->member_offset;
  277. tmp = entry->matcher->match(entry->matcher, stream, member_ptr);
  278. matches = matches && tmp;
  279. kunit_stream_add(stream, ", ");
  280. }
  281. kunit_stream_add(stream, "}");
  282. return matches;
  283. }
  284. struct mock_param_matcher *kunit_struct_cmp(
  285. struct kunit *test,
  286. const char *struct_name,
  287. struct mock_struct_matcher_entry *entries)
  288. {
  289. struct mock_struct_matcher *matcher;
  290. matcher = kunit_kzalloc(test, sizeof(*matcher), GFP_KERNEL);
  291. if (!matcher)
  292. return NULL;
  293. matcher->matcher.match = match_struct;
  294. matcher->struct_name = struct_name;
  295. matcher->entries = entries;
  296. return &matcher->matcher;
  297. }
  298. static bool match_and_capture_param(struct mock_param_matcher *pmatcher,
  299. struct kunit_stream *stream,
  300. const void *param)
  301. {
  302. struct mock_param_capturer *capturer =
  303. container_of(pmatcher,
  304. struct mock_param_capturer,
  305. matcher);
  306. struct mock_param_matcher *child_matcher = capturer->child_matcher;
  307. bool matches;
  308. matches = child_matcher->match(child_matcher, stream, param);
  309. if (matches)
  310. capturer->captured_param = capturer->capture_param(stream->test,
  311. param);
  312. return matches;
  313. }
  314. struct mock_param_capturer *mock_param_capturer_create(
  315. struct kunit *test,
  316. struct mock_param_matcher *child_matcher,
  317. void *(*capture_param)(struct kunit *, const void *))
  318. {
  319. struct mock_param_capturer *capturer;
  320. capturer = kunit_kzalloc(test, sizeof(*capturer), GFP_KERNEL);
  321. if (!capturer)
  322. return NULL;
  323. capturer->matcher.match = match_and_capture_param;
  324. capturer->child_matcher = child_matcher;
  325. capturer->capture_param = capture_param;
  326. capturer->captured_param = NULL;
  327. return capturer;
  328. }
  329. static void *mock_capture_int(struct kunit *test, const void *param)
  330. {
  331. int value = CONVERT_TO_ACTUAL_TYPE(int, param);
  332. int *pvalue;
  333. pvalue = kunit_kzalloc(test, sizeof(*pvalue), GFP_KERNEL);
  334. if (!pvalue)
  335. return NULL;
  336. *pvalue = value;
  337. return pvalue;
  338. }
  339. struct mock_param_capturer *mock_int_capturer_create(
  340. struct kunit *test, struct mock_param_matcher *child_matcher)
  341. {
  342. return mock_param_capturer_create(test,
  343. child_matcher,
  344. mock_capture_int);
  345. }
  346. static void *mock_capture_ptr(struct kunit *test, const void *param)
  347. {
  348. void *ptr = CONVERT_TO_ACTUAL_TYPE(void *, param);
  349. void **pptr;
  350. pptr = kunit_kzalloc(test, sizeof(*pptr), GFP_KERNEL);
  351. *pptr = ptr;
  352. return pptr;
  353. }
  354. struct mock_param_capturer *mock_ptr_capturer_create(
  355. struct kunit *test, struct mock_param_matcher *child_matcher)
  356. {
  357. return mock_param_capturer_create(test,
  358. child_matcher,
  359. mock_capture_ptr);
  360. }
  361. #define DEFINE_RETURN_ACTION_STRUCT(type_name, type) \
  362. struct mock_##type_name##_action { \
  363. struct mock_action action; \
  364. type ret; \
  365. }
  366. #define DEFINE_RETURN_ACTION_FUNC(type_name, type) \
  367. void *do_##type_name##_return(struct mock_action *paction, \
  368. const void **params, \
  369. int len) \
  370. { \
  371. struct mock_##type_name##_action *action = \
  372. container_of(paction, \
  373. struct mock_##type_name##_action,\
  374. action); \
  375. \
  376. return (void *) &action->ret; \
  377. }
  378. #define DEFINE_RETURN_ACTION_FACTORY(type_name, type) \
  379. struct mock_action *kunit_##type_name##_return( \
  380. struct kunit *test, \
  381. type ret) \
  382. { \
  383. struct mock_##type_name##_action *action; \
  384. \
  385. action = kunit_kmalloc(test, \
  386. sizeof(*action), \
  387. GFP_KERNEL); \
  388. if (!action) \
  389. return NULL; \
  390. \
  391. action->action.do_action = do_##type_name##_return; \
  392. action->ret = ret; \
  393. \
  394. return &action->action; \
  395. }
  396. #define DEFINE_RETURN_ACTION_WITH_TYPENAME(type_name, type) \
  397. DEFINE_RETURN_ACTION_STRUCT(type_name, type); \
  398. DEFINE_RETURN_ACTION_FUNC(type_name, type); \
  399. DEFINE_RETURN_ACTION_FACTORY(type_name, type)
  400. #define DEFINE_RETURN_ACTION(type) \
  401. DEFINE_RETURN_ACTION_WITH_TYPENAME(type, type)
  402. DEFINE_RETURN_ACTION(bool);
  403. DEFINE_RETURN_ACTION(u8);
  404. DEFINE_RETURN_ACTION(u16);
  405. DEFINE_RETURN_ACTION(u32);
  406. DEFINE_RETURN_ACTION(u64);
  407. DEFINE_RETURN_ACTION(char);
  408. DEFINE_RETURN_ACTION_WITH_TYPENAME(uchar, unsigned char);
  409. DEFINE_RETURN_ACTION_WITH_TYPENAME(schar, signed char);
  410. DEFINE_RETURN_ACTION(short);
  411. DEFINE_RETURN_ACTION_WITH_TYPENAME(ushort, unsigned short);
  412. DEFINE_RETURN_ACTION(int);
  413. DEFINE_RETURN_ACTION_WITH_TYPENAME(uint, unsigned int);
  414. DEFINE_RETURN_ACTION(long);
  415. DEFINE_RETURN_ACTION_WITH_TYPENAME(ulong, unsigned long);
  416. DEFINE_RETURN_ACTION_WITH_TYPENAME(longlong, long long);
  417. DEFINE_RETURN_ACTION_WITH_TYPENAME(ulonglong, unsigned long long);
  418. DEFINE_RETURN_ACTION_WITH_TYPENAME(ptr, void *);
  419. struct mock_invoke_action {
  420. struct mock_action action;
  421. struct kunit *test;
  422. void *(*invokable)(struct kunit *test, const void *params[], int len);
  423. };
  424. static void *do_invoke(struct mock_action *paction,
  425. const void *params[],
  426. int len)
  427. {
  428. struct mock_invoke_action *action =
  429. container_of(paction,
  430. struct mock_invoke_action,
  431. action);
  432. return action->invokable(action->test, params, len);
  433. }
  434. struct mock_action *invoke(struct kunit *test,
  435. void *(*invokable)(struct kunit *,
  436. const void *params[],
  437. int len))
  438. {
  439. struct mock_invoke_action *action;
  440. action = kunit_kmalloc(test, sizeof(*action), GFP_KERNEL);
  441. if (!action)
  442. return NULL;
  443. action->action.do_action = do_invoke;
  444. action->test = test;
  445. action->invokable = invokable;
  446. return &action->action;
  447. }
  448. struct mock_struct_formatter {
  449. struct mock_param_formatter formatter;
  450. const char *type_name;
  451. struct mock_struct_formatter_entry *entries;
  452. };
  453. static void mock_format_struct(struct mock_param_formatter *pformatter,
  454. struct kunit_stream *stream,
  455. const void *pparam)
  456. {
  457. struct mock_struct_formatter *formatter =
  458. container_of(pformatter,
  459. struct mock_struct_formatter,
  460. formatter);
  461. struct mock_struct_formatter_entry *entry;
  462. const char *param = CONVERT_TO_ACTUAL_TYPE(const char *, pparam);
  463. const char *member_ptr;
  464. kunit_stream_add(stream, "%s {", formatter->type_name);
  465. for (entry = formatter->entries; entry->formatter; entry++) {
  466. member_ptr = param + entry->member_offset;
  467. entry->formatter->format(entry->formatter, stream, member_ptr);
  468. kunit_stream_add(stream, ", ");
  469. }
  470. kunit_stream_add(stream, "}");
  471. }
  472. struct mock_param_formatter *mock_struct_formatter(
  473. struct kunit *test,
  474. const char *type_name,
  475. struct mock_struct_formatter_entry *entries)
  476. {
  477. struct mock_struct_formatter *formatter;
  478. formatter = kunit_kzalloc(test, sizeof(*formatter), GFP_KERNEL);
  479. if (!formatter)
  480. return NULL;
  481. formatter->formatter.type_name = type_name;
  482. formatter->formatter.format = mock_format_struct;
  483. formatter->type_name = type_name;
  484. formatter->entries = entries;
  485. return &formatter->formatter;
  486. }