xref: /dpdk/app/test/test_argparse.c (revision 9684dfeae3284ec93a56090e653fb74886d5a40e)
16c5c6571SChengwen Feng /* SPDX-License-Identifier: BSD-3-Clause
26c5c6571SChengwen Feng  * Copyright(c) 2024 HiSilicon Limited
36c5c6571SChengwen Feng  */
46c5c6571SChengwen Feng 
56c5c6571SChengwen Feng #include <stdio.h>
66c5c6571SChengwen Feng #include <string.h>
76c5c6571SChengwen Feng 
86c5c6571SChengwen Feng #include <rte_argparse.h>
96c5c6571SChengwen Feng 
106c5c6571SChengwen Feng #include "test.h"
116c5c6571SChengwen Feng 
126c5c6571SChengwen Feng static int default_argc;
136c5c6571SChengwen Feng static char *default_argv[1];
146c5c6571SChengwen Feng 
156c5c6571SChengwen Feng #define MAX_STRDUP_STORE_NUM	512
166c5c6571SChengwen Feng static char *strdup_store_array[MAX_STRDUP_STORE_NUM];
176c5c6571SChengwen Feng static uint32_t strdup_store_index;
186c5c6571SChengwen Feng 
196c5c6571SChengwen Feng /*
206c5c6571SChengwen Feng  * Define strdup wrapper.
216c5c6571SChengwen Feng  * 1. Mainly to fix compile error "warning: assignment discards 'const'
226c5c6571SChengwen Feng  *    qualifier from pointer target type [-Wdiscarded-qualifiers]" for
236c5c6571SChengwen Feng  *    following code:
246c5c6571SChengwen Feng  *      argv[x] = "100";
256c5c6571SChengwen Feng  * 2. The strdup result will store in the strdup_store_array, and then
266c5c6571SChengwen Feng  *    freed in the teardown function, prevent ASAN errors from being
276c5c6571SChengwen Feng  *    triggered.
286c5c6571SChengwen Feng  */
296c5c6571SChengwen Feng static char *
306c5c6571SChengwen Feng test_strdup(const char *str)
316c5c6571SChengwen Feng {
326c5c6571SChengwen Feng 	char *s = strdup(str);
336c5c6571SChengwen Feng 	if (s == NULL) {
346c5c6571SChengwen Feng 		printf("strdup failed! exiting...\n");
356c5c6571SChengwen Feng 		exit(-ENOMEM);
366c5c6571SChengwen Feng 	}
376c5c6571SChengwen Feng 	if (strdup_store_index >= MAX_STRDUP_STORE_NUM) {
386c5c6571SChengwen Feng 		printf("too much strdup calls! exiting...\n");
396c5c6571SChengwen Feng 		exit(-ERANGE);
406c5c6571SChengwen Feng 	}
416c5c6571SChengwen Feng 	strdup_store_array[strdup_store_index++] = s;
426c5c6571SChengwen Feng 	return s;
436c5c6571SChengwen Feng }
446c5c6571SChengwen Feng 
456c5c6571SChengwen Feng static int
466c5c6571SChengwen Feng test_argparse_setup(void)
476c5c6571SChengwen Feng {
486c5c6571SChengwen Feng 	strdup_store_index = 0;
496c5c6571SChengwen Feng 	default_argc = 1;
506c5c6571SChengwen Feng 	default_argv[0] = test_strdup("test_argparse");
516c5c6571SChengwen Feng 	return 0;
526c5c6571SChengwen Feng }
536c5c6571SChengwen Feng 
546c5c6571SChengwen Feng static void
556c5c6571SChengwen Feng test_argparse_teardown(void)
566c5c6571SChengwen Feng {
576c5c6571SChengwen Feng 	uint32_t i;
586c5c6571SChengwen Feng 	printf("total used strdup_store_index = %u\n", strdup_store_index);
596c5c6571SChengwen Feng 	for (i = 0; i < strdup_store_index; i++)
606c5c6571SChengwen Feng 		free(strdup_store_array[i]);
616c5c6571SChengwen Feng 	strdup_store_index = 0;
626c5c6571SChengwen Feng }
636c5c6571SChengwen Feng 
646c5c6571SChengwen Feng static int
656c5c6571SChengwen Feng test_argparse_callback(uint32_t index, const char *value, void *opaque)
666c5c6571SChengwen Feng {
676c5c6571SChengwen Feng 	RTE_SET_USED(index);
686c5c6571SChengwen Feng 	RTE_SET_USED(value);
696c5c6571SChengwen Feng 	RTE_SET_USED(opaque);
706c5c6571SChengwen Feng 	return 0;
716c5c6571SChengwen Feng }
726c5c6571SChengwen Feng 
736c5c6571SChengwen Feng /* valid templater, must contain at least two args. */
746c5c6571SChengwen Feng #define argparse_templater() { \
756c5c6571SChengwen Feng 	.prog_name = "test_argparse", \
766c5c6571SChengwen Feng 	.usage = "-a xx -b yy", \
776c5c6571SChengwen Feng 	.descriptor = NULL, \
786c5c6571SChengwen Feng 	.epilog = NULL, \
796c5c6571SChengwen Feng 	.exit_on_error = false, \
806c5c6571SChengwen Feng 	.callback = test_argparse_callback, \
816c5c6571SChengwen Feng 	.args = { \
826c5c6571SChengwen Feng 		{ "--abc", "-a", "abc argument", (void *)1, (void *)1, RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_INT }, \
836c5c6571SChengwen Feng 		{ "--xyz", "-x", "xyz argument", (void *)1, (void *)2, RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_INT }, \
846c5c6571SChengwen Feng 		ARGPARSE_ARG_END(), \
856c5c6571SChengwen Feng 	}, \
866c5c6571SChengwen Feng }
876c5c6571SChengwen Feng 
886c5c6571SChengwen Feng static void
896c5c6571SChengwen Feng test_argparse_copy(struct rte_argparse *dst, struct rte_argparse *src)
906c5c6571SChengwen Feng {
916c5c6571SChengwen Feng 	uint32_t i;
926c5c6571SChengwen Feng 	memcpy(dst, src, sizeof(*src));
936c5c6571SChengwen Feng 	for (i = 0; /* NULL */; i++) {
946c5c6571SChengwen Feng 		memcpy(&dst->args[i], &src->args[i], sizeof(src->args[i]));
956c5c6571SChengwen Feng 		if (src->args[i].name_long == NULL)
966c5c6571SChengwen Feng 			break;
976c5c6571SChengwen Feng 	}
986c5c6571SChengwen Feng }
996c5c6571SChengwen Feng 
1006c5c6571SChengwen Feng static struct rte_argparse *
1016c5c6571SChengwen Feng test_argparse_init_obj(void)
1026c5c6571SChengwen Feng {
1036c5c6571SChengwen Feng 	static struct rte_argparse backup = argparse_templater();
1046c5c6571SChengwen Feng 	static struct rte_argparse obj = argparse_templater();
1056c5c6571SChengwen Feng 	/* Because obj may be overwritten, do a deep copy. */
1066c5c6571SChengwen Feng 	test_argparse_copy(&obj, &backup);
1076c5c6571SChengwen Feng 	return &obj;
1086c5c6571SChengwen Feng }
1096c5c6571SChengwen Feng 
1106c5c6571SChengwen Feng static int
1116c5c6571SChengwen Feng test_argparse_invalid_basic_param(void)
1126c5c6571SChengwen Feng {
1136c5c6571SChengwen Feng 	struct rte_argparse *obj;
1146c5c6571SChengwen Feng 	int ret;
1156c5c6571SChengwen Feng 
1166c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
1176c5c6571SChengwen Feng 	obj->prog_name = NULL;
1186c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
1196c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
1206c5c6571SChengwen Feng 
1216c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
1226c5c6571SChengwen Feng 	obj->usage = NULL;
1236c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
1246c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
1256c5c6571SChengwen Feng 
1266c5c6571SChengwen Feng 	return TEST_SUCCESS;
1276c5c6571SChengwen Feng }
1286c5c6571SChengwen Feng 
1296c5c6571SChengwen Feng static int
1306c5c6571SChengwen Feng test_argparse_invalid_arg_name(void)
1316c5c6571SChengwen Feng {
1326c5c6571SChengwen Feng 	struct rte_argparse *obj;
1336c5c6571SChengwen Feng 	int ret;
1346c5c6571SChengwen Feng 
1356c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
1366c5c6571SChengwen Feng 	obj->args[0].name_long = "-ab";
1376c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
1386c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
1396c5c6571SChengwen Feng 
1406c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
1416c5c6571SChengwen Feng 	obj->args[0].name_long = "-abc";
1426c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
1436c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
1446c5c6571SChengwen Feng 
1456c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
1466c5c6571SChengwen Feng 	obj->args[0].name_long = "---c";
1476c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
1486c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
1496c5c6571SChengwen Feng 
1506c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
1516c5c6571SChengwen Feng 	obj->args[0].name_long = "abc";
1526c5c6571SChengwen Feng 	obj->args[0].name_short = "-a";
1536c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
1546c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
1556c5c6571SChengwen Feng 
1566c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
1576c5c6571SChengwen Feng 	obj->args[0].name_short = "a";
1586c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
1596c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
1606c5c6571SChengwen Feng 
1616c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
1626c5c6571SChengwen Feng 	obj->args[0].name_short = "abc";
1636c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
1646c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
1656c5c6571SChengwen Feng 
1666c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
1676c5c6571SChengwen Feng 	obj->args[0].name_short = "ab";
1686c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
1696c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
1706c5c6571SChengwen Feng 
1716c5c6571SChengwen Feng 	return 0;
1726c5c6571SChengwen Feng }
1736c5c6571SChengwen Feng 
1746c5c6571SChengwen Feng static int
1756c5c6571SChengwen Feng test_argparse_invalid_arg_help(void)
1766c5c6571SChengwen Feng {
1776c5c6571SChengwen Feng 	struct rte_argparse *obj;
1786c5c6571SChengwen Feng 	int ret;
1796c5c6571SChengwen Feng 
1806c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
1816c5c6571SChengwen Feng 	obj->args[0].help = NULL;
1826c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
1836c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
1846c5c6571SChengwen Feng 
1856c5c6571SChengwen Feng 	return 0;
1866c5c6571SChengwen Feng }
1876c5c6571SChengwen Feng 
1886c5c6571SChengwen Feng static int
1896c5c6571SChengwen Feng test_argparse_invalid_has_val(void)
1906c5c6571SChengwen Feng {
191f48e4eedSChengwen Feng 	uint64_t set_mask[] = { 0,
1926c5c6571SChengwen Feng 				RTE_ARGPARSE_ARG_NO_VALUE,
1936c5c6571SChengwen Feng 				RTE_ARGPARSE_ARG_OPTIONAL_VALUE
1946c5c6571SChengwen Feng 			      };
1956c5c6571SChengwen Feng 	struct rte_argparse *obj;
1966c5c6571SChengwen Feng 	uint32_t index;
1976c5c6571SChengwen Feng 	int ret;
1986c5c6571SChengwen Feng 
199*9684dfeaSChengwen Feng 	/* test optional arg don't config has-value. */
2006c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
201f48e4eedSChengwen Feng 	obj->args[0].flags &= ~RTE_ARGPARSE_HAS_VAL_BITMASK;
2026c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
2036c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
2046c5c6571SChengwen Feng 
205*9684dfeaSChengwen Feng 	/* test positional arg don't config required-value. */
2066c5c6571SChengwen Feng 	for (index = 0; index < RTE_DIM(set_mask); index++) {
2076c5c6571SChengwen Feng 		obj = test_argparse_init_obj();
2086c5c6571SChengwen Feng 		obj->args[0].name_long = "abc";
2096c5c6571SChengwen Feng 		obj->args[0].name_short = NULL;
210f48e4eedSChengwen Feng 		obj->args[0].flags &= ~RTE_ARGPARSE_HAS_VAL_BITMASK;
2116c5c6571SChengwen Feng 		obj->args[0].flags |= set_mask[index];
2126c5c6571SChengwen Feng 		ret = rte_argparse_parse(obj, default_argc, default_argv);
2136c5c6571SChengwen Feng 		TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
2146c5c6571SChengwen Feng 	}
2156c5c6571SChengwen Feng 
2166c5c6571SChengwen Feng 	return 0;
2176c5c6571SChengwen Feng }
2186c5c6571SChengwen Feng 
2196c5c6571SChengwen Feng static int
2206c5c6571SChengwen Feng test_argparse_invalid_arg_saver(void)
2216c5c6571SChengwen Feng {
2226c5c6571SChengwen Feng 	struct rte_argparse *obj;
2236c5c6571SChengwen Feng 	int ret;
2246c5c6571SChengwen Feng 
2256c5c6571SChengwen Feng 	/* test saver == NULL with val-type != 0. */
2266c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
2276c5c6571SChengwen Feng 	obj->args[0].val_saver = NULL;
2286c5c6571SChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_INT;
2296c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
2306c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
2316c5c6571SChengwen Feng 
2326c5c6571SChengwen Feng 	/* test saver == NULL with callback is NULL. */
2336c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
2346c5c6571SChengwen Feng 	obj->args[0].val_saver = NULL;
2356c5c6571SChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE;
2366c5c6571SChengwen Feng 	obj->callback = NULL;
2376c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
2386c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
2396c5c6571SChengwen Feng 
2406c5c6571SChengwen Feng 	/* test saver != NULL with val-type is zero! */
2416c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
2426c5c6571SChengwen Feng 	obj->args[0].val_saver = (void *)1;
2436c5c6571SChengwen Feng 	obj->args[0].val_set = (void *)1;
2446c5c6571SChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE;
2456c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
2466c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
2476c5c6571SChengwen Feng 
2486c5c6571SChengwen Feng 	/* test saver != NULL with val-type is max. */
2496c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
2506c5c6571SChengwen Feng 	obj->args[0].val_saver = (void *)1;
2516c5c6571SChengwen Feng 	obj->args[0].val_set = (void *)1;
2526c5c6571SChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_MAX;
2536c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
2546c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
2556c5c6571SChengwen Feng 
2566c5c6571SChengwen Feng 	/* test saver != NULL with required value, but val-set is not NULL. */
2576c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
2586c5c6571SChengwen Feng 	obj->args[0].val_saver = (void *)1;
2596c5c6571SChengwen Feng 	obj->args[0].val_set = (void *)1;
2606c5c6571SChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT;
2616c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
2626c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
2636c5c6571SChengwen Feng 
2646c5c6571SChengwen Feng 	return 0;
2656c5c6571SChengwen Feng }
2666c5c6571SChengwen Feng 
2676c5c6571SChengwen Feng static int
2686c5c6571SChengwen Feng test_argparse_invalid_arg_flags(void)
2696c5c6571SChengwen Feng {
2706c5c6571SChengwen Feng 	struct rte_argparse *obj;
2716c5c6571SChengwen Feng 	int ret;
2726c5c6571SChengwen Feng 
273*9684dfeaSChengwen Feng 	/* test set unused bits. */
2746c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
275f48e4eedSChengwen Feng 	obj->args[0].flags |= ~(RTE_ARGPARSE_HAS_VAL_BITMASK |
276f48e4eedSChengwen Feng 				RTE_ARGPARSE_VAL_TYPE_BITMASK |
277f48e4eedSChengwen Feng 				RTE_ARGPARSE_ARG_SUPPORT_MULTI);
2786c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
2796c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
2806c5c6571SChengwen Feng 
281*9684dfeaSChengwen Feng 	/* test positional arg should not config multiple.  */
2826c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
2836c5c6571SChengwen Feng 	obj->args[0].name_long = "positional";
2846c5c6571SChengwen Feng 	obj->args[0].name_short = NULL;
2856c5c6571SChengwen Feng 	obj->args[0].val_saver = (void *)1;
286*9684dfeaSChengwen Feng 	obj->args[0].val_set = NULL;
2876c5c6571SChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT |
2886c5c6571SChengwen Feng 			     RTE_ARGPARSE_ARG_SUPPORT_MULTI;
2896c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
2906c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
2916c5c6571SChengwen Feng 
292*9684dfeaSChengwen Feng 	/* test optional arg enabled multiple but prased by autosave. */
2936c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
2946c5c6571SChengwen Feng 	obj->args[0].flags |= RTE_ARGPARSE_ARG_SUPPORT_MULTI;
2956c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
2966c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
2976c5c6571SChengwen Feng 
2986c5c6571SChengwen Feng 	return 0;
2996c5c6571SChengwen Feng }
3006c5c6571SChengwen Feng 
3016c5c6571SChengwen Feng static int
3026c5c6571SChengwen Feng test_argparse_invalid_arg_repeat(void)
3036c5c6571SChengwen Feng {
3046c5c6571SChengwen Feng 	struct rte_argparse *obj;
3056c5c6571SChengwen Feng 	int ret;
3066c5c6571SChengwen Feng 
3076c5c6571SChengwen Feng 	/* test for long name repeat! */
3086c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
3096c5c6571SChengwen Feng 	obj->args[1].name_long = obj->args[0].name_long;
3106c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
3116c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
3126c5c6571SChengwen Feng 
3136c5c6571SChengwen Feng 	/* test for short name repeat! */
3146c5c6571SChengwen Feng 	obj = test_argparse_init_obj();
3156c5c6571SChengwen Feng 	obj->args[1].name_short = obj->args[0].name_short;
3166c5c6571SChengwen Feng 	ret = rte_argparse_parse(obj, default_argc, default_argv);
3176c5c6571SChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
3186c5c6571SChengwen Feng 
3196c5c6571SChengwen Feng 	return 0;
3206c5c6571SChengwen Feng }
3216c5c6571SChengwen Feng 
32231ed9f9fSChengwen Feng static int
32331ed9f9fSChengwen Feng test_argparse_invalid_option(void)
32431ed9f9fSChengwen Feng {
32531ed9f9fSChengwen Feng 	struct rte_argparse *obj;
32631ed9f9fSChengwen Feng 	char *argv[2];
32731ed9f9fSChengwen Feng 	int ret;
32831ed9f9fSChengwen Feng 
32931ed9f9fSChengwen Feng 	obj = test_argparse_init_obj();
330*9684dfeaSChengwen Feng 	argv[0] = test_strdup(obj->prog_name);
33131ed9f9fSChengwen Feng 	argv[1] = test_strdup("--invalid");
33231ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
33331ed9f9fSChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
33431ed9f9fSChengwen Feng 
33531ed9f9fSChengwen Feng 	obj = test_argparse_init_obj();
336*9684dfeaSChengwen Feng 	argv[0] = test_strdup(obj->prog_name);
33731ed9f9fSChengwen Feng 	argv[1] = test_strdup("invalid");
33831ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
33931ed9f9fSChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
34031ed9f9fSChengwen Feng 
34131ed9f9fSChengwen Feng 	return 0;
34231ed9f9fSChengwen Feng }
34331ed9f9fSChengwen Feng 
34431ed9f9fSChengwen Feng static int
34531ed9f9fSChengwen Feng test_argparse_opt_autosave_parse_int_of_no_val(void)
34631ed9f9fSChengwen Feng {
347f48e4eedSChengwen Feng 	uint64_t flags = RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_INT;
34831ed9f9fSChengwen Feng 	struct rte_argparse *obj;
34931ed9f9fSChengwen Feng 	int val_saver = 0;
35031ed9f9fSChengwen Feng 	char *argv[2];
35131ed9f9fSChengwen Feng 	int ret;
35231ed9f9fSChengwen Feng 
35331ed9f9fSChengwen Feng 	obj = test_argparse_init_obj();
35431ed9f9fSChengwen Feng 	obj->args[0].name_long = "--test-long";
35531ed9f9fSChengwen Feng 	obj->args[0].name_short = "-t";
35631ed9f9fSChengwen Feng 	obj->args[0].val_saver = (void *)&val_saver;
35731ed9f9fSChengwen Feng 	obj->args[0].val_set = (void *)100;
35831ed9f9fSChengwen Feng 	obj->args[0].flags = flags;
35931ed9f9fSChengwen Feng 	obj->args[1].name_long = NULL;
360*9684dfeaSChengwen Feng 	argv[0] = test_strdup(obj->prog_name);
36131ed9f9fSChengwen Feng 	argv[1] = test_strdup("--test-long");
36231ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
36331ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
36431ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
36531ed9f9fSChengwen Feng 
36631ed9f9fSChengwen Feng 	obj->args[0].flags = flags;
36731ed9f9fSChengwen Feng 	val_saver = 0;
36831ed9f9fSChengwen Feng 	argv[1] = test_strdup("-t");
36931ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
37031ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
37131ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
37231ed9f9fSChengwen Feng 
37331ed9f9fSChengwen Feng 	return 0;
37431ed9f9fSChengwen Feng }
37531ed9f9fSChengwen Feng 
37631ed9f9fSChengwen Feng static int
37731ed9f9fSChengwen Feng test_argparse_opt_autosave_parse_int_of_required_val(void)
37831ed9f9fSChengwen Feng {
379f48e4eedSChengwen Feng 	uint64_t flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT;
38031ed9f9fSChengwen Feng 	struct rte_argparse *obj;
38131ed9f9fSChengwen Feng 	int val_saver = 0;
38231ed9f9fSChengwen Feng 	char *argv[3];
38331ed9f9fSChengwen Feng 	int ret;
38431ed9f9fSChengwen Feng 
38531ed9f9fSChengwen Feng 	obj = test_argparse_init_obj();
38631ed9f9fSChengwen Feng 	obj->args[0].name_long = "--test-long";
38731ed9f9fSChengwen Feng 	obj->args[0].name_short = "-t";
38831ed9f9fSChengwen Feng 	obj->args[0].val_saver = (void *)&val_saver;
38931ed9f9fSChengwen Feng 	obj->args[0].val_set = NULL;
39031ed9f9fSChengwen Feng 	obj->args[0].flags = flags;
39131ed9f9fSChengwen Feng 	obj->args[1].name_long = NULL;
392*9684dfeaSChengwen Feng 	argv[0] = test_strdup(obj->prog_name);
39331ed9f9fSChengwen Feng 	argv[1] = test_strdup("--test-long");
39431ed9f9fSChengwen Feng 	argv[2] = test_strdup("100");
39531ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 3, argv);
39631ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
39731ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
39831ed9f9fSChengwen Feng 
39931ed9f9fSChengwen Feng 	obj->args[0].flags = flags;
40031ed9f9fSChengwen Feng 	val_saver = 0;
40131ed9f9fSChengwen Feng 	argv[1] = test_strdup("-t");
40231ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 3, argv);
40331ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
40431ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
40531ed9f9fSChengwen Feng 
40631ed9f9fSChengwen Feng 	/* test invalid value. */
40731ed9f9fSChengwen Feng 	obj->args[0].flags = flags;
40831ed9f9fSChengwen Feng 	val_saver = 0;
40931ed9f9fSChengwen Feng 	argv[1] = test_strdup("-t");
41031ed9f9fSChengwen Feng 	argv[2] = test_strdup("100a");
41131ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 3, argv);
41231ed9f9fSChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
41331ed9f9fSChengwen Feng 
41431ed9f9fSChengwen Feng 	return 0;
41531ed9f9fSChengwen Feng }
41631ed9f9fSChengwen Feng 
41731ed9f9fSChengwen Feng static int
41831ed9f9fSChengwen Feng test_argparse_opt_autosave_parse_int_of_optional_val(void)
41931ed9f9fSChengwen Feng {
420f48e4eedSChengwen Feng 	uint64_t flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE | RTE_ARGPARSE_ARG_VALUE_INT;
42131ed9f9fSChengwen Feng 	struct rte_argparse *obj;
42231ed9f9fSChengwen Feng 	int val_saver = 0;
42331ed9f9fSChengwen Feng 	char *argv[2];
42431ed9f9fSChengwen Feng 	int ret;
42531ed9f9fSChengwen Feng 
426*9684dfeaSChengwen Feng 	/* test without value. */
42731ed9f9fSChengwen Feng 	obj = test_argparse_init_obj();
42831ed9f9fSChengwen Feng 	obj->args[0].name_long = "--test-long";
42931ed9f9fSChengwen Feng 	obj->args[0].name_short = "-t";
43031ed9f9fSChengwen Feng 	obj->args[0].val_saver = (void *)&val_saver;
43131ed9f9fSChengwen Feng 	obj->args[0].val_set = (void *)100;
43231ed9f9fSChengwen Feng 	obj->args[0].flags = flags;
43331ed9f9fSChengwen Feng 	obj->args[1].name_long = NULL;
434*9684dfeaSChengwen Feng 	argv[0] = test_strdup(obj->prog_name);
43531ed9f9fSChengwen Feng 	argv[1] = test_strdup("--test-long");
43631ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
43731ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
43831ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
43931ed9f9fSChengwen Feng 	obj->args[0].flags = flags;
44031ed9f9fSChengwen Feng 	val_saver = 0;
44131ed9f9fSChengwen Feng 	argv[1] = test_strdup("-t");
44231ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
44331ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
44431ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
44531ed9f9fSChengwen Feng 
44631ed9f9fSChengwen Feng 	/* test with value. */
44731ed9f9fSChengwen Feng 	obj->args[0].flags = flags;
44831ed9f9fSChengwen Feng 	val_saver = 0;
44931ed9f9fSChengwen Feng 	argv[1] = test_strdup("--test-long=200");
45031ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
45131ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
45231ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 200, "Argparse parse expect success!");
45331ed9f9fSChengwen Feng 	obj->args[0].flags = flags;
45431ed9f9fSChengwen Feng 	val_saver = 0;
45531ed9f9fSChengwen Feng 	argv[1] = test_strdup("-t=200");
45631ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
45731ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
45831ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 200, "Argparse parse expect success!");
45931ed9f9fSChengwen Feng 
46031ed9f9fSChengwen Feng 	/* test with option value, but with wrong value. */
46131ed9f9fSChengwen Feng 	obj->args[0].flags = flags;
46231ed9f9fSChengwen Feng 	val_saver = 0;
46331ed9f9fSChengwen Feng 	argv[1] = test_strdup("--test-long=200a");
46431ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
46531ed9f9fSChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
46631ed9f9fSChengwen Feng 	obj->args[0].flags = flags;
46731ed9f9fSChengwen Feng 	val_saver = 0;
46831ed9f9fSChengwen Feng 	argv[1] = test_strdup("-t=200a");
46931ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
47031ed9f9fSChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
47131ed9f9fSChengwen Feng 
47231ed9f9fSChengwen Feng 	return 0;
47331ed9f9fSChengwen Feng }
47431ed9f9fSChengwen Feng 
47531ed9f9fSChengwen Feng static int
47631ed9f9fSChengwen Feng opt_callback_parse_int_of_no_val(uint32_t index, const char *value, void *opaque)
47731ed9f9fSChengwen Feng {
478*9684dfeaSChengwen Feng 	if (index != 1)
479*9684dfeaSChengwen Feng 		return -EINVAL;
48031ed9f9fSChengwen Feng 	if (value != NULL)
48131ed9f9fSChengwen Feng 		return -EINVAL;
48231ed9f9fSChengwen Feng 	*(int *)opaque = 100;
48331ed9f9fSChengwen Feng 	return 0;
48431ed9f9fSChengwen Feng }
48531ed9f9fSChengwen Feng 
48631ed9f9fSChengwen Feng static int
48731ed9f9fSChengwen Feng test_argparse_opt_callback_parse_int_of_no_val(void)
48831ed9f9fSChengwen Feng {
48931ed9f9fSChengwen Feng 	struct rte_argparse *obj;
49031ed9f9fSChengwen Feng 	int val_saver = 0;
49131ed9f9fSChengwen Feng 	char *argv[2];
49231ed9f9fSChengwen Feng 	int ret;
49331ed9f9fSChengwen Feng 
49431ed9f9fSChengwen Feng 	obj = test_argparse_init_obj();
49531ed9f9fSChengwen Feng 	obj->callback = opt_callback_parse_int_of_no_val;
49631ed9f9fSChengwen Feng 	obj->opaque = (void *)&val_saver;
49731ed9f9fSChengwen Feng 	obj->args[0].name_long = "--test-long";
49831ed9f9fSChengwen Feng 	obj->args[0].name_short = "-t";
49931ed9f9fSChengwen Feng 	obj->args[0].val_saver = NULL;
500*9684dfeaSChengwen Feng 	obj->args[0].val_set = (void *)1;
50131ed9f9fSChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE;
50231ed9f9fSChengwen Feng 	obj->args[1].name_long = NULL;
503*9684dfeaSChengwen Feng 	argv[0] = test_strdup(obj->prog_name);
50431ed9f9fSChengwen Feng 	argv[1] = test_strdup("--test-long");
50531ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
50631ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
50731ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
50831ed9f9fSChengwen Feng 
50931ed9f9fSChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE;
51031ed9f9fSChengwen Feng 	val_saver = 0;
51131ed9f9fSChengwen Feng 	argv[1] = test_strdup("-t");
51231ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
51331ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
51431ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
51531ed9f9fSChengwen Feng 
51631ed9f9fSChengwen Feng 	return 0;
51731ed9f9fSChengwen Feng }
51831ed9f9fSChengwen Feng 
51931ed9f9fSChengwen Feng static int
52031ed9f9fSChengwen Feng opt_callback_parse_int_of_required_val(uint32_t index, const char *value, void *opaque)
52131ed9f9fSChengwen Feng {
52231ed9f9fSChengwen Feng 	char *s = NULL;
52331ed9f9fSChengwen Feng 
52431ed9f9fSChengwen Feng 	if (index != 1)
52531ed9f9fSChengwen Feng 		return -EINVAL;
52631ed9f9fSChengwen Feng 
52731ed9f9fSChengwen Feng 	if (value == NULL)
52831ed9f9fSChengwen Feng 		return -EINVAL;
52931ed9f9fSChengwen Feng 	*(int *)opaque = strtol(value, &s, 0);
53031ed9f9fSChengwen Feng 
53131ed9f9fSChengwen Feng 	if (s[0] != '\0')
53231ed9f9fSChengwen Feng 		return -EINVAL;
53331ed9f9fSChengwen Feng 
53431ed9f9fSChengwen Feng 	return 0;
53531ed9f9fSChengwen Feng }
53631ed9f9fSChengwen Feng 
53731ed9f9fSChengwen Feng static int
53831ed9f9fSChengwen Feng test_argparse_opt_callback_parse_int_of_required_val(void)
53931ed9f9fSChengwen Feng {
54031ed9f9fSChengwen Feng 	struct rte_argparse *obj;
54131ed9f9fSChengwen Feng 	int val_saver = 0;
54231ed9f9fSChengwen Feng 	char *argv[3];
54331ed9f9fSChengwen Feng 	int ret;
54431ed9f9fSChengwen Feng 
54531ed9f9fSChengwen Feng 	obj = test_argparse_init_obj();
54631ed9f9fSChengwen Feng 	obj->callback = opt_callback_parse_int_of_required_val;
54731ed9f9fSChengwen Feng 	obj->opaque = (void *)&val_saver;
54831ed9f9fSChengwen Feng 	obj->args[0].name_long = "--test-long";
54931ed9f9fSChengwen Feng 	obj->args[0].name_short = "-t";
55031ed9f9fSChengwen Feng 	obj->args[0].val_saver = NULL;
55131ed9f9fSChengwen Feng 	obj->args[0].val_set = (void *)1;
55231ed9f9fSChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
55331ed9f9fSChengwen Feng 	obj->args[1].name_long = NULL;
554*9684dfeaSChengwen Feng 	argv[0] = test_strdup(obj->prog_name);
55531ed9f9fSChengwen Feng 	argv[1] = test_strdup("--test-long");
55631ed9f9fSChengwen Feng 	argv[2] = test_strdup("100");
55731ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 3, argv);
55831ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
55931ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
56031ed9f9fSChengwen Feng 
56131ed9f9fSChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
56231ed9f9fSChengwen Feng 	val_saver = 0;
56331ed9f9fSChengwen Feng 	argv[1] = test_strdup("-t");
56431ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 3, argv);
56531ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
56631ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
56731ed9f9fSChengwen Feng 
56831ed9f9fSChengwen Feng 	/* test no more parameters. */
56931ed9f9fSChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
57031ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
57131ed9f9fSChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
57231ed9f9fSChengwen Feng 
57331ed9f9fSChengwen Feng 	/* test callback return failed. */
57431ed9f9fSChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
57531ed9f9fSChengwen Feng 	argv[2] = test_strdup("100a");
57631ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 3, argv);
57731ed9f9fSChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
57831ed9f9fSChengwen Feng 
57931ed9f9fSChengwen Feng 	return 0;
58031ed9f9fSChengwen Feng }
58131ed9f9fSChengwen Feng 
58231ed9f9fSChengwen Feng static int
58331ed9f9fSChengwen Feng opt_callback_parse_int_of_optional_val(uint32_t index, const char *value, void *opaque)
58431ed9f9fSChengwen Feng {
58531ed9f9fSChengwen Feng 	char *s = NULL;
58631ed9f9fSChengwen Feng 
58731ed9f9fSChengwen Feng 	if (index != 1)
58831ed9f9fSChengwen Feng 		return -EINVAL;
58931ed9f9fSChengwen Feng 
59031ed9f9fSChengwen Feng 	if (value == NULL) {
59131ed9f9fSChengwen Feng 		*(int *)opaque = 10;
59231ed9f9fSChengwen Feng 	} else {
59331ed9f9fSChengwen Feng 		*(int *)opaque = strtol(value, &s, 0);
59431ed9f9fSChengwen Feng 		if (s[0] != '\0')
59531ed9f9fSChengwen Feng 			return -EINVAL;
59631ed9f9fSChengwen Feng 	}
59731ed9f9fSChengwen Feng 
59831ed9f9fSChengwen Feng 	return 0;
59931ed9f9fSChengwen Feng }
60031ed9f9fSChengwen Feng 
60131ed9f9fSChengwen Feng static int
60231ed9f9fSChengwen Feng test_argparse_opt_callback_parse_int_of_optional_val(void)
60331ed9f9fSChengwen Feng {
60431ed9f9fSChengwen Feng 	struct rte_argparse *obj;
60531ed9f9fSChengwen Feng 	int val_saver = 0;
60631ed9f9fSChengwen Feng 	char *argv[2];
60731ed9f9fSChengwen Feng 	int ret;
60831ed9f9fSChengwen Feng 
60931ed9f9fSChengwen Feng 	obj = test_argparse_init_obj();
61031ed9f9fSChengwen Feng 	obj->callback = opt_callback_parse_int_of_optional_val;
61131ed9f9fSChengwen Feng 	obj->opaque = (void *)&val_saver;
61231ed9f9fSChengwen Feng 	obj->args[0].name_long = "--test-long";
61331ed9f9fSChengwen Feng 	obj->args[0].name_short = "-t";
61431ed9f9fSChengwen Feng 	obj->args[0].val_saver = NULL;
61531ed9f9fSChengwen Feng 	obj->args[0].val_set = (void *)1;
61631ed9f9fSChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE;
61731ed9f9fSChengwen Feng 	obj->args[1].name_long = NULL;
618*9684dfeaSChengwen Feng 	argv[0] = test_strdup(obj->prog_name);
61931ed9f9fSChengwen Feng 	argv[1] = test_strdup("--test-long");
62031ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
62131ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
62231ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 10, "Argparse parse expect success!");
62331ed9f9fSChengwen Feng 
62431ed9f9fSChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE;
62531ed9f9fSChengwen Feng 	val_saver = 0;
62631ed9f9fSChengwen Feng 	argv[1] = test_strdup("-t");
62731ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
62831ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
62931ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 10, "Argparse parse expect success!");
63031ed9f9fSChengwen Feng 
63131ed9f9fSChengwen Feng 	/* test with value. */
63231ed9f9fSChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE;
63331ed9f9fSChengwen Feng 	val_saver = 0;
63431ed9f9fSChengwen Feng 	argv[1] = test_strdup("--test-long=100");
63531ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
63631ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
63731ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
63831ed9f9fSChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE;
63931ed9f9fSChengwen Feng 	val_saver = 0;
64031ed9f9fSChengwen Feng 	argv[1] = test_strdup("-t=100");
64131ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
64231ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
64331ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
64431ed9f9fSChengwen Feng 
64531ed9f9fSChengwen Feng 	/* test callback return failed. */
64631ed9f9fSChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE;
64731ed9f9fSChengwen Feng 	argv[1] = test_strdup("-t=100a");
64831ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
64931ed9f9fSChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
65031ed9f9fSChengwen Feng 
65131ed9f9fSChengwen Feng 	return 0;
65231ed9f9fSChengwen Feng }
65331ed9f9fSChengwen Feng 
65431ed9f9fSChengwen Feng static int
65531ed9f9fSChengwen Feng test_argparse_pos_autosave_parse_int(void)
65631ed9f9fSChengwen Feng {
657f48e4eedSChengwen Feng 	uint64_t flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT;
65831ed9f9fSChengwen Feng 	struct rte_argparse *obj;
65931ed9f9fSChengwen Feng 	int val_saver = 0;
66031ed9f9fSChengwen Feng 	char *argv[3];
66131ed9f9fSChengwen Feng 	int ret;
66231ed9f9fSChengwen Feng 
663*9684dfeaSChengwen Feng 	/* test positional autosave parse successful. */
66431ed9f9fSChengwen Feng 	obj = test_argparse_init_obj();
66531ed9f9fSChengwen Feng 	obj->args[0].name_long = "test-long";
66631ed9f9fSChengwen Feng 	obj->args[0].name_short = NULL;
66731ed9f9fSChengwen Feng 	obj->args[0].val_saver = (void *)&val_saver;
66831ed9f9fSChengwen Feng 	obj->args[0].val_set = NULL;
66931ed9f9fSChengwen Feng 	obj->args[0].flags = flags;
67031ed9f9fSChengwen Feng 	obj->args[1].name_long = NULL;
671*9684dfeaSChengwen Feng 	argv[0] = test_strdup(obj->prog_name);
67231ed9f9fSChengwen Feng 	argv[1] = test_strdup("100");
67331ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
67431ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
67531ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
67631ed9f9fSChengwen Feng 
677*9684dfeaSChengwen Feng 	/* test positional autosave parse failed. */
67831ed9f9fSChengwen Feng 	obj->args[0].flags = flags;
67931ed9f9fSChengwen Feng 	val_saver = 0;
68031ed9f9fSChengwen Feng 	argv[1] = test_strdup("100a");
68131ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 2, argv);
68231ed9f9fSChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
68331ed9f9fSChengwen Feng 
684*9684dfeaSChengwen Feng 	/* test too much position parameters. */
68531ed9f9fSChengwen Feng 	obj->args[0].flags = flags;
68631ed9f9fSChengwen Feng 	argv[1] = test_strdup("100");
68731ed9f9fSChengwen Feng 	argv[2] = test_strdup("200");
68831ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 3, argv);
68931ed9f9fSChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
69031ed9f9fSChengwen Feng 
69131ed9f9fSChengwen Feng 	return 0;
69231ed9f9fSChengwen Feng }
69331ed9f9fSChengwen Feng 
69431ed9f9fSChengwen Feng static int
69531ed9f9fSChengwen Feng pos_callback_parse_int(uint32_t index, const char *value, void *opaque)
69631ed9f9fSChengwen Feng {
69731ed9f9fSChengwen Feng 	uint32_t int_val;
69831ed9f9fSChengwen Feng 	char *s = NULL;
69931ed9f9fSChengwen Feng 
70031ed9f9fSChengwen Feng 	if (index != 1 && index != 2)
70131ed9f9fSChengwen Feng 		return -EINVAL;
70231ed9f9fSChengwen Feng 	if (value == NULL)
70331ed9f9fSChengwen Feng 		return -EINVAL;
70431ed9f9fSChengwen Feng 
70531ed9f9fSChengwen Feng 	int_val = strtol(value, &s, 0);
70631ed9f9fSChengwen Feng 	if (s[0] != '\0')
70731ed9f9fSChengwen Feng 		return -EINVAL;
70831ed9f9fSChengwen Feng 
70931ed9f9fSChengwen Feng 	*((int *)opaque	+ index) = int_val;
71031ed9f9fSChengwen Feng 
71131ed9f9fSChengwen Feng 	return 0;
71231ed9f9fSChengwen Feng }
71331ed9f9fSChengwen Feng 
71431ed9f9fSChengwen Feng static int
71531ed9f9fSChengwen Feng test_argparse_pos_callback_parse_int(void)
71631ed9f9fSChengwen Feng {
71731ed9f9fSChengwen Feng 	int val_saver[3] = { 0, 0, 0 };
71831ed9f9fSChengwen Feng 	struct rte_argparse *obj;
71931ed9f9fSChengwen Feng 	char *argv[3];
72031ed9f9fSChengwen Feng 	int ret;
72131ed9f9fSChengwen Feng 
722*9684dfeaSChengwen Feng 	/* test positional callback parse successful. */
72331ed9f9fSChengwen Feng 	obj = test_argparse_init_obj();
72431ed9f9fSChengwen Feng 	obj->callback = pos_callback_parse_int;
72531ed9f9fSChengwen Feng 	obj->opaque = (void *)val_saver;
72631ed9f9fSChengwen Feng 	obj->args[0].name_long = "test-long1";
72731ed9f9fSChengwen Feng 	obj->args[0].name_short = NULL;
72831ed9f9fSChengwen Feng 	obj->args[0].val_saver = NULL;
72931ed9f9fSChengwen Feng 	obj->args[0].val_set = (void *)1;
73031ed9f9fSChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
73131ed9f9fSChengwen Feng 	obj->args[1].name_long = "test-long2";
73231ed9f9fSChengwen Feng 	obj->args[1].name_short = NULL;
73331ed9f9fSChengwen Feng 	obj->args[1].val_saver = NULL;
73431ed9f9fSChengwen Feng 	obj->args[1].val_set = (void *)2;
73531ed9f9fSChengwen Feng 	obj->args[1].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
73631ed9f9fSChengwen Feng 	obj->args[2].name_long = NULL;
737*9684dfeaSChengwen Feng 	argv[0] = test_strdup(obj->prog_name);
73831ed9f9fSChengwen Feng 	argv[1] = test_strdup("100");
73931ed9f9fSChengwen Feng 	argv[2] = test_strdup("200");
74031ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 3, argv);
74131ed9f9fSChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse expect success!");
74231ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver[1] == 100, "Argparse parse expect success!");
74331ed9f9fSChengwen Feng 	TEST_ASSERT(val_saver[2] == 200, "Argparse parse expect success!");
74431ed9f9fSChengwen Feng 
745*9684dfeaSChengwen Feng 	/* test positional callback parse failed. */
74631ed9f9fSChengwen Feng 	obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
74731ed9f9fSChengwen Feng 	obj->args[1].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
74831ed9f9fSChengwen Feng 	argv[2] = test_strdup("200a");
74931ed9f9fSChengwen Feng 	ret = rte_argparse_parse(obj, 3, argv);
75031ed9f9fSChengwen Feng 	TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
75131ed9f9fSChengwen Feng 
75231ed9f9fSChengwen Feng 	return 0;
75331ed9f9fSChengwen Feng }
75431ed9f9fSChengwen Feng 
7559ccd7b27SChengwen Feng static int
7569ccd7b27SChengwen Feng test_argparse_parse_type(void)
7579ccd7b27SChengwen Feng {
7589ccd7b27SChengwen Feng 	char *str_erange = test_strdup("9999999999999999999999999999999999");
7595357c248SChengwen Feng 	char *str_erange_u32 = test_strdup("4294967296");
7605357c248SChengwen Feng 	char *str_erange_u16 = test_strdup("65536");
7615357c248SChengwen Feng 	char *str_erange_u8 = test_strdup("256");
7629ccd7b27SChengwen Feng 	char *str_invalid = test_strdup("1a");
7639ccd7b27SChengwen Feng 	char *str_ok = test_strdup("123");
7645357c248SChengwen Feng 	uint16_t val_u16;
7655357c248SChengwen Feng 	uint32_t val_u32;
7665357c248SChengwen Feng 	uint64_t val_u64;
7675357c248SChengwen Feng 	uint8_t val_u8;
7685357c248SChengwen Feng 	int val_int;
7699ccd7b27SChengwen Feng 	int ret;
7709ccd7b27SChengwen Feng 
7719ccd7b27SChengwen Feng 	/* test for int parsing */
7725357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_INT, &val_int);
7739ccd7b27SChengwen Feng 	TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
7745357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_INT, &val_int);
7759ccd7b27SChengwen Feng 	TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
7765357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_INT, &val_int);
7779ccd7b27SChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
7785357c248SChengwen Feng 	TEST_ASSERT(val_int == 123, "Argparse parse type expect failed!");
7795357c248SChengwen Feng 
7805357c248SChengwen Feng 	/* test for u8 parsing */
7815357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8);
7825357c248SChengwen Feng 	TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
7835357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_erange_u8, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8);
7845357c248SChengwen Feng 	TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
7855357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8);
7865357c248SChengwen Feng 	TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
7875357c248SChengwen Feng 	val_u8 = 0;
7885357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8);
7895357c248SChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
7905357c248SChengwen Feng 	TEST_ASSERT(val_u8 == 123, "Argparse parse type expect failed!");
7915357c248SChengwen Feng 
7925357c248SChengwen Feng 	/* test for u16 parsing */
7935357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16);
7945357c248SChengwen Feng 	TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
7955357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_erange_u16, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16);
7965357c248SChengwen Feng 	TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
7975357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16);
7985357c248SChengwen Feng 	TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
7995357c248SChengwen Feng 	val_u16 = 0;
8005357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16);
8015357c248SChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
8025357c248SChengwen Feng 	TEST_ASSERT(val_u16 == 123, "Argparse parse type expect failed!");
8035357c248SChengwen Feng 
8045357c248SChengwen Feng 	/* test for u32 parsing */
8055357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32);
8065357c248SChengwen Feng 	TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
8075357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_erange_u32, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32);
8085357c248SChengwen Feng 	TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
8095357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32);
8105357c248SChengwen Feng 	TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
8115357c248SChengwen Feng 	val_u32 = 0;
8125357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32);
8135357c248SChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
8145357c248SChengwen Feng 	TEST_ASSERT(val_u32 == 123, "Argparse parse type expect failed!");
8155357c248SChengwen Feng 
8165357c248SChengwen Feng 	/* test for u64 parsing */
8175357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64);
8185357c248SChengwen Feng 	TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
8195357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64);
8205357c248SChengwen Feng 	TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
8215357c248SChengwen Feng 	val_u64 = 0;
8225357c248SChengwen Feng 	ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64);
8235357c248SChengwen Feng 	TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
8245357c248SChengwen Feng 	TEST_ASSERT(val_u64 == 123, "Argparse parse type expect failed!");
8259ccd7b27SChengwen Feng 
8269ccd7b27SChengwen Feng 	return 0;
8279ccd7b27SChengwen Feng }
8289ccd7b27SChengwen Feng 
8296c5c6571SChengwen Feng static struct unit_test_suite argparse_test_suite = {
8306c5c6571SChengwen Feng 	.suite_name = "Argparse Unit Test Suite",
8316c5c6571SChengwen Feng 	.setup = test_argparse_setup,
8326c5c6571SChengwen Feng 	.teardown = test_argparse_teardown,
8336c5c6571SChengwen Feng 	.unit_test_cases = {
8346c5c6571SChengwen Feng 		TEST_CASE(test_argparse_invalid_basic_param),
8356c5c6571SChengwen Feng 		TEST_CASE(test_argparse_invalid_arg_name),
8366c5c6571SChengwen Feng 		TEST_CASE(test_argparse_invalid_arg_help),
8376c5c6571SChengwen Feng 		TEST_CASE(test_argparse_invalid_has_val),
8386c5c6571SChengwen Feng 		TEST_CASE(test_argparse_invalid_arg_saver),
8396c5c6571SChengwen Feng 		TEST_CASE(test_argparse_invalid_arg_flags),
8406c5c6571SChengwen Feng 		TEST_CASE(test_argparse_invalid_arg_repeat),
84131ed9f9fSChengwen Feng 		TEST_CASE(test_argparse_invalid_option),
84231ed9f9fSChengwen Feng 		TEST_CASE(test_argparse_opt_autosave_parse_int_of_no_val),
84331ed9f9fSChengwen Feng 		TEST_CASE(test_argparse_opt_autosave_parse_int_of_required_val),
84431ed9f9fSChengwen Feng 		TEST_CASE(test_argparse_opt_autosave_parse_int_of_optional_val),
84531ed9f9fSChengwen Feng 		TEST_CASE(test_argparse_opt_callback_parse_int_of_no_val),
84631ed9f9fSChengwen Feng 		TEST_CASE(test_argparse_opt_callback_parse_int_of_required_val),
84731ed9f9fSChengwen Feng 		TEST_CASE(test_argparse_opt_callback_parse_int_of_optional_val),
84831ed9f9fSChengwen Feng 		TEST_CASE(test_argparse_pos_autosave_parse_int),
84931ed9f9fSChengwen Feng 		TEST_CASE(test_argparse_pos_callback_parse_int),
8509ccd7b27SChengwen Feng 		TEST_CASE(test_argparse_parse_type),
8516c5c6571SChengwen Feng 
8526c5c6571SChengwen Feng 		TEST_CASES_END() /**< NULL terminate unit test array */
8536c5c6571SChengwen Feng 	}
8546c5c6571SChengwen Feng };
8556c5c6571SChengwen Feng 
8566c5c6571SChengwen Feng static int
8576c5c6571SChengwen Feng test_argparse(void)
8586c5c6571SChengwen Feng {
8596c5c6571SChengwen Feng 	return unit_test_suite_runner(&argparse_test_suite);
8606c5c6571SChengwen Feng }
8616c5c6571SChengwen Feng 
8626c5c6571SChengwen Feng REGISTER_FAST_TEST(argparse_autotest, true, true, test_argparse);
863