Back to home page

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_le[] __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_4_le[] __initconst = {
0036     "7bdb32be", "b293180a", "24c4ba70", "9b34837d",
0037     "ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143",
0038 };
0039 
0040 static const char * const test_data_8_le[] __initconst = {
0041     "b293180a7bdb32be", "9b34837d24c4ba70",
0042     "e9ac0f9cad319ca6", "0cafb1439919d14c",
0043 };
0044 
0045 #define FILL_CHAR   '#'
0046 
0047 static unsigned total_tests __initdata;
0048 static unsigned failed_tests __initdata;
0049 
0050 static void __init test_hexdump_prepare_test(size_t len, int rowsize,
0051                          int groupsize, char *test,
0052                          size_t testlen, bool ascii)
0053 {
0054     char *p;
0055     const char * const *result;
0056     size_t l = len;
0057     int gs = groupsize, rs = rowsize;
0058     unsigned int i;
0059 
0060     if (rs != 16 && rs != 32)
0061         rs = 16;
0062 
0063     if (l > rs)
0064         l = rs;
0065 
0066     if (!is_power_of_2(gs) || gs > 8 || (len % gs != 0))
0067         gs = 1;
0068 
0069     if (gs == 8)
0070         result = test_data_8_le;
0071     else if (gs == 4)
0072         result = test_data_4_le;
0073     else if (gs == 2)
0074         result = test_data_2_le;
0075     else
0076         result = test_data_1_le;
0077 
0078     /* hex dump */
0079     p = test;
0080     for (i = 0; i < l / gs; i++) {
0081         const char *q = *result++;
0082         size_t amount = strlen(q);
0083 
0084         strncpy(p, q, amount);
0085         p += amount;
0086 
0087         *p++ = ' ';
0088     }
0089     if (i)
0090         p--;
0091 
0092     /* ASCII part */
0093     if (ascii) {
0094         do {
0095             *p++ = ' ';
0096         } while (p < test + rs * 2 + rs / gs + 1);
0097 
0098         strncpy(p, data_a, l);
0099         p += l;
0100     }
0101 
0102     *p = '\0';
0103 }
0104 
0105 #define TEST_HEXDUMP_BUF_SIZE       (32 * 3 + 2 + 32 + 1)
0106 
0107 static void __init test_hexdump(size_t len, int rowsize, int groupsize,
0108                 bool ascii)
0109 {
0110     char test[TEST_HEXDUMP_BUF_SIZE];
0111     char real[TEST_HEXDUMP_BUF_SIZE];
0112 
0113     total_tests++;
0114 
0115     memset(real, FILL_CHAR, sizeof(real));
0116     hex_dump_to_buffer(data_b, len, rowsize, groupsize, real, sizeof(real),
0117                ascii);
0118 
0119     memset(test, FILL_CHAR, sizeof(test));
0120     test_hexdump_prepare_test(len, rowsize, groupsize, test, sizeof(test),
0121                   ascii);
0122 
0123     if (memcmp(test, real, TEST_HEXDUMP_BUF_SIZE)) {
0124         pr_err("Len: %zu row: %d group: %d\n", len, rowsize, groupsize);
0125         pr_err("Result: '%s'\n", real);
0126         pr_err("Expect: '%s'\n", test);
0127         failed_tests++;
0128     }
0129 }
0130 
0131 static void __init test_hexdump_set(int rowsize, bool ascii)
0132 {
0133     size_t d = min_t(size_t, sizeof(data_b), rowsize);
0134     size_t len = get_random_int() % d + 1;
0135 
0136     test_hexdump(len, rowsize, 4, ascii);
0137     test_hexdump(len, rowsize, 2, ascii);
0138     test_hexdump(len, rowsize, 8, ascii);
0139     test_hexdump(len, rowsize, 1, ascii);
0140 }
0141 
0142 static void __init test_hexdump_overflow(size_t buflen, size_t len,
0143                      int rowsize, int groupsize,
0144                      bool ascii)
0145 {
0146     char test[TEST_HEXDUMP_BUF_SIZE];
0147     char buf[TEST_HEXDUMP_BUF_SIZE];
0148     int rs = rowsize, gs = groupsize;
0149     int ae, he, e, f, r;
0150     bool a;
0151 
0152     total_tests++;
0153 
0154     memset(buf, FILL_CHAR, sizeof(buf));
0155 
0156     r = hex_dump_to_buffer(data_b, len, rs, gs, buf, buflen, ascii);
0157 
0158     /*
0159      * Caller must provide the data length multiple of groupsize. The
0160      * calculations below are made with that assumption in mind.
0161      */
0162     ae = rs * 2 /* hex */ + rs / gs /* spaces */ + 1 /* space */ + len /* ascii */;
0163     he = (gs * 2 /* hex */ + 1 /* space */) * len / gs - 1 /* no trailing space */;
0164 
0165     if (ascii)
0166         e = ae;
0167     else
0168         e = he;
0169 
0170     f = min_t(int, e + 1, buflen);
0171     if (buflen) {
0172         test_hexdump_prepare_test(len, rs, gs, test, sizeof(test), ascii);
0173         test[f - 1] = '\0';
0174     }
0175     memset(test + f, FILL_CHAR, sizeof(test) - f);
0176 
0177     a = r == e && !memcmp(test, buf, TEST_HEXDUMP_BUF_SIZE);
0178 
0179     buf[sizeof(buf) - 1] = '\0';
0180 
0181     if (!a) {
0182         pr_err("Len: %zu buflen: %zu strlen: %zu\n",
0183             len, buflen, strnlen(buf, sizeof(buf)));
0184         pr_err("Result: %d '%s'\n", r, buf);
0185         pr_err("Expect: %d '%s'\n", e, test);
0186         failed_tests++;
0187     }
0188 }
0189 
0190 static void __init test_hexdump_overflow_set(size_t buflen, bool ascii)
0191 {
0192     unsigned int i = 0;
0193     int rs = (get_random_int() % 2 + 1) * 16;
0194 
0195     do {
0196         int gs = 1 << i;
0197         size_t len = get_random_int() % rs + gs;
0198 
0199         test_hexdump_overflow(buflen, rounddown(len, gs), rs, gs, ascii);
0200     } while (i++ < 3);
0201 }
0202 
0203 static int __init test_hexdump_init(void)
0204 {
0205     unsigned int i;
0206     int rowsize;
0207 
0208     rowsize = (get_random_int() % 2 + 1) * 16;
0209     for (i = 0; i < 16; i++)
0210         test_hexdump_set(rowsize, false);
0211 
0212     rowsize = (get_random_int() % 2 + 1) * 16;
0213     for (i = 0; i < 16; i++)
0214         test_hexdump_set(rowsize, true);
0215 
0216     for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++)
0217         test_hexdump_overflow_set(i, false);
0218 
0219     for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++)
0220         test_hexdump_overflow_set(i, true);
0221 
0222     if (failed_tests == 0)
0223         pr_info("all %u tests passed\n", total_tests);
0224     else
0225         pr_err("failed %u out of %u tests\n", failed_tests, total_tests);
0226 
0227     return failed_tests ? -EINVAL : 0;
0228 }
0229 module_init(test_hexdump_init);
0230 
0231 static void __exit test_hexdump_exit(void)
0232 {
0233     /* do nothing */
0234 }
0235 module_exit(test_hexdump_exit);
0236 
0237 MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
0238 MODULE_LICENSE("Dual BSD/GPL");