xref: /dpdk/app/test/test_kvargs.c (revision 0e95a6777fe3e99b5cd5747a84e6df4aa85c4ec4)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2014 6WIND S.A.
3  */
4 
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 
9 #include <rte_common.h>
10 #include <rte_kvargs.h>
11 
12 #include "test.h"
13 
14 typedef int (*f_kvargs_process)(const struct rte_kvargs *kvlist,
15 				const char *key_match, arg_handler_t handler,
16 				void *opaque_arg);
17 
18 static bool use_kvargs_process_opt[] = { false, true };
19 
20 /* incremented in handler, to check it is properly called once per
21  * key/value association */
22 static unsigned count;
23 
24 /* this handler increment the "count" variable at each call and check
25  * that the key is "check" and the value is "value%d" */
26 static int
27 check_handler(const char *key, const char *value, __rte_unused void *opaque)
28 {
29 	char buf[16];
30 
31 	/* we check that the value is "check" */
32 	if (strcmp(key, "check"))
33 		return -1;
34 
35 	/* we check that the value is "value$(count)" */
36 	snprintf(buf, sizeof(buf), "value%d", count);
37 	if (strncmp(buf, value, sizeof(buf)))
38 		return -1;
39 
40 	count ++;
41 	return 0;
42 }
43 
44 static int
45 check_only_handler(const char *key, const char *value, __rte_unused void *opaque)
46 {
47 	if (strcmp(key, "check"))
48 		return -1;
49 
50 	if (value != NULL)
51 		return -1;
52 
53 	return 0;
54 }
55 
56 static int
57 test_basic_token_count(void)
58 {
59 	static const struct {
60 		unsigned int expected;
61 		const char *input;
62 	} valid_inputs[] = {
63 		{ 3, "foo=1,check=1,check=2" },
64 		{ 3, "foo=1,check,check=2"   },
65 		{ 2, "foo=1,foo="            },
66 		{ 2, "foo=1,foo="            },
67 		{ 2, "foo=1,foo"             },
68 		{ 2, "foo=1,=2"              },
69 		{ 2, "foo=1,,foo=2,,"        },
70 		{ 1, "foo=[1,2"              },
71 		{ 1, ",="                    },
72 		{ 1, "foo=["                 },
73 		{ 0, ""                      },
74 	};
75 	struct rte_kvargs *kvlist;
76 	unsigned int count;
77 	const char *args;
78 	unsigned int i;
79 
80 	for (i = 0; i < RTE_DIM(valid_inputs); i++) {
81 		args = valid_inputs[i].input;
82 		kvlist = rte_kvargs_parse(args, NULL);
83 		if (kvlist == NULL) {
84 			printf("rte_kvargs_parse() error: %s\n", args);
85 			return -1;
86 		}
87 		count = rte_kvargs_count(kvlist, NULL);
88 		if (count != valid_inputs[i].expected) {
89 			printf("invalid count value %u (expected %u): %s\n",
90 			       count, valid_inputs[i].expected, args);
91 			rte_kvargs_free(kvlist);
92 			return -1;
93 		}
94 		rte_kvargs_free(kvlist);
95 	}
96 
97 	return 0;
98 }
99 
100 static int
101 test_parse_without_valid_keys(const void *params)
102 {
103 	const bool use_opt = *(const bool *)params;
104 	f_kvargs_process proc_func = use_opt ? rte_kvargs_process_opt : rte_kvargs_process;
105 	const char *proc_name = use_opt ? "rte_kvargs_process_opt" : "rte_kvargs_process";
106 	const char *args = "foo=1234,check=value0,check=value1";
107 	struct rte_kvargs *kvlist;
108 
109 	kvlist = rte_kvargs_parse(args, NULL);
110 	if (kvlist == NULL) {
111 		printf("rte_kvargs_parse() error\n");
112 		return -1;
113 	}
114 
115 	/* call check_handler() for all entries with key="check" */
116 	count = 0;
117 	if (proc_func(kvlist, "check", check_handler, NULL) < 0) {
118 		printf("%s(check) error\n", proc_name);
119 		rte_kvargs_free(kvlist);
120 		return -1;
121 	}
122 	if (count != 2) {
123 		printf("invalid count value %u after %s(check)\n",
124 			count, proc_name);
125 		rte_kvargs_free(kvlist);
126 		return -1;
127 	}
128 
129 	/* call check_handler() for all entries with key="nonexistent_key" */
130 	count = 0;
131 	if (proc_func(kvlist, "nonexistent_key", check_handler, NULL) < 0) {
132 		printf("%s(nonexistent_key) error\n", proc_name);
133 		rte_kvargs_free(kvlist);
134 		return -1;
135 	}
136 	if (count != 0) {
137 		printf("invalid count value %d after %s(nonexistent_key)\n",
138 			count, proc_name);
139 		rte_kvargs_free(kvlist);
140 		return -1;
141 	}
142 
143 	/* count all entries with key="foo" */
144 	count = rte_kvargs_count(kvlist, "foo");
145 	if (count != 1) {
146 		printf("invalid count value %d after rte_kvargs_count(foo)\n",
147 			count);
148 		rte_kvargs_free(kvlist);
149 		return -1;
150 	}
151 
152 	/* count all entries with key="nonexistent_key" */
153 	count = rte_kvargs_count(kvlist, "nonexistent_key");
154 	if (count != 0) {
155 		printf("invalid count value %d after rte_kvargs_count(nonexistent_key)\n",
156 			count);
157 		rte_kvargs_free(kvlist);
158 		return -1;
159 	}
160 
161 	rte_kvargs_free(kvlist);
162 	return 0;
163 }
164 
165 static int
166 test_parse_with_valid_keys(const void *params)
167 {
168 	const bool use_opt = *(const bool *)params;
169 	f_kvargs_process proc_func = use_opt ? rte_kvargs_process_opt : rte_kvargs_process;
170 	const char *proc_name = use_opt ? "rte_kvargs_process_opt" : "rte_kvargs_process";
171 	const char *args = "foo=droids,check=value0,check=value1,check=wrong_value";
172 	const char *valid_keys[] = { "foo", "check", NULL };
173 	struct rte_kvargs *kvlist;
174 
175 	kvlist = rte_kvargs_parse(args, valid_keys);
176 	if (kvlist == NULL) {
177 		printf("rte_kvargs_parse() error\n");
178 		return -1;
179 	}
180 
181 	/* call check_handler() on all entries with key="check", it
182 	 * should fail as the value is not recognized by the handler
183 	 */
184 	count = 0;
185 	if (proc_func(kvlist, "check", check_handler, NULL) == 0 || count != 2) {
186 		printf("%s(check) is success but should not\n", proc_name);
187 		rte_kvargs_free(kvlist);
188 		return -1;
189 	}
190 
191 	count = rte_kvargs_count(kvlist, "check");
192 	if (count != 3) {
193 		printf("invalid count value %u after rte_kvargs_count(check)\n",
194 			count);
195 		rte_kvargs_free(kvlist);
196 		return -1;
197 	}
198 
199 	rte_kvargs_free(kvlist);
200 	return 0;
201 }
202 
203 static int
204 test_parse_list_value(void)
205 {
206 	const char *valid_keys[] = { "foo", "check", NULL };
207 	const char *args = "foo=[0,1],check=value2";
208 	struct rte_kvargs *kvlist;
209 
210 	kvlist = rte_kvargs_parse(args, valid_keys);
211 	if (kvlist == NULL) {
212 		printf("rte_kvargs_parse() error\n");
213 		return -1;
214 	}
215 
216 	count = kvlist->count;
217 	if (count != 2) {
218 		printf("invalid count value %u\n", count);
219 		rte_kvargs_free(kvlist);
220 		return -1;
221 	}
222 
223 	if (strcmp(kvlist->pairs[0].value, "[0,1]") != 0) {
224 		printf("wrong value %s", kvlist->pairs[0].value);
225 		rte_kvargs_free(kvlist);
226 		return -1;
227 	}
228 
229 	rte_kvargs_free(kvlist);
230 	return 0;
231 }
232 
233 static int
234 test_parse_empty_elements(void)
235 {
236 	const char *args = "foo=1,,check=value2,,";
237 	struct rte_kvargs *kvlist;
238 
239 	kvlist = rte_kvargs_parse(args, NULL);
240 	if (kvlist == NULL) {
241 		printf("rte_kvargs_parse() error\n");
242 		return -1;
243 	}
244 
245 	count = kvlist->count;
246 	if (count != 2) {
247 		printf("invalid count value %u\n", count);
248 		rte_kvargs_free(kvlist);
249 		return -1;
250 	}
251 
252 	if (rte_kvargs_count(kvlist, "foo") != 1) {
253 		printf("invalid count value for 'foo'\n");
254 		rte_kvargs_free(kvlist);
255 		return -1;
256 	}
257 
258 	if (rte_kvargs_count(kvlist, "check") != 1) {
259 		printf("invalid count value for 'check'\n");
260 		rte_kvargs_free(kvlist);
261 		return -1;
262 	}
263 
264 	rte_kvargs_free(kvlist);
265 	return 0;
266 }
267 
268 static int
269 test_parse_with_only_key(void)
270 {
271 	const char *args = "foo,check";
272 	struct rte_kvargs *kvlist;
273 
274 	kvlist = rte_kvargs_parse(args, NULL);
275 	if (kvlist == NULL) {
276 		printf("rte_kvargs_parse() error\n");
277 		return -1;
278 	}
279 
280 	if (rte_kvargs_process(kvlist, "check", check_only_handler, NULL) == 0) {
281 		printf("rte_kvargs_process(check) error\n");
282 		rte_kvargs_free(kvlist);
283 		return -1;
284 	}
285 
286 	if (rte_kvargs_process_opt(kvlist, "check", check_only_handler, NULL) != 0) {
287 		printf("rte_kvargs_process_opt(check) error\n");
288 		rte_kvargs_free(kvlist);
289 		return -1;
290 	}
291 
292 	rte_kvargs_free(kvlist);
293 	return 0;
294 }
295 
296 /* test several error cases */
297 static int test_invalid_kvargs(void)
298 {
299 	struct rte_kvargs *kvlist;
300 	/* list of argument that should fail */
301 	const char *args_list[] = {
302 		"wrong-key=x",     /* key not in valid_keys_list */
303 		NULL };
304 	const char **args;
305 	const char *valid_keys_list[] = { "foo", "check", NULL };
306 	const char **valid_keys = valid_keys_list;
307 
308 	for (args = args_list; *args != NULL; args++) {
309 
310 		kvlist = rte_kvargs_parse(*args, valid_keys);
311 		if (kvlist != NULL) {
312 			printf("rte_kvargs_parse() returned 0 (but should not)\n");
313 			rte_kvargs_free(kvlist);
314 			goto fail;
315 		}
316 	}
317 	return 0;
318 
319  fail:
320 	printf("while processing <%s>", *args);
321 	if (valid_keys != NULL && *valid_keys != NULL) {
322 		printf(" using valid_keys=<%s", *valid_keys);
323 		while (*(++valid_keys) != NULL)
324 			printf(",%s", *valid_keys);
325 		printf(">");
326 	}
327 	printf("\n");
328 	return -1;
329 }
330 
331 static struct unit_test_suite kvargs_test_suite  = {
332 	.suite_name = "Kvargs Unit Test Suite",
333 	.setup = NULL,
334 	.teardown = NULL,
335 	.unit_test_cases = {
336 		TEST_CASE(test_basic_token_count),
337 		TEST_CASE_NAMED_WITH_DATA("test_parse_without_valid_keys_no_opt",
338 					  NULL, NULL,
339 					  test_parse_without_valid_keys,
340 					  &use_kvargs_process_opt[0]),
341 		TEST_CASE_NAMED_WITH_DATA("test_parse_without_valid_keys_with_opt",
342 					  NULL, NULL,
343 					  test_parse_without_valid_keys,
344 					  &use_kvargs_process_opt[1]),
345 		TEST_CASE_NAMED_WITH_DATA("test_parse_with_valid_keys_no_opt",
346 					  NULL, NULL,
347 					  test_parse_with_valid_keys,
348 					  &use_kvargs_process_opt[0]),
349 		TEST_CASE_NAMED_WITH_DATA("test_parse_with_valid_keys_with_opt",
350 					  NULL, NULL,
351 					  test_parse_with_valid_keys,
352 					  &use_kvargs_process_opt[1]),
353 		TEST_CASE(test_parse_list_value),
354 		TEST_CASE(test_parse_empty_elements),
355 		TEST_CASE(test_parse_with_only_key),
356 		TEST_CASE(test_invalid_kvargs),
357 		TEST_CASES_END() /**< NULL terminate unit test array */
358 	}
359 };
360 
361 static int
362 test_kvargs(void)
363 {
364 	return unit_test_suite_runner(&kvargs_test_suite);
365 }
366 
367 REGISTER_FAST_TEST(kvargs_autotest, true, true, test_kvargs);
368