test_redblacktree.cpp

Back to Red-black tree

test/pastel/sys/

// Description: Testing for red-black tree
// DocumentationOf: redblacktree.h

#include "test/test_init.h"

#include <pastel/sys/redblacktree.h>
#include <pastel/sys/random/random_uniform.h>
#include <pastel/sys/random/random_integer.h>
#include <pastel/sys/downfilter.h>

#include <boost/range/adaptor/reversed.hpp> 

#include <algorithm>
#include <iostream>
#include <list>

namespace
{

    class Propagation
    {
    public:
        integer blackHeight;
        bool marked;
    };

    template <typename Settings_>
    class Map_Counting_Customization
        : public Empty_RedBlackTree_Customization<Settings_>
    {
    protected:
        using Fwd = RedBlackTree_Fwd<Settings_>;
        PASTEL_FWD(Iterator);
        PASTEL_FWD(Propagation_Class);

        Map_Counting_Customization() {}

        void updatePropagation(
            const Iterator& iter,
            Propagation_Class& propagation)
        {
            propagation.marked =
                iter.data().marked ||
                iter.left().propagation().marked ||
                iter.right().propagation().marked;
            propagation.blackHeight = 
                std::max(iter.left().propagation().blackHeight, iter.right().propagation().blackHeight) +
                iter.black();
        }

    private:
        Map_Counting_Customization(const Map_Counting_Customization& that) = delete;
        Map_Counting_Customization(Map_Counting_Customization&& that) = delete;
        Map_Counting_Customization& operator=(Map_Counting_Customization) = delete;
    };

    template <typename Settings_>
    class Set_Counting_Customization
        : public Empty_RedBlackTree_Customization<Settings_>
    {
    protected:
        using Fwd = RedBlackTree_Fwd<Settings_>;
        PASTEL_FWD(Iterator);
        PASTEL_FWD(Propagation_Class);

        Set_Counting_Customization() {}

        void updatePropagation(
            const Iterator& iter,
            Propagation_Class& propagation)
        {
            propagation.blackHeight =
                std::max(iter.left().propagation().blackHeight, iter.right().propagation().blackHeight) +
                iter.black();
        }

    private:
        Set_Counting_Customization(const Set_Counting_Customization& that) = delete;
        Set_Counting_Customization(Set_Counting_Customization&& that) = delete;
        Set_Counting_Customization& operator=(Set_Counting_Customization) = delete;
    };

    template <typename Data_, bool MultipleKeys>
    using Counting_Settings =
        RedBlackTree_Set_Settings<integer, Data_, LessThan, Propagation, void, MultipleKeys>;

    class Data
    {
    public:
        Data(integer value_ = 0, bool marked_ = false)
            : value(value_)
            , marked(marked_)
        {
        }

        operator integer() const
        {
            return value;
        }

        integer value;
        bool marked;
    };

    using Set_Settings = Counting_Settings<void, false>;
    using MultiSet_Settings = Counting_Settings<void, true>;
    using Map_Settings = Counting_Settings<Data, false>;
    using MultiMap_Settings = Counting_Settings<Data, true>;

    using Set = RedBlackTree<Set_Settings, Set_Counting_Customization>;
    using MultiSet = RedBlackTree<MultiSet_Settings, Set_Counting_Customization>;
    using Map = RedBlackTree<Map_Settings, Map_Counting_Customization>;
    using MultiMap = RedBlackTree<MultiMap_Settings, Map_Counting_Customization>;

    template <typename Tree>
    void testMapFilteredIterator()
    {
        using ConstIterator = typename Tree::ConstIterator;

        Tree map
        { 
            { 2, { 0, false } },
            { 4, { 0, false } },
            { 5, { 0, true } },
            { 6, { 0, false } },
            { 9, { 0, false } },
            { 10, { 0, true } },
            { 14, { 0, true } },
            { 16, { 0, false } },
            { 19, { 0, false } },
            { 20, { 0, true } }
        };

        auto onlyMarked = indicatorDownFilter(
            [](const ConstIterator& that) {return that.data().marked;},
            [](const ConstIterator& that) {return that.propagation().marked;}
        );

        {
            auto test = [&](const ConstIterator& i, integer correct)
            {
                return !i.isSentinel() &&
                    i.key() == correct;
            };

            ConstIterator i = map.cbegin();
            REQUIRE(test(i, 2));

            i = i.next(onlyMarked);
            REQUIRE(test(i, 5));

            i = i.next(onlyMarked);
            REQUIRE(test(i, 10));

            i = i.next(onlyMarked);
            REQUIRE(test(i, 14));

            i = i.next(onlyMarked);
            REQUIRE(test(i, 20));

            i = i.next(onlyMarked);
            REQUIRE(i == map.cend());

            i = i.prev(onlyMarked);
            REQUIRE(test(i, 20));

            i = i.prev(onlyMarked);
            REQUIRE(test(i, 14));

            i = i.prev(onlyMarked);
            REQUIRE(test(i, 10));

            i = i.prev(onlyMarked);
            REQUIRE(test(i, 5));

            i = i.prev(onlyMarked);
            REQUIRE(i == map.cend());

            i = map.begin();
            REQUIRE(test(i, 2));

            ++i;
            REQUIRE(test(i, 4));

            ++i;
            REQUIRE(test(i, 5));

            ++i;
            REQUIRE(test(i, 6));

            ++i;
            REQUIRE(test(i, 9));

            ++i;
            REQUIRE(test(i, 10));

            ++i;
            REQUIRE(test(i, 14));

            ++i;
            REQUIRE(test(i, 16));

            ++i;
            REQUIRE(test(i, 19));

            ++i;
            REQUIRE(test(i, 20));

            ++i;
            REQUIRE(i == map.cend());

            --i;
            REQUIRE(test(i, 20));

            --i;
            REQUIRE(test(i, 19));

            --i;
            REQUIRE(test(i, 16));

            --i;
            REQUIRE(test(i, 14));

            --i;
            REQUIRE(test(i, 10));

            --i;
            REQUIRE(test(i, 9));

            --i;
            REQUIRE(test(i, 6));

            --i;
            REQUIRE(test(i, 5));

            --i;
            REQUIRE(test(i, 4));

            --i;
            REQUIRE(test(i, 2));

            --i;
            REQUIRE(i == map.cend());
        }
    }

