xref: /aosp_15_r20/external/coreboot/tests/lib/string-test.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <string.h>
4 #include <stdlib.h>
5 #include <stdint.h>
6 #include <stddef.h>
7 #include <tests/test.h>
8 
9 /*
10  * Important note: In every particular test, don't use any string-related
11  * functions other than function under test. We are linking against
12  * src/lib/string.c not the standard library. This is important for proper test
13  * isolation.
14  */
15 
16 struct string_pairs_t {
17 	char *dst;
18 	char *src;
19 } string_pairs[] = {
20 	{"Hello ", "world!"},
21 	{"He\0llo ", "world"},
22 	{"", "world!"},
23 	{"", ""},
24 };
25 
26 const char *strings[] = {
27 	"coreboot",
28 	"is\0very",
29 	"nice\n"
30 };
31 
32 /* Used to test atol */
33 struct str_with_l_val_t {
34 	char *str;
35 	long value;
36 } str_with_l_val[] = {
37 	{"42", 42},
38 	{"four42", 0},
39 	{"42five5",	42},
40 	{"4\02", 4},
41 	{"+42", 42},
42 	{"-42", -42},
43 	{"\t\n\r\f\v-42", -42},
44 };
45 
test_strdup(void ** state)46 static void test_strdup(void **state)
47 {
48 	char str[] = "Hello coreboot\n";
49 	char *duplicate = strdup(str);
50 
51 	/* There is a more suitable Cmocka's function 'assert_string_equal()', but it
52 	   is using strcmp() internally. */
53 	assert_int_equal(0, memcmp(str, duplicate, __builtin_strlen(str)));
54 
55 	free(duplicate);
56 }
57 
test_strconcat(void ** state)58 static void test_strconcat(void **state)
59 {
60 	int i;
61 	size_t str_len, str2_len, res_len;
62 	char *result;
63 
64 	for (i = 0; i < ARRAY_SIZE(string_pairs); i++) {
65 		str_len = __builtin_strlen(string_pairs[i].dst);
66 		str2_len = __builtin_strlen(string_pairs[i].src);
67 
68 		result = strconcat(string_pairs[i].dst, string_pairs[i].src);
69 		res_len = __builtin_strlen(result);
70 
71 		assert_int_equal(res_len, str_len + str2_len);
72 		assert_int_equal(0, memcmp(string_pairs[i].dst, result, str_len));
73 		assert_int_equal(0, memcmp(string_pairs[i].src, result + str_len, str2_len));
74 
75 		free(result);
76 	}
77 }
78 
test_strnlen(void ** state)79 static void test_strnlen(void **state)
80 {
81 	int i, n = 5;
82 	size_t str_len, limited_len;
83 
84 	for (i = 0; i < ARRAY_SIZE(strings); i++) {
85 		str_len = __builtin_strlen(strings[i]);
86 		limited_len = MIN(n, str_len);
87 		assert_int_equal(limited_len, strnlen(strings[i], n));
88 	}
89 }
90 
test_strlen(void ** state)91 static void test_strlen(void **state)
92 {
93 	int i;
94 
95 	for (i = 0; i < ARRAY_SIZE(strings); i++)
96 		assert_int_equal(__builtin_strlen(strings[i]), strlen(strings[i]));
97 }
98 
test_strchr(void ** state)99 static void test_strchr(void **state)
100 {
101 	char str[] = "Abracadabra!\n";
102 
103 	assert_ptr_equal(str, strchr(str, 'A'));
104 	assert_ptr_equal(str + 3, strchr(str, 'a'));
105 	assert_ptr_equal(str + 12, strchr(str, '\n'));
106 
107 	assert_null(strchr(str, 'z'));
108 }
109 
110 
test_strrchr(void ** state)111 static void test_strrchr(void **state)
112 {
113 	char str[] = "Abracadabra!\n";
114 
115 	assert_ptr_equal(str, strrchr(str, 'A'));
116 	assert_ptr_equal(str + 9, strrchr(str, 'r'));
117 	assert_ptr_equal(str + 12, strrchr(str, '\n'));
118 
119 	assert_null(strrchr(str, 'z'));
120 }
121 
test_strncpy(void ** state)122 static void test_strncpy(void **state)
123 {
124 	int i;
125 	int n1 = 2, n2 = 8;
126 	char src[] = "Hello";
127 	char dst[sizeof(src) + 5];
128 	size_t src_len = __builtin_strlen(src);
129 	size_t dst_len = sizeof(dst);
130 
131 	/* n1 case  */
132 
133 	/* Needed for ensuring that characters behind the limit
134 	   are not overwritten */
135 	memset(dst, 'x', dst_len);
136 
137 	strncpy(dst, src, n1);
138 
139 	assert_int_equal(0, memcmp(dst, src, n1));
140 
141 	for (i = n1; i < dst_len; i++)
142 		assert_true(dst[i] == 'x');
143 
144 	/* n2 case: */
145 
146 	memset(dst, 'x', dst_len);
147 
148 	strncpy(dst, src, n2);
149 
150 	assert_int_equal(0, memcmp(dst, src, src_len));
151 
152 	for (i = src_len; i < n2; i++)
153 		assert_true(dst[i] == '\0');
154 
155 	for (i = n2; i < dst_len; i++)
156 		assert_true(dst[i] == 'x');
157 }
158 
test_strcpy(void ** state)159 static void test_strcpy(void **state)
160 {
161 	char src[] = "Hello coreboot\n";
162 	char dst[sizeof(src)];
163 
164 	/* Make sure that strcpy() sets '\0' by initializing a whole
165 	   dst array to fixed, non-'\0' value */
166 	memset(dst, 'x', sizeof(dst));
167 
168 	strcpy(dst, src);
169 
170 	assert_int_equal(0, memcmp(dst, src, __builtin_strlen(src) + 1));
171 }
172 
test_strcmp(void ** state)173 static void test_strcmp(void **state)
174 {
175 	char str[] = "Banana";
176 	char str2[] = "Banana";
177 	char str3[] = "Bananas";
178 
179 	assert_true(strcmp(str, str3) < 0);
180 	assert_int_equal(0, strcmp(str, str2));
181 	assert_true(strcmp(str3, str2) > 0);
182 }
183 
test_strncmp(void ** state)184 static void test_strncmp(void **state)
185 {
186 	char str[] = "Banana";
187 	char str2[] = "Bananas";
188 
189 	size_t str2_len = __builtin_strlen(str2);
190 
191 	assert_true(strncmp(str, str2, str2_len) < 0);
192 	assert_int_equal(0, strncmp(str, str2, str2_len - 1));
193 }
194 
test_strspn(void ** state)195 static void test_strspn(void **state)
196 {
197 	char str[] = "4213401234";
198 	char str2[] = "01234";
199 	char str3[] = "1234";
200 
201 	assert_int_equal(5, strspn(str, str3));
202 	assert_int_equal(0, strspn(str2, str3));
203 }
204 
test_strcspn(void ** state)205 static void test_strcspn(void **state)
206 {
207 	char str[] = "12340000";
208 	char str2[] = "00001234";
209 	char str3[] = "1234";
210 
211 	assert_int_equal(0, strcspn(str, str3));
212 	assert_int_equal(4, strcspn(str2, str3));
213 }
214 
215 /* Please bear in mind that `atol()` uses `strspn()` internally, so the result
216    of `test_atol` is dependent on the result of `test_strspn`. */
test_atol(void ** state)217 static void test_atol(void **state)
218 {
219 	int i;
220 
221 	for (i = 0; i < ARRAY_SIZE(str_with_l_val); i++)
222 		assert_int_equal(str_with_l_val[i].value, atol(str_with_l_val[i].str));
223 }
224 
main(void)225 int main(void)
226 {
227 	const struct CMUnitTest tests[] = {
228 		cmocka_unit_test(test_strdup),
229 		cmocka_unit_test(test_strconcat),
230 		cmocka_unit_test(test_strnlen),
231 		cmocka_unit_test(test_strlen),
232 		cmocka_unit_test(test_strchr),
233 		cmocka_unit_test(test_strrchr),
234 		cmocka_unit_test(test_strncpy),
235 		cmocka_unit_test(test_strcpy),
236 		cmocka_unit_test(test_strcmp),
237 		cmocka_unit_test(test_strncmp),
238 		cmocka_unit_test(test_strspn),
239 		cmocka_unit_test(test_strcspn),
240 		cmocka_unit_test(test_atol),
241 	};
242 
243 	return cb_run_group_tests(tests, NULL, NULL);
244 }
245