1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Kernel module for testing 'strcat' family of functions. |
4 | */ |
5 | |
6 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
7 | |
8 | #include <kunit/test.h> |
9 | #include <linux/string.h> |
10 | |
11 | static volatile int unconst; |
12 | |
13 | static void strcat_test(struct kunit *test) |
14 | { |
15 | char dest[8]; |
16 | |
17 | /* Destination is terminated. */ |
18 | memset(dest, 0, sizeof(dest)); |
19 | KUNIT_EXPECT_EQ(test, strlen(dest), 0); |
20 | /* Empty copy does nothing. */ |
21 | KUNIT_EXPECT_TRUE(test, strcat(dest, "" ) == dest); |
22 | KUNIT_EXPECT_STREQ(test, dest, "" ); |
23 | /* 4 characters copied in, stops at %NUL. */ |
24 | KUNIT_EXPECT_TRUE(test, strcat(dest, "four\000123" ) == dest); |
25 | KUNIT_EXPECT_STREQ(test, dest, "four" ); |
26 | KUNIT_EXPECT_EQ(test, dest[5], '\0'); |
27 | /* 2 more characters copied in okay. */ |
28 | KUNIT_EXPECT_TRUE(test, strcat(dest, "AB" ) == dest); |
29 | KUNIT_EXPECT_STREQ(test, dest, "fourAB" ); |
30 | } |
31 | |
32 | static void strncat_test(struct kunit *test) |
33 | { |
34 | char dest[8]; |
35 | |
36 | /* Destination is terminated. */ |
37 | memset(dest, 0, sizeof(dest)); |
38 | KUNIT_EXPECT_EQ(test, strlen(dest), 0); |
39 | /* Empty copy of size 0 does nothing. */ |
40 | KUNIT_EXPECT_TRUE(test, strncat(dest, "" , 0 + unconst) == dest); |
41 | KUNIT_EXPECT_STREQ(test, dest, "" ); |
42 | /* Empty copy of size 1 does nothing too. */ |
43 | KUNIT_EXPECT_TRUE(test, strncat(dest, "" , 1 + unconst) == dest); |
44 | KUNIT_EXPECT_STREQ(test, dest, "" ); |
45 | /* Copy of max 0 characters should do nothing. */ |
46 | KUNIT_EXPECT_TRUE(test, strncat(dest, "asdf" , 0 + unconst) == dest); |
47 | KUNIT_EXPECT_STREQ(test, dest, "" ); |
48 | |
49 | /* 4 characters copied in, even if max is 8. */ |
50 | KUNIT_EXPECT_TRUE(test, strncat(dest, "four\000123" , 8 + unconst) == dest); |
51 | KUNIT_EXPECT_STREQ(test, dest, "four" ); |
52 | KUNIT_EXPECT_EQ(test, dest[5], '\0'); |
53 | KUNIT_EXPECT_EQ(test, dest[6], '\0'); |
54 | /* 2 characters copied in okay, 2 ignored. */ |
55 | KUNIT_EXPECT_TRUE(test, strncat(dest, "ABCD" , 2 + unconst) == dest); |
56 | KUNIT_EXPECT_STREQ(test, dest, "fourAB" ); |
57 | } |
58 | |
59 | static void strlcat_test(struct kunit *test) |
60 | { |
61 | char dest[8] = "" ; |
62 | int len = sizeof(dest) + unconst; |
63 | |
64 | /* Destination is terminated. */ |
65 | KUNIT_EXPECT_EQ(test, strlen(dest), 0); |
66 | /* Empty copy is size 0. */ |
67 | KUNIT_EXPECT_EQ(test, strlcat(dest, "" , len), 0); |
68 | KUNIT_EXPECT_STREQ(test, dest, "" ); |
69 | /* Size 1 should keep buffer terminated, report size of source only. */ |
70 | KUNIT_EXPECT_EQ(test, strlcat(dest, "four" , 1 + unconst), 4); |
71 | KUNIT_EXPECT_STREQ(test, dest, "" ); |
72 | |
73 | /* 4 characters copied in. */ |
74 | KUNIT_EXPECT_EQ(test, strlcat(dest, "four" , len), 4); |
75 | KUNIT_EXPECT_STREQ(test, dest, "four" ); |
76 | /* 2 characters copied in okay, gets to 6 total. */ |
77 | KUNIT_EXPECT_EQ(test, strlcat(dest, "AB" , len), 6); |
78 | KUNIT_EXPECT_STREQ(test, dest, "fourAB" ); |
79 | /* 2 characters ignored if max size (7) reached. */ |
80 | KUNIT_EXPECT_EQ(test, strlcat(dest, "CD" , 7 + unconst), 8); |
81 | KUNIT_EXPECT_STREQ(test, dest, "fourAB" ); |
82 | /* 1 of 2 characters skipped, now at true max size. */ |
83 | KUNIT_EXPECT_EQ(test, strlcat(dest, "EFG" , len), 9); |
84 | KUNIT_EXPECT_STREQ(test, dest, "fourABE" ); |
85 | /* Everything else ignored, now at full size. */ |
86 | KUNIT_EXPECT_EQ(test, strlcat(dest, "1234" , len), 11); |
87 | KUNIT_EXPECT_STREQ(test, dest, "fourABE" ); |
88 | } |
89 | |
90 | static struct kunit_case strcat_test_cases[] = { |
91 | KUNIT_CASE(strcat_test), |
92 | KUNIT_CASE(strncat_test), |
93 | KUNIT_CASE(strlcat_test), |
94 | {} |
95 | }; |
96 | |
97 | static struct kunit_suite strcat_test_suite = { |
98 | .name = "strcat" , |
99 | .test_cases = strcat_test_cases, |
100 | }; |
101 | |
102 | kunit_test_suite(strcat_test_suite); |
103 | |
104 | MODULE_LICENSE("GPL" ); |
105 | |