test: cover rbtTest
This commit is contained in:
1 parent
5efb4c4203
commit
32e09c8de3
1 file changed
+143
+143
@@ -154,3 +154,146 @@ KTEST(rbtSingleRemoveRelinksNeighbors)
|
||||
RbTree tree;
|
||||
rbtInit(&tree);
|
||||
|
||||
IntNode nodes[5];
|
||||
int32 values[] = { 10, 20, 30, 40, 50 };
|
||||
for (int i = 0; i < 5; i++) {
|
||||
nodes[i].key = values[i];
|
||||
rbtInsert(&tree, &nodes[i].node, compareIntNode);
|
||||
}
|
||||
|
||||
rbtRemove(&tree, &nodes[2].node); /* remove 30, the middle */
|
||||
KT_EQ(t, rbtCount(&tree), 4);
|
||||
KT_TRUE(t, checkInvariants(&tree));
|
||||
|
||||
int32 key30 = 30;
|
||||
KT_NULL(t, rbtFind(&tree, &key30, lookupIntKey));
|
||||
|
||||
int32 expected[] = { 10, 20, 40, 50 };
|
||||
usize i = 0;
|
||||
for (RbtNode* c = rbtFirst(&tree); c != nullptr; c = rbtNext(c), i++)
|
||||
KT_EQ(t, rbtEntry(c, IntNode, node)->key, expected[i]);
|
||||
KT_EQ(t, i, 4);
|
||||
}
|
||||
|
||||
#define rbtStressN 500
|
||||
|
||||
KTEST(rbtStressInsertMaintainsInvariants)
|
||||
{
|
||||
IntNode* pool = (IntNode*)kmalloc(sizeof(IntNode) * rbtStressN);
|
||||
int32* order = (int32*)kmalloc(sizeof(int32) * rbtStressN);
|
||||
KT_NOTNULL(t, pool);
|
||||
KT_NOTNULL(t, order);
|
||||
if (!pool || !order) {
|
||||
kfree(pool);
|
||||
kfree(order);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < rbtStressN; i++)
|
||||
order[i] = i;
|
||||
shuffle(order, rbtStressN, 0xC0FFEEu);
|
||||
|
||||
RbTree tree;
|
||||
rbtInit(&tree);
|
||||
for (int32 i = 0; i < rbtStressN; i++) {
|
||||
int32 key = order[i];
|
||||
pool[key].key = key;
|
||||
KT_TRUE(t, rbtInsert(&tree, &pool[key].node, compareIntNode));
|
||||
}
|
||||
KT_EQ(t, rbtCount(&tree), rbtStressN);
|
||||
KT_TRUE(t, checkInvariants(&tree));
|
||||
|
||||
int32 expect = 0;
|
||||
usize visited = 0;
|
||||
for (RbtNode* c = rbtFirst(&tree); c != nullptr; c = rbtNext(c)) {
|
||||
KT_EQ(t, rbtEntry(c, IntNode, node)->key, expect);
|
||||
expect++;
|
||||
visited++;
|
||||
}
|
||||
KT_EQ(t, visited, rbtStressN);
|
||||
|
||||
kfree(pool);
|
||||
kfree(order);
|
||||
}
|
||||
|
||||
KTEST(rbtStressRemoveMaintainsInvariants)
|
||||
{
|
||||
IntNode* pool = (IntNode*)kmalloc(sizeof(IntNode) * rbtStressN);
|
||||
int32* order = (int32*)kmalloc(sizeof(int32) * rbtStressN);
|
||||
int32* removeOrder = (int32*)kmalloc(sizeof(int32) * rbtStressN);
|
||||
KT_NOTNULL(t, pool);
|
||||
KT_NOTNULL(t, order);
|
||||
KT_NOTNULL(t, removeOrder);
|
||||
if (!pool || !order || !removeOrder) {
|
||||
kfree(pool);
|
||||
kfree(order);
|
||||
kfree(removeOrder);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < rbtStressN; i++) {
|
||||
order[i] = i;
|
||||
removeOrder[i] = i;
|
||||
}
|
||||
shuffle(order, rbtStressN, 0xDEADBEEFu);
|
||||
shuffle(removeOrder, rbtStressN, 0x1234567u);
|
||||
|
||||
RbTree tree;
|
||||
rbtInit(&tree);
|
||||
for (int32 i = 0; i < rbtStressN; i++) {
|
||||
int32 key = order[i];
|
||||
pool[key].key = key;
|
||||
rbtInsert(&tree, &pool[key].node, compareIntNode);
|
||||
}
|
||||
|
||||
/* remove every even key, in scrambled order */
|
||||
int32 removed = 0;
|
||||
for (int32 i = 0; i < rbtStressN; i++) {
|
||||
int32 key = removeOrder[i];
|
||||
if (key % 2 != 0)
|
||||
continue;
|
||||
RbtNode* found = rbtFind(&tree, &key, lookupIntKey);
|
||||
KT_NOTNULL(t, found);
|
||||
if (found) {
|
||||
rbtRemove(&tree, found);
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
KT_EQ(t, rbtCount(&tree), rbtStressN - removed);
|
||||
KT_TRUE(t, checkInvariants(&tree));
|
||||
|
||||
for (int32 key = 0; key < rbtStressN; key++) {
|
||||
RbtNode* found = rbtFind(&tree, &key, lookupIntKey);
|
||||
if (key % 2 == 0)
|
||||
KT_NULL(t, found);
|
||||
else
|
||||
KT_NOTNULL(t, found);
|
||||
}
|
||||
|
||||
int32 expect = 1;
|
||||
usize visited = 0;
|
||||
for (RbtNode* c = rbtFirst(&tree); c != nullptr; c = rbtNext(c)) {
|
||||
KT_EQ(t, rbtEntry(c, IntNode, node)->key, expect);
|
||||
expect += 2;
|
||||
visited++;
|
||||
}
|
||||
KT_EQ(t, visited, rbtStressN - removed);
|
||||
|
||||
/* drain the rest, in the same scrambled order, down to nothing */
|
||||
for (int32 i = 0; i < rbtStressN; i++) {
|
||||
int32 key = removeOrder[i];
|
||||
if (key % 2 == 0)
|
||||
continue;
|
||||
RbtNode* found = rbtFind(&tree, &key, lookupIntKey);
|
||||
if (found)
|
||||
rbtRemove(&tree, found);
|
||||
}
|
||||
KT_TRUE(t, rbtIsEmpty(&tree));
|
||||
KT_EQ(t, rbtCount(&tree), 0);
|
||||
KT_NULL(t, rbtFirst(&tree));
|
||||
KT_NULL(t, rbtLast(&tree));
|
||||
|
||||
kfree(pool);
|
||||
kfree(order);
|
||||
kfree(removeOrder);
|
||||
}
|
||||
Reference in new issue
Block a user