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