0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-05 08:31:53 +00:00

Birdtest: add test for filter/tree.c

This commit is contained in:
Pavel Tvrdík 2015-08-19 14:55:51 +02:00
parent 1c7e2c284b
commit 4885a7167e

View File

@ -7,42 +7,272 @@
*/ */
#include "test/birdtest.h" #include "test/birdtest.h"
#include "test/utils.h" #include "test/bt-utils.h"
#include "filter/filter.h" #include "filter/filter.h"
static void static struct f_tree *
show_buffer(buffer *b) new_tree(uint id)
{ {
byte *p; struct f_tree *tree = f_new_tree();
for (p=b->start; p != b->pos; p++) tree->from.type = tree->to.type = T_INT;
bt_debug("%c", *p); tree->from.val.i = tree->to.val.i = id;
bt_debug("\n");
return tree;
} }
static int static void
t_tree(void) show_subtree(struct f_tree *node)
{ {
bt_bird_init(); if (!node)
return;
struct f_tree *a = f_new_tree(); if (node->from.val.i == node->to.val.i)
struct f_tree *b = f_new_tree(); bt_debug("%u ", node->from.val.i);
bt_assert(same_tree(a, b)); else
bt_debug("%u..%u ", node->from.val.i, node->to.val.i);
show_subtree(node->left);
show_subtree(node->right);
}
buffer buffer1; static void
LOG_BUFFER_INIT(buffer1); show_tree2(struct f_tree *root_node, const char *tree_name)
tree_format(a, &buffer1); {
bt_debug("%s: \n", tree_name);
bt_debug("[ ");
show_subtree(root_node);
bt_debug("]\n\n");
}
show_buffer(&buffer1); #define show_tree(tree) show_tree2(tree, #tree);
static uint
get_nodes_count_in_full_tree(uint height)
{
return (naive_pow(2, height+1) - 1);
}
static struct f_tree *
get_balanced_full_subtree(uint height, uint idx)
{
struct f_tree *node = new_tree(idx);
if (height > 0)
{
uint nodes_in_subtree = get_nodes_count_in_full_tree(--height);
node->left = get_balanced_full_subtree(height, idx - nodes_in_subtree/2 - 1);
node->right = get_balanced_full_subtree(height, idx + nodes_in_subtree/2 + 1);
}
return node;
}
static struct f_tree *
get_balanced_full_tree(uint height)
{
return get_balanced_full_subtree(height, get_nodes_count_in_full_tree(height)/2);
}
static struct f_tree *
get_degenerated_left_tree(uint nodes_count)
{
struct f_tree **nodes = (struct f_tree **) malloc(nodes_count * sizeof(struct f_tree *));
int i;
for (i = nodes_count-1; i >= 0; i--)
{
nodes[i] = new_tree(i);
if (i != nodes_count-1)
nodes[i]->left = nodes[i+1];
}
struct f_tree *root_node = nodes[0];
free(nodes);
return root_node;
}
static struct f_tree *
get_random_degenerated_left_tree(uint nodes_count)
{
struct f_tree *tree = get_degenerated_left_tree(nodes_count);
size_t avaible_indexes_size = nodes_count * sizeof(byte);
byte *avaible_indexes = malloc(avaible_indexes_size);
bzero(avaible_indexes, avaible_indexes_size);
struct f_tree *n;
for (n = tree; n; n = n->left)
{
uint selected_idx;
do {
selected_idx = bt_rand_num() % nodes_count;
} while(avaible_indexes[selected_idx] != 0);
avaible_indexes[selected_idx] = 1;
n->from.type = n->to.type = T_INT;
n->from.val.i = n->to.val.i = selected_idx;
}
free(avaible_indexes);
return tree;
}
static struct f_tree *
get_balanced_tree_with_ranged_values(uint nodes_count)
{
struct f_tree *tree = get_degenerated_left_tree(nodes_count);
uint idx = 0;
struct f_tree *n;
for (n = tree; n; n = n->left)
{
n->from.type = n->to.type = T_INT;
n->from.val.i = idx;
idx += (uint)bt_rand_num() / nodes_count; /* (... / nodes_count) preventing overflow an uint idx */
n->to.val.i = idx++;
}
return build_tree(tree);
}
static int
t_balancing(void)
{
bt_bird_init_with_simple_configuration();
uint height;
for (height = 1; height < 13; height++)
{
uint nodes_count = get_nodes_count_in_full_tree(height);
struct f_tree *simple_degenerated_tree = get_degenerated_left_tree(nodes_count);
struct f_tree *expected_balanced_tree = get_balanced_full_tree(height);
struct f_tree *balanced_tree_from_simple_degenerated = build_tree(simple_degenerated_tree);
show_tree(simple_degenerated_tree);
show_tree(expected_balanced_tree);
show_tree(balanced_tree_from_simple_degenerated);
bt_assert(same_tree(balanced_tree_from_simple_degenerated, expected_balanced_tree));
}
return BT_SUCCESS; return BT_SUCCESS;
} }
static int
t_balancing_random(void)
{
bt_bird_init_with_simple_configuration();
uint height;
for (height = 1; height < 10; height++)
{
uint nodes_count = get_nodes_count_in_full_tree(height);
struct f_tree *expected_balanced_tree = get_balanced_full_tree(height);
uint i;
for(i = 0; i < 10; i++)
{
struct f_tree *random_degenerated_tree = get_random_degenerated_left_tree(nodes_count);
struct f_tree *balanced_tree_from_random_degenerated = build_tree(random_degenerated_tree);
show_tree(random_degenerated_tree);
show_tree(expected_balanced_tree);
show_tree(balanced_tree_from_random_degenerated);
bt_assert(same_tree(balanced_tree_from_random_degenerated, expected_balanced_tree));
}
}
return BT_SUCCESS;
}
static int
t_find(void)
{
bt_bird_init_with_simple_configuration();
uint height;
for (height = 1; height < 13; height++)
{
uint nodes_count = get_nodes_count_in_full_tree(height);
struct f_tree *tree = get_balanced_full_tree(height);
struct f_val looking_up_value = {
.type = T_INT
};
for(looking_up_value.val.i = 0; looking_up_value.val.i < nodes_count; looking_up_value.val.i++)
{
struct f_tree *found_tree = find_tree(tree, looking_up_value);
bt_assert((val_compare(looking_up_value, found_tree->from) == 0) && (val_compare(looking_up_value, found_tree->to) == 0));
}
}
return BT_SUCCESS;
}
static uint
get_max_value_in_unbalanced_tree(struct f_tree *node, uint max)
{
if (!node)
return max;
if (node->to.val.i > max)
max = node->to.val.i;
uint max_left = get_max_value_in_unbalanced_tree(node->left, max);
if (max_left > max)
max = max_left;
uint max_right = get_max_value_in_unbalanced_tree(node->right, max);
if (max_right > max)
max = max_right;
return max;
}
static int
t_find_ranges(void)
{
bt_bird_init_with_simple_configuration();
uint height;
for (height = 1; height < 10; height++)
{
uint nodes_count = get_nodes_count_in_full_tree(height);
struct f_tree *tree = get_balanced_tree_with_ranged_values(nodes_count);
uint max_value = get_max_value_in_unbalanced_tree(tree, 0);
bt_debug("max_value: %u \n", max_value);
struct f_val looking_up_value = {
.type = T_INT
};
for(looking_up_value.val.i = 0; looking_up_value.val.i <= max_value; looking_up_value.val.i += ((uint)bt_rand_num()/nodes_count))
{
struct f_tree *found_tree = find_tree(tree, looking_up_value);
bt_debug("searching: %u \n", looking_up_value.val.i);
bt_assert(
(val_compare(looking_up_value, found_tree->from) == 0) || (val_compare(looking_up_value, found_tree->to) == 0) ||
((val_compare(looking_up_value, found_tree->from) == 1) && (val_compare(looking_up_value, found_tree->to) == -1))
);
}
}
return BT_SUCCESS;
}
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
bt_init(argc, argv); bt_init(argc, argv);
bt_test_suite(t_tree, "Tree Test"); bt_test_suite(t_balancing, "Balancing strong unbalanced trees");
bt_test_suite(t_balancing_random, "Balancing random unbalanced trees");
bt_test_suite(t_find, "Finding values in trees");
bt_test_suite(t_find_ranges, "Finding values in trees with random ranged values");
return bt_end(); return bt_end();
} }