ac44c9245dcf1a73cba5c297a3d5a8fcf35ecff9
[cascardo/linux.git] / lib / test-string_helpers.c
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/module.h>
9 #include <linux/random.h>
10 #include <linux/string.h>
11 #include <linux/string_helpers.h>
12
13 static __init bool test_string_check_buf(const char *name, unsigned int flags,
14                                          char *in, size_t p,
15                                          char *out_real, size_t q_real,
16                                          char *out_test, size_t q_test)
17 {
18         if (q_real == q_test && !memcmp(out_test, out_real, q_test))
19                 return true;
20
21         pr_warn("Test '%s' failed: flags = %u\n", name, flags);
22
23         print_hex_dump(KERN_WARNING, "Input: ", DUMP_PREFIX_NONE, 16, 1,
24                        in, p, true);
25         print_hex_dump(KERN_WARNING, "Expected: ", DUMP_PREFIX_NONE, 16, 1,
26                        out_test, q_test, true);
27         print_hex_dump(KERN_WARNING, "Got: ", DUMP_PREFIX_NONE, 16, 1,
28                        out_real, q_real, true);
29
30         return false;
31 }
32
33 struct test_string {
34         const char *in;
35         const char *out;
36         unsigned int flags;
37 };
38
39 static const struct test_string strings[] __initconst = {
40         {
41                 .in = "\\f\\ \\n\\r\\t\\v",
42                 .out = "\f\\ \n\r\t\v",
43                 .flags = UNESCAPE_SPACE,
44         },
45         {
46                 .in = "\\40\\1\\387\\0064\\05\\040\\8a\\110\\777",
47                 .out = " \001\00387\0064\005 \\8aH?7",
48                 .flags = UNESCAPE_OCTAL,
49         },
50         {
51                 .in = "\\xv\\xa\\x2c\\xD\\x6f2",
52                 .out = "\\xv\n,\ro2",
53                 .flags = UNESCAPE_HEX,
54         },
55         {
56                 .in = "\\h\\\\\\\"\\a\\e\\",
57                 .out = "\\h\\\"\a\e\\",
58                 .flags = UNESCAPE_SPECIAL,
59         },
60 };
61
62 static void __init test_string_unescape(const char *name, unsigned int flags,
63                                         bool inplace)
64 {
65         char in[256];
66         char out_test[256];
67         char out_real[256];
68         int i, p = 0, q_test = 0, q_real = sizeof(out_real);
69
70         for (i = 0; i < ARRAY_SIZE(strings); i++) {
71                 const char *s = strings[i].in;
72                 int len = strlen(strings[i].in);
73
74                 /* Copy string to in buffer */
75                 memcpy(&in[p], s, len);
76                 p += len;
77
78                 /* Copy expected result for given flags */
79                 if (flags & strings[i].flags) {
80                         s = strings[i].out;
81                         len = strlen(strings[i].out);
82                 }
83                 memcpy(&out_test[q_test], s, len);
84                 q_test += len;
85         }
86         in[p++] = '\0';
87
88         /* Call string_unescape and compare result */
89         if (inplace) {
90                 memcpy(out_real, in, p);
91                 if (flags == UNESCAPE_ANY)
92                         q_real = string_unescape_any_inplace(out_real);
93                 else
94                         q_real = string_unescape_inplace(out_real, flags);
95         } else if (flags == UNESCAPE_ANY) {
96                 q_real = string_unescape_any(in, out_real, q_real);
97         } else {
98                 q_real = string_unescape(in, out_real, q_real, flags);
99         }
100
101         test_string_check_buf(name, flags, in, p - 1, out_real, q_real,
102                               out_test, q_test);
103 }
104
105 static int __init test_string_helpers_init(void)
106 {
107         unsigned int i;
108
109         pr_info("Running tests...\n");
110         for (i = 0; i < UNESCAPE_ANY + 1; i++)
111                 test_string_unescape("unescape", i, false);
112         test_string_unescape("unescape inplace",
113                              get_random_int() % (UNESCAPE_ANY + 1), true);
114
115         return -EINVAL;
116 }
117 module_init(test_string_helpers_init);
118 MODULE_LICENSE("Dual BSD/GPL");