projects/linux·blob master · refs

640 lines · 16.0 KiB

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
19static 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
30struct test_string {
31 const char *in;
32 const char *out;
33 unsigned int flags;
34};
35
36static 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
59static 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
108struct test_string_1 {
109 const char *out;
110 unsigned int flags;
111};
112
113#define TEST_STRING_2_MAX_S1 32
114struct 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
120static 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"
218static 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
355static const struct test_string strings_upper[] = {
356 {
357 .in = "abcdefgh1234567890test",
358 .out = "ABCDEFGH1234567890TEST",
359 },
360 {
361 .in = "abCdeFgH1234567890TesT",
362 .out = "ABCDEFGH1234567890TEST",
363 },
364};
365
366static const struct test_string strings_lower[] = {
367 {
368 .in = "ABCDEFGH1234567890TEST",
369 .out = "abcdefgh1234567890test",
370 },
371 {
372 .in = "abCdeFgH1234567890TesT",
373 .out = "abcdefgh1234567890test",
374 },
375};
376
377static 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
399static void
400test_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
410static 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
475static 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
487static 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
501static 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
528static 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
551static 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
571static 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
601static 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
611static 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
624static 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
632static struct kunit_suite string_helpers_test_suite = {
633 .name = "string_helpers",
634 .test_cases = string_helpers_test_cases,
635};
636
637kunit_test_suites(&string_helpers_test_suite);
638
639MODULE_DESCRIPTION("Test cases for string helpers module");
640MODULE_LICENSE("Dual BSD/GPL");