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" | #include "vieter_tree_node.h" | ||||||
| 
 | 
 | ||||||
| struct vieter_tree { | struct vieter_tree { | ||||||
|  | @ -98,3 +98,23 @@ void vieter_tree_free(vieter_tree *tree) { | ||||||
| end: | end: | ||||||
|   free(tree); |   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" | #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 *vieter_tree_node_balance(vieter_tree_node *node) { | ||||||
|   vieter_tree_node *parent = node->parent; |   vieter_tree_node *parent = node->parent; | ||||||
|   vieter_tree_node *grand_parent = parent->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, | void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, | ||||||
|                                 vieter_tree_node *child); |                                 vieter_tree_node *child); | ||||||
| 
 | 
 | ||||||
|  | int vieter_tree_node_validate(vieter_tree_node *node, uint64_t passed_black_nodes, uint64_t expected_black_nodes); | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| #include "acutest.h" | #include "acutest.h" | ||||||
| #include "vieter_tree.h" | #include "vieter_tree_internal.h" | ||||||
| 
 | 
 | ||||||
| #define TEST_SIZE(tree, size) \ | #define TEST_SIZE(tree, size) \ | ||||||
|     TEST_CHECK(vieter_tree_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++) { |     for (uint64_t i = 0; i < 250; i++) { | ||||||
|         TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok); |         TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok); | ||||||
|         TEST_SIZE(tree, i + 1); |         TEST_SIZE(tree, i + 1); | ||||||
|  |         TEST_CHECK(vieter_tree_validate(tree) == 0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void *out; |     void *out; | ||||||
|  | @ -36,13 +37,15 @@ void test_remove() { | ||||||
| 
 | 
 | ||||||
|     for (uint64_t i = 0; i < 250; i++) { |     for (uint64_t i = 0; i < 250; i++) { | ||||||
|         TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok); |         TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok); | ||||||
|  |         TEST_CHECK(vieter_tree_validate(tree) == 0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void *out; |     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_search(&out, tree, i) == vieter_tree_ok); | ||||||
|         TEST_CHECK(vieter_tree_remove(&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_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_not_present); | ||||||
|         TEST_SIZE(tree, 250 - i - 1); |         TEST_SIZE(tree, 250 - i - 1); | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue