blob: 621a74ceff179cb5e8126cd266b148796fedf8de [file] [log] [blame]
Jan Dabrosb0800d32020-05-06 16:01:27 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Jan Dabrosb0800d32020-05-06 16:01:27 +02002
Jan Dabros2d0ee362020-04-20 15:19:45 +02003#include <string.h>
Anna Karas907ddc32020-05-27 21:14:29 +02004#include <stdlib.h>
5#include <stdint.h>
6#include <stddef.h>
Julius Werner21744812020-05-04 17:44:04 -07007#include <tests/test.h>
Jan Dabros2d0ee362020-04-20 15:19:45 +02008
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
Anna Karas907ddc32020-05-27 21:14:29 +020013 * isolation.
Jan Dabros2d0ee362020-04-20 15:19:45 +020014 */
15
Anna Karas907ddc32020-05-27 21:14:29 +020016struct string_pairs_t {
17 char *dst;
18 char *src;
19} string_pairs[] = {
20 {"Hello ", "world!"},
21 {"He\0llo ", "world"},
22 {"", "world!"},
23 {"", ""},
Jan Dabros2d0ee362020-04-20 15:19:45 +020024};
25
Anna Karas907ddc32020-05-27 21:14:29 +020026const char *strings[] = {
27 "coreboot",
28 "is\0very",
29 "nice\n"
30};
Jan Dabros2d0ee362020-04-20 15:19:45 +020031
Anna Karas907ddc32020-05-27 21:14:29 +020032/* Used to test atol */
33struct 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
46/* Used to test skip_atoi */
47struct str_with_u_val_t {
48 char *str;
49 uint32_t value;
Anna Karas86acc042020-07-07 15:34:54 +020050 uint32_t offset;
Anna Karas907ddc32020-05-27 21:14:29 +020051} str_with_u_val[] = {
Anna Karas86acc042020-07-07 15:34:54 +020052 {"42aa", 42, 2},
53 {"a", 0, 0},
54 {"0", 0, 1},
55 {"4a2", 4, 1},
Anna Karas907ddc32020-05-27 21:14:29 +020056};
Jan Dabros2d0ee362020-04-20 15:19:45 +020057
58static void test_strdup(void **state)
59{
60 char str[] = "Hello coreboot\n";
Anna Karas907ddc32020-05-27 21:14:29 +020061 char *duplicate = strdup(str);
Jan Dabros2d0ee362020-04-20 15:19:45 +020062
63 /* There is a more suitable Cmocka's function 'assert_string_equal()', but it
64 is using strcmp() internally. */
65 assert_int_equal(0, memcmp(str, duplicate, __builtin_strlen(str)));
Anna Karas907ddc32020-05-27 21:14:29 +020066
67 free(duplicate);
68}
69
70static void test_strconcat(void **state)
71{
72 int i;
73 size_t str_len, str2_len, res_len;
74 char *result;
75
76 for (i = 0; i < ARRAY_SIZE(string_pairs); i++) {
77 str_len = __builtin_strlen(string_pairs[i].dst);
78 str2_len = __builtin_strlen(string_pairs[i].src);
79
80 result = strconcat(string_pairs[i].dst, string_pairs[i].src);
81 res_len = __builtin_strlen(result);
82
83 assert_int_equal(res_len, str_len + str2_len);
84 assert_int_equal(0, memcmp(string_pairs[i].dst, result, str_len));
85 assert_int_equal(0, memcmp(string_pairs[i].src, result + str_len, str2_len));
86
87 free(result);
88 }
89}
90
91static void test_strnlen(void **state)
92{
93 int i, n = 5;
94 size_t str_len, limited_len;
95
96 for (i = 0; i < ARRAY_SIZE(strings); i++) {
97 str_len = __builtin_strlen(strings[i]);
98 limited_len = MIN(n, str_len);
99 assert_int_equal(limited_len, strnlen(strings[i], n));
100 }
101}
102
103static void test_strlen(void **state)
104{
105 int i;
106
107 for (i = 0; i < ARRAY_SIZE(strings); i++)
108 assert_int_equal(__builtin_strlen(strings[i]), strlen(strings[i]));
109}
110
111static void test_strchr(void **state)
112{
113 char str[] = "Abracadabra!\n";
114
115 assert_ptr_equal(str, strchr(str, 'A'));
116 assert_ptr_equal(str + 3, strchr(str, 'a'));
117 assert_ptr_equal(str + 12, strchr(str, '\n'));
118
119 assert_null(strchr(str, 'z'));
120}
121
122
123static void test_strrchr(void **state)
124{
125 char str[] = "Abracadabra!\n";
126
127 assert_ptr_equal(str, strrchr(str, 'A'));
128 assert_ptr_equal(str + 9, strrchr(str, 'r'));
129 assert_ptr_equal(str + 12, strrchr(str, '\n'));
130
131 assert_null(strrchr(str, 'z'));
132}
133
134static void test_strncpy(void **state)
135{
136 int i;
137 int n1 = 2, n2 = 8;
138 char src[] = "Hello";
139 char dst[sizeof(src) + 5];
140 size_t src_len = __builtin_strlen(src);
141 size_t dst_len = sizeof(dst);
142
143 /* n1 case */
144
145 /* Needed for ensuring that characters behind the limit
146 are not overwritten */
147 memset(dst, 'x', dst_len);
148
149 strncpy(dst, src, n1);
150
151 assert_int_equal(0, memcmp(dst, src, n1));
152
153 for (i = n1; i < dst_len; i++)
154 assert_true(dst[i] == 'x');
155
156 /* n2 case: */
157
158 memset(dst, 'x', dst_len);
159
160 strncpy(dst, src, n2);
161
162 assert_int_equal(0, memcmp(dst, src, src_len));
163
164 for (i = src_len; i < n2; i++)
165 assert_true(dst[i] == '\0');
166
167 for (i = n2; i < dst_len; i++)
168 assert_true(dst[i] == 'x');
169}
170
171static void test_strcpy(void **state)
172{
173 char src[] = "Hello coreboot\n";
174 char dst[sizeof(src)];
175
176 /* Make sure that strcpy() sets '\0' by initializing a whole
177 dst array to fixed, non-'\0' value */
178 memset(dst, 'x', sizeof(dst));
179
180 strcpy(dst, src);
181
182 assert_int_equal(0, memcmp(dst, src, __builtin_strlen(src) + 1));
183}
184
185static void test_strcmp(void **state)
186{
187 char str[] = "Banana";
188 char str2[] = "Banana";
189 char str3[] = "Bananas";
190
191 assert_true(strcmp(str, str3) < 0);
192 assert_int_equal(0, strcmp(str, str2));
193 assert_true(strcmp(str3, str2) > 0);
194}
195
196static void test_strncmp(void **state)
197{
198 char str[] = "Banana";
199 char str2[] = "Bananas";
200
201 size_t str2_len = __builtin_strlen(str2);
202
203 assert_true(strncmp(str, str2, str2_len) < 0);
204 assert_int_equal(0, strncmp(str, str2, str2_len - 1));
205}
206
207static void test_skip_atoi(void **state)
208{
209 int i;
Anna Karas86acc042020-07-07 15:34:54 +0200210 char *ptr, *copy;
Anna Karas907ddc32020-05-27 21:14:29 +0200211
212 for (i = 0; i < ARRAY_SIZE(str_with_u_val); i++) {
213 ptr = str_with_u_val[i].str;
Anna Karas86acc042020-07-07 15:34:54 +0200214 copy = ptr;
Anna Karas907ddc32020-05-27 21:14:29 +0200215 assert_true(str_with_u_val[i].value == skip_atoi(&ptr));
Anna Karas86acc042020-07-07 15:34:54 +0200216 assert_int_equal(str_with_u_val[i].offset, ptr - copy);
Anna Karas907ddc32020-05-27 21:14:29 +0200217 }
218}
219
220static void test_strspn(void **state)
221{
222 char str[] = "4213401234";
223 char str2[] = "01234";
224 char str3[] = "1234";
225
226 assert_int_equal(5, strspn(str, str3));
227 assert_int_equal(0, strspn(str2, str3));
228}
229
230static void test_strcspn(void **state)
231{
232 char str[] = "12340000";
233 char str2[] = "00001234";
234 char str3[] = "1234";
235
236 assert_int_equal(0, strcspn(str, str3));
237 assert_int_equal(4, strcspn(str2, str3));
238}
239
240/* Please bear in mind that `atol()` uses `strspn()` internally, so the result
241 of `test_atol` is dependent on the result of `test_strspn`. */
242static void test_atol(void **state)
243{
244 int i;
245
246 for (i = 0; i < ARRAY_SIZE(str_with_l_val); i++)
247 assert_int_equal(str_with_l_val[i].value, atol(str_with_l_val[i].str));
Jan Dabros2d0ee362020-04-20 15:19:45 +0200248}
249
250int main(void)
251{
252 const struct CMUnitTest tests[] = {
Jan Dabros2d0ee362020-04-20 15:19:45 +0200253 cmocka_unit_test(test_strdup),
Anna Karas907ddc32020-05-27 21:14:29 +0200254 cmocka_unit_test(test_strconcat),
255 cmocka_unit_test(test_strnlen),
256 cmocka_unit_test(test_strlen),
257 cmocka_unit_test(test_strchr),
258 cmocka_unit_test(test_strrchr),
259 cmocka_unit_test(test_strncpy),
260 cmocka_unit_test(test_strcpy),
261 cmocka_unit_test(test_strcmp),
262 cmocka_unit_test(test_strncmp),
263 cmocka_unit_test(test_skip_atoi),
264 cmocka_unit_test(test_strspn),
265 cmocka_unit_test(test_strcspn),
266 cmocka_unit_test(test_atol),
Jan Dabros2d0ee362020-04-20 15:19:45 +0200267 };
268
Jakub Czapiga7c6081e2021-08-25 16:27:35 +0200269 return cb_run_group_tests(tests, NULL, NULL);
Jan Dabros2d0ee362020-04-20 15:19:45 +0200270}