1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2024 HiSilicon Limited 3 */ 4 5 #include <stdio.h> 6 #include <string.h> 7 8 #include <rte_argparse.h> 9 10 #include "test.h" 11 12 static int default_argc; 13 static char *default_argv[1]; 14 15 #define MAX_STRDUP_STORE_NUM 512 16 static char *strdup_store_array[MAX_STRDUP_STORE_NUM]; 17 static uint32_t strdup_store_index; 18 19 /* 20 * Define strdup wrapper. 21 * 1. Mainly to fix compile error "warning: assignment discards 'const' 22 * qualifier from pointer target type [-Wdiscarded-qualifiers]" for 23 * following code: 24 * argv[x] = "100"; 25 * 2. The strdup result will store in the strdup_store_array, and then 26 * freed in the teardown function, prevent ASAN errors from being 27 * triggered. 28 */ 29 static char * 30 test_strdup(const char *str) 31 { 32 char *s = strdup(str); 33 if (s == NULL) { 34 printf("strdup failed! exiting...\n"); 35 exit(-ENOMEM); 36 } 37 if (strdup_store_index >= MAX_STRDUP_STORE_NUM) { 38 printf("too much strdup calls! exiting...\n"); 39 exit(-ERANGE); 40 } 41 strdup_store_array[strdup_store_index++] = s; 42 return s; 43 } 44 45 static int 46 test_argparse_setup(void) 47 { 48 strdup_store_index = 0; 49 default_argc = 1; 50 default_argv[0] = test_strdup("test_argparse"); 51 return 0; 52 } 53 54 static void 55 test_argparse_teardown(void) 56 { 57 uint32_t i; 58 printf("total used strdup_store_index = %u\n", strdup_store_index); 59 for (i = 0; i < strdup_store_index; i++) 60 free(strdup_store_array[i]); 61 strdup_store_index = 0; 62 } 63 64 static int 65 test_argparse_callback(uint32_t index, const char *value, void *opaque) 66 { 67 RTE_SET_USED(index); 68 RTE_SET_USED(value); 69 RTE_SET_USED(opaque); 70 return 0; 71 } 72 73 /* valid templater, must contain at least two args. */ 74 #define argparse_templater() { \ 75 .prog_name = "test_argparse", \ 76 .usage = "-a xx -b yy", \ 77 .descriptor = NULL, \ 78 .epilog = NULL, \ 79 .exit_on_error = false, \ 80 .callback = test_argparse_callback, \ 81 .args = { \ 82 { "--abc", "-a", "abc argument", (void *)1, (void *)1, RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_INT }, \ 83 { "--xyz", "-x", "xyz argument", (void *)1, (void *)2, RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_INT }, \ 84 ARGPARSE_ARG_END(), \ 85 }, \ 86 } 87 88 static void 89 test_argparse_copy(struct rte_argparse *dst, struct rte_argparse *src) 90 { 91 uint32_t i; 92 memcpy(dst, src, sizeof(*src)); 93 for (i = 0; /* NULL */; i++) { 94 memcpy(&dst->args[i], &src->args[i], sizeof(src->args[i])); 95 if (src->args[i].name_long == NULL) 96 break; 97 } 98 } 99 100 static struct rte_argparse * 101 test_argparse_init_obj(void) 102 { 103 static struct rte_argparse backup = argparse_templater(); 104 static struct rte_argparse obj = argparse_templater(); 105 /* Because obj may be overwritten, do a deep copy. */ 106 test_argparse_copy(&obj, &backup); 107 return &obj; 108 } 109 110 static int 111 test_argparse_invalid_basic_param(void) 112 { 113 struct rte_argparse *obj; 114 int ret; 115 116 obj = test_argparse_init_obj(); 117 obj->prog_name = NULL; 118 ret = rte_argparse_parse(obj, default_argc, default_argv); 119 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 120 121 obj = test_argparse_init_obj(); 122 obj->usage = NULL; 123 ret = rte_argparse_parse(obj, default_argc, default_argv); 124 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 125 126 return TEST_SUCCESS; 127 } 128 129 static int 130 test_argparse_invalid_arg_name(void) 131 { 132 struct rte_argparse *obj; 133 int ret; 134 135 obj = test_argparse_init_obj(); 136 obj->args[0].name_long = "-ab"; 137 ret = rte_argparse_parse(obj, default_argc, default_argv); 138 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 139 140 obj = test_argparse_init_obj(); 141 obj->args[0].name_long = "-abc"; 142 ret = rte_argparse_parse(obj, default_argc, default_argv); 143 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 144 145 obj = test_argparse_init_obj(); 146 obj->args[0].name_long = "---c"; 147 ret = rte_argparse_parse(obj, default_argc, default_argv); 148 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 149 150 obj = test_argparse_init_obj(); 151 obj->args[0].name_long = "abc"; 152 obj->args[0].name_short = "-a"; 153 ret = rte_argparse_parse(obj, default_argc, default_argv); 154 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 155 156 obj = test_argparse_init_obj(); 157 obj->args[0].name_short = "a"; 158 ret = rte_argparse_parse(obj, default_argc, default_argv); 159 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 160 161 obj = test_argparse_init_obj(); 162 obj->args[0].name_short = "abc"; 163 ret = rte_argparse_parse(obj, default_argc, default_argv); 164 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 165 166 obj = test_argparse_init_obj(); 167 obj->args[0].name_short = "ab"; 168 ret = rte_argparse_parse(obj, default_argc, default_argv); 169 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 170 171 return 0; 172 } 173 174 static int 175 test_argparse_invalid_arg_help(void) 176 { 177 struct rte_argparse *obj; 178 int ret; 179 180 obj = test_argparse_init_obj(); 181 obj->args[0].help = NULL; 182 ret = rte_argparse_parse(obj, default_argc, default_argv); 183 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 184 185 return 0; 186 } 187 188 static int 189 test_argparse_invalid_has_val(void) 190 { 191 uint64_t set_mask[] = { 0, 192 RTE_ARGPARSE_ARG_NO_VALUE, 193 RTE_ARGPARSE_ARG_OPTIONAL_VALUE 194 }; 195 struct rte_argparse *obj; 196 uint32_t index; 197 int ret; 198 199 obj = test_argparse_init_obj(); 200 obj->args[0].flags &= ~RTE_ARGPARSE_HAS_VAL_BITMASK; 201 ret = rte_argparse_parse(obj, default_argc, default_argv); 202 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 203 204 for (index = 0; index < RTE_DIM(set_mask); index++) { 205 obj = test_argparse_init_obj(); 206 obj->args[0].name_long = "abc"; 207 obj->args[0].name_short = NULL; 208 obj->args[0].flags &= ~RTE_ARGPARSE_HAS_VAL_BITMASK; 209 obj->args[0].flags |= set_mask[index]; 210 ret = rte_argparse_parse(obj, default_argc, default_argv); 211 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 212 } 213 214 return 0; 215 } 216 217 static int 218 test_argparse_invalid_arg_saver(void) 219 { 220 struct rte_argparse *obj; 221 int ret; 222 223 /* test saver == NULL with val-type != 0. */ 224 obj = test_argparse_init_obj(); 225 obj->args[0].val_saver = NULL; 226 obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_INT; 227 ret = rte_argparse_parse(obj, default_argc, default_argv); 228 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 229 230 /* test saver == NULL with callback is NULL. */ 231 obj = test_argparse_init_obj(); 232 obj->args[0].val_saver = NULL; 233 obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE; 234 obj->callback = NULL; 235 ret = rte_argparse_parse(obj, default_argc, default_argv); 236 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 237 238 /* test saver != NULL with val-type is zero! */ 239 obj = test_argparse_init_obj(); 240 obj->args[0].val_saver = (void *)1; 241 obj->args[0].val_set = (void *)1; 242 obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE; 243 ret = rte_argparse_parse(obj, default_argc, default_argv); 244 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 245 246 /* test saver != NULL with val-type is max. */ 247 obj = test_argparse_init_obj(); 248 obj->args[0].val_saver = (void *)1; 249 obj->args[0].val_set = (void *)1; 250 obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_MAX; 251 ret = rte_argparse_parse(obj, default_argc, default_argv); 252 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 253 254 /* test saver != NULL with required value, but val-set is not NULL. */ 255 obj = test_argparse_init_obj(); 256 obj->args[0].val_saver = (void *)1; 257 obj->args[0].val_set = (void *)1; 258 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT; 259 ret = rte_argparse_parse(obj, default_argc, default_argv); 260 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 261 262 return 0; 263 } 264 265 static int 266 test_argparse_invalid_arg_flags(void) 267 { 268 struct rte_argparse *obj; 269 int ret; 270 271 obj = test_argparse_init_obj(); 272 obj->args[0].flags |= ~(RTE_ARGPARSE_HAS_VAL_BITMASK | 273 RTE_ARGPARSE_VAL_TYPE_BITMASK | 274 RTE_ARGPARSE_ARG_SUPPORT_MULTI); 275 ret = rte_argparse_parse(obj, default_argc, default_argv); 276 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 277 278 obj = test_argparse_init_obj(); 279 obj->args[0].name_long = "positional"; 280 obj->args[0].name_short = NULL; 281 obj->args[0].val_saver = (void *)1; 282 obj->args[0].val_set = (void *)1; 283 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT | 284 RTE_ARGPARSE_ARG_SUPPORT_MULTI; 285 ret = rte_argparse_parse(obj, default_argc, default_argv); 286 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 287 288 obj = test_argparse_init_obj(); 289 obj->args[0].flags |= RTE_ARGPARSE_ARG_SUPPORT_MULTI; 290 ret = rte_argparse_parse(obj, default_argc, default_argv); 291 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 292 293 return 0; 294 } 295 296 static int 297 test_argparse_invalid_arg_repeat(void) 298 { 299 struct rte_argparse *obj; 300 int ret; 301 302 /* test for long name repeat! */ 303 obj = test_argparse_init_obj(); 304 obj->args[1].name_long = obj->args[0].name_long; 305 ret = rte_argparse_parse(obj, default_argc, default_argv); 306 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 307 308 /* test for short name repeat! */ 309 obj = test_argparse_init_obj(); 310 obj->args[1].name_short = obj->args[0].name_short; 311 ret = rte_argparse_parse(obj, default_argc, default_argv); 312 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 313 314 return 0; 315 } 316 317 static int 318 test_argparse_invalid_option(void) 319 { 320 struct rte_argparse *obj; 321 char *argv[2]; 322 int ret; 323 324 obj = test_argparse_init_obj(); 325 argv[0] = test_strdup(obj->usage); 326 argv[1] = test_strdup("--invalid"); 327 ret = rte_argparse_parse(obj, 2, argv); 328 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 329 330 obj = test_argparse_init_obj(); 331 argv[0] = test_strdup(obj->usage); 332 argv[1] = test_strdup("invalid"); 333 ret = rte_argparse_parse(obj, 2, argv); 334 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 335 336 return 0; 337 } 338 339 static int 340 test_argparse_opt_autosave_parse_int_of_no_val(void) 341 { 342 uint64_t flags = RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_INT; 343 struct rte_argparse *obj; 344 int val_saver = 0; 345 char *argv[2]; 346 int ret; 347 348 obj = test_argparse_init_obj(); 349 obj->args[0].name_long = "--test-long"; 350 obj->args[0].name_short = "-t"; 351 obj->args[0].val_saver = (void *)&val_saver; 352 obj->args[0].val_set = (void *)100; 353 obj->args[0].flags = flags; 354 obj->args[1].name_long = NULL; 355 argv[0] = test_strdup(obj->usage); 356 argv[1] = test_strdup("--test-long"); 357 ret = rte_argparse_parse(obj, 2, argv); 358 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 359 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 360 361 obj->args[0].flags = flags; 362 val_saver = 0; 363 argv[1] = test_strdup("-t"); 364 ret = rte_argparse_parse(obj, 2, argv); 365 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 366 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 367 368 return 0; 369 } 370 371 static int 372 test_argparse_opt_autosave_parse_int_of_required_val(void) 373 { 374 uint64_t flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT; 375 struct rte_argparse *obj; 376 int val_saver = 0; 377 char *argv[3]; 378 int ret; 379 380 obj = test_argparse_init_obj(); 381 obj->args[0].name_long = "--test-long"; 382 obj->args[0].name_short = "-t"; 383 obj->args[0].val_saver = (void *)&val_saver; 384 obj->args[0].val_set = NULL; 385 obj->args[0].flags = flags; 386 obj->args[1].name_long = NULL; 387 argv[0] = test_strdup(obj->usage); 388 argv[1] = test_strdup("--test-long"); 389 argv[2] = test_strdup("100"); 390 ret = rte_argparse_parse(obj, 3, argv); 391 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 392 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 393 394 obj->args[0].flags = flags; 395 val_saver = 0; 396 argv[1] = test_strdup("-t"); 397 ret = rte_argparse_parse(obj, 3, argv); 398 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 399 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 400 401 /* test invalid value. */ 402 obj->args[0].flags = flags; 403 val_saver = 0; 404 argv[1] = test_strdup("-t"); 405 argv[2] = test_strdup("100a"); 406 ret = rte_argparse_parse(obj, 3, argv); 407 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 408 409 return 0; 410 } 411 412 static int 413 test_argparse_opt_autosave_parse_int_of_optional_val(void) 414 { 415 uint64_t flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE | RTE_ARGPARSE_ARG_VALUE_INT; 416 struct rte_argparse *obj; 417 int val_saver = 0; 418 char *argv[2]; 419 int ret; 420 421 obj = test_argparse_init_obj(); 422 obj->args[0].name_long = "--test-long"; 423 obj->args[0].name_short = "-t"; 424 obj->args[0].val_saver = (void *)&val_saver; 425 obj->args[0].val_set = (void *)100; 426 obj->args[0].flags = flags; 427 obj->args[1].name_long = NULL; 428 argv[0] = test_strdup(obj->usage); 429 argv[1] = test_strdup("--test-long"); 430 ret = rte_argparse_parse(obj, 2, argv); 431 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 432 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 433 obj->args[0].flags = flags; 434 val_saver = 0; 435 argv[1] = test_strdup("-t"); 436 ret = rte_argparse_parse(obj, 2, argv); 437 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 438 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 439 440 /* test with value. */ 441 obj->args[0].flags = flags; 442 val_saver = 0; 443 argv[1] = test_strdup("--test-long=200"); 444 ret = rte_argparse_parse(obj, 2, argv); 445 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 446 TEST_ASSERT(val_saver == 200, "Argparse parse expect success!"); 447 obj->args[0].flags = flags; 448 val_saver = 0; 449 argv[1] = test_strdup("-t=200"); 450 ret = rte_argparse_parse(obj, 2, argv); 451 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 452 TEST_ASSERT(val_saver == 200, "Argparse parse expect success!"); 453 454 /* test with option value, but with wrong value. */ 455 obj->args[0].flags = flags; 456 val_saver = 0; 457 argv[1] = test_strdup("--test-long=200a"); 458 ret = rte_argparse_parse(obj, 2, argv); 459 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 460 obj->args[0].flags = flags; 461 val_saver = 0; 462 argv[1] = test_strdup("-t=200a"); 463 ret = rte_argparse_parse(obj, 2, argv); 464 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 465 466 return 0; 467 } 468 469 static int 470 opt_callback_parse_int_of_no_val(uint32_t index, const char *value, void *opaque) 471 { 472 RTE_SET_USED(index); 473 if (value != NULL) 474 return -EINVAL; 475 *(int *)opaque = 100; 476 return 0; 477 } 478 479 static int 480 test_argparse_opt_callback_parse_int_of_no_val(void) 481 { 482 struct rte_argparse *obj; 483 int val_saver = 0; 484 char *argv[2]; 485 int ret; 486 487 obj = test_argparse_init_obj(); 488 obj->callback = opt_callback_parse_int_of_no_val; 489 obj->opaque = (void *)&val_saver; 490 obj->args[0].name_long = "--test-long"; 491 obj->args[0].name_short = "-t"; 492 obj->args[0].val_saver = NULL; 493 obj->args[0].val_set = (void *)100; 494 obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE; 495 obj->args[1].name_long = NULL; 496 argv[0] = test_strdup(obj->usage); 497 argv[1] = test_strdup("--test-long"); 498 ret = rte_argparse_parse(obj, 2, argv); 499 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 500 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 501 502 obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE; 503 val_saver = 0; 504 argv[1] = test_strdup("-t"); 505 ret = rte_argparse_parse(obj, 2, argv); 506 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 507 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 508 509 return 0; 510 } 511 512 static int 513 opt_callback_parse_int_of_required_val(uint32_t index, const char *value, void *opaque) 514 { 515 char *s = NULL; 516 517 if (index != 1) 518 return -EINVAL; 519 520 if (value == NULL) 521 return -EINVAL; 522 *(int *)opaque = strtol(value, &s, 0); 523 524 if (s[0] != '\0') 525 return -EINVAL; 526 527 return 0; 528 } 529 530 static int 531 test_argparse_opt_callback_parse_int_of_required_val(void) 532 { 533 struct rte_argparse *obj; 534 int val_saver = 0; 535 char *argv[3]; 536 int ret; 537 538 obj = test_argparse_init_obj(); 539 obj->callback = opt_callback_parse_int_of_required_val; 540 obj->opaque = (void *)&val_saver; 541 obj->args[0].name_long = "--test-long"; 542 obj->args[0].name_short = "-t"; 543 obj->args[0].val_saver = NULL; 544 obj->args[0].val_set = (void *)1; 545 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 546 obj->args[1].name_long = NULL; 547 argv[0] = test_strdup(obj->usage); 548 argv[1] = test_strdup("--test-long"); 549 argv[2] = test_strdup("100"); 550 ret = rte_argparse_parse(obj, 3, argv); 551 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 552 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 553 554 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 555 val_saver = 0; 556 argv[1] = test_strdup("-t"); 557 ret = rte_argparse_parse(obj, 3, argv); 558 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 559 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 560 561 /* test no more parameters. */ 562 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 563 ret = rte_argparse_parse(obj, 2, argv); 564 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 565 566 /* test callback return failed. */ 567 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 568 argv[2] = test_strdup("100a"); 569 ret = rte_argparse_parse(obj, 3, argv); 570 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 571 572 return 0; 573 } 574 575 static int 576 opt_callback_parse_int_of_optional_val(uint32_t index, const char *value, void *opaque) 577 { 578 char *s = NULL; 579 580 if (index != 1) 581 return -EINVAL; 582 583 if (value == NULL) { 584 *(int *)opaque = 10; 585 } else { 586 *(int *)opaque = strtol(value, &s, 0); 587 if (s[0] != '\0') 588 return -EINVAL; 589 } 590 591 return 0; 592 } 593 594 static int 595 test_argparse_opt_callback_parse_int_of_optional_val(void) 596 { 597 struct rte_argparse *obj; 598 int val_saver = 0; 599 char *argv[2]; 600 int ret; 601 602 obj = test_argparse_init_obj(); 603 obj->callback = opt_callback_parse_int_of_optional_val; 604 obj->opaque = (void *)&val_saver; 605 obj->args[0].name_long = "--test-long"; 606 obj->args[0].name_short = "-t"; 607 obj->args[0].val_saver = NULL; 608 obj->args[0].val_set = (void *)1; 609 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 610 obj->args[1].name_long = NULL; 611 argv[0] = test_strdup(obj->usage); 612 argv[1] = test_strdup("--test-long"); 613 ret = rte_argparse_parse(obj, 2, argv); 614 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 615 TEST_ASSERT(val_saver == 10, "Argparse parse expect success!"); 616 617 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 618 val_saver = 0; 619 argv[1] = test_strdup("-t"); 620 ret = rte_argparse_parse(obj, 2, argv); 621 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 622 TEST_ASSERT(val_saver == 10, "Argparse parse expect success!"); 623 624 /* test with value. */ 625 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 626 val_saver = 0; 627 argv[1] = test_strdup("--test-long=100"); 628 ret = rte_argparse_parse(obj, 2, argv); 629 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 630 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 631 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 632 val_saver = 0; 633 argv[1] = test_strdup("-t=100"); 634 ret = rte_argparse_parse(obj, 2, argv); 635 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 636 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 637 638 /* test callback return failed. */ 639 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 640 argv[1] = test_strdup("-t=100a"); 641 ret = rte_argparse_parse(obj, 2, argv); 642 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 643 644 return 0; 645 } 646 647 static int 648 test_argparse_pos_autosave_parse_int(void) 649 { 650 uint64_t flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT; 651 struct rte_argparse *obj; 652 int val_saver = 0; 653 char *argv[3]; 654 int ret; 655 656 obj = test_argparse_init_obj(); 657 obj->args[0].name_long = "test-long"; 658 obj->args[0].name_short = NULL; 659 obj->args[0].val_saver = (void *)&val_saver; 660 obj->args[0].val_set = NULL; 661 obj->args[0].flags = flags; 662 obj->args[1].name_long = NULL; 663 argv[0] = test_strdup(obj->usage); 664 argv[1] = test_strdup("100"); 665 ret = rte_argparse_parse(obj, 2, argv); 666 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 667 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 668 669 obj->args[0].flags = flags; 670 val_saver = 0; 671 argv[1] = test_strdup("100a"); 672 ret = rte_argparse_parse(obj, 2, argv); 673 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 674 675 /* test over position parameters. */ 676 obj->args[0].flags = flags; 677 argv[1] = test_strdup("100"); 678 argv[2] = test_strdup("200"); 679 ret = rte_argparse_parse(obj, 3, argv); 680 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 681 682 return 0; 683 } 684 685 static int 686 pos_callback_parse_int(uint32_t index, const char *value, void *opaque) 687 { 688 uint32_t int_val; 689 char *s = NULL; 690 691 if (index != 1 && index != 2) 692 return -EINVAL; 693 if (value == NULL) 694 return -EINVAL; 695 696 int_val = strtol(value, &s, 0); 697 if (s[0] != '\0') 698 return -EINVAL; 699 700 *((int *)opaque + index) = int_val; 701 702 return 0; 703 } 704 705 static int 706 test_argparse_pos_callback_parse_int(void) 707 { 708 int val_saver[3] = { 0, 0, 0 }; 709 struct rte_argparse *obj; 710 char *argv[3]; 711 int ret; 712 713 obj = test_argparse_init_obj(); 714 obj->callback = pos_callback_parse_int; 715 obj->opaque = (void *)val_saver; 716 obj->args[0].name_long = "test-long1"; 717 obj->args[0].name_short = NULL; 718 obj->args[0].val_saver = NULL; 719 obj->args[0].val_set = (void *)1; 720 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 721 obj->args[1].name_long = "test-long2"; 722 obj->args[1].name_short = NULL; 723 obj->args[1].val_saver = NULL; 724 obj->args[1].val_set = (void *)2; 725 obj->args[1].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 726 obj->args[2].name_long = NULL; 727 argv[0] = test_strdup(obj->usage); 728 argv[1] = test_strdup("100"); 729 argv[2] = test_strdup("200"); 730 ret = rte_argparse_parse(obj, 3, argv); 731 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 732 TEST_ASSERT(val_saver[1] == 100, "Argparse parse expect success!"); 733 TEST_ASSERT(val_saver[2] == 200, "Argparse parse expect success!"); 734 735 /* test callback return failed. */ 736 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 737 obj->args[1].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 738 argv[2] = test_strdup("200a"); 739 ret = rte_argparse_parse(obj, 3, argv); 740 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 741 742 return 0; 743 } 744 745 static int 746 test_argparse_parse_type(void) 747 { 748 char *str_erange = test_strdup("9999999999999999999999999999999999"); 749 char *str_erange_u32 = test_strdup("4294967296"); 750 char *str_erange_u16 = test_strdup("65536"); 751 char *str_erange_u8 = test_strdup("256"); 752 char *str_invalid = test_strdup("1a"); 753 char *str_ok = test_strdup("123"); 754 uint16_t val_u16; 755 uint32_t val_u32; 756 uint64_t val_u64; 757 uint8_t val_u8; 758 int val_int; 759 int ret; 760 761 /* test for int parsing */ 762 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_INT, &val_int); 763 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 764 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_INT, &val_int); 765 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 766 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_INT, &val_int); 767 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 768 TEST_ASSERT(val_int == 123, "Argparse parse type expect failed!"); 769 770 /* test for u8 parsing */ 771 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8); 772 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 773 ret = rte_argparse_parse_type(str_erange_u8, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8); 774 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 775 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8); 776 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 777 val_u8 = 0; 778 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8); 779 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 780 TEST_ASSERT(val_u8 == 123, "Argparse parse type expect failed!"); 781 782 /* test for u16 parsing */ 783 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16); 784 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 785 ret = rte_argparse_parse_type(str_erange_u16, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16); 786 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 787 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16); 788 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 789 val_u16 = 0; 790 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16); 791 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 792 TEST_ASSERT(val_u16 == 123, "Argparse parse type expect failed!"); 793 794 /* test for u32 parsing */ 795 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32); 796 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 797 ret = rte_argparse_parse_type(str_erange_u32, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32); 798 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 799 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32); 800 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 801 val_u32 = 0; 802 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32); 803 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 804 TEST_ASSERT(val_u32 == 123, "Argparse parse type expect failed!"); 805 806 /* test for u64 parsing */ 807 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64); 808 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 809 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64); 810 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 811 val_u64 = 0; 812 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64); 813 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 814 TEST_ASSERT(val_u64 == 123, "Argparse parse type expect failed!"); 815 816 return 0; 817 } 818 819 static struct unit_test_suite argparse_test_suite = { 820 .suite_name = "Argparse Unit Test Suite", 821 .setup = test_argparse_setup, 822 .teardown = test_argparse_teardown, 823 .unit_test_cases = { 824 TEST_CASE(test_argparse_invalid_basic_param), 825 TEST_CASE(test_argparse_invalid_arg_name), 826 TEST_CASE(test_argparse_invalid_arg_help), 827 TEST_CASE(test_argparse_invalid_has_val), 828 TEST_CASE(test_argparse_invalid_arg_saver), 829 TEST_CASE(test_argparse_invalid_arg_flags), 830 TEST_CASE(test_argparse_invalid_arg_repeat), 831 TEST_CASE(test_argparse_invalid_option), 832 TEST_CASE(test_argparse_opt_autosave_parse_int_of_no_val), 833 TEST_CASE(test_argparse_opt_autosave_parse_int_of_required_val), 834 TEST_CASE(test_argparse_opt_autosave_parse_int_of_optional_val), 835 TEST_CASE(test_argparse_opt_callback_parse_int_of_no_val), 836 TEST_CASE(test_argparse_opt_callback_parse_int_of_required_val), 837 TEST_CASE(test_argparse_opt_callback_parse_int_of_optional_val), 838 TEST_CASE(test_argparse_pos_autosave_parse_int), 839 TEST_CASE(test_argparse_pos_callback_parse_int), 840 TEST_CASE(test_argparse_parse_type), 841 842 TEST_CASES_END() /**< NULL terminate unit test array */ 843 } 844 }; 845 846 static int 847 test_argparse(void) 848 { 849 return unit_test_suite_runner(&argparse_test_suite); 850 } 851 852 REGISTER_FAST_TEST(argparse_autotest, true, true, test_argparse); 853