string_helpers_kunit.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
  2. /*
  3. * Test cases for lib/string_helpers.c module.
  4. */
  5. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  6. #include <kunit/test.h>
  7. #include <linux/array_size.h>
  8. #include <linux/kernel.h>
  9. #include <linux/random.h>
  10. #include <linux/string.h>
  11. #include <linux/string_helpers.h>
  12. static void test_string_check_buf(struct kunit *test,
  13. const char *name, unsigned int flags,
  14. char *in, size_t p,
  15. char *out_real, size_t q_real,
  16. char *out_test, size_t q_test)
  17. {
  18. KUNIT_ASSERT_EQ_MSG(test, q_real, q_test, "name:%s", name);
  19. KUNIT_EXPECT_MEMEQ_MSG(test, out_test, out_real, q_test,
  20. "name:%s", name);
  21. }
  22. struct test_string {
  23. const char *in;
  24. const char *out;
  25. unsigned int flags;
  26. };
  27. static const struct test_string strings[] = {
  28. {
  29. .in = "\\f\\ \\n\\r\\t\\v",
  30. .out = "\f\\ \n\r\t\v",
  31. .flags = UNESCAPE_SPACE,
  32. },
  33. {
  34. .in = "\\40\\1\\387\\0064\\05\\040\\8a\\110\\777",
  35. .out = " \001\00387\0064\005 \\8aH?7",
  36. .flags = UNESCAPE_OCTAL,
  37. },
  38. {
  39. .in = "\\xv\\xa\\x2c\\xD\\x6f2",
  40. .out = "\\xv\n,\ro2",
  41. .flags = UNESCAPE_HEX,
  42. },
  43. {
  44. .in = "\\h\\\\\\\"\\a\\e\\",
  45. .out = "\\h\\\"\a\e\\",
  46. .flags = UNESCAPE_SPECIAL,
  47. },
  48. };
  49. static void test_string_unescape(struct kunit *test,
  50. const char *name, unsigned int flags,
  51. bool inplace)
  52. {
  53. int q_real = 256;
  54. char *in = kunit_kzalloc(test, q_real, GFP_KERNEL);
  55. char *out_test = kunit_kzalloc(test, q_real, GFP_KERNEL);
  56. char *out_real = kunit_kzalloc(test, q_real, GFP_KERNEL);
  57. int i, p = 0, q_test = 0;
  58. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, in);
  59. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, out_test);
  60. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, out_real);
  61. for (i = 0; i < ARRAY_SIZE(strings); i++) {
  62. const char *s = strings[i].in;
  63. int len = strlen(strings[i].in);
  64. /* Copy string to in buffer */
  65. memcpy(&in[p], s, len);
  66. p += len;
  67. /* Copy expected result for given flags */
  68. if (flags & strings[i].flags) {
  69. s = strings[i].out;
  70. len = strlen(strings[i].out);
  71. }
  72. memcpy(&out_test[q_test], s, len);
  73. q_test += len;
  74. }
  75. in[p++] = '\0';
  76. /* Call string_unescape and compare result */
  77. if (inplace) {
  78. memcpy(out_real, in, p);
  79. if (flags == UNESCAPE_ANY)
  80. q_real = string_unescape_any_inplace(out_real);
  81. else
  82. q_real = string_unescape_inplace(out_real, flags);
  83. } else if (flags == UNESCAPE_ANY) {
  84. q_real = string_unescape_any(in, out_real, q_real);
  85. } else {
  86. q_real = string_unescape(in, out_real, q_real, flags);
  87. }
  88. test_string_check_buf(test, name, flags, in, p - 1, out_real, q_real,
  89. out_test, q_test);
  90. }
  91. struct test_string_1 {
  92. const char *out;
  93. unsigned int flags;
  94. };
  95. #define TEST_STRING_2_MAX_S1 32
  96. struct test_string_2 {
  97. const char *in;
  98. struct test_string_1 s1[TEST_STRING_2_MAX_S1];
  99. };
  100. #define TEST_STRING_2_DICT_0 NULL
  101. static const struct test_string_2 escape0[] = {{
  102. .in = "\f\\ \n\r\t\v",
  103. .s1 = {{
  104. .out = "\\f\\ \\n\\r\\t\\v",
  105. .flags = ESCAPE_SPACE,
  106. },{
  107. .out = "\\f\\134\\040\\n\\r\\t\\v",
  108. .flags = ESCAPE_SPACE | ESCAPE_OCTAL,
  109. },{
  110. .out = "\\f\\x5c\\x20\\n\\r\\t\\v",
  111. .flags = ESCAPE_SPACE | ESCAPE_HEX,
  112. },{
  113. /* terminator */
  114. }}
  115. },{
  116. .in = "\\h\\\"\a\e\\",
  117. .s1 = {{
  118. .out = "\\\\h\\\\\\\"\\a\\e\\\\",
  119. .flags = ESCAPE_SPECIAL,
  120. },{
  121. .out = "\\\\\\150\\\\\\\"\\a\\e\\\\",
  122. .flags = ESCAPE_SPECIAL | ESCAPE_OCTAL,
  123. },{
  124. .out = "\\\\\\x68\\\\\\\"\\a\\e\\\\",
  125. .flags = ESCAPE_SPECIAL | ESCAPE_HEX,
  126. },{
  127. /* terminator */
  128. }}
  129. },{
  130. .in = "\eb \\C\007\"\x90\r]",
  131. .s1 = {{
  132. .out = "\eb \\C\007\"\x90\\r]",
  133. .flags = ESCAPE_SPACE,
  134. },{
  135. .out = "\\eb \\\\C\\a\\\"\x90\r]",
  136. .flags = ESCAPE_SPECIAL,
  137. },{
  138. .out = "\\eb \\\\C\\a\\\"\x90\\r]",
  139. .flags = ESCAPE_SPACE | ESCAPE_SPECIAL,
  140. },{
  141. .out = "\\033\\142\\040\\134\\103\\007\\042\\220\\015\\135",
  142. .flags = ESCAPE_OCTAL,
  143. },{
  144. .out = "\\033\\142\\040\\134\\103\\007\\042\\220\\r\\135",
  145. .flags = ESCAPE_SPACE | ESCAPE_OCTAL,
  146. },{
  147. .out = "\\e\\142\\040\\\\\\103\\a\\\"\\220\\015\\135",
  148. .flags = ESCAPE_SPECIAL | ESCAPE_OCTAL,
  149. },{
  150. .out = "\\e\\142\\040\\\\\\103\\a\\\"\\220\\r\\135",
  151. .flags = ESCAPE_SPACE | ESCAPE_SPECIAL | ESCAPE_OCTAL,
  152. },{
  153. .out = "\eb \\C\007\"\x90\r]",
  154. .flags = ESCAPE_NP,
  155. },{
  156. .out = "\eb \\C\007\"\x90\\r]",
  157. .flags = ESCAPE_SPACE | ESCAPE_NP,
  158. },{
  159. .out = "\\eb \\C\\a\"\x90\r]",
  160. .flags = ESCAPE_SPECIAL | ESCAPE_NP,
  161. },{
  162. .out = "\\eb \\C\\a\"\x90\\r]",
  163. .flags = ESCAPE_SPACE | ESCAPE_SPECIAL | ESCAPE_NP,
  164. },{
  165. .out = "\\033b \\C\\007\"\\220\\015]",
  166. .flags = ESCAPE_OCTAL | ESCAPE_NP,
  167. },{
  168. .out = "\\033b \\C\\007\"\\220\\r]",
  169. .flags = ESCAPE_SPACE | ESCAPE_OCTAL | ESCAPE_NP,
  170. },{
  171. .out = "\\eb \\C\\a\"\\220\\r]",
  172. .flags = ESCAPE_SPECIAL | ESCAPE_SPACE | ESCAPE_OCTAL |
  173. ESCAPE_NP,
  174. },{
  175. .out = "\\x1bb \\C\\x07\"\\x90\\x0d]",
  176. .flags = ESCAPE_NP | ESCAPE_HEX,
  177. },{
  178. /* terminator */
  179. }}
  180. },{
  181. .in = "\007 \eb\"\x90\xCF\r",
  182. .s1 = {{
  183. .out = "\007 \eb\"\\220\\317\r",
  184. .flags = ESCAPE_OCTAL | ESCAPE_NA,
  185. },{
  186. .out = "\007 \eb\"\\x90\\xcf\r",
  187. .flags = ESCAPE_HEX | ESCAPE_NA,
  188. },{
  189. .out = "\007 \eb\"\x90\xCF\r",
  190. .flags = ESCAPE_NA,
  191. },{
  192. /* terminator */
  193. }}
  194. },{
  195. /* terminator */
  196. }};
  197. #define TEST_STRING_2_DICT_1 "b\\ \t\r\xCF"
  198. static const struct test_string_2 escape1[] = {{
  199. .in = "\f\\ \n\r\t\v",
  200. .s1 = {{
  201. .out = "\f\\134\\040\n\\015\\011\v",
  202. .flags = ESCAPE_OCTAL,
  203. },{
  204. .out = "\f\\x5c\\x20\n\\x0d\\x09\v",
  205. .flags = ESCAPE_HEX,
  206. },{
  207. .out = "\f\\134\\040\n\\015\\011\v",
  208. .flags = ESCAPE_ANY | ESCAPE_APPEND,
  209. },{
  210. .out = "\\014\\134\\040\\012\\015\\011\\013",
  211. .flags = ESCAPE_OCTAL | ESCAPE_APPEND | ESCAPE_NAP,
  212. },{
  213. .out = "\\x0c\\x5c\\x20\\x0a\\x0d\\x09\\x0b",
  214. .flags = ESCAPE_HEX | ESCAPE_APPEND | ESCAPE_NAP,
  215. },{
  216. .out = "\f\\134\\040\n\\015\\011\v",
  217. .flags = ESCAPE_OCTAL | ESCAPE_APPEND | ESCAPE_NA,
  218. },{
  219. .out = "\f\\x5c\\x20\n\\x0d\\x09\v",
  220. .flags = ESCAPE_HEX | ESCAPE_APPEND | ESCAPE_NA,
  221. },{
  222. /* terminator */
  223. }}
  224. },{
  225. .in = "\\h\\\"\a\xCF\e\\",
  226. .s1 = {{
  227. .out = "\\134h\\134\"\a\\317\e\\134",
  228. .flags = ESCAPE_OCTAL,
  229. },{
  230. .out = "\\134h\\134\"\a\\317\e\\134",
  231. .flags = ESCAPE_ANY | ESCAPE_APPEND,
  232. },{
  233. .out = "\\134h\\134\"\\007\\317\\033\\134",
  234. .flags = ESCAPE_OCTAL | ESCAPE_APPEND | ESCAPE_NAP,
  235. },{
  236. .out = "\\134h\\134\"\a\\317\e\\134",
  237. .flags = ESCAPE_OCTAL | ESCAPE_APPEND | ESCAPE_NA,
  238. },{
  239. /* terminator */
  240. }}
  241. },{
  242. .in = "\eb \\C\007\"\x90\r]",
  243. .s1 = {{
  244. .out = "\e\\142\\040\\134C\007\"\x90\\015]",
  245. .flags = ESCAPE_OCTAL,
  246. },{
  247. /* terminator */
  248. }}
  249. },{
  250. .in = "\007 \eb\"\x90\xCF\r",
  251. .s1 = {{
  252. .out = "\007 \eb\"\x90\xCF\r",
  253. .flags = ESCAPE_NA,
  254. },{
  255. .out = "\007 \eb\"\x90\xCF\r",
  256. .flags = ESCAPE_SPACE | ESCAPE_NA,
  257. },{
  258. .out = "\007 \eb\"\x90\xCF\r",
  259. .flags = ESCAPE_SPECIAL | ESCAPE_NA,
  260. },{
  261. .out = "\007 \eb\"\x90\xCF\r",
  262. .flags = ESCAPE_SPACE | ESCAPE_SPECIAL | ESCAPE_NA,
  263. },{
  264. .out = "\007 \eb\"\x90\\317\r",
  265. .flags = ESCAPE_OCTAL | ESCAPE_NA,
  266. },{
  267. .out = "\007 \eb\"\x90\\317\r",
  268. .flags = ESCAPE_SPACE | ESCAPE_OCTAL | ESCAPE_NA,
  269. },{
  270. .out = "\007 \eb\"\x90\\317\r",
  271. .flags = ESCAPE_SPECIAL | ESCAPE_OCTAL | ESCAPE_NA,
  272. },{
  273. .out = "\007 \eb\"\x90\\317\r",
  274. .flags = ESCAPE_ANY | ESCAPE_NA,
  275. },{
  276. .out = "\007 \eb\"\x90\\xcf\r",
  277. .flags = ESCAPE_HEX | ESCAPE_NA,
  278. },{
  279. .out = "\007 \eb\"\x90\\xcf\r",
  280. .flags = ESCAPE_SPACE | ESCAPE_HEX | ESCAPE_NA,
  281. },{
  282. .out = "\007 \eb\"\x90\\xcf\r",
  283. .flags = ESCAPE_SPECIAL | ESCAPE_HEX | ESCAPE_NA,
  284. },{
  285. .out = "\007 \eb\"\x90\\xcf\r",
  286. .flags = ESCAPE_SPACE | ESCAPE_SPECIAL | ESCAPE_HEX | ESCAPE_NA,
  287. },{
  288. /* terminator */
  289. }}
  290. },{
  291. .in = "\007 \eb\"\x90\xCF\r",
  292. .s1 = {{
  293. .out = "\007 \eb\"\x90\xCF\r",
  294. .flags = ESCAPE_NAP,
  295. },{
  296. .out = "\007 \eb\"\x90\xCF\\r",
  297. .flags = ESCAPE_SPACE | ESCAPE_NAP,
  298. },{
  299. .out = "\007 \eb\"\x90\xCF\r",
  300. .flags = ESCAPE_SPECIAL | ESCAPE_NAP,
  301. },{
  302. .out = "\007 \eb\"\x90\xCF\\r",
  303. .flags = ESCAPE_SPACE | ESCAPE_SPECIAL | ESCAPE_NAP,
  304. },{
  305. .out = "\007 \eb\"\x90\\317\\015",
  306. .flags = ESCAPE_OCTAL | ESCAPE_NAP,
  307. },{
  308. .out = "\007 \eb\"\x90\\317\\r",
  309. .flags = ESCAPE_SPACE | ESCAPE_OCTAL | ESCAPE_NAP,
  310. },{
  311. .out = "\007 \eb\"\x90\\317\\015",
  312. .flags = ESCAPE_SPECIAL | ESCAPE_OCTAL | ESCAPE_NAP,
  313. },{
  314. .out = "\007 \eb\"\x90\\317\r",
  315. .flags = ESCAPE_ANY | ESCAPE_NAP,
  316. },{
  317. .out = "\007 \eb\"\x90\\xcf\\x0d",
  318. .flags = ESCAPE_HEX | ESCAPE_NAP,
  319. },{
  320. .out = "\007 \eb\"\x90\\xcf\\r",
  321. .flags = ESCAPE_SPACE | ESCAPE_HEX | ESCAPE_NAP,
  322. },{
  323. .out = "\007 \eb\"\x90\\xcf\\x0d",
  324. .flags = ESCAPE_SPECIAL | ESCAPE_HEX | ESCAPE_NAP,
  325. },{
  326. .out = "\007 \eb\"\x90\\xcf\\r",
  327. .flags = ESCAPE_SPACE | ESCAPE_SPECIAL | ESCAPE_HEX | ESCAPE_NAP,
  328. },{
  329. /* terminator */
  330. }}
  331. },{
  332. /* terminator */
  333. }};
  334. static const struct test_string strings_upper[] = {
  335. {
  336. .in = "abcdefgh1234567890test",
  337. .out = "ABCDEFGH1234567890TEST",
  338. },
  339. {
  340. .in = "abCdeFgH1234567890TesT",
  341. .out = "ABCDEFGH1234567890TEST",
  342. },
  343. };
  344. static const struct test_string strings_lower[] = {
  345. {
  346. .in = "ABCDEFGH1234567890TEST",
  347. .out = "abcdefgh1234567890test",
  348. },
  349. {
  350. .in = "abCdeFgH1234567890TesT",
  351. .out = "abcdefgh1234567890test",
  352. },
  353. };
  354. static const char *test_string_find_match(const struct test_string_2 *s2,
  355. unsigned int flags)
  356. {
  357. const struct test_string_1 *s1 = s2->s1;
  358. unsigned int i;
  359. if (!flags)
  360. return s2->in;
  361. /* Test cases are NULL-aware */
  362. flags &= ~ESCAPE_NULL;
  363. /* ESCAPE_OCTAL has a higher priority */
  364. if (flags & ESCAPE_OCTAL)
  365. flags &= ~ESCAPE_HEX;
  366. for (i = 0; i < TEST_STRING_2_MAX_S1 && s1->out; i++, s1++)
  367. if (s1->flags == flags)
  368. return s1->out;
  369. return NULL;
  370. }
  371. static void
  372. test_string_escape_overflow(struct kunit *test,
  373. const char *in, int p, unsigned int flags, const char *esc,
  374. int q_test, const char *name)
  375. {
  376. int q_real;
  377. q_real = string_escape_mem(in, p, NULL, 0, flags, esc);
  378. KUNIT_EXPECT_EQ_MSG(test, q_real, q_test, "name:%s: flags:%#x", name, flags);
  379. }
  380. static void test_string_escape(struct kunit *test, const char *name,
  381. const struct test_string_2 *s2,
  382. unsigned int flags, const char *esc)
  383. {
  384. size_t out_size = 512;
  385. char *out_test = kunit_kzalloc(test, out_size, GFP_KERNEL);
  386. char *out_real = kunit_kzalloc(test, out_size, GFP_KERNEL);
  387. char *in = kunit_kzalloc(test, 256, GFP_KERNEL);
  388. int p = 0, q_test = 0;
  389. int q_real;
  390. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, out_test);
  391. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, out_real);
  392. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, in);
  393. for (; s2->in; s2++) {
  394. const char *out;
  395. int len;
  396. /* NULL injection */
  397. if (flags & ESCAPE_NULL) {
  398. in[p++] = '\0';
  399. /* '\0' passes isascii() test */
  400. if (flags & ESCAPE_NA && !(flags & ESCAPE_APPEND && esc)) {
  401. out_test[q_test++] = '\0';
  402. } else {
  403. out_test[q_test++] = '\\';
  404. out_test[q_test++] = '0';
  405. }
  406. }
  407. /* Don't try strings that have no output */
  408. out = test_string_find_match(s2, flags);
  409. if (!out)
  410. continue;
  411. /* Copy string to in buffer */
  412. len = strlen(s2->in);
  413. memcpy(&in[p], s2->in, len);
  414. p += len;
  415. /* Copy expected result for given flags */
  416. len = strlen(out);
  417. memcpy(&out_test[q_test], out, len);
  418. q_test += len;
  419. }
  420. q_real = string_escape_mem(in, p, out_real, out_size, flags, esc);
  421. test_string_check_buf(test, name, flags, in, p, out_real, q_real, out_test,
  422. q_test);
  423. test_string_escape_overflow(test, in, p, flags, esc, q_test, name);
  424. }
  425. #define string_get_size_maxbuf 16
  426. #define test_string_get_size_one(size, blk_size, exp_result10, exp_result2) \
  427. do { \
  428. BUILD_BUG_ON(sizeof(exp_result10) >= string_get_size_maxbuf); \
  429. BUILD_BUG_ON(sizeof(exp_result2) >= string_get_size_maxbuf); \
  430. __test_string_get_size(test, (size), (blk_size), (exp_result10), \
  431. (exp_result2)); \
  432. } while (0)
  433. static void test_string_get_size_check(struct kunit *test,
  434. const char *units,
  435. const char *exp,
  436. char *res,
  437. const u64 size,
  438. const u64 blk_size)
  439. {
  440. KUNIT_EXPECT_MEMEQ_MSG(test, res, exp, strlen(exp) + 1,
  441. "string_get_size(size = %llu, blk_size = %llu, units = %s)",
  442. size, blk_size, units);
  443. }
  444. static void __strchrcut(char *dst, const char *src, const char *cut)
  445. {
  446. const char *from = src;
  447. size_t len;
  448. do {
  449. len = strcspn(from, cut);
  450. memcpy(dst, from, len);
  451. dst += len;
  452. from += len;
  453. } while (*from++);
  454. *dst = '\0';
  455. }
  456. static void __test_string_get_size_one(struct kunit *test,
  457. const u64 size, const u64 blk_size,
  458. const char *exp_result10,
  459. const char *exp_result2,
  460. enum string_size_units units,
  461. const char *cut)
  462. {
  463. char buf10[string_get_size_maxbuf];
  464. char buf2[string_get_size_maxbuf];
  465. char exp10[string_get_size_maxbuf];
  466. char exp2[string_get_size_maxbuf];
  467. char prefix10[64];
  468. char prefix2[64];
  469. sprintf(prefix10, "STRING_UNITS_10 [%s]", cut);
  470. sprintf(prefix2, "STRING_UNITS_2 [%s]", cut);
  471. __strchrcut(exp10, exp_result10, cut);
  472. __strchrcut(exp2, exp_result2, cut);
  473. string_get_size(size, blk_size, STRING_UNITS_10 | units, buf10, sizeof(buf10));
  474. string_get_size(size, blk_size, STRING_UNITS_2 | units, buf2, sizeof(buf2));
  475. test_string_get_size_check(test, prefix10, exp10, buf10, size, blk_size);
  476. test_string_get_size_check(test, prefix2, exp2, buf2, size, blk_size);
  477. }
  478. static void __test_string_get_size(struct kunit *test,
  479. const u64 size, const u64 blk_size,
  480. const char *exp_result10,
  481. const char *exp_result2)
  482. {
  483. struct {
  484. enum string_size_units units;
  485. const char *cut;
  486. } get_size_test_cases[] = {
  487. { 0, "" },
  488. { STRING_UNITS_NO_SPACE, " " },
  489. { STRING_UNITS_NO_SPACE | STRING_UNITS_NO_BYTES, " B" },
  490. { STRING_UNITS_NO_BYTES, "B" },
  491. };
  492. int i;
  493. for (i = 0; i < ARRAY_SIZE(get_size_test_cases); i++)
  494. __test_string_get_size_one(test, size, blk_size,
  495. exp_result10, exp_result2,
  496. get_size_test_cases[i].units,
  497. get_size_test_cases[i].cut);
  498. }
  499. static void test_get_size(struct kunit *test)
  500. {
  501. /* small values */
  502. test_string_get_size_one(0, 512, "0 B", "0 B");
  503. test_string_get_size_one(1, 512, "512 B", "512 B");
  504. test_string_get_size_one(1100, 1, "1.10 kB", "1.07 KiB");
  505. /* normal values */
  506. test_string_get_size_one(16384, 512, "8.39 MB", "8.00 MiB");
  507. test_string_get_size_one(500118192, 512, "256 GB", "238 GiB");
  508. test_string_get_size_one(8192, 4096, "33.6 MB", "32.0 MiB");
  509. /* weird block sizes */
  510. test_string_get_size_one(3000, 1900, "5.70 MB", "5.44 MiB");
  511. /* huge values */
  512. test_string_get_size_one(U64_MAX, 4096, "75.6 ZB", "64.0 ZiB");
  513. test_string_get_size_one(4096, U64_MAX, "75.6 ZB", "64.0 ZiB");
  514. }
  515. static void test_upper_lower(struct kunit *test)
  516. {
  517. char *dst;
  518. int i;
  519. for (i = 0; i < ARRAY_SIZE(strings_upper); i++) {
  520. const char *s = strings_upper[i].in;
  521. int len = strlen(strings_upper[i].in) + 1;
  522. dst = kmalloc(len, GFP_KERNEL);
  523. KUNIT_ASSERT_NOT_NULL(test, dst);
  524. string_upper(dst, s);
  525. KUNIT_EXPECT_STREQ(test, dst, strings_upper[i].out);
  526. kfree(dst);
  527. }
  528. for (i = 0; i < ARRAY_SIZE(strings_lower); i++) {
  529. const char *s = strings_lower[i].in;
  530. int len = strlen(strings_lower[i].in) + 1;
  531. dst = kmalloc(len, GFP_KERNEL);
  532. KUNIT_ASSERT_NOT_NULL(test, dst);
  533. string_lower(dst, s);
  534. KUNIT_EXPECT_STREQ(test, dst, strings_lower[i].out);
  535. kfree(dst);
  536. }
  537. }
  538. static void test_unescape(struct kunit *test)
  539. {
  540. unsigned int i;
  541. for (i = 0; i < UNESCAPE_ALL_MASK + 1; i++)
  542. test_string_unescape(test, "unescape", i, false);
  543. test_string_unescape(test, "unescape inplace",
  544. get_random_u32_below(UNESCAPE_ALL_MASK + 1), true);
  545. /* Without dictionary */
  546. for (i = 0; i < ESCAPE_ALL_MASK + 1; i++)
  547. test_string_escape(test, "escape 0", escape0, i, TEST_STRING_2_DICT_0);
  548. /* With dictionary */
  549. for (i = 0; i < ESCAPE_ALL_MASK + 1; i++)
  550. test_string_escape(test, "escape 1", escape1, i, TEST_STRING_2_DICT_1);
  551. }
  552. static struct kunit_case string_helpers_test_cases[] = {
  553. KUNIT_CASE(test_get_size),
  554. KUNIT_CASE(test_upper_lower),
  555. KUNIT_CASE(test_unescape),
  556. {}
  557. };
  558. static struct kunit_suite string_helpers_test_suite = {
  559. .name = "string_helpers",
  560. .test_cases = string_helpers_test_cases,
  561. };
  562. kunit_test_suites(&string_helpers_test_suite);
  563. MODULE_DESCRIPTION("Test cases for string helpers module");
  564. MODULE_LICENSE("Dual BSD/GPL");