#include "test/jemalloc_test.h"

#define	rbtn_black_height(a_type, a_field, a_rbt, r_height) do {	\
    a_type *rbp_bh_t;							\
    for (rbp_bh_t = (a_rbt)->rbt_root, (r_height) = 0;			\
	 rbp_bh_t != NULL;						\
      rbp_bh_t = rbtn_left_get(a_type, a_field, rbp_bh_t)) {		\
	if (!rbtn_red_get(a_type, a_field, rbp_bh_t)) {			\
	    (r_height)++;						\
	}								\
    }									\
} while (0)

typedef struct node_s node_t;

struct node_s {
#define	NODE_MAGIC 0x9823af7e
	uint32_t magic;
	rb_node(node_t) link;
	uint64_t key;
};

static int
node_cmp(const node_t *a, const node_t *b) {
	int ret;

	assert_u32_eq(a->magic, NODE_MAGIC, "Bad magic");
	assert_u32_eq(b->magic, NODE_MAGIC, "Bad magic");

	ret = (a->key > b->key) - (a->key < b->key);
	if (ret == 0) {
		/*
		 * Duplicates are not allowed in the tree, so force an
		 * arbitrary ordering for non-identical items with equal keys.
		 */
		ret = (((uintptr_t)a) > ((uintptr_t)b))
		    - (((uintptr_t)a) < ((uintptr_t)b));
	}
	return (ret);
}

typedef rb_tree(node_t) tree_t;
rb_gen(static, tree_, tree_t, node_t, link, node_cmp);

TEST_BEGIN(test_rb_empty)
{
	tree_t tree;
	node_t key;

	tree_new(&tree);

	assert_true(tree_empty(&tree), "Tree should be empty");
	assert_ptr_null(tree_first(&tree), "Unexpected node");
	assert_ptr_null(tree_last(&tree), "Unexpected node");

	key.key = 0;
	key.magic = NODE_MAGIC;
	assert_ptr_null(tree_search(&tree, &key), "Unexpected node");

	key.key = 0;
	key.magic = NODE_MAGIC;
	assert_ptr_null(tree_nsearch(&tree, &key), "Unexpected node");

	key.key = 0;
	key.magic = NODE_MAGIC;
	assert_ptr_null(tree_psearch(&tree, &key), "Unexpected node");
}
TEST_END

static unsigned
tree_recurse(node_t *node, unsigned black_height, unsigned black_depth)
{
	unsigned ret = 0;
	node_t *left_node;
	node_t *right_node;

	if (node == NULL)
		return (ret);

	left_node = rbtn_left_get(node_t, link, node);
	right_node = rbtn_right_get(node_t, link, node);

	if (!rbtn_red_get(node_t, link, node))
		black_depth++;

	/* Red nodes must be interleaved with black nodes. */
	if (rbtn_red_get(node_t, link, node)) {
		if (left_node != NULL)
			assert_false(rbtn_red_get(node_t, link, left_node),
				"Node should be black");
		if (right_node != NULL)
			assert_false(rbtn_red_get(node_t, link, right_node),
			    "Node should be black");
	}

	/* Self. */
	assert_u32_eq(node->magic, NODE_MAGIC, "Bad magic");

	/* Left subtree. */
	if (left_node != NULL)
		ret += tree_recurse(left_node, black_height, black_depth);
	else
		ret += (black_depth != black_height);

	/* Right subtree. */
	if (right_node != NULL)
		ret += tree_recurse(right_node, black_height, black_depth);
	else
		ret += (black_depth != black_height);

	return (ret);
}

static node_t *
tree_iterate_cb(tree_t *tree, node_t *node, void *data)
{
	unsigned *i = (unsigned *)data;
	node_t *search_node;

	assert_u32_eq(node->magic, NODE_MAGIC, "Bad magic");

	/* Test rb_search(). */
	search_node = tree_search(tree, node);
	assert_ptr_eq(search_node, node,
	    "tree_search() returned unexpected node");

	/* Test rb_nsearch(). */
	search_node = tree_nsearch(tree, node);
	assert_ptr_eq(search_node, node,
	    "tree_nsearch() returned unexpected node");

	/* Test rb_psearch(). */
	search_node = tree_psearch(tree, node);
	assert_ptr_eq(search_node, node,
	    "tree_psearch() returned unexpected node");

	(*i)++;

	return (NULL);
}

static unsigned
tree_iterate(tree_t *tree)
{
	unsigned i;

	i = 0;
	tree_iter(tree, NULL, tree_iterate_cb, (void *)&i);

	return (i);
}

static unsigned
tree_iterate_reverse(tree_t *tree)
{
	unsigned i;

	i = 0;
	tree_reverse_iter(tree, NULL, tree_iterate_cb, (void *)&i);

	return (i);
}

