1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | #include <linux/module.h> |
3 | #include <linux/printk.h> |
4 | #include <linux/slab.h> |
5 | #include <linux/string.h> |
6 | |
7 | static __init int memset16_selftest(void) |
8 | { |
9 | unsigned i, j, k; |
10 | u16 v, *p; |
11 | |
12 | p = kmalloc(size: 256 * 2 * 2, GFP_KERNEL); |
13 | if (!p) |
14 | return -1; |
15 | |
16 | for (i = 0; i < 256; i++) { |
17 | for (j = 0; j < 256; j++) { |
18 | memset(p, 0xa1, 256 * 2 * sizeof(v)); |
19 | memset16(s: p + i, v: 0xb1b2, n: j); |
20 | for (k = 0; k < 512; k++) { |
21 | v = p[k]; |
22 | if (k < i) { |
23 | if (v != 0xa1a1) |
24 | goto fail; |
25 | } else if (k < i + j) { |
26 | if (v != 0xb1b2) |
27 | goto fail; |
28 | } else { |
29 | if (v != 0xa1a1) |
30 | goto fail; |
31 | } |
32 | } |
33 | } |
34 | } |
35 | |
36 | fail: |
37 | kfree(objp: p); |
38 | if (i < 256) |
39 | return (i << 24) | (j << 16) | k | 0x8000; |
40 | return 0; |
41 | } |
42 | |
43 | static __init int memset32_selftest(void) |
44 | { |
45 | unsigned i, j, k; |
46 | u32 v, *p; |
47 | |
48 | p = kmalloc(size: 256 * 2 * 4, GFP_KERNEL); |
49 | if (!p) |
50 | return -1; |
51 | |
52 | for (i = 0; i < 256; i++) { |
53 | for (j = 0; j < 256; j++) { |
54 | memset(p, 0xa1, 256 * 2 * sizeof(v)); |
55 | memset32(s: p + i, v: 0xb1b2b3b4, n: j); |
56 | for (k = 0; k < 512; k++) { |
57 | v = p[k]; |
58 | if (k < i) { |
59 | if (v != 0xa1a1a1a1) |
60 | goto fail; |
61 | } else if (k < i + j) { |
62 | if (v != 0xb1b2b3b4) |
63 | goto fail; |
64 | } else { |
65 | if (v != 0xa1a1a1a1) |
66 | goto fail; |
67 | } |
68 | } |
69 | } |
70 | } |
71 | |
72 | fail: |
73 | kfree(objp: p); |
74 | if (i < 256) |
75 | return (i << 24) | (j << 16) | k | 0x8000; |
76 | return 0; |
77 | } |
78 | |
79 | static __init int memset64_selftest(void) |
80 | { |
81 | unsigned i, j, k; |
82 | u64 v, *p; |
83 | |
84 | p = kmalloc(size: 256 * 2 * 8, GFP_KERNEL); |
85 | if (!p) |
86 | return -1; |
87 | |
88 | for (i = 0; i < 256; i++) { |
89 | for (j = 0; j < 256; j++) { |
90 | memset(p, 0xa1, 256 * 2 * sizeof(v)); |
91 | memset64(s: p + i, v: 0xb1b2b3b4b5b6b7b8ULL, n: j); |
92 | for (k = 0; k < 512; k++) { |
93 | v = p[k]; |
94 | if (k < i) { |
95 | if (v != 0xa1a1a1a1a1a1a1a1ULL) |
96 | goto fail; |
97 | } else if (k < i + j) { |
98 | if (v != 0xb1b2b3b4b5b6b7b8ULL) |
99 | goto fail; |
100 | } else { |
101 | if (v != 0xa1a1a1a1a1a1a1a1ULL) |
102 | goto fail; |
103 | } |
104 | } |
105 | } |
106 | } |
107 | |
108 | fail: |
109 | kfree(objp: p); |
110 | if (i < 256) |
111 | return (i << 24) | (j << 16) | k | 0x8000; |
112 | return 0; |
113 | } |
114 | |
115 | static __init int strchr_selftest(void) |
116 | { |
117 | const char *test_string = "abcdefghijkl" ; |
118 | const char *empty_string = "" ; |
119 | char *result; |
120 | int i; |
121 | |
122 | for (i = 0; i < strlen(test_string) + 1; i++) { |
123 | result = strchr(test_string, test_string[i]); |
124 | if (result - test_string != i) |
125 | return i + 'a'; |
126 | } |
127 | |
128 | result = strchr(empty_string, '\0'); |
129 | if (result != empty_string) |
130 | return 0x101; |
131 | |
132 | result = strchr(empty_string, 'a'); |
133 | if (result) |
134 | return 0x102; |
135 | |
136 | result = strchr(test_string, 'z'); |
137 | if (result) |
138 | return 0x103; |
139 | |
140 | return 0; |
141 | } |
142 | |
143 | static __init int strnchr_selftest(void) |
144 | { |
145 | const char *test_string = "abcdefghijkl" ; |
146 | const char *empty_string = "" ; |
147 | char *result; |
148 | int i, j; |
149 | |
150 | for (i = 0; i < strlen(test_string) + 1; i++) { |
151 | for (j = 0; j < strlen(test_string) + 2; j++) { |
152 | result = strnchr(test_string, j, test_string[i]); |
153 | if (j <= i) { |
154 | if (!result) |
155 | continue; |
156 | return ((i + 'a') << 8) | j; |
157 | } |
158 | if (result - test_string != i) |
159 | return ((i + 'a') << 8) | j; |
160 | } |
161 | } |
162 | |
163 | result = strnchr(empty_string, 0, '\0'); |
164 | if (result) |
165 | return 0x10001; |
166 | |
167 | result = strnchr(empty_string, 1, '\0'); |
168 | if (result != empty_string) |
169 | return 0x10002; |
170 | |
171 | result = strnchr(empty_string, 1, 'a'); |
172 | if (result) |
173 | return 0x10003; |
174 | |
175 | result = strnchr(NULL, 0, '\0'); |
176 | if (result) |
177 | return 0x10004; |
178 | |
179 | return 0; |
180 | } |
181 | |
182 | static __init int strspn_selftest(void) |
183 | { |
184 | static const struct strspn_test { |
185 | const char str[16]; |
186 | const char accept[16]; |
187 | const char reject[16]; |
188 | unsigned a; |
189 | unsigned r; |
190 | } tests[] __initconst = { |
191 | { "foobar" , "" , "" , 0, 6 }, |
192 | { "abba" , "abc" , "ABBA" , 4, 4 }, |
193 | { "abba" , "a" , "b" , 1, 1 }, |
194 | { "" , "abc" , "abc" , 0, 0}, |
195 | }; |
196 | const struct strspn_test *s = tests; |
197 | size_t i, res; |
198 | |
199 | for (i = 0; i < ARRAY_SIZE(tests); ++i, ++s) { |
200 | res = strspn(s->str, s->accept); |
201 | if (res != s->a) |
202 | return 0x100 + 2*i; |
203 | res = strcspn(s->str, s->reject); |
204 | if (res != s->r) |
205 | return 0x100 + 2*i + 1; |
206 | } |
207 | return 0; |
208 | } |
209 | |
210 | static __exit void string_selftest_remove(void) |
211 | { |
212 | } |
213 | |
214 | static __init int string_selftest_init(void) |
215 | { |
216 | int test, subtest; |
217 | |
218 | test = 1; |
219 | subtest = memset16_selftest(); |
220 | if (subtest) |
221 | goto fail; |
222 | |
223 | test = 2; |
224 | subtest = memset32_selftest(); |
225 | if (subtest) |
226 | goto fail; |
227 | |
228 | test = 3; |
229 | subtest = memset64_selftest(); |
230 | if (subtest) |
231 | goto fail; |
232 | |
233 | test = 4; |
234 | subtest = strchr_selftest(); |
235 | if (subtest) |
236 | goto fail; |
237 | |
238 | test = 5; |
239 | subtest = strnchr_selftest(); |
240 | if (subtest) |
241 | goto fail; |
242 | |
243 | test = 6; |
244 | subtest = strspn_selftest(); |
245 | if (subtest) |
246 | goto fail; |
247 | |
248 | pr_info("String selftests succeeded\n" ); |
249 | return 0; |
250 | fail: |
251 | pr_crit("String selftest failure %d.%08x\n" , test, subtest); |
252 | return 0; |
253 | } |
254 | |
255 | module_init(string_selftest_init); |
256 | module_exit(string_selftest_remove); |
257 | MODULE_LICENSE("GPL v2" ); |
258 | |