Files
mars-nwe/tests/nwnss/rbpTree/test_nwnss_rbpTree.c
2026-06-16 07:27:24 +02:00

178 lines
4.7 KiB
C

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rbpTree.h>
#define CHECK(expr) do { \
if (!(expr)) { \
fprintf(stderr, "CHECK failed: %s:%d: %s\n", __FILE__, __LINE__, #expr); \
return 1; \
} \
} while (0)
typedef struct TestNode_s {
int key;
RBP_Node_s link;
} TestNode_s;
typedef struct WalkState_s {
int expected;
int count;
} WalkState_s;
static SNINT node_compare(void *a, void *b)
{
const TestNode_s *x = a;
const TestNode_s *y = b;
return (x->key > y->key) - (x->key < y->key);
}
static SNINT key_compare(void *key, void *node)
{
const int *k = key;
const TestNode_s *n = node;
return (*k > n->key) - (*k < n->key);
}
static BOOL count_destroy(void *node)
{
TestNode_s *n = node;
n->key = -n->key;
return TRUE;
}
static BOOL in_order_check(void *node, NINT depth, ADDR user_data)
{
TestNode_s *n = node;
WalkState_s *state = (WalkState_s *)user_data;
(void)depth;
if (n->key != state->expected) {
fprintf(stderr, "in-order expected %d, got %d\n", state->expected, n->key);
return FALSE;
}
state->expected += 1;
state->count += 1;
return TRUE;
}
static int expect_node(TestNode_s *node, int key)
{
if (node == NULL || node->key != key) {
fprintf(stderr, "expected key %d, got %s%d\n", key,
node ? "" : "NULL/", node ? node->key : -1);
return 1;
}
return 0;
}
static int audit_tree(RBP_Tree_s *tree, RBP_Node_s *root, int expected_nodes)
{
RBP_Audit_s audit;
RBP_Audit(tree, root, &audit);
if (audit.nodes != expected_nodes) {
fprintf(stderr, "audit expected %d nodes, got %ld\n",
expected_nodes, (long)audit.nodes);
return 1;
}
if (expected_nodes == 0)
return 0;
if (audit.maxDepth >= MAX_DEPTH) {
fprintf(stderr, "tree depth unexpectedly high: %ld\n", (long)audit.maxDepth);
return 1;
}
return 0;
}
int main(void)
{
RBP_Tree_s tree;
RBP_Node_s *root = NULL;
TestNode_s nodes[64];
int order[] = {31, 7, 55, 3, 15, 47, 63, 0, 5, 11, 19, 39, 51, 59, 61,
1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60,
62, 9, 13, 17, 21, 23, 25, 27, 29, 33, 35, 37, 41, 43, 45,
49, 53, 57};
int i;
int key;
TestNode_s *node;
WalkState_s walk;
CHECK((int)(sizeof(order) / sizeof(order[0])) == 64);
RBP_Init(&tree, (SNINT (*)(void))node_compare,
(SNINT (*)(void))key_compare,
(BOOL (*)(void))count_destroy, NULL,
offsetof(TestNode_s, link));
for (i = 0; i < 64; i++) {
nodes[i].key = order[i];
RBP_Insert(&tree, &root, &nodes[i]);
CHECK(root != NULL);
CHECK(root->red == FALSE);
CHECK(audit_tree(&tree, root, i + 1) == 0);
}
for (i = 0; i < 64; i++) {
key = i;
CHECK(expect_node(RBP_Find(&tree, root, &key), i) == 0);
}
key = -1;
CHECK(expect_node(RBP_FindCeiling(&tree, root, &key), 0) == 0);
CHECK(RBP_FindFloor(&tree, root, &key) == NULL);
key = 64;
CHECK(RBP_FindCeiling(&tree, root, &key) == NULL);
CHECK(expect_node(RBP_FindFloor(&tree, root, &key), 63) == 0);
key = 37;
CHECK(expect_node(RBP_FindCeiling(&tree, root, &key), 37) == 0);
CHECK(expect_node(RBP_FindFloor(&tree, root, &key), 37) == 0);
key = 37;
node = RBP_Find(&tree, root, &key);
CHECK(expect_node(RBP_Succ(&tree, node), 38) == 0);
CHECK(expect_node(RBP_Pred(&tree, node), 36) == 0);
CHECK(expect_node(RBP_Min(&tree, root), 0) == 0);
CHECK(expect_node(RBP_Max(&tree, root), 63) == 0);
memset(&walk, 0, sizeof(walk));
walk.expected = 0;
RBP_InOrder(&tree, root, in_order_check, (ADDR)&walk);
CHECK(walk.count == 64);
CHECK(walk.expected == 64);
for (i = 0; i < 64; i += 2) {
key = i;
node = RBP_Find(&tree, root, &key);
CHECK(node != NULL);
RBP_Delete(&tree, &root, node);
CHECK(audit_tree(&tree, root, 64 - (i / 2) - 1) == 0);
}
for (i = 0; i < 64; i++) {
key = i;
node = RBP_Find(&tree, root, &key);
if ((i & 1) == 0)
CHECK(node == NULL);
else
CHECK(expect_node(node, i) == 0);
}
key = 4;
CHECK(expect_node(RBP_FindCeiling(&tree, root, &key), 5) == 0);
CHECK(expect_node(RBP_FindFloor(&tree, root, &key), 3) == 0);
RBP_DestroyTree(&tree, &root);
CHECK(root == NULL);
CHECK(audit_tree(&tree, root, 0) == 0);
for (i = 0; i < 64; i++) {
if (order[i] & 1)
CHECK(nodes[i].key < 0);
}
return 0;
}