    template <typename Tree>
    void testMapFilteredSearch()
    {
        using ConstIterator = typename Tree::ConstIterator;

        Tree map
        { 
            { 2, { 0, false } },
            { 4, { 0, false } },
            { 5, { 0, true } },
            { 6, { 0, false } },
            { 9, { 0, false } },
            { 10, { 0, true } },
            { 14, { 0, true } },
            { 16, { 0, false } },
            { 19, { 0, false } },
            { 20, { 0, true } }
        };

        auto onlyMarked = indicatorDownFilter(
            [](const ConstIterator& that) {return that.data().marked; },
            [](const ConstIterator& that) {return that.propagation().marked; }
        );

        {
            auto test = [&](integer i)
            {
                ConstIterator iter = 
                    map.find(i, onlyMarked);

                return !iter.isSentinel() &&
                    iter.key() == i &&
                    map.exists(i, onlyMarked);
            };

            REQUIRE(!test(2));
            REQUIRE(!test(4));
            REQUIRE(!test(6));
            REQUIRE(!test(9));
            REQUIRE(!test(16));
            REQUIRE(!test(19));

            REQUIRE(test(5));
            REQUIRE(test(10));
            REQUIRE(test(14));
            REQUIRE(test(20));
        }
        {
            auto test = [&](integer i, integer correct)
            {
                ConstIterator iter = 
                    map.lowerBound(i, onlyMarked);

                return !iter.isSentinel() &&
                    iter.key() == correct;
            };

            REQUIRE(test(-1, 5));
            REQUIRE(test(0, 5));
            REQUIRE(test(1, 5));
            REQUIRE(test(2, 5));
            REQUIRE(test(3, 5));
            REQUIRE(test(4, 5));
            REQUIRE(test(5, 5));
            REQUIRE(test(6, 10));
            REQUIRE(test(7, 10));
            REQUIRE(test(8, 10));
            REQUIRE(test(9, 10));
            REQUIRE(test(10, 10));
            REQUIRE(test(11, 14));
            REQUIRE(test(12, 14));
            REQUIRE(test(13, 14));
            REQUIRE(test(14, 14));
            REQUIRE(test(15, 20));
            REQUIRE(test(16, 20));
            REQUIRE(test(17, 20));
            REQUIRE(test(18, 20));
            REQUIRE(test(19, 20));
            REQUIRE(test(20, 20));
        }

        {
            auto test = [&](integer i, integer correct)
            {
                ConstIterator iter = 
                    map.upperBound(i, onlyMarked);

                return !iter.isSentinel() &&
                    iter.key() == correct;
            };

            REQUIRE(test(-1, 5));
            REQUIRE(test(0, 5));
            REQUIRE(test(1, 5));
            REQUIRE(test(2, 5));
            REQUIRE(test(3, 5));
            REQUIRE(test(4, 5));
            REQUIRE(test(5, 10));
            REQUIRE(test(6, 10));
            REQUIRE(test(7, 10));
            REQUIRE(test(8, 10));
            REQUIRE(test(9, 10));
            REQUIRE(test(10, 14));
            REQUIRE(test(11, 14));
            REQUIRE(test(12, 14));
            REQUIRE(test(13, 14));
            REQUIRE(test(14, 20));
            REQUIRE(test(15, 20));
            REQUIRE(test(16, 20));
            REQUIRE(test(17, 20));
            REQUIRE(test(18, 20));
            REQUIRE(test(19, 20));
            REQUIRE(map.upperBound(20) == map.cend());
        }
    }

    template <typename Tree>
    void testMultiLowerBound()
    {
        {
            Tree tree;

            auto test = [&](integer that, integer index)
            {
                integer actualIndex =
                    std::distance(tree.begin(), tree.lowerBound(that));

                return actualIndex == index;
            };

            {
                tree = { 2, 4, 4, 5, 5, 5, 5, 9, 15, 20 };
                REQUIRE(testInvariants(tree));

                REQUIRE(test(0, 0));
                REQUIRE(test(1, 0));
                REQUIRE(test(2, 0));
                REQUIRE(test(3, 1));
                REQUIRE(test(4, 1));
                REQUIRE(test(5, 3));
                REQUIRE(test(6, 7));
                REQUIRE(test(7, 7));
                REQUIRE(test(8, 7));
                REQUIRE(test(9, 7));
                REQUIRE(test(10, 8));
                REQUIRE(test(11, 8));
                REQUIRE(test(12, 8));
                REQUIRE(test(13, 8));
                REQUIRE(test(14, 8));
                REQUIRE(test(15, 8));
                REQUIRE(test(16, 9));
                REQUIRE(test(17, 9));
                REQUIRE(test(18, 9));
                REQUIRE(test(19, 9));
                REQUIRE(test(20, 9));
                REQUIRE(test(21, 10));
                REQUIRE(test(22, 10));
            }

            {
                tree = { 3, 4, 5, 5, 5, 5, 5, 5, 5, 6, 7 };
                REQUIRE(testInvariants(tree));

                REQUIRE(test(0, 0));
                REQUIRE(test(1, 0));
                REQUIRE(test(2, 0));
                REQUIRE(test(3, 0));
                REQUIRE(test(4, 1));
                REQUIRE(test(5, 2));
                REQUIRE(test(6, 9));
                REQUIRE(test(7, 10));
                REQUIRE(test(8, 11));
                REQUIRE(test(9, 11));
            }
        }
    }

