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 /* test optional arg don't config has-value. */ 200 obj = test_argparse_init_obj(); 201 obj->args[0].flags &= ~RTE_ARGPARSE_HAS_VAL_BITMASK; 202 ret = rte_argparse_parse(obj, default_argc, default_argv); 203 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 204 205 /* test positional arg don't config required-value. */ 206 for (index = 0; index < RTE_DIM(set_mask); index++) { 207 obj = test_argparse_init_obj(); 208 obj->args[0].name_long = "abc"; 209 obj->args[0].name_short = NULL; 210 obj->args[0].flags &= ~RTE_ARGPARSE_HAS_VAL_BITMASK; 211 obj->args[0].flags |= set_mask[index]; 212 ret = rte_argparse_parse(obj, default_argc, default_argv); 213 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 214 } 215 216 return 0; 217 } 218 219 static int 220 test_argparse_invalid_arg_saver(void) 221 { 222 struct rte_argparse *obj; 223 int ret; 224 225 /* test saver == NULL with val-type != 0. */ 226 obj = test_argparse_init_obj(); 227 obj->args[0].val_saver = NULL; 228 obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_INT; 229 ret = rte_argparse_parse(obj, default_argc, default_argv); 230 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 231 232 /* test saver == NULL with callback is NULL. */ 233 obj = test_argparse_init_obj(); 234 obj->args[0].val_saver = NULL; 235 obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE; 236 obj->callback = NULL; 237 ret = rte_argparse_parse(obj, default_argc, default_argv); 238 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 239 240 /* test saver != NULL with val-type is zero! */ 241 obj = test_argparse_init_obj(); 242 obj->args[0].val_saver = (void *)1; 243 obj->args[0].val_set = (void *)1; 244 obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE; 245 ret = rte_argparse_parse(obj, default_argc, default_argv); 246 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 247 248 /* test saver != NULL with val-type is max. */ 249 obj = test_argparse_init_obj(); 250 obj->args[0].val_saver = (void *)1; 251 obj->args[0].val_set = (void *)1; 252 obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_MAX; 253 ret = rte_argparse_parse(obj, default_argc, default_argv); 254 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 255 256 /* test saver != NULL with required value, but val-set is not NULL. */ 257 obj = test_argparse_init_obj(); 258 obj->args[0].val_saver = (void *)1; 259 obj->args[0].val_set = (void *)1; 260 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT; 261 ret = rte_argparse_parse(obj, default_argc, default_argv); 262 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 263 264 return 0; 265 } 266 267 static int 268 test_argparse_invalid_arg_flags(void) 269 { 270 struct rte_argparse *obj; 271 int ret; 272 273 /* test set unused bits. */ 274 obj = test_argparse_init_obj(); 275 obj->args[0].flags |= ~(RTE_ARGPARSE_HAS_VAL_BITMASK | 276 RTE_ARGPARSE_VAL_TYPE_BITMASK | 277 RTE_ARGPARSE_ARG_SUPPORT_MULTI); 278 ret = rte_argparse_parse(obj, default_argc, default_argv); 279 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 280 281 /* test positional arg should not config multiple. */ 282 obj = test_argparse_init_obj(); 283 obj->args[0].name_long = "positional"; 284 obj->args[0].name_short = NULL; 285 obj->args[0].val_saver = (void *)1; 286 obj->args[0].val_set = NULL; 287 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT | 288 RTE_ARGPARSE_ARG_SUPPORT_MULTI; 289 ret = rte_argparse_parse(obj, default_argc, default_argv); 290 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 291 292 /* test optional arg enabled multiple but prased by autosave. */ 293 obj = test_argparse_init_obj(); 294 obj->args[0].flags |= RTE_ARGPARSE_ARG_SUPPORT_MULTI; 295 ret = rte_argparse_parse(obj, default_argc, default_argv); 296 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 297 298 return 0; 299 } 300 301 static int 302 test_argparse_invalid_arg_repeat(void) 303 { 304 struct rte_argparse *obj; 305 int ret; 306 307 /* test for long name repeat! */ 308 obj = test_argparse_init_obj(); 309 obj->args[1].name_long = obj->args[0].name_long; 310 ret = rte_argparse_parse(obj, default_argc, default_argv); 311 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 312 313 /* test for short name repeat! */ 314 obj = test_argparse_init_obj(); 315 obj->args[1].name_short = obj->args[0].name_short; 316 ret = rte_argparse_parse(obj, default_argc, default_argv); 317 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 318 319 return 0; 320 } 321 322 static int 323 test_argparse_invalid_option(void) 324 { 325 struct rte_argparse *obj; 326 char *argv[2]; 327 int ret; 328 329 obj = test_argparse_init_obj(); 330 argv[0] = test_strdup(obj->prog_name); 331 argv[1] = test_strdup("--invalid"); 332 ret = rte_argparse_parse(obj, 2, argv); 333 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 334 335 obj = test_argparse_init_obj(); 336 argv[0] = test_strdup(obj->prog_name); 337 argv[1] = test_strdup("invalid"); 338 ret = rte_argparse_parse(obj, 2, argv); 339 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 340 341 return 0; 342 } 343 344 static int 345 test_argparse_opt_autosave_parse_int_of_no_val(void) 346 { 347 uint64_t flags = RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_INT; 348 struct rte_argparse *obj; 349 int val_saver = 0; 350 char *argv[2]; 351 int ret; 352 353 obj = test_argparse_init_obj(); 354 obj->args[0].name_long = "--test-long"; 355 obj->args[0].name_short = "-t"; 356 obj->args[0].val_saver = (void *)&val_saver; 357 obj->args[0].val_set = (void *)100; 358 obj->args[0].flags = flags; 359 obj->args[1].name_long = NULL; 360 argv[0] = test_strdup(obj->prog_name); 361 argv[1] = test_strdup("--test-long"); 362 ret = rte_argparse_parse(obj, 2, argv); 363 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 364 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 365 366 obj->args[0].flags = flags; 367 val_saver = 0; 368 argv[1] = test_strdup("-t"); 369 ret = rte_argparse_parse(obj, 2, argv); 370 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 371 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 372 373 return 0; 374 } 375 376 static int 377 test_argparse_opt_autosave_parse_int_of_required_val(void) 378 { 379 uint64_t flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT; 380 struct rte_argparse *obj; 381 int val_saver = 0; 382 char *argv[3]; 383 int ret; 384 385 obj = test_argparse_init_obj(); 386 obj->args[0].name_long = "--test-long"; 387 obj->args[0].name_short = "-t"; 388 obj->args[0].val_saver = (void *)&val_saver; 389 obj->args[0].val_set = NULL; 390 obj->args[0].flags = flags; 391 obj->args[1].name_long = NULL; 392 argv[0] = test_strdup(obj->prog_name); 393 argv[1] = test_strdup("--test-long"); 394 argv[2] = test_strdup("100"); 395 ret = rte_argparse_parse(obj, 3, argv); 396 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 397 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 398 399 obj->args[0].flags = flags; 400 val_saver = 0; 401 argv[1] = test_strdup("-t"); 402 ret = rte_argparse_parse(obj, 3, argv); 403 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 404 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 405 406 /* test invalid value. */ 407 obj->args[0].flags = flags; 408 val_saver = 0; 409 argv[1] = test_strdup("-t"); 410 argv[2] = test_strdup("100a"); 411 ret = rte_argparse_parse(obj, 3, argv); 412 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 413 414 return 0; 415 } 416 417 static int 418 test_argparse_opt_autosave_parse_int_of_optional_val(void) 419 { 420 uint64_t flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE | RTE_ARGPARSE_ARG_VALUE_INT; 421 struct rte_argparse *obj; 422 int val_saver = 0; 423 char *argv[2]; 424 int ret; 425 426 /* test without value. */ 427 obj = test_argparse_init_obj(); 428 obj->args[0].name_long = "--test-long"; 429 obj->args[0].name_short = "-t"; 430 obj->args[0].val_saver = (void *)&val_saver; 431 obj->args[0].val_set = (void *)100; 432 obj->args[0].flags = flags; 433 obj->args[1].name_long = NULL; 434 argv[0] = test_strdup(obj->prog_name); 435 argv[1] = test_strdup("--test-long"); 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 obj->args[0].flags = flags; 440 val_saver = 0; 441 argv[1] = test_strdup("-t"); 442 ret = rte_argparse_parse(obj, 2, argv); 443 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 444 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 445 446 /* test with value. */ 447 obj->args[0].flags = flags; 448 val_saver = 0; 449 argv[1] = test_strdup("--test-long=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 obj->args[0].flags = flags; 454 val_saver = 0; 455 argv[1] = test_strdup("-t=200"); 456 ret = rte_argparse_parse(obj, 2, argv); 457 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 458 TEST_ASSERT(val_saver == 200, "Argparse parse expect success!"); 459 460 /* test with option value, but with wrong value. */ 461 obj->args[0].flags = flags; 462 val_saver = 0; 463 argv[1] = test_strdup("--test-long=200a"); 464 ret = rte_argparse_parse(obj, 2, argv); 465 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 466 obj->args[0].flags = flags; 467 val_saver = 0; 468 argv[1] = test_strdup("-t=200a"); 469 ret = rte_argparse_parse(obj, 2, argv); 470 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 471 472 return 0; 473 } 474 475 static int 476 opt_callback_parse_int_of_no_val(uint32_t index, const char *value, void *opaque) 477 { 478 if (index != 1) 479 return -EINVAL; 480 if (value != NULL) 481 return -EINVAL; 482 *(int *)opaque = 100; 483 return 0; 484 } 485 486 static int 487 test_argparse_opt_callback_parse_int_of_no_val(void) 488 { 489 struct rte_argparse *obj; 490 int val_saver = 0; 491 char *argv[2]; 492 int ret; 493 494 obj = test_argparse_init_obj(); 495 obj->callback = opt_callback_parse_int_of_no_val; 496 obj->opaque = (void *)&val_saver; 497 obj->args[0].name_long = "--test-long"; 498 obj->args[0].name_short = "-t"; 499 obj->args[0].val_saver = NULL; 500 obj->args[0].val_set = (void *)1; 501 obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE; 502 obj->args[1].name_long = NULL; 503 argv[0] = test_strdup(obj->prog_name); 504 argv[1] = test_strdup("--test-long"); 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 obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE; 510 val_saver = 0; 511 argv[1] = test_strdup("-t"); 512 ret = rte_argparse_parse(obj, 2, argv); 513 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 514 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 515 516 return 0; 517 } 518 519 static int 520 opt_callback_parse_int_of_required_val(uint32_t index, const char *value, void *opaque) 521 { 522 char *s = NULL; 523 524 if (index != 1) 525 return -EINVAL; 526 527 if (value == NULL) 528 return -EINVAL; 529 *(int *)opaque = strtol(value, &s, 0); 530 531 if (s[0] != '\0') 532 return -EINVAL; 533 534 return 0; 535 } 536 537 static int 538 test_argparse_opt_callback_parse_int_of_required_val(void) 539 { 540 struct rte_argparse *obj; 541 int val_saver = 0; 542 char *argv[3]; 543 int ret; 544 545 obj = test_argparse_init_obj(); 546 obj->callback = opt_callback_parse_int_of_required_val; 547 obj->opaque = (void *)&val_saver; 548 obj->args[0].name_long = "--test-long"; 549 obj->args[0].name_short = "-t"; 550 obj->args[0].val_saver = NULL; 551 obj->args[0].val_set = (void *)1; 552 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 553 obj->args[1].name_long = NULL; 554 argv[0] = test_strdup(obj->prog_name); 555 argv[1] = test_strdup("--test-long"); 556 argv[2] = test_strdup("100"); 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 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 562 val_saver = 0; 563 argv[1] = test_strdup("-t"); 564 ret = rte_argparse_parse(obj, 3, argv); 565 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 566 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 567 568 /* test no more parameters. */ 569 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 570 ret = rte_argparse_parse(obj, 2, argv); 571 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 572 573 /* test callback return failed. */ 574 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 575 argv[2] = test_strdup("100a"); 576 ret = rte_argparse_parse(obj, 3, argv); 577 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 578 579 return 0; 580 } 581 582 static int 583 opt_callback_parse_int_of_optional_val(uint32_t index, const char *value, void *opaque) 584 { 585 char *s = NULL; 586 587 if (index != 1) 588 return -EINVAL; 589 590 if (value == NULL) { 591 *(int *)opaque = 10; 592 } else { 593 *(int *)opaque = strtol(value, &s, 0); 594 if (s[0] != '\0') 595 return -EINVAL; 596 } 597 598 return 0; 599 } 600 601 static int 602 test_argparse_opt_callback_parse_int_of_optional_val(void) 603 { 604 struct rte_argparse *obj; 605 int val_saver = 0; 606 char *argv[2]; 607 int ret; 608 609 obj = test_argparse_init_obj(); 610 obj->callback = opt_callback_parse_int_of_optional_val; 611 obj->opaque = (void *)&val_saver; 612 obj->args[0].name_long = "--test-long"; 613 obj->args[0].name_short = "-t"; 614 obj->args[0].val_saver = NULL; 615 obj->args[0].val_set = (void *)1; 616 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 617 obj->args[1].name_long = NULL; 618 argv[0] = test_strdup(obj->prog_name); 619 argv[1] = test_strdup("--test-long"); 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 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 625 val_saver = 0; 626 argv[1] = test_strdup("-t"); 627 ret = rte_argparse_parse(obj, 2, argv); 628 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 629 TEST_ASSERT(val_saver == 10, "Argparse parse expect success!"); 630 631 /* test with value. */ 632 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 633 val_saver = 0; 634 argv[1] = test_strdup("--test-long=100"); 635 ret = rte_argparse_parse(obj, 2, argv); 636 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 637 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 638 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 639 val_saver = 0; 640 argv[1] = test_strdup("-t=100"); 641 ret = rte_argparse_parse(obj, 2, argv); 642 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 643 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 644 645 /* test callback return failed. */ 646 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 647 argv[1] = test_strdup("-t=100a"); 648 ret = rte_argparse_parse(obj, 2, argv); 649 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 650 651 return 0; 652 } 653 654 static int 655 test_argparse_pos_autosave_parse_int(void) 656 { 657 uint64_t flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT; 658 struct rte_argparse *obj; 659 int val_saver = 0; 660 char *argv[3]; 661 int ret; 662 663 /* test positional autosave parse successful. */ 664 obj = test_argparse_init_obj(); 665 obj->args[0].name_long = "test-long"; 666 obj->args[0].name_short = NULL; 667 obj->args[0].val_saver = (void *)&val_saver; 668 obj->args[0].val_set = NULL; 669 obj->args[0].flags = flags; 670 obj->args[1].name_long = NULL; 671 argv[0] = test_strdup(obj->prog_name); 672 argv[1] = test_strdup("100"); 673 ret = rte_argparse_parse(obj, 2, argv); 674 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 675 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 676 677 /* test positional autosave parse failed. */ 678 obj->args[0].flags = flags; 679 val_saver = 0; 680 argv[1] = test_strdup("100a"); 681 ret = rte_argparse_parse(obj, 2, argv); 682 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 683 684 /* test too much position parameters. */ 685 obj->args[0].flags = flags; 686 argv[1] = test_strdup("100"); 687 argv[2] = test_strdup("200"); 688 ret = rte_argparse_parse(obj, 3, argv); 689 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 690 691 return 0; 692 } 693 694 static int 695 pos_callback_parse_int(uint32_t index, const char *value, void *opaque) 696 { 697 uint32_t int_val; 698 char *s = NULL; 699 700 if (index != 1 && index != 2) 701 return -EINVAL; 702 if (value == NULL) 703 return -EINVAL; 704 705 int_val = strtol(value, &s, 0); 706 if (s[0] != '\0') 707 return -EINVAL; 708 709 *((int *)opaque + index) = int_val; 710 711 return 0; 712 } 713 714 static int 715 test_argparse_pos_callback_parse_int(void) 716 { 717 int val_saver[3] = { 0, 0, 0 }; 718 struct rte_argparse *obj; 719 char *argv[3]; 720 int ret; 721 722 /* test positional callback parse successful. */ 723 obj = test_argparse_init_obj(); 724 obj->callback = pos_callback_parse_int; 725 obj->opaque = (void *)val_saver; 726 obj->args[0].name_long = "test-long1"; 727 obj->args[0].name_short = NULL; 728 obj->args[0].val_saver = NULL; 729 obj->args[0].val_set = (void *)1; 730 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 731 obj->args[1].name_long = "test-long2"; 732 obj->args[1].name_short = NULL; 733 obj->args[1].val_saver = NULL; 734 obj->args[1].val_set = (void *)2; 735 obj->args[1].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 736 obj->args[2].name_long = NULL; 737 argv[0] = test_strdup(obj->prog_name); 738 argv[1] = test_strdup("100"); 739 argv[2] = test_strdup("200"); 740 ret = rte_argparse_parse(obj, 3, argv); 741 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 742 TEST_ASSERT(val_saver[1] == 100, "Argparse parse expect success!"); 743 TEST_ASSERT(val_saver[2] == 200, "Argparse parse expect success!"); 744 745 /* test positional callback parse failed. */ 746 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 747 obj->args[1].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 748 argv[2] = test_strdup("200a"); 749 ret = rte_argparse_parse(obj, 3, argv); 750 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 751 752 return 0; 753 } 754 755 static int 756 test_argparse_parse_type(void) 757 { 758 char *str_erange = test_strdup("9999999999999999999999999999999999"); 759 char *str_erange_u32 = test_strdup("4294967296"); 760 char *str_erange_u16 = test_strdup("65536"); 761 char *str_erange_u8 = test_strdup("256"); 762 char *str_invalid = test_strdup("1a"); 763 char *str_ok = test_strdup("123"); 764 uint16_t val_u16; 765 uint32_t val_u32; 766 uint64_t val_u64; 767 uint8_t val_u8; 768 int val_int; 769 int ret; 770 771 /* test for int parsing */ 772 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_INT, &val_int); 773 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 774 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_INT, &val_int); 775 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 776 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_INT, &val_int); 777 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 778 TEST_ASSERT(val_int == 123, "Argparse parse type expect failed!"); 779 780 /* test for u8 parsing */ 781 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8); 782 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 783 ret = rte_argparse_parse_type(str_erange_u8, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8); 784 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 785 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8); 786 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 787 val_u8 = 0; 788 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8); 789 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 790 TEST_ASSERT(val_u8 == 123, "Argparse parse type expect failed!"); 791 792 /* test for u16 parsing */ 793 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16); 794 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 795 ret = rte_argparse_parse_type(str_erange_u16, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16); 796 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 797 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16); 798 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 799 val_u16 = 0; 800 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16); 801 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 802 TEST_ASSERT(val_u16 == 123, "Argparse parse type expect failed!"); 803 804 /* test for u32 parsing */ 805 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32); 806 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 807 ret = rte_argparse_parse_type(str_erange_u32, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32); 808 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 809 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32); 810 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 811 val_u32 = 0; 812 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32); 813 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 814 TEST_ASSERT(val_u32 == 123, "Argparse parse type expect failed!"); 815 816 /* test for u64 parsing */ 817 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64); 818 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 819 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64); 820 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 821 val_u64 = 0; 822 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64); 823 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 824 TEST_ASSERT(val_u64 == 123, "Argparse parse type expect failed!"); 825 826 return 0; 827 } 828 829 static struct unit_test_suite argparse_test_suite = { 830 .suite_name = "Argparse Unit Test Suite", 831 .setup = test_argparse_setup, 832 .teardown = test_argparse_teardown, 833 .unit_test_cases = { 834 TEST_CASE(test_argparse_invalid_basic_param), 835 TEST_CASE(test_argparse_invalid_arg_name), 836 TEST_CASE(test_argparse_invalid_arg_help), 837 TEST_CASE(test_argparse_invalid_has_val), 838 TEST_CASE(test_argparse_invalid_arg_saver), 839 TEST_CASE(test_argparse_invalid_arg_flags), 840 TEST_CASE(test_argparse_invalid_arg_repeat), 841 TEST_CASE(test_argparse_invalid_option), 842 TEST_CASE(test_argparse_opt_autosave_parse_int_of_no_val), 843 TEST_CASE(test_argparse_opt_autosave_parse_int_of_required_val), 844 TEST_CASE(test_argparse_opt_autosave_parse_int_of_optional_val), 845 TEST_CASE(test_argparse_opt_callback_parse_int_of_no_val), 846 TEST_CASE(test_argparse_opt_callback_parse_int_of_required_val), 847 TEST_CASE(test_argparse_opt_callback_parse_int_of_optional_val), 848 TEST_CASE(test_argparse_pos_autosave_parse_int), 849 TEST_CASE(test_argparse_pos_callback_parse_int), 850 TEST_CASE(test_argparse_parse_type), 851 852 TEST_CASES_END() /**< NULL terminate unit test array */ 853 } 854 }; 855 856 static int 857 test_argparse(void) 858 { 859 return unit_test_suite_runner(&argparse_test_suite); 860 } 861 862 REGISTER_FAST_TEST(argparse_autotest, true, true, test_argparse); 863