proc: faster /proc/cmdline
[linux-2.6-block.git] / lib / test_hexdump.c
CommitLineData
64d1d77a
AS
1/*
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
c79574ab 21static const char * const test_data_1_le[] __initconst = {
64d1d77a
AS
22 "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
79e23d57 28static const char * const test_data_2_le[] __initconst = {
64d1d77a
AS
29 "32be", "7bdb", "180a", "b293",
30 "ba70", "24c4", "837d", "9b34",
31 "9ca6", "ad31", "0f9c", "e9ac",
32 "d14c", "9919", "b143", "0caf",
33};
34
79e23d57 35static const char * const test_data_4_le[] __initconst = {
64d1d77a
AS
36 "7bdb32be", "b293180a", "24c4ba70", "9b34837d",
37 "ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143",
38};
39
79e23d57 40static const char * const test_data_8_le[] __initconst = {
64d1d77a
AS
41 "b293180a7bdb32be", "9b34837d24c4ba70",
42 "e9ac0f9cad319ca6", "0cafb1439919d14c",
43};
44
3db4a987
AS
45#define FILL_CHAR '#'
46
7aaf4c3e
AS
47static unsigned total_tests __initdata;
48static unsigned failed_tests __initdata;
49
87977ca6
AS
50static void __init test_hexdump_prepare_test(size_t len, int rowsize,
51 int groupsize, char *test,
52 size_t testlen, bool ascii)
64d1d77a 53{
64d1d77a 54 char *p;
17974c05 55 const char * const *result;
64d1d77a
AS
56 size_t l = len;
57 int gs = groupsize, rs = rowsize;
58 unsigned int i;
59
64d1d77a
AS
60 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
64d1d77a
AS
78 /* 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);
3db4a987
AS
85 p += amount;
86
87 *p++ = ' ';
64d1d77a
AS
88 }
89 if (i)
90 p--;
91
92 /* ASCII part */
93 if (ascii) {
3db4a987
AS
94 do {
95 *p++ = ' ';
96 } while (p < test + rs * 2 + rs / gs + 1);
97
64d1d77a
AS
98 strncpy(p, data_a, l);
99 p += l;
100 }
101
102 *p = '\0';
87977ca6
AS
103}
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
7aaf4c3e
AS
113 total_tests++;
114
7047d813 115 memset(real, FILL_CHAR, sizeof(real));
87977ca6
AS
116 hex_dump_to_buffer(data_b, len, rowsize, groupsize, real, sizeof(real),
117 ascii);
118
7047d813 119 memset(test, FILL_CHAR, sizeof(test));
87977ca6
AS
120 test_hexdump_prepare_test(len, rowsize, groupsize, test, sizeof(test),
121 ascii);
64d1d77a 122
7047d813 123 if (memcmp(test, real, TEST_HEXDUMP_BUF_SIZE)) {
64d1d77a
AS
124 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);
7aaf4c3e 127 failed_tests++;
64d1d77a
AS
128 }
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
1dacd9dd
AS
142static void __init test_hexdump_overflow(size_t buflen, size_t len,
143 int rowsize, int groupsize,
144 bool ascii)
114fc1af 145{
cc77a719 146 char test[TEST_HEXDUMP_BUF_SIZE];
a3d601fc 147 char buf[TEST_HEXDUMP_BUF_SIZE];
cc77a719
AS
148 int rs = rowsize, gs = groupsize;
149 int ae, he, e, f, r;
114fc1af 150 bool a;
114fc1af 151
7aaf4c3e
AS
152 total_tests++;
153
3db4a987 154 memset(buf, FILL_CHAR, sizeof(buf));
114fc1af 155
ad27a755
AS
156 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 */;
114fc1af
AS
164
165 if (ascii)
ad27a755 166 e = ae;
114fc1af 167 else
ad27a755 168 e = he;
cc77a719
AS
169
170 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';
114fc1af 174 }
cc77a719
AS
175 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';
114fc1af
AS
180
181 if (!a) {
cc77a719
AS
182 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);
7aaf4c3e 186 failed_tests++;
114fc1af
AS
187 }
188}
189
1dacd9dd
AS
190static 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
64d1d77a
AS
203static int __init test_hexdump_init(void)
204{
205 unsigned int i;
206 int rowsize;
207
64d1d77a
AS
208 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
a3d601fc 216 for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++)
1dacd9dd 217 test_hexdump_overflow_set(i, false);
114fc1af 218
a3d601fc 219 for (i = 0; i <= TEST_HEXDUMP_BUF_SIZE; i++)
1dacd9dd 220 test_hexdump_overflow_set(i, true);
114fc1af 221
7aaf4c3e
AS
222 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;
64d1d77a
AS
228}
229module_init(test_hexdump_init);
7aaf4c3e
AS
230
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>");
64d1d77a 238MODULE_LICENSE("Dual BSD/GPL");