/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright 2016, Olivier MATZ <zer0@droids-corp.org>
 */

#include "test.h"

EC_TEST_MAIN()
{
	struct ec_node *node;
	int testres = 0;

	node = EC_NODE_SUBSET(
		EC_NO_ID,
		EC_NODE_OR(EC_NO_ID, ec_node_str(EC_NO_ID, "foo"), ec_node_str(EC_NO_ID, "bar")),
		ec_node_str(EC_NO_ID, "bar"),
		ec_node_str(EC_NO_ID, "toto")
	);
	if (node == NULL) {
		EC_LOG(EC_LOG_ERR, "cannot create node\n");
		return -1;
	}
	testres |= EC_TEST_CHECK_PARSE(node, 0);
	testres |= EC_TEST_CHECK_PARSE(node, 1, "foo");
	testres |= EC_TEST_CHECK_PARSE(node, 1, "bar");
	testres |= EC_TEST_CHECK_PARSE(node, 2, "foo", "bar", "titi");
	testres |= EC_TEST_CHECK_PARSE(node, 3, "bar", "foo", "toto");
	testres |= EC_TEST_CHECK_PARSE(node, 1, "foo", "foo");
	testres |= EC_TEST_CHECK_PARSE(node, 2, "bar", "bar");
	testres |= EC_TEST_CHECK_PARSE(node, 2, "bar", "foo");
	testres |= EC_TEST_CHECK_PARSE(node, 0, " ");
	testres |= EC_TEST_CHECK_PARSE(node, 0, "foox");
	ec_node_free(node);

	/* test with min=1 (at least one child must match) */
	node = EC_NODE_SUBSET(
		EC_NO_ID,
		ec_node_str(EC_NO_ID, "foo"),
		ec_node_str(EC_NO_ID, "bar"),
		ec_node_str(EC_NO_ID, "toto")
	);
	if (node == NULL) {
		EC_LOG(EC_LOG_ERR, "cannot create node\n");
		return -1;
	}
	ec_node_subset_set_min(node, 1);
	testres |= EC_TEST_CHECK_PARSE(node, -1);
	testres |= EC_TEST_CHECK_PARSE(node, 1, "foo");
	testres |= EC_TEST_CHECK_PARSE(node, 2, "foo", "bar");
	testres |= EC_TEST_CHECK_PARSE(node, 3, "bar", "foo", "toto");
	testres |= EC_TEST_CHECK_PARSE(node, -1, "x");
	ec_node_free(node);

	/* test with min=len (all children must match) */
	node = EC_NODE_SUBSET(
		EC_NO_ID,
		ec_node_str(EC_NO_ID, "foo"),
		ec_node_str(EC_NO_ID, "bar"),
		ec_node_str(EC_NO_ID, "toto")
	);
	if (node == NULL) {
		EC_LOG(EC_LOG_ERR, "cannot create node\n");
		return -1;
	}
	ec_node_subset_set_min(node, 3);
	testres |= EC_TEST_CHECK_PARSE(node, -1);
	testres |= EC_TEST_CHECK_PARSE(node, -1, "foo");
	testres |= EC_TEST_CHECK_PARSE(node, -1, "foo", "bar");
	testres |= EC_TEST_CHECK_PARSE(node, 3, "bar", "foo", "toto");
	testres |= EC_TEST_CHECK_PARSE(node, 3, "toto", "bar", "foo");
	testres |= EC_TEST_CHECK_PARSE(node, 3, "foo", "toto", "bar", "x");
	testres |= EC_TEST_CHECK_PARSE(node, -1, "x");
	ec_node_free(node);

	/* test that a non-matching subset with min=1 does not shadow or branches */
	{
		struct ec_node *subset;

		subset = EC_NODE_SUBSET(
			EC_NO_ID,
			ec_node_str(EC_NO_ID, "foo"),
			ec_node_str(EC_NO_ID, "bar"),
			ec_node_str(EC_NO_ID, "toto")
		);
		if (subset == NULL) {
			EC_LOG(EC_LOG_ERR, "cannot create node\n");
			return -1;
		}
		ec_node_subset_set_min(subset, 1);
		node = EC_NODE_OR(EC_NO_ID, subset, ec_node_str(EC_NO_ID, "id"));
		if (node == NULL) {
			EC_LOG(EC_LOG_ERR, "cannot create node\n");
			return -1;
		}
		testres |= EC_TEST_CHECK_PARSE(node, 1, "id");
		testres |= EC_TEST_CHECK_PARSE(node, 1, "foo");
		testres |= EC_TEST_CHECK_PARSE(node, 2, "foo", "bar");
		testres |= EC_TEST_CHECK_PARSE(node, -1, "x");
		ec_node_free(node);
	}

	/* test completion */
	node = EC_NODE_SUBSET(
		EC_NO_ID,
		ec_node_str(EC_NO_ID, "foo"),
		ec_node_str(EC_NO_ID, "bar"),
		ec_node_str(EC_NO_ID, "bar2"),
		ec_node_str(EC_NO_ID, "toto"),
		ec_node_str(EC_NO_ID, "titi")
	);
	if (node == NULL) {
		EC_LOG(EC_LOG_ERR, "cannot create node\n");
		return -1;
	}
	testres |= EC_TEST_CHECK_COMPLETE(
		node, "", EC_VA_END, "foo", "bar", "bar2", "toto", "titi", EC_VA_END
	);
	testres |= EC_TEST_CHECK_COMPLETE(
		node, "", EC_VA_END, "bar2", "bar", "foo", "toto", "titi", EC_VA_END
	);
	testres |= EC_TEST_CHECK_COMPLETE(
		node, "bar", "bar2", "", EC_VA_END, "foo", "toto", "titi", EC_VA_END
	);
	testres |= EC_TEST_CHECK_COMPLETE(node, "f", EC_VA_END, "foo", EC_VA_END);
	testres |= EC_TEST_CHECK_COMPLETE(node, "b", EC_VA_END, "bar", "bar2", EC_VA_END);
	testres |= EC_TEST_CHECK_COMPLETE(node, "bar", EC_VA_END, "bar", "bar2", EC_VA_END);
	testres |= EC_TEST_CHECK_COMPLETE(node, "bar", "b", EC_VA_END, "bar2", EC_VA_END);
	testres |= EC_TEST_CHECK_COMPLETE(node, "t", EC_VA_END, "toto", "titi", EC_VA_END);
	testres |= EC_TEST_CHECK_COMPLETE(node, "to", EC_VA_END, "toto", EC_VA_END);
	testres |= EC_TEST_CHECK_COMPLETE(node, "x", EC_VA_END, EC_VA_END);
	ec_node_free(node);

	return testres;
}
