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 : : #include <rte_os.h>
10 : :
11 : : #include "test.h"
12 : :
13 : : static int default_argc;
14 : : static char *default_argv[1];
15 : :
16 : : #define MAX_STRDUP_STORE_NUM 512
17 : : static char *strdup_store_array[MAX_STRDUP_STORE_NUM];
18 : : static uint32_t strdup_store_index;
19 : :
20 : : /*
21 : : * Define strdup wrapper.
22 : : * 1. Mainly to fix compile error "warning: assignment discards 'const'
23 : : * qualifier from pointer target type [-Wdiscarded-qualifiers]" for
24 : : * following code:
25 : : * argv[x] = "100";
26 : : * 2. The strdup result will store in the strdup_store_array, and then
27 : : * freed in the teardown function, prevent ASAN errors from being
28 : : * triggered.
29 : : */
30 : : static char *
31 : 155 : test_strdup(const char *str)
32 : : {
33 : 155 : char *s = strdup(str);
34 [ - + ]: 155 : if (s == NULL) {
35 : : printf("strdup failed! exiting...\n");
36 : 0 : exit(-ENOMEM);
37 : : }
38 [ - + ]: 155 : if (strdup_store_index >= MAX_STRDUP_STORE_NUM) {
39 : : printf("too much strdup calls! exiting...\n");
40 : 0 : exit(-ERANGE);
41 : : }
42 : 155 : strdup_store_array[strdup_store_index++] = s;
43 : 155 : return s;
44 : : }
45 : :
46 : : static int
47 : 1 : test_argparse_setup(void)
48 : : {
49 : 1 : strdup_store_index = 0;
50 : 1 : default_argc = 1;
51 : 1 : default_argv[0] = test_strdup("test_argparse");
52 : 1 : return 0;
53 : : }
54 : :
55 : : static void
56 : 1 : test_argparse_teardown(void)
57 : : {
58 : : uint32_t i;
59 : 1 : printf("total used strdup_store_index = %u\n", strdup_store_index);
60 [ + + ]: 156 : for (i = 0; i < strdup_store_index; i++)
61 : 155 : free(strdup_store_array[i]);
62 : 1 : strdup_store_index = 0;
63 : 1 : }
64 : :
65 : : static int
66 : 18 : test_argparse_callback(uint32_t index, const char *value, void *opaque)
67 : : {
68 : : RTE_SET_USED(index);
69 : : RTE_SET_USED(value);
70 : : RTE_SET_USED(opaque);
71 : 18 : return 0;
72 : : }
73 : :
74 : : /* valid templater, must contain at least two args. */
75 : : #define ARGPARSE_TEMPLATE { \
76 : : .prog_name = "test_argparse", \
77 : : .usage = "-a xx -b yy", \
78 : : .descriptor = NULL, \
79 : : .epilog = NULL, \
80 : : .exit_on_error = false, \
81 : : .callback = test_argparse_callback, \
82 : : .args = { \
83 : : { "--abc", "-a", "abc argument", (void *)1, (void *)1, \
84 : : RTE_ARGPARSE_VALUE_NONE, RTE_ARGPARSE_VALUE_TYPE_NONE }, \
85 : : { "--xyz", "-x", "xyz argument", (void *)1, (void *)2, \
86 : : RTE_ARGPARSE_VALUE_NONE, RTE_ARGPARSE_VALUE_TYPE_NONE }, \
87 : : ARGPARSE_ARG_END(), \
88 : : }, \
89 : : }
90 : :
91 : :
92 : : static struct rte_argparse *
93 : 54 : test_argparse_init_obj(void)
94 : : {
95 : : /* Note: initialization of structure with flexible array
96 : : * increases the size of the variable to match.
97 : : */
98 : : static const struct rte_argparse backup = ARGPARSE_TEMPLATE;
99 : : static struct rte_argparse obj = ARGPARSE_TEMPLATE;
100 : : unsigned int i;
101 : :
102 : 54 : obj = backup;
103 : 108 : for (i = 0; ; i++) {
104 : 162 : obj.args[i] = backup.args[i];
105 [ + + ]: 162 : if (backup.args[i].name_long == NULL)
106 : : break;
107 : : }
108 : :
109 : 54 : return &obj;
110 : : }
111 : :
112 : : static int
113 : 1 : test_argparse_invalid_basic_param(void)
114 : : {
115 : : struct rte_argparse *obj;
116 : : int ret;
117 : :
118 : 1 : obj = test_argparse_init_obj();
119 : 1 : obj->prog_name = NULL;
120 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
121 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
122 : :
123 : 1 : obj = test_argparse_init_obj();
124 : 1 : obj->usage = NULL;
125 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
126 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
127 : :
128 : : return TEST_SUCCESS;
129 : : }
130 : :
131 : : static int
132 : 1 : test_argparse_invalid_arg_name(void)
133 : : {
134 : : struct rte_argparse *obj;
135 : : int ret;
136 : :
137 : 1 : obj = test_argparse_init_obj();
138 : 1 : obj->args[0].name_long = "-ab";
139 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
140 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
141 : :
142 : 1 : obj = test_argparse_init_obj();
143 : 1 : obj->args[0].name_long = "-abc";
144 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
145 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
146 : :
147 : 1 : obj = test_argparse_init_obj();
148 : 1 : obj->args[0].name_long = "---c";
149 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
150 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
151 : :
152 : 1 : obj = test_argparse_init_obj();
153 : 1 : obj->args[0].name_long = "abc";
154 : 1 : obj->args[0].name_short = "-a";
155 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
156 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
157 : :
158 : 1 : obj = test_argparse_init_obj();
159 : 1 : obj->args[0].name_short = "a";
160 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
161 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
162 : :
163 : 1 : obj = test_argparse_init_obj();
164 : 1 : obj->args[0].name_short = "abc";
165 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
166 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
167 : :
168 : 1 : obj = test_argparse_init_obj();
169 : 1 : obj->args[0].name_short = "ab";
170 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
171 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
172 : :
173 : : return 0;
174 : : }
175 : :
176 : : static int
177 : 1 : test_argparse_invalid_arg_help(void)
178 : : {
179 : : struct rte_argparse *obj;
180 : : int ret;
181 : :
182 : 1 : obj = test_argparse_init_obj();
183 : 1 : obj->args[0].help = NULL;
184 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
185 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
186 : :
187 : : return 0;
188 : : }
189 : :
190 : : static int
191 : 1 : test_argparse_invalid_has_val(void)
192 : : {
193 : 1 : uint64_t invalid_values[] = {
194 : : RTE_ARGPARSE_VALUE_NONE,
195 : : RTE_ARGPARSE_VALUE_OPTIONAL,
196 : : };
197 : : struct rte_argparse *obj;
198 : : uint32_t index;
199 : : int ret;
200 : :
201 : : /* test positional arg don't config required-value. */
202 [ + + ]: 3 : for (index = 0; index < RTE_DIM(invalid_values); index++) {
203 : 2 : obj = test_argparse_init_obj();
204 : 2 : obj->args[0].name_long = "abc";
205 : 2 : obj->args[0].name_short = NULL;
206 : 2 : obj->args[0].value_required = invalid_values[index];
207 : 2 : ret = rte_argparse_parse(obj, default_argc, default_argv);
208 [ - + ]: 2 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
209 : : }
210 : :
211 : : return 0;
212 : : }
213 : :
214 : : static int
215 : 1 : test_argparse_invalid_arg_saver(void)
216 : : {
217 : : struct rte_argparse *obj;
218 : : int ret;
219 : :
220 : : /* test saver == NULL with val-type != 0. */
221 : 1 : obj = test_argparse_init_obj();
222 : 1 : obj->args[0].val_saver = NULL;
223 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_NONE;
224 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
225 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
226 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
227 : :
228 : : /* test saver == NULL with callback is NULL. */
229 : 1 : obj = test_argparse_init_obj();
230 : 1 : obj->args[0].val_saver = NULL;
231 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_NONE;
232 : 1 : obj->callback = NULL;
233 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
234 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
235 : :
236 : : /* test saver != NULL with val-type is zero! */
237 : 1 : obj = test_argparse_init_obj();
238 : 1 : obj->args[0].val_saver = (void *)1;
239 : 1 : obj->args[0].val_set = (void *)1;
240 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_NONE;
241 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
242 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
243 : :
244 : : /* test saver != NULL with required value, but val-set is not NULL. */
245 : 1 : obj = test_argparse_init_obj();
246 : 1 : obj->args[0].val_saver = (void *)1;
247 : 1 : obj->args[0].val_set = (void *)1;
248 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
249 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
250 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
251 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
252 : :
253 : : return 0;
254 : : }
255 : :
256 : : static int
257 : 1 : test_argparse_invalid_arg_flags(void)
258 : : {
259 : : struct rte_argparse *obj;
260 : : int ret;
261 : :
262 : : /* test set unused bits. */
263 : 1 : obj = test_argparse_init_obj();
264 : 1 : obj->args[0].flags |= ~(RTE_ARGPARSE_FLAG_SUPPORT_MULTI);
265 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
266 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
267 : :
268 : : /* test positional arg should not config multiple. */
269 : 1 : obj = test_argparse_init_obj();
270 : 1 : obj->args[0].name_long = "positional";
271 : 1 : obj->args[0].name_short = NULL;
272 : 1 : obj->args[0].val_saver = (void *)1;
273 : 1 : obj->args[0].val_set = NULL;
274 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
275 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
276 : 1 : obj->args[0].flags |= RTE_ARGPARSE_FLAG_SUPPORT_MULTI;
277 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
278 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
279 : :
280 : : /* test optional arg enabled multiple but prased by autosave. */
281 : 1 : obj = test_argparse_init_obj();
282 : 1 : obj->args[0].flags |= RTE_ARGPARSE_FLAG_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 : : return 0;
287 : : }
288 : :
289 : : static int
290 : 1 : test_argparse_invalid_arg_repeat(void)
291 : : {
292 : : struct rte_argparse *obj;
293 : : int ret;
294 : :
295 : : /* test for long name repeat! */
296 : 1 : obj = test_argparse_init_obj();
297 : 1 : obj->args[1].name_long = obj->args[0].name_long;
298 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
299 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
300 : :
301 : : /* test for short name repeat! */
302 : 1 : obj = test_argparse_init_obj();
303 : 1 : obj->args[1].name_short = obj->args[0].name_short;
304 : 1 : ret = rte_argparse_parse(obj, default_argc, default_argv);
305 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
306 : :
307 : : return 0;
308 : : }
309 : :
310 : : static int
311 : 1 : test_argparse_invalid_option(void)
312 : : {
313 : : struct rte_argparse *obj;
314 : : char *argv[2];
315 : : int ret;
316 : :
317 : 1 : obj = test_argparse_init_obj();
318 : 1 : argv[0] = test_strdup(obj->prog_name);
319 : 1 : argv[1] = test_strdup("--invalid");
320 : 1 : ret = rte_argparse_parse(obj, 2, argv);
321 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
322 : :
323 : 1 : obj = test_argparse_init_obj();
324 : 1 : argv[0] = test_strdup(obj->prog_name);
325 : 1 : argv[1] = test_strdup("invalid");
326 : 1 : ret = rte_argparse_parse(obj, 2, argv);
327 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
328 : :
329 : : return 0;
330 : : }
331 : :
332 : : static int
333 : 1 : test_argparse_invalid_repeated_option(void)
334 : : {
335 : : /* test that we allow repeated args only with the MULTI flag */
336 : : struct rte_argparse *obj;
337 : : char *argv[3];
338 : : int ret;
339 : :
340 : : /* check that we error out with two "-a" flags */
341 : 1 : obj = test_argparse_init_obj();
342 : 1 : obj->args[0].val_saver = NULL;
343 : 1 : obj->args[1].val_saver = NULL;
344 : 1 : argv[0] = test_strdup(obj->prog_name);
345 : 1 : argv[1] = test_strdup("-a");
346 : 1 : argv[2] = test_strdup("-a");
347 : 1 : ret = rte_argparse_parse(obj, 3, argv);
348 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse did not error out with two '-a' flags!");
349 : :
350 : 1 : obj = test_argparse_init_obj();
351 : 1 : obj->args[0].val_saver = NULL;
352 : 1 : obj->args[1].val_saver = NULL;
353 : 1 : obj->args[0].flags |= RTE_ARGPARSE_FLAG_SUPPORT_MULTI;
354 : : /* check that we allow two "-a" flags with MULTI flag set */
355 : 1 : argv[0] = test_strdup(obj->prog_name);
356 : 1 : argv[1] = test_strdup("-a");
357 : 1 : argv[2] = test_strdup("-a");
358 : 1 : ret = rte_argparse_parse(obj, 3, argv);
359 [ - + ]: 1 : TEST_ASSERT(ret == 3, "Argparse failed to handle duplicate '-a' flags!");
360 : :
361 : : return 0;
362 : : }
363 : :
364 : : static int
365 : 1 : test_argparse_opt_autosave_parse_int_of_no_val(void)
366 : : {
367 : : struct rte_argparse *obj;
368 : 1 : int val_saver = 0;
369 : : char *argv[2];
370 : : int ret;
371 : :
372 : 1 : obj = test_argparse_init_obj();
373 : 1 : obj->args[0].name_long = "--test-long";
374 : 1 : obj->args[0].name_short = "-t";
375 : 1 : obj->args[0].val_saver = (void *)&val_saver;
376 : 1 : obj->args[0].val_set = (void *)100;
377 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_NONE;
378 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
379 : 1 : obj->args[1].name_long = NULL;
380 : 1 : argv[0] = test_strdup(obj->prog_name);
381 : 1 : argv[1] = test_strdup("--test-long");
382 : 1 : ret = rte_argparse_parse(obj, 2, argv);
383 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse expect success!");
384 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
385 : :
386 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_NONE;
387 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
388 : 1 : val_saver = 0;
389 : 1 : argv[1] = test_strdup("-t");
390 : 1 : ret = rte_argparse_parse(obj, 2, argv);
391 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse expect success!");
392 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
393 : :
394 : : return 0;
395 : : }
396 : :
397 : : static int
398 : 1 : test_argparse_opt_autosave_parse_int_of_required_val(void)
399 : : {
400 : : struct rte_argparse *obj;
401 : 1 : int val_saver = 0;
402 : : char *argv[3];
403 : : int ret;
404 : :
405 : 1 : obj = test_argparse_init_obj();
406 : 1 : obj->args[0].name_long = "--test-long";
407 : 1 : obj->args[0].name_short = "-t";
408 : 1 : obj->args[0].val_saver = (void *)&val_saver;
409 : 1 : obj->args[0].val_set = NULL;
410 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
411 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
412 : 1 : obj->args[1].name_long = NULL;
413 : 1 : argv[0] = test_strdup(obj->prog_name);
414 : 1 : argv[1] = test_strdup("--test-long");
415 : 1 : argv[2] = test_strdup("100");
416 : 1 : ret = rte_argparse_parse(obj, 3, argv);
417 [ - + ]: 1 : TEST_ASSERT(ret == 3, "Argparse parse expect success!");
418 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
419 : :
420 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
421 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
422 : 1 : val_saver = 0;
423 : 1 : argv[1] = test_strdup("-t");
424 : 1 : ret = rte_argparse_parse(obj, 3, argv);
425 [ - + ]: 1 : TEST_ASSERT(ret == 3, "Argparse parse expect success!");
426 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
427 : :
428 : : /* test invalid value. */
429 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
430 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
431 : 1 : val_saver = 0;
432 : 1 : argv[1] = test_strdup("-t");
433 : 1 : argv[2] = test_strdup("100a");
434 : 1 : ret = rte_argparse_parse(obj, 3, argv);
435 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
436 : :
437 : : return 0;
438 : : }
439 : :
440 : : static int
441 : 1 : test_argparse_opt_autosave_parse_int_of_optional_val(void)
442 : : {
443 : : struct rte_argparse *obj;
444 : 1 : int val_saver = 0;
445 : : char *argv[2];
446 : : int ret;
447 : :
448 : : /* test without value. */
449 : 1 : obj = test_argparse_init_obj();
450 : 1 : obj->args[0].name_long = "--test-long";
451 : 1 : obj->args[0].name_short = "-t";
452 : 1 : obj->args[0].val_saver = (void *)&val_saver;
453 : 1 : obj->args[0].val_set = (void *)100;
454 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_OPTIONAL;
455 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
456 : 1 : obj->args[1].name_long = NULL;
457 : 1 : argv[0] = test_strdup(obj->prog_name);
458 : 1 : argv[1] = test_strdup("--test-long");
459 : 1 : ret = rte_argparse_parse(obj, 2, argv);
460 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse expect success!");
461 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
462 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_OPTIONAL;
463 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
464 : 1 : val_saver = 0;
465 : 1 : argv[1] = test_strdup("-t");
466 : 1 : ret = rte_argparse_parse(obj, 2, argv);
467 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse expect success!");
468 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
469 : :
470 : : /* test with value. */
471 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_OPTIONAL;
472 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
473 : 1 : val_saver = 0;
474 : 1 : argv[1] = test_strdup("--test-long=200");
475 : 1 : ret = rte_argparse_parse(obj, 2, argv);
476 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse expect success!");
477 [ - + ]: 1 : TEST_ASSERT(val_saver == 200, "Argparse parse expect success!");
478 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_OPTIONAL;
479 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
480 : 1 : val_saver = 0;
481 : 1 : argv[1] = test_strdup("-t=200");
482 : 1 : ret = rte_argparse_parse(obj, 2, argv);
483 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse expect success!");
484 [ - + ]: 1 : TEST_ASSERT(val_saver == 200, "Argparse parse expect success!");
485 : :
486 : : /* test with option value, but with wrong value. */
487 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_OPTIONAL;
488 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
489 : 1 : val_saver = 0;
490 : 1 : argv[1] = test_strdup("--test-long=200a");
491 : 1 : ret = rte_argparse_parse(obj, 2, argv);
492 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
493 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_OPTIONAL;
494 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
495 : 1 : val_saver = 0;
496 : 1 : argv[1] = test_strdup("-t=200a");
497 : 1 : ret = rte_argparse_parse(obj, 2, argv);
498 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
499 : :
500 : : return 0;
501 : : }
502 : :
503 : : static int
504 : 1 : test_argparse_opt_parse_corelist_of_required_val(void)
505 : : {
506 : : struct rte_argparse *obj;
507 : : rte_cpuset_t val_cpuset;
508 : : char *argv[3];
509 : : int ret;
510 : :
511 : : /* test with long option and single core - this is known to work */
512 : 1 : obj = test_argparse_init_obj();
513 : 1 : obj->args[0].name_long = "--corelist";
514 : 1 : obj->args[0].name_short = "-c";
515 : 1 : obj->args[0].val_saver = (void *)&val_cpuset;
516 : 1 : obj->args[0].val_set = NULL;
517 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
518 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_CORELIST;
519 : 1 : obj->args[1].name_long = NULL;
520 : 1 : argv[0] = test_strdup(obj->prog_name);
521 : 1 : argv[1] = test_strdup("--corelist");
522 : 1 : argv[2] = test_strdup("1,3-5");
523 : 1 : CPU_ZERO(&val_cpuset);
524 : 1 : ret = rte_argparse_parse(obj, 3, argv);
525 [ - + ]: 1 : TEST_ASSERT(ret == 3, "Argparse parse expect success!");
526 [ - + ]: 1 : TEST_ASSERT(!CPU_ISSET(0, &val_cpuset), "Core 0 should not be set in corelist!");
527 [ - + ]: 1 : TEST_ASSERT(CPU_ISSET(1, &val_cpuset), "Core 1 should be set in corelist!");
528 [ + - ]: 1 : TEST_ASSERT(!CPU_ISSET(2, &val_cpuset), "Core 2 should not be set in corelist!");
529 [ - + ]: 1 : TEST_ASSERT(CPU_ISSET(3, &val_cpuset), "Core 3 should be set in corelist!");
530 [ - + ]: 1 : TEST_ASSERT(CPU_ISSET(4, &val_cpuset), "Core 4 should be set in corelist!");
531 [ - + ]: 1 : TEST_ASSERT(CPU_ISSET(5, &val_cpuset), "Core 5 should be set in corelist!");
532 [ - + ]: 1 : TEST_ASSERT(!CPU_ISSET(6, &val_cpuset), "Core 6 should not be set in corelist!");
533 : :
534 : : return 0;
535 : : }
536 : :
537 : : static int
538 : 2 : opt_callback_parse_int_of_no_val(uint32_t index, const char *value, void *opaque)
539 : : {
540 [ + - ]: 2 : if (index != 1)
541 : : return -EINVAL;
542 [ + - ]: 2 : if (value != NULL)
543 : : return -EINVAL;
544 : 2 : *(int *)opaque = 100;
545 : 2 : return 0;
546 : : }
547 : :
548 : : static int
549 : 1 : test_argparse_opt_callback_parse_int_of_no_val(void)
550 : : {
551 : : struct rte_argparse *obj;
552 : 1 : int val_saver = 0;
553 : : char *argv[2];
554 : : int ret;
555 : :
556 : 1 : obj = test_argparse_init_obj();
557 : 1 : obj->callback = opt_callback_parse_int_of_no_val;
558 : 1 : obj->opaque = (void *)&val_saver;
559 : 1 : obj->args[0].name_long = "--test-long";
560 : 1 : obj->args[0].name_short = "-t";
561 : 1 : obj->args[0].val_saver = NULL;
562 : 1 : obj->args[0].val_set = (void *)1;
563 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_NONE;
564 : 1 : obj->args[1].name_long = NULL;
565 : 1 : argv[0] = test_strdup(obj->prog_name);
566 : 1 : argv[1] = test_strdup("--test-long");
567 : 1 : ret = rte_argparse_parse(obj, 2, argv);
568 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse expect success!");
569 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
570 : :
571 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_NONE;
572 : 1 : val_saver = 0;
573 : 1 : argv[1] = test_strdup("-t");
574 : 1 : ret = rte_argparse_parse(obj, 2, argv);
575 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse expect success!");
576 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
577 : :
578 : : return 0;
579 : : }
580 : :
581 : : static int
582 : 3 : opt_callback_parse_int_of_required_val(uint32_t index, const char *value, void *opaque)
583 : : {
584 : 3 : char *s = NULL;
585 : :
586 [ + - ]: 3 : if (index != 1)
587 : : return -EINVAL;
588 : :
589 [ + - ]: 3 : if (value == NULL)
590 : : return -EINVAL;
591 : 3 : *(int *)opaque = strtol(value, &s, 0);
592 : :
593 [ + + ]: 3 : if (s[0] != '\0')
594 : 1 : return -EINVAL;
595 : :
596 : : return 0;
597 : : }
598 : :
599 : : static int
600 : 1 : test_argparse_opt_callback_parse_int_of_required_val(void)
601 : : {
602 : : struct rte_argparse *obj;
603 : 1 : int val_saver = 0;
604 : : char *argv[3];
605 : : int ret;
606 : :
607 : 1 : obj = test_argparse_init_obj();
608 : 1 : obj->callback = opt_callback_parse_int_of_required_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].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
615 : 1 : obj->args[1].name_long = NULL;
616 : 1 : argv[0] = test_strdup(obj->prog_name);
617 : 1 : argv[1] = test_strdup("--test-long");
618 : 1 : argv[2] = test_strdup("100");
619 : 1 : ret = rte_argparse_parse(obj, 3, argv);
620 [ - + ]: 1 : TEST_ASSERT(ret == 3, "Argparse parse expect success!");
621 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
622 : :
623 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
624 : 1 : val_saver = 0;
625 : 1 : argv[1] = test_strdup("-t");
626 : 1 : ret = rte_argparse_parse(obj, 3, argv);
627 [ - + ]: 1 : TEST_ASSERT(ret == 3, "Argparse parse expect success!");
628 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
629 : :
630 : : /* test no more parameters. */
631 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
632 : 1 : ret = rte_argparse_parse(obj, 2, argv);
633 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
634 : :
635 : : /* test callback return failed. */
636 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
637 : 1 : argv[2] = test_strdup("100a");
638 : 1 : ret = rte_argparse_parse(obj, 3, argv);
639 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
640 : :
641 : : return 0;
642 : : }
643 : :
644 : : static int
645 : 5 : opt_callback_parse_int_of_optional_val(uint32_t index, const char *value, void *opaque)
646 : : {
647 : 5 : char *s = NULL;
648 : :
649 [ + - ]: 5 : if (index != 1)
650 : : return -EINVAL;
651 : :
652 [ + + ]: 5 : if (value == NULL) {
653 : 2 : *(int *)opaque = 10;
654 : : } else {
655 : 3 : *(int *)opaque = strtol(value, &s, 0);
656 [ + + ]: 3 : if (s[0] != '\0')
657 : 1 : return -EINVAL;
658 : : }
659 : :
660 : : return 0;
661 : : }
662 : :
663 : : static int
664 : 1 : test_argparse_opt_callback_parse_int_of_optional_val(void)
665 : : {
666 : : struct rte_argparse *obj;
667 : 1 : int val_saver = 0;
668 : : char *argv[2];
669 : : int ret;
670 : :
671 : 1 : obj = test_argparse_init_obj();
672 : 1 : obj->callback = opt_callback_parse_int_of_optional_val;
673 : 1 : obj->opaque = (void *)&val_saver;
674 : 1 : obj->args[0].name_long = "--test-long";
675 : 1 : obj->args[0].name_short = "-t";
676 : 1 : obj->args[0].val_saver = NULL;
677 : 1 : obj->args[0].val_set = (void *)1;
678 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_OPTIONAL;
679 : 1 : obj->args[1].name_long = NULL;
680 : 1 : argv[0] = test_strdup(obj->prog_name);
681 : 1 : argv[1] = test_strdup("--test-long");
682 : 1 : ret = rte_argparse_parse(obj, 2, argv);
683 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse expect success!");
684 [ - + ]: 1 : TEST_ASSERT(val_saver == 10, "Argparse parse expect success!");
685 : :
686 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_OPTIONAL;
687 : 1 : val_saver = 0;
688 : 1 : argv[1] = test_strdup("-t");
689 : 1 : ret = rte_argparse_parse(obj, 2, argv);
690 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse expect success!");
691 [ - + ]: 1 : TEST_ASSERT(val_saver == 10, "Argparse parse expect success!");
692 : :
693 : : /* test with value. */
694 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_OPTIONAL;
695 : 1 : val_saver = 0;
696 : 1 : argv[1] = test_strdup("--test-long=100");
697 : 1 : ret = rte_argparse_parse(obj, 2, argv);
698 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse expect success!");
699 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
700 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_OPTIONAL;
701 : 1 : val_saver = 0;
702 : 1 : argv[1] = test_strdup("-t=100");
703 : 1 : ret = rte_argparse_parse(obj, 2, argv);
704 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse expect success!");
705 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
706 : :
707 : : /* test callback return failed. */
708 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_OPTIONAL;
709 : 1 : argv[1] = test_strdup("-t=100a");
710 : 1 : ret = rte_argparse_parse(obj, 2, argv);
711 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
712 : :
713 : : return 0;
714 : : }
715 : :
716 : : static int
717 : 1 : test_argparse_pos_autosave_parse_int(void)
718 : : {
719 : : struct rte_argparse *obj;
720 : 1 : int val_saver = 0;
721 : : char *argv[3];
722 : : int ret;
723 : :
724 : : /* test positional autosave parse successful. */
725 : 1 : obj = test_argparse_init_obj();
726 : 1 : obj->args[0].name_long = "test-long";
727 : 1 : obj->args[0].name_short = NULL;
728 : 1 : obj->args[0].val_saver = (void *)&val_saver;
729 : 1 : obj->args[0].val_set = NULL;
730 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
731 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
732 : 1 : obj->args[1].name_long = NULL;
733 : 1 : argv[0] = test_strdup(obj->prog_name);
734 : 1 : argv[1] = test_strdup("100");
735 : 1 : ret = rte_argparse_parse(obj, 2, argv);
736 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse expect success!");
737 [ - + ]: 1 : TEST_ASSERT(val_saver == 100, "Argparse parse expect success!");
738 : :
739 : : /* test positional autosave parse failed. */
740 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
741 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
742 : 1 : val_saver = 0;
743 : 1 : argv[1] = test_strdup("100a");
744 : 1 : ret = rte_argparse_parse(obj, 2, argv);
745 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
746 : :
747 : : /* test too much position parameters. */
748 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
749 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
750 : 1 : argv[1] = test_strdup("100");
751 : 1 : argv[2] = test_strdup("200");
752 : 1 : ret = rte_argparse_parse(obj, 3, argv);
753 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
754 : :
755 : : return 0;
756 : : }
757 : :
758 : : static int
759 : 4 : pos_callback_parse_int(uint32_t index, const char *value, void *opaque)
760 : : {
761 : : uint32_t int_val;
762 : 4 : char *s = NULL;
763 : :
764 [ + - ]: 4 : if (index != 1 && index != 2)
765 : : return -EINVAL;
766 [ + - ]: 4 : if (value == NULL)
767 : : return -EINVAL;
768 : :
769 : 4 : int_val = strtol(value, &s, 0);
770 [ + + ]: 4 : if (s[0] != '\0')
771 : : return -EINVAL;
772 : :
773 : 3 : *((int *)opaque + index) = int_val;
774 : :
775 : 3 : return 0;
776 : : }
777 : :
778 : : static int
779 : 1 : test_argparse_pos_callback_parse_int(void)
780 : : {
781 : 1 : int val_saver[3] = { 0, 0, 0 };
782 : : struct rte_argparse *obj;
783 : : char *argv[3];
784 : : int ret;
785 : :
786 : : /* test positional callback parse successful. */
787 : 1 : obj = test_argparse_init_obj();
788 : 1 : obj->callback = pos_callback_parse_int;
789 : 1 : obj->opaque = (void *)val_saver;
790 : 1 : obj->args[0].name_long = "test-long1";
791 : 1 : obj->args[0].name_short = NULL;
792 : 1 : obj->args[0].val_saver = NULL;
793 : 1 : obj->args[0].val_set = (void *)1;
794 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
795 : 1 : obj->args[1].name_long = "test-long2";
796 : 1 : obj->args[1].name_short = NULL;
797 : 1 : obj->args[1].val_saver = NULL;
798 : 1 : obj->args[1].val_set = (void *)2;
799 : 1 : obj->args[1].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
800 : 1 : obj->args[2].name_long = NULL;
801 : 1 : argv[0] = test_strdup(obj->prog_name);
802 : 1 : argv[1] = test_strdup("100");
803 : 1 : argv[2] = test_strdup("200");
804 : 1 : ret = rte_argparse_parse(obj, 3, argv);
805 [ - + ]: 1 : TEST_ASSERT(ret == 3, "Argparse parse expect success!");
806 [ - + ]: 1 : TEST_ASSERT(val_saver[1] == 100, "Argparse parse expect success!");
807 [ - + ]: 1 : TEST_ASSERT(val_saver[2] == 200, "Argparse parse expect success!");
808 : :
809 : : /* test positional callback parse failed. */
810 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
811 : 1 : obj->args[1].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
812 : 1 : argv[2] = test_strdup("200a");
813 : 1 : ret = rte_argparse_parse(obj, 3, argv);
814 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse parse expect failed!");
815 : :
816 : : return 0;
817 : : }
818 : :
819 : : static int
820 : 1 : test_argparse_parse_type_corelist(void)
821 : : {
822 : 1 : char *corelist_valid_single = test_strdup("5");
823 : 1 : char *corelist_valid_multiple = test_strdup("0,1,5");
824 : 1 : char *corelist_valid_range = test_strdup("1-5");
825 : 1 : char *corelist_valid_mixed = test_strdup("0,1,5-10,12-16,18,20");
826 : 1 : char *corelist_valid_reverse_range = test_strdup("10-5");
827 : 1 : char *corelist_valid_initial_spaces = test_strdup(" 1,2,5-7");
828 : 1 : char *corelist_valid_empty = test_strdup("");
829 : 1 : char *corelist_invalid_spaces = test_strdup(" 1 , 2 , 5-7 ");
830 : 1 : char *corelist_invalid_letters = test_strdup("1,a,3");
831 : 1 : char *corelist_invalid_range_incomplete = test_strdup("1-");
832 : 1 : char *corelist_invalid_range_double_dash = test_strdup("1--5");
833 : 1 : char *corelist_invalid_range_double_range = test_strdup("1-3-5");
834 : 1 : char *corelist_invalid_special_chars = test_strdup("1,2@3");
835 : 1 : char *corelist_invalid_comma_only = test_strdup(",");
836 : 1 : char *corelist_invalid_out_of_range = test_strdup("70000");
837 : : rte_cpuset_t val_cpuset;
838 : : int ret;
839 : :
840 : : /* test valid single core */
841 : 1 : CPU_ZERO(&val_cpuset);
842 : 1 : ret = rte_argparse_parse_type(corelist_valid_single,
843 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
844 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type for corelist (single core) failed!");
845 [ + - ]: 1 : TEST_ASSERT(CPU_ISSET(5, &val_cpuset), "Core 5 should be set in corelist!");
846 [ + - ]: 1 : TEST_ASSERT(!CPU_ISSET(0, &val_cpuset), "Core 0 should not be set in corelist!");
847 [ + - ]: 1 : TEST_ASSERT(!CPU_ISSET(1, &val_cpuset), "Core 1 should not be set in corelist!");
848 : :
849 : : /* test valid multiple cores */
850 : 1 : CPU_ZERO(&val_cpuset);
851 : 1 : ret = rte_argparse_parse_type(corelist_valid_multiple,
852 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
853 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type for corelist (multiple cores) failed!");
854 [ - + ]: 1 : TEST_ASSERT(CPU_ISSET(0, &val_cpuset), "Core 0 should be set in corelist!");
855 [ - + ]: 1 : TEST_ASSERT(CPU_ISSET(1, &val_cpuset), "Core 1 should be set in corelist!");
856 [ - + ]: 1 : TEST_ASSERT(CPU_ISSET(5, &val_cpuset), "Core 5 should be set in corelist!");
857 [ + - ]: 1 : TEST_ASSERT(!CPU_ISSET(2, &val_cpuset), "Core 2 should not be set in corelist!");
858 [ + - ]: 1 : TEST_ASSERT(!CPU_ISSET(3, &val_cpuset), "Core 3 should not be set in corelist!");
859 : :
860 : : /* test valid range */
861 : 1 : CPU_ZERO(&val_cpuset);
862 : 1 : ret = rte_argparse_parse_type(corelist_valid_range,
863 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
864 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type for corelist (range) failed!");
865 [ + + ]: 6 : for (int i = 1; i <= 5; i++)
866 [ - + ]: 5 : TEST_ASSERT(CPU_ISSET(i, &val_cpuset), "Core %d should be set in range 1-5!", i);
867 [ + - ]: 1 : TEST_ASSERT(!CPU_ISSET(0, &val_cpuset), "Core 0 should not be set in range 1-5!");
868 [ + - ]: 1 : TEST_ASSERT(!CPU_ISSET(6, &val_cpuset), "Core 6 should not be set in range 1-5!");
869 : :
870 : : /* test valid mixed corelist */
871 : 1 : CPU_ZERO(&val_cpuset);
872 : 1 : ret = rte_argparse_parse_type(corelist_valid_mixed,
873 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
874 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type for corelist (mixed) failed!");
875 [ - + ]: 1 : TEST_ASSERT(CPU_ISSET(0, &val_cpuset), "Core 0 should be set in mixed corelist!");
876 [ - + ]: 1 : TEST_ASSERT(CPU_ISSET(1, &val_cpuset), "Core 1 should be set in mixed corelist!");
877 [ + + ]: 7 : for (int i = 5; i <= 10; i++)
878 [ - + ]: 6 : TEST_ASSERT(CPU_ISSET(i, &val_cpuset), "Core %d should be set in range 5-10!", i);
879 [ + + ]: 6 : for (int i = 12; i <= 16; i++)
880 [ - + ]: 5 : TEST_ASSERT(CPU_ISSET(i, &val_cpuset), "Core %d should be set in range 12-16!", i);
881 : :
882 [ - + ]: 1 : TEST_ASSERT(CPU_ISSET(18, &val_cpuset), "Core 18 should be set in mixed corelist!");
883 [ - + ]: 1 : TEST_ASSERT(CPU_ISSET(20, &val_cpuset), "Core 20 should be set in mixed corelist!");
884 [ + - ]: 1 : TEST_ASSERT(!CPU_ISSET(2, &val_cpuset), "Core 2 should not be set in mixed corelist!");
885 [ + - ]: 1 : TEST_ASSERT(!CPU_ISSET(11, &val_cpuset), "Core 11 should not be set in mixed corelist!");
886 [ + - ]: 1 : TEST_ASSERT(!CPU_ISSET(17, &val_cpuset), "Core 17 should not be set in mixed corelist!");
887 [ + - ]: 1 : TEST_ASSERT(!CPU_ISSET(19, &val_cpuset), "Core 19 should not be set in mixed corelist!");
888 : :
889 : : /* test valid reverse range (10-5 should be interpreted as 5-10) */
890 : 1 : CPU_ZERO(&val_cpuset);
891 : 1 : ret = rte_argparse_parse_type(corelist_valid_reverse_range,
892 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
893 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type for corelist (reverse range) failed!");
894 [ + + ]: 7 : for (int i = 5; i <= 10; i++)
895 [ - + ]: 6 : TEST_ASSERT(CPU_ISSET(i, &val_cpuset),
896 : : "Core %d should be set in reverse range 10-5!", i);
897 [ + - ]: 1 : TEST_ASSERT(!CPU_ISSET(4, &val_cpuset), "Core 4 should not be set in reverse range 10-5!");
898 [ + - ]: 1 : TEST_ASSERT(!CPU_ISSET(11, &val_cpuset), "Core 11 should not be set in reverse range 10-5!");
899 : :
900 : : /* test valid corelist with initial spaces only */
901 : 1 : CPU_ZERO(&val_cpuset);
902 : 1 : ret = rte_argparse_parse_type(corelist_valid_initial_spaces,
903 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
904 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type for corelist (with initial spaces) failed!");
905 [ - + ]: 1 : TEST_ASSERT(CPU_ISSET(1, &val_cpuset), "Core 1 should be set in initial spaced corelist!");
906 [ - + ]: 1 : TEST_ASSERT(CPU_ISSET(2, &val_cpuset), "Core 2 should be set in initial spaced corelist!");
907 [ + + ]: 4 : for (int i = 5; i <= 7; i++)
908 [ - + ]: 3 : TEST_ASSERT(CPU_ISSET(i, &val_cpuset),
909 : : "Core %d should be set in initial spaced range 5-7!", i);
910 : :
911 : : /* test valid empty corelist */
912 : 1 : CPU_ZERO(&val_cpuset);
913 : 1 : ret = rte_argparse_parse_type(corelist_valid_empty,
914 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
915 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type for corelist (empty) failed!");
916 : : /* Verify that no cores are set in empty corelist */
917 [ + + ]: 1025 : for (int i = 0; i < CPU_SETSIZE; i++)
918 [ + - ]: 1024 : TEST_ASSERT(!CPU_ISSET(i, &val_cpuset),
919 : : "Core %d should not be set in empty corelist!", i);
920 : :
921 : : /* test invalid corelist with spaces */
922 : 1 : CPU_ZERO(&val_cpuset);
923 : 1 : ret = rte_argparse_parse_type(corelist_invalid_spaces,
924 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
925 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type for corelist (with spaces) should have failed!");
926 : :
927 : : /* test invalid corelist with letters */
928 : 1 : CPU_ZERO(&val_cpuset);
929 : 1 : ret = rte_argparse_parse_type(corelist_invalid_letters,
930 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
931 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type for corelist (with letters) should have failed!");
932 : :
933 : : /* test invalid corelist with incomplete range */
934 : 1 : CPU_ZERO(&val_cpuset);
935 : 1 : ret = rte_argparse_parse_type(corelist_invalid_range_incomplete,
936 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
937 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type for corelist (incomplete range) should have failed!");
938 : :
939 : : /* test invalid corelist with double dash */
940 : 1 : CPU_ZERO(&val_cpuset);
941 : 1 : ret = rte_argparse_parse_type(corelist_invalid_range_double_dash,
942 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
943 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type for corelist (double dash) should have failed!");
944 : :
945 : : /* test invalid corelist with double dash */
946 : 1 : CPU_ZERO(&val_cpuset);
947 : 1 : ret = rte_argparse_parse_type(corelist_invalid_range_double_range,
948 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
949 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type for corelist (double range) should have failed!");
950 : :
951 : : /* test invalid corelist with special characters */
952 : 1 : CPU_ZERO(&val_cpuset);
953 : 1 : ret = rte_argparse_parse_type(corelist_invalid_special_chars,
954 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
955 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type for corelist (special chars) should have failed!");
956 : :
957 : : /* test invalid comma-only corelist */
958 : 1 : CPU_ZERO(&val_cpuset);
959 : 1 : ret = rte_argparse_parse_type(corelist_invalid_comma_only,
960 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
961 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type for corelist (comma only) should have failed!");
962 : :
963 : : /* test invalid out-of-range corelist */
964 : 1 : CPU_ZERO(&val_cpuset);
965 : 1 : ret = rte_argparse_parse_type(corelist_invalid_out_of_range,
966 : : RTE_ARGPARSE_VALUE_TYPE_CORELIST, &val_cpuset);
967 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type for corelist (out of range) should have failed!");
968 : :
969 : : return 0;
970 : : }
971 : :
972 : : static int
973 : 1 : test_argparse_parse_type(void)
974 : : {
975 : 1 : char *str_erange = test_strdup("9999999999999999999999999999999999");
976 : 1 : char *str_erange_u32 = test_strdup("4294967296");
977 : 1 : char *str_erange_u16 = test_strdup("65536");
978 : 1 : char *str_erange_u8 = test_strdup("256");
979 : 1 : char *str_invalid = test_strdup("1a");
980 : 1 : char *str_ok = test_strdup("123");
981 : 1 : char *bool_true = test_strdup("true");
982 : 1 : char *bool_false = test_strdup("false");
983 : 1 : char *bool_invalid = test_strdup("invalid");
984 : 1 : char *bool_numeric_true = test_strdup("1");
985 : 1 : char *bool_numeric_false = test_strdup("0");
986 : 1 : char *bool_numeric_invalid = test_strdup("2");
987 : : uint16_t val_u16;
988 : : uint32_t val_u32;
989 : : uint64_t val_u64;
990 : : uint8_t val_u8;
991 : : int val_int;
992 : : int ret;
993 : :
994 : : /* test for int parsing */
995 : 1 : ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_VALUE_TYPE_INT, &val_int);
996 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
997 : 1 : ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_VALUE_TYPE_INT, &val_int);
998 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
999 : 1 : ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_VALUE_TYPE_INT, &val_int);
1000 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
1001 [ - + ]: 1 : TEST_ASSERT(val_int == 123, "Argparse parse type expect failed!");
1002 : :
1003 : : /* test for u8 parsing */
1004 : 1 : ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_VALUE_TYPE_U8, &val_u8);
1005 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
1006 : 1 : ret = rte_argparse_parse_type(str_erange_u8, RTE_ARGPARSE_VALUE_TYPE_U8, &val_u8);
1007 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
1008 : 1 : ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_VALUE_TYPE_U8, &val_u8);
1009 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
1010 : 1 : val_u8 = 0;
1011 : 1 : ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_VALUE_TYPE_U8, &val_u8);
1012 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
1013 [ - + ]: 1 : TEST_ASSERT(val_u8 == 123, "Argparse parse type expect failed!");
1014 : :
1015 : : /* test for u16 parsing */
1016 : 1 : ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_VALUE_TYPE_U16, &val_u16);
1017 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
1018 : 1 : ret = rte_argparse_parse_type(str_erange_u16, RTE_ARGPARSE_VALUE_TYPE_U16, &val_u16);
1019 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
1020 : 1 : ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_VALUE_TYPE_U16, &val_u16);
1021 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
1022 : 1 : val_u16 = 0;
1023 : 1 : ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_VALUE_TYPE_U16, &val_u16);
1024 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
1025 [ - + ]: 1 : TEST_ASSERT(val_u16 == 123, "Argparse parse type expect failed!");
1026 : :
1027 : : /* test for u32 parsing */
1028 : 1 : ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_VALUE_TYPE_U32, &val_u32);
1029 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
1030 : 1 : ret = rte_argparse_parse_type(str_erange_u32, RTE_ARGPARSE_VALUE_TYPE_U32, &val_u32);
1031 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
1032 : 1 : ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_VALUE_TYPE_U32, &val_u32);
1033 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
1034 : 1 : val_u32 = 0;
1035 : 1 : ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_VALUE_TYPE_U32, &val_u32);
1036 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
1037 [ - + ]: 1 : TEST_ASSERT(val_u32 == 123, "Argparse parse type expect failed!");
1038 : :
1039 : : /* test for u64 parsing */
1040 : 1 : ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_VALUE_TYPE_U64, &val_u64);
1041 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
1042 : 1 : ret = rte_argparse_parse_type(str_invalid, RTE_ARGPARSE_VALUE_TYPE_U64, &val_u64);
1043 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type expect failed!");
1044 : 1 : val_u64 = 0;
1045 : 1 : ret = rte_argparse_parse_type(str_ok, RTE_ARGPARSE_VALUE_TYPE_U64, &val_u64);
1046 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse type expect failed!");
1047 [ - + ]: 1 : TEST_ASSERT(val_u64 == 123, "Argparse parse type expect failed!");
1048 : :
1049 : : /* test for string parsing - all it does is save string, so all are valid */
1050 : : const char *val_str;
1051 : 1 : ret = rte_argparse_parse_type(str_erange, RTE_ARGPARSE_VALUE_TYPE_STR, &val_str);
1052 [ - + ]: 1 : TEST_ASSERT(ret == 0, "Argparse parse a string failed unexpectedly!");
1053 : :
1054 : : /* test for boolean parsing */
1055 : 1 : bool val_bool = false;
1056 : 1 : ret = rte_argparse_parse_type(bool_true, RTE_ARGPARSE_VALUE_TYPE_BOOL, &val_bool);
1057 [ + - - + ]: 1 : TEST_ASSERT(ret == 0 && val_bool == true, "Argparse parse type for bool (true) failed!");
1058 : 1 : ret = rte_argparse_parse_type(bool_false, RTE_ARGPARSE_VALUE_TYPE_BOOL, &val_bool);
1059 [ + - - + ]: 1 : TEST_ASSERT(ret == 0 && val_bool == false, "Argparse parse type for bool (false) failed!");
1060 : 1 : ret = rte_argparse_parse_type(bool_invalid, RTE_ARGPARSE_VALUE_TYPE_BOOL, &val_bool);
1061 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type for bool (invalid) passed unexpectedly!");
1062 : 1 : ret = rte_argparse_parse_type(bool_numeric_true, RTE_ARGPARSE_VALUE_TYPE_BOOL, &val_bool);
1063 [ + - - + ]: 1 : TEST_ASSERT(ret == 0 && val_bool == true, "Argparse parse type for bool (numeric true) failed!");
1064 : 1 : ret = rte_argparse_parse_type(bool_numeric_false, RTE_ARGPARSE_VALUE_TYPE_BOOL,
1065 : : &val_bool);
1066 [ + - - + ]: 1 : TEST_ASSERT(ret == 0 && val_bool == false, "Argparse parse type for bool (numeric false) failed!");
1067 : 1 : ret = rte_argparse_parse_type(bool_numeric_invalid, RTE_ARGPARSE_VALUE_TYPE_BOOL,
1068 : : &val_bool);
1069 [ - + ]: 1 : TEST_ASSERT(ret != 0, "Argparse parse type for bool (numeric invalid) passed unexpectedly!");
1070 : :
1071 : : /* test for corelist parsing */
1072 : 1 : ret = test_argparse_parse_type_corelist();
1073 [ - + ]: 1 : if (ret != 0)
1074 : 0 : return ret;
1075 : :
1076 : : return 0;
1077 : : }
1078 : :
1079 : : static int
1080 : 1 : test_argparse_ignore_non_flag_args_disabled(void)
1081 : : {
1082 : : struct rte_argparse *obj;
1083 : : char *argv[6];
1084 : : int ret;
1085 : :
1086 : : /* Test that without ignore_non_flag_args, non-flag args cause an error */
1087 : 1 : obj = test_argparse_init_obj();
1088 : 1 : obj->ignore_non_flag_args = false;
1089 : 1 : obj->args[0].val_saver = NULL;
1090 : 1 : obj->args[1].val_saver = NULL;
1091 : 1 : argv[0] = test_strdup(obj->prog_name);
1092 : 1 : argv[1] = test_strdup("-a");
1093 : 1 : argv[2] = test_strdup("nonflagvalue");
1094 : 1 : argv[3] = test_strdup("-x");
1095 : 1 : ret = rte_argparse_parse(obj, 4, argv);
1096 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse should fail with non-flag arg when flag is disabled!");
1097 : :
1098 : : /* Test with non-flag args mixed with flags */
1099 : 1 : obj = test_argparse_init_obj();
1100 : 1 : obj->ignore_non_flag_args = false;
1101 : 1 : obj->args[0].val_saver = NULL;
1102 : 1 : obj->args[1].val_saver = NULL;
1103 : 1 : argv[0] = test_strdup(obj->prog_name);
1104 : 1 : argv[1] = test_strdup("nonflagvalue1");
1105 : 1 : argv[2] = test_strdup("-a");
1106 : 1 : argv[3] = test_strdup("-x");
1107 : 1 : argv[4] = test_strdup("nonflagvalue2");
1108 : 1 : ret = rte_argparse_parse(obj, 5, argv);
1109 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL, "Argparse should fail with non-flag args when flag is disabled!");
1110 : :
1111 : : return 0;
1112 : : }
1113 : :
1114 : : static int
1115 : 1 : test_argparse_ignore_non_flag_args_basic(void)
1116 : : {
1117 : : struct rte_argparse *obj;
1118 : : char *argv[8];
1119 : : int ret;
1120 : :
1121 : : /* Test basic reordering: ['app', '-a', 'nonflagvalue', '-x']
1122 : : * Should process -a and -x, return 2 processed args, move nonflagvalue to end
1123 : : */
1124 : 1 : obj = test_argparse_init_obj();
1125 : 1 : obj->ignore_non_flag_args = true;
1126 : 1 : obj->args[0].val_saver = NULL;
1127 : 1 : obj->args[1].val_saver = NULL;
1128 : 1 : argv[0] = test_strdup(obj->prog_name);
1129 : 1 : argv[1] = test_strdup("-a");
1130 : 1 : argv[2] = test_strdup("nonflagvalue");
1131 : 1 : argv[3] = test_strdup("-x");
1132 : 1 : ret = rte_argparse_parse(obj, 4, argv);
1133 [ - + ]: 1 : TEST_ASSERT(ret == 3, "Argparse should return 3 (processed all but 1 non-flag), got %d!",
1134 : : ret);
1135 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[3], "nonflagvalue") == 0,
1136 : : "Non-flag arg should be moved to end, but argv[3]='%s'!", argv[3]);
1137 : :
1138 : : /* Test with multiple non-flag args:
1139 : : * ['app', '-a', 'nonflag1', '-x', 'nonflag2']
1140 : : * Should process -a and -x, return 3, reorder to [..., 'nonflag1', 'nonflag2']
1141 : : */
1142 : 1 : obj = test_argparse_init_obj();
1143 : 1 : obj->ignore_non_flag_args = true;
1144 : 1 : obj->args[0].val_saver = NULL;
1145 : 1 : obj->args[1].val_saver = NULL;
1146 : 1 : argv[0] = test_strdup(obj->prog_name);
1147 : 1 : argv[1] = test_strdup("-a");
1148 : 1 : argv[2] = test_strdup("nonflag1");
1149 : 1 : argv[3] = test_strdup("-x");
1150 : 1 : argv[4] = test_strdup("nonflag2");
1151 : 1 : ret = rte_argparse_parse(obj, 5, argv);
1152 [ - + ]: 1 : TEST_ASSERT(ret == 3, "Argparse should return 3 (processed all but 2 non-flags), got %d!",
1153 : : ret);
1154 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[3], "nonflag1") == 0,
1155 : : "First non-flag arg should be at position 3, but argv[3]='%s'!", argv[3]);
1156 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[4], "nonflag2") == 0,
1157 : : "Second non-flag arg should be at position 4, but argv[4]='%s'!", argv[4]);
1158 : :
1159 : : return 0;
1160 : : }
1161 : :
1162 : : static int
1163 : 1 : test_argparse_ignore_non_flag_args_with_values(void)
1164 : : {
1165 : : struct rte_argparse *obj;
1166 : 1 : int val_a = 0, val_x = 0;
1167 : : char *argv[10];
1168 : : int ret;
1169 : :
1170 : : /* Test with flags that take values:
1171 : : * ['app', '-a', 'avalue', 'nonflag1', '-x', 'xvalue', 'nonflag2']
1172 : : * Should process -a avalue and -x xvalue, move non-flags to end
1173 : : */
1174 : 1 : obj = test_argparse_init_obj();
1175 : 1 : obj->ignore_non_flag_args = true;
1176 : 1 : obj->args[0].val_saver = (void *)&val_a;
1177 : 1 : obj->args[0].val_set = NULL;
1178 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
1179 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
1180 : 1 : obj->args[1].val_saver = (void *)&val_x;
1181 : 1 : obj->args[1].val_set = NULL;
1182 : 1 : obj->args[1].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
1183 : 1 : obj->args[1].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
1184 : 1 : argv[0] = test_strdup(obj->prog_name);
1185 : 1 : argv[1] = test_strdup("-a");
1186 : 1 : argv[2] = test_strdup("100");
1187 : 1 : argv[3] = test_strdup("nonflag1");
1188 : 1 : argv[4] = test_strdup("-x");
1189 : 1 : argv[5] = test_strdup("200");
1190 : 1 : argv[6] = test_strdup("nonflag2");
1191 : 1 : ret = rte_argparse_parse(obj, 7, argv);
1192 [ - + ]: 1 : TEST_ASSERT(ret == 5, "Argparse should return 5 (app + 4 flag-related + 0 non-flags), got %d!",
1193 : : ret);
1194 [ - + ]: 1 : TEST_ASSERT(val_a == 100, "Value for -a should be parsed correctly, got %d!", val_a);
1195 [ - + ]: 1 : TEST_ASSERT(val_x == 200, "Value for -x should be parsed correctly, got %d!", val_x);
1196 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[5], "nonflag1") == 0,
1197 : : "First non-flag arg should be at position 5, but argv[5]='%s'!", argv[5]);
1198 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[6], "nonflag2") == 0,
1199 : : "Second non-flag arg should be at position 6, but argv[6]='%s'!", argv[6]);
1200 : :
1201 : : return 0;
1202 : : }
1203 : :
1204 : : static int
1205 : 1 : test_argparse_ignore_non_flag_args_complex_order(void)
1206 : : {
1207 : : struct rte_argparse *obj;
1208 : 1 : int val_a = 0;
1209 : : char *argv[10];
1210 : : int ret;
1211 : :
1212 : : /* Test complex reordering matching example from requirements:
1213 : : * ['app', '-a', 'avalue', 'nonflag1', '-x', 'nonflag2']
1214 : : * Should become: ['app', '-a', 'avalue', '-x', 'nonflag1', 'nonflag2']
1215 : : */
1216 : 1 : obj = test_argparse_init_obj();
1217 : 1 : obj->ignore_non_flag_args = true;
1218 : 1 : obj->args[0].val_saver = (void *)&val_a;
1219 : 1 : obj->args[0].val_set = NULL;
1220 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
1221 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
1222 : 1 : obj->args[1].val_saver = NULL;
1223 : 1 : argv[0] = test_strdup(obj->prog_name);
1224 : 1 : argv[1] = test_strdup("-a");
1225 : 1 : argv[2] = test_strdup("50");
1226 : 1 : argv[3] = test_strdup("nonflag1");
1227 : 1 : argv[4] = test_strdup("-x");
1228 : 1 : argv[5] = test_strdup("nonflag2");
1229 : 1 : ret = rte_argparse_parse(obj, 6, argv);
1230 [ - + ]: 1 : TEST_ASSERT(ret == 4, "Argparse should return 4 (app + 3 flag-related), got %d!", ret);
1231 [ - + ]: 1 : TEST_ASSERT(val_a == 50, "Value for -a should be parsed correctly, got %d!", val_a);
1232 : : /* Verify reordering */
1233 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[4], "nonflag1") == 0,
1234 : : "First non-flag should be at position 4, but argv[4]='%s'!", argv[4]);
1235 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[5], "nonflag2") == 0,
1236 : : "Second non-flag should be at position 5, but argv[5]='%s'!", argv[5]);
1237 : :
1238 : : return 0;
1239 : : }
1240 : :
1241 : : static int
1242 : 1 : test_argparse_ignore_non_flag_args_only_non_flags(void)
1243 : : {
1244 : : struct rte_argparse *obj;
1245 : : char *argv[5];
1246 : : int ret;
1247 : :
1248 : : /* Edge case: only non-flag args
1249 : : * ['app', 'nonflag1', 'nonflag2', 'nonflag3']
1250 : : * Should return 1 (only app name processed), argv unchanged
1251 : : */
1252 : 1 : obj = test_argparse_init_obj();
1253 : 1 : obj->ignore_non_flag_args = true;
1254 : 1 : obj->args[0].val_saver = NULL;
1255 : 1 : obj->args[1].val_saver = NULL;
1256 : 1 : argv[0] = test_strdup(obj->prog_name);
1257 : 1 : argv[1] = test_strdup("nonflag1");
1258 : 1 : argv[2] = test_strdup("nonflag2");
1259 : 1 : argv[3] = test_strdup("nonflag3");
1260 : 1 : ret = rte_argparse_parse(obj, 4, argv);
1261 [ - + ]: 1 : TEST_ASSERT(ret == 1, "Argparse should return 1 (only app name processed), got %d!", ret);
1262 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[1], "nonflag1") == 0,
1263 : : "First non-flag should remain at position 1, but argv[1]='%s'!", argv[1]);
1264 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[2], "nonflag2") == 0,
1265 : : "Second non-flag should remain at position 2, but argv[2]='%s'!", argv[2]);
1266 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[3], "nonflag3") == 0,
1267 : : "Third non-flag should remain at position 3, but argv[3]='%s'!", argv[3]);
1268 : :
1269 : : return 0;
1270 : : }
1271 : :
1272 : : static int
1273 : 1 : test_argparse_ignore_non_flag_args_no_non_flags(void)
1274 : : {
1275 : : struct rte_argparse *obj;
1276 : : char *argv[4];
1277 : : int ret;
1278 : :
1279 : : /* Edge case: no non-flag args, only flags
1280 : : * ['app', '-a', '-x']
1281 : : * Should process all args normally
1282 : : */
1283 : 1 : obj = test_argparse_init_obj();
1284 : 1 : obj->ignore_non_flag_args = true;
1285 : 1 : obj->args[0].val_saver = NULL;
1286 : 1 : obj->args[1].val_saver = NULL;
1287 : 1 : argv[0] = test_strdup(obj->prog_name);
1288 : 1 : argv[1] = test_strdup("-a");
1289 : 1 : argv[2] = test_strdup("-x");
1290 : 1 : ret = rte_argparse_parse(obj, 3, argv);
1291 [ - + ]: 1 : TEST_ASSERT(ret == 3, "Argparse should return 3 (all args processed), got %d!", ret);
1292 : :
1293 : : return 0;
1294 : : }
1295 : :
1296 : : static int
1297 : 1 : test_argparse_ignore_non_flag_args_with_double_dash(void)
1298 : : {
1299 : : struct rte_argparse *obj;
1300 : : char *argv[8];
1301 : : int ret;
1302 : :
1303 : : /* Test with -- separator:
1304 : : * ['app', '-a', 'nonflag1', '--', 'arg1', 'arg2']
1305 : : * Should process -a, stop at --, and move nonflag1 after --
1306 : : */
1307 : 1 : obj = test_argparse_init_obj();
1308 : 1 : obj->ignore_non_flag_args = true;
1309 : 1 : obj->args[0].val_saver = NULL;
1310 : 1 : obj->args[1].val_saver = NULL;
1311 : 1 : argv[0] = test_strdup(obj->prog_name);
1312 : 1 : argv[1] = test_strdup("-a");
1313 : 1 : argv[2] = test_strdup("nonflag1");
1314 : 1 : argv[3] = test_strdup("--");
1315 : 1 : argv[4] = test_strdup("arg1");
1316 : 1 : argv[5] = test_strdup("arg2");
1317 : 1 : ret = rte_argparse_parse(obj, 6, argv);
1318 : : /* Should return position of first flag after -- */
1319 [ - + ]: 1 : TEST_ASSERT(ret == 3, "Argparse should return 3 (app + -a, stopped at --), got %d!", ret);
1320 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[2], "--") == 0,
1321 : : "-- should be moved to position 2, but argv[2]='%s'!", argv[2]);
1322 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[3], "nonflag1") == 0,
1323 : : "Non-flag should be moved after --, but argv[3]='%s'!", argv[3]);
1324 : :
1325 : : return 0;
1326 : : }
1327 : :
1328 : : static int
1329 : 1 : test_argparse_ignore_non_flag_args_leading_non_flags(void)
1330 : : {
1331 : : struct rte_argparse *obj;
1332 : : char *argv[7];
1333 : : int ret;
1334 : :
1335 : : /* Test with leading non-flag args:
1336 : : * ['app', 'nonflag1', 'nonflag2', '-a', '-x']
1337 : : * Should process -a and -x, move non-flags to end
1338 : : */
1339 : 1 : obj = test_argparse_init_obj();
1340 : 1 : obj->ignore_non_flag_args = true;
1341 : 1 : obj->args[0].val_saver = NULL;
1342 : 1 : obj->args[1].val_saver = NULL;
1343 : 1 : argv[0] = test_strdup(obj->prog_name);
1344 : 1 : argv[1] = test_strdup("nonflag1");
1345 : 1 : argv[2] = test_strdup("nonflag2");
1346 : 1 : argv[3] = test_strdup("-a");
1347 : 1 : argv[4] = test_strdup("-x");
1348 : 1 : ret = rte_argparse_parse(obj, 5, argv);
1349 [ - + ]: 1 : TEST_ASSERT(ret == 3, "Argparse should return 3 (app + 2 flags), got %d!", ret);
1350 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[3], "nonflag1") == 0,
1351 : : "First non-flag should be at position 3, but argv[3]='%s'!", argv[3]);
1352 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[4], "nonflag2") == 0,
1353 : : "Second non-flag should be at position 4, but argv[4]='%s'!", argv[4]);
1354 : :
1355 : : return 0;
1356 : : }
1357 : :
1358 : : static int
1359 : 1 : test_argparse_ignore_non_flag_args_trailing_non_flags(void)
1360 : : {
1361 : : struct rte_argparse *obj;
1362 : : char *argv[7];
1363 : : int ret;
1364 : :
1365 : : /* Test with trailing non-flag args:
1366 : : * ['app', '-a', '-x', 'nonflag1', 'nonflag2']
1367 : : * Should process -a and -x, non-flags already at end
1368 : : */
1369 : 1 : obj = test_argparse_init_obj();
1370 : 1 : obj->ignore_non_flag_args = true;
1371 : 1 : obj->args[0].val_saver = NULL;
1372 : 1 : obj->args[1].val_saver = NULL;
1373 : 1 : argv[0] = test_strdup(obj->prog_name);
1374 : 1 : argv[1] = test_strdup("-a");
1375 : 1 : argv[2] = test_strdup("-x");
1376 : 1 : argv[3] = test_strdup("nonflag1");
1377 : 1 : argv[4] = test_strdup("nonflag2");
1378 : 1 : ret = rte_argparse_parse(obj, 5, argv);
1379 [ - + ]: 1 : TEST_ASSERT(ret == 3, "Argparse should return 3 (app + 2 flags), got %d!", ret);
1380 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[3], "nonflag1") == 0,
1381 : : "First non-flag should remain at position 3, but argv[3]='%s'!", argv[3]);
1382 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[4], "nonflag2") == 0,
1383 : : "Second non-flag should remain at position 4, but argv[4]='%s'!", argv[4]);
1384 : :
1385 : : return 0;
1386 : : }
1387 : :
1388 : : static int
1389 : 1 : test_argparse_ignore_non_flag_args_with_positional(void)
1390 : : {
1391 : : struct rte_argparse *obj;
1392 : : char *argv[5];
1393 : : int ret;
1394 : :
1395 : : /* Test that ignore_non_flag_args cannot be used with positional args
1396 : : * This should fail during validation
1397 : : */
1398 : 1 : obj = test_argparse_init_obj();
1399 : 1 : obj->ignore_non_flag_args = true;
1400 : 1 : obj->args[0].name_long = "positional";
1401 : 1 : obj->args[0].name_short = NULL;
1402 : 1 : obj->args[0].val_saver = (void *)1;
1403 : 1 : obj->args[0].val_set = NULL;
1404 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
1405 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
1406 : 1 : argv[0] = test_strdup(obj->prog_name);
1407 : 1 : argv[1] = test_strdup("100");
1408 : 1 : ret = rte_argparse_parse(obj, 2, argv);
1409 [ - + ]: 1 : TEST_ASSERT(ret == -EINVAL,
1410 : : "Argparse should fail when ignore_non_flag_args is used with positional args!");
1411 : :
1412 : : return 0;
1413 : : }
1414 : :
1415 : : static int
1416 : 1 : test_argparse_ignore_non_flag_args_short_and_long(void)
1417 : : {
1418 : : struct rte_argparse *obj;
1419 : : char *argv[8];
1420 : : int ret;
1421 : :
1422 : : /* Test with both short and long options:
1423 : : * ['app', '--abc', 'nonflag1', '-x', 'nonflag2']
1424 : : */
1425 : 1 : obj = test_argparse_init_obj();
1426 : 1 : obj->ignore_non_flag_args = true;
1427 : 1 : obj->args[0].val_saver = NULL;
1428 : 1 : obj->args[1].val_saver = NULL;
1429 : 1 : argv[0] = test_strdup(obj->prog_name);
1430 : 1 : argv[1] = test_strdup("--abc");
1431 : 1 : argv[2] = test_strdup("nonflag1");
1432 : 1 : argv[3] = test_strdup("-x");
1433 : 1 : argv[4] = test_strdup("nonflag2");
1434 : 1 : ret = rte_argparse_parse(obj, 5, argv);
1435 [ - + ]: 1 : TEST_ASSERT(ret == 3, "Argparse should return 3 (app + 2 flags), got %d!", ret);
1436 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[3], "nonflag1") == 0,
1437 : : "First non-flag should be at position 3, but argv[3]='%s'!", argv[3]);
1438 [ - + ]: 1 : TEST_ASSERT(strcmp(argv[4], "nonflag2") == 0,
1439 : : "Second non-flag should be at position 4, but argv[4]='%s'!", argv[4]);
1440 : :
1441 : : return 0;
1442 : : }
1443 : :
1444 : : static int
1445 : 1 : test_argparse_short_opt_value_without_equal(void)
1446 : : {
1447 : : struct rte_argparse *obj;
1448 : 1 : int val_saver = 0;
1449 : : char *argv[3];
1450 : : int ret;
1451 : :
1452 : : /* Test short option with required value using -a3 syntax (no '=') */
1453 : 1 : obj = test_argparse_init_obj();
1454 : 1 : obj->args[0].name_long = "--test-long";
1455 : 1 : obj->args[0].name_short = "-t";
1456 : 1 : obj->args[0].val_saver = (void *)&val_saver;
1457 : 1 : obj->args[0].val_set = NULL;
1458 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
1459 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
1460 : 1 : obj->args[1].name_long = NULL;
1461 : 1 : argv[0] = test_strdup(obj->prog_name);
1462 : 1 : argv[1] = test_strdup("-t42");
1463 : 1 : ret = rte_argparse_parse(obj, 2, argv);
1464 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse with -t42 expect success, got %d!", ret);
1465 [ - + ]: 1 : TEST_ASSERT(val_saver == 42, "Argparse parse -t42 should set value to 42, got %d!",
1466 : : val_saver);
1467 : :
1468 : : /* Test short option with optional value using -t100 syntax (no '=') */
1469 : 1 : obj = test_argparse_init_obj();
1470 : 1 : obj->args[0].name_long = "--test-long";
1471 : 1 : obj->args[0].name_short = "-t";
1472 : 1 : obj->args[0].val_saver = (void *)&val_saver;
1473 : 1 : obj->args[0].val_set = (void *)99;
1474 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_OPTIONAL;
1475 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
1476 : 1 : obj->args[1].name_long = NULL;
1477 : 1 : val_saver = 0;
1478 : 1 : argv[0] = test_strdup(obj->prog_name);
1479 : 1 : argv[1] = test_strdup("-t123");
1480 : 1 : ret = rte_argparse_parse(obj, 2, argv);
1481 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse with -t123 expect success, got %d!", ret);
1482 [ - + ]: 1 : TEST_ASSERT(val_saver == 123, "Argparse parse -t123 should set value to 123, got %d!",
1483 : : val_saver);
1484 : :
1485 : : /* Test that -t alone with optional value uses default */
1486 : 1 : obj = test_argparse_init_obj();
1487 : 1 : obj->args[0].name_long = "--test-long";
1488 : 1 : obj->args[0].name_short = "-t";
1489 : 1 : obj->args[0].val_saver = (void *)&val_saver;
1490 : 1 : obj->args[0].val_set = (void *)99;
1491 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_OPTIONAL;
1492 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
1493 : 1 : obj->args[1].name_long = NULL;
1494 : 1 : val_saver = 0;
1495 : 1 : argv[0] = test_strdup(obj->prog_name);
1496 : 1 : argv[1] = test_strdup("-t");
1497 : 1 : ret = rte_argparse_parse(obj, 2, argv);
1498 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse with -t expect success, got %d!", ret);
1499 [ - + ]: 1 : TEST_ASSERT(val_saver == 99, "Argparse parse -t should use default 99, got %d!",
1500 : : val_saver);
1501 : :
1502 : : /* Test short option with '=' still works */
1503 : 1 : obj = test_argparse_init_obj();
1504 : 1 : obj->args[0].name_long = "--test-long";
1505 : 1 : obj->args[0].name_short = "-t";
1506 : 1 : obj->args[0].val_saver = (void *)&val_saver;
1507 : 1 : obj->args[0].val_set = NULL;
1508 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
1509 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
1510 : 1 : obj->args[1].name_long = NULL;
1511 : 1 : val_saver = 0;
1512 : 1 : argv[0] = test_strdup(obj->prog_name);
1513 : 1 : argv[1] = test_strdup("-t=55");
1514 : 1 : ret = rte_argparse_parse(obj, 2, argv);
1515 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse with -t=55 expect success, got %d!", ret);
1516 [ - + ]: 1 : TEST_ASSERT(val_saver == 55, "Argparse parse -t=55 should set value to 55, got %d!",
1517 : : val_saver);
1518 : :
1519 : : /* Test that long option with value works with '=' */
1520 : 1 : obj = test_argparse_init_obj();
1521 : 1 : obj->args[0].name_long = "--test-long";
1522 : 1 : obj->args[0].name_short = "-t";
1523 : 1 : obj->args[0].val_saver = (void *)&val_saver;
1524 : 1 : obj->args[0].val_set = (void *)88;
1525 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_OPTIONAL;
1526 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
1527 : 1 : obj->args[1].name_long = NULL;
1528 : 1 : val_saver = 0;
1529 : 1 : argv[0] = test_strdup(obj->prog_name);
1530 : 1 : argv[1] = test_strdup("--test-long=66");
1531 : 1 : ret = rte_argparse_parse(obj, 2, argv);
1532 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse with --test-long=66 expect success, got %d!", ret);
1533 [ - + ]: 1 : TEST_ASSERT(val_saver == 66, "Argparse parse --test-long=66 should set value to 66, got %d!",
1534 : : val_saver);
1535 : :
1536 : : /* Test short option with string value without '=' */
1537 : 1 : const char *str_saver = NULL;
1538 : 1 : obj = test_argparse_init_obj();
1539 : 1 : obj->args[0].name_long = "--test-string";
1540 : 1 : obj->args[0].name_short = "-s";
1541 : 1 : obj->args[0].val_saver = (void *)&str_saver;
1542 : 1 : obj->args[0].val_set = NULL;
1543 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
1544 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_STR;
1545 : 1 : obj->args[1].name_long = NULL;
1546 : 1 : argv[0] = test_strdup(obj->prog_name);
1547 : 1 : argv[1] = test_strdup("-shello");
1548 : 1 : ret = rte_argparse_parse(obj, 2, argv);
1549 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse with -shello expect success, got %d!", ret);
1550 [ + - - + : 1 : TEST_ASSERT(str_saver != NULL && strcmp(str_saver, "hello") == 0,
- - ]
1551 : : "Argparse parse -shello should set string to 'hello', got '%s'!",
1552 : : str_saver ? str_saver : "(null)");
1553 : :
1554 : : /* Test short option with negative number without '=' */
1555 : 1 : obj = test_argparse_init_obj();
1556 : 1 : obj->args[0].name_long = "--test-long";
1557 : 1 : obj->args[0].name_short = "-t";
1558 : 1 : obj->args[0].val_saver = (void *)&val_saver;
1559 : 1 : obj->args[0].val_set = NULL;
1560 : 1 : obj->args[0].value_required = RTE_ARGPARSE_VALUE_REQUIRED;
1561 : 1 : obj->args[0].value_type = RTE_ARGPARSE_VALUE_TYPE_INT;
1562 : 1 : obj->args[1].name_long = NULL;
1563 : 1 : val_saver = 0;
1564 : 1 : argv[0] = test_strdup(obj->prog_name);
1565 : 1 : argv[1] = test_strdup("-t-42");
1566 : 1 : ret = rte_argparse_parse(obj, 2, argv);
1567 [ - + ]: 1 : TEST_ASSERT(ret == 2, "Argparse parse with -t-42 expect success, got %d!", ret);
1568 [ - + ]: 1 : TEST_ASSERT(val_saver == -42, "Argparse parse -t-42 should set value to -42, got %d!",
1569 : : val_saver);
1570 : :
1571 : : return 0;
1572 : : }
1573 : :
1574 : : static struct unit_test_suite argparse_test_suite = {
1575 : : .suite_name = "Argparse Unit Test Suite",
1576 : : .setup = test_argparse_setup,
1577 : : .teardown = test_argparse_teardown,
1578 : : .unit_test_cases = {
1579 : : TEST_CASE(test_argparse_invalid_basic_param),
1580 : : TEST_CASE(test_argparse_invalid_arg_name),
1581 : : TEST_CASE(test_argparse_invalid_arg_help),
1582 : : TEST_CASE(test_argparse_invalid_has_val),
1583 : : TEST_CASE(test_argparse_invalid_arg_saver),
1584 : : TEST_CASE(test_argparse_invalid_arg_flags),
1585 : : TEST_CASE(test_argparse_invalid_arg_repeat),
1586 : : TEST_CASE(test_argparse_invalid_option),
1587 : : TEST_CASE(test_argparse_invalid_repeated_option),
1588 : : TEST_CASE(test_argparse_opt_autosave_parse_int_of_no_val),
1589 : : TEST_CASE(test_argparse_opt_autosave_parse_int_of_required_val),
1590 : : TEST_CASE(test_argparse_opt_autosave_parse_int_of_optional_val),
1591 : : TEST_CASE(test_argparse_opt_parse_corelist_of_required_val),
1592 : : TEST_CASE(test_argparse_opt_callback_parse_int_of_no_val),
1593 : : TEST_CASE(test_argparse_opt_callback_parse_int_of_required_val),
1594 : : TEST_CASE(test_argparse_opt_callback_parse_int_of_optional_val),
1595 : : TEST_CASE(test_argparse_pos_autosave_parse_int),
1596 : : TEST_CASE(test_argparse_pos_callback_parse_int),
1597 : : TEST_CASE(test_argparse_parse_type),
1598 : : TEST_CASE(test_argparse_ignore_non_flag_args_disabled),
1599 : : TEST_CASE(test_argparse_ignore_non_flag_args_basic),
1600 : : TEST_CASE(test_argparse_ignore_non_flag_args_with_values),
1601 : : TEST_CASE(test_argparse_ignore_non_flag_args_complex_order),
1602 : : TEST_CASE(test_argparse_ignore_non_flag_args_only_non_flags),
1603 : : TEST_CASE(test_argparse_ignore_non_flag_args_no_non_flags),
1604 : : TEST_CASE(test_argparse_ignore_non_flag_args_with_double_dash),
1605 : : TEST_CASE(test_argparse_ignore_non_flag_args_leading_non_flags),
1606 : : TEST_CASE(test_argparse_ignore_non_flag_args_trailing_non_flags),
1607 : : TEST_CASE(test_argparse_ignore_non_flag_args_with_positional),
1608 : : TEST_CASE(test_argparse_ignore_non_flag_args_short_and_long),
1609 : : TEST_CASE(test_argparse_short_opt_value_without_equal),
1610 : :
1611 : : TEST_CASES_END() /**< NULL terminate unit test array */
1612 : : }
1613 : : };
1614 : :
1615 : : static int
1616 : 1 : test_argparse(void)
1617 : : {
1618 : 1 : return unit_test_suite_runner(&argparse_test_suite);
1619 : : }
1620 : :
1621 : 253 : REGISTER_FAST_TEST(argparse_autotest, true, true, test_argparse);
|