xref: /dpdk/app/test/test_argparse.c (revision 9684dfeae3284ec93a56090e653fb74886d5a40e)
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