Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Test cases for lib/hexdump.c module.
0003  */
0004 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0005 
0006 #include <linux/init.h>
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 #include <linux/random.h>
0010 #include <linux/string.h>
0011 
0012 static const unsigned char data_b[] = {
0013     '\xbe', '\x32', '\xdb', '\x7b', '\x0a', '\x18', '\x93', '\xb2', /* 00 - 07 */
0014     '\x70', '\xba', '\xc4', '\x24', '\x7d', '\x83', '\x34', '\x9b', /* 08 - 0f */
0015     '\xa6', '\x9c', '\x31', '\xad', '\x9c', '\x0f', '\xac', '\xe9', /* 10 - 17 */
0016     '\x4c', '\xd1', '\x19', '\x99', '\x43', '\xb1', '\xaf', '\x0c', /* 18 - 1f */
0017 };
0018 
0019 static const unsigned char data_a[] = ".2.{....p..$}.4...1.....L...C...";
0020 
0021 static const char * const test_data_1[] __initconst = {
0022     "be", "32", "db", "7b", "0a", "18", "93", "b2",
0023     "70", "ba", "c4", "24", "7d", "83", "34", "9b",
0024     "a6", "9c", "31", "ad", "9c", "0f", "ac", "e9",
0025     "4c", "d1", "19", "99", "43", "b1", "af", "0c",
0026 };
0027 
0028 static const char * const test_data_2_le[] __initconst = {
0029     "32be", "7bdb", "180a", "b293",
0030     "ba70", "24c4", "837d", "9b34",
0031     "9ca6", "ad31", "0f9c", "e9ac",
0032     "d14c", "9919", "b143", "0caf",
0033 };
0034 
0035 static const char * const test_data_2_be[] __initconst = {
0036     "be32", "db7b", "0a18", "93b2",
0037     "70ba", "c424", "7d83", "349b",
0038     "a69c", "31ad", "9c0f", "ace9",
0039     "4cd1", "1999", "43b1", "af0c",
0040 };
0041 
0042 static const char * const test_data_4_le[] __initconst = {
0043     "7bdb32be", "b293180a", "24c4ba70", "9b34837d",
0044     "ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143",
0045 };
0046 
0047 static const char * const test_data_4_be[] __initconst = {
0048     "be32db7b", "0a1893b2", "70bac424", "7d83349b",
0049     "a69c31ad", "9c0face9", "4cd11999", "43b1af0c",
0050 };
0051 
0052 static const char * const test_data_8_le[] __initconst = {
0053     "b293180a7bdb32be", "9b34837d24c4ba70",
0054     "e9ac0f9cad319ca6", "0cafb1439919d14c",
0055 };
0056 
0057 static const char * const test_data_8_be[] __initconst = {
0058     "be32db7b0a1893b2", "70bac4247d83349b",
0059     "a69c31ad9c0face9", "4cd1199943b1af0c",
0060 };
0061 
0062 #define FILL_CHAR   '#'
0063 
0064 static unsigned total_tests __initdata;
0065 static unsigned failed_tests __initdata;
0066 
0067 static void __init test_hexdump_prepare_test(size_t len, int rowsize,
0068                          int groupsize, char *test,
0069                          size_t testlen, bool ascii)
0070 {
0071     char *p;
0072     const char * const *result;
0073     size_t l = len;
0074     int gs = groupsize, rs = rowsize;
0075     unsigned int i;
0076     const bool is_be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN);
0077 
0078     if (rs != 16 && rs != 32)
0079         rs = 16;
0080 
0081     if (l > rs)
0082         l = rs;
0083 
0084     if (!is_power_of_2(gs) || gs > 8 || (len % gs != 0))
0085         gs = 1;
0086 
0087     if (gs == 8)
0088         result = is_be ? test_data_8_be : test_data_8_le;
0089     else if (gs == 4)
0090         result = is_be ? test_data_4_be : test_data_4_le;
0091     else if (gs == 2)
0092         result = is_be ? test_data_2_be : test_data_2_le;
0093     else
0094         result = test_data_1;
0095 
0096     /* hex dump */
0097     p = test;
0098     for (i = 0; i < l / gs; i++) {
0099         const char *q = *result++;
0100         size_t amount = strlen(q);
0101 
0102         memcpy(p, q, amount);
0103         p += amount;
0104 
0105         *p++ = ' ';
0106     }
0107     if (i)
0108         p--;
0109 
0110     /* ASCII part */
0111     if (ascii) {
0112         do {
0113             *p++ = ' ';
0114         } while (p < test + rs * 2 + rs / gs + 1);
0115 
0116         strncpy(p, data_a, l);
0117         p += l;
0118     }
0119 
0120     *p = '\0';
0121 }
0122 
0123 #define TEST_HEXDUMP_BUF_SIZE       (32 * 3 + 2 + 32 + 1)
0124 
0125 static void __init test_hexdump(size_t len, int rowsize, int groupsize,
0126                 bool ascii)
0127 {
0128     char test[TEST_HEXDUMP_BUF_SIZE];
0129     char real[TEST_HEXDUMP_BUF_SIZE];
0130 
0131     total_tests++;
0132 
0133     memset(real, FILL_CHAR, sizeof(real));
0134     hex_dump_to_buffer(data_b, len, rowsize, groupsize, real, sizeof(real),
0135                ascii);
0136 
0137     memset(test, FILL_CHAR, sizeof(test));
0138     test_hexdump_prepare_test(len, rowsize, groupsize, test, sizeof(test),
0139                   ascii);
0140 
0141     if (memcmp(test, real, TEST_HEXDUMP_BUF_SIZE)) {
0142         pr_err("Len: %zu row: %d group: %d\n", len, rowsize, groupsize);
0143         pr_err("Result: '%s'\n", real);
0144         pr_err("Expect: '%s'\n", test);
0145         failed_tests++;
0146     }
0147 }
0148 
0149 static void __init test_hexdump_set(int rowsize, bool ascii)
0150 {
0151     size_t d = min_t(size_t, sizeof(data_b), rowsize);
0152     size_t len = get_random_int() % d + 1;
0153 
0154     test_hexdump(len, rowsize, 4, ascii);
0155     test_hexdump(len, rowsize, 2, ascii);
0156     test_hexdump(len, rowsize, 8, ascii);
0157     test_hexdump(len, rowsize, 1, ascii);
0158 }
0159 
0160 static void __init test_hexdump_overflow(size_t buflen, size_t len,
0161                      int rowsize, int groupsize,
0162                      bool ascii)
0163 {
0164     char test[TEST_HEXDUMP_BUF_SIZE];
0165     char buf[TEST_HEXDUMP_BUF_SIZE];
0166     int rs = rowsize, gs = groupsize;
0167     int ae, he, e, f, r;
0168     bool a;
0169 
0170     total_tests++;
0171 
0172     memset(buf, FILL_CHAR, sizeof(buf));
0173 
0174     r = hex_dump_to_buffer(data_b, len, rs, gs, buf, buflen, ascii);
0175 
0176     /*
0177      * Caller must provide the data length multiple of groupsize. The
0178      * calculations below are made with that assumption in mind.
0179      */
0180     ae = rs * 2 /* hex */ + rs / gs /* spaces */ + 1 /* space */ + len /* ascii */;
0181     he = (gs * 2 /* hex */ + 1 /* space */) * len / gs - 1 /* no trailing space */;
0182 
0183     if (ascii)
0184         e = ae;
0185     else
0186         e = he;
0187 
0188     f = min_t(int, e + 1, buflen);
0189     if (buflen) {
0190         test_hexdump_prepare_test(len, rs, gs, test, sizeof(test), ascii);
0191         test[f - 1] = '\0';
0192     }
0193     memset(test + f, FILL_CHAR, sizeof(test) - f);
0194 
0195     a = r == e && !memcmp(test, buf, TEST_HEXDUMP_BUF_SIZE);
0196 
0197     buf[sizeof(buf) - 1] = '\0';
0198 
0199     if (!a) {
0200         pr_err("Len: %zu buflen: %zu strlen: %zu\n",
0201             len, buflen, strnlen(buf, sizeof(buf)));
0202         pr_err("Result: %d '%s'\n", r, buf);
0203         pr_err("Expect: %d '%s'\n", e, test);
0204         failed_tests++;
0205     }
0206 }
0207 
0208 static void __init test_hexdump_overflow_set(size_t buflen, bool ascii)
0209 {
0210     unsigned int i = 0;
0211     int rs = (get_random_int() % 2 + 1) * 16;
0212 
0213     do {
0214         int gs = 1 << i;
0215         size_t len = get_random_int() % rs + gs;
0216 
0217         test_hexdump_overflow(buflen, rounddown(len, gs), rs, gs, ascii);
0218     } while (i++ < 3);
0219 }
0220 
0221 static int __init test_hexdump_init(void)
0222 {
0223     unsigned int i;
0224     int rowsize;
0225 
0226     rowsize = (get_random_int() % 2 + 1) * 16;
0227     for (i = 0; i < 16; i++)
0228         test_hexdump_set(rowsize, false);
0229 
0230     rowsize = (get_random_int() % 2 + 1) * 16;
0231     for (i = 0; i < 16; i++)
0232         test_hexdump_set(rowsize, true);
0233 
0234     for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++)
0235         test_hexdump_overflow_set(i, false);
0236 
0237     for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++)
0238         test_hexdump_overflow_set(i, true);
0239 
0240     if (failed_tests == 0)
0241         pr_info("all %u tests passed\n", total_tests);
0242     else
0243         pr_err("failed %u out of %u tests\n", failed_tests, total_tests);
0244 
0245     return failed_tests ? -EINVAL : 0;
0246 }
0247 module_init(test_hexdump_init);
0248 
0249 static void __exit test_hexdump_exit(void)
0250 {
0251     /* do nothing */
0252 }
0253 module_exit(test_hexdump_exit);
0254 
0255 MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
0256 MODULE_LICENSE("Dual BSD/GPL");