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