Branch data Line data Source code
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 : 50 : test_strdup(const char *str)
31 : : {
32 : 50 : char *s = strdup(str);
33 [ - + ]: 50 : if (s == NULL) {
34 : : printf("strdup failed! exiting...\n");
35 : 0 : exit(-ENOMEM);
36 : : }
37 [ - + ]: 50 : if (strdup_store_index >= MAX_STRDUP_STORE_NUM) {
38 : : printf("too much strdup calls! exiting...\n");
39 : 0 : exit(-ERANGE);
40 : : }
41 : 50 : strdup_store_array[strdup_store_index++] = s;
42 : 50 : return s;
43 : : }
44 : :
45 : : static int
46 : 1 : test_argparse_setup(void)
47 : : {
48 : 1 : strdup_store_index = 0;
49 : 1 : default_argc = 1;
50 : 1 : default_argv[0] = test_strdup("test_argparse");
51 : 1 : return 0;
52 : : }
53 : :
54 : : static void
55 : 1 : test_argparse_teardown(void)
56 : : {
57 : : uint32_t i;
58 : 1 : printf("total used strdup_store_index = %u\n", strdup_store_index);
59 [ + + ]: 51 : for (i = 0; i < strdup_store_index; i++)
60 : 50 : free(strdup_store_array[i]);
61 : 1 : strdup_store_index = 0;
62 : 1 : }
63 : :
64 : : static int
65 : 0 : 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 : 0 : 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 : 34 : test_argparse_copy(struct rte_argparse *dst, struct rte_argparse *src)
90 : : {
91 : : uint32_t i;
92 : : memcpy(dst, src, sizeof(*src));
93 : 68 : for (i = 0; /* NULL */; i++) {
94 [ + + ]: 102 : memcpy(&dst->args[i], &src->args[i], sizeof(src->args[i]));
95 [ + + ]: 102 : if (src->args[i].name_long == NULL)
96 : : break;
97 : : }
98 : 34 : }
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 : 18 : test_argparse_copy(&obj, &backup);
107 : : return &obj;
108 : : }
109 : :
110 : : static int
111 : 1 : test_argparse_invalid_basic_param(void)
112 : : {
113 : : struct rte_argparse *obj;
114 : : int ret;
115 : :
116 : : obj = test_argparse_init_obj();
117 : 1 : obj->prog_name = NULL;
118 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
119 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
120 : :
121 : : obj = test_argparse_init_obj();
122 : 1 : obj->usage = NULL;
123 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
124 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
125 : :
126 : : return TEST_SUCCESS;
127 : : }
128 : :
129 : : static int
130 : 1 : test_argparse_invalid_arg_name(void)
131 : : {
132 : : struct rte_argparse *obj;
133 : : int ret;
134 : :
135 : : obj = test_argparse_init_obj();
136 : 1 : obj->args[0].name_long = "-ab";
137 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
138 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
139 : :
140 : : obj = test_argparse_init_obj();
141 : 1 : obj->args[0].name_long = "-abc";
142 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
143 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
144 : :
145 : : obj = test_argparse_init_obj();
146 : 1 : obj->args[0].name_long = "---c";
147 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
148 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
149 : :
150 : : obj = test_argparse_init_obj();
151 : 1 : obj->args[0].name_long = "abc";
152 : 1 : obj->args[0].name_short = "-a";
153 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
154 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
155 : :
156 : : obj = test_argparse_init_obj();
157 : 1 : obj->args[0].name_short = "a";
158 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
159 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
160 : :
161 : : obj = test_argparse_init_obj();
162 : 1 : obj->args[0].name_short = "abc";
163 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
164 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
165 : :
166 : : obj = test_argparse_init_obj();
167 : 1 : obj->args[0].name_short = "ab";
168 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
169 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
170 : :
171 : : return 0;
172 : : }
173 : :
174 : : static int
175 : 1 : test_argparse_invalid_arg_help(void)
176 : : {
177 : : struct rte_argparse *obj;
178 : : int ret;
179 : :
180 : : obj = test_argparse_init_obj();
181 : 1 : obj->args[0].help = NULL;
182 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
183 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
184 : :
185 : : return 0;
186 : : }
187 : :
188 : : static int
189 : 1 : test_argparse_invalid_has_val(void)
190 : : {
191 : 1 : 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 : 1 : obj->args[0].flags &= ~RTE_ARGPARSE_HAS_VAL_BITMASK;
202 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
203 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
204 : :
205 : : /* test positional arg don't config required-value. */
206 [ + + ]: 4 : for (index = 0; index < RTE_DIM(set_mask); index++) {
207 : : obj = test_argparse_init_obj();
208 : 3 : obj->args[0].name_long = "abc";
209 : 3 : obj->args[0].name_short = NULL;
210 : 3 : obj->args[0].flags &= ~RTE_ARGPARSE_HAS_VAL_BITMASK;
211 : 3 : obj->args[0].flags |= set_mask[index];
212 : 3 : ret = rte_argparse_parse(obj, default_argc, default_argv);
213 [ - + ]: 3 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
214 : : }
215 : :
216 : : return 0;
217 : : }
218 : :
219 : : static int
220 : 1 : 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 : 1 : obj->args[0].val_saver = NULL;
228 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_INT;
229 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
230 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
231 : :
232 : : /* test saver == NULL with callback is NULL. */
233 : : obj = test_argparse_init_obj();
234 : 1 : obj->args[0].val_saver = NULL;
235 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE;
236 : 1 : obj->callback = NULL;
237 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
238 [ - + ]: 1 : 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 : 1 : obj->args[0].val_saver = (void *)1;
243 : 1 : obj->args[0].val_set = (void *)1;
244 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE;
245 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
246 [ - + ]: 1 : 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 : 1 : obj->args[0].val_saver = (void *)1;
251 : 1 : obj->args[0].val_set = (void *)1;
252 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_MAX;
253 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
254 [ - + ]: 1 : 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 : 1 : obj->args[0].val_saver = (void *)1;
259 : 1 : obj->args[0].val_set = (void *)1;
260 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT;
261 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
262 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
263 : :
264 : : return 0;
265 : : }
266 : :
267 : : static int
268 : 1 : 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 : 1 : obj->args[0].flags |= ~(RTE_ARGPARSE_HAS_VAL_BITMASK |
276 : : RTE_ARGPARSE_VAL_TYPE_BITMASK |
277 : : RTE_ARGPARSE_ARG_SUPPORT_MULTI);
278 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
279 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
280 : :
281 : : /* test positional arg should not config multiple. */
282 : : obj = test_argparse_init_obj();
283 : 1 : obj->args[0].name_long = "positional";
284 : 1 : obj->args[0].name_short = NULL;
285 : 1 : obj->args[0].val_saver = (void *)1;
286 : 1 : obj->args[0].val_set = NULL;
287 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT |
288 : : RTE_ARGPARSE_ARG_SUPPORT_MULTI;
289 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
290 [ - + ]: 1 : 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 : 1 : obj->args[0].flags |= RTE_ARGPARSE_ARG_SUPPORT_MULTI;
295 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
296 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
297 : :
298 : : return 0;
299 : : }
300 : :
301 : : static int
302 : 1 : 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 : 1 : obj->args[1].name_long = obj->args[0].name_long;
310 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
311 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
312 : :
313 : : /* test for short name repeat! */
314 : : obj = test_argparse_init_obj();
315 : 1 : obj->args[1].name_short = obj->args[0].name_short;
316 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
317 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
318 : :
319 : : return 0;
320 : : }
321 : :
322 : : static int
323 : 1 : 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 : 1 : argv[0] = test_strdup(obj->prog_name);
331 : 1 : argv[1] = test_strdup("--invalid");
332 : 1 : ret = rte_argparse_parse(obj, 2, argv);
333 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
334 : :
335 : : obj = test_argparse_init_obj();
336 : 1 : argv[0] = test_strdup(obj->prog_name);
337 : 1 : argv[1] = test_strdup("invalid");
338 : 1 : ret = rte_argparse_parse(obj, 2, argv);
339 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
340 : :
341 : : return 0;
342 : : }
343 : :
344 : : static int
345 : 1 : 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 : 1 : int val_saver = 0;
350 : : char *argv[2];
351 : : int ret;
352 : :
353 : : obj = test_argparse_init_obj();
354 : 1 : obj->args[0].name_long = "--test-long";
355 : 1 : obj->args[0].name_short = "-t";
356 : 1 : obj->args[0].val_saver = (void *)&val_saver;
357 : 1 : obj->args[0].val_set = (void *)100;
358 : 1 : obj->args[0].flags = flags;
359 : 1 : obj->args[1].name_long = NULL;
360 : 1 : argv[0] = test_strdup(obj->prog_name);
361 : 1 : argv[1] = test_strdup("--test-long");
362 : 1 : ret = rte_argparse_parse(obj, 2, argv);
363 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
364 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
365 : :
366 : 1 : obj->args[0].flags = flags;
367 : 1 : val_saver = 0;
368 : 1 : argv[1] = test_strdup("-t");
369 : 1 : ret = rte_argparse_parse(obj, 2, argv);
370 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
371 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
372 : :
373 : : return 0;
374 : : }
375 : :
376 : : static int
377 : 1 : 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 : 1 : int val_saver = 0;
382 : : char *argv[3];
383 : : int ret;
384 : :
385 : : obj = test_argparse_init_obj();
386 : 1 : obj->args[0].name_long = "--test-long";
387 : 1 : obj->args[0].name_short = "-t";
388 : 1 : obj->args[0].val_saver = (void *)&val_saver;
389 : 1 : obj->args[0].val_set = NULL;
390 : 1 : obj->args[0].flags = flags;
391 : 1 : obj->args[1].name_long = NULL;
392 : 1 : argv[0] = test_strdup(obj->prog_name);
393 : 1 : argv[1] = test_strdup("--test-long");
394 : 1 : argv[2] = test_strdup("100");
395 : 1 : ret = rte_argparse_parse(obj, 3, argv);
396 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
397 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
398 : :
399 : 1 : obj->args[0].flags = flags;
400 : 1 : val_saver = 0;
401 : 1 : argv[1] = test_strdup("-t");
402 : 1 : ret = rte_argparse_parse(obj, 3, argv);
403 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
404 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
405 : :
406 : : /* test invalid value. */
407 : 1 : obj->args[0].flags = flags;
408 : 1 : val_saver = 0;
409 : 1 : argv[1] = test_strdup("-t");
410 : 1 : argv[2] = test_strdup("100a");
411 : 1 : ret = rte_argparse_parse(obj, 3, argv);
412 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
413 : :
414 : : return 0;
415 : : }
416 : :
417 : : static int
418 : 1 : 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 : 1 : int val_saver = 0;
423 : : char *argv[2];
424 : : int ret;
425 : :
426 : : /* test without value. */
427 : : obj = test_argparse_init_obj();
428 : 1 : obj->args[0].name_long = "--test-long";
429 : 1 : obj->args[0].name_short = "-t";
430 : 1 : obj->args[0].val_saver = (void *)&val_saver;
431 : 1 : obj->args[0].val_set = (void *)100;
432 : 1 : obj->args[0].flags = flags;
433 : 1 : obj->args[1].name_long = NULL;
434 : 1 : argv[0] = test_strdup(obj->prog_name);
435 : 1 : argv[1] = test_strdup("--test-long");
436 : 1 : ret = rte_argparse_parse(obj, 2, argv);
437 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
438 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
439 : 1 : obj->args[0].flags = flags;
440 : 1 : val_saver = 0;
441 : 1 : argv[1] = test_strdup("-t");
442 : 1 : ret = rte_argparse_parse(obj, 2, argv);
443 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
444 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
445 : :
446 : : /* test with value. */
447 : 1 : obj->args[0].flags = flags;
448 : 1 : val_saver = 0;
449 : 1 : argv[1] = test_strdup("--test-long=200");
450 : 1 : ret = rte_argparse_parse(obj, 2, argv);
451 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
452 [ - + ]: 1 : TEST_ASSERT(val_saver == 200, "Argparse parse expect success!");
453 : 1 : obj->args[0].flags = flags;
454 : 1 : val_saver = 0;
455 : 1 : argv[1] = test_strdup("-t=200");
456 : 1 : ret = rte_argparse_parse(obj, 2, argv);
457 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
458 [ - + ]: 1 : TEST_ASSERT(val_saver == 200, "Argparse parse expect success!");
459 : :
460 : : /* test with option value, but with wrong value. */
461 : 1 : obj->args[0].flags = flags;
462 : 1 : val_saver = 0;
463 : 1 : argv[1] = test_strdup("--test-long=200a");
464 : 1 : ret = rte_argparse_parse(obj, 2, argv);
465 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
466 : 1 : obj->args[0].flags = flags;
467 : 1 : val_saver = 0;
468 : 1 : argv[1] = test_strdup("-t=200a");
469 : 1 : ret = rte_argparse_parse(obj, 2, argv);
470 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
471 : :
472 : : return 0;
473 : : }
474 : :
475 : : static int
476 : 2 : opt_callback_parse_int_of_no_val(uint32_t index, const char *value, void *opaque)
477 : : {
478 [ + - ]: 2 : if (index != 1)
479 : : return -EINVAL;
480 [ + - ]: 2 : if (value != NULL)
481 : : return -EINVAL;
482 : 2 : *(int *)opaque = 100;
483 : 2 : return 0;
484 : : }
485 : :
486 : : static int
487 : 1 : test_argparse_opt_callback_parse_int_of_no_val(void)
488 : : {
489 : : struct rte_argparse *obj;
490 : 1 : int val_saver = 0;
491 : : char *argv[2];
492 : : int ret;
493 : :
494 : : obj = test_argparse_init_obj();
495 : 1 : obj->callback = opt_callback_parse_int_of_no_val;
496 : 1 : obj->opaque = (void *)&val_saver;
497 : 1 : obj->args[0].name_long = "--test-long";
498 : 1 : obj->args[0].name_short = "-t";
499 : 1 : obj->args[0].val_saver = NULL;
500 : 1 : obj->args[0].val_set = (void *)1;
501 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE;
502 : 1 : obj->args[1].name_long = NULL;
503 : 1 : argv[0] = test_strdup(obj->prog_name);
504 : 1 : argv[1] = test_strdup("--test-long");
505 : 1 : ret = rte_argparse_parse(obj, 2, argv);
506 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
507 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
508 : :
509 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_NO_VALUE;
510 : 1 : val_saver = 0;
511 : 1 : argv[1] = test_strdup("-t");
512 : 1 : ret = rte_argparse_parse(obj, 2, argv);
513 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
514 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
515 : :
516 : : return 0;
517 : : }
518 : :
519 : : static int
520 : 3 : opt_callback_parse_int_of_required_val(uint32_t index, const char *value, void *opaque)
521 : : {
522 : 3 : char *s = NULL;
523 : :
524 [ + - ]: 3 : if (index != 1)
525 : : return -EINVAL;
526 : :
527 [ + - ]: 3 : if (value == NULL)
528 : : return -EINVAL;
529 : 3 : *(int *)opaque = strtol(value, &s, 0);
530 : :
531 [ + + ]: 3 : if (s[0] != '\0')
532 : 1 : return -EINVAL;
533 : :
534 : : return 0;
535 : : }
536 : :
537 : : static int
538 : 1 : test_argparse_opt_callback_parse_int_of_required_val(void)
539 : : {
540 : : struct rte_argparse *obj;
541 : 1 : int val_saver = 0;
542 : : char *argv[3];
543 : : int ret;
544 : :
545 : : obj = test_argparse_init_obj();
546 : 1 : obj->callback = opt_callback_parse_int_of_required_val;
547 : 1 : obj->opaque = (void *)&val_saver;
548 : 1 : obj->args[0].name_long = "--test-long";
549 : 1 : obj->args[0].name_short = "-t";
550 : 1 : obj->args[0].val_saver = NULL;
551 : 1 : obj->args[0].val_set = (void *)1;
552 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
553 : 1 : obj->args[1].name_long = NULL;
554 : 1 : argv[0] = test_strdup(obj->prog_name);
555 : 1 : argv[1] = test_strdup("--test-long");
556 : 1 : argv[2] = test_strdup("100");
557 : 1 : ret = rte_argparse_parse(obj, 3, argv);
558 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
559 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
560 : :
561 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
562 : 1 : val_saver = 0;
563 : 1 : argv[1] = test_strdup("-t");
564 : 1 : ret = rte_argparse_parse(obj, 3, argv);
565 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
566 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
567 : :
568 : : /* test no more parameters. */
569 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
570 : 1 : ret = rte_argparse_parse(obj, 2, argv);
571 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
572 : :
573 : : /* test callback return failed. */
574 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
575 : 1 : argv[2] = test_strdup("100a");
576 : 1 : ret = rte_argparse_parse(obj, 3, argv);
577 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
578 : :
579 : : return 0;
580 : : }
581 : :
582 : : static int
583 : 5 : opt_callback_parse_int_of_optional_val(uint32_t index, const char *value, void *opaque)
584 : : {
585 : 5 : char *s = NULL;
586 : :
587 [ + - ]: 5 : if (index != 1)
588 : : return -EINVAL;
589 : :
590 [ + + ]: 5 : if (value == NULL) {
591 : 2 : *(int *)opaque = 10;
592 : : } else {
593 : 3 : *(int *)opaque = strtol(value, &s, 0);
594 [ + + ]: 3 : if (s[0] != '\0')
595 : 1 : return -EINVAL;
596 : : }
597 : :
598 : : return 0;
599 : : }
600 : :
601 : : static int
602 : 1 : test_argparse_opt_callback_parse_int_of_optional_val(void)
603 : : {
604 : : struct rte_argparse *obj;
605 : 1 : int val_saver = 0;
606 : : char *argv[2];
607 : : int ret;
608 : :
609 : : obj = test_argparse_init_obj();
610 : 1 : obj->callback = opt_callback_parse_int_of_optional_val;
611 : 1 : obj->opaque = (void *)&val_saver;
612 : 1 : obj->args[0].name_long = "--test-long";
613 : 1 : obj->args[0].name_short = "-t";
614 : 1 : obj->args[0].val_saver = NULL;
615 : 1 : obj->args[0].val_set = (void *)1;
616 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE;
617 : 1 : obj->args[1].name_long = NULL;
618 : 1 : argv[0] = test_strdup(obj->prog_name);
619 : 1 : argv[1] = test_strdup("--test-long");
620 : 1 : ret = rte_argparse_parse(obj, 2, argv);
621 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
622 [ - + ]: 1 : TEST_ASSERT(val_saver == 10, "Argparse parse expect success!");
623 : :
624 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE;
625 : 1 : val_saver = 0;
626 : 1 : argv[1] = test_strdup("-t");
627 : 1 : ret = rte_argparse_parse(obj, 2, argv);
628 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
629 [ - + ]: 1 : TEST_ASSERT(val_saver == 10, "Argparse parse expect success!");
630 : :
631 : : /* test with value. */
632 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE;
633 : 1 : val_saver = 0;
634 : 1 : argv[1] = test_strdup("--test-long=100");
635 : 1 : ret = rte_argparse_parse(obj, 2, argv);
636 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
637 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
638 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE;
639 : 1 : val_saver = 0;
640 : 1 : argv[1] = test_strdup("-t=100");
641 : 1 : ret = rte_argparse_parse(obj, 2, argv);
642 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
643 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
644 : :
645 : : /* test callback return failed. */
646 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_OPTIONAL_VALUE;
647 : 1 : argv[1] = test_strdup("-t=100a");
648 : 1 : ret = rte_argparse_parse(obj, 2, argv);
649 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
650 : :
651 : : return 0;
652 : : }
653 : :
654 : : static int
655 : 1 : 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 : 1 : 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 : 1 : obj->args[0].name_long = "test-long";
666 : 1 : obj->args[0].name_short = NULL;
667 : 1 : obj->args[0].val_saver = (void *)&val_saver;
668 : 1 : obj->args[0].val_set = NULL;
669 : 1 : obj->args[0].flags = flags;
670 : 1 : obj->args[1].name_long = NULL;
671 : 1 : argv[0] = test_strdup(obj->prog_name);
672 : 1 : argv[1] = test_strdup("100");
673 : 1 : ret = rte_argparse_parse(obj, 2, argv);
674 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
675 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
676 : :
677 : : /* test positional autosave parse failed. */
678 : 1 : obj->args[0].flags = flags;
679 : 1 : val_saver = 0;
680 : 1 : argv[1] = test_strdup("100a");
681 : 1 : ret = rte_argparse_parse(obj, 2, argv);
682 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
683 : :
684 : : /* test too much position parameters. */
685 : 1 : obj->args[0].flags = flags;
686 : 1 : argv[1] = test_strdup("100");
687 : 1 : argv[2] = test_strdup("200");
688 : 1 : ret = rte_argparse_parse(obj, 3, argv);
689 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
690 : :
691 : : return 0;
692 : : }
693 : :
694 : : static int
695 : 4 : pos_callback_parse_int(uint32_t index, const char *value, void *opaque)
696 : : {
697 : : uint32_t int_val;
698 : 4 : char *s = NULL;
699 : :
700 [ + - ]: 4 : if (index != 1 && index != 2)
701 : : return -EINVAL;
702 [ + - ]: 4 : if (value == NULL)
703 : : return -EINVAL;
704 : :
705 : 4 : int_val = strtol(value, &s, 0);
706 [ + + ]: 4 : if (s[0] != '\0')
707 : : return -EINVAL;
708 : :
709 : 3 : *((int *)opaque + index) = int_val;
710 : :
711 : 3 : return 0;
712 : : }
713 : :
714 : : static int
715 : 1 : test_argparse_pos_callback_parse_int(void)
716 : : {
717 : 1 : 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 : 1 : obj->callback = pos_callback_parse_int;
725 : 1 : obj->opaque = (void *)val_saver;
726 : 1 : obj->args[0].name_long = "test-long1";
727 : 1 : obj->args[0].name_short = NULL;
728 : 1 : obj->args[0].val_saver = NULL;
729 : 1 : obj->args[0].val_set = (void *)1;
730 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
731 : 1 : obj->args[1].name_long = "test-long2";
732 : 1 : obj->args[1].name_short = NULL;
733 : 1 : obj->args[1].val_saver = NULL;
734 : 1 : obj->args[1].val_set = (void *)2;
735 : 1 : obj->args[1].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
736 : 1 : obj->args[2].name_long = NULL;
737 : 1 : argv[0] = test_strdup(obj->prog_name);
738 : 1 : argv[1] = test_strdup("100");
739 : 1 : argv[2] = test_strdup("200");
740 : 1 : ret = rte_argparse_parse(obj, 3, argv);
741 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse expect success!");
742 [ - + ]: 1 : TEST_ASSERT(val_saver[1] == 100, "Argparse parse expect success!");
743 [ - + ]: 1 : TEST_ASSERT(val_saver[2] == 200, "Argparse parse expect success!");
744 : :
745 : : /* test positional callback parse failed. */
746 : 1 : obj->args[0].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
747 : 1 : obj->args[1].flags = RTE_ARGPARSE_ARG_REQUIRED_VALUE;
748 : 1 : argv[2] = test_strdup("200a");
749 : 1 : ret = rte_argparse_parse(obj, 3, argv);
750 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
751 : :
752 : : return 0;
753 : : }
754 : :
755 : : static int
756 : 1 : test_argparse_parse_type(void)
757 : : {
758 : 1 : char *str_erange = test_strdup("9999999999999999999999999999999999");
759 : 1 : char *str_erange_u32 = test_strdup("4294967296");
760 : 1 : char *str_erange_u16 = test_strdup("65536");
761 : 1 : char *str_erange_u8 = test_strdup("256");
762 : 1 : char *str_invalid = test_strdup("1a");
763 : 1 : 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 : 1 : ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_INT, &val_int);
773 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
774 : 1 : ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_INT, &val_int);
775 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
776 : 1 : ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_INT, &val_int);
777 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
778 [ - + ]: 1 : TEST_ASSERT(val_int == 123, "Argparse parse type expect failed!");
779 : :
780 : : /* test for u8 parsing */
781 : 1 : ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8);
782 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
783 : 1 : ret = rte_argparse_parse_type(str_erange_u8, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8);
784 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
785 : 1 : ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8);
786 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
787 : 1 : val_u8 = 0;
788 : 1 : ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U8, &val_u8);
789 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
790 [ - + ]: 1 : TEST_ASSERT(val_u8 == 123, "Argparse parse type expect failed!");
791 : :
792 : : /* test for u16 parsing */
793 : 1 : ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16);
794 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
795 : 1 : ret = rte_argparse_parse_type(str_erange_u16, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16);
796 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
797 : 1 : ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16);
798 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
799 : 1 : val_u16 = 0;
800 : 1 : ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U16, &val_u16);
801 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
802 [ - + ]: 1 : TEST_ASSERT(val_u16 == 123, "Argparse parse type expect failed!");
803 : :
804 : : /* test for u32 parsing */
805 : 1 : ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32);
806 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
807 : 1 : ret = rte_argparse_parse_type(str_erange_u32, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32);
808 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
809 : 1 : ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32);
810 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
811 : 1 : val_u32 = 0;
812 : 1 : ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U32, &val_u32);
813 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
814 [ - + ]: 1 : TEST_ASSERT(val_u32 == 123, "Argparse parse type expect failed!");
815 : :
816 : : /* test for u64 parsing */
817 : 1 : ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64);
818 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
819 : 1 : ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64);
820 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
821 : 1 : val_u64 = 0;
822 : 1 : ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_ARG_VALUE_U64, &val_u64);
823 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
824 [ - + ]: 1 : 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 : 1 : test_argparse(void)
858 : : {
859 : 1 : return unit_test_suite_runner(&argparse_test_suite);
860 : : }
861 : :
862 : 251 : REGISTER_FAST_TEST(argparse_autotest, true, true, test_argparse);
|