    template <typename Tree>
    void testConstruction()
    {
        {
            Tree tree;
            REQUIRE(testInvariants(tree));
            REQUIRE(!tree.hasSeparateSentinels());
            REQUIRE(!tree.sharesBottom());
            REQUIRE(tree.sharesBottom(tree));
            REQUIRE(tree.size() == 0);
            REQUIRE(tree.empty());
        }

        {
            Tree tree({ 1, 2, 3, 4, 5, 6, 7 });
            integer correctSet[] = { 1, 2, 3, 4, 5, 6, 7 };

            REQUIRE(tree.extremum(false) == tree.cbegin());
            REQUIRE(tree.extremum(false).key() == 1);
            REQUIRE(tree.extremum(true) == tree.clast());
            REQUIRE(tree.extremum(true).key() == 7);

            REQUIRE(testInvariants(tree));
            REQUIRE(!tree.hasSeparateSentinels());
            REQUIRE(!tree.sharesBottom());
            REQUIRE(tree.sharesBottom(tree));
            REQUIRE(tree.size() == 7);
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
        }
        {
            Tree tree{ 1, 2, 3, 4, 5, 6, 7 };
            integer correctSet[] = { 1, 2, 3, 4, 5, 6, 7 };

            Tree copy(tree);
            REQUIRE(testInvariants(copy));
            REQUIRE(copy.hasSeparateSentinels());
            REQUIRE(copy.sharesBottom());
            REQUIRE(copy.sharesBottom(copy));
            REQUIRE(copy.sharesBottom(tree));
            REQUIRE(copy.size() == 7);
            REQUIRE(boost::equal(copy.crange().dereferenceKey(), correctSet));

            REQUIRE(testInvariants(tree));
            REQUIRE(!tree.hasSeparateSentinels());
            REQUIRE(tree.sharesBottom());
            REQUIRE(tree.sharesBottom(tree));
            REQUIRE(tree.sharesBottom(copy));
            REQUIRE(tree.size() == 7);
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
        }
        {
            Tree tree{ 1, 2, 3, 4, 5, 6, 7 };
            integer correctSet[] = { 1, 2, 3, 4, 5, 6, 7 };

            Tree copy{ 11, 12, 13, 14, 15, 16, 17 };
            copy = tree;
            REQUIRE(testInvariants(copy));
            REQUIRE(!copy.hasSeparateSentinels());
            REQUIRE(!copy.sharesBottom());
            REQUIRE(copy.sharesBottom(copy));
            REQUIRE(!copy.sharesBottom(tree));
            REQUIRE(copy.size() == 7);
            REQUIRE(boost::equal(copy.crange().dereferenceKey(), correctSet));

            REQUIRE(testInvariants(tree));
            REQUIRE(!tree.hasSeparateSentinels());
            REQUIRE(!tree.sharesBottom());
            REQUIRE(tree.sharesBottom(tree));
            REQUIRE(!tree.sharesBottom(copy));
            REQUIRE(tree.size() == 7);
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
        }
        {
            Tree tree{ 1, 2, 3, 4, 5, 6, 7 };
            integer correctSet[] = { 1, 2, 3, 4, 5, 6, 7 };

            Tree moved(std::move(tree));
            REQUIRE(testInvariants(moved));
            REQUIRE(moved.hasSeparateSentinels());
            REQUIRE(moved.sharesBottom());
            REQUIRE(moved.sharesBottom(moved));
            REQUIRE(moved.sharesBottom(tree));
            REQUIRE(moved.size() == 7);
            REQUIRE(boost::equal(moved.crange().dereferenceKey(), correctSet));

            REQUIRE(testInvariants(tree));
            REQUIRE(!tree.hasSeparateSentinels());
            REQUIRE(tree.sharesBottom());
            REQUIRE(tree.sharesBottom(tree));
            REQUIRE(tree.sharesBottom(moved));
            REQUIRE(tree.size() == 0);
            REQUIRE(tree.empty());
        }
        {
            Tree tree{ 1, 2, 3, 4, 5, 6, 7 };
            integer correctSet[] = { 1, 2, 3, 4, 5, 6, 7 };
            Tree moved{ 11, 12, 13, 14, 15, 16, 17 };
            moved = std::move(tree);
            REQUIRE(testInvariants(moved));
            REQUIRE(moved.hasSeparateSentinels());
            REQUIRE(moved.sharesBottom());
            REQUIRE(moved.sharesBottom(moved));
            REQUIRE(moved.sharesBottom(tree));
            REQUIRE(moved.size() == 7);
            REQUIRE(boost::equal(moved.crange().dereferenceKey(), correctSet));

            REQUIRE(testInvariants(tree));
            REQUIRE(!tree.hasSeparateSentinels());
            REQUIRE(tree.sharesBottom());
            REQUIRE(tree.sharesBottom(tree));
            REQUIRE(tree.sharesBottom(moved));
            REQUIRE(tree.size() == 0);
            REQUIRE(tree.empty());
        }
        {
            Tree tree;
            Tree copy(tree);
            REQUIRE(testInvariants(tree));
            REQUIRE(testInvariants(copy));
        }
    }

