160b2e8f4SAndy Shevchenko /* 260b2e8f4SAndy Shevchenko * Test cases for lib/hexdump.c module. 360b2e8f4SAndy Shevchenko */ 460b2e8f4SAndy Shevchenko #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 560b2e8f4SAndy Shevchenko 660b2e8f4SAndy Shevchenko #include <linux/init.h> 760b2e8f4SAndy Shevchenko #include <linux/kernel.h> 860b2e8f4SAndy Shevchenko #include <linux/module.h> 960b2e8f4SAndy Shevchenko #include <linux/random.h> 1060b2e8f4SAndy Shevchenko #include <linux/string.h> 1160b2e8f4SAndy Shevchenko 1260b2e8f4SAndy Shevchenko static const unsigned char data_b[] = { 1360b2e8f4SAndy Shevchenko '\xbe', '\x32', '\xdb', '\x7b', '\x0a', '\x18', '\x93', '\xb2', /* 00 - 07 */ 1460b2e8f4SAndy Shevchenko '\x70', '\xba', '\xc4', '\x24', '\x7d', '\x83', '\x34', '\x9b', /* 08 - 0f */ 1560b2e8f4SAndy Shevchenko '\xa6', '\x9c', '\x31', '\xad', '\x9c', '\x0f', '\xac', '\xe9', /* 10 - 17 */ 1660b2e8f4SAndy Shevchenko '\x4c', '\xd1', '\x19', '\x99', '\x43', '\xb1', '\xaf', '\x0c', /* 18 - 1f */ 1760b2e8f4SAndy Shevchenko }; 1860b2e8f4SAndy Shevchenko 1960b2e8f4SAndy Shevchenko static const unsigned char data_a[] = ".2.{....p..$}.4...1.....L...C..."; 2060b2e8f4SAndy Shevchenko 2160b2e8f4SAndy Shevchenko static const char * const test_data_1_le[] __initconst = { 2260b2e8f4SAndy Shevchenko "be", "32", "db", "7b", "0a", "18", "93", "b2", 2360b2e8f4SAndy Shevchenko "70", "ba", "c4", "24", "7d", "83", "34", "9b", 2460b2e8f4SAndy Shevchenko "a6", "9c", "31", "ad", "9c", "0f", "ac", "e9", 2560b2e8f4SAndy Shevchenko "4c", "d1", "19", "99", "43", "b1", "af", "0c", 2660b2e8f4SAndy Shevchenko }; 2760b2e8f4SAndy Shevchenko 2860b2e8f4SAndy Shevchenko static const char * const test_data_2_le[] __initconst = { 2960b2e8f4SAndy Shevchenko "32be", "7bdb", "180a", "b293", 3060b2e8f4SAndy Shevchenko "ba70", "24c4", "837d", "9b34", 3160b2e8f4SAndy Shevchenko "9ca6", "ad31", "0f9c", "e9ac", 3260b2e8f4SAndy Shevchenko "d14c", "9919", "b143", "0caf", 3360b2e8f4SAndy Shevchenko }; 3460b2e8f4SAndy Shevchenko 3560b2e8f4SAndy Shevchenko static const char * const test_data_4_le[] __initconst = { 3660b2e8f4SAndy Shevchenko "7bdb32be", "b293180a", "24c4ba70", "9b34837d", 3760b2e8f4SAndy Shevchenko "ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143", 3860b2e8f4SAndy Shevchenko }; 3960b2e8f4SAndy Shevchenko 4060b2e8f4SAndy Shevchenko static const char * const test_data_8_le[] __initconst = { 4160b2e8f4SAndy Shevchenko "b293180a7bdb32be", "9b34837d24c4ba70", 4260b2e8f4SAndy Shevchenko "e9ac0f9cad319ca6", "0cafb1439919d14c", 4360b2e8f4SAndy Shevchenko }; 4460b2e8f4SAndy Shevchenko 453db4a987SAndy Shevchenko #define FILL_CHAR '#' 463db4a987SAndy Shevchenko 4787977ca6SAndy Shevchenko static void __init test_hexdump_prepare_test(size_t len, int rowsize, 4887977ca6SAndy Shevchenko int groupsize, char *test, 4987977ca6SAndy Shevchenko size_t testlen, bool ascii) 5060b2e8f4SAndy Shevchenko { 5160b2e8f4SAndy Shevchenko char *p; 5260b2e8f4SAndy Shevchenko const char * const *result; 5360b2e8f4SAndy Shevchenko size_t l = len; 5460b2e8f4SAndy Shevchenko int gs = groupsize, rs = rowsize; 5560b2e8f4SAndy Shevchenko unsigned int i; 5660b2e8f4SAndy Shevchenko 5760b2e8f4SAndy Shevchenko if (rs != 16 && rs != 32) 5860b2e8f4SAndy Shevchenko rs = 16; 5960b2e8f4SAndy Shevchenko 6060b2e8f4SAndy Shevchenko if (l > rs) 6160b2e8f4SAndy Shevchenko l = rs; 6260b2e8f4SAndy Shevchenko 6360b2e8f4SAndy Shevchenko if (!is_power_of_2(gs) || gs > 8 || (len % gs != 0)) 6460b2e8f4SAndy Shevchenko gs = 1; 6560b2e8f4SAndy Shevchenko 6660b2e8f4SAndy Shevchenko if (gs == 8) 6760b2e8f4SAndy Shevchenko result = test_data_8_le; 6860b2e8f4SAndy Shevchenko else if (gs == 4) 6960b2e8f4SAndy Shevchenko result = test_data_4_le; 7060b2e8f4SAndy Shevchenko else if (gs == 2) 7160b2e8f4SAndy Shevchenko result = test_data_2_le; 7260b2e8f4SAndy Shevchenko else 7360b2e8f4SAndy Shevchenko result = test_data_1_le; 7460b2e8f4SAndy Shevchenko 753db4a987SAndy Shevchenko memset(test, FILL_CHAR, testlen); 7660b2e8f4SAndy Shevchenko 7760b2e8f4SAndy Shevchenko /* hex dump */ 7860b2e8f4SAndy Shevchenko p = test; 7960b2e8f4SAndy Shevchenko for (i = 0; i < l / gs; i++) { 8060b2e8f4SAndy Shevchenko const char *q = *result++; 8160b2e8f4SAndy Shevchenko size_t amount = strlen(q); 8260b2e8f4SAndy Shevchenko 8360b2e8f4SAndy Shevchenko strncpy(p, q, amount); 843db4a987SAndy Shevchenko p += amount; 853db4a987SAndy Shevchenko 863db4a987SAndy Shevchenko *p++ = ' '; 8760b2e8f4SAndy Shevchenko } 8860b2e8f4SAndy Shevchenko if (i) 8960b2e8f4SAndy Shevchenko p--; 9060b2e8f4SAndy Shevchenko 9160b2e8f4SAndy Shevchenko /* ASCII part */ 9260b2e8f4SAndy Shevchenko if (ascii) { 933db4a987SAndy Shevchenko do { 943db4a987SAndy Shevchenko *p++ = ' '; 953db4a987SAndy Shevchenko } while (p < test + rs * 2 + rs / gs + 1); 963db4a987SAndy Shevchenko 9760b2e8f4SAndy Shevchenko strncpy(p, data_a, l); 9860b2e8f4SAndy Shevchenko p += l; 9960b2e8f4SAndy Shevchenko } 10060b2e8f4SAndy Shevchenko 10160b2e8f4SAndy Shevchenko *p = '\0'; 10287977ca6SAndy Shevchenko } 10387977ca6SAndy Shevchenko 10487977ca6SAndy Shevchenko #define TEST_HEXDUMP_BUF_SIZE (32 * 3 + 2 + 32 + 1) 10587977ca6SAndy Shevchenko 10687977ca6SAndy Shevchenko static void __init test_hexdump(size_t len, int rowsize, int groupsize, 10787977ca6SAndy Shevchenko bool ascii) 10887977ca6SAndy Shevchenko { 10987977ca6SAndy Shevchenko char test[TEST_HEXDUMP_BUF_SIZE]; 11087977ca6SAndy Shevchenko char real[TEST_HEXDUMP_BUF_SIZE]; 11187977ca6SAndy Shevchenko 11287977ca6SAndy Shevchenko hex_dump_to_buffer(data_b, len, rowsize, groupsize, real, sizeof(real), 11387977ca6SAndy Shevchenko ascii); 11487977ca6SAndy Shevchenko 11587977ca6SAndy Shevchenko test_hexdump_prepare_test(len, rowsize, groupsize, test, sizeof(test), 11687977ca6SAndy Shevchenko ascii); 11760b2e8f4SAndy Shevchenko 11860b2e8f4SAndy Shevchenko if (strcmp(test, real)) { 11960b2e8f4SAndy Shevchenko pr_err("Len: %zu row: %d group: %d\n", len, rowsize, groupsize); 12060b2e8f4SAndy Shevchenko pr_err("Result: '%s'\n", real); 12160b2e8f4SAndy Shevchenko pr_err("Expect: '%s'\n", test); 12260b2e8f4SAndy Shevchenko } 12360b2e8f4SAndy Shevchenko } 12460b2e8f4SAndy Shevchenko 12560b2e8f4SAndy Shevchenko static void __init test_hexdump_set(int rowsize, bool ascii) 12660b2e8f4SAndy Shevchenko { 12760b2e8f4SAndy Shevchenko size_t d = min_t(size_t, sizeof(data_b), rowsize); 12860b2e8f4SAndy Shevchenko size_t len = get_random_int() % d + 1; 12960b2e8f4SAndy Shevchenko 13060b2e8f4SAndy Shevchenko test_hexdump(len, rowsize, 4, ascii); 13160b2e8f4SAndy Shevchenko test_hexdump(len, rowsize, 2, ascii); 13260b2e8f4SAndy Shevchenko test_hexdump(len, rowsize, 8, ascii); 13360b2e8f4SAndy Shevchenko test_hexdump(len, rowsize, 1, ascii); 13460b2e8f4SAndy Shevchenko } 13560b2e8f4SAndy Shevchenko 136*a3d601fcSAndy Shevchenko static void __init test_hexdump_overflow(size_t buflen, bool ascii) 13760b2e8f4SAndy Shevchenko { 138*a3d601fcSAndy Shevchenko char buf[TEST_HEXDUMP_BUF_SIZE]; 13960b2e8f4SAndy Shevchenko const char *t = test_data_1_le[0]; 14060b2e8f4SAndy Shevchenko bool a; 14160b2e8f4SAndy Shevchenko int e, r; 14260b2e8f4SAndy Shevchenko 1433db4a987SAndy Shevchenko memset(buf, FILL_CHAR, sizeof(buf)); 14460b2e8f4SAndy Shevchenko 145*a3d601fcSAndy Shevchenko r = hex_dump_to_buffer(data_b, 1, 16, 1, buf, buflen, ascii); 14660b2e8f4SAndy Shevchenko 14760b2e8f4SAndy Shevchenko if (ascii) 14860b2e8f4SAndy Shevchenko e = 50; 14960b2e8f4SAndy Shevchenko else 15060b2e8f4SAndy Shevchenko e = 2; 15160b2e8f4SAndy Shevchenko buf[e + 2] = '\0'; 15260b2e8f4SAndy Shevchenko 153*a3d601fcSAndy Shevchenko if (!buflen) { 1543db4a987SAndy Shevchenko a = r == e && buf[0] == FILL_CHAR; 155*a3d601fcSAndy Shevchenko } else if (buflen < 3) { 15660b2e8f4SAndy Shevchenko a = r == e && buf[0] == '\0'; 157*a3d601fcSAndy Shevchenko } else if (buflen < 4) { 15860b2e8f4SAndy Shevchenko a = r == e && !strcmp(buf, t); 15960b2e8f4SAndy Shevchenko } else if (ascii) { 160*a3d601fcSAndy Shevchenko if (buflen < 51) 161*a3d601fcSAndy Shevchenko a = r == e && buf[buflen - 1] == '\0' && buf[buflen - 2] == FILL_CHAR; 16260b2e8f4SAndy Shevchenko else 16360b2e8f4SAndy Shevchenko a = r == e && buf[50] == '\0' && buf[49] == '.'; 16460b2e8f4SAndy Shevchenko } else { 16560b2e8f4SAndy Shevchenko a = r == e && buf[e] == '\0'; 16660b2e8f4SAndy Shevchenko } 16760b2e8f4SAndy Shevchenko 16860b2e8f4SAndy Shevchenko if (!a) { 169*a3d601fcSAndy Shevchenko pr_err("Len: %zu rc: %u strlen: %zu\n", buflen, r, strlen(buf)); 17060b2e8f4SAndy Shevchenko pr_err("Result: '%s'\n", buf); 17160b2e8f4SAndy Shevchenko } 17260b2e8f4SAndy Shevchenko } 17360b2e8f4SAndy Shevchenko 17460b2e8f4SAndy Shevchenko static int __init test_hexdump_init(void) 17560b2e8f4SAndy Shevchenko { 17660b2e8f4SAndy Shevchenko unsigned int i; 17760b2e8f4SAndy Shevchenko int rowsize; 17860b2e8f4SAndy Shevchenko 17960b2e8f4SAndy Shevchenko pr_info("Running tests...\n"); 18060b2e8f4SAndy Shevchenko 18160b2e8f4SAndy Shevchenko rowsize = (get_random_int() % 2 + 1) * 16; 18260b2e8f4SAndy Shevchenko for (i = 0; i < 16; i++) 18360b2e8f4SAndy Shevchenko test_hexdump_set(rowsize, false); 18460b2e8f4SAndy Shevchenko 18560b2e8f4SAndy Shevchenko rowsize = (get_random_int() % 2 + 1) * 16; 18660b2e8f4SAndy Shevchenko for (i = 0; i < 16; i++) 18760b2e8f4SAndy Shevchenko test_hexdump_set(rowsize, true); 18860b2e8f4SAndy Shevchenko 189*a3d601fcSAndy Shevchenko for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++) 190*a3d601fcSAndy Shevchenko test_hexdump_overflow(i, false); 19160b2e8f4SAndy Shevchenko 192*a3d601fcSAndy Shevchenko for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++) 193*a3d601fcSAndy Shevchenko test_hexdump_overflow(i, true); 19460b2e8f4SAndy Shevchenko 19560b2e8f4SAndy Shevchenko return -EINVAL; 19660b2e8f4SAndy Shevchenko } 19760b2e8f4SAndy Shevchenko module_init(test_hexdump_init); 19860b2e8f4SAndy Shevchenko MODULE_LICENSE("Dual BSD/GPL"); 199