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 uint32_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 &= ~0x3u; 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 &= ~0x3u; 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 |= ~0x107FFu; 273 ret = rte_argparse_parse(obj, default_argc, default_argv); 274 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 275 276 obj = test_argparse_init_obj(); 277 obj->args[0].name_long = "positional"; 278 obj->args[0].name_short = NULL; 279 obj->args[0].val_saver = (void *)1; 280 obj->args[0].val_set = (void *)1; 281 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT | 282 RTE_ARGPARSE_ARG_SUPPORT_MULTI; 283 ret = rte_argparse_parse(obj, default_argc, default_argv); 284 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 285 286 obj = test_argparse_init_obj(); 287 obj->args[0].flags |= RTE_ARGPARSE_ARG_SUPPORT_MULTI; 288 ret = rte_argparse_parse(obj, default_argc, default_argv); 289 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 290 291 obj = test_argparse_init_obj(); 292 obj->args[0].val_saver = NULL; 293 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_SUPPORT_MULTI; 294 obj->callback = NULL; 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->usage); 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->usage); 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 uint32_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->usage); 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 uint32_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->usage); 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 uint32_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 obj = test_argparse_init_obj(); 427 obj->args[0].name_long = "--test-long"; 428 obj->args[0].name_short = "-t"; 429 obj->args[0].val_saver = (void *)&val_saver; 430 obj->args[0].val_set = (void *)100; 431 obj->args[0].flags = flags; 432 obj->args[1].name_long = NULL; 433 argv[0] = test_strdup(obj->usage); 434 argv[1] = test_strdup("--test-long"); 435 ret = rte_argparse_parse(obj, 2, argv); 436 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 437 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 438 obj->args[0].flags = flags; 439 val_saver = 0; 440 argv[1] = test_strdup("-t"); 441 ret = rte_argparse_parse(obj, 2, argv); 442 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 443 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 444 445 /* test with value. */ 446 obj->args[0].flags = flags; 447 val_saver = 0; 448 argv[1] = test_strdup("--test-long=200"); 449 ret = rte_argparse_parse(obj, 2, argv); 450 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 451 TEST_ASSERT(val_saver == 200, "Argparse parse expect success!"); 452 obj->args[0].flags = flags; 453 val_saver = 0; 454 argv[1] = test_strdup("-t=200"); 455 ret = rte_argparse_parse(obj, 2, argv); 456 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 457 TEST_ASSERT(val_saver == 200, "Argparse parse expect success!"); 458 459 /* test with option value, but with wrong value. */ 460 obj->args[0].flags = flags; 461 val_saver = 0; 462 argv[1] = test_strdup("--test-long=200a"); 463 ret = rte_argparse_parse(obj, 2, argv); 464 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 465 obj->args[0].flags = flags; 466 val_saver = 0; 467 argv[1] = test_strdup("-t=200a"); 468 ret = rte_argparse_parse(obj, 2, argv); 469 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 470 471 return 0; 472 } 473 474 static int 475 opt_callback_parse_int_of_no_val(uint32_t index, const char *value, void *opaque) 476 { 477 RTE_SET_USED(index); 478 if (value != NULL) 479 return -EINVAL; 480 *(int *)opaque = 100; 481 return 0; 482 } 483 484 static int 485 test_argparse_opt_callback_parse_int_of_no_val(void) 486 { 487 struct rte_argparse *obj; 488 int val_saver = 0; 489 char *argv[2]; 490 int ret; 491 492 obj = test_argparse_init_obj(); 493 obj->callback = opt_callback_parse_int_of_no_val; 494 obj->opaque = (void *)&val_saver; 495 obj->args[0].name_long = "--test-long"; 496 obj->args[0].name_short = "-t"; 497 obj->args[0].val_saver = NULL; 498 obj->args[0].val_set = (void *)100; 499 obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE; 500 obj->args[1].name_long = NULL; 501 argv[0] = test_strdup(obj->usage); 502 argv[1] = test_strdup("--test-long"); 503 ret = rte_argparse_parse(obj, 2, argv); 504 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 505 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 506 507 obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE; 508 val_saver = 0; 509 argv[1] = test_strdup("-t"); 510 ret = rte_argparse_parse(obj, 2, argv); 511 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 512 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 513 514 return 0; 515 } 516 517 static int 518 opt_callback_parse_int_of_required_val(uint32_t index, const char *value, void *opaque) 519 { 520 char *s = NULL; 521 522 if (index != 1) 523 return -EINVAL; 524 525 if (value == NULL) 526 return -EINVAL; 527 *(int *)opaque = strtol(value, &s, 0); 528 529 if (s[0] != '\0') 530 return -EINVAL; 531 532 return 0; 533 } 534 535 static int 536 test_argparse_opt_callback_parse_int_of_required_val(void) 537 { 538 struct rte_argparse *obj; 539 int val_saver = 0; 540 char *argv[3]; 541 int ret; 542 543 obj = test_argparse_init_obj(); 544 obj->callback = opt_callback_parse_int_of_required_val; 545 obj->opaque = (void *)&val_saver; 546 obj->args[0].name_long = "--test-long"; 547 obj->args[0].name_short = "-t"; 548 obj->args[0].val_saver = NULL; 549 obj->args[0].val_set = (void *)1; 550 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 551 obj->args[1].name_long = NULL; 552 argv[0] = test_strdup(obj->usage); 553 argv[1] = test_strdup("--test-long"); 554 argv[2] = test_strdup("100"); 555 ret = rte_argparse_parse(obj, 3, argv); 556 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 557 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 558 559 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 560 val_saver = 0; 561 argv[1] = test_strdup("-t"); 562 ret = rte_argparse_parse(obj, 3, argv); 563 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 564 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 565 566 /* test no more parameters. */ 567 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 568 ret = rte_argparse_parse(obj, 2, argv); 569 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 570 571 /* test callback return failed. */ 572 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 573 argv[2] = test_strdup("100a"); 574 ret = rte_argparse_parse(obj, 3, argv); 575 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 576 577 return 0; 578 } 579 580 static int 581 opt_callback_parse_int_of_optional_val(uint32_t index, const char *value, void *opaque) 582 { 583 char *s = NULL; 584 585 if (index != 1) 586 return -EINVAL; 587 588 if (value == NULL) { 589 *(int *)opaque = 10; 590 } else { 591 *(int *)opaque = strtol(value, &s, 0); 592 if (s[0] != '\0') 593 return -EINVAL; 594 } 595 596 return 0; 597 } 598 599 static int 600 test_argparse_opt_callback_parse_int_of_optional_val(void) 601 { 602 struct rte_argparse *obj; 603 int val_saver = 0; 604 char *argv[2]; 605 int ret; 606 607 obj = test_argparse_init_obj(); 608 obj->callback = opt_callback_parse_int_of_optional_val; 609 obj->opaque = (void *)&val_saver; 610 obj->args[0].name_long = "--test-long"; 611 obj->args[0].name_short = "-t"; 612 obj->args[0].val_saver = NULL; 613 obj->args[0].val_set = (void *)1; 614 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 615 obj->args[1].name_long = NULL; 616 argv[0] = test_strdup(obj->usage); 617 argv[1] = test_strdup("--test-long"); 618 ret = rte_argparse_parse(obj, 2, argv); 619 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 620 TEST_ASSERT(val_saver == 10, "Argparse parse expect success!"); 621 622 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 623 val_saver = 0; 624 argv[1] = test_strdup("-t"); 625 ret = rte_argparse_parse(obj, 2, argv); 626 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 627 TEST_ASSERT(val_saver == 10, "Argparse parse expect success!"); 628 629 /* test with value. */ 630 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 631 val_saver = 0; 632 argv[1] = test_strdup("--test-long=100"); 633 ret = rte_argparse_parse(obj, 2, argv); 634 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 635 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 636 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 637 val_saver = 0; 638 argv[1] = test_strdup("-t=100"); 639 ret = rte_argparse_parse(obj, 2, argv); 640 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 641 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 642 643 /* test callback return failed. */ 644 obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE; 645 argv[1] = test_strdup("-t=100a"); 646 ret = rte_argparse_parse(obj, 2, argv); 647 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 648 649 return 0; 650 } 651 652 static int 653 test_argparse_pos_autosave_parse_int(void) 654 { 655 uint32_t flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT; 656 struct rte_argparse *obj; 657 int val_saver = 0; 658 char *argv[3]; 659 int ret; 660 661 obj = test_argparse_init_obj(); 662 obj->args[0].name_long = "test-long"; 663 obj->args[0].name_short = NULL; 664 obj->args[0].val_saver = (void *)&val_saver; 665 obj->args[0].val_set = NULL; 666 obj->args[0].flags = flags; 667 obj->args[1].name_long = NULL; 668 argv[0] = test_strdup(obj->usage); 669 argv[1] = test_strdup("100"); 670 ret = rte_argparse_parse(obj, 2, argv); 671 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 672 TEST_ASSERT(val_saver == 100, "Argparse parse expect success!"); 673 674 obj->args[0].flags = flags; 675 val_saver = 0; 676 argv[1] = test_strdup("100a"); 677 ret = rte_argparse_parse(obj, 2, argv); 678 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 679 680 /* test over position parameters. */ 681 obj->args[0].flags = flags; 682 argv[1] = test_strdup("100"); 683 argv[2] = test_strdup("200"); 684 ret = rte_argparse_parse(obj, 3, argv); 685 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 686 687 return 0; 688 } 689 690 static int 691 pos_callback_parse_int(uint32_t index, const char *value, void *opaque) 692 { 693 uint32_t int_val; 694 char *s = NULL; 695 696 if (index != 1 && index != 2) 697 return -EINVAL; 698 if (value == NULL) 699 return -EINVAL; 700 701 int_val = strtol(value, &s, 0); 702 if (s[0] != '\0') 703 return -EINVAL; 704 705 *((int *)opaque + index) = int_val; 706 707 return 0; 708 } 709 710 static int 711 test_argparse_pos_callback_parse_int(void) 712 { 713 int val_saver[3] = { 0, 0, 0 }; 714 struct rte_argparse *obj; 715 char *argv[3]; 716 int ret; 717 718 obj = test_argparse_init_obj(); 719 obj->callback = pos_callback_parse_int; 720 obj->opaque = (void *)val_saver; 721 obj->args[0].name_long = "test-long1"; 722 obj->args[0].name_short = NULL; 723 obj->args[0].val_saver = NULL; 724 obj->args[0].val_set = (void *)1; 725 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 726 obj->args[1].name_long = "test-long2"; 727 obj->args[1].name_short = NULL; 728 obj->args[1].val_saver = NULL; 729 obj->args[1].val_set = (void *)2; 730 obj->args[1].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 731 obj->args[2].name_long = NULL; 732 argv[0] = test_strdup(obj->usage); 733 argv[1] = test_strdup("100"); 734 argv[2] = test_strdup("200"); 735 ret = rte_argparse_parse(obj, 3, argv); 736 TEST_ASSERT(ret == 0, "Argparse parse expect success!"); 737 TEST_ASSERT(val_saver[1] == 100, "Argparse parse expect success!"); 738 TEST_ASSERT(val_saver[2] == 200, "Argparse parse expect success!"); 739 740 /* test callback return failed. */ 741 obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 742 obj->args[1].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE; 743 argv[2] = test_strdup("200a"); 744 ret = rte_argparse_parse(obj, 3, argv); 745 TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!"); 746 747 return 0; 748 } 749 750 static int 751 test_argparse_parse_type(void) 752 { 753 char *str_erange = test_strdup("9999999999999999999999999999999999"); 754 char *str_erange_u32 = test_strdup("4294967296"); 755 char *str_erange_u16 = test_strdup("65536"); 756 char *str_erange_u8 = test_strdup("256"); 757 char *str_invalid = test_strdup("1a"); 758 char *str_ok = test_strdup("123"); 759 uint16_t val_u16; 760 uint32_t val_u32; 761 uint64_t val_u64; 762 uint8_t val_u8; 763 int val_int; 764 int ret; 765 766 /* test for int parsing */ 767 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_INT, &val_int); 768 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 769 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_INT, &val_int); 770 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 771 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_INT, &val_int); 772 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 773 TEST_ASSERT(val_int == 123, "Argparse parse type expect failed!"); 774 775 /* test for u8 parsing */ 776 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8); 777 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 778 ret = rte_argparse_parse_type(str_erange_u8, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8); 779 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 780 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8); 781 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 782 val_u8 = 0; 783 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8); 784 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 785 TEST_ASSERT(val_u8 == 123, "Argparse parse type expect failed!"); 786 787 /* test for u16 parsing */ 788 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16); 789 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 790 ret = rte_argparse_parse_type(str_erange_u16, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16); 791 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 792 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16); 793 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 794 val_u16 = 0; 795 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16); 796 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 797 TEST_ASSERT(val_u16 == 123, "Argparse parse type expect failed!"); 798 799 /* test for u32 parsing */ 800 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32); 801 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 802 ret = rte_argparse_parse_type(str_erange_u32, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32); 803 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 804 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32); 805 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 806 val_u32 = 0; 807 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32); 808 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 809 TEST_ASSERT(val_u32 == 123, "Argparse parse type expect failed!"); 810 811 /* test for u64 parsing */ 812 ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64); 813 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 814 ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64); 815 TEST_ASSERT(ret != 0, "Argparse parse type expect failed!"); 816 val_u64 = 0; 817 ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64); 818 TEST_ASSERT(ret == 0, "Argparse parse type expect failed!"); 819 TEST_ASSERT(val_u64 == 123, "Argparse parse type expect failed!"); 820 821 return 0; 822 } 823 824 static struct unit_test_suite argparse_test_suite = { 825 .suite_name = "Argparse Unit Test Suite", 826 .setup = test_argparse_setup, 827 .teardown = test_argparse_teardown, 828 .unit_test_cases = { 829 TEST_CASE(test_argparse_invalid_basic_param), 830 TEST_CASE(test_argparse_invalid_arg_name), 831 TEST_CASE(test_argparse_invalid_arg_help), 832 TEST_CASE(test_argparse_invalid_has_val), 833 TEST_CASE(test_argparse_invalid_arg_saver), 834 TEST_CASE(test_argparse_invalid_arg_flags), 835 TEST_CASE(test_argparse_invalid_arg_repeat), 836 TEST_CASE(test_argparse_invalid_option), 837 TEST_CASE(test_argparse_opt_autosave_parse_int_of_no_val), 838 TEST_CASE(test_argparse_opt_autosave_parse_int_of_required_val), 839 TEST_CASE(test_argparse_opt_autosave_parse_int_of_optional_val), 840 TEST_CASE(test_argparse_opt_callback_parse_int_of_no_val), 841 TEST_CASE(test_argparse_opt_callback_parse_int_of_required_val), 842 TEST_CASE(test_argparse_opt_callback_parse_int_of_optional_val), 843 TEST_CASE(test_argparse_pos_autosave_parse_int), 844 TEST_CASE(test_argparse_pos_callback_parse_int), 845 TEST_CASE(test_argparse_parse_type), 846 847 TEST_CASES_END() /**< NULL terminate unit test array */ 848 } 849 }; 850 851 static int 852 test_argparse(void) 853 { 854 return unit_test_suite_runner(&argparse_test_suite); 855 } 856 857 REGISTER_FAST_TEST(argparse_autotest, true, true, test_argparse); 858