static void
node_remove(tree_t *tree, node_t *node, unsigned nnodes)
{
	node_t *search_node;
	unsigned black_height, imbalances;

	tree_remove(tree, node);

	/* Test rb_nsearch(). */
	search_node = tree_nsearch(tree, node);
	if (search_node != NULL) {
		assert_u64_ge(search_node->key, node->key,
		    "Key ordering error");
	}

	/* Test rb_psearch(). */
	search_node = tree_psearch(tree, node);
	if (search_node != NULL) {
		assert_u64_le(search_node->key, node->key,
		    "Key ordering error");
	}

	node->magic = 0;

	rbtn_black_height(node_t, link, tree, black_height);
	imbalances = tree_recurse(tree->rbt_root, black_height, 0);
	assert_u_eq(imbalances, 0, "Tree is unbalanced");
	assert_u_eq(tree_iterate(tree), nnodes-1,
	    "Unexpected node iteration count");
	assert_u_eq(tree_iterate_reverse(tree), nnodes-1,
	    "Unexpected node iteration count");
}

static node_t *
remove_iterate_cb(tree_t *tree, node_t *node, void *data)
{
	unsigned *nnodes = (unsigned *)data;
	node_t *ret = tree_next(tree, node);

	node_remove(tree, node, *nnodes);

	return (ret);
}

static node_t *
remove_reverse_iterate_cb(tree_t *tree, node_t *node, void *data)
{
	unsigned *nnodes = (unsigned *)data;
	node_t *ret = tree_prev(tree, node);

	node_remove(tree, node, *nnodes);

	return (ret);
}

static void
destroy_cb(node_t *node, void *data)
{
	unsigned *nnodes = (unsigned *)data;

	assert_u_gt(*nnodes, 0, "Destruction removed too many nodes");
	(*nnodes)--;
}

TEST_BEGIN(test_rb_random)
{
#define	NNODES 25
#define	NBAGS 250
#define	SEED 42
	sfmt_t *sfmt;
	uint64_t bag[NNODES];
	tree_t tree;
	node_t nodes[NNODES];
	unsigned i, j, k, black_height, imbalances;

	sfmt = init_gen_rand(SEED);
	for (i = 0; i < NBAGS; i++) {
		switch (i) {
		case 0:
			/* Insert in order. */
			for (j = 0; j < NNODES; j++)
				bag[j] = j;
			break;
		case 1:
			/* Insert in reverse order. */
			for (j = 0; j < NNODES; j++)
				bag[j] = NNODES - j - 1;
			break;
		default:
			for (j = 0; j < NNODES; j++)
				bag[j] = gen_rand64_range(sfmt, NNODES);
		}

		for (j = 1; j <= NNODES; j++) {
			/* Initialize tree and nodes. */
			tree_new(&tree);
			for (k = 0; k < j; k++) {
				nodes[k].magic = NODE_MAGIC;
				nodes[k].key = bag[k];
			}

			/* Insert nodes. */
			for (k = 0; k < j; k++) {
				tree_insert(&tree, &nodes[k]);

				rbtn_black_height(node_t, link, &tree,
				    black_height);
				imbalances = tree_recurse(tree.rbt_root,
				    black_height, 0);
				assert_u_eq(imbalances, 0,
				    "Tree is unbalanced");

				assert_u_eq(tree_iterate(&tree), k+1,
				    "Unexpected node iteration count");
				assert_u_eq(tree_iterate_reverse(&tree), k+1,
				    "Unexpected node iteration count");

				assert_false(tree_empty(&tree),
				    "Tree should not be empty");
				assert_ptr_not_null(tree_first(&tree),
				    "Tree should not be empty");
				assert_ptr_not_null(tree_last(&tree),
				    "Tree should not be empty");

				tree_next(&tree, &nodes[k]);
				tree_prev(&tree, &nodes[k]);
			}

			/* Remove nodes. */
			switch (i % 5) {
			case 0:
				for (k = 0; k < j; k++)
					node_remove(&tree, &nodes[k], j - k);
				break;
			case 1:
				for (k = j; k > 0; k--)
					node_remove(&tree, &nodes[k-1], k);
				break;
			case 2: {
				node_t *start;
				unsigned nnodes = j;

				start = NULL;
				do {
					start = tree_iter(&tree, start,
					    remove_iterate_cb, (void *)&nnodes);
					nnodes--;
				} while (start != NULL);
				assert_u_eq(nnodes, 0,
				    "Removal terminated early");
				break;
			} case 3: {
				node_t *start;
				unsigned nnodes = j;

				start = NULL;
				do {
					start = tree_reverse_iter(&tree, start,
					    remove_reverse_iterate_cb,
					    (void *)&nnodes);
					nnodes--;
				} while (start != NULL);
				assert_u_eq(nnodes, 0,
				    "Removal terminated early");
				break;
			} case 4: {
				unsigned nnodes = j;
				tree_destroy(&tree, destroy_cb, &nnodes);
				assert_u_eq(nnodes, 0,
				    "Destruction terminated early");
				break;
			} default:
				not_reached();
			}
		}
	}
	fini_gen_rand(sfmt);
#undef NNODES
#undef NBAGS
#undef SEED
}
TEST_END

int
main(void)
{

	return (test(
	    test_rb_empty,
	    test_rb_random));
}
