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 }