root/lib/test-string_helpers.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. test_string_check_buf
  2. test_string_unescape
  3. test_string_find_match
  4. test_string_escape_overflow
  5. test_string_escape
  6. test_string_get_size_check
  7. __test_string_get_size
  8. test_string_get_size
  9. test_string_helpers_init

   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(out_test, out_real, q_test))
  20                 return true;
  21 
  22         pr_warn("Test '%s' failed: flags = %u\n", name, flags);
  23 
  24         print_hex_dump(KERN_WARNING, "Input: ", DUMP_PREFIX_NONE, 16, 1,
  25                        in, p, true);
  26         print_hex_dump(KERN_WARNING, "Expected: ", DUMP_PREFIX_NONE, 16, 1,
  27                        out_test, q_test, true);
  28         print_hex_dump(KERN_WARNING, "Got: ", DUMP_PREFIX_NONE, 16, 1,
  29                        out_real, q_real, 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(q_real, GFP_KERNEL);
  68         char *out_test = kmalloc(q_real, GFP_KERNEL);
  69         char *out_real = kmalloc(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(out_real);
  98                 else
  99                         q_real = string_unescape_inplace(out_real, flags);
 100         } else if (flags == UNESCAPE_ANY) {
 101                 q_real = string_unescape_any(in, out_real, q_real);
 102         } else {
 103                 q_real = string_unescape(in, out_real, q_real, flags);
 104         }
 105 
 106         test_string_check_buf(name, flags, in, p - 1, out_real, q_real,
 107                               out_test, q_test);
 108 out:
 109         kfree(out_real);
 110         kfree(out_test);
 111         kfree(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\\\\\\042\\a\\e\\\\",
 147                 .flags = ESCAPE_SPECIAL | ESCAPE_OCTAL,
 148         },{
 149                 .out = "\\\\\\x68\\\\\\x22\\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\\042\\220\\015\\135",
 173                 .flags = ESCAPE_SPECIAL | ESCAPE_OCTAL,
 174         },{
 175                 .out = "\\e\\142\\040\\\\\\103\\a\\042\\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         /* terminator */
 207 }};
 208 
 209 #define TEST_STRING_2_DICT_1            "b\\ \t\r"
 210 static const struct test_string_2 escape1[] __initconst = {{
 211         .in = "\f\\ \n\r\t\v",
 212         .s1 = {{
 213                 .out = "\f\\134\\040\n\\015\\011\v",
 214                 .flags = ESCAPE_OCTAL,
 215         },{
 216                 .out = "\f\\x5c\\x20\n\\x0d\\x09\v",
 217                 .flags = ESCAPE_HEX,
 218         },{
 219                 /* terminator */
 220         }},
 221 },{
 222         .in = "\\h\\\"\a\e\\",
 223         .s1 = {{
 224                 .out = "\\134h\\134\"\a\e\\134",
 225                 .flags = ESCAPE_OCTAL,
 226         },{
 227                 /* terminator */
 228         }},
 229 },{
 230         .in = "\eb \\C\007\"\x90\r]",
 231         .s1 = {{
 232                 .out = "\e\\142\\040\\134C\007\"\x90\\015]",
 233                 .flags = ESCAPE_OCTAL,
 234         },{
 235                 /* terminator */
 236         }},
 237 },{
 238         /* terminator */
 239 }};
 240 
 241 static __init const char *test_string_find_match(const struct test_string_2 *s2,
 242                                                  unsigned int flags)
 243 {
 244         const struct test_string_1 *s1 = s2->s1;
 245         unsigned int i;
 246 
 247         if (!flags)
 248                 return s2->in;
 249 
 250         /* Test cases are NULL-aware */
 251         flags &= ~ESCAPE_NULL;
 252 
 253         /* ESCAPE_OCTAL has a higher priority */
 254         if (flags & ESCAPE_OCTAL)
 255                 flags &= ~ESCAPE_HEX;
 256 
 257         for (i = 0; i < TEST_STRING_2_MAX_S1 && s1->out; i++, s1++)
 258                 if (s1->flags == flags)
 259                         return s1->out;
 260         return NULL;
 261 }
 262 
 263 static __init void
 264 test_string_escape_overflow(const char *in, int p, unsigned int flags, const char *esc,
 265                             int q_test, const char *name)
 266 {
 267         int q_real;
 268 
 269         q_real = string_escape_mem(in, p, NULL, 0, flags, esc);
 270         if (q_real != q_test)
 271                 pr_warn("Test '%s' failed: flags = %u, osz = 0, expected %d, got %d\n",
 272                         name, flags, q_test, q_real);
 273 }
 274 
 275 static __init void test_string_escape(const char *name,
 276                                       const struct test_string_2 *s2,
 277                                       unsigned int flags, const char *esc)
 278 {
 279         size_t out_size = 512;
 280         char *out_test = kmalloc(out_size, GFP_KERNEL);
 281         char *out_real = kmalloc(out_size, GFP_KERNEL);
 282         char *in = kmalloc(256, GFP_KERNEL);
 283         int p = 0, q_test = 0;
 284         int q_real;
 285 
 286         if (!out_test || !out_real || !in)
 287                 goto out;
 288 
 289         for (; s2->in; s2++) {
 290                 const char *out;
 291                 int len;
 292 
 293                 /* NULL injection */
 294                 if (flags & ESCAPE_NULL) {
 295                         in[p++] = '\0';
 296                         out_test[q_test++] = '\\';
 297                         out_test[q_test++] = '0';
 298                 }
 299 
 300                 /* Don't try strings that have no output */
 301                 out = test_string_find_match(s2, flags);
 302                 if (!out)
 303                         continue;
 304 
 305                 /* Copy string to in buffer */
 306                 len = strlen(s2->in);
 307                 memcpy(&in[p], s2->in, len);
 308                 p += len;
 309 
 310                 /* Copy expected result for given flags */
 311                 len = strlen(out);
 312                 memcpy(&out_test[q_test], out, len);
 313                 q_test += len;
 314         }
 315 
 316         q_real = string_escape_mem(in, p, out_real, out_size, flags, esc);
 317 
 318         test_string_check_buf(name, flags, in, p, out_real, q_real, out_test,
 319                               q_test);
 320 
 321         test_string_escape_overflow(in, p, flags, esc, q_test, name);
 322 
 323 out:
 324         kfree(in);
 325         kfree(out_real);
 326         kfree(out_test);
 327 }
 328 
 329 #define string_get_size_maxbuf 16
 330 #define test_string_get_size_one(size, blk_size, exp_result10, exp_result2)    \
 331         do {                                                                   \
 332                 BUILD_BUG_ON(sizeof(exp_result10) >= string_get_size_maxbuf);  \
 333                 BUILD_BUG_ON(sizeof(exp_result2) >= string_get_size_maxbuf);   \
 334                 __test_string_get_size((size), (blk_size), (exp_result10),     \
 335                                        (exp_result2));                         \
 336         } while (0)
 337 
 338 
 339 static __init void test_string_get_size_check(const char *units,
 340                                               const char *exp,
 341                                               char *res,
 342                                               const u64 size,
 343                                               const u64 blk_size)
 344 {
 345         if (!memcmp(res, exp, strlen(exp) + 1))
 346                 return;
 347 
 348         res[string_get_size_maxbuf - 1] = '\0';
 349 
 350         pr_warn("Test 'test_string_get_size' failed!\n");
 351         pr_warn("string_get_size(size = %llu, blk_size = %llu, units = %s)\n",
 352                 size, blk_size, units);
 353         pr_warn("expected: '%s', got '%s'\n", exp, res);
 354 }
 355 
 356 static __init void __test_string_get_size(const u64 size, const u64 blk_size,
 357                                           const char *exp_result10,
 358                                           const char *exp_result2)
 359 {
 360         char buf10[string_get_size_maxbuf];
 361         char buf2[string_get_size_maxbuf];
 362 
 363         string_get_size(size, blk_size, STRING_UNITS_10, buf10, sizeof(buf10));
 364         string_get_size(size, blk_size, STRING_UNITS_2, buf2, sizeof(buf2));
 365 
 366         test_string_get_size_check("STRING_UNITS_10", exp_result10, buf10,
 367                                    size, blk_size);
 368 
 369         test_string_get_size_check("STRING_UNITS_2", exp_result2, buf2,
 370                                    size, blk_size);
 371 }
 372 
 373 static __init void test_string_get_size(void)
 374 {
 375         /* small values */
 376         test_string_get_size_one(0, 512, "0 B", "0 B");
 377         test_string_get_size_one(1, 512, "512 B", "512 B");
 378         test_string_get_size_one(1100, 1, "1.10 kB", "1.07 KiB");
 379 
 380         /* normal values */
 381         test_string_get_size_one(16384, 512, "8.39 MB", "8.00 MiB");
 382         test_string_get_size_one(500118192, 512, "256 GB", "238 GiB");
 383         test_string_get_size_one(8192, 4096, "33.6 MB", "32.0 MiB");
 384 
 385         /* weird block sizes */
 386         test_string_get_size_one(3000, 1900, "5.70 MB", "5.44 MiB");
 387 
 388         /* huge values */
 389         test_string_get_size_one(U64_MAX, 4096, "75.6 ZB", "64.0 ZiB");
 390         test_string_get_size_one(4096, U64_MAX, "75.6 ZB", "64.0 ZiB");
 391 }
 392 
 393 static int __init test_string_helpers_init(void)
 394 {
 395         unsigned int i;
 396 
 397         pr_info("Running tests...\n");
 398         for (i = 0; i < UNESCAPE_ANY + 1; i++)
 399                 test_string_unescape("unescape", i, false);
 400         test_string_unescape("unescape inplace",
 401                              get_random_int() % (UNESCAPE_ANY + 1), true);
 402 
 403         /* Without dictionary */
 404         for (i = 0; i < (ESCAPE_ANY_NP | ESCAPE_HEX) + 1; i++)
 405                 test_string_escape("escape 0", escape0, i, TEST_STRING_2_DICT_0);
 406 
 407         /* With dictionary */
 408         for (i = 0; i < (ESCAPE_ANY_NP | ESCAPE_HEX) + 1; i++)
 409                 test_string_escape("escape 1", escape1, i, TEST_STRING_2_DICT_1);
 410 
 411         /* Test string_get_size() */
 412         test_string_get_size();
 413 
 414         return -EINVAL;
 415 }
 416 module_init(test_string_helpers_init);
 417 MODULE_LICENSE("Dual BSD/GPL");

/* [<][>][^][v][top][bottom][index][help] */