From: Mike D. Lowis Date: Fri, 19 Apr 2013 01:37:34 +0000 (-0400) Subject: commit tests for tree X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=9e88f9ebeb2ca737867d137f45e0e1f5472b5d66;p=projs%2Flibcds.git commit tests for tree --- diff --git a/source/tree/tree.c b/source/tree/tree.c index 051ec9b..324a3d2 100644 --- a/source/tree/tree.c +++ b/source/tree/tree.c @@ -7,10 +7,12 @@ #include #include "tree.h" +#include + tree_t* tree_new(tree_cmp_fn_t cmp_fn) { tree_t* tree = (tree_t*)malloc(sizeof(tree_t)); - tree->cmp_fn = (NULL == cmp_fn) ? tree_cmp_ptrs : cmp_fn; + tree->cmp_fn = (NULL == cmp_fn) ? &tree_cmp_ptrs : cmp_fn; tree->size = 0; tree->root = NULL; return tree; @@ -37,7 +39,8 @@ int tree_cmp_ptrs(void* tval,void* fval) void tree_free(tree_t* tree, bool free_values) { - tree_free_node(tree->root, free_values); + if (NULL != tree->root) + tree_free_node(tree->root, free_values); free(tree); } @@ -71,41 +74,49 @@ void tree_insert(tree_t* tree, void* value) { bool finished = false; tree_node_t* node = tree->root; - while(!finished) + if (node == NULL) + { + tree->root = tree_new_node( value ); + tree->size++; + } + else { - switch (tree->cmp_fn(node->value, value)) + while(!finished) { - // If the value is already in the tree - case 0: - // Nothing to do because it's already there. - finished = true; - break; - - case -1: - if (NULL == node->right) - { - node->right = tree_new_node( value ); - tree->size++; + switch (tree->cmp_fn(node->value, value)) + { + // If the value is already in the tree + case 0: + // Nothing to do because it's already there. finished = true; - } - else - { - node = node->right; - } - break; - - case 1: - if (NULL == node->left) - { - node->left = tree_new_node( value ); - tree->size++; - finished = true; - } - else - { - node = node->left; - } - break; + break; + + case -1: + if (NULL == node->right) + { + node->right = tree_new_node( value ); + tree->size++; + finished = true; + } + else + { + node = node->right; + } + break; + + case 1: + if (NULL == node->left) + { + node->left = tree_new_node( value ); + tree->size++; + finished = true; + } + else + { + node = node->left; + } + break; + } } } } @@ -116,47 +127,51 @@ void* tree_at(tree_t* tree, void* value) tree_node_t* node = tree->root; while(node != NULL) { - switch (tree->cmp_fn(node->value, value)) + int cmp_val = tree->cmp_fn(node->value, value); + if (0 == cmp_val) + { + ret_val = node->value; + node = NULL; + } + else { - case 0: - ret_val = node->value; - node = NULL; - break; - - case -1: - node = node->right; - break; - - case 1: - node = node->left; - break; + node = (-1 == cmp_val) ? node->right : node->left; } } return ret_val; } -void tree_erase(tree_t* tree, void* value) +void tree_erase(tree_t* tree, void* value, bool free_value) { - //tree_node_t* prev_node = NULL; - //tree_node_t* curr_node = tree->root; - //while(node != NULL) - //{ - // switch (tree->cmp_fn(node->value, value)) - // { - // case 0: - // ret_val = node->value; - // node = NULL; - // break; - - // case -1: - // node = node->right; - // break; - - // case 1: - // node = node->left; - // break; - // } - //} + tree_node_t* prev_node = NULL; + tree_node_t* curr_node = tree->root; + while(curr_node != NULL) + { + int cmp_val = tree->cmp_fn(curr_node->value, value); + if (0 == cmp_val) + { + // Node to delete has no children + if ((curr_node->left == NULL) && (curr_node->right == NULL)) + { + //tree_erase_leaf(prev_node,curr_node); + } + // Node to delete has two children + else if ((curr_node->left != NULL) && (curr_node->right != NULL)) + { + //tree_erase_inner_node(prev_node,curr_node); + } + // Node only has one child + else + { + //tree_erase_node(prev_node,curr_node); + } + } + else + { + prev_node = curr_node; + curr_node = (-1 == cmp_val) ? curr_node->right : curr_node->left; + } + } } void tree_clear(tree_t* tree, bool free_values) diff --git a/source/tree/tree.h b/source/tree/tree.h index 1fe6836..5611be5 100644 --- a/source/tree/tree.h +++ b/source/tree/tree.h @@ -1,6 +1,6 @@ /** @file tree.h - @brief An implementation of a binary tree. + @brief An implementation of a binary search tree. $Revision$ $HeadURL$ */ @@ -139,7 +139,7 @@ void* tree_at(tree_t* tree, void* value); * @param tree The tree from which the value will be removed. * @param value Pointer to the value to erase. */ -void tree_erase(tree_t* tree, void* value); +void tree_erase(tree_t* tree, void* value, bool free_value); /** * @brief Erase all values in the tree. diff --git a/tests/test_tree.cpp b/tests/test_tree.cpp index 8e12564..1459cdc 100644 --- a/tests/test_tree.cpp +++ b/tests/test_tree.cpp @@ -1,7 +1,7 @@ // Unit Test Framework Includes #include "UnitTest++.h" #include -#include +#include // File To Test #include "tree.h" @@ -12,5 +12,197 @@ using namespace UnitTest; // Begin Unit Tests //----------------------------------------------------------------------------- namespace { + //------------------------------------------------------------------------- + // Test tree_new function + //------------------------------------------------------------------------- + TEST(Verify_tree_new_allocates_a_new_tree_with_default_compare_fn) + { + tree_t* tree = tree_new(NULL); + CHECK(tree != NULL); + CHECK(tree->cmp_fn != NULL); + CHECK(tree->size == 0); + CHECK(tree->root == NULL); + tree_free( tree, false ); + } + TEST(Verify_tree_new_allocates_a_new_tree_with_provided_compare_fn) + { + tree_t* tree = tree_new( (tree_cmp_fn_t)0x1234 ); + CHECK(tree != NULL); + CHECK(tree->cmp_fn == (tree_cmp_fn_t)0x1234); + CHECK(tree->size == 0); + CHECK(tree->root == NULL); + tree_free( tree, false ); + } + + //------------------------------------------------------------------------- + // Test tree_new_node function + //------------------------------------------------------------------------- + TEST(Verify_tree_new_node_allocates_a_new_tree_node_with_the_given_value) + { + tree_node_t* node = tree_new_node((void*)0x1234); + CHECK( node->value == (void*)0x1234); + CHECK( node->left == NULL); + CHECK( node->right == NULL); + tree_free_node( node, false ); + } + + //------------------------------------------------------------------------- + // Test tree_cmp_ptrs function + //------------------------------------------------------------------------- + TEST(Verify_tree_cmp_ptrs_returns_0_when_pointers_equal) + { + CHECK(0 == tree_cmp_ptrs((void*)0x1234,(void*)0x1234)); + } + + TEST(Verify_tree_cmp_ptrs_returns_negative_when_tree_pointer_is_less_than_free_pointer) + { + CHECK(-1 == tree_cmp_ptrs((void*)0x1234,(void*)0x1235)); + } + + TEST(Verify_tree_cmp_ptrs_returns_positive_when_tree_pointer_is_greater_than_free_pointer) + { + CHECK(1 == tree_cmp_ptrs((void*)0x1234,(void*)0x1233)); + } + + //------------------------------------------------------------------------- + // Test tree_empty function + //------------------------------------------------------------------------- + TEST(Verify_tree_empty_returns_true_if_tree_is_empty) + { + tree_t tree = { NULL, 0, NULL }; + CHECK( true == tree_empty( &tree ) ); + } + + TEST(Verify_tree_empty_returns_false_if_tree_is_not_empty) + { + tree_t tree = { NULL, 1, NULL }; + CHECK( false == tree_empty( &tree ) ); + } + + //------------------------------------------------------------------------- + // Test tree_size function + //------------------------------------------------------------------------- + TEST(Verify_tree_size_returns_the_number_of_elements_in_the_tree) + { + tree_t tree = { NULL, 42, NULL }; + CHECK( 42 == tree_size( &tree ) ); + } + + //------------------------------------------------------------------------- + // Test tree_max_size function + //------------------------------------------------------------------------- + TEST(Verify_max_size_returns_the_maximum_number_of_elements_a_tree_can_hold) + { + CHECK( (size_t)-1 == tree_max_size() ); + } + + //------------------------------------------------------------------------- + // Test tree_insert function + //------------------------------------------------------------------------- + TEST(Verify_tree_insert_inserts_the_value_in_the_empty_tree) + { + tree_t* tree = tree_new(NULL); + tree_insert(tree,(void*)0x1234); + CHECK( tree->root != NULL ); + CHECK( tree->root->value == (void*)0x1234 ); + CHECK( tree->root->left == NULL ); + CHECK( tree->root->right == NULL ); + CHECK( tree->size == 1 ); + tree_free(tree,false); + } + + TEST(Verify_tree_insert_inserts_the_value_as_a_left_child) + { + tree_t* tree = tree_new(NULL); + tree_insert(tree,(void*)0x1234); + tree_insert(tree,(void*)0x1233); + + CHECK( tree->root->left != NULL ); + tree_node_t* node = (tree_node_t*)tree->root->left; + CHECK( node->value == (void*)0x1233 ); + CHECK( node->left == NULL ); + CHECK( node->right == NULL ); + CHECK( tree->size == 2 ); + + tree_free(tree,false); + } + + TEST(Verify_tree_insert_inserts_the_value_as_a_right_child) + { + tree_t* tree = tree_new(NULL); + tree_insert(tree,(void*)0x1234); + tree_insert(tree,(void*)0x1235); + + CHECK( tree->root->right != NULL ); + tree_node_t* node = (tree_node_t*)tree->root->right; + CHECK( node->value == (void*)0x1235 ); + CHECK( node->left == NULL ); + CHECK( node->right == NULL ); + CHECK( tree->size == 2 ); + + tree_free(tree,false); + } + + TEST(Verify_tree_insert_does_nothing_when_identical_node_already_exists) + { + tree_t* tree = tree_new(NULL); + tree_insert(tree,(void*)0x1234); + tree_insert(tree,(void*)0x1234); + CHECK( tree->root != NULL ); + CHECK( tree->root->value == (void*)0x1234 ); + CHECK( tree->root->left == NULL ); + CHECK( tree->root->right == NULL ); + CHECK( tree->size == 1 ); + tree_free(tree,false); + } + + //------------------------------------------------------------------------- + // Test tree_at function + //------------------------------------------------------------------------- + TEST(Verify_tree_at_returns_the_item_if_found) + { + tree_t* tree = tree_new(NULL); + tree_insert(tree,(void*)0x1234); + tree_insert(tree,(void*)0x1233); + tree_insert(tree,(void*)0x1235); + CHECK( (void*)0x1234 == tree_at(tree,(void*)0x1234) ); + tree_free(tree,false); + } + + TEST(Verify_tree_at_returns_null_if_tem_not_found) + { + tree_t* tree = tree_new(NULL); + tree_insert(tree,(void*)0x1234); + tree_insert(tree,(void*)0x1233); + tree_insert(tree,(void*)0x1235); + CHECK( (void*)NULL == tree_at(tree,(void*)0x1236) ); + tree_free(tree,false); + } + + //------------------------------------------------------------------------- + // Test tree_erase function + //------------------------------------------------------------------------- + TEST(Verify_tree_erase_erases_the_node_with_the_matching_value) + { + } + + //------------------------------------------------------------------------- + // Test tree_clear function + //------------------------------------------------------------------------- + TEST(Verify_tree_clear_erases_all_nodes_in_the_tree) + { + tree_t* tree = tree_new(NULL); + tree_insert(tree,(void*)0x1234); + tree_insert(tree,(void*)0x1233); + tree_insert(tree,(void*)0x1235); + + tree_clear(tree,false); + CHECK(tree != NULL); + CHECK(tree->cmp_fn != NULL); + CHECK(tree->size == 0); + CHECK(tree->root == NULL); + + tree_free(tree,false); + } }