/ tests / lib / string-test.c
string-test.c
  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  /* Used to test atol */
 27  struct str_with_l_val_t {
 28  	char *str;
 29  	long value;
 30  } str_with_l_val[] = {
 31  	{"42", 42},
 32  	{"four42", 0},
 33  	{"42five5",	42},
 34  	{"4\02", 4},
 35  	{"+42", 42},
 36  	{"-42", -42},
 37  	{"\t\n\r\f\v-42", -42},
 38  };
 39  
 40  static void test_strdup(void **state)
 41  {
 42  	char str[] = "Hello coreboot\n";
 43  	char *duplicate = strdup(str);
 44  
 45  	/* There is a more suitable Cmocka's function 'assert_string_equal()', but it
 46  	   is using strcmp() internally. */
 47  	assert_int_equal(0, memcmp(str, duplicate, __builtin_strlen(str)));
 48  
 49  	free(duplicate);
 50  }
 51  
 52  static void test_strconcat(void **state)
 53  {
 54  	int i;
 55  	size_t str_len, str2_len, res_len;
 56  	char *result;
 57  
 58  	for (i = 0; i < ARRAY_SIZE(string_pairs); i++) {
 59  		str_len = __builtin_strlen(string_pairs[i].dst);
 60  		str2_len = __builtin_strlen(string_pairs[i].src);
 61  
 62  		result = strconcat(string_pairs[i].dst, string_pairs[i].src);
 63  		res_len = __builtin_strlen(result);
 64  
 65  		assert_int_equal(res_len, str_len + str2_len);
 66  		assert_int_equal(0, memcmp(string_pairs[i].dst, result, str_len));
 67  		assert_int_equal(0, memcmp(string_pairs[i].src, result + str_len, str2_len));
 68  
 69  		free(result);
 70  	}
 71  }
 72  
 73  static void test_strchr(void **state)
 74  {
 75  	char str[] = "Abracadabra!\n";
 76  
 77  	assert_ptr_equal(str, strchr(str, 'A'));
 78  	assert_ptr_equal(str + 3, strchr(str, 'a'));
 79  	assert_ptr_equal(str + 12, strchr(str, '\n'));
 80  
 81  	assert_null(strchr(str, 'z'));
 82  }
 83  
 84  
 85  static void test_strrchr(void **state)
 86  {
 87  	char str[] = "Abracadabra!\n";
 88  
 89  	assert_ptr_equal(str, strrchr(str, 'A'));
 90  	assert_ptr_equal(str + 9, strrchr(str, 'r'));
 91  	assert_ptr_equal(str + 12, strrchr(str, '\n'));
 92  
 93  	assert_null(strrchr(str, 'z'));
 94  }
 95  
 96  static void test_strncpy(void **state)
 97  {
 98  	int i;
 99  	int n1 = 2, n2 = 8;
100  	char src[] = "Hello";
101  	char dst[sizeof(src) + 5];
102  	size_t src_len = __builtin_strlen(src);
103  	size_t dst_len = sizeof(dst);
104  
105  	/* n1 case  */
106  
107  	/* Needed for ensuring that characters behind the limit
108  	   are not overwritten */
109  	memset(dst, 'x', dst_len);
110  
111  	strncpy(dst, src, n1);
112  
113  	assert_int_equal(0, memcmp(dst, src, n1));
114  
115  	for (i = n1; i < dst_len; i++)
116  		assert_true(dst[i] == 'x');
117  
118  	/* n2 case: */
119  
120  	memset(dst, 'x', dst_len);
121  
122  	strncpy(dst, src, n2);
123  
124  	assert_int_equal(0, memcmp(dst, src, src_len));
125  
126  	for (i = src_len; i < n2; i++)
127  		assert_true(dst[i] == '\0');
128  
129  	for (i = n2; i < dst_len; i++)
130  		assert_true(dst[i] == 'x');
131  }
132  
133  static void test_strcpy(void **state)
134  {
135  	char src[] = "Hello coreboot\n";
136  	char dst[sizeof(src)];
137  
138  	/* Make sure that strcpy() sets '\0' by initializing a whole
139  	   dst array to fixed, non-'\0' value */
140  	memset(dst, 'x', sizeof(dst));
141  
142  	strcpy(dst, src);
143  
144  	assert_int_equal(0, memcmp(dst, src, __builtin_strlen(src) + 1));
145  }
146  
147  static void test_strcmp(void **state)
148  {
149  	char str[] = "Banana";
150  	char str2[] = "Banana";
151  	char str3[] = "Bananas";
152  
153  	assert_true(strcmp(str, str3) < 0);
154  	assert_int_equal(0, strcmp(str, str2));
155  	assert_true(strcmp(str3, str2) > 0);
156  }
157  
158  static void test_strncmp(void **state)
159  {
160  	char str[] = "Banana";
161  	char str2[] = "Bananas";
162  
163  	size_t str2_len = __builtin_strlen(str2);
164  
165  	assert_true(strncmp(str, str2, str2_len) < 0);
166  	assert_int_equal(0, strncmp(str, str2, str2_len - 1));
167  }
168  
169  static void test_strspn(void **state)
170  {
171  	char str[] = "4213401234";
172  	char str2[] = "01234";
173  	char str3[] = "1234";
174  
175  	assert_int_equal(5, strspn(str, str3));
176  	assert_int_equal(0, strspn(str2, str3));
177  }
178  
179  static void test_strcspn(void **state)
180  {
181  	char str[] = "12340000";
182  	char str2[] = "00001234";
183  	char str3[] = "1234";
184  
185  	assert_int_equal(0, strcspn(str, str3));
186  	assert_int_equal(4, strcspn(str2, str3));
187  }
188  
189  /* Please bear in mind that `atol()` uses `strspn()` internally, so the result
190     of `test_atol` is dependent on the result of `test_strspn`. */
191  static void test_atol(void **state)
192  {
193  	int i;
194  
195  	for (i = 0; i < ARRAY_SIZE(str_with_l_val); i++)
196  		assert_int_equal(str_with_l_val[i].value, atol(str_with_l_val[i].str));
197  }
198  
199  int main(void)
200  {
201  	const struct CMUnitTest tests[] = {
202  		cmocka_unit_test(test_strdup),
203  		cmocka_unit_test(test_strconcat),
204  		cmocka_unit_test(test_strchr),
205  		cmocka_unit_test(test_strrchr),
206  		cmocka_unit_test(test_strncpy),
207  		cmocka_unit_test(test_strcpy),
208  		cmocka_unit_test(test_strcmp),
209  		cmocka_unit_test(test_strncmp),
210  		cmocka_unit_test(test_strspn),
211  		cmocka_unit_test(test_strcspn),
212  		cmocka_unit_test(test_atol),
213  	};
214  
215  	return cb_run_group_tests(tests, NULL, NULL);
216  }