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