xref: /dpdk/app/test/test_kvargs.c (revision 0e95a6777fe3e99b5cd5747a84e6df4aa85c4ec4)
1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2a9de470cSBruce Richardson  * Copyright 2014 6WIND S.A.
3a9de470cSBruce Richardson  */
4a9de470cSBruce Richardson 
5a9de470cSBruce Richardson #include <stdlib.h>
6a9de470cSBruce Richardson #include <stdio.h>
7a9de470cSBruce Richardson #include <string.h>
8a9de470cSBruce Richardson 
9a9de470cSBruce Richardson #include <rte_common.h>
10a9de470cSBruce Richardson #include <rte_kvargs.h>
11a9de470cSBruce Richardson 
12a9de470cSBruce Richardson #include "test.h"
13a9de470cSBruce Richardson 
14*0e95a677SChengwen Feng typedef int (*f_kvargs_process)(const struct rte_kvargs *kvlist,
15*0e95a677SChengwen Feng 				const char *key_match, arg_handler_t handler,
16*0e95a677SChengwen Feng 				void *opaque_arg);
17*0e95a677SChengwen Feng 
18*0e95a677SChengwen Feng static bool use_kvargs_process_opt[] = { false, true };
19*0e95a677SChengwen Feng 
207be78d02SJosh Soref /* incremented in handler, to check it is properly called once per
21a9de470cSBruce Richardson  * key/value association */
22a9de470cSBruce Richardson static unsigned count;
23a9de470cSBruce Richardson 
24a9de470cSBruce Richardson /* this handler increment the "count" variable at each call and check
25a9de470cSBruce Richardson  * that the key is "check" and the value is "value%d" */
26*0e95a677SChengwen Feng static int
27*0e95a677SChengwen Feng check_handler(const char *key, const char *value, __rte_unused void *opaque)
28a9de470cSBruce Richardson {
29a9de470cSBruce Richardson 	char buf[16];
30a9de470cSBruce Richardson 
31a9de470cSBruce Richardson 	/* we check that the value is "check" */
32a9de470cSBruce Richardson 	if (strcmp(key, "check"))
33a9de470cSBruce Richardson 		return -1;
34a9de470cSBruce Richardson 
35a9de470cSBruce Richardson 	/* we check that the value is "value$(count)" */
36a9de470cSBruce Richardson 	snprintf(buf, sizeof(buf), "value%d", count);
37a9de470cSBruce Richardson 	if (strncmp(buf, value, sizeof(buf)))
38a9de470cSBruce Richardson 		return -1;
39a9de470cSBruce Richardson 
40a9de470cSBruce Richardson 	count ++;
41a9de470cSBruce Richardson 	return 0;
42a9de470cSBruce Richardson }
43a9de470cSBruce Richardson 
44ce7e937fSChengwen Feng static int
45*0e95a677SChengwen Feng check_only_handler(const char *key, const char *value, __rte_unused void *opaque)
46*0e95a677SChengwen Feng {
47*0e95a677SChengwen Feng 	if (strcmp(key, "check"))
48*0e95a677SChengwen Feng 		return -1;
49*0e95a677SChengwen Feng 
50*0e95a677SChengwen Feng 	if (value != NULL)
51*0e95a677SChengwen Feng 		return -1;
52*0e95a677SChengwen Feng 
53*0e95a677SChengwen Feng 	return 0;
54*0e95a677SChengwen Feng }
55*0e95a677SChengwen Feng 
56*0e95a677SChengwen Feng static int
57ce7e937fSChengwen Feng test_basic_token_count(void)
58ce7e937fSChengwen Feng {
59ce7e937fSChengwen Feng 	static const struct {
60ce7e937fSChengwen Feng 		unsigned int expected;
61ce7e937fSChengwen Feng 		const char *input;
62ce7e937fSChengwen Feng 	} valid_inputs[] = {
63ce7e937fSChengwen Feng 		{ 3, "foo=1,check=1,check=2" },
64ce7e937fSChengwen Feng 		{ 3, "foo=1,check,check=2"   },
65ce7e937fSChengwen Feng 		{ 2, "foo=1,foo="            },
66ce7e937fSChengwen Feng 		{ 2, "foo=1,foo="            },
67ce7e937fSChengwen Feng 		{ 2, "foo=1,foo"             },
68ce7e937fSChengwen Feng 		{ 2, "foo=1,=2"              },
69ce7e937fSChengwen Feng 		{ 2, "foo=1,,foo=2,,"        },
70ce7e937fSChengwen Feng 		{ 1, "foo=[1,2"              },
71ce7e937fSChengwen Feng 		{ 1, ",="                    },
72ce7e937fSChengwen Feng 		{ 1, "foo=["                 },
73ce7e937fSChengwen Feng 		{ 0, ""                      },
74ce7e937fSChengwen Feng 	};
75ce7e937fSChengwen Feng 	struct rte_kvargs *kvlist;
76ce7e937fSChengwen Feng 	unsigned int count;
77ce7e937fSChengwen Feng 	const char *args;
78ce7e937fSChengwen Feng 	unsigned int i;
79ce7e937fSChengwen Feng 
80ce7e937fSChengwen Feng 	for (i = 0; i < RTE_DIM(valid_inputs); i++) {
81ce7e937fSChengwen Feng 		args = valid_inputs[i].input;
82ce7e937fSChengwen Feng 		kvlist = rte_kvargs_parse(args, NULL);
83ce7e937fSChengwen Feng 		if (kvlist == NULL) {
84ce7e937fSChengwen Feng 			printf("rte_kvargs_parse() error: %s\n", args);
85ce7e937fSChengwen Feng 			return -1;
86ce7e937fSChengwen Feng 		}
87ce7e937fSChengwen Feng 		count = rte_kvargs_count(kvlist, NULL);
88ce7e937fSChengwen Feng 		if (count != valid_inputs[i].expected) {
89ce7e937fSChengwen Feng 			printf("invalid count value %u (expected %u): %s\n",
90ce7e937fSChengwen Feng 			       count, valid_inputs[i].expected, args);
91ce7e937fSChengwen Feng 			rte_kvargs_free(kvlist);
92ce7e937fSChengwen Feng 			return -1;
93ce7e937fSChengwen Feng 		}
94ce7e937fSChengwen Feng 		rte_kvargs_free(kvlist);
95ce7e937fSChengwen Feng 	}
96ce7e937fSChengwen Feng 
97ce7e937fSChengwen Feng 	return 0;
98ce7e937fSChengwen Feng }
99ce7e937fSChengwen Feng 
1007dd71026SChengwen Feng static int
101*0e95a677SChengwen Feng test_parse_without_valid_keys(const void *params)
1027dd71026SChengwen Feng {
103*0e95a677SChengwen Feng 	const bool use_opt = *(const bool *)params;
104*0e95a677SChengwen Feng 	f_kvargs_process proc_func = use_opt ? rte_kvargs_process_opt : rte_kvargs_process;
105*0e95a677SChengwen Feng 	const char *proc_name = use_opt ? "rte_kvargs_process_opt" : "rte_kvargs_process";
1067dd71026SChengwen Feng 	const char *args = "foo=1234,check=value0,check=value1";
1077dd71026SChengwen Feng 	struct rte_kvargs *kvlist;
1087dd71026SChengwen Feng 
1097dd71026SChengwen Feng 	kvlist = rte_kvargs_parse(args, NULL);
1107dd71026SChengwen Feng 	if (kvlist == NULL) {
1117dd71026SChengwen Feng 		printf("rte_kvargs_parse() error\n");
1127dd71026SChengwen Feng 		return -1;
1137dd71026SChengwen Feng 	}
1147dd71026SChengwen Feng 
1157dd71026SChengwen Feng 	/* call check_handler() for all entries with key="check" */
1167dd71026SChengwen Feng 	count = 0;
117*0e95a677SChengwen Feng 	if (proc_func(kvlist, "check", check_handler, NULL) < 0) {
118*0e95a677SChengwen Feng 		printf("%s(check) error\n", proc_name);
1197dd71026SChengwen Feng 		rte_kvargs_free(kvlist);
1207dd71026SChengwen Feng 		return -1;
1217dd71026SChengwen Feng 	}
1227dd71026SChengwen Feng 	if (count != 2) {
123*0e95a677SChengwen Feng 		printf("invalid count value %u after %s(check)\n",
124*0e95a677SChengwen Feng 			count, proc_name);
1257dd71026SChengwen Feng 		rte_kvargs_free(kvlist);
1267dd71026SChengwen Feng 		return -1;
1277dd71026SChengwen Feng 	}
1287dd71026SChengwen Feng 
1297dd71026SChengwen Feng 	/* call check_handler() for all entries with key="nonexistent_key" */
1307dd71026SChengwen Feng 	count = 0;
131*0e95a677SChengwen Feng 	if (proc_func(kvlist, "nonexistent_key", check_handler, NULL) < 0) {
132*0e95a677SChengwen Feng 		printf("%s(nonexistent_key) error\n", proc_name);
1337dd71026SChengwen Feng 		rte_kvargs_free(kvlist);
1347dd71026SChengwen Feng 		return -1;
1357dd71026SChengwen Feng 	}
1367dd71026SChengwen Feng 	if (count != 0) {
137*0e95a677SChengwen Feng 		printf("invalid count value %d after %s(nonexistent_key)\n",
138*0e95a677SChengwen Feng 			count, proc_name);
1397dd71026SChengwen Feng 		rte_kvargs_free(kvlist);
1407dd71026SChengwen Feng 		return -1;
1417dd71026SChengwen Feng 	}
1427dd71026SChengwen Feng 
1437dd71026SChengwen Feng 	/* count all entries with key="foo" */
1447dd71026SChengwen Feng 	count = rte_kvargs_count(kvlist, "foo");
1457dd71026SChengwen Feng 	if (count != 1) {
1467dd71026SChengwen Feng 		printf("invalid count value %d after rte_kvargs_count(foo)\n",
1477dd71026SChengwen Feng 			count);
1487dd71026SChengwen Feng 		rte_kvargs_free(kvlist);
1497dd71026SChengwen Feng 		return -1;
1507dd71026SChengwen Feng 	}
1517dd71026SChengwen Feng 
1527dd71026SChengwen Feng 	/* count all entries with key="nonexistent_key" */
1537dd71026SChengwen Feng 	count = rte_kvargs_count(kvlist, "nonexistent_key");
1547dd71026SChengwen Feng 	if (count != 0) {
1557dd71026SChengwen Feng 		printf("invalid count value %d after rte_kvargs_count(nonexistent_key)\n",
1567dd71026SChengwen Feng 			count);
1577dd71026SChengwen Feng 		rte_kvargs_free(kvlist);
1587dd71026SChengwen Feng 		return -1;
1597dd71026SChengwen Feng 	}
1607dd71026SChengwen Feng 
1617dd71026SChengwen Feng 	rte_kvargs_free(kvlist);
1627dd71026SChengwen Feng 	return 0;
1637dd71026SChengwen Feng }
1647dd71026SChengwen Feng 
165a04d13aaSChengwen Feng static int
166*0e95a677SChengwen Feng test_parse_with_valid_keys(const void *params)
167a04d13aaSChengwen Feng {
168*0e95a677SChengwen Feng 	const bool use_opt = *(const bool *)params;
169*0e95a677SChengwen Feng 	f_kvargs_process proc_func = use_opt ? rte_kvargs_process_opt : rte_kvargs_process;
170*0e95a677SChengwen Feng 	const char *proc_name = use_opt ? "rte_kvargs_process_opt" : "rte_kvargs_process";
171a04d13aaSChengwen Feng 	const char *args = "foo=droids,check=value0,check=value1,check=wrong_value";
172a04d13aaSChengwen Feng 	const char *valid_keys[] = { "foo", "check", NULL };
173a04d13aaSChengwen Feng 	struct rte_kvargs *kvlist;
174a04d13aaSChengwen Feng 
175a04d13aaSChengwen Feng 	kvlist = rte_kvargs_parse(args, valid_keys);
176a04d13aaSChengwen Feng 	if (kvlist == NULL) {
177a04d13aaSChengwen Feng 		printf("rte_kvargs_parse() error\n");
178a04d13aaSChengwen Feng 		return -1;
179a04d13aaSChengwen Feng 	}
180a04d13aaSChengwen Feng 
181a04d13aaSChengwen Feng 	/* call check_handler() on all entries with key="check", it
182a04d13aaSChengwen Feng 	 * should fail as the value is not recognized by the handler
183a04d13aaSChengwen Feng 	 */
184a04d13aaSChengwen Feng 	count = 0;
185*0e95a677SChengwen Feng 	if (proc_func(kvlist, "check", check_handler, NULL) == 0 || count != 2) {
186*0e95a677SChengwen Feng 		printf("%s(check) is success but should not\n", proc_name);
187a04d13aaSChengwen Feng 		rte_kvargs_free(kvlist);
188a04d13aaSChengwen Feng 		return -1;
189a04d13aaSChengwen Feng 	}
190a04d13aaSChengwen Feng 
191a04d13aaSChengwen Feng 	count = rte_kvargs_count(kvlist, "check");
192a04d13aaSChengwen Feng 	if (count != 3) {
193a04d13aaSChengwen Feng 		printf("invalid count value %u after rte_kvargs_count(check)\n",
194a04d13aaSChengwen Feng 			count);
195a04d13aaSChengwen Feng 		rte_kvargs_free(kvlist);
196a04d13aaSChengwen Feng 		return -1;
197a04d13aaSChengwen Feng 	}
198a04d13aaSChengwen Feng 
199a04d13aaSChengwen Feng 	rte_kvargs_free(kvlist);
200a04d13aaSChengwen Feng 	return 0;
201a04d13aaSChengwen Feng }
202a04d13aaSChengwen Feng 
203c189450bSChengwen Feng static int
204c189450bSChengwen Feng test_parse_list_value(void)
205c189450bSChengwen Feng {
206c189450bSChengwen Feng 	const char *valid_keys[] = { "foo", "check", NULL };
207c189450bSChengwen Feng 	const char *args = "foo=[0,1],check=value2";
208c189450bSChengwen Feng 	struct rte_kvargs *kvlist;
209c189450bSChengwen Feng 
210c189450bSChengwen Feng 	kvlist = rte_kvargs_parse(args, valid_keys);
211c189450bSChengwen Feng 	if (kvlist == NULL) {
212c189450bSChengwen Feng 		printf("rte_kvargs_parse() error\n");
213c189450bSChengwen Feng 		return -1;
214c189450bSChengwen Feng 	}
215c189450bSChengwen Feng 
216c189450bSChengwen Feng 	count = kvlist->count;
217c189450bSChengwen Feng 	if (count != 2) {
218c189450bSChengwen Feng 		printf("invalid count value %u\n", count);
219c189450bSChengwen Feng 		rte_kvargs_free(kvlist);
220c189450bSChengwen Feng 		return -1;
221c189450bSChengwen Feng 	}
222c189450bSChengwen Feng 
223c189450bSChengwen Feng 	if (strcmp(kvlist->pairs[0].value, "[0,1]") != 0) {
224c189450bSChengwen Feng 		printf("wrong value %s", kvlist->pairs[0].value);
225c189450bSChengwen Feng 		rte_kvargs_free(kvlist);
226c189450bSChengwen Feng 		return -1;
227c189450bSChengwen Feng 	}
228c189450bSChengwen Feng 
229c189450bSChengwen Feng 	rte_kvargs_free(kvlist);
230c189450bSChengwen Feng 	return 0;
231c189450bSChengwen Feng }
232c189450bSChengwen Feng 
2338b1656a9SChengwen Feng static int
2348b1656a9SChengwen Feng test_parse_empty_elements(void)
2358b1656a9SChengwen Feng {
2368b1656a9SChengwen Feng 	const char *args = "foo=1,,check=value2,,";
2378b1656a9SChengwen Feng 	struct rte_kvargs *kvlist;
2388b1656a9SChengwen Feng 
2398b1656a9SChengwen Feng 	kvlist = rte_kvargs_parse(args, NULL);
2408b1656a9SChengwen Feng 	if (kvlist == NULL) {
2418b1656a9SChengwen Feng 		printf("rte_kvargs_parse() error\n");
2428b1656a9SChengwen Feng 		return -1;
2438b1656a9SChengwen Feng 	}
2448b1656a9SChengwen Feng 
245*0e95a677SChengwen Feng 	count = kvlist->count;
246*0e95a677SChengwen Feng 	if (count != 2) {
247*0e95a677SChengwen Feng 		printf("invalid count value %u\n", count);
248*0e95a677SChengwen Feng 		rte_kvargs_free(kvlist);
249*0e95a677SChengwen Feng 		return -1;
250*0e95a677SChengwen Feng 	}
251*0e95a677SChengwen Feng 
2528b1656a9SChengwen Feng 	if (rte_kvargs_count(kvlist, "foo") != 1) {
2538b1656a9SChengwen Feng 		printf("invalid count value for 'foo'\n");
2548b1656a9SChengwen Feng 		rte_kvargs_free(kvlist);
2558b1656a9SChengwen Feng 		return -1;
2568b1656a9SChengwen Feng 	}
2578b1656a9SChengwen Feng 
2588b1656a9SChengwen Feng 	if (rte_kvargs_count(kvlist, "check") != 1) {
2598b1656a9SChengwen Feng 		printf("invalid count value for 'check'\n");
2608b1656a9SChengwen Feng 		rte_kvargs_free(kvlist);
2618b1656a9SChengwen Feng 		return -1;
2628b1656a9SChengwen Feng 	}
2638b1656a9SChengwen Feng 
2648b1656a9SChengwen Feng 	rte_kvargs_free(kvlist);
2658b1656a9SChengwen Feng 	return 0;
2668b1656a9SChengwen Feng }
2678b1656a9SChengwen Feng 
268*0e95a677SChengwen Feng static int
269*0e95a677SChengwen Feng test_parse_with_only_key(void)
270*0e95a677SChengwen Feng {
271*0e95a677SChengwen Feng 	const char *args = "foo,check";
272*0e95a677SChengwen Feng 	struct rte_kvargs *kvlist;
273*0e95a677SChengwen Feng 
274*0e95a677SChengwen Feng 	kvlist = rte_kvargs_parse(args, NULL);
275*0e95a677SChengwen Feng 	if (kvlist == NULL) {
276*0e95a677SChengwen Feng 		printf("rte_kvargs_parse() error\n");
277*0e95a677SChengwen Feng 		return -1;
278*0e95a677SChengwen Feng 	}
279*0e95a677SChengwen Feng 
280*0e95a677SChengwen Feng 	if (rte_kvargs_process(kvlist, "check", check_only_handler, NULL) == 0) {
281*0e95a677SChengwen Feng 		printf("rte_kvargs_process(check) error\n");
282*0e95a677SChengwen Feng 		rte_kvargs_free(kvlist);
283*0e95a677SChengwen Feng 		return -1;
284*0e95a677SChengwen Feng 	}
285*0e95a677SChengwen Feng 
286*0e95a677SChengwen Feng 	if (rte_kvargs_process_opt(kvlist, "check", check_only_handler, NULL) != 0) {
287*0e95a677SChengwen Feng 		printf("rte_kvargs_process_opt(check) error\n");
288*0e95a677SChengwen Feng 		rte_kvargs_free(kvlist);
289*0e95a677SChengwen Feng 		return -1;
290*0e95a677SChengwen Feng 	}
291*0e95a677SChengwen Feng 
292*0e95a677SChengwen Feng 	rte_kvargs_free(kvlist);
293*0e95a677SChengwen Feng 	return 0;
294*0e95a677SChengwen Feng }
295*0e95a677SChengwen Feng 
296a9de470cSBruce Richardson /* test several error cases */
297a9de470cSBruce Richardson static int test_invalid_kvargs(void)
298a9de470cSBruce Richardson {
299a9de470cSBruce Richardson 	struct rte_kvargs *kvlist;
300a9de470cSBruce Richardson 	/* list of argument that should fail */
301a9de470cSBruce Richardson 	const char *args_list[] = {
302a9de470cSBruce Richardson 		"wrong-key=x",     /* key not in valid_keys_list */
303a9de470cSBruce Richardson 		NULL };
304a9de470cSBruce Richardson 	const char **args;
305a9de470cSBruce Richardson 	const char *valid_keys_list[] = { "foo", "check", NULL };
306a9de470cSBruce Richardson 	const char **valid_keys = valid_keys_list;
307a9de470cSBruce Richardson 
308a9de470cSBruce Richardson 	for (args = args_list; *args != NULL; args++) {
309a9de470cSBruce Richardson 
310a9de470cSBruce Richardson 		kvlist = rte_kvargs_parse(*args, valid_keys);
311a9de470cSBruce Richardson 		if (kvlist != NULL) {
312a9de470cSBruce Richardson 			printf("rte_kvargs_parse() returned 0 (but should not)\n");
313a9de470cSBruce Richardson 			rte_kvargs_free(kvlist);
314a9de470cSBruce Richardson 			goto fail;
315a9de470cSBruce Richardson 		}
316a9de470cSBruce Richardson 	}
3174bf2b36fSOlivier Matz 	return 0;
318a9de470cSBruce Richardson 
319a9de470cSBruce Richardson  fail:
320a9de470cSBruce Richardson 	printf("while processing <%s>", *args);
321a9de470cSBruce Richardson 	if (valid_keys != NULL && *valid_keys != NULL) {
322a9de470cSBruce Richardson 		printf(" using valid_keys=<%s", *valid_keys);
323a9de470cSBruce Richardson 		while (*(++valid_keys) != NULL)
324a9de470cSBruce Richardson 			printf(",%s", *valid_keys);
325a9de470cSBruce Richardson 		printf(">");
326a9de470cSBruce Richardson 	}
327a9de470cSBruce Richardson 	printf("\n");
328a9de470cSBruce Richardson 	return -1;
329a9de470cSBruce Richardson }
330a9de470cSBruce Richardson 
331a79d5ce9SChengwen Feng static struct unit_test_suite kvargs_test_suite  = {
332a79d5ce9SChengwen Feng 	.suite_name = "Kvargs Unit Test Suite",
333a79d5ce9SChengwen Feng 	.setup = NULL,
334a79d5ce9SChengwen Feng 	.teardown = NULL,
335a79d5ce9SChengwen Feng 	.unit_test_cases = {
336ce7e937fSChengwen Feng 		TEST_CASE(test_basic_token_count),
337*0e95a677SChengwen Feng 		TEST_CASE_NAMED_WITH_DATA("test_parse_without_valid_keys_no_opt",
338*0e95a677SChengwen Feng 					  NULL, NULL,
339*0e95a677SChengwen Feng 					  test_parse_without_valid_keys,
340*0e95a677SChengwen Feng 					  &use_kvargs_process_opt[0]),
341*0e95a677SChengwen Feng 		TEST_CASE_NAMED_WITH_DATA("test_parse_without_valid_keys_with_opt",
342*0e95a677SChengwen Feng 					  NULL, NULL,
343*0e95a677SChengwen Feng 					  test_parse_without_valid_keys,
344*0e95a677SChengwen Feng 					  &use_kvargs_process_opt[1]),
345*0e95a677SChengwen Feng 		TEST_CASE_NAMED_WITH_DATA("test_parse_with_valid_keys_no_opt",
346*0e95a677SChengwen Feng 					  NULL, NULL,
347*0e95a677SChengwen Feng 					  test_parse_with_valid_keys,
348*0e95a677SChengwen Feng 					  &use_kvargs_process_opt[0]),
349*0e95a677SChengwen Feng 		TEST_CASE_NAMED_WITH_DATA("test_parse_with_valid_keys_with_opt",
350*0e95a677SChengwen Feng 					  NULL, NULL,
351*0e95a677SChengwen Feng 					  test_parse_with_valid_keys,
352*0e95a677SChengwen Feng 					  &use_kvargs_process_opt[1]),
353c189450bSChengwen Feng 		TEST_CASE(test_parse_list_value),
3548b1656a9SChengwen Feng 		TEST_CASE(test_parse_empty_elements),
355*0e95a677SChengwen Feng 		TEST_CASE(test_parse_with_only_key),
356a79d5ce9SChengwen Feng 		TEST_CASE(test_invalid_kvargs),
357a79d5ce9SChengwen Feng 		TEST_CASES_END() /**< NULL terminate unit test array */
358a79d5ce9SChengwen Feng 	}
359a79d5ce9SChengwen Feng };
360a79d5ce9SChengwen Feng 
361a9de470cSBruce Richardson static int
362a9de470cSBruce Richardson test_kvargs(void)
363a9de470cSBruce Richardson {
364a79d5ce9SChengwen Feng 	return unit_test_suite_runner(&kvargs_test_suite);
365a9de470cSBruce Richardson }
366a9de470cSBruce Richardson 
367e0a8442cSBruce Richardson REGISTER_FAST_TEST(kvargs_autotest, true, true, test_kvargs);
368