Branch data Line data Source code
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 : 10 : 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 [ + - ]: 10 : if (strcmp(key, "check"))
33 : : return -1;
34 : :
35 : : /* we check that the value is "value$(count)" */
36 [ + + ]: 10 : snprintf(buf, sizeof(buf), "value%d", count);
37 [ + + ]: 10 : if (strncmp(buf, value, sizeof(buf)))
38 : : return -1;
39 : :
40 : 8 : count ++;
41 : 8 : return 0;
42 : : }
43 : :
44 : : static int
45 : 1 : check_only_handler(const char *key, const char *value, __rte_unused void *opaque)
46 : : {
47 [ + - ]: 1 : if (strcmp(key, "check"))
48 : : return -1;
49 : :
50 [ - + ]: 1 : if (value != NULL)
51 : 0 : return -1;
52 : :
53 : : return 0;
54 : : }
55 : :
56 : : static int
57 : 1 : 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 [ + + ]: 12 : for (i = 0; i < RTE_DIM(valid_inputs); i++) {
81 : 11 : args = valid_inputs[i].input;
82 : 11 : kvlist = rte_kvargs_parse(args, NULL);
83 [ - + ]: 11 : if (kvlist == NULL) {
84 : : printf("rte_kvargs_parse() error: %s\n", args);
85 : 0 : return -1;
86 : : }
87 : 11 : count = rte_kvargs_count(kvlist, NULL);
88 [ - + ]: 11 : if (count != valid_inputs[i].expected) {
89 : : printf("invalid count value %u (expected %u): %s\n",
90 : : count, valid_inputs[i].expected, args);
91 : 0 : rte_kvargs_free(kvlist);
92 : 0 : return -1;
93 : : }
94 : 11 : rte_kvargs_free(kvlist);
95 : : }
96 : :
97 : : return 0;
98 : : }
99 : :
100 : : static int
101 : 2 : test_parse_without_valid_keys(const void *params)
102 : : {
103 : 2 : const bool use_opt = *(const bool *)params;
104 [ + + ]: 2 : f_kvargs_process proc_func = use_opt ? rte_kvargs_process_opt : rte_kvargs_process;
105 [ + + ]: 2 : 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 : 2 : kvlist = rte_kvargs_parse(args, NULL);
110 [ - + ]: 2 : if (kvlist == NULL) {
111 : : printf("rte_kvargs_parse() error\n");
112 : 0 : return -1;
113 : : }
114 : :
115 : : /* call check_handler() for all entries with key="check" */
116 : 2 : count = 0;
117 [ - + ]: 2 : if (proc_func(kvlist, "check", check_handler, NULL) < 0) {
118 : : printf("%s(check) error\n", proc_name);
119 : 0 : rte_kvargs_free(kvlist);
120 : 0 : return -1;
121 : : }
122 [ - + ]: 2 : if (count != 2) {
123 : : printf("invalid count value %u after %s(check)\n",
124 : : count, proc_name);
125 : 0 : rte_kvargs_free(kvlist);
126 : 0 : return -1;
127 : : }
128 : :
129 : : /* call check_handler() for all entries with key="nonexistent_key" */
130 : 2 : count = 0;
131 [ - + ]: 2 : if (proc_func(kvlist, "nonexistent_key", check_handler, NULL) < 0) {
132 : : printf("%s(nonexistent_key) error\n", proc_name);
133 : 0 : rte_kvargs_free(kvlist);
134 : 0 : return -1;
135 : : }
136 [ - + ]: 2 : if (count != 0) {
137 : : printf("invalid count value %d after %s(nonexistent_key)\n",
138 : : count, proc_name);
139 : 0 : rte_kvargs_free(kvlist);
140 : 0 : return -1;
141 : : }
142 : :
143 : : /* count all entries with key="foo" */
144 : 2 : count = rte_kvargs_count(kvlist, "foo");
145 [ - + ]: 2 : if (count != 1) {
146 : : printf("invalid count value %d after rte_kvargs_count(foo)\n",
147 : : count);
148 : 0 : rte_kvargs_free(kvlist);
149 : 0 : return -1;
150 : : }
151 : :
152 : : /* count all entries with key="nonexistent_key" */
153 : 2 : count = rte_kvargs_count(kvlist, "nonexistent_key");
154 [ - + ]: 2 : if (count != 0) {
155 : : printf("invalid count value %d after rte_kvargs_count(nonexistent_key)\n",
156 : : count);
157 : 0 : rte_kvargs_free(kvlist);
158 : 0 : return -1;
159 : : }
160 : :
161 : 2 : rte_kvargs_free(kvlist);
162 : 2 : return 0;
163 : : }
164 : :
165 : : static int
166 : 2 : test_parse_with_valid_keys(const void *params)
167 : : {
168 : 2 : const bool use_opt = *(const bool *)params;
169 [ + + ]: 2 : f_kvargs_process proc_func = use_opt ? rte_kvargs_process_opt : rte_kvargs_process;
170 [ + + ]: 2 : 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 : 2 : const char *valid_keys[] = { "foo", "check", NULL };
173 : : struct rte_kvargs *kvlist;
174 : :
175 : 2 : kvlist = rte_kvargs_parse(args, valid_keys);
176 [ - + ]: 2 : if (kvlist == NULL) {
177 : : printf("rte_kvargs_parse() error\n");
178 : 0 : 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 : 2 : count = 0;
185 [ + - - + ]: 2 : if (proc_func(kvlist, "check", check_handler, NULL) == 0 || count != 2) {
186 : : printf("%s(check) is success but should not\n", proc_name);
187 : 0 : rte_kvargs_free(kvlist);
188 : 0 : return -1;
189 : : }
190 : :
191 : 2 : count = rte_kvargs_count(kvlist, "check");
192 [ - + ]: 2 : if (count != 3) {
193 : : printf("invalid count value %u after rte_kvargs_count(check)\n",
194 : : count);
195 : 0 : rte_kvargs_free(kvlist);
196 : 0 : return -1;
197 : : }
198 : :
199 : 2 : rte_kvargs_free(kvlist);
200 : 2 : return 0;
201 : : }
202 : :
203 : : static int
204 : 1 : test_parse_list_value(void)
205 : : {
206 : 1 : const char *valid_keys[] = { "foo", "check", NULL };
207 : : const char *args = "foo=[0,1],check=value2";
208 : : struct rte_kvargs *kvlist;
209 : :
210 : 1 : kvlist = rte_kvargs_parse(args, valid_keys);
211 [ - + ]: 1 : if (kvlist == NULL) {
212 : : printf("rte_kvargs_parse() error\n");
213 : 0 : return -1;
214 : : }
215 : :
216 : 1 : count = kvlist->count;
217 [ - + ]: 1 : if (count != 2) {
218 : : printf("invalid count value %u\n", count);
219 : 0 : rte_kvargs_free(kvlist);
220 : 0 : return -1;
221 : : }
222 : :
223 [ - + ]: 1 : if (strcmp(kvlist->pairs[0].value, "[0,1]") != 0) {
224 : : printf("wrong value %s", kvlist->pairs[0].value);
225 : 0 : rte_kvargs_free(kvlist);
226 : 0 : return -1;
227 : : }
228 : :
229 : 1 : rte_kvargs_free(kvlist);
230 : 1 : return 0;
231 : : }
232 : :
233 : : static int
234 : 1 : test_parse_empty_elements(void)
235 : : {
236 : : const char *args = "foo=1,,check=value2,,";
237 : : struct rte_kvargs *kvlist;
238 : :
239 : 1 : kvlist = rte_kvargs_parse(args, NULL);
240 [ - + ]: 1 : if (kvlist == NULL) {
241 : : printf("rte_kvargs_parse() error\n");
242 : 0 : return -1;
243 : : }
244 : :
245 : 1 : count = kvlist->count;
246 [ - + ]: 1 : if (count != 2) {
247 : : printf("invalid count value %u\n", count);
248 : 0 : rte_kvargs_free(kvlist);
249 : 0 : return -1;
250 : : }
251 : :
252 [ - + ]: 1 : if (rte_kvargs_count(kvlist, "foo") != 1) {
253 : : printf("invalid count value for 'foo'\n");
254 : 0 : rte_kvargs_free(kvlist);
255 : 0 : return -1;
256 : : }
257 : :
258 [ - + ]: 1 : if (rte_kvargs_count(kvlist, "check") != 1) {
259 : : printf("invalid count value for 'check'\n");
260 : 0 : rte_kvargs_free(kvlist);
261 : 0 : return -1;
262 : : }
263 : :
264 : 1 : rte_kvargs_free(kvlist);
265 : 1 : return 0;
266 : : }
267 : :
268 : : static int
269 : 1 : test_parse_with_only_key(void)
270 : : {
271 : : const char *args = "foo,check";
272 : : struct rte_kvargs *kvlist;
273 : :
274 : 1 : kvlist = rte_kvargs_parse(args, NULL);
275 [ - + ]: 1 : if (kvlist == NULL) {
276 : : printf("rte_kvargs_parse() error\n");
277 : 0 : return -1;
278 : : }
279 : :
280 [ - + ]: 1 : if (rte_kvargs_process(kvlist, "check", check_only_handler, NULL) == 0) {
281 : : printf("rte_kvargs_process(check) error\n");
282 : 0 : rte_kvargs_free(kvlist);
283 : 0 : return -1;
284 : : }
285 : :
286 [ - + ]: 1 : if (rte_kvargs_process_opt(kvlist, "check", check_only_handler, NULL) != 0) {
287 : : printf("rte_kvargs_process_opt(check) error\n");
288 : 0 : rte_kvargs_free(kvlist);
289 : 0 : return -1;
290 : : }
291 : :
292 : 1 : rte_kvargs_free(kvlist);
293 : 1 : return 0;
294 : : }
295 : :
296 : : /* test several error cases */
297 : 1 : static int test_invalid_kvargs(void)
298 : : {
299 : : struct rte_kvargs *kvlist;
300 : : /* list of argument that should fail */
301 : 1 : const char *args_list[] = {
302 : : "wrong-key=x", /* key not in valid_keys_list */
303 : : NULL };
304 : : const char **args;
305 : 1 : const char *valid_keys_list[] = { "foo", "check", NULL };
306 : : const char **valid_keys = valid_keys_list;
307 : :
308 [ + + ]: 2 : for (args = args_list; *args != NULL; args++) {
309 : :
310 : 1 : kvlist = rte_kvargs_parse(*args, valid_keys);
311 [ - + ]: 1 : if (kvlist != NULL) {
312 : : printf("rte_kvargs_parse() returned 0 (but should not)\n");
313 : 0 : rte_kvargs_free(kvlist);
314 : 0 : goto fail;
315 : : }
316 : : }
317 : : return 0;
318 : :
319 : : fail:
320 : : printf("while processing <%s>", *args);
321 [ # # ]: 0 : if (valid_keys != NULL && *valid_keys != NULL) {
322 : : printf(" using valid_keys=<%s", *valid_keys);
323 [ # # ]: 0 : while (*(++valid_keys) != NULL)
324 : : printf(",%s", *valid_keys);
325 : : printf(">");
326 : : }
327 : : printf("\n");
328 : 0 : 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 : 1 : test_kvargs(void)
363 : : {
364 : 1 : return unit_test_suite_runner(&kvargs_test_suite);
365 : : }
366 : :
367 : 251 : REGISTER_FAST_TEST(kvargs_autotest, true, true, test_kvargs);
|