blob: 0f21747e11d0ee3a7905e1a38fd78b22abeff15c [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>
Anna Karas907ddc32020-05-27 21:14:29 +02008#include <stdio.h>
Jan Dabros2d0ee362020-04-20 15:19:45 +02009
10/*
11 * Important note: In every particular test, don't use any string-related
12 * functions other than function under test. We are linking against
13 * src/lib/string.c not the standard library. This is important for proper test
Anna Karas907ddc32020-05-27 21:14:29 +020014 * isolation.
Jan Dabros2d0ee362020-04-20 15:19:45 +020015 */
16
Anna Karas907ddc32020-05-27 21:14:29 +020017struct string_pairs_t {
18 char *dst;
19 char *src;
20} string_pairs[] = {
21 {"Hello ", "world!"},
22 {"He\0llo ", "world"},
23 {"", "world!"},
24 {"", ""},
Jan Dabros2d0ee362020-04-20 15:19:45 +020025};
26
Anna Karas907ddc32020-05-27 21:14:29 +020027const char *strings[] = {
28 "coreboot",
29 "is\0very",
30 "nice\n"
31};
Jan Dabros2d0ee362020-04-20 15:19:45 +020032
Anna Karas907ddc32020-05-27 21:14:29 +020033/* Used to test atol */
34struct str_with_l_val_t {
35 char *str;
36 long value;
37} str_with_l_val[] = {
38 {"42", 42},
39 {"four42", 0},
40 {"42five5", 42},
41 {"4\02", 4},
42 {"+42", 42},
43 {"-42", -42},
44 {"\t\n\r\f\v-42", -42},
45};
46
47/* Used to test skip_atoi */
48struct str_with_u_val_t {
49 char *str;
50 uint32_t value;
Anna Karas86acc042020-07-07 15:34:54 +020051 uint32_t offset;
Anna Karas907ddc32020-05-27 21:14:29 +020052} str_with_u_val[] = {
Anna Karas86acc042020-07-07 15:34:54 +020053 {"42aa", 42, 2},
54 {"a", 0, 0},
55 {"0", 0, 1},
56 {"4a2", 4, 1},
Anna Karas907ddc32020-05-27 21:14:29 +020057};
Jan Dabros2d0ee362020-04-20 15:19:45 +020058
59static void test_strdup(void **state)
60{
61 char str[] = "Hello coreboot\n";
Anna Karas907ddc32020-05-27 21:14:29 +020062 char *duplicate = strdup(str);
Jan Dabros2d0ee362020-04-20 15:19:45 +020063
64 /* There is a more suitable Cmocka's function 'assert_string_equal()', but it
65 is using strcmp() internally. */
66 assert_int_equal(0, memcmp(str, duplicate, __builtin_strlen(str)));
Anna Karas907ddc32020-05-27 21:14:29 +020067
68 free(duplicate);
69}
70
71static void test_strconcat(void **state)
72{
73 int i;
74 size_t str_len, str2_len, res_len;
75 char *result;
76
77 for (i = 0; i < ARRAY_SIZE(string_pairs); i++) {
78 str_len = __builtin_strlen(string_pairs[i].dst);
79 str2_len = __builtin_strlen(string_pairs[i].src);
80
81 result = strconcat(string_pairs[i].dst, string_pairs[i].src);
82 res_len = __builtin_strlen(result);
83
84 assert_int_equal(res_len, str_len + str2_len);
85 assert_int_equal(0, memcmp(string_pairs[i].dst, result, str_len));
86 assert_int_equal(0, memcmp(string_pairs[i].src, result + str_len, str2_len));
87
88 free(result);
89 }
90}
91
92static void test_strnlen(void **state)
93{
94 int i, n = 5;
95 size_t str_len, limited_len;
96
97 for (i = 0; i < ARRAY_SIZE(strings); i++) {
98 str_len = __builtin_strlen(strings[i]);
99 limited_len = MIN(n, str_len);
100 assert_int_equal(limited_len, strnlen(strings[i], n));
101 }
102}
103
104static void test_strlen(void **state)
105{
106 int i;
107
108 for (i = 0; i < ARRAY_SIZE(strings); i++)
109 assert_int_equal(__builtin_strlen(strings[i]), strlen(strings[i]));
110}
111
112static void test_strchr(void **state)
113{
114 char str[] = "Abracadabra!\n";
115
116 assert_ptr_equal(str, strchr(str, 'A'));
117 assert_ptr_equal(str + 3, strchr(str, 'a'));
118 assert_ptr_equal(str + 12, strchr(str, '\n'));
119
120 assert_null(strchr(str, 'z'));
121}
122
123
124static void test_strrchr(void **state)
125{
126 char str[] = "Abracadabra!\n";
127
128 assert_ptr_equal(str, strrchr(str, 'A'));
129 assert_ptr_equal(str + 9, strrchr(str, 'r'));
130 assert_ptr_equal(str + 12, strrchr(str, '\n'));
131
132 assert_null(strrchr(str, 'z'));
133}
134
135static void test_strncpy(void **state)
136{
137 int i;
138 int n1 = 2, n2 = 8;
139 char src[] = "Hello";
140 char dst[sizeof(src) + 5];
141 size_t src_len = __builtin_strlen(src);
142 size_t dst_len = sizeof(dst);
143
144 /* n1 case */
145
146 /* Needed for ensuring that characters behind the limit
147 are not overwritten */
148 memset(dst, 'x', dst_len);
149
150 strncpy(dst, src, n1);
151
152 assert_int_equal(0, memcmp(dst, src, n1));
153
154 for (i = n1; i < dst_len; i++)
155 assert_true(dst[i] == 'x');
156
157 /* n2 case: */
158
159 memset(dst, 'x', dst_len);
160
161 strncpy(dst, src, n2);
162
163 assert_int_equal(0, memcmp(dst, src, src_len));
164
165 for (i = src_len; i < n2; i++)
166 assert_true(dst[i] == '\0');
167
168 for (i = n2; i < dst_len; i++)
169 assert_true(dst[i] == 'x');
170}
171
172static void test_strcpy(void **state)
173{
174 char src[] = "Hello coreboot\n";
175 char dst[sizeof(src)];
176
177 /* Make sure that strcpy() sets '\0' by initializing a whole
178 dst array to fixed, non-'\0' value */
179 memset(dst, 'x', sizeof(dst));
180
181 strcpy(dst, src);
182
183 assert_int_equal(0, memcmp(dst, src, __builtin_strlen(src) + 1));
184}
185
186static void test_strcmp(void **state)
187{
188 char str[] = "Banana";
189 char str2[] = "Banana";
190 char str3[] = "Bananas";
191
192 assert_true(strcmp(str, str3) < 0);
193 assert_int_equal(0, strcmp(str, str2));
194 assert_true(strcmp(str3, str2) > 0);
195}
196
197static void test_strncmp(void **state)
198{
199 char str[] = "Banana";
200 char str2[] = "Bananas";
201
202 size_t str2_len = __builtin_strlen(str2);
203
204 assert_true(strncmp(str, str2, str2_len) < 0);
205 assert_int_equal(0, strncmp(str, str2, str2_len - 1));
206}
207
208static void test_skip_atoi(void **state)
209{
210 int i;
Anna Karas86acc042020-07-07 15:34:54 +0200211 char *ptr, *copy;
Anna Karas907ddc32020-05-27 21:14:29 +0200212
213 for (i = 0; i < ARRAY_SIZE(str_with_u_val); i++) {
214 ptr = str_with_u_val[i].str;
Anna Karas86acc042020-07-07 15:34:54 +0200215 copy = ptr;
Anna Karas907ddc32020-05-27 21:14:29 +0200216 assert_true(str_with_u_val[i].value == skip_atoi(&ptr));
Anna Karas86acc042020-07-07 15:34:54 +0200217 assert_int_equal(str_with_u_val[i].offset, ptr - copy);
Anna Karas907ddc32020-05-27 21:14:29 +0200218 }
219}
220
221static void test_strspn(void **state)
222{
223 char str[] = "4213401234";
224 char str2[] = "01234";
225 char str3[] = "1234";
226
227 assert_int_equal(5, strspn(str, str3));
228 assert_int_equal(0, strspn(str2, str3));
229}
230
231static void test_strcspn(void **state)
232{
233 char str[] = "12340000";
234 char str2[] = "00001234";
235 char str3[] = "1234";
236
237 assert_int_equal(0, strcspn(str, str3));
238 assert_int_equal(4, strcspn(str2, str3));
239}
240
241/* Please bear in mind that `atol()` uses `strspn()` internally, so the result
242 of `test_atol` is dependent on the result of `test_strspn`. */
243static void test_atol(void **state)
244{
245 int i;
246
247 for (i = 0; i < ARRAY_SIZE(str_with_l_val); i++)
248 assert_int_equal(str_with_l_val[i].value, atol(str_with_l_val[i].str));
Jan Dabros2d0ee362020-04-20 15:19:45 +0200249}
250
251int main(void)
252{
253 const struct CMUnitTest tests[] = {
Jan Dabros2d0ee362020-04-20 15:19:45 +0200254 cmocka_unit_test(test_strdup),
Anna Karas907ddc32020-05-27 21:14:29 +0200255 cmocka_unit_test(test_strconcat),
256 cmocka_unit_test(test_strnlen),
257 cmocka_unit_test(test_strlen),
258 cmocka_unit_test(test_strchr),
259 cmocka_unit_test(test_strrchr),
260 cmocka_unit_test(test_strncpy),
261 cmocka_unit_test(test_strcpy),
262 cmocka_unit_test(test_strcmp),
263 cmocka_unit_test(test_strncmp),
264 cmocka_unit_test(test_skip_atoi),
265 cmocka_unit_test(test_strspn),
266 cmocka_unit_test(test_strcspn),
267 cmocka_unit_test(test_atol),
Jan Dabros2d0ee362020-04-20 15:19:45 +0200268 };
269
Jakub Czapiga7c6081e2021-08-25 16:27:35 +0200270 return cb_run_group_tests(tests, NULL, NULL);
Jan Dabros2d0ee362020-04-20 15:19:45 +0200271}