    template <typename Tree>
    void testIterator()
    {
        using ConstIterator = typename Tree::ConstIterator;
        using Iterator = typename Tree::Iterator;

        Tree aTree{ 1, 2, 3, 4 };
        Tree bTree{ 5, 6, 7 };

        ConstIterator iter = aTree.cend();

        // The next element from the end-node is 
        // the first element of the tree.
        ++iter;
        REQUIRE(iter.key() == 1);

        // The previous element from the first element
        // is the end-node.
        --iter;
        REQUIRE(iter == aTree.cend());

        // The previous element from the end-node is
        // the last element.
        --iter;
        REQUIRE(iter.key() == 4);

        // The next element from the last node is the
        // end-node.
        ++iter;
        REQUIRE(iter == aTree.cend());

        // A const-iterator can be explicitly converted to an iterator,
        // provided one has a mutable reference to the tree.
        Iterator bIter = aTree.cast(iter);

        // An iterator can be converted to a const-iterator.
        iter = bIter;
        REQUIRE(iter == bIter);

        ConstIterator cIter = bIter;
        unused(cIter);
    }

    template <typename Tree>
    void testRandom()
    {
        Tree tree;

        std::list<integer> dataSet;

        integer treeSizeSet[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100};
        integer treeSizes = sizeof(treeSizeSet) / sizeof(integer);

        for (integer k = 0;k < treeSizes;++k)
        {
            integer treeSize = treeSizeSet[k];
            tree.clear();
            dataSet.clear();

            for (integer i = 0;i < 4 * treeSize;++i)
            {
                uinteger n = randomUinteger() % 100;
                dataSet.push_back(n);

                tree.insert(n);
                REQUIRE(testInvariants(tree));

                if (tree.size() > treeSize)
                {
                    tree.erase(dataSet.front());
                    REQUIRE(testInvariants(tree));
                    dataSet.pop_front();
                }
            }

            {
                Tree copy(tree);
                REQUIRE(testInvariants(copy));
                REQUIRE(tree.size() == copy.size());
                REQUIRE(boost::equal(tree.crange().dereferenceKey(), copy.crange().dereferenceKey()));
            }
        }
    }

