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