summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 6c17fc8)
raw | patch | inline | side by side (parent: 6c17fc8)
author | Sebastian Harl <sh@tokkee.org> | |
Wed, 9 Jul 2014 19:07:58 +0000 (21:07 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Wed, 9 Jul 2014 19:07:58 +0000 (21:07 +0200) |
The function walks the entire tree and checks each node for problems (e.g.
unbalanced nodes, wrong height, missing child/parent links).
Use the function in the unit tests (which is the primary use for the function
anyway ;-)).
unbalanced nodes, wrong height, missing child/parent links).
Use the function in the unit tests (which is the primary use for the function
anyway ;-)).
src/include/utils/avltree.h | patch | blob | history | |
src/utils/avltree.c | patch | blob | history | |
t/unit/utils/avltree_test.c | patch | blob | history |
index b3eec42f177e4752d1118cac5e321bf22c02e257..4e4d00c1b95f37742eab50cf7cd4226511ee8e60 100644 (file)
size_t
sdb_avltree_size(sdb_avltree_t *tree);
+_Bool
+sdb_avltree_valid(sdb_avltree_t *tree);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/src/utils/avltree.c b/src/utils/avltree.c
index d8151c8926cb9f443539225eda05514347d4384c..353a3849c2c307c975413d72a9dba64dfc0f7258 100644 (file)
--- a/src/utils/avltree.c
+++ b/src/utils/avltree.c
#include "sysdb.h"
#include "utils/avltree.h"
+#include "utils/error.h"
#include <assert.h>
size_t height;
};
+#define NODE_NAME(n) ((n) && (n)->obj ? (n)->obj->name : "<nil>")
#define NODE_HEIGHT(n) ((n) ? (n)->height : (size_t)0)
#define CALC_HEIGHT(n) (SDB_MAX(NODE_HEIGHT((n)->right), \
NODE_HEIGHT((n)->left)) + 1)
return tree ? tree->size : 0;
} /* sdb_avltree_size */
+_Bool
+sdb_avltree_valid(sdb_avltree_t *tree)
+{
+ node_t *n;
+
+ _Bool status = 1;
+ size_t size = 0;
+
+ if (! tree)
+ return 1;
+
+ for (n = node_smallest(tree); n; n = node_next(n)) {
+ int bf = BALANCE(n);
+
+ if ((bf < -1) || (1 < bf)) {
+ sdb_log(SDB_LOG_ERR, "avltree: Unbalanced node '%s' (bf=%i)",
+ NODE_NAME(n), bf);
+ status = 0;
+ }
+
+ if (NODE_HEIGHT(n) != n->height) {
+ sdb_log(SDB_LOG_ERR, "avltree: Unexpected height for node '%s': "
+ "%zu; expected: %zu", NODE_NAME(n), n->height,
+ NODE_HEIGHT(n));
+ status = 0;
+ }
+
+ if (n->parent && (n->parent->left != n) && (n->parent->right != n)) {
+ sdb_log(SDB_LOG_ERR, "avltree: Invalid child nodes for parent of "
+ "node '%s': {left: %s, right: %s}; expected: %s",
+ NODE_NAME(n), NODE_NAME(n->parent->left),
+ NODE_NAME(n->parent->right), NODE_NAME(n));
+ status = 0;
+ }
+ if ((! n->parent) && (n != tree->root)) {
+ sdb_log(SDB_LOG_ERR, "avltree: Non-root node '%s' does not "
+ "have a parent", NODE_NAME(n));
+ status = 0;
+ }
+
+ ++size;
+ }
+
+ if (size != tree->size) {
+ sdb_log(SDB_LOG_ERR, "avltree: Invalid size %zu; expected: %zu",
+ tree->size, size);
+ status = 0;
+ }
+ return status;
+} /* sdb_avltree_valid */
+
/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
index 9b48fdcb2ea44e8f60c53ee5c1474348e9d3d566..f1ea1fc09fd27baa7aac336cd3b3ba5047b43bbb 100644 (file)
fail_unless(check == (int)i + 1,
"sdb_avltree_size(<tree>) = %d; expected: %zu",
check, i + 1);
+
+ fail_unless(sdb_avltree_valid(tree),
+ "sdb_avltree_insert(<tree>, <%s>) left behind invalid tree",
+ test_data[i].name);
}
/* and again ... now reporting errors because of duplicates */