    template <typename Tree>
    void testInsert()
    {
        using ConstIterator = typename Tree::ConstIterator;

        Tree tree;
        {
            REQUIRE(tree.empty());
            REQUIRE(tree.size() == 0);
            REQUIRE(testInvariants(tree));
        }

        tree.insert(1);
        {
            REQUIRE(!tree.empty());
            REQUIRE(tree.size() == 1);
            REQUIRE(testInvariants(tree));

            integer correctSet[] = { 1 };
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
        }

        tree.insert(5);
        {
            REQUIRE(!tree.empty());
            REQUIRE(tree.size() == 2);
            REQUIRE(testInvariants(tree));

            integer correctSet[] = { 1, 5 };
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
        }

        tree.insert(3);
        {
            REQUIRE(!tree.empty());
            REQUIRE(tree.size() == 3);
            REQUIRE(testInvariants(tree));

            integer correctSet[] = { 1, 3, 5 };
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
        }

        tree.insert(4);
        {
            REQUIRE(!tree.empty());
            REQUIRE(tree.size() == 4);
            REQUIRE(testInvariants(tree));

            integer correctSet[] = { 1, 3, 4, 5 };
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
        }

        tree.insert(8);
        {
            REQUIRE(!tree.empty());
            REQUIRE(tree.size() == 5);
            REQUIRE(testInvariants(tree));

            integer correctSet[] = { 1, 3, 4, 5, 8 };
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
        }

        tree.insert(7);
        {
            REQUIRE(!tree.empty());
            REQUIRE(tree.size() == 6);
            REQUIRE(testInvariants(tree));

            integer correctSet[] = { 1, 3, 4, 5, 7, 8 };
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
        }

        tree.insert(6);
        {
            REQUIRE(!tree.empty());
            REQUIRE(tree.size() == 7);
            REQUIRE(testInvariants(tree));

            integer correctSet[] = { 1, 3, 4, 5, 6, 7, 8 };
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
        }

        tree.insert(9);
        {
            REQUIRE(!tree.empty());
            REQUIRE(tree.size() == 8);
            REQUIRE(testInvariants(tree));

            integer correctSet[] = { 1, 3, 4, 5, 6, 7, 8, 9 };
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
        }

        tree.insert(2);
        {
            REQUIRE(!tree.empty());
            REQUIRE(tree.size() == 9);
            REQUIRE(testInvariants(tree));

            integer correctSet[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
        }

        integer correctSet[] =
        {
            1, 2, 3, 4, 5, 6, 7, 8, 9
        };

        {
            REQUIRE(boost::distance(tree) == 9);
            REQUIRE(boost::distance(tree.crange().dereferenceKey()) == 9);
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
        }

        {
            ConstIterator copyIter = tree.cend();
            ++copyIter;
            REQUIRE(copyIter == tree.cbegin());
        }

        {
            REQUIRE(boost::equal(
                tree.crange().dereferenceKey() | boost::adaptors::reversed,
                correctSet | boost::adaptors::reversed));
        }

        {
            ConstIterator copyIter = tree.cbegin();
            --copyIter;
            REQUIRE(copyIter == tree.cend());
        }
    }

    template <typename Tree>
    void testErase()
    {
        Tree tree{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        {
            integer correctSet[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            REQUIRE(tree.size() == 9);
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
            REQUIRE(testInvariants(tree));
        }

        tree.erase(0);
        {
            integer correctSet[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            REQUIRE(tree.size() == 9);
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
            REQUIRE(testInvariants(tree));
        }

        tree.erase(4);
        {
            integer correctSet[] = { 1, 2, 3, 5, 6, 7, 8, 9 };
            REQUIRE(tree.size() == 8);
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
            REQUIRE(testInvariants(tree));
        }

        tree.erase(7);
        {
            integer correctSet[] = { 1, 2, 3, 5, 6, 8, 9 };
            REQUIRE(tree.size() == 7);
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
            REQUIRE(testInvariants(tree));
        }

        tree.erase(1);
        {
            integer correctSet[] = { 2, 3, 5, 6, 8, 9 };
            REQUIRE(tree.size() == 6);
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
            REQUIRE(testInvariants(tree));
        }

        tree.erase(9);
        {
            integer correctSet[] = { 2, 3, 5, 6, 8};
            REQUIRE(tree.size() == 5);
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
            REQUIRE(testInvariants(tree));
        }

        tree.erase(5);
        {
            integer correctSet[] = { 2, 3, 6, 8 };
            REQUIRE(tree.size() == 4);
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
            REQUIRE(testInvariants(tree));
        }

        tree.erase(3);
        {
            integer correctSet[] = { 2, 6, 8 };
            REQUIRE(tree.size() == 3);
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
            REQUIRE(testInvariants(tree));
        }

        tree.erase(2);
        {
            integer correctSet[] = { 6, 8 };
            REQUIRE(tree.size() == 2);
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
            REQUIRE(testInvariants(tree));
        }

        tree.erase(6);
        {
            integer correctSet[] = { 8 };
            REQUIRE(tree.size() == 1);
            REQUIRE(boost::equal(tree.crange().dereferenceKey(), correctSet));
            REQUIRE(testInvariants(tree));
        }

        tree.erase(8);
        {
            REQUIRE(tree.size() == 0);
            REQUIRE(tree.empty());
            REQUIRE(testInvariants(tree));
        }
    }

    template <typename Tree>
    void testSplice()
    {
        Tree a{ 0, 1, 4, 5, 9, 15, 20 };
        REQUIRE(testInvariants(a));

        Tree b{ 1, 2, 6, 7, 8, 9, 10 };
        REQUIRE(testInvariants(b));

        {
            a.splice(b, b.find(6));

            REQUIRE(testInvariants(a));
            REQUIRE(a.size() == 8);
            integer aCorrectSet[] = { 0, 1, 4, 5, 6, 9, 15, 20 };
            REQUIRE(boost::equal(a.crange().dereferenceKey(), aCorrectSet));

            REQUIRE(testInvariants(b));
            REQUIRE(b.size() == 6);
            integer bCorrectSet[] = { 1, 2, 7, 8, 9, 10 };
            REQUIRE(boost::equal(b.crange().dereferenceKey(), bCorrectSet));
        }

        {
            a.splice(b, b.find(10));

            REQUIRE(testInvariants(a));
            REQUIRE(a.size() == 9);
            integer aCorrectSet[] = { 0, 1, 4, 5, 6, 9, 10, 15, 20 };
            REQUIRE(boost::equal(a.crange().dereferenceKey(), aCorrectSet));

            REQUIRE(testInvariants(b));
            REQUIRE(b.size() == 5);
            integer bCorrectSet[] = { 1, 2, 7, 8, 9};
            REQUIRE(boost::equal(b.crange().dereferenceKey(), bCorrectSet));
        }
    }

    template <typename Tree>

    void print(const Tree& tree, integer height, bool key = true)
    {
        using ConstIterator = typename Tree::ConstIterator;

        std::list<std::pair<ConstIterator, integer>> nodeSet;
        nodeSet.push_back(std::make_pair(tree.croot(), (integer)0));
        integer prevLevel = 0;
        while (!nodeSet.empty() && nodeSet.front().second < height)
        {
            auto entry = nodeSet.front();
            nodeSet.pop_front();

            if (entry.second != prevLevel)
            {
                std::cout << std::endl;
                prevLevel = entry.second;
            }

            if (!entry.first.isSentinel())
            {
                if (key)
                {
                    std::cout << entry.first.key();
                }
                else
                {
                    std::cout << entry.first.data();
                }
                if (entry.first.red())
                {
                    std::cout << "R";
                }
                else
                {
                    std::cout << "B";
                }
                std::cout << " ";
            }
            else
            {
                std::cout << "- ";
            }

            nodeSet.push_back(
                std::make_pair(entry.first.left(), entry.second + 1));

            ConstIterator right = entry.first.isSentinel() ?
                tree.cend() : entry.first.right();
            nodeSet.push_back(
                std::make_pair(right, entry.second + 1));
        }
        std::cout << std::endl;

        if (key)
        {
            for (auto&& key : tree.crange().dereferenceKey())
            {
                std::cout << key << ", ";
            }
        }
        else
        {
            for (auto&& data : tree.crange().dereferenceData())
            {
                std::cout << data << ", ";
            }
        }
        std::cout << std::endl;
    }

    template <typename Tree>
    void testFind()
    {
        Tree tree{ 2, 4, 4, 5, 5, 5, 5, 9, 15, 20 };
        REQUIRE(testInvariants(tree));

        auto test = [&](integer that)
        {
            return tree.exists(that) &&
                tree.find(that) != tree.cend() &&
                tree.find(that).key() == that;
        };

        auto notFound = [&](integer that)
        {
            return (tree.find(that) == tree.cend()) &&
                !tree.exists(that);
        };

        REQUIRE(notFound(0));
        REQUIRE(notFound(1));
        REQUIRE(notFound(3));
        REQUIRE(notFound(6));
        REQUIRE(notFound(7));
        REQUIRE(notFound(8));
        REQUIRE(notFound(10));
        REQUIRE(notFound(11));
        REQUIRE(notFound(12));
        REQUIRE(notFound(13));
        REQUIRE(notFound(14));
        REQUIRE(notFound(16));
        REQUIRE(notFound(17));
        REQUIRE(notFound(18));
        REQUIRE(notFound(19));
        REQUIRE(notFound(21));

        REQUIRE(test(2));
        REQUIRE(test(4));
        REQUIRE(test(5));
        REQUIRE(test(9));
        REQUIRE(test(15));
        REQUIRE(test(20));
    }

    template <typename Tree>
    void testLowerBound()
    {
        Tree tree;
    }

    template <typename Tree>
    void testUpperBound()
    {
        Tree tree{ 2, 4, 4, 5, 5, 5, 5, 9, 15, 20 };
        REQUIRE(testInvariants(tree));

        auto test = [&](integer that, integer bound)
        {
            return tree.upperBound(that) != tree.cend() &&
                tree.upperBound(that).key() == bound;
        };

        auto notFound = [&](integer that)
        {
            return tree.upperBound(that) == tree.cend();
        };

        REQUIRE(test(0, 2));
        REQUIRE(test(1, 2));
        REQUIRE(test(2, 4));
        REQUIRE(test(3, 4));
        REQUIRE(test(4, 5));
        REQUIRE(test(5, 9));
        REQUIRE(test(6, 9));
        REQUIRE(test(7, 9));
        REQUIRE(test(8, 9));
        REQUIRE(test(9, 15));
        REQUIRE(test(10, 15));
        REQUIRE(test(11, 15));
        REQUIRE(test(12, 15));
        REQUIRE(test(13, 15));
        REQUIRE(test(14, 15));
        REQUIRE(test(15, 20));
        REQUIRE(test(16, 20));
        REQUIRE(test(17, 20));
        REQUIRE(test(18, 20));
        REQUIRE(test(19, 20));
        REQUIRE(notFound(20));
        REQUIRE(notFound(21));
    }

    template <typename Tree>
    void testJoin()
    {
        {
            Tree aTree = { 1, 2, 3, 4, 5 };
            REQUIRE(testInvariants(aTree));

            Tree bTree;
            bTree.useBottomFrom(aTree);
            REQUIRE(testInvariants(bTree));
            REQUIRE(bTree.sharesBottom(aTree));

            aTree.join(bTree);
            REQUIRE(testInvariants(aTree));
            REQUIRE(testInvariants(bTree));
            REQUIRE(bTree.empty());

            integer correctSet[] =
                { 1, 2, 3, 4, 5 };
            REQUIRE(boost::equal(aTree.crange().dereferenceKey(), correctSet));

            bTree.join(aTree);
            REQUIRE(testInvariants(aTree));
            REQUIRE(testInvariants(bTree));
            REQUIRE(aTree.empty());
            REQUIRE(boost::equal(bTree.crange().dereferenceKey(), correctSet));
        }

        {
            Tree aTree = { 1, 2, 3, 4, 5 };
            REQUIRE(testInvariants(aTree));

            Tree bTree;
            bTree.useBottomFrom(aTree);
            bTree = { 6, 7, 8 };
            REQUIRE(testInvariants(bTree));

            bTree.join(aTree);
            REQUIRE(testInvariants(aTree));
            REQUIRE(testInvariants(bTree));
            REQUIRE(aTree.empty());

            integer correctSet[] =
                { 1, 2, 3, 4, 5, 6, 7, 8 };
            REQUIRE(boost::equal(bTree.crange().dereferenceKey(), correctSet));
        }

        {
            Tree aTree = { 1, 2, 3, 4, 5 };
            REQUIRE(testInvariants(aTree));

            Tree bTree;
            bTree.useBottomFrom(aTree);
            bTree = { 6, 7, 8 };
            REQUIRE(testInvariants(bTree));

            aTree.join(bTree);
            REQUIRE(testInvariants(aTree));
            REQUIRE(testInvariants(bTree));
            REQUIRE(bTree.empty());

            integer correctSet[] = 
                {1, 2, 3, 4, 5, 6, 7, 8};
            REQUIRE(boost::equal(aTree.crange().dereferenceKey(), correctSet));
        }
    }

    template <typename Tree>
    void testQuantile()
    {
        Tree tree {0, 1, 2, 3, 4};

        using ConstIterator = typename Tree::ConstIterator;

        auto test = [&](real alpha, integer correct)
        {
            ConstIterator q = quantile(tree, alpha);
            return q != tree.cend() && 
                q.key() == correct;
        };

        REQUIRE(test(-0.10, 0));
        REQUIRE(test(0.00, 0));
        REQUIRE(test(0.10, 0));
        REQUIRE(test(0.19, 0));
        REQUIRE(test(0.20, 1));
        REQUIRE(test(0.29, 1));
        REQUIRE(test(0.30, 1));
        REQUIRE(test(0.39, 1));
        REQUIRE(test(0.40, 2));
        REQUIRE(test(0.49, 2));
        REQUIRE(test(0.50, 2));
        REQUIRE(test(0.59, 2));
        REQUIRE(test(0.60, 3));
        REQUIRE(test(0.69, 3));
        REQUIRE(test(0.70, 3));
        REQUIRE(test(0.79, 3));
        REQUIRE(test(0.80, 4));
        REQUIRE(test(0.89, 4));
        REQUIRE(test(0.90, 4));
        REQUIRE(test(0.99, 4));
        REQUIRE(test(1.00, 4));
        REQUIRE(test(1.09, 4));
        REQUIRE(test(1.10, 4));
        REQUIRE(test(1.19, 4));
    }

    template <typename Tree>
    void testMultiCount()
    {
        Tree tree = { 3, 4, 5, 5, 5, 5, 5, 5, 5, 6, 7 };

        auto test = [&](integer key, integer count)
        {
            return tree.count(key) == count;
        };

        REQUIRE(test(0, 0));
        REQUIRE(test(1, 0));
        REQUIRE(test(2, 0));
        REQUIRE(test(3, 1));
        REQUIRE(test(4, 1));
        REQUIRE(test(5, 7));
        REQUIRE(test(6, 1));
        REQUIRE(test(7, 1));
        REQUIRE(test(8, 0));
        REQUIRE(test(9, 0));
    }

    template <typename Tree>
    void testManyThings()
    {
        testConstruction<Tree>();
        testIterator<Tree>();
        testInsert<Tree>();
        testErase<Tree>();
        testRandom<Tree>();
        testSplice<Tree>();
        testFind<Tree>();
        testLowerBound<Tree>();
        testUpperBound<Tree>();
        testJoin<Tree>();
        testQuantile<Tree>();
    }

}

TEST_CASE("VoidSet (RedBlackTree)")
{
    using Set = RedBlackTree_Set<void>;
    Set tree;
    REQUIRE(testInvariants(tree));
    tree.insert(nullptr);
}

TEST_CASE("Set (RedBlackTree)")
{
    {
        Set tree;
        auto test = [&](integer that)
        {
            auto iterAndNew = tree.insert(that);
            REQUIRE(testInvariants(tree));
            REQUIRE(iterAndNew.second);
            REQUIRE(*iterAndNew.first == that);
            REQUIRE(tree.find(that) == iterAndNew.first);
            REQUIRE(tree.lowerBound(that) == iterAndNew.first);
            REQUIRE(tree.exists(that));
        };

        test(1);
        REQUIRE(tree.size() == 1);

        test(5);
        REQUIRE(tree.size() == 2);

        test(3);
        REQUIRE(tree.size() == 3);

        auto iterAndNew = tree.insert(1);
        REQUIRE(!iterAndNew.second);
        REQUIRE(*iterAndNew.first == 1);
        REQUIRE(tree.size() == 3);
    }
    {
        Set tree({ 4, 2, 1, 1, 1, 3 });
        integer correctSet[] = { 1, 2, 3, 4 };
        REQUIRE(tree.size() == 4);
        REQUIRE(boost::equal(tree, correctSet));
    }
    {
        Set tree;
        tree = { 4, 2, 1, 1, 1, 3 };

        integer correctSet[] = { 1, 2, 3, 4 };
        REQUIRE(tree.size() == 4);
        REQUIRE(boost::equal(tree, correctSet));
    }
}

TEST_CASE("MultiSet (RedBlackTree)")
{
    using Tree = MultiSet;

    {
        Tree tree;

        auto test = [&](integer that)
        {
            auto iter = tree.insert(that);
            REQUIRE(testInvariants(tree));
            REQUIRE(*iter == that);
            REQUIRE(tree.find(that) == iter);
            REQUIRE(tree.lowerBound(that) == iter);
            REQUIRE(tree.exists(that));
        };

        test(1);
        REQUIRE(tree.size() == 1);

        test(5);
        REQUIRE(tree.size() == 2);

        test(3);
        REQUIRE(tree.size() == 3);
    }
    {
        Tree tree;

        auto test = [&](integer that)
        {
            auto iter = tree.insert(that);
            REQUIRE(testInvariants(tree));
            REQUIRE(*iter == that);
            REQUIRE(iter == std::prev(tree.cend()));
        };

        test(1);
        REQUIRE(tree.size() == 1);

        test(1);
        REQUIRE(tree.size() == 2);

        test(1);
        REQUIRE(tree.size() == 3);

        test(5);
        REQUIRE(tree.size() == 4);

        test(5);
        REQUIRE(tree.size() == 5);

        test(5);
        REQUIRE(tree.size() == 6);
    }
    {
        Tree aTree = { 1, 1, 2, 3, 4, 5, 5, 5 };
        REQUIRE(testInvariants(aTree));
        REQUIRE(aTree.size() == 8);

        Tree bTree;
        bTree.useBottomFrom(aTree);
        bTree = { 5, 5, 6, 7, 7, 8 };
        REQUIRE(testInvariants(bTree));
        REQUIRE(bTree.size() == 6);

        aTree.join(bTree);
        REQUIRE(testInvariants(aTree));
        REQUIRE(testInvariants(bTree));
        REQUIRE(aTree.size() == 14);
        REQUIRE(bTree.empty());

        integer correctSet[] =
            { 1, 1, 2, 3, 4, 5, 5, 5, 5, 5, 6, 7, 7, 8 };
        REQUIRE(boost::equal(aTree.crange().dereferenceKey(), correctSet));
    }
}

TEST_CASE("Map (RedBlackTree)")
{
    using Tree = Map;

    {
        Tree tree{ { 1, 1 }, { 2, 4 }, { 3, 9 }, { 4, 16 }, { 5, 25 }, { 6, 36 }, { 7, 49 } };
        REQUIRE(testInvariants(tree));
        REQUIRE(tree.size() == 7);

        integer keySet[] = { 1, 2, 3, 4, 5, 6, 7 };
        REQUIRE(boost::equal(tree.crange().dereferenceKey(), keySet));

        integer dataSet[] = { 1, 4, 9, 16, 25, 36, 49 };
        REQUIRE(boost::equal(tree.crange().dereferenceData(), dataSet));

        REQUIRE(*tree.begin().dereferenceKey() == 1);
        REQUIRE(*tree.begin().dereferenceData() == 1);
        REQUIRE(*std::next(tree.begin().dereferenceKey()) == 2);
        REQUIRE(*std::next(tree.begin().dereferenceData()) == 4);
    }
    {
        Map tree;
        auto a = tree.insert(5).first;

        *a = 4;
        REQUIRE(*a == 4);

        auto b = tree.insert(1, *a).first;
        REQUIRE(*b == 4);

    }
}

TEST_CASE("MultiMap (RedBlackTree)")
{
    using Tree = MultiMap;

    {
        Tree tree { { 1, 1 }, { 2, 4 }, { 3, 9 }, { 4, 16 }, { 5, 25 }, { 6, 36 }, { 7, 49 } };
        REQUIRE(testInvariants(tree));
        REQUIRE(tree.size() == 7);

        integer keySet[] = { 1, 2, 3, 4, 5, 6, 7 };
        REQUIRE(boost::equal(tree.crange().dereferenceKey(), keySet));

        integer dataSet[] = { 1, 4, 9, 16, 25, 36, 49 };
        REQUIRE(boost::equal(tree.crange().dereferenceData(), dataSet));
    }
}

TEST_CASE("MultiSplit (RedBlackTree)")
{
    using Tree = MultiMap;
    using Iterator = Tree::Iterator;
    {
        Tree tree;
        std::vector<integer> dataSet;
        integer n = 5000;
        for (integer i = 0;i < n;++i)
        {
            integer data = randomInteger(65536);
            dataSet.push_back(data);

            tree.insert(0, data);
            //REQUIRE(testInvariants(tree));
        }

        std::vector<integer> correctSet = dataSet;
        REQUIRE(boost::equal(tree.range().dereferenceData(), correctSet));

        std::vector<integer> indexSet;
        for (integer i = 0; i < 25; ++i)
        {
            indexSet.push_back(i);
        }
        for (integer i = 3000; i < 3025; ++i)
        {
            indexSet.push_back(i);
        }
        for (integer i = 4975; i < 5000; ++i)
        {
            indexSet.push_back(i);
        }
        /*
       for (integer i = 0; i < 5000; ++i)
       {
           indexSet.push_back(i);
       }
       */

        RANGES_FOR(integer i, indexSet)
        {
            Tree aTree = tree;
            REQUIRE(testInvariants(aTree));

            Tree bTree;

            {
                Iterator aEndBefore = aTree.end();
                Iterator aBottomBefore = aTree.bottom();
                Iterator bEndBefore = bTree.end();

                bTree = aTree.split(std::next(aTree.cbegin(), i));

                Iterator bEndAfter = bTree.end();
                Iterator aBottomAfter = aTree.bottom();
                Iterator aEndAfter = aTree.end();

                REQUIRE(aEndBefore == aEndAfter);
                REQUIRE(aBottomBefore == aBottomAfter);
                REQUIRE(bEndBefore == bEndAfter);
            }

            REQUIRE(testInvariants(aTree));
            REQUIRE(aTree.size() == i);
            REQUIRE(testInvariants(bTree));
            REQUIRE(bTree.size() == n - i);

            {
                Iterator aEndBefore = aTree.end();
                Iterator aBottomBefore = aTree.bottom();
                Iterator bEndBefore = bTree.end();
                Iterator bBottomBefore = bTree.bottom();

                aTree.join(bTree);

                Iterator bBottomAfter = bTree.bottom();
                Iterator bEndAfter = bTree.end();
                Iterator aBottomAfter = aTree.bottom();
                Iterator aEndAfter = aTree.end();

                REQUIRE(aEndBefore == aEndAfter);
                REQUIRE(aBottomBefore == aBottomAfter);
                REQUIRE(bEndBefore == bEndAfter);
                REQUIRE(bBottomBefore == bBottomAfter);
            }

            REQUIRE(testInvariants(aTree));
            REQUIRE(aTree.size() == n);
            REQUIRE(boost::equal(aTree.range().dereferenceData(), correctSet));
            REQUIRE(testInvariants(bTree));
            REQUIRE(bTree.size() == 0);
        }
    }
}

TEST_CASE("MultiJoin (RedBlackTree)")
{
    using Tree = MultiMap;
    using Iterator = Tree::Iterator;
    {
        integer n = 20;
        for (integer i = 0; i < n; ++i)
        {
            for (integer j = 0; j < n; ++j)
            {
                std::vector<integer> correctSet;

                Tree aTree;
                for (integer k = 0; k < i; ++k)
                {
                    integer data = randomInteger(65536);
                    correctSet.push_back(data);

                    aTree.insert(0, data);
                    REQUIRE(testInvariants(aTree));
                }

                Tree bTree;
                bTree.useBottomFrom(aTree);

                for (integer k = 0; k < j; ++k)
                {
                    integer data = randomInteger(65536);
                    correctSet.push_back(data);

                    bTree.insert(0, data);
                    REQUIRE(testInvariants(bTree));
                }

                {
                    Iterator aEndBefore = aTree.end();
                    Iterator aBottomBefore = aTree.bottom();
                    Iterator bEndBefore = bTree.end();
                    Iterator bBottomBefore = bTree.bottom();

                    aTree.join(bTree);

                    Iterator bBottomAfter = bTree.bottom();
                    Iterator bEndAfter = bTree.end();
                    Iterator aBottomAfter = aTree.bottom();
                    Iterator aEndAfter = aTree.end();

                    REQUIRE(aEndBefore == aEndAfter);
                    REQUIRE(aBottomBefore == aBottomAfter);
                    REQUIRE(bEndBefore == bEndAfter);
                    REQUIRE(bBottomBefore == bBottomAfter);
                }

                REQUIRE(testInvariants(aTree));
                REQUIRE(testInvariants(bTree));
                REQUIRE(boost::equal(aTree.crange().dereferenceData(), correctSet));
            }
        }
    }
}

TEST_CASE("RedBlackTree (RedBlackTree)")
{
    testMapFilteredIterator<Map>();
    testMapFilteredIterator<MultiMap>();

    testMapFilteredSearch<Map>();
    testMapFilteredSearch<MultiMap>();

    testMultiLowerBound<MultiSet>();
    testMultiLowerBound<MultiMap>();
    testMultiCount<MultiSet>();
    testMultiCount<MultiMap>();

    testManyThings<Set>();
    testManyThings<Map>();
    testManyThings<MultiSet>();
    testManyThings<MultiMap>();
}