xref: /linux/lib/test_hexdump.c (revision a3d601fcc2f94fd1583053a1b1aea5de66ffc79c)
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