blob: 940b1d318831b6aee44eb59616e51cac40c21ddd [file] [log] [blame]
Andy Shevchenko64d1d772015-02-12 15:02:21 -08001/*
2 * Test cases for lib/hexdump.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/module.h>
9#include <linux/random.h>
10#include <linux/string.h>
11
12static const unsigned char data_b[] = {
13 '\xbe', '\x32', '\xdb', '\x7b', '\x0a', '\x18', '\x93', '\xb2', /* 00 - 07 */
14 '\x70', '\xba', '\xc4', '\x24', '\x7d', '\x83', '\x34', '\x9b', /* 08 - 0f */
15 '\xa6', '\x9c', '\x31', '\xad', '\x9c', '\x0f', '\xac', '\xe9', /* 10 - 17 */
16 '\x4c', '\xd1', '\x19', '\x99', '\x43', '\xb1', '\xaf', '\x0c', /* 18 - 1f */
17};
18
19static const unsigned char data_a[] = ".2.{....p..$}.4...1.....L...C...";
20
Andi Kleenc79574a2015-04-15 16:16:39 -070021static const char * const test_data_1_le[] __initconst = {
Andy Shevchenko64d1d772015-02-12 15:02:21 -080022 "be", "32", "db", "7b", "0a", "18", "93", "b2",
23 "70", "ba", "c4", "24", "7d", "83", "34", "9b",
24 "a6", "9c", "31", "ad", "9c", "0f", "ac", "e9",
25 "4c", "d1", "19", "99", "43", "b1", "af", "0c",
26};
27
Geert Uytterhoeven79e23d52015-06-25 15:02:11 -070028static const char * const test_data_2_le[] __initconst = {
Andy Shevchenko64d1d772015-02-12 15:02:21 -080029 "32be", "7bdb", "180a", "b293",
30 "ba70", "24c4", "837d", "9b34",
31 "9ca6", "ad31", "0f9c", "e9ac",
32 "d14c", "9919", "b143", "0caf",
33};
34
Geert Uytterhoeven79e23d52015-06-25 15:02:11 -070035static const char * const test_data_4_le[] __initconst = {
Andy Shevchenko64d1d772015-02-12 15:02:21 -080036 "7bdb32be", "b293180a", "24c4ba70", "9b34837d",
37 "ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143",
38};
39
Geert Uytterhoeven79e23d52015-06-25 15:02:11 -070040static const char * const test_data_8_le[] __initconst = {
Andy Shevchenko64d1d772015-02-12 15:02:21 -080041 "b293180a7bdb32be", "9b34837d24c4ba70",
42 "e9ac0f9cad319ca6", "0cafb1439919d14c",
43};
44
Andy Shevchenko3db4a982016-01-20 14:58:50 -080045#define FILL_CHAR '#'
46
Andy Shevchenko87977ca6b2016-01-20 14:58:47 -080047static void __init test_hexdump_prepare_test(size_t len, int rowsize,
48 int groupsize, char *test,
49 size_t testlen, bool ascii)
Andy Shevchenko64d1d772015-02-12 15:02:21 -080050{
Andy Shevchenko64d1d772015-02-12 15:02:21 -080051 char *p;
Linus Torvalds17974c052015-04-19 13:48:40 -070052 const char * const *result;
Andy Shevchenko64d1d772015-02-12 15:02:21 -080053 size_t l = len;
54 int gs = groupsize, rs = rowsize;
55 unsigned int i;
56
Andy Shevchenko64d1d772015-02-12 15:02:21 -080057 if (rs != 16 && rs != 32)
58 rs = 16;
59
60 if (l > rs)
61 l = rs;
62
63 if (!is_power_of_2(gs) || gs > 8 || (len % gs != 0))
64 gs = 1;
65
66 if (gs == 8)
67 result = test_data_8_le;
68 else if (gs == 4)
69 result = test_data_4_le;
70 else if (gs == 2)
71 result = test_data_2_le;
72 else
73 result = test_data_1_le;
74
Andy Shevchenko3db4a982016-01-20 14:58:50 -080075 memset(test, FILL_CHAR, testlen);
Andy Shevchenko64d1d772015-02-12 15:02:21 -080076
77 /* hex dump */
78 p = test;
79 for (i = 0; i < l / gs; i++) {
80 const char *q = *result++;
81 size_t amount = strlen(q);
82
83 strncpy(p, q, amount);
Andy Shevchenko3db4a982016-01-20 14:58:50 -080084 p += amount;
85
86 *p++ = ' ';
Andy Shevchenko64d1d772015-02-12 15:02:21 -080087 }
88 if (i)
89 p--;
90
91 /* ASCII part */
92 if (ascii) {
Andy Shevchenko3db4a982016-01-20 14:58:50 -080093 do {
94 *p++ = ' ';
95 } while (p < test + rs * 2 + rs / gs + 1);
96
Andy Shevchenko64d1d772015-02-12 15:02:21 -080097 strncpy(p, data_a, l);
98 p += l;
99 }
100
101 *p = '\0';
Andy Shevchenko87977ca6b2016-01-20 14:58:47 -0800102}
103
104#define TEST_HEXDUMP_BUF_SIZE (32 * 3 + 2 + 32 + 1)
105
106static void __init test_hexdump(size_t len, int rowsize, int groupsize,
107 bool ascii)
108{
109 char test[TEST_HEXDUMP_BUF_SIZE];
110 char real[TEST_HEXDUMP_BUF_SIZE];
111
112 hex_dump_to_buffer(data_b, len, rowsize, groupsize, real, sizeof(real),
113 ascii);
114
115 test_hexdump_prepare_test(len, rowsize, groupsize, test, sizeof(test),
116 ascii);
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800117
118 if (strcmp(test, real)) {
119 pr_err("Len: %zu row: %d group: %d\n", len, rowsize, groupsize);
120 pr_err("Result: '%s'\n", real);
121 pr_err("Expect: '%s'\n", test);
122 }
123}
124
125static void __init test_hexdump_set(int rowsize, bool ascii)
126{
127 size_t d = min_t(size_t, sizeof(data_b), rowsize);
128 size_t len = get_random_int() % d + 1;
129
130 test_hexdump(len, rowsize, 4, ascii);
131 test_hexdump(len, rowsize, 2, ascii);
132 test_hexdump(len, rowsize, 8, ascii);
133 test_hexdump(len, rowsize, 1, ascii);
134}
135
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800136static void __init test_hexdump_overflow(size_t buflen, bool ascii)
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800137{
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800138 char buf[TEST_HEXDUMP_BUF_SIZE];
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800139 const char *t = test_data_1_le[0];
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800140 bool a;
141 int e, r;
142
Andy Shevchenko3db4a982016-01-20 14:58:50 -0800143 memset(buf, FILL_CHAR, sizeof(buf));
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800144
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800145 r = hex_dump_to_buffer(data_b, 1, 16, 1, buf, buflen, ascii);
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800146
147 if (ascii)
148 e = 50;
149 else
150 e = 2;
151 buf[e + 2] = '\0';
152
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800153 if (!buflen) {
Andy Shevchenko3db4a982016-01-20 14:58:50 -0800154 a = r == e && buf[0] == FILL_CHAR;
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800155 } else if (buflen < 3) {
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800156 a = r == e && buf[0] == '\0';
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800157 } else if (buflen < 4) {
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800158 a = r == e && !strcmp(buf, t);
159 } else if (ascii) {
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800160 if (buflen < 51)
161 a = r == e && buf[buflen - 1] == '\0' && buf[buflen - 2] == FILL_CHAR;
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800162 else
163 a = r == e && buf[50] == '\0' && buf[49] == '.';
164 } else {
165 a = r == e && buf[e] == '\0';
166 }
167
168 if (!a) {
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800169 pr_err("Len: %zu rc: %u strlen: %zu\n", buflen, r, strlen(buf));
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800170 pr_err("Result: '%s'\n", buf);
171 }
172}
173
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800174static int __init test_hexdump_init(void)
175{
176 unsigned int i;
177 int rowsize;
178
179 pr_info("Running tests...\n");
180
181 rowsize = (get_random_int() % 2 + 1) * 16;
182 for (i = 0; i < 16; i++)
183 test_hexdump_set(rowsize, false);
184
185 rowsize = (get_random_int() % 2 + 1) * 16;
186 for (i = 0; i < 16; i++)
187 test_hexdump_set(rowsize, true);
188
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800189 for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++)
190 test_hexdump_overflow(i, false);
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800191
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800192 for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++)
193 test_hexdump_overflow(i, true);
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800194
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800195 return -EINVAL;
196}
197module_init(test_hexdump_init);
198MODULE_LICENSE("Dual BSD/GPL");