Loading...
Note: File does not exist in v5.14.15.
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Test cases for string functions.
4 */
5
6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7
8#include <kunit/test.h>
9#include <linux/module.h>
10#include <linux/printk.h>
11#include <linux/slab.h>
12#include <linux/string.h>
13
14#define STRCMP_LARGE_BUF_LEN 2048
15#define STRCMP_CHANGE_POINT 1337
16#define STRCMP_TEST_EXPECT_EQUAL(test, fn, ...) KUNIT_EXPECT_EQ(test, fn(__VA_ARGS__), 0)
17#define STRCMP_TEST_EXPECT_LOWER(test, fn, ...) KUNIT_EXPECT_LT(test, fn(__VA_ARGS__), 0)
18#define STRCMP_TEST_EXPECT_GREATER(test, fn, ...) KUNIT_EXPECT_GT(test, fn(__VA_ARGS__), 0)
19
20static void test_memset16(struct kunit *test)
21{
22 unsigned i, j, k;
23 u16 v, *p;
24
25 p = kunit_kzalloc(test, 256 * 2 * 2, GFP_KERNEL);
26 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, p);
27
28 for (i = 0; i < 256; i++) {
29 for (j = 0; j < 256; j++) {
30 memset(p, 0xa1, 256 * 2 * sizeof(v));
31 memset16(p + i, 0xb1b2, j);
32 for (k = 0; k < 512; k++) {
33 v = p[k];
34 if (k < i) {
35 KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1,
36 "i:%d j:%d k:%d", i, j, k);
37 } else if (k < i + j) {
38 KUNIT_ASSERT_EQ_MSG(test, v, 0xb1b2,
39 "i:%d j:%d k:%d", i, j, k);
40 } else {
41 KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1,
42 "i:%d j:%d k:%d", i, j, k);
43 }
44 }
45 }
46 }
47}
48
49static void test_memset32(struct kunit *test)
50{
51 unsigned i, j, k;
52 u32 v, *p;
53
54 p = kunit_kzalloc(test, 256 * 2 * 4, GFP_KERNEL);
55 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, p);
56
57 for (i = 0; i < 256; i++) {
58 for (j = 0; j < 256; j++) {
59 memset(p, 0xa1, 256 * 2 * sizeof(v));
60 memset32(p + i, 0xb1b2b3b4, j);
61 for (k = 0; k < 512; k++) {
62 v = p[k];
63 if (k < i) {
64 KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1a1a1,
65 "i:%d j:%d k:%d", i, j, k);
66 } else if (k < i + j) {
67 KUNIT_ASSERT_EQ_MSG(test, v, 0xb1b2b3b4,
68 "i:%d j:%d k:%d", i, j, k);
69 } else {
70 KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1a1a1,
71 "i:%d j:%d k:%d", i, j, k);
72 }
73 }
74 }
75 }
76}
77
78static void test_memset64(struct kunit *test)
79{
80 unsigned i, j, k;
81 u64 v, *p;
82
83 p = kunit_kzalloc(test, 256 * 2 * 8, GFP_KERNEL);
84 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, p);
85
86 for (i = 0; i < 256; i++) {
87 for (j = 0; j < 256; j++) {
88 memset(p, 0xa1, 256 * 2 * sizeof(v));
89 memset64(p + i, 0xb1b2b3b4b5b6b7b8ULL, j);
90 for (k = 0; k < 512; k++) {
91 v = p[k];
92 if (k < i) {
93 KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1a1a1a1a1a1a1ULL,
94 "i:%d j:%d k:%d", i, j, k);
95 } else if (k < i + j) {
96 KUNIT_ASSERT_EQ_MSG(test, v, 0xb1b2b3b4b5b6b7b8ULL,
97 "i:%d j:%d k:%d", i, j, k);
98 } else {
99 KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1a1a1a1a1a1a1ULL,
100 "i:%d j:%d k:%d", i, j, k);
101 }
102 }
103 }
104 }
105}
106
107static void test_strchr(struct kunit *test)
108{
109 const char *test_string = "abcdefghijkl";
110 const char *empty_string = "";
111 char *result;
112 int i;
113
114 for (i = 0; i < strlen(test_string) + 1; i++) {
115 result = strchr(test_string, test_string[i]);
116 KUNIT_ASSERT_EQ_MSG(test, result - test_string, i,
117 "char:%c", 'a' + i);
118 }
119
120 result = strchr(empty_string, '\0');
121 KUNIT_ASSERT_PTR_EQ(test, result, empty_string);
122
123 result = strchr(empty_string, 'a');
124 KUNIT_ASSERT_NULL(test, result);
125
126 result = strchr(test_string, 'z');
127 KUNIT_ASSERT_NULL(test, result);
128}
129
130static void test_strnchr(struct kunit *test)
131{
132 const char *test_string = "abcdefghijkl";
133 const char *empty_string = "";
134 char *result;
135 int i, j;
136
137 for (i = 0; i < strlen(test_string) + 1; i++) {
138 for (j = 0; j < strlen(test_string) + 2; j++) {
139 result = strnchr(test_string, j, test_string[i]);
140 if (j <= i) {
141 KUNIT_ASSERT_NULL_MSG(test, result,
142 "char:%c i:%d j:%d", 'a' + i, i, j);
143 } else {
144 KUNIT_ASSERT_EQ_MSG(test, result - test_string, i,
145 "char:%c i:%d j:%d", 'a' + i, i, j);
146 }
147 }
148 }
149
150 result = strnchr(empty_string, 0, '\0');
151 KUNIT_ASSERT_NULL(test, result);
152
153 result = strnchr(empty_string, 1, '\0');
154 KUNIT_ASSERT_PTR_EQ(test, result, empty_string);
155
156 result = strnchr(empty_string, 1, 'a');
157 KUNIT_ASSERT_NULL(test, result);
158
159 result = strnchr(NULL, 0, '\0');
160 KUNIT_ASSERT_NULL(test, result);
161}
162
163static void test_strspn(struct kunit *test)
164{
165 static const struct strspn_test {
166 const char str[16];
167 const char accept[16];
168 const char reject[16];
169 unsigned a;
170 unsigned r;
171 } tests[] = {
172 { "foobar", "", "", 0, 6 },
173 { "abba", "abc", "ABBA", 4, 4 },
174 { "abba", "a", "b", 1, 1 },
175 { "", "abc", "abc", 0, 0},
176 };
177 const struct strspn_test *s = tests;
178 size_t i;
179
180 for (i = 0; i < ARRAY_SIZE(tests); ++i, ++s) {
181 KUNIT_ASSERT_EQ_MSG(test, s->a, strspn(s->str, s->accept),
182 "i:%zu", i);
183 KUNIT_ASSERT_EQ_MSG(test, s->r, strcspn(s->str, s->reject),
184 "i:%zu", i);
185 }
186}
187
188static char strcmp_buffer1[STRCMP_LARGE_BUF_LEN];
189static char strcmp_buffer2[STRCMP_LARGE_BUF_LEN];
190
191static void strcmp_fill_buffers(char fill1, char fill2)
192{
193 memset(strcmp_buffer1, fill1, STRCMP_LARGE_BUF_LEN);
194 memset(strcmp_buffer2, fill2, STRCMP_LARGE_BUF_LEN);
195 strcmp_buffer1[STRCMP_LARGE_BUF_LEN - 1] = 0;
196 strcmp_buffer2[STRCMP_LARGE_BUF_LEN - 1] = 0;
197}
198
199static void test_strcmp(struct kunit *test)
200{
201 /* Equal strings */
202 STRCMP_TEST_EXPECT_EQUAL(test, strcmp, "Hello, Kernel!", "Hello, Kernel!");
203 /* First string is lexicographically less than the second */
204 STRCMP_TEST_EXPECT_LOWER(test, strcmp, "Hello, KUnit!", "Hello, Kernel!");
205 /* First string is lexicographically larger than the second */
206 STRCMP_TEST_EXPECT_GREATER(test, strcmp, "Hello, Kernel!", "Hello, KUnit!");
207 /* Empty string is always lexicographically less than any non-empty string */
208 STRCMP_TEST_EXPECT_LOWER(test, strcmp, "", "Non-empty string");
209 /* Two empty strings should be equal */
210 STRCMP_TEST_EXPECT_EQUAL(test, strcmp, "", "");
211 /* Compare two strings which have only one char difference */
212 STRCMP_TEST_EXPECT_LOWER(test, strcmp, "Abacaba", "Abadaba");
213 /* Compare two strings which have the same prefix*/
214 STRCMP_TEST_EXPECT_LOWER(test, strcmp, "Just a string", "Just a string and something else");
215}
216
217static void test_strcmp_long_strings(struct kunit *test)
218{
219 strcmp_fill_buffers('B', 'B');
220 STRCMP_TEST_EXPECT_EQUAL(test, strcmp, strcmp_buffer1, strcmp_buffer2);
221
222 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'A';
223 STRCMP_TEST_EXPECT_LOWER(test, strcmp, strcmp_buffer1, strcmp_buffer2);
224
225 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'C';
226 STRCMP_TEST_EXPECT_GREATER(test, strcmp, strcmp_buffer1, strcmp_buffer2);
227}
228
229static void test_strncmp(struct kunit *test)
230{
231 /* Equal strings */
232 STRCMP_TEST_EXPECT_EQUAL(test, strncmp, "Hello, KUnit!", "Hello, KUnit!", 13);
233 /* First string is lexicographically less than the second */
234 STRCMP_TEST_EXPECT_LOWER(test, strncmp, "Hello, KUnit!", "Hello, Kernel!", 13);
235 /* Result is always 'equal' when count = 0 */
236 STRCMP_TEST_EXPECT_EQUAL(test, strncmp, "Hello, Kernel!", "Hello, KUnit!", 0);
237 /* Strings with common prefix are equal if count = length of prefix */
238 STRCMP_TEST_EXPECT_EQUAL(test, strncmp, "Abacaba", "Abadaba", 3);
239 /* Strings with common prefix are not equal when count = length of prefix + 1 */
240 STRCMP_TEST_EXPECT_LOWER(test, strncmp, "Abacaba", "Abadaba", 4);
241 /* If one string is a prefix of another, the shorter string is lexicographically smaller */
242 STRCMP_TEST_EXPECT_LOWER(test, strncmp, "Just a string", "Just a string and something else",
243 strlen("Just a string and something else"));
244 /*
245 * If one string is a prefix of another, and we check first length
246 * of prefix chars, the result is 'equal'
247 */
248 STRCMP_TEST_EXPECT_EQUAL(test, strncmp, "Just a string", "Just a string and something else",
249 strlen("Just a string"));
250}
251
252static void test_strncmp_long_strings(struct kunit *test)
253{
254 strcmp_fill_buffers('B', 'B');
255 STRCMP_TEST_EXPECT_EQUAL(test, strncmp, strcmp_buffer1,
256 strcmp_buffer2, STRCMP_LARGE_BUF_LEN);
257
258 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'A';
259 STRCMP_TEST_EXPECT_LOWER(test, strncmp, strcmp_buffer1,
260 strcmp_buffer2, STRCMP_LARGE_BUF_LEN);
261
262 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'C';
263 STRCMP_TEST_EXPECT_GREATER(test, strncmp, strcmp_buffer1,
264 strcmp_buffer2, STRCMP_LARGE_BUF_LEN);
265 /* the strings are equal up to STRCMP_CHANGE_POINT */
266 STRCMP_TEST_EXPECT_EQUAL(test, strncmp, strcmp_buffer1,
267 strcmp_buffer2, STRCMP_CHANGE_POINT);
268 STRCMP_TEST_EXPECT_GREATER(test, strncmp, strcmp_buffer1,
269 strcmp_buffer2, STRCMP_CHANGE_POINT + 1);
270}
271
272static void test_strcasecmp(struct kunit *test)
273{
274 /* Same strings in different case should be equal */
275 STRCMP_TEST_EXPECT_EQUAL(test, strcasecmp, "Hello, Kernel!", "HeLLO, KErNeL!");
276 /* Empty strings should be equal */
277 STRCMP_TEST_EXPECT_EQUAL(test, strcasecmp, "", "");
278 /* Despite ascii code for 'a' is larger than ascii code for 'B', 'a' < 'B' */
279 STRCMP_TEST_EXPECT_LOWER(test, strcasecmp, "a", "B");
280 STRCMP_TEST_EXPECT_GREATER(test, strcasecmp, "B", "a");
281 /* Special symbols and numbers should be processed correctly */
282 STRCMP_TEST_EXPECT_EQUAL(test, strcasecmp, "-+**.1230ghTTT~^", "-+**.1230Ghttt~^");
283}
284
285static void test_strcasecmp_long_strings(struct kunit *test)
286{
287 strcmp_fill_buffers('b', 'B');
288 STRCMP_TEST_EXPECT_EQUAL(test, strcasecmp, strcmp_buffer1, strcmp_buffer2);
289
290 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'a';
291 STRCMP_TEST_EXPECT_LOWER(test, strcasecmp, strcmp_buffer1, strcmp_buffer2);
292
293 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'C';
294 STRCMP_TEST_EXPECT_GREATER(test, strcasecmp, strcmp_buffer1, strcmp_buffer2);
295}
296
297static void test_strncasecmp(struct kunit *test)
298{
299 /* Same strings in different case should be equal */
300 STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, "AbAcAbA", "Abacaba", strlen("Abacaba"));
301 /* strncasecmp should check 'count' chars only */
302 STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, "AbaCaBa", "abaCaDa", 5);
303 STRCMP_TEST_EXPECT_LOWER(test, strncasecmp, "a", "B", 1);
304 STRCMP_TEST_EXPECT_GREATER(test, strncasecmp, "B", "a", 1);
305 /* Result is always 'equal' when count = 0 */
306 STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, "Abacaba", "Not abacaba", 0);
307}
308
309static void test_strncasecmp_long_strings(struct kunit *test)
310{
311 strcmp_fill_buffers('b', 'B');
312 STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, strcmp_buffer1,
313 strcmp_buffer2, STRCMP_LARGE_BUF_LEN);
314
315 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'a';
316 STRCMP_TEST_EXPECT_LOWER(test, strncasecmp, strcmp_buffer1,
317 strcmp_buffer2, STRCMP_LARGE_BUF_LEN);
318
319 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'C';
320 STRCMP_TEST_EXPECT_GREATER(test, strncasecmp, strcmp_buffer1,
321 strcmp_buffer2, STRCMP_LARGE_BUF_LEN);
322
323 STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, strcmp_buffer1,
324 strcmp_buffer2, STRCMP_CHANGE_POINT);
325 STRCMP_TEST_EXPECT_GREATER(test, strncasecmp, strcmp_buffer1,
326 strcmp_buffer2, STRCMP_CHANGE_POINT + 1);
327}
328
329static struct kunit_case string_test_cases[] = {
330 KUNIT_CASE(test_memset16),
331 KUNIT_CASE(test_memset32),
332 KUNIT_CASE(test_memset64),
333 KUNIT_CASE(test_strchr),
334 KUNIT_CASE(test_strnchr),
335 KUNIT_CASE(test_strspn),
336 KUNIT_CASE(test_strcmp),
337 KUNIT_CASE(test_strcmp_long_strings),
338 KUNIT_CASE(test_strncmp),
339 KUNIT_CASE(test_strncmp_long_strings),
340 KUNIT_CASE(test_strcasecmp),
341 KUNIT_CASE(test_strcasecmp_long_strings),
342 KUNIT_CASE(test_strncasecmp),
343 KUNIT_CASE(test_strncasecmp_long_strings),
344 {}
345};
346
347static struct kunit_suite string_test_suite = {
348 .name = "string",
349 .test_cases = string_test_cases,
350};
351
352kunit_test_suites(&string_test_suite);
353
354MODULE_LICENSE("GPL v2");