test/util/TestIntrusiveTreeSet: add test with large randomized tree, erasing random elements

Test fails currently due to two bugs in the red-black tree
implementation.
This commit is contained in:
Max Kellermann 2024-04-10 09:35:33 +02:00 committed by Max Kellermann
parent e0a53d4747
commit 3cf0896998
1 changed files with 62 additions and 0 deletions

View File

@ -6,6 +6,8 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <cstdlib> // for std::rand()
#include <deque>
#include <string> #include <string>
namespace { namespace {
@ -192,3 +194,63 @@ TEST(IntrusiveTreeSet, RandomOrder)
} }
} }
} }
TEST(IntrusiveTreeSet, LargeRandom)
{
std::deque<std::unique_ptr<IntItem>> items;
IntrusiveTreeSet<IntItem,
IntrusiveTreeSetOperators<IntItem, IntItem::GetKey>> set;
std::srand(42);
for (unsigned i = 0; i < 1024; ++i) {
items.emplace_back(std::make_unique<IntItem>(std::rand()));
set.insert(*items.back());
#ifndef NDEBUG
set.Check();
#endif
}
std::sort(items.begin(), items.end(), [](const auto &a, const auto &b){
return a->value < b->value;
});
std::size_t idx = 0;
for (const auto &i : set) {
EXPECT_EQ(i.value, items[idx++]->value);
}
while (!set.empty()) {
EXPECT_FALSE(items.empty());
EXPECT_TRUE(items.front()->is_linked());
EXPECT_EQ(items.front()->value, set.front().value);
// erase the front element
set.pop_front();
EXPECT_FALSE(items.front()->is_linked());
items.pop_front();
#ifndef NDEBUG
set.Check();
#endif
// erase a random element
const auto r = std::next(items.begin(), std::rand() % items.size());
EXPECT_TRUE((*r)->is_linked());
set.erase(set.iterator_to(**r));
EXPECT_FALSE((*r)->is_linked());
items.erase(r);
#ifndef NDEBUG
set.Check();
#endif
idx = 0;
for (const auto &i : set) {
EXPECT_EQ(i.value, items[idx++]->value);
}
}
EXPECT_TRUE(items.empty());
}