diff --git a/tests/unit/tests/utils/utils_rbtree.c/utils_rbtree.c b/tests/unit/tests/utils/utils_rbtree.c/utils_rbtree.c new file mode 100644 index 0000000..dae23fe --- /dev/null +++ b/tests/unit/tests/utils/utils_rbtree.c/utils_rbtree.c @@ -0,0 +1,227 @@ +/* + * Copyright(c) 2012-2020 Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause-Clear + */ + +/* + * src/utils/utils_rbtree.c + * ocf_rb_tree_insert + * + * ocf_rb_tree_init + * ocf_rb_tree_update_parent + * ocf_rb_tree_update_children + * ocf_rb_tree_rotate_left + * ocf_rb_tree_rotate_right + * ocf_rb_tree_fix_violation + * ocf_rb_tree_fix_violation + * ocf_rb_tree_insert + * ocf_rb_tree_swap + * ocf_rb_tree_successor + * ocf_rb_tree_predecessor + * ocf_rb_tree_bst_replacement + * ocf_rb_tree_sibling + * ocf_rb_tree_fix_double_black + * ocf_rb_tree_remove + * ocf_rb_tree_can_update + * ocf_rb_tree_find + * + */ + +#undef static + +#undef inline + + +#include +#include +#include +#include +#include "print_desc.h" + +#include "utils_rbtree.h" + +#include "utils/utils_rbtree.c/utils_rbtree_generated_wraps.c" + +struct test_node { + int val; + struct ocf_rb_node tree; +}; + +static int test_cmp(struct ocf_rb_node *n1, + struct ocf_rb_node *n2) +{ + struct test_node *t1 = container_of(n1, + struct test_node, tree); + struct test_node *t2 = container_of(n2, + struct test_node, tree); + + if (t1->val > t2->val) + return 1; + + if (t1->val < t2->val) + return -1; + + return 0; +} + +struct test_node nodes[] = {{.val=50}, {.val=25}, {.val=12}, {.val=6}, + {.val=3}, {.val=1}, {.val=37}, {.val=42}, + {.val=45}, {.val=47}, {.val=75}, {.val=87}, + {.val=92}, {.val=97}, {.val=99}, {.val=67}, + {.val=62}, {.val=57}, {.val=55}, {.val=299}}; +size_t nodes_number = sizeof(nodes)/sizeof(nodes[0]); + +#define get_node(__ptr) container_of(__ptr, struct test_node, tree) + +void prepare(struct ocf_rb_tree *tree) +{ + int i; + + ocf_rb_tree_init(tree, test_cmp); + + for (i = 0; i < nodes_number; i++) + ocf_rb_tree_insert(tree, &nodes[i].tree); +} + +static void ocf_rb_tree_test01(void **state) +{ + struct ocf_rb_tree tree; + int i; + + print_test_description("Find existing values in tree"); + + prepare(&tree); + + for (i = 0; i < nodes_number; i++) { + struct test_node *tmp_node = ocf_rb_tree_find(&tree, &nodes[i].tree); + assert_int_equal(nodes[i].val, get_node(tmp_node)->val); + assert_ptr_equal(&nodes[i], get_node(tmp_node)); + } +} + +static void ocf_rb_tree_test02(void **state) +{ + struct ocf_rb_tree tree; + int i; + + struct test_node n_a_nodes[] = {{.val=250}, {.val=-1}, {.val=130}, + {.val=330}, {.val=123}, + {.val=420}, {.val=456}}; + size_t n_a_nodes_number = sizeof(n_a_nodes)/sizeof(n_a_nodes[0]); + + print_test_description("Lookup for non existing values"); + + prepare(&tree); + + for (i = 0; i < n_a_nodes_number; i++) { + assert_null(ocf_rb_tree_find(&tree, &n_a_nodes[i].tree)); + } +} + +static void ocf_rb_tree_test03(void **state) +{ + struct ocf_rb_tree tree; + struct test_node *node_to_remove = &nodes[5]; + struct test_node *tmp_node; + + print_test_description("Check if value is in tree, remove it, and recheck"); + + prepare(&tree); + + tmp_node = ocf_rb_tree_find(&tree, &node_to_remove->tree); + + assert_int_equal(node_to_remove->val, get_node(tmp_node)->val); + assert_ptr_equal(node_to_remove, get_node(tmp_node)); + + ocf_rb_tree_remove(&tree, &node_to_remove->tree); + + tmp_node = ocf_rb_tree_find(&tree, &node_to_remove->tree); + assert_null(tmp_node); +} + +static void ocf_rb_tree_test04(void **state) +{ + struct ocf_rb_tree tree; + struct test_node *node_to_update; + struct test_node new_node = {.val=49}; + + print_test_description("Check if node can be updated without " + "changing the tree"); + + prepare(&tree); + + node_to_update = &nodes[9]; //.val=47 + new_node.val = 49; + assert_true( + ocf_rb_tree_can_update(&tree, &node_to_update->tree, &new_node.tree) + ); + + node_to_update = &nodes[1]; //.val=25 + new_node.val = 30; + assert_true( + ocf_rb_tree_can_update(&tree, &node_to_update->tree, &new_node.tree) + ); + + node_to_update = &nodes[1]; //.val=25 + new_node.val = 14; + assert_true( + ocf_rb_tree_can_update(&tree, &node_to_update->tree, &new_node.tree) + ); + + node_to_update = &nodes[10]; //.val=75 + new_node.val = 70; + assert_true( + ocf_rb_tree_can_update(&tree, &node_to_update->tree, &new_node.tree) + ); +} + +static void ocf_rb_tree_test05(void **state) +{ + struct ocf_rb_tree tree; + struct test_node *node_to_update; + struct test_node new_node = {.val=49}; + + print_test_description("Verify if node can't be updated without " + "changing the tree"); + + prepare(&tree); + + node_to_update = &nodes[3]; //.val=6 + new_node.val = 13; + assert_false( + ocf_rb_tree_can_update(&tree, &node_to_update->tree, &new_node.tree) + ); + + node_to_update = &nodes[19]; //.val=299 + new_node.val = 2; + assert_false( + ocf_rb_tree_can_update(&tree, &node_to_update->tree, &new_node.tree) + ); + + node_to_update = &nodes[16]; //.val=62 + new_node.val = 50; + assert_false( + ocf_rb_tree_can_update(&tree, &node_to_update->tree, &new_node.tree) + ); + + node_to_update = &nodes[5]; //.val=1 + new_node.val = 50; + assert_false( + ocf_rb_tree_can_update(&tree, &node_to_update->tree, &new_node.tree) + ); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(ocf_rb_tree_test01), + cmocka_unit_test(ocf_rb_tree_test02), + cmocka_unit_test(ocf_rb_tree_test03), + cmocka_unit_test(ocf_rb_tree_test04), + cmocka_unit_test(ocf_rb_tree_test05) + }; + + print_message("Unit tests for rb tree\n"); + + return cmocka_run_group_tests(tests, NULL, NULL); +}