blob: 5144899d3c6b8b235d33c8a988f3a413fa34aff8 [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
Christophe Leroyde9df392018-08-21 21:57:22 -070021static const char * const test_data_1[] __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
Christophe Leroyde9df392018-08-21 21:57:22 -070035static const char * const test_data_2_be[] __initconst = {
36 "be32", "db7b", "0a18", "93b2",
37 "70ba", "c424", "7d83", "349b",
38 "a69c", "31ad", "9c0f", "ace9",
39 "4cd1", "1999", "43b1", "af0c",
40};
41
Geert Uytterhoeven79e23d52015-06-25 15:02:11 -070042static const char * const test_data_4_le[] __initconst = {
Andy Shevchenko64d1d772015-02-12 15:02:21 -080043 "7bdb32be", "b293180a", "24c4ba70", "9b34837d",
44 "ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143",
45};
46
Christophe Leroyde9df392018-08-21 21:57:22 -070047static const char * const test_data_4_be[] __initconst = {
48 "be32db7b", "0a1893b2", "70bac424", "7d83349b",
49 "a69c31ad", "9c0face9", "4cd11999", "43b1af0c",
50};
51
Geert Uytterhoeven79e23d52015-06-25 15:02:11 -070052static const char * const test_data_8_le[] __initconst = {
Andy Shevchenko64d1d772015-02-12 15:02:21 -080053 "b293180a7bdb32be", "9b34837d24c4ba70",
54 "e9ac0f9cad319ca6", "0cafb1439919d14c",
55};
56
Christophe Leroyde9df392018-08-21 21:57:22 -070057static const char * const test_data_8_be[] __initconst = {
58 "be32db7b0a1893b2", "70bac4247d83349b",
59 "a69c31ad9c0face9", "4cd1199943b1af0c",
60};
61
Andy Shevchenko3db4a982016-01-20 14:58:50 -080062#define FILL_CHAR '#'
63
Andy Shevchenko7aaf4c32016-01-20 14:59:07 -080064static unsigned total_tests __initdata;
65static unsigned failed_tests __initdata;
66
Andy Shevchenko87977ca6b2016-01-20 14:58:47 -080067static void __init test_hexdump_prepare_test(size_t len, int rowsize,
68 int groupsize, char *test,
69 size_t testlen, bool ascii)
Andy Shevchenko64d1d772015-02-12 15:02:21 -080070{
Andy Shevchenko64d1d772015-02-12 15:02:21 -080071 char *p;
Linus Torvalds17974c052015-04-19 13:48:40 -070072 const char * const *result;
Andy Shevchenko64d1d772015-02-12 15:02:21 -080073 size_t l = len;
74 int gs = groupsize, rs = rowsize;
75 unsigned int i;
Christophe Leroyde9df392018-08-21 21:57:22 -070076 const bool is_be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN);
Andy Shevchenko64d1d772015-02-12 15:02:21 -080077
Andy Shevchenko64d1d772015-02-12 15:02:21 -080078 if (rs != 16 && rs != 32)
79 rs = 16;
80
81 if (l > rs)
82 l = rs;
83
84 if (!is_power_of_2(gs) || gs > 8 || (len % gs != 0))
85 gs = 1;
86
87 if (gs == 8)
Christophe Leroyde9df392018-08-21 21:57:22 -070088 result = is_be ? test_data_8_be : test_data_8_le;
Andy Shevchenko64d1d772015-02-12 15:02:21 -080089 else if (gs == 4)
Christophe Leroyde9df392018-08-21 21:57:22 -070090 result = is_be ? test_data_4_be : test_data_4_le;
Andy Shevchenko64d1d772015-02-12 15:02:21 -080091 else if (gs == 2)
Christophe Leroyde9df392018-08-21 21:57:22 -070092 result = is_be ? test_data_2_be : test_data_2_le;
Andy Shevchenko64d1d772015-02-12 15:02:21 -080093 else
Christophe Leroyde9df392018-08-21 21:57:22 -070094 result = test_data_1;
Andy Shevchenko64d1d772015-02-12 15:02:21 -080095
Andy Shevchenko64d1d772015-02-12 15:02:21 -080096 /* hex dump */
97 p = test;
98 for (i = 0; i < l / gs; i++) {
99 const char *q = *result++;
100 size_t amount = strlen(q);
101
Linus Torvaldsf2d12a02018-11-30 12:13:15 -0800102 memcpy(p, q, amount);
Andy Shevchenko3db4a982016-01-20 14:58:50 -0800103 p += amount;
104
105 *p++ = ' ';
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800106 }
107 if (i)
108 p--;
109
110 /* ASCII part */
111 if (ascii) {
Andy Shevchenko3db4a982016-01-20 14:58:50 -0800112 do {
113 *p++ = ' ';
114 } while (p < test + rs * 2 + rs / gs + 1);
115
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800116 strncpy(p, data_a, l);
117 p += l;
118 }
119
120 *p = '\0';
Andy Shevchenko87977ca6b2016-01-20 14:58:47 -0800121}
122
123#define TEST_HEXDUMP_BUF_SIZE (32 * 3 + 2 + 32 + 1)
124
125static void __init test_hexdump(size_t len, int rowsize, int groupsize,
126 bool ascii)
127{
128 char test[TEST_HEXDUMP_BUF_SIZE];
129 char real[TEST_HEXDUMP_BUF_SIZE];
130
Andy Shevchenko7aaf4c32016-01-20 14:59:07 -0800131 total_tests++;
132
Andy Shevchenko7047d812016-01-20 14:58:58 -0800133 memset(real, FILL_CHAR, sizeof(real));
Andy Shevchenko87977ca6b2016-01-20 14:58:47 -0800134 hex_dump_to_buffer(data_b, len, rowsize, groupsize, real, sizeof(real),
135 ascii);
136
Andy Shevchenko7047d812016-01-20 14:58:58 -0800137 memset(test, FILL_CHAR, sizeof(test));
Andy Shevchenko87977ca6b2016-01-20 14:58:47 -0800138 test_hexdump_prepare_test(len, rowsize, groupsize, test, sizeof(test),
139 ascii);
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800140
Andy Shevchenko7047d812016-01-20 14:58:58 -0800141 if (memcmp(test, real, TEST_HEXDUMP_BUF_SIZE)) {
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800142 pr_err("Len: %zu row: %d group: %d\n", len, rowsize, groupsize);
143 pr_err("Result: '%s'\n", real);
144 pr_err("Expect: '%s'\n", test);
Andy Shevchenko7aaf4c32016-01-20 14:59:07 -0800145 failed_tests++;
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800146 }
147}
148
149static void __init test_hexdump_set(int rowsize, bool ascii)
150{
151 size_t d = min_t(size_t, sizeof(data_b), rowsize);
152 size_t len = get_random_int() % d + 1;
153
154 test_hexdump(len, rowsize, 4, ascii);
155 test_hexdump(len, rowsize, 2, ascii);
156 test_hexdump(len, rowsize, 8, ascii);
157 test_hexdump(len, rowsize, 1, ascii);
158}
159
Andy Shevchenko1dacd9d2016-01-20 14:59:04 -0800160static void __init test_hexdump_overflow(size_t buflen, size_t len,
161 int rowsize, int groupsize,
162 bool ascii)
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800163{
Andy Shevchenkocc77a712016-01-20 14:59:01 -0800164 char test[TEST_HEXDUMP_BUF_SIZE];
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800165 char buf[TEST_HEXDUMP_BUF_SIZE];
Andy Shevchenkocc77a712016-01-20 14:59:01 -0800166 int rs = rowsize, gs = groupsize;
167 int ae, he, e, f, r;
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800168 bool a;
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800169
Andy Shevchenko7aaf4c32016-01-20 14:59:07 -0800170 total_tests++;
171
Andy Shevchenko3db4a982016-01-20 14:58:50 -0800172 memset(buf, FILL_CHAR, sizeof(buf));
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800173
Andy Shevchenkoad27a752016-01-20 14:58:56 -0800174 r = hex_dump_to_buffer(data_b, len, rs, gs, buf, buflen, ascii);
175
176 /*
177 * Caller must provide the data length multiple of groupsize. The
178 * calculations below are made with that assumption in mind.
179 */
180 ae = rs * 2 /* hex */ + rs / gs /* spaces */ + 1 /* space */ + len /* ascii */;
181 he = (gs * 2 /* hex */ + 1 /* space */) * len / gs - 1 /* no trailing space */;
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800182
183 if (ascii)
Andy Shevchenkoad27a752016-01-20 14:58:56 -0800184 e = ae;
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800185 else
Andy Shevchenkoad27a752016-01-20 14:58:56 -0800186 e = he;
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800187
Andy Shevchenkocc77a712016-01-20 14:59:01 -0800188 f = min_t(int, e + 1, buflen);
189 if (buflen) {
190 test_hexdump_prepare_test(len, rs, gs, test, sizeof(test), ascii);
191 test[f - 1] = '\0';
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800192 }
Andy Shevchenkocc77a712016-01-20 14:59:01 -0800193 memset(test + f, FILL_CHAR, sizeof(test) - f);
194
195 a = r == e && !memcmp(test, buf, TEST_HEXDUMP_BUF_SIZE);
196
197 buf[sizeof(buf) - 1] = '\0';
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800198
199 if (!a) {
Andy Shevchenkocc77a712016-01-20 14:59:01 -0800200 pr_err("Len: %zu buflen: %zu strlen: %zu\n",
201 len, buflen, strnlen(buf, sizeof(buf)));
202 pr_err("Result: %d '%s'\n", r, buf);
203 pr_err("Expect: %d '%s'\n", e, test);
Andy Shevchenko7aaf4c32016-01-20 14:59:07 -0800204 failed_tests++;
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800205 }
206}
207
Andy Shevchenko1dacd9d2016-01-20 14:59:04 -0800208static void __init test_hexdump_overflow_set(size_t buflen, bool ascii)
209{
210 unsigned int i = 0;
211 int rs = (get_random_int() % 2 + 1) * 16;
212
213 do {
214 int gs = 1 << i;
215 size_t len = get_random_int() % rs + gs;
216
217 test_hexdump_overflow(buflen, rounddown(len, gs), rs, gs, ascii);
218 } while (i++ < 3);
219}
220
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800221static int __init test_hexdump_init(void)
222{
223 unsigned int i;
224 int rowsize;
225
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800226 rowsize = (get_random_int() % 2 + 1) * 16;
227 for (i = 0; i < 16; i++)
228 test_hexdump_set(rowsize, false);
229
230 rowsize = (get_random_int() % 2 + 1) * 16;
231 for (i = 0; i < 16; i++)
232 test_hexdump_set(rowsize, true);
233
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800234 for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++)
Andy Shevchenko1dacd9d2016-01-20 14:59:04 -0800235 test_hexdump_overflow_set(i, false);
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800236
Andy Shevchenkoa3d601f2016-01-20 14:58:53 -0800237 for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++)
Andy Shevchenko1dacd9d2016-01-20 14:59:04 -0800238 test_hexdump_overflow_set(i, true);
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800239
Andy Shevchenko7aaf4c32016-01-20 14:59:07 -0800240 if (failed_tests == 0)
241 pr_info("all %u tests passed\n", total_tests);
242 else
243 pr_err("failed %u out of %u tests\n", failed_tests, total_tests);
244
245 return failed_tests ? -EINVAL : 0;
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800246}
247module_init(test_hexdump_init);
Andy Shevchenko7aaf4c32016-01-20 14:59:07 -0800248
249static void __exit test_hexdump_exit(void)
250{
251 /* do nothing */
252}
253module_exit(test_hexdump_exit);
254
255MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800256MODULE_LICENSE("Dual BSD/GPL");