Skip to content

Commit

Permalink
Merge pull request #33 from 5cript/feat/more-erase-tests
Browse files Browse the repository at this point in the history
Feat/more erase tests
  • Loading branch information
5cript authored Jul 31, 2024
2 parents 639401d + 0478ae2 commit a661ab1
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 16 deletions.
8 changes: 4 additions & 4 deletions include/interval-tree/draw.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ namespace lib_interval_tree
{};

template <>
struct NumericalPointerEquivalent <sizeof(unsigned long)>
struct NumericalPointerEquivalent <sizeof(std::uint32_t)>
{
using type = unsigned long;
using type = uint32_t;
};

template <>
struct NumericalPointerEquivalent <sizeof(unsigned long long)>
struct NumericalPointerEquivalent <sizeof(std::uint64_t)>
{
using type = unsigned long long;
using type = uint64_t;
};

template <typename... List>
Expand Down
30 changes: 19 additions & 11 deletions include/interval-tree/interval_tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -886,19 +886,27 @@ namespace lib_interval_tree
throw std::out_of_range("cannot erase end iterator");

auto next = iter;
++next;

node_type* y;
if (!iter.node_->left_ || !iter.node_->right_)
y = iter.node_;
else
y = successor(iter.node_);
node_type* y = [&next, &iter, this]() {
if (!iter.node_->left_ || !iter.node_->right_)
{
++next;
return iter.node_;
}
else
{
const auto y = successor(iter.node_);
next = iterator{iter.node_, this};
return y;
}
}();

node_type* x;
if (y->left_)
x = y->left_;
else
x = y->right_;
node_type* x = [y](){
if (y->left_)
return y->left_;
else
return y->right_;
}();

if (x)
x->parent_ = y->parent_;
Expand Down
4 changes: 4 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ target_compile_options(tree-tests PUBLIC "$<$<CONFIG:DEBUG>:${DEBUG_OPTIONS}>")
set(RELEASE_OPTIONS -fexceptions -O3 -Wall -pedantic)
target_compile_options(tree-tests PUBLIC "$<$<CONFIG:RELEASE>:${RELEASE_OPTIONS}>")

if (INT_TREE_DRAW_EXAMPLES)
target_link_libraries(tree-tests PRIVATE cairo cairo-wrap)
endif()

# If msys2, copy dynamic libraries to executable directory, visual studio does this automatically.
# And there is no need on linux.
if (DEFINED ENV{MSYSTEM})
Expand Down
103 changes: 102 additions & 1 deletion tests/erase_tests.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#pragma once

#include "interval_io.hpp"
#include "test_utility.hpp"

#include <ctime>
#include <random>
#include <cmath>
Expand Down Expand Up @@ -48,7 +51,7 @@ class OracleInterval : public lib_interval_tree::interval<numerical_type, interv
other.oracle_ = nullptr;
return *this;
}
~OracleInterval()
~OracleInterval()
{
if (oracle_ != nullptr)
--oracle_->livingInstances;
Expand All @@ -73,6 +76,23 @@ class EraseTests
public:
using interval_type = OracleInterval<int>;

public:
auto makeTree()
{
lib_interval_tree::interval_tree_t <int> regularTree;
regularTree.insert({16, 21});
regularTree.insert({8, 9});
regularTree.insert({25, 30});
regularTree.insert({5, 8});
regularTree.insert({15, 23});
regularTree.insert({17, 19});
regularTree.insert({26, 26});
regularTree.insert({0, 3});
regularTree.insert({6, 10});
regularTree.insert({19, 20});
return regularTree;
}

protected:
Oracle oracle;
lib_interval_tree::interval_tree <OracleInterval<int>> tree;
Expand Down Expand Up @@ -162,3 +182,84 @@ TEST_F(EraseTests, RandomEraseTest)
testMaxProperty(tree);
testTreeHeightHealth(tree);
}



TEST_F(EraseTests, MassiveDeleteEntireTreeWithEraseReturnIterator)
{
constexpr int amount = 1000;

for (int i = 0; i != amount; ++i)
tree.insert(makeSafeOracleInterval(&oracle, distSmall(gen), distSmall(gen)));

for(auto iter = tree.begin(); !tree.empty();)
{
iter = tree.erase(iter);
}

EXPECT_EQ(oracle.livingInstances, 0);
testMaxProperty(tree);
testTreeHeightHealth(tree);
}

TEST_F(EraseTests, ReturnedIteratorPointsToNextInOrderNode)
{
auto regularTree = makeTree();
auto iter = regularTree.erase(regularTree.find({16, 21}));
EXPECT_EQ(*iter, (decltype(regularTree)::interval_type{17, 19})) << *iter;

regularTree = makeTree();
iter = regularTree.erase(regularTree.find({8, 9}));
EXPECT_EQ(*iter, (decltype(regularTree)::interval_type{15, 23})) << *iter;

regularTree = makeTree();
iter = regularTree.erase(regularTree.find({25, 30}));
EXPECT_EQ(*iter, (decltype(regularTree)::interval_type{26, 26})) << *iter;

regularTree = makeTree();
iter = regularTree.erase(regularTree.find({5, 8}));
EXPECT_EQ(*iter, (decltype(regularTree)::interval_type{6, 10})) << *iter;

regularTree = makeTree();
iter = regularTree.erase(regularTree.find({15, 23}));
EXPECT_EQ(*iter, (decltype(regularTree)::interval_type{16, 21})) << *iter;

regularTree = makeTree();
iter = regularTree.erase(regularTree.find({17, 19}));
EXPECT_EQ(*iter, (decltype(regularTree)::interval_type{19, 20})) << *iter;

regularTree = makeTree();
iter = regularTree.erase(regularTree.find({26, 26}));
EXPECT_EQ(iter, regularTree.end());

regularTree = makeTree();
iter = regularTree.erase(regularTree.find({0, 3}));
EXPECT_EQ(*iter, (decltype(regularTree)::interval_type{5, 8})) << *iter;

regularTree = makeTree();
iter = regularTree.erase(regularTree.find({6, 10}));
EXPECT_EQ(*iter, (decltype(regularTree)::interval_type{8, 9})) << *iter;

regularTree = makeTree();
iter = regularTree.erase(regularTree.find({19, 20}));
EXPECT_EQ(*iter, (decltype(regularTree)::interval_type{25, 30})) << *iter;
}

TEST_F(EraseTests, CanEraseEntireTreeUsingReturnedIterator)
{
auto tree = makeTree();
for (auto iter = tree.begin(); iter != tree.end();)
iter = tree.erase(iter);
EXPECT_EQ(tree.empty(), true);
}

TEST_F(EraseTests, FromNuiTest)
{
lib_interval_tree::interval_tree_t <int> tree;
tree.insert({0, 0});
tree.insert({4, 4});
tree.insert({13, 13});

auto iter = tree.erase(tree.find({4, 4}));
EXPECT_EQ(*iter, (decltype(tree)::interval_type{13, 13})) << *iter;
}
16 changes: 16 additions & 0 deletions tests/interval_io.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include <interval-tree/interval_tree.hpp>

#include <iostream>

namespace lib_interval_tree
{
template <typename... IntervalArgs>
std::ostream&
operator<<(std::ostream& os, lib_interval_tree::interval<IntervalArgs...> const& interval)
{
os << '[' << interval.low() << ", " << interval.high() << ']';
return os;
}
}

0 comments on commit a661ab1

Please sign in to comment.