blob: ed7c6a704f3486956c4699abf3095bf8d53de326 [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 Shevchenko87977ca6b2016-01-20 14:58:47 -080045static void __init test_hexdump_prepare_test(size_t len, int rowsize,
46 int groupsize, char *test,
47 size_t testlen, bool ascii)
Andy Shevchenko64d1d772015-02-12 15:02:21 -080048{
Andy Shevchenko64d1d772015-02-12 15:02:21 -080049 char *p;
Linus Torvalds17974c052015-04-19 13:48:40 -070050 const char * const *result;
Andy Shevchenko64d1d772015-02-12 15:02:21 -080051 size_t l = len;
52 int gs = groupsize, rs = rowsize;
53 unsigned int i;
54
Andy Shevchenko64d1d772015-02-12 15:02:21 -080055 if (rs != 16 && rs != 32)
56 rs = 16;
57
58 if (l > rs)
59 l = rs;
60
61 if (!is_power_of_2(gs) || gs > 8 || (len % gs != 0))
62 gs = 1;
63
64 if (gs == 8)
65 result = test_data_8_le;
66 else if (gs == 4)
67 result = test_data_4_le;
68 else if (gs == 2)
69 result = test_data_2_le;
70 else
71 result = test_data_1_le;
72
Andy Shevchenko87977ca6b2016-01-20 14:58:47 -080073 memset(test, ' ', testlen);
Andy Shevchenko64d1d772015-02-12 15:02:21 -080074
75 /* hex dump */
76 p = test;
77 for (i = 0; i < l / gs; i++) {
78 const char *q = *result++;
79 size_t amount = strlen(q);
80
81 strncpy(p, q, amount);
82 p += amount + 1;
83 }
84 if (i)
85 p--;
86
87 /* ASCII part */
88 if (ascii) {
89 p = test + rs * 2 + rs / gs + 1;
90 strncpy(p, data_a, l);
91 p += l;
92 }
93
94 *p = '\0';
Andy Shevchenko87977ca6b2016-01-20 14:58:47 -080095}
96
97#define TEST_HEXDUMP_BUF_SIZE (32 * 3 + 2 + 32 + 1)
98
99static void __init test_hexdump(size_t len, int rowsize, int groupsize,
100 bool ascii)
101{
102 char test[TEST_HEXDUMP_BUF_SIZE];
103 char real[TEST_HEXDUMP_BUF_SIZE];
104
105 hex_dump_to_buffer(data_b, len, rowsize, groupsize, real, sizeof(real),
106 ascii);
107
108 test_hexdump_prepare_test(len, rowsize, groupsize, test, sizeof(test),
109 ascii);
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800110
111 if (strcmp(test, real)) {
112 pr_err("Len: %zu row: %d group: %d\n", len, rowsize, groupsize);
113 pr_err("Result: '%s'\n", real);
114 pr_err("Expect: '%s'\n", test);
115 }
116}
117
118static void __init test_hexdump_set(int rowsize, bool ascii)
119{
120 size_t d = min_t(size_t, sizeof(data_b), rowsize);
121 size_t len = get_random_int() % d + 1;
122
123 test_hexdump(len, rowsize, 4, ascii);
124 test_hexdump(len, rowsize, 2, ascii);
125 test_hexdump(len, rowsize, 8, ascii);
126 test_hexdump(len, rowsize, 1, ascii);
127}
128
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800129static void __init test_hexdump_overflow(bool ascii)
130{
131 char buf[56];
132 const char *t = test_data_1_le[0];
133 size_t l = get_random_int() % sizeof(buf);
134 bool a;
135 int e, r;
136
137 memset(buf, ' ', sizeof(buf));
138
139 r = hex_dump_to_buffer(data_b, 1, 16, 1, buf, l, ascii);
140
141 if (ascii)
142 e = 50;
143 else
144 e = 2;
145 buf[e + 2] = '\0';
146
147 if (!l) {
148 a = r == e && buf[0] == ' ';
149 } else if (l < 3) {
150 a = r == e && buf[0] == '\0';
151 } else if (l < 4) {
152 a = r == e && !strcmp(buf, t);
153 } else if (ascii) {
154 if (l < 51)
155 a = r == e && buf[l - 1] == '\0' && buf[l - 2] == ' ';
156 else
157 a = r == e && buf[50] == '\0' && buf[49] == '.';
158 } else {
159 a = r == e && buf[e] == '\0';
160 }
161
162 if (!a) {
163 pr_err("Len: %zu rc: %u strlen: %zu\n", l, r, strlen(buf));
164 pr_err("Result: '%s'\n", buf);
165 }
166}
167
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800168static int __init test_hexdump_init(void)
169{
170 unsigned int i;
171 int rowsize;
172
173 pr_info("Running tests...\n");
174
175 rowsize = (get_random_int() % 2 + 1) * 16;
176 for (i = 0; i < 16; i++)
177 test_hexdump_set(rowsize, false);
178
179 rowsize = (get_random_int() % 2 + 1) * 16;
180 for (i = 0; i < 16; i++)
181 test_hexdump_set(rowsize, true);
182
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800183 for (i = 0; i < 16; i++)
184 test_hexdump_overflow(false);
185
186 for (i = 0; i < 16; i++)
187 test_hexdump_overflow(true);
188
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800189 return -EINVAL;
190}
191module_init(test_hexdump_init);
192MODULE_LICENSE("Dual BSD/GPL");