blob: 5241df36eedf922b19adc9429225ed006b6b851d [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
45static void __init test_hexdump(size_t len, int rowsize, int groupsize,
46 bool ascii)
47{
48 char test[32 * 3 + 2 + 32 + 1];
49 char real[32 * 3 + 2 + 32 + 1];
50 char *p;
Linus Torvalds17974c052015-04-19 13:48:40 -070051 const char * const *result;
Andy Shevchenko64d1d772015-02-12 15:02:21 -080052 size_t l = len;
53 int gs = groupsize, rs = rowsize;
54 unsigned int i;
55
56 hex_dump_to_buffer(data_b, l, rs, gs, real, sizeof(real), ascii);
57
58 if (rs != 16 && rs != 32)
59 rs = 16;
60
61 if (l > rs)
62 l = rs;
63
64 if (!is_power_of_2(gs) || gs > 8 || (len % gs != 0))
65 gs = 1;
66
67 if (gs == 8)
68 result = test_data_8_le;
69 else if (gs == 4)
70 result = test_data_4_le;
71 else if (gs == 2)
72 result = test_data_2_le;
73 else
74 result = test_data_1_le;
75
76 memset(test, ' ', sizeof(test));
77
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);
85 p += amount + 1;
86 }
87 if (i)
88 p--;
89
90 /* ASCII part */
91 if (ascii) {
92 p = test + rs * 2 + rs / gs + 1;
93 strncpy(p, data_a, l);
94 p += l;
95 }
96
97 *p = '\0';
98
99 if (strcmp(test, real)) {
100 pr_err("Len: %zu row: %d group: %d\n", len, rowsize, groupsize);
101 pr_err("Result: '%s'\n", real);
102 pr_err("Expect: '%s'\n", test);
103 }
104}
105
106static void __init test_hexdump_set(int rowsize, bool ascii)
107{
108 size_t d = min_t(size_t, sizeof(data_b), rowsize);
109 size_t len = get_random_int() % d + 1;
110
111 test_hexdump(len, rowsize, 4, ascii);
112 test_hexdump(len, rowsize, 2, ascii);
113 test_hexdump(len, rowsize, 8, ascii);
114 test_hexdump(len, rowsize, 1, ascii);
115}
116
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800117static void __init test_hexdump_overflow(bool ascii)
118{
119 char buf[56];
120 const char *t = test_data_1_le[0];
121 size_t l = get_random_int() % sizeof(buf);
122 bool a;
123 int e, r;
124
125 memset(buf, ' ', sizeof(buf));
126
127 r = hex_dump_to_buffer(data_b, 1, 16, 1, buf, l, ascii);
128
129 if (ascii)
130 e = 50;
131 else
132 e = 2;
133 buf[e + 2] = '\0';
134
135 if (!l) {
136 a = r == e && buf[0] == ' ';
137 } else if (l < 3) {
138 a = r == e && buf[0] == '\0';
139 } else if (l < 4) {
140 a = r == e && !strcmp(buf, t);
141 } else if (ascii) {
142 if (l < 51)
143 a = r == e && buf[l - 1] == '\0' && buf[l - 2] == ' ';
144 else
145 a = r == e && buf[50] == '\0' && buf[49] == '.';
146 } else {
147 a = r == e && buf[e] == '\0';
148 }
149
150 if (!a) {
151 pr_err("Len: %zu rc: %u strlen: %zu\n", l, r, strlen(buf));
152 pr_err("Result: '%s'\n", buf);
153 }
154}
155
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800156static int __init test_hexdump_init(void)
157{
158 unsigned int i;
159 int rowsize;
160
161 pr_info("Running tests...\n");
162
163 rowsize = (get_random_int() % 2 + 1) * 16;
164 for (i = 0; i < 16; i++)
165 test_hexdump_set(rowsize, false);
166
167 rowsize = (get_random_int() % 2 + 1) * 16;
168 for (i = 0; i < 16; i++)
169 test_hexdump_set(rowsize, true);
170
Andy Shevchenko114fc1a2015-02-12 15:02:29 -0800171 for (i = 0; i < 16; i++)
172 test_hexdump_overflow(false);
173
174 for (i = 0; i < 16; i++)
175 test_hexdump_overflow(true);
176
Andy Shevchenko64d1d772015-02-12 15:02:21 -0800177 return -EINVAL;
178}
179module_init(test_hexdump_init);
180MODULE_LICENSE("Dual BSD/GPL");