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