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