18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Test cases for lib/string_helpers.c module. 38c2ecf20Sopenharmony_ci */ 48c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/init.h> 78c2ecf20Sopenharmony_ci#include <linux/kernel.h> 88c2ecf20Sopenharmony_ci#include <linux/slab.h> 98c2ecf20Sopenharmony_ci#include <linux/module.h> 108c2ecf20Sopenharmony_ci#include <linux/random.h> 118c2ecf20Sopenharmony_ci#include <linux/string.h> 128c2ecf20Sopenharmony_ci#include <linux/string_helpers.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic __init bool test_string_check_buf(const char *name, unsigned int flags, 158c2ecf20Sopenharmony_ci char *in, size_t p, 168c2ecf20Sopenharmony_ci char *out_real, size_t q_real, 178c2ecf20Sopenharmony_ci char *out_test, size_t q_test) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci if (q_real == q_test && !memcmp(out_test, out_real, q_test)) 208c2ecf20Sopenharmony_ci return true; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci pr_warn("Test '%s' failed: flags = %u\n", name, flags); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci print_hex_dump(KERN_WARNING, "Input: ", DUMP_PREFIX_NONE, 16, 1, 258c2ecf20Sopenharmony_ci in, p, true); 268c2ecf20Sopenharmony_ci print_hex_dump(KERN_WARNING, "Expected: ", DUMP_PREFIX_NONE, 16, 1, 278c2ecf20Sopenharmony_ci out_test, q_test, true); 288c2ecf20Sopenharmony_ci print_hex_dump(KERN_WARNING, "Got: ", DUMP_PREFIX_NONE, 16, 1, 298c2ecf20Sopenharmony_ci out_real, q_real, true); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci return false; 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistruct test_string { 358c2ecf20Sopenharmony_ci const char *in; 368c2ecf20Sopenharmony_ci const char *out; 378c2ecf20Sopenharmony_ci unsigned int flags; 388c2ecf20Sopenharmony_ci}; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic const struct test_string strings[] __initconst = { 418c2ecf20Sopenharmony_ci { 428c2ecf20Sopenharmony_ci .in = "\\f\\ \\n\\r\\t\\v", 438c2ecf20Sopenharmony_ci .out = "\f\\ \n\r\t\v", 448c2ecf20Sopenharmony_ci .flags = UNESCAPE_SPACE, 458c2ecf20Sopenharmony_ci }, 468c2ecf20Sopenharmony_ci { 478c2ecf20Sopenharmony_ci .in = "\\40\\1\\387\\0064\\05\\040\\8a\\110\\777", 488c2ecf20Sopenharmony_ci .out = " \001\00387\0064\005 \\8aH?7", 498c2ecf20Sopenharmony_ci .flags = UNESCAPE_OCTAL, 508c2ecf20Sopenharmony_ci }, 518c2ecf20Sopenharmony_ci { 528c2ecf20Sopenharmony_ci .in = "\\xv\\xa\\x2c\\xD\\x6f2", 538c2ecf20Sopenharmony_ci .out = "\\xv\n,\ro2", 548c2ecf20Sopenharmony_ci .flags = UNESCAPE_HEX, 558c2ecf20Sopenharmony_ci }, 568c2ecf20Sopenharmony_ci { 578c2ecf20Sopenharmony_ci .in = "\\h\\\\\\\"\\a\\e\\", 588c2ecf20Sopenharmony_ci .out = "\\h\\\"\a\e\\", 598c2ecf20Sopenharmony_ci .flags = UNESCAPE_SPECIAL, 608c2ecf20Sopenharmony_ci }, 618c2ecf20Sopenharmony_ci}; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic void __init test_string_unescape(const char *name, unsigned int flags, 648c2ecf20Sopenharmony_ci bool inplace) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci int q_real = 256; 678c2ecf20Sopenharmony_ci char *in = kmalloc(q_real, GFP_KERNEL); 688c2ecf20Sopenharmony_ci char *out_test = kmalloc(q_real, GFP_KERNEL); 698c2ecf20Sopenharmony_ci char *out_real = kmalloc(q_real, GFP_KERNEL); 708c2ecf20Sopenharmony_ci int i, p = 0, q_test = 0; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci if (!in || !out_test || !out_real) 738c2ecf20Sopenharmony_ci goto out; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(strings); i++) { 768c2ecf20Sopenharmony_ci const char *s = strings[i].in; 778c2ecf20Sopenharmony_ci int len = strlen(strings[i].in); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /* Copy string to in buffer */ 808c2ecf20Sopenharmony_ci memcpy(&in[p], s, len); 818c2ecf20Sopenharmony_ci p += len; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci /* Copy expected result for given flags */ 848c2ecf20Sopenharmony_ci if (flags & strings[i].flags) { 858c2ecf20Sopenharmony_ci s = strings[i].out; 868c2ecf20Sopenharmony_ci len = strlen(strings[i].out); 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci memcpy(&out_test[q_test], s, len); 898c2ecf20Sopenharmony_ci q_test += len; 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci in[p++] = '\0'; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* Call string_unescape and compare result */ 948c2ecf20Sopenharmony_ci if (inplace) { 958c2ecf20Sopenharmony_ci memcpy(out_real, in, p); 968c2ecf20Sopenharmony_ci if (flags == UNESCAPE_ANY) 978c2ecf20Sopenharmony_ci q_real = string_unescape_any_inplace(out_real); 988c2ecf20Sopenharmony_ci else 998c2ecf20Sopenharmony_ci q_real = string_unescape_inplace(out_real, flags); 1008c2ecf20Sopenharmony_ci } else if (flags == UNESCAPE_ANY) { 1018c2ecf20Sopenharmony_ci q_real = string_unescape_any(in, out_real, q_real); 1028c2ecf20Sopenharmony_ci } else { 1038c2ecf20Sopenharmony_ci q_real = string_unescape(in, out_real, q_real, flags); 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci test_string_check_buf(name, flags, in, p - 1, out_real, q_real, 1078c2ecf20Sopenharmony_ci out_test, q_test); 1088c2ecf20Sopenharmony_ciout: 1098c2ecf20Sopenharmony_ci kfree(out_real); 1108c2ecf20Sopenharmony_ci kfree(out_test); 1118c2ecf20Sopenharmony_ci kfree(in); 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistruct test_string_1 { 1158c2ecf20Sopenharmony_ci const char *out; 1168c2ecf20Sopenharmony_ci unsigned int flags; 1178c2ecf20Sopenharmony_ci}; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci#define TEST_STRING_2_MAX_S1 32 1208c2ecf20Sopenharmony_cistruct test_string_2 { 1218c2ecf20Sopenharmony_ci const char *in; 1228c2ecf20Sopenharmony_ci struct test_string_1 s1[TEST_STRING_2_MAX_S1]; 1238c2ecf20Sopenharmony_ci}; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci#define TEST_STRING_2_DICT_0 NULL 1268c2ecf20Sopenharmony_cistatic const struct test_string_2 escape0[] __initconst = {{ 1278c2ecf20Sopenharmony_ci .in = "\f\\ \n\r\t\v", 1288c2ecf20Sopenharmony_ci .s1 = {{ 1298c2ecf20Sopenharmony_ci .out = "\\f\\ \\n\\r\\t\\v", 1308c2ecf20Sopenharmony_ci .flags = ESCAPE_SPACE, 1318c2ecf20Sopenharmony_ci },{ 1328c2ecf20Sopenharmony_ci .out = "\\f\\134\\040\\n\\r\\t\\v", 1338c2ecf20Sopenharmony_ci .flags = ESCAPE_SPACE | ESCAPE_OCTAL, 1348c2ecf20Sopenharmony_ci },{ 1358c2ecf20Sopenharmony_ci .out = "\\f\\x5c\\x20\\n\\r\\t\\v", 1368c2ecf20Sopenharmony_ci .flags = ESCAPE_SPACE | ESCAPE_HEX, 1378c2ecf20Sopenharmony_ci },{ 1388c2ecf20Sopenharmony_ci /* terminator */ 1398c2ecf20Sopenharmony_ci }}, 1408c2ecf20Sopenharmony_ci},{ 1418c2ecf20Sopenharmony_ci .in = "\\h\\\"\a\e\\", 1428c2ecf20Sopenharmony_ci .s1 = {{ 1438c2ecf20Sopenharmony_ci .out = "\\\\h\\\\\"\\a\\e\\\\", 1448c2ecf20Sopenharmony_ci .flags = ESCAPE_SPECIAL, 1458c2ecf20Sopenharmony_ci },{ 1468c2ecf20Sopenharmony_ci .out = "\\\\\\150\\\\\\042\\a\\e\\\\", 1478c2ecf20Sopenharmony_ci .flags = ESCAPE_SPECIAL | ESCAPE_OCTAL, 1488c2ecf20Sopenharmony_ci },{ 1498c2ecf20Sopenharmony_ci .out = "\\\\\\x68\\\\\\x22\\a\\e\\\\", 1508c2ecf20Sopenharmony_ci .flags = ESCAPE_SPECIAL | ESCAPE_HEX, 1518c2ecf20Sopenharmony_ci },{ 1528c2ecf20Sopenharmony_ci /* terminator */ 1538c2ecf20Sopenharmony_ci }}, 1548c2ecf20Sopenharmony_ci},{ 1558c2ecf20Sopenharmony_ci .in = "\eb \\C\007\"\x90\r]", 1568c2ecf20Sopenharmony_ci .s1 = {{ 1578c2ecf20Sopenharmony_ci .out = "\eb \\C\007\"\x90\\r]", 1588c2ecf20Sopenharmony_ci .flags = ESCAPE_SPACE, 1598c2ecf20Sopenharmony_ci },{ 1608c2ecf20Sopenharmony_ci .out = "\\eb \\\\C\\a\"\x90\r]", 1618c2ecf20Sopenharmony_ci .flags = ESCAPE_SPECIAL, 1628c2ecf20Sopenharmony_ci },{ 1638c2ecf20Sopenharmony_ci .out = "\\eb \\\\C\\a\"\x90\\r]", 1648c2ecf20Sopenharmony_ci .flags = ESCAPE_SPACE | ESCAPE_SPECIAL, 1658c2ecf20Sopenharmony_ci },{ 1668c2ecf20Sopenharmony_ci .out = "\\033\\142\\040\\134\\103\\007\\042\\220\\015\\135", 1678c2ecf20Sopenharmony_ci .flags = ESCAPE_OCTAL, 1688c2ecf20Sopenharmony_ci },{ 1698c2ecf20Sopenharmony_ci .out = "\\033\\142\\040\\134\\103\\007\\042\\220\\r\\135", 1708c2ecf20Sopenharmony_ci .flags = ESCAPE_SPACE | ESCAPE_OCTAL, 1718c2ecf20Sopenharmony_ci },{ 1728c2ecf20Sopenharmony_ci .out = "\\e\\142\\040\\\\\\103\\a\\042\\220\\015\\135", 1738c2ecf20Sopenharmony_ci .flags = ESCAPE_SPECIAL | ESCAPE_OCTAL, 1748c2ecf20Sopenharmony_ci },{ 1758c2ecf20Sopenharmony_ci .out = "\\e\\142\\040\\\\\\103\\a\\042\\220\\r\\135", 1768c2ecf20Sopenharmony_ci .flags = ESCAPE_SPACE | ESCAPE_SPECIAL | ESCAPE_OCTAL, 1778c2ecf20Sopenharmony_ci },{ 1788c2ecf20Sopenharmony_ci .out = "\eb \\C\007\"\x90\r]", 1798c2ecf20Sopenharmony_ci .flags = ESCAPE_NP, 1808c2ecf20Sopenharmony_ci },{ 1818c2ecf20Sopenharmony_ci .out = "\eb \\C\007\"\x90\\r]", 1828c2ecf20Sopenharmony_ci .flags = ESCAPE_SPACE | ESCAPE_NP, 1838c2ecf20Sopenharmony_ci },{ 1848c2ecf20Sopenharmony_ci .out = "\\eb \\C\\a\"\x90\r]", 1858c2ecf20Sopenharmony_ci .flags = ESCAPE_SPECIAL | ESCAPE_NP, 1868c2ecf20Sopenharmony_ci },{ 1878c2ecf20Sopenharmony_ci .out = "\\eb \\C\\a\"\x90\\r]", 1888c2ecf20Sopenharmony_ci .flags = ESCAPE_SPACE | ESCAPE_SPECIAL | ESCAPE_NP, 1898c2ecf20Sopenharmony_ci },{ 1908c2ecf20Sopenharmony_ci .out = "\\033b \\C\\007\"\\220\\015]", 1918c2ecf20Sopenharmony_ci .flags = ESCAPE_OCTAL | ESCAPE_NP, 1928c2ecf20Sopenharmony_ci },{ 1938c2ecf20Sopenharmony_ci .out = "\\033b \\C\\007\"\\220\\r]", 1948c2ecf20Sopenharmony_ci .flags = ESCAPE_SPACE | ESCAPE_OCTAL | ESCAPE_NP, 1958c2ecf20Sopenharmony_ci },{ 1968c2ecf20Sopenharmony_ci .out = "\\eb \\C\\a\"\\220\\r]", 1978c2ecf20Sopenharmony_ci .flags = ESCAPE_SPECIAL | ESCAPE_SPACE | ESCAPE_OCTAL | 1988c2ecf20Sopenharmony_ci ESCAPE_NP, 1998c2ecf20Sopenharmony_ci },{ 2008c2ecf20Sopenharmony_ci .out = "\\x1bb \\C\\x07\"\\x90\\x0d]", 2018c2ecf20Sopenharmony_ci .flags = ESCAPE_NP | ESCAPE_HEX, 2028c2ecf20Sopenharmony_ci },{ 2038c2ecf20Sopenharmony_ci /* terminator */ 2048c2ecf20Sopenharmony_ci }}, 2058c2ecf20Sopenharmony_ci},{ 2068c2ecf20Sopenharmony_ci /* terminator */ 2078c2ecf20Sopenharmony_ci}}; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci#define TEST_STRING_2_DICT_1 "b\\ \t\r" 2108c2ecf20Sopenharmony_cistatic const struct test_string_2 escape1[] __initconst = {{ 2118c2ecf20Sopenharmony_ci .in = "\f\\ \n\r\t\v", 2128c2ecf20Sopenharmony_ci .s1 = {{ 2138c2ecf20Sopenharmony_ci .out = "\f\\134\\040\n\\015\\011\v", 2148c2ecf20Sopenharmony_ci .flags = ESCAPE_OCTAL, 2158c2ecf20Sopenharmony_ci },{ 2168c2ecf20Sopenharmony_ci .out = "\f\\x5c\\x20\n\\x0d\\x09\v", 2178c2ecf20Sopenharmony_ci .flags = ESCAPE_HEX, 2188c2ecf20Sopenharmony_ci },{ 2198c2ecf20Sopenharmony_ci /* terminator */ 2208c2ecf20Sopenharmony_ci }}, 2218c2ecf20Sopenharmony_ci},{ 2228c2ecf20Sopenharmony_ci .in = "\\h\\\"\a\e\\", 2238c2ecf20Sopenharmony_ci .s1 = {{ 2248c2ecf20Sopenharmony_ci .out = "\\134h\\134\"\a\e\\134", 2258c2ecf20Sopenharmony_ci .flags = ESCAPE_OCTAL, 2268c2ecf20Sopenharmony_ci },{ 2278c2ecf20Sopenharmony_ci /* terminator */ 2288c2ecf20Sopenharmony_ci }}, 2298c2ecf20Sopenharmony_ci},{ 2308c2ecf20Sopenharmony_ci .in = "\eb \\C\007\"\x90\r]", 2318c2ecf20Sopenharmony_ci .s1 = {{ 2328c2ecf20Sopenharmony_ci .out = "\e\\142\\040\\134C\007\"\x90\\015]", 2338c2ecf20Sopenharmony_ci .flags = ESCAPE_OCTAL, 2348c2ecf20Sopenharmony_ci },{ 2358c2ecf20Sopenharmony_ci /* terminator */ 2368c2ecf20Sopenharmony_ci }}, 2378c2ecf20Sopenharmony_ci},{ 2388c2ecf20Sopenharmony_ci /* terminator */ 2398c2ecf20Sopenharmony_ci}}; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic const struct test_string strings_upper[] __initconst = { 2428c2ecf20Sopenharmony_ci { 2438c2ecf20Sopenharmony_ci .in = "abcdefgh1234567890test", 2448c2ecf20Sopenharmony_ci .out = "ABCDEFGH1234567890TEST", 2458c2ecf20Sopenharmony_ci }, 2468c2ecf20Sopenharmony_ci { 2478c2ecf20Sopenharmony_ci .in = "abCdeFgH1234567890TesT", 2488c2ecf20Sopenharmony_ci .out = "ABCDEFGH1234567890TEST", 2498c2ecf20Sopenharmony_ci }, 2508c2ecf20Sopenharmony_ci}; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_cistatic const struct test_string strings_lower[] __initconst = { 2538c2ecf20Sopenharmony_ci { 2548c2ecf20Sopenharmony_ci .in = "ABCDEFGH1234567890TEST", 2558c2ecf20Sopenharmony_ci .out = "abcdefgh1234567890test", 2568c2ecf20Sopenharmony_ci }, 2578c2ecf20Sopenharmony_ci { 2588c2ecf20Sopenharmony_ci .in = "abCdeFgH1234567890TesT", 2598c2ecf20Sopenharmony_ci .out = "abcdefgh1234567890test", 2608c2ecf20Sopenharmony_ci }, 2618c2ecf20Sopenharmony_ci}; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic __init const char *test_string_find_match(const struct test_string_2 *s2, 2648c2ecf20Sopenharmony_ci unsigned int flags) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci const struct test_string_1 *s1 = s2->s1; 2678c2ecf20Sopenharmony_ci unsigned int i; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci if (!flags) 2708c2ecf20Sopenharmony_ci return s2->in; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci /* Test cases are NULL-aware */ 2738c2ecf20Sopenharmony_ci flags &= ~ESCAPE_NULL; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci /* ESCAPE_OCTAL has a higher priority */ 2768c2ecf20Sopenharmony_ci if (flags & ESCAPE_OCTAL) 2778c2ecf20Sopenharmony_ci flags &= ~ESCAPE_HEX; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci for (i = 0; i < TEST_STRING_2_MAX_S1 && s1->out; i++, s1++) 2808c2ecf20Sopenharmony_ci if (s1->flags == flags) 2818c2ecf20Sopenharmony_ci return s1->out; 2828c2ecf20Sopenharmony_ci return NULL; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic __init void 2868c2ecf20Sopenharmony_citest_string_escape_overflow(const char *in, int p, unsigned int flags, const char *esc, 2878c2ecf20Sopenharmony_ci int q_test, const char *name) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci int q_real; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci q_real = string_escape_mem(in, p, NULL, 0, flags, esc); 2928c2ecf20Sopenharmony_ci if (q_real != q_test) 2938c2ecf20Sopenharmony_ci pr_warn("Test '%s' failed: flags = %u, osz = 0, expected %d, got %d\n", 2948c2ecf20Sopenharmony_ci name, flags, q_test, q_real); 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic __init void test_string_escape(const char *name, 2988c2ecf20Sopenharmony_ci const struct test_string_2 *s2, 2998c2ecf20Sopenharmony_ci unsigned int flags, const char *esc) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci size_t out_size = 512; 3028c2ecf20Sopenharmony_ci char *out_test = kmalloc(out_size, GFP_KERNEL); 3038c2ecf20Sopenharmony_ci char *out_real = kmalloc(out_size, GFP_KERNEL); 3048c2ecf20Sopenharmony_ci char *in = kmalloc(256, GFP_KERNEL); 3058c2ecf20Sopenharmony_ci int p = 0, q_test = 0; 3068c2ecf20Sopenharmony_ci int q_real; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci if (!out_test || !out_real || !in) 3098c2ecf20Sopenharmony_ci goto out; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci for (; s2->in; s2++) { 3128c2ecf20Sopenharmony_ci const char *out; 3138c2ecf20Sopenharmony_ci int len; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci /* NULL injection */ 3168c2ecf20Sopenharmony_ci if (flags & ESCAPE_NULL) { 3178c2ecf20Sopenharmony_ci in[p++] = '\0'; 3188c2ecf20Sopenharmony_ci out_test[q_test++] = '\\'; 3198c2ecf20Sopenharmony_ci out_test[q_test++] = '0'; 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci /* Don't try strings that have no output */ 3238c2ecf20Sopenharmony_ci out = test_string_find_match(s2, flags); 3248c2ecf20Sopenharmony_ci if (!out) 3258c2ecf20Sopenharmony_ci continue; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* Copy string to in buffer */ 3288c2ecf20Sopenharmony_ci len = strlen(s2->in); 3298c2ecf20Sopenharmony_ci memcpy(&in[p], s2->in, len); 3308c2ecf20Sopenharmony_ci p += len; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci /* Copy expected result for given flags */ 3338c2ecf20Sopenharmony_ci len = strlen(out); 3348c2ecf20Sopenharmony_ci memcpy(&out_test[q_test], out, len); 3358c2ecf20Sopenharmony_ci q_test += len; 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci q_real = string_escape_mem(in, p, out_real, out_size, flags, esc); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci test_string_check_buf(name, flags, in, p, out_real, q_real, out_test, 3418c2ecf20Sopenharmony_ci q_test); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci test_string_escape_overflow(in, p, flags, esc, q_test, name); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ciout: 3468c2ecf20Sopenharmony_ci kfree(in); 3478c2ecf20Sopenharmony_ci kfree(out_real); 3488c2ecf20Sopenharmony_ci kfree(out_test); 3498c2ecf20Sopenharmony_ci} 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci#define string_get_size_maxbuf 16 3528c2ecf20Sopenharmony_ci#define test_string_get_size_one(size, blk_size, exp_result10, exp_result2) \ 3538c2ecf20Sopenharmony_ci do { \ 3548c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(exp_result10) >= string_get_size_maxbuf); \ 3558c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(exp_result2) >= string_get_size_maxbuf); \ 3568c2ecf20Sopenharmony_ci __test_string_get_size((size), (blk_size), (exp_result10), \ 3578c2ecf20Sopenharmony_ci (exp_result2)); \ 3588c2ecf20Sopenharmony_ci } while (0) 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic __init void test_string_get_size_check(const char *units, 3628c2ecf20Sopenharmony_ci const char *exp, 3638c2ecf20Sopenharmony_ci char *res, 3648c2ecf20Sopenharmony_ci const u64 size, 3658c2ecf20Sopenharmony_ci const u64 blk_size) 3668c2ecf20Sopenharmony_ci{ 3678c2ecf20Sopenharmony_ci if (!memcmp(res, exp, strlen(exp) + 1)) 3688c2ecf20Sopenharmony_ci return; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci res[string_get_size_maxbuf - 1] = '\0'; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci pr_warn("Test 'test_string_get_size' failed!\n"); 3738c2ecf20Sopenharmony_ci pr_warn("string_get_size(size = %llu, blk_size = %llu, units = %s)\n", 3748c2ecf20Sopenharmony_ci size, blk_size, units); 3758c2ecf20Sopenharmony_ci pr_warn("expected: '%s', got '%s'\n", exp, res); 3768c2ecf20Sopenharmony_ci} 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_cistatic __init void __test_string_get_size(const u64 size, const u64 blk_size, 3798c2ecf20Sopenharmony_ci const char *exp_result10, 3808c2ecf20Sopenharmony_ci const char *exp_result2) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci char buf10[string_get_size_maxbuf]; 3838c2ecf20Sopenharmony_ci char buf2[string_get_size_maxbuf]; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci string_get_size(size, blk_size, STRING_UNITS_10, buf10, sizeof(buf10)); 3868c2ecf20Sopenharmony_ci string_get_size(size, blk_size, STRING_UNITS_2, buf2, sizeof(buf2)); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci test_string_get_size_check("STRING_UNITS_10", exp_result10, buf10, 3898c2ecf20Sopenharmony_ci size, blk_size); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci test_string_get_size_check("STRING_UNITS_2", exp_result2, buf2, 3928c2ecf20Sopenharmony_ci size, blk_size); 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_cistatic __init void test_string_get_size(void) 3968c2ecf20Sopenharmony_ci{ 3978c2ecf20Sopenharmony_ci /* small values */ 3988c2ecf20Sopenharmony_ci test_string_get_size_one(0, 512, "0 B", "0 B"); 3998c2ecf20Sopenharmony_ci test_string_get_size_one(1, 512, "512 B", "512 B"); 4008c2ecf20Sopenharmony_ci test_string_get_size_one(1100, 1, "1.10 kB", "1.07 KiB"); 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci /* normal values */ 4038c2ecf20Sopenharmony_ci test_string_get_size_one(16384, 512, "8.39 MB", "8.00 MiB"); 4048c2ecf20Sopenharmony_ci test_string_get_size_one(500118192, 512, "256 GB", "238 GiB"); 4058c2ecf20Sopenharmony_ci test_string_get_size_one(8192, 4096, "33.6 MB", "32.0 MiB"); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci /* weird block sizes */ 4088c2ecf20Sopenharmony_ci test_string_get_size_one(3000, 1900, "5.70 MB", "5.44 MiB"); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* huge values */ 4118c2ecf20Sopenharmony_ci test_string_get_size_one(U64_MAX, 4096, "75.6 ZB", "64.0 ZiB"); 4128c2ecf20Sopenharmony_ci test_string_get_size_one(4096, U64_MAX, "75.6 ZB", "64.0 ZiB"); 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_cistatic void __init test_string_upper_lower(void) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci char *dst; 4188c2ecf20Sopenharmony_ci int i; 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(strings_upper); i++) { 4218c2ecf20Sopenharmony_ci const char *s = strings_upper[i].in; 4228c2ecf20Sopenharmony_ci int len = strlen(strings_upper[i].in) + 1; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci dst = kmalloc(len, GFP_KERNEL); 4258c2ecf20Sopenharmony_ci if (!dst) 4268c2ecf20Sopenharmony_ci return; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci string_upper(dst, s); 4298c2ecf20Sopenharmony_ci if (memcmp(dst, strings_upper[i].out, len)) { 4308c2ecf20Sopenharmony_ci pr_warn("Test 'string_upper' failed : expected %s, got %s!\n", 4318c2ecf20Sopenharmony_ci strings_upper[i].out, dst); 4328c2ecf20Sopenharmony_ci kfree(dst); 4338c2ecf20Sopenharmony_ci return; 4348c2ecf20Sopenharmony_ci } 4358c2ecf20Sopenharmony_ci kfree(dst); 4368c2ecf20Sopenharmony_ci } 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(strings_lower); i++) { 4398c2ecf20Sopenharmony_ci const char *s = strings_lower[i].in; 4408c2ecf20Sopenharmony_ci int len = strlen(strings_lower[i].in) + 1; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci dst = kmalloc(len, GFP_KERNEL); 4438c2ecf20Sopenharmony_ci if (!dst) 4448c2ecf20Sopenharmony_ci return; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci string_lower(dst, s); 4478c2ecf20Sopenharmony_ci if (memcmp(dst, strings_lower[i].out, len)) { 4488c2ecf20Sopenharmony_ci pr_warn("Test 'string_lower failed : : expected %s, got %s!\n", 4498c2ecf20Sopenharmony_ci strings_lower[i].out, dst); 4508c2ecf20Sopenharmony_ci kfree(dst); 4518c2ecf20Sopenharmony_ci return; 4528c2ecf20Sopenharmony_ci } 4538c2ecf20Sopenharmony_ci kfree(dst); 4548c2ecf20Sopenharmony_ci } 4558c2ecf20Sopenharmony_ci} 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_cistatic int __init test_string_helpers_init(void) 4588c2ecf20Sopenharmony_ci{ 4598c2ecf20Sopenharmony_ci unsigned int i; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci pr_info("Running tests...\n"); 4628c2ecf20Sopenharmony_ci for (i = 0; i < UNESCAPE_ANY + 1; i++) 4638c2ecf20Sopenharmony_ci test_string_unescape("unescape", i, false); 4648c2ecf20Sopenharmony_ci test_string_unescape("unescape inplace", 4658c2ecf20Sopenharmony_ci get_random_int() % (UNESCAPE_ANY + 1), true); 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci /* Without dictionary */ 4688c2ecf20Sopenharmony_ci for (i = 0; i < (ESCAPE_ANY_NP | ESCAPE_HEX) + 1; i++) 4698c2ecf20Sopenharmony_ci test_string_escape("escape 0", escape0, i, TEST_STRING_2_DICT_0); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci /* With dictionary */ 4728c2ecf20Sopenharmony_ci for (i = 0; i < (ESCAPE_ANY_NP | ESCAPE_HEX) + 1; i++) 4738c2ecf20Sopenharmony_ci test_string_escape("escape 1", escape1, i, TEST_STRING_2_DICT_1); 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci /* Test string_get_size() */ 4768c2ecf20Sopenharmony_ci test_string_get_size(); 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci /* Test string upper(), string_lower() */ 4798c2ecf20Sopenharmony_ci test_string_upper_lower(); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci return -EINVAL; 4828c2ecf20Sopenharmony_ci} 4838c2ecf20Sopenharmony_cimodule_init(test_string_helpers_init); 4848c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 485