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