blob: 3f415d8101f3209f16ba66143ee1b31b56d4b0b1 [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 Shevchenko7aaf4c32016-01-20 14:59:07 -080047static unsigned total_tests __initdata;
48static unsigned failed_tests __initdata;
49
Andy Shevchenko87977ca6b2016-01-20 14:58:47 -080050static void __init test_hexdump_prepare_test(size_t len, int rowsize,
51 int groupsize, char *test,
52 size_t testlen, bool ascii)
Andy Shevchenko64d1d772015-02-12 15:02:21 -080053{
Andy Shevchenko64d1d772015-02-12 15:02:21 -080054 char *p;
Linus Torvalds17974c052015-04-19 13:48:40 -070055 const char * const *result;
Andy Shevchenko64d1d772015-02-12 15:02:21 -080056 size_t l = len;
57 int gs = groupsize, rs = rowsize;
58 unsigned int i;
59
Andy Shevchenko64d1d772015-02-12 15:02:21 -080060 if (rs != 16 && rs != 32)
61 rs = 16;
62
63 if (l > rs)
64 l = rs;
65
66 if (!is_power_of_2(gs) || gs > 8 || (len % gs != 0))
67 gs = 1;
68
69 if (gs == 8)
70 result = test_data_8_le;
71 else if (gs == 4)
72 result = test_data_4_le;
73 else if (gs == 2)
74 result = test_data_2_le;
75 else
76 result = test_data_1_le;
77
Andy Shevchenko64d1d772015-02-12 15:02:21 -080078 /* hex dump */
79 p = test;
80 for (i = 0; i < l / gs; i++) {
81 const char *q = *result++;
82 size_t amount = strlen(q);
83
84 strncpy(p, q, amount);
Andy Shevchenko3db4a982016-01-20 14:58:50 -080085 p += amount;
86
87 *p++ = ' ';
Andy Shevchenko64d1d772015-02-12 15:02:21 -080088 }
89 if (i)
90 p--;
91
92 /* ASCII part */
93 if (ascii) {
Andy Shevchenko3db4a982016-01-20 14:58:50 -080094 do {
95 *p++ = ' ';
96 } while (p < test + rs * 2 + rs / gs + 1);
97
Andy Shevchenko64d1d772015-02-12 15:02:21 -080098 strncpy(p, data_a, l);
99 p += l;
100 }
101
102 *p = '\0';
Andy Shevchenko87977ca6b2016-01-20 14:58:47 -0800103}
104
105#define TEST_HEXDUMP_BUF_SIZE (32 * 3 + 2 + 32 + 1)
106
107static void __init test_hexdump(size_t len, int rowsize, int groupsize,
108 bool ascii)
109{
110 char test[TEST_HEXDUMP_BUF_SIZE];
111 char real[TEST_HEXDUMP_BUF_SIZE];
112
Andy Shevchenko7aaf4c32016-01-20 14:59:07 -0800113 total_tests++;
114
Andy Shevchenko7047d812016-01-20 14:58:58 -0800115 memset(real, FILL_CHAR, sizeof(real));
Andy Shevchenko87977ca6b2016-01-20 14:58:47 -0800116 hex_dump_to_buffer(data_b, len, rowsize, groupsize, real, sizeof(real),
117 ascii);
118
Andy Shevchenko7047d812016-01-20 14:58:58 -0800119 memset(test, FILL_CHAR, sizeof(test));
Andy Shevchenko87977ca6b2016-01-20 14:58:47 -0800120 test_hexdump_prepare_test(len, rowsize, groupsize, test, sizeof(test),
121 ascii);
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800122
Andy Shevchenko7047d812016-01-20 14:58:58 -0800123 if (memcmp(test, real, TEST_HEXDUMP_BUF_SIZE)) {
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800124 pr_err("Len: %zu row: %d group: %d\n", len, rowsize, groupsize);
125 pr_err("Result: '%s'\n", real);
126 pr_err("Expect: '%s'\n", test);
Andy Shevchenko7aaf4c32016-01-20 14:59:07 -0800127 failed_tests++;
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800128 }
129}
130
131static void __init test_hexdump_set(int rowsize, bool ascii)
132{
133 size_t d = min_t(size_t, sizeof(data_b), rowsize);
134 size_t len = get_random_int() % d + 1;
135
136 test_hexdump(len, rowsize, 4, ascii);
137 test_hexdump(len, rowsize, 2, ascii);
138 test_hexdump(len, rowsize, 8, ascii);
139 test_hexdump(len, rowsize, 1, ascii);
140}
141
Andy Shevchenko1dacd9d2016-01-20 14:59:04 -0800142static void __init test_hexdump_overflow(size_t buflen, size_t len,
143 int rowsize, int groupsize,
144 bool ascii)
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800145{
Andy Shevchenkocc77a712016-01-20 14:59:01 -0800146 char test[TEST_HEXDUMP_BUF_SIZE];
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800147 char buf[TEST_HEXDUMP_BUF_SIZE];
Andy Shevchenkocc77a712016-01-20 14:59:01 -0800148 int rs = rowsize, gs = groupsize;
149 int ae, he, e, f, r;
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800150 bool a;
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800151
Andy Shevchenko7aaf4c32016-01-20 14:59:07 -0800152 total_tests++;
153
Andy Shevchenko3db4a982016-01-20 14:58:50 -0800154 memset(buf, FILL_CHAR, sizeof(buf));
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800155
Andy Shevchenkoad27a752016-01-20 14:58:56 -0800156 r = hex_dump_to_buffer(data_b, len, rs, gs, buf, buflen, ascii);
157
158 /*
159 * Caller must provide the data length multiple of groupsize. The
160 * calculations below are made with that assumption in mind.
161 */
162 ae = rs * 2 /* hex */ + rs / gs /* spaces */ + 1 /* space */ + len /* ascii */;
163 he = (gs * 2 /* hex */ + 1 /* space */) * len / gs - 1 /* no trailing space */;
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800164
165 if (ascii)
Andy Shevchenkoad27a752016-01-20 14:58:56 -0800166 e = ae;
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800167 else
Andy Shevchenkoad27a752016-01-20 14:58:56 -0800168 e = he;
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800169
Andy Shevchenkocc77a712016-01-20 14:59:01 -0800170 f = min_t(int, e + 1, buflen);
171 if (buflen) {
172 test_hexdump_prepare_test(len, rs, gs, test, sizeof(test), ascii);
173 test[f - 1] = '\0';
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800174 }
Andy Shevchenkocc77a712016-01-20 14:59:01 -0800175 memset(test + f, FILL_CHAR, sizeof(test) - f);
176
177 a = r == e && !memcmp(test, buf, TEST_HEXDUMP_BUF_SIZE);
178
179 buf[sizeof(buf) - 1] = '\0';
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800180
181 if (!a) {
Andy Shevchenkocc77a712016-01-20 14:59:01 -0800182 pr_err("Len: %zu buflen: %zu strlen: %zu\n",
183 len, buflen, strnlen(buf, sizeof(buf)));
184 pr_err("Result: %d '%s'\n", r, buf);
185 pr_err("Expect: %d '%s'\n", e, test);
Andy Shevchenko7aaf4c32016-01-20 14:59:07 -0800186 failed_tests++;
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800187 }
188}
189
Andy Shevchenko1dacd9d2016-01-20 14:59:04 -0800190static void __init test_hexdump_overflow_set(size_t buflen, bool ascii)
191{
192 unsigned int i = 0;
193 int rs = (get_random_int() % 2 + 1) * 16;
194
195 do {
196 int gs = 1 << i;
197 size_t len = get_random_int() % rs + gs;
198
199 test_hexdump_overflow(buflen, rounddown(len, gs), rs, gs, ascii);
200 } while (i++ < 3);
201}
202
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800203static int __init test_hexdump_init(void)
204{
205 unsigned int i;
206 int rowsize;
207
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800208 rowsize = (get_random_int() % 2 + 1) * 16;
209 for (i = 0; i < 16; i++)
210 test_hexdump_set(rowsize, false);
211
212 rowsize = (get_random_int() % 2 + 1) * 16;
213 for (i = 0; i < 16; i++)
214 test_hexdump_set(rowsize, true);
215
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800216 for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++)
Andy Shevchenko1dacd9d2016-01-20 14:59:04 -0800217 test_hexdump_overflow_set(i, false);
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800218
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800219 for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++)
Andy Shevchenko1dacd9d2016-01-20 14:59:04 -0800220 test_hexdump_overflow_set(i, true);
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800221
Andy Shevchenko7aaf4c32016-01-20 14:59:07 -0800222 if (failed_tests == 0)
223 pr_info("all %u tests passed\n", total_tests);
224 else
225 pr_err("failed %u out of %u tests\n", failed_tests, total_tests);
226
227 return failed_tests ? -EINVAL : 0;
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800228}
229module_init(test_hexdump_init);
Andy Shevchenko7aaf4c32016-01-20 14:59:07 -0800230
231static void __exit test_hexdump_exit(void)
232{
233 /* do nothing */
234}
235module_exit(test_hexdump_exit);
236
237MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800238MODULE_LICENSE("Dual BSD/GPL");