forked from vieter-v/libvieter
				
			test(tree): validation function to use in testing
							parent
							
								
									89d1c9cdca
								
							
						
					
					
						commit
						3fb027715c
					
				| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
#include "vieter_tree.h"
 | 
			
		||||
#include "vieter_tree_internal.h"
 | 
			
		||||
#include "vieter_tree_node.h"
 | 
			
		||||
 | 
			
		||||
struct vieter_tree {
 | 
			
		||||
| 
						 | 
				
			
			@ -98,3 +98,23 @@ void vieter_tree_free(vieter_tree *tree) {
 | 
			
		|||
end:
 | 
			
		||||
  free(tree);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vieter_tree_validate(vieter_tree *tree) {
 | 
			
		||||
  if (tree->size == 0) {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // DFS to get expected black nodes
 | 
			
		||||
  uint64_t expected_black_nodes = 0;
 | 
			
		||||
  vieter_tree_node *node = tree->root;
 | 
			
		||||
 | 
			
		||||
  while (node != NULL) {
 | 
			
		||||
    if (vieter_tree_node_get(node, vieter_node_black)) {
 | 
			
		||||
      expected_black_nodes++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    node = node->left;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return vieter_tree_node_validate(tree->root, 0, expected_black_nodes);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,43 @@
 | 
			
		|||
#include "vieter_tree_balancing.h"
 | 
			
		||||
 | 
			
		||||
int vieter_tree_node_validate(vieter_tree_node *node,
 | 
			
		||||
                              uint64_t passed_black_nodes,
 | 
			
		||||
                              uint64_t expected_black_nodes) {
 | 
			
		||||
  if (vieter_tree_node_get(node, vieter_node_black)) {
 | 
			
		||||
    passed_black_nodes++;
 | 
			
		||||
  } else {
 | 
			
		||||
    // A red node should have black child nodes
 | 
			
		||||
    if ((node->left != NULL &&
 | 
			
		||||
         !vieter_tree_node_get(node->left, vieter_node_black)) ||
 | 
			
		||||
        (node->right != NULL &&
 | 
			
		||||
         !vieter_tree_node_get(node->right, vieter_node_black))) {
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // All paths to a NULL child should have the same amount of black nodes
 | 
			
		||||
  if ((node->left == NULL || node->right == NULL) &&
 | 
			
		||||
      passed_black_nodes != expected_black_nodes) {
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (node->left != NULL) {
 | 
			
		||||
    if (vieter_tree_node_validate(node->left, passed_black_nodes,
 | 
			
		||||
                                  expected_black_nodes) != 0) {
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (node->right != NULL) {
 | 
			
		||||
    if (vieter_tree_node_validate(node->right, passed_black_nodes,
 | 
			
		||||
                                  expected_black_nodes) != 0) {
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) {
 | 
			
		||||
  vieter_tree_node *parent = node->parent;
 | 
			
		||||
  vieter_tree_node *grand_parent = parent->parent;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
#include "vieter_tree.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Inspect whether the tree is still a valid red-black-tree.
 | 
			
		||||
 *
 | 
			
		||||
 * @return 0 if correct, 1 if not.
 | 
			
		||||
 */
 | 
			
		||||
int vieter_tree_validate(vieter_tree *tree);
 | 
			
		||||
| 
						 | 
				
			
			@ -40,4 +40,6 @@ bool vieter_tree_node_get(vieter_tree_node *node, vieter_node_flag flag);
 | 
			
		|||
void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key,
 | 
			
		||||
                                vieter_tree_node *child);
 | 
			
		||||
 | 
			
		||||
int vieter_tree_node_validate(vieter_tree_node *node, uint64_t passed_black_nodes, uint64_t expected_black_nodes);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
#include "acutest.h"
 | 
			
		||||
#include "vieter_tree.h"
 | 
			
		||||
#include "vieter_tree_internal.h"
 | 
			
		||||
 | 
			
		||||
#define TEST_SIZE(tree, size) \
 | 
			
		||||
    TEST_CHECK(vieter_tree_size(tree) == size); \
 | 
			
		||||
| 
						 | 
				
			
			@ -18,6 +18,7 @@ void test_insert() {
 | 
			
		|||
    for (uint64_t i = 0; i < 250; i++) {
 | 
			
		||||
        TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok);
 | 
			
		||||
        TEST_SIZE(tree, i + 1);
 | 
			
		||||
        TEST_CHECK(vieter_tree_validate(tree) == 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void *out;
 | 
			
		||||
| 
						 | 
				
			
			@ -36,13 +37,15 @@ void test_remove() {
 | 
			
		|||
 | 
			
		||||
    for (uint64_t i = 0; i < 250; i++) {
 | 
			
		||||
        TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok);
 | 
			
		||||
        TEST_CHECK(vieter_tree_validate(tree) == 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void *out;
 | 
			
		||||
 | 
			
		||||
    for (uint64_t i = 0; i < 250; i++) {
 | 
			
		||||
    for (uint64_t i = 0; i < 25; i++) {
 | 
			
		||||
        TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok);
 | 
			
		||||
        TEST_CHECK(vieter_tree_remove(&out, tree, i) == vieter_tree_ok);
 | 
			
		||||
        TEST_CHECK(vieter_tree_validate(tree) == 0);
 | 
			
		||||
        TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_not_present);
 | 
			
		||||
        TEST_SIZE(tree, 250 - i - 1);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue