1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2017 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 8 #include "spdk_cunit.h" 9 10 #include "util/string.c" 11 12 static void 13 test_parse_ip_addr(void) 14 { 15 int rc; 16 char *host; 17 char *port; 18 char ip[255]; 19 20 /* IPv4 */ 21 snprintf(ip, 255, "%s", "192.168.0.1"); 22 rc = spdk_parse_ip_addr(ip, &host, &port); 23 CU_ASSERT_EQUAL(rc, 0); 24 SPDK_CU_ASSERT_FATAL(host != NULL); 25 CU_ASSERT(strcmp(host, "192.168.0.1") == 0); 26 CU_ASSERT_EQUAL(strlen(host), 11); 27 CU_ASSERT_EQUAL(port, NULL); 28 29 /* IPv4 with port */ 30 snprintf(ip, 255, "%s", "123.456.789.0:5520"); 31 rc = spdk_parse_ip_addr(ip, &host, &port); 32 CU_ASSERT_EQUAL(rc, 0); 33 SPDK_CU_ASSERT_FATAL(host != NULL); 34 CU_ASSERT(strcmp(host, "123.456.789.0") == 0); 35 CU_ASSERT_EQUAL(strlen(host), 13); 36 SPDK_CU_ASSERT_FATAL(port != NULL); 37 CU_ASSERT(strcmp(port, "5520") == 0); 38 CU_ASSERT_EQUAL(strlen(port), 4); 39 40 /* IPv6 */ 41 snprintf(ip, 255, "%s", "[2001:db8:85a3:8d3:1319:8a2e:370:7348]"); 42 rc = spdk_parse_ip_addr(ip, &host, &port); 43 CU_ASSERT_EQUAL(rc, 0); 44 SPDK_CU_ASSERT_FATAL(host != NULL); 45 CU_ASSERT(strcmp(host, "2001:db8:85a3:8d3:1319:8a2e:370:7348") == 0); 46 CU_ASSERT_EQUAL(strlen(host), 36); 47 CU_ASSERT_EQUAL(port, NULL); 48 49 /* IPv6 with port */ 50 snprintf(ip, 255, "%s", "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443"); 51 rc = spdk_parse_ip_addr(ip, &host, &port); 52 CU_ASSERT_EQUAL(rc, 0); 53 SPDK_CU_ASSERT_FATAL(host != NULL); 54 CU_ASSERT(strcmp(host, "2001:db8:85a3:8d3:1319:8a2e:370:7348") == 0); 55 CU_ASSERT_EQUAL(strlen(host), 36); 56 SPDK_CU_ASSERT_FATAL(port != NULL); 57 CU_ASSERT(strcmp(port, "443") == 0); 58 CU_ASSERT_EQUAL(strlen(port), 3); 59 60 /* IPv6 dangling colon */ 61 snprintf(ip, 255, "%s", "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:"); 62 rc = spdk_parse_ip_addr(ip, &host, &port); 63 CU_ASSERT_EQUAL(rc, 0); 64 SPDK_CU_ASSERT_FATAL(host != NULL); 65 CU_ASSERT(strcmp(host, "2001:db8:85a3:8d3:1319:8a2e:370:7348") == 0); 66 CU_ASSERT_EQUAL(strlen(host), 36); 67 CU_ASSERT_EQUAL(port, NULL); 68 } 69 70 static void 71 test_str_chomp(void) 72 { 73 char s[1024]; 74 75 /* One \n newline */ 76 snprintf(s, sizeof(s), "%s", "hello world\n"); 77 CU_ASSERT(spdk_str_chomp(s) == 1); 78 CU_ASSERT(strcmp(s, "hello world") == 0); 79 80 /* One \r\n newline */ 81 snprintf(s, sizeof(s), "%s", "hello world\r\n"); 82 CU_ASSERT(spdk_str_chomp(s) == 2); 83 CU_ASSERT(strcmp(s, "hello world") == 0); 84 85 /* No newlines */ 86 snprintf(s, sizeof(s), "%s", "hello world"); 87 CU_ASSERT(spdk_str_chomp(s) == 0); 88 CU_ASSERT(strcmp(s, "hello world") == 0); 89 90 /* Two newlines */ 91 snprintf(s, sizeof(s), "%s", "hello world\n\n"); 92 CU_ASSERT(spdk_str_chomp(s) == 2); 93 CU_ASSERT(strcmp(s, "hello world") == 0); 94 95 /* Empty string */ 96 snprintf(s, sizeof(s), "%s", ""); 97 CU_ASSERT(spdk_str_chomp(s) == 0); 98 CU_ASSERT(strcmp(s, "") == 0); 99 100 /* One-character string with only \n */ 101 snprintf(s, sizeof(s), "%s", "\n"); 102 CU_ASSERT(spdk_str_chomp(s) == 1); 103 CU_ASSERT(strcmp(s, "") == 0); 104 105 /* One-character string without a newline */ 106 snprintf(s, sizeof(s), "%s", "a"); 107 CU_ASSERT(spdk_str_chomp(s) == 0); 108 CU_ASSERT(strcmp(s, "a") == 0); 109 } 110 111 static void 112 test_parse_capacity(void) 113 { 114 char str[128]; 115 uint64_t cap; 116 int rc; 117 bool has_prefix = true; 118 119 rc = spdk_parse_capacity("472", &cap, &has_prefix); 120 CU_ASSERT(rc == 0); 121 CU_ASSERT(cap == 472); 122 CU_ASSERT(has_prefix == false); 123 124 snprintf(str, sizeof(str), "%"PRIu64, UINT64_MAX); 125 rc = spdk_parse_capacity(str, &cap, &has_prefix); 126 CU_ASSERT(rc == 0); 127 CU_ASSERT(cap == UINT64_MAX); 128 CU_ASSERT(has_prefix == false); 129 130 rc = spdk_parse_capacity("12k", &cap, &has_prefix); 131 CU_ASSERT(rc == 0); 132 CU_ASSERT(cap == 12 * 1024); 133 CU_ASSERT(has_prefix == true); 134 135 rc = spdk_parse_capacity("12K", &cap, &has_prefix); 136 CU_ASSERT(rc == 0); 137 CU_ASSERT(cap == 12 * 1024); 138 CU_ASSERT(has_prefix == true); 139 140 rc = spdk_parse_capacity("12KB", &cap, &has_prefix); 141 CU_ASSERT(rc == 0); 142 CU_ASSERT(cap == 12 * 1024); 143 CU_ASSERT(has_prefix == true); 144 145 rc = spdk_parse_capacity("100M", &cap, &has_prefix); 146 CU_ASSERT(rc == 0); 147 CU_ASSERT(cap == 100 * 1024 * 1024); 148 CU_ASSERT(has_prefix == true); 149 150 rc = spdk_parse_capacity("128M", &cap, &has_prefix); 151 CU_ASSERT(rc == 0); 152 CU_ASSERT(cap == 128 * 1024 * 1024); 153 CU_ASSERT(has_prefix == true); 154 155 rc = spdk_parse_capacity("4G", &cap, &has_prefix); 156 CU_ASSERT(rc == 0); 157 CU_ASSERT(cap == 4ULL * 1024 * 1024 * 1024); 158 CU_ASSERT(has_prefix == true); 159 160 rc = spdk_parse_capacity("100M 512k", &cap, &has_prefix); 161 CU_ASSERT(rc == 0); 162 CU_ASSERT(cap == 100ULL * 1024 * 1024); 163 164 rc = spdk_parse_capacity("12k8K", &cap, &has_prefix); 165 CU_ASSERT(rc == 0); 166 CU_ASSERT(cap == 12 * 1024); 167 CU_ASSERT(has_prefix == true); 168 169 /* Non-number */ 170 rc = spdk_parse_capacity("G", &cap, &has_prefix); 171 CU_ASSERT(rc != 0); 172 173 rc = spdk_parse_capacity("darsto", &cap, &has_prefix); 174 CU_ASSERT(rc != 0); 175 } 176 177 static void 178 test_sprintf_append_realloc(void) 179 { 180 char *str1, *str2, *str3, *str4; 181 182 /* Test basic functionality. */ 183 str1 = spdk_sprintf_alloc("hello world\ngood morning\n" \ 184 "good afternoon\ngood evening\n"); 185 SPDK_CU_ASSERT_FATAL(str1 != NULL); 186 187 str2 = spdk_sprintf_append_realloc(NULL, "hello world\n"); 188 SPDK_CU_ASSERT_FATAL(str2); 189 190 str2 = spdk_sprintf_append_realloc(str2, "good morning\n"); 191 SPDK_CU_ASSERT_FATAL(str2); 192 193 str2 = spdk_sprintf_append_realloc(str2, "good afternoon\n"); 194 SPDK_CU_ASSERT_FATAL(str2); 195 196 str2 = spdk_sprintf_append_realloc(str2, "good evening\n"); 197 SPDK_CU_ASSERT_FATAL(str2); 198 199 CU_ASSERT(strcmp(str1, str2) == 0); 200 201 free(str1); 202 free(str2); 203 204 /* Test doubling buffer size. */ 205 str3 = spdk_sprintf_append_realloc(NULL, "aaaaaaaaaa\n"); 206 str3 = spdk_sprintf_append_realloc(str3, "bbbbbbbbbb\n"); 207 str3 = spdk_sprintf_append_realloc(str3, "cccccccccc\n"); 208 209 str4 = malloc(33 + 1); 210 memset(&str4[0], 'a', 10); 211 str4[10] = '\n'; 212 memset(&str4[11], 'b', 10); 213 str4[21] = '\n'; 214 memset(&str4[22], 'c', 10); 215 str4[32] = '\n'; 216 str4[33] = 0; 217 218 CU_ASSERT(strcmp(str3, str4) == 0); 219 220 free(str3); 221 free(str4); 222 } 223 224 static void 225 generate_string(char *str, size_t len, int64_t limit, int adjust) 226 { 227 /* There isn't a portable way of handling the arithmetic, so */ 228 /* perform the calculation in two parts to avoid overflow */ 229 int64_t hi = (limit / 10) + (adjust / 10); 230 int64_t lo = (limit % 10) + (adjust % 10); 231 232 /* limit is large and adjust is small, so hi part will be */ 233 /* non-zero even if there is a carry, but check it */ 234 CU_ASSERT(hi < -1 || hi > 1); 235 236 /* Correct a difference in sign */ 237 if ((hi < 0) != (lo < 0) && lo != 0) { 238 lo += (hi < 0) ? -10 : 10; 239 hi += (hi < 0) ? 1 : -1; 240 } 241 242 snprintf(str, len, "%" PRId64 "%01" PRId64, hi + (lo / 10), 243 (lo < 0) ? (-lo % 10) : (lo % 10)); 244 } 245 246 static void 247 test_strtol(void) 248 { 249 long int val; 250 char str[256]; 251 252 const char *val1 = "no_digits"; 253 /* digits + chars */ 254 const char *val8 = "10_is_ten"; 255 /* chars + digits */ 256 const char *val9 = "ten_is_10"; 257 /* all zeroes */ 258 const char *val10 = "00000000"; 259 /* leading minus sign, but not negative */ 260 const char *val11 = "-0"; 261 262 val = spdk_strtol(val1, 10); 263 CU_ASSERT(val == -EINVAL); 264 265 /* LONG_MIN - 1 */ 266 generate_string(str, sizeof(str), LONG_MIN, -1); 267 val = spdk_strtol(str, 10); 268 CU_ASSERT(val == -ERANGE); 269 270 /* LONG_MIN */ 271 generate_string(str, sizeof(str), LONG_MIN, 0); 272 val = spdk_strtol(str, 10); 273 CU_ASSERT(val == -ERANGE); 274 275 /* LONG_MIN + 1 */ 276 generate_string(str, sizeof(str), LONG_MIN, +1); 277 val = spdk_strtol(str, 10); 278 CU_ASSERT(val == -ERANGE); 279 280 /* LONG_MAX - 1 */ 281 generate_string(str, sizeof(str), LONG_MAX, -1); 282 val = spdk_strtol(str, 10); 283 CU_ASSERT(val == LONG_MAX - 1); 284 285 /* LONG_MAX */ 286 generate_string(str, sizeof(str), LONG_MAX, 0); 287 val = spdk_strtol(str, 10); 288 CU_ASSERT(val == LONG_MAX); 289 290 /* LONG_MAX + 1 */ 291 generate_string(str, sizeof(str), LONG_MAX, +1); 292 val = spdk_strtol(str, 10); 293 CU_ASSERT(val == -ERANGE); 294 295 val = spdk_strtol(val8, 10); 296 CU_ASSERT(val == -EINVAL); 297 298 val = spdk_strtol(val9, 10); 299 CU_ASSERT(val == -EINVAL); 300 301 val = spdk_strtol(val10, 10); 302 CU_ASSERT(val == 0); 303 304 /* Invalid base */ 305 val = spdk_strtol(val10, 1); 306 CU_ASSERT(val == -EINVAL); 307 308 val = spdk_strtol(val11, 10); 309 CU_ASSERT(val == 0); 310 } 311 312 static void 313 test_strtoll(void) 314 { 315 long long int val; 316 char str[256]; 317 318 const char *val1 = "no_digits"; 319 /* digits + chars */ 320 const char *val8 = "10_is_ten"; 321 /* chars + digits */ 322 const char *val9 = "ten_is_10"; 323 /* all zeroes */ 324 const char *val10 = "00000000"; 325 /* leading minus sign, but not negative */ 326 const char *val11 = "-0"; 327 328 val = spdk_strtoll(val1, 10); 329 CU_ASSERT(val == -EINVAL); 330 331 /* LLONG_MIN - 1 */ 332 generate_string(str, sizeof(str), LLONG_MIN, -1); 333 val = spdk_strtoll(str, 10); 334 CU_ASSERT(val == -ERANGE); 335 336 /* LLONG_MIN */ 337 generate_string(str, sizeof(str), LLONG_MIN, 0); 338 val = spdk_strtoll(str, 10); 339 CU_ASSERT(val == -ERANGE); 340 341 /* LLONG_MIN + 1 */ 342 generate_string(str, sizeof(str), LLONG_MIN, +1); 343 val = spdk_strtoll(str, 10); 344 CU_ASSERT(val == -ERANGE); 345 346 /* LLONG_MAX - 1 */ 347 generate_string(str, sizeof(str), LLONG_MAX, -1); 348 val = spdk_strtoll(str, 10); 349 CU_ASSERT(val == LLONG_MAX - 1); 350 351 /* LLONG_MAX */ 352 generate_string(str, sizeof(str), LLONG_MAX, 0); 353 val = spdk_strtoll(str, 10); 354 CU_ASSERT(val == LLONG_MAX); 355 356 /* LLONG_MAX + 1 */ 357 generate_string(str, sizeof(str), LLONG_MAX, +1); 358 val = spdk_strtoll(str, 10); 359 CU_ASSERT(val == -ERANGE); 360 361 val = spdk_strtoll(val8, 10); 362 CU_ASSERT(val == -EINVAL); 363 364 val = spdk_strtoll(val9, 10); 365 CU_ASSERT(val == -EINVAL); 366 367 val = spdk_strtoll(val10, 10); 368 CU_ASSERT(val == 0); 369 370 /* Invalid base */ 371 val = spdk_strtoll(val10, 1); 372 CU_ASSERT(val == -EINVAL); 373 374 val = spdk_strtoll(val11, 10); 375 CU_ASSERT(val == 0); 376 } 377 378 int 379 main(int argc, char **argv) 380 { 381 CU_pSuite suite = NULL; 382 unsigned int num_failures; 383 384 CU_set_error_action(CUEA_ABORT); 385 CU_initialize_registry(); 386 387 suite = CU_add_suite("string", NULL, NULL); 388 389 CU_ADD_TEST(suite, test_parse_ip_addr); 390 CU_ADD_TEST(suite, test_str_chomp); 391 CU_ADD_TEST(suite, test_parse_capacity); 392 CU_ADD_TEST(suite, test_sprintf_append_realloc); 393 CU_ADD_TEST(suite, test_strtol); 394 CU_ADD_TEST(suite, test_strtoll); 395 396 CU_basic_set_mode(CU_BRM_VERBOSE); 397 398 CU_basic_run_tests(); 399 400 num_failures = CU_get_number_of_failures(); 401 CU_cleanup_registry(); 402 403 return num_failures; 404 } 405