15129044dSC.J. Collier/*
25129044dSC.J. Collier * Copyright 2014 6WIND S.A.
35129044dSC.J. Collier *
45129044dSC.J. Collier * Redistribution and use in source and binary forms, with or without
55129044dSC.J. Collier * modification, are permitted provided that the following conditions
65129044dSC.J. Collier * are met:
75129044dSC.J. Collier *
85129044dSC.J. Collier * - Redistributions of source code must retain the above copyright
95129044dSC.J. Collier *   notice, this list of conditions and the following disclaimer.
105129044dSC.J. Collier *
115129044dSC.J. Collier * - Redistributions in binary form must reproduce the above copyright
125129044dSC.J. Collier *   notice, this list of conditions and the following disclaimer in
135129044dSC.J. Collier *   the documentation and/or other materials provided with the
145129044dSC.J. Collier *   distribution.
155129044dSC.J. Collier *
165129044dSC.J. Collier * - Neither the name of 6WIND S.A. nor the names of its
175129044dSC.J. Collier *   contributors may be used to endorse or promote products derived
185129044dSC.J. Collier *   from this software without specific prior written permission.
195129044dSC.J. Collier *
205129044dSC.J. Collier * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
215129044dSC.J. Collier * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
225129044dSC.J. Collier * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
235129044dSC.J. Collier * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
245129044dSC.J. Collier * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
255129044dSC.J. Collier * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
265129044dSC.J. Collier * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
275129044dSC.J. Collier * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
285129044dSC.J. Collier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
295129044dSC.J. Collier * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
305129044dSC.J. Collier * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
315129044dSC.J. Collier * OF THE POSSIBILITY OF SUCH DAMAGE.
325129044dSC.J. Collier */
335129044dSC.J. Collier
345129044dSC.J. Collier#include <stdlib.h>
355129044dSC.J. Collier#include <stdio.h>
365129044dSC.J. Collier#include <string.h>
375129044dSC.J. Collier
385129044dSC.J. Collier#include <rte_common.h>
395129044dSC.J. Collier#include <rte_kvargs.h>
405129044dSC.J. Collier
415129044dSC.J. Collier#include "test.h"
425129044dSC.J. Collier
435129044dSC.J. Collier/* incrementd in handler, to check it is properly called once per
445129044dSC.J. Collier * key/value association */
455129044dSC.J. Collierstatic unsigned count;
465129044dSC.J. Collier
475129044dSC.J. Collier/* this handler increment the "count" variable at each call and check
485129044dSC.J. Collier * that the key is "check" and the value is "value%d" */
495129044dSC.J. Collierstatic int check_handler(const char *key, const char *value,
505129044dSC.J. Collier	__rte_unused void *opaque)
515129044dSC.J. Collier{
525129044dSC.J. Collier	char buf[16];
535129044dSC.J. Collier
545129044dSC.J. Collier	/* we check that the value is "check" */
555129044dSC.J. Collier	if (strcmp(key, "check"))
565129044dSC.J. Collier		return -1;
575129044dSC.J. Collier
585129044dSC.J. Collier	/* we check that the value is "value$(count)" */
595129044dSC.J. Collier	snprintf(buf, sizeof(buf), "value%d", count);
605129044dSC.J. Collier	if (strncmp(buf, value, sizeof(buf)))
615129044dSC.J. Collier		return -1;
625129044dSC.J. Collier
635129044dSC.J. Collier	count ++;
645129044dSC.J. Collier	return 0;
655129044dSC.J. Collier}
665129044dSC.J. Collier
675129044dSC.J. Collier/* test a valid case */
685129044dSC.J. Collierstatic int test_valid_kvargs(void)
695129044dSC.J. Collier{
705129044dSC.J. Collier	struct rte_kvargs *kvlist;
715129044dSC.J. Collier	const char *args;
725129044dSC.J. Collier	const char *valid_keys_list[] = { "foo", "check", NULL };
735129044dSC.J. Collier	const char **valid_keys;
745129044dSC.J. Collier
755129044dSC.J. Collier	/* empty args is valid */
765129044dSC.J. Collier	args = "";
775129044dSC.J. Collier	valid_keys = NULL;
785129044dSC.J. Collier	kvlist = rte_kvargs_parse(args, valid_keys);
795129044dSC.J. Collier	if (kvlist == NULL) {
805129044dSC.J. Collier		printf("rte_kvargs_parse() error");
815129044dSC.J. Collier		goto fail;
825129044dSC.J. Collier	}
835129044dSC.J. Collier	rte_kvargs_free(kvlist);
845129044dSC.J. Collier
855129044dSC.J. Collier	/* first test without valid_keys */
865129044dSC.J. Collier	args = "foo=1234,check=value0,check=value1";
875129044dSC.J. Collier	valid_keys = NULL;
885129044dSC.J. Collier	kvlist = rte_kvargs_parse(args, valid_keys);
895129044dSC.J. Collier	if (kvlist == NULL) {
905129044dSC.J. Collier		printf("rte_kvargs_parse() error");
915129044dSC.J. Collier		goto fail;
925129044dSC.J. Collier	}
935129044dSC.J. Collier	/* call check_handler() for all entries with key="check" */
945129044dSC.J. Collier	count = 0;
955129044dSC.J. Collier	if (rte_kvargs_process(kvlist, "check", check_handler, NULL) < 0) {
965129044dSC.J. Collier		printf("rte_kvargs_process() error\n");
975129044dSC.J. Collier		rte_kvargs_free(kvlist);
985129044dSC.J. Collier		goto fail;
995129044dSC.J. Collier	}
1005129044dSC.J. Collier	if (count != 2) {
1015129044dSC.J. Collier		printf("invalid count value %d after rte_kvargs_process(check)\n",
1025129044dSC.J. Collier			count);
1035129044dSC.J. Collier		rte_kvargs_free(kvlist);
1045129044dSC.J. Collier		goto fail;
1055129044dSC.J. Collier	}
1065129044dSC.J. Collier	count = 0;
1075129044dSC.J. Collier	/* call check_handler() for all entries with key="unexistant_key" */
1085129044dSC.J. Collier	if (rte_kvargs_process(kvlist, "unexistant_key", check_handler, NULL) < 0) {
1095129044dSC.J. Collier		printf("rte_kvargs_process() error\n");
1105129044dSC.J. Collier		rte_kvargs_free(kvlist);
1115129044dSC.J. Collier		goto fail;
1125129044dSC.J. Collier	}
1135129044dSC.J. Collier	if (count != 0) {
1145129044dSC.J. Collier		printf("invalid count value %d after rte_kvargs_process(unexistant_key)\n",
1155129044dSC.J. Collier			count);
1165129044dSC.J. Collier		rte_kvargs_free(kvlist);
1175129044dSC.J. Collier		goto fail;
1185129044dSC.J. Collier	}
1195129044dSC.J. Collier	/* count all entries with key="foo" */
1205129044dSC.J. Collier	count = rte_kvargs_count(kvlist, "foo");
1215129044dSC.J. Collier	if (count != 1) {
1225129044dSC.J. Collier		printf("invalid count value %d after rte_kvargs_count(foo)\n",
1235129044dSC.J. Collier			count);
1245129044dSC.J. Collier		rte_kvargs_free(kvlist);
1255129044dSC.J. Collier		goto fail;
1265129044dSC.J. Collier	}
1275129044dSC.J. Collier	/* count all entries */
1285129044dSC.J. Collier	count = rte_kvargs_count(kvlist, NULL);
1295129044dSC.J. Collier	if (count != 3) {
1305129044dSC.J. Collier		printf("invalid count value %d after rte_kvargs_count(NULL)\n",
1315129044dSC.J. Collier			count);
1325129044dSC.J. Collier		rte_kvargs_free(kvlist);
1335129044dSC.J. Collier		goto fail;
1345129044dSC.J. Collier	}
1355129044dSC.J. Collier	/* count all entries with key="unexistant_key" */
1365129044dSC.J. Collier	count = rte_kvargs_count(kvlist, "unexistant_key");
1375129044dSC.J. Collier	if (count != 0) {
1385129044dSC.J. Collier		printf("invalid count value %d after rte_kvargs_count(unexistant_key)\n",
1395129044dSC.J. Collier			count);
1405129044dSC.J. Collier		rte_kvargs_free(kvlist);
1415129044dSC.J. Collier		goto fail;
1425129044dSC.J. Collier	}
1435129044dSC.J. Collier	rte_kvargs_free(kvlist);
1445129044dSC.J. Collier
1455129044dSC.J. Collier	/* second test using valid_keys */
1465129044dSC.J. Collier	args = "foo=droids,check=value0,check=value1,check=wrong_value";
1475129044dSC.J. Collier	valid_keys = valid_keys_list;
1485129044dSC.J. Collier	kvlist = rte_kvargs_parse(args, valid_keys);
1495129044dSC.J. Collier	if (kvlist == NULL) {
1505129044dSC.J. Collier		printf("rte_kvargs_parse() error");
1515129044dSC.J. Collier		goto fail;
1525129044dSC.J. Collier	}
1535129044dSC.J. Collier	/* call check_handler() on all entries with key="check", it
1545129044dSC.J. Collier	 * should fail as the value is not recognized by the handler */
1555129044dSC.J. Collier	if (rte_kvargs_process(kvlist, "check", check_handler, NULL) == 0) {
1565129044dSC.J. Collier		printf("rte_kvargs_process() is success bu should not\n");
1575129044dSC.J. Collier		rte_kvargs_free(kvlist);
1585129044dSC.J. Collier		goto fail;
1595129044dSC.J. Collier	}
1605129044dSC.J. Collier	count = rte_kvargs_count(kvlist, "check");
1615129044dSC.J. Collier	if (count != 3) {
1625129044dSC.J. Collier		printf("invalid count value %d after rte_kvargs_count(check)\n",
1635129044dSC.J. Collier			count);
1645129044dSC.J. Collier		rte_kvargs_free(kvlist);
1655129044dSC.J. Collier		goto fail;
1665129044dSC.J. Collier	}
1675129044dSC.J. Collier	rte_kvargs_free(kvlist);
1685129044dSC.J. Collier
1695129044dSC.J. Collier	return 0;
1705129044dSC.J. Collier
1715129044dSC.J. Collier fail:
1725129044dSC.J. Collier	printf("while processing <%s>", args);
1735129044dSC.J. Collier	if (valid_keys != NULL && *valid_keys != NULL) {
1745129044dSC.J. Collier		printf(" using valid_keys=<%s", *valid_keys);
1755129044dSC.J. Collier		while (*(++valid_keys) != NULL)
1765129044dSC.J. Collier			printf(",%s", *valid_keys);
1775129044dSC.J. Collier		printf(">");
1785129044dSC.J. Collier	}
1795129044dSC.J. Collier	printf("\n");
1805129044dSC.J. Collier	return -1;
1815129044dSC.J. Collier}
1825129044dSC.J. Collier
1835129044dSC.J. Collier/* test several error cases */
1845129044dSC.J. Collierstatic int test_invalid_kvargs(void)
1855129044dSC.J. Collier{
1865129044dSC.J. Collier	struct rte_kvargs *kvlist;
1875129044dSC.J. Collier	/* list of argument that should fail */
1885129044dSC.J. Collier	const char *args_list[] = {
1895129044dSC.J. Collier		"wrong-key=x",     /* key not in valid_keys_list */
1905129044dSC.J. Collier		"foo=1,foo=",      /* empty value */
1915129044dSC.J. Collier		"foo=1,,foo=2",    /* empty key/value */
1925129044dSC.J. Collier		"foo=1,foo",       /* no value */
1935129044dSC.J. Collier		"foo=1,=2",        /* no key */
1945129044dSC.J. Collier		",=",              /* also test with a smiley */
1955129044dSC.J. Collier		NULL };
1965129044dSC.J. Collier	const char **args;
1975129044dSC.J. Collier	const char *valid_keys_list[] = { "foo", "check", NULL };
1985129044dSC.J. Collier	const char **valid_keys = valid_keys_list;
1995129044dSC.J. Collier
2005129044dSC.J. Collier	for (args = args_list; *args != NULL; args++) {
2015129044dSC.J. Collier
2025129044dSC.J. Collier		kvlist = rte_kvargs_parse(*args, valid_keys);
2035129044dSC.J. Collier		if (kvlist != NULL) {
2045129044dSC.J. Collier			printf("rte_kvargs_parse() returned 0 (but should not)\n");
2055129044dSC.J. Collier			rte_kvargs_free(kvlist);
2065129044dSC.J. Collier			goto fail;
2075129044dSC.J. Collier		}
2085129044dSC.J. Collier		return 0;
2095129044dSC.J. Collier	}
2105129044dSC.J. Collier
2115129044dSC.J. Collier fail:
2125129044dSC.J. Collier	printf("while processing <%s>", *args);
2135129044dSC.J. Collier	if (valid_keys != NULL && *valid_keys != NULL) {
2145129044dSC.J. Collier		printf(" using valid_keys=<%s", *valid_keys);
2155129044dSC.J. Collier		while (*(++valid_keys) != NULL)
2165129044dSC.J. Collier			printf(",%s", *valid_keys);
2175129044dSC.J. Collier		printf(">");
2185129044dSC.J. Collier	}
2195129044dSC.J. Collier	printf("\n");
2205129044dSC.J. Collier	return -1;
2215129044dSC.J. Collier}
2225129044dSC.J. Collier
2235129044dSC.J. Collierstatic int
2245129044dSC.J. Colliertest_kvargs(void)
2255129044dSC.J. Collier{
2265129044dSC.J. Collier	printf("== test valid case ==\n");
2275129044dSC.J. Collier	if (test_valid_kvargs() < 0)
2285129044dSC.J. Collier		return -1;
2295129044dSC.J. Collier	printf("== test invalid case ==\n");
2305129044dSC.J. Collier	if (test_invalid_kvargs() < 0)
2315129044dSC.J. Collier		return -1;
2325129044dSC.J. Collier	return 0;
2335129044dSC.J. Collier}
2345129044dSC.J. Collier
2359ecc306dSRicardo SalvetiREGISTER_TEST_COMMAND(kvargs_autotest, test_kvargs);
236