test_tree.cpp

Back to Generic binary tree

test/pastel/sys/

// Description: Testing for Tree
// DocumentationOf: tree.h

#include "test/test_init.h"

#include "pastel/sys/tree.h"
#include "pastel/sys/predicate.h"

#include <boost/range/algorithm/equal.hpp>

#include <iostream>

namespace
{

    class Label
    {
    public:
        Label(integer label_)
        : label(label_)
        {
        }

        operator integer() const
        {
            return label;
        }

        integer label;
    };

    using Tre = Tree<Label>;
    using Iterator = Tre::Iterator;
    using ConstIterator = Tre::ConstIterator;
    using Range = Tre::Range;
    using ConstRange = Tre::ConstRange;

    template <integer N>
    bool same(const Tre& tree, integer (&correctSet)[N])
    {
        return boost::equal(range(correctSet), tree.crange(), EqualTo());
    }

    bool same(const Tre& tree, const Tre& that)
    {
        return boost::equal(tree.crange(), that.crange(), EqualTo());
    }

}

TEST_CASE("various (Tree)")
{
    Tre tree;
    {
        REQUIRE(tree.empty());
        REQUIRE(tree.size() == 0);
        REQUIRE(tree.sentinelCount() == 1);
    }
    Iterator aIter = tree.insertRoot(0);
    {
        REQUIRE(tree.size() == 1);
        REQUIRE(!tree.empty());
        REQUIRE(tree.sentinelCount() == 3);

        integer correctSet[] = {0};
        REQUIRE(same(tree, correctSet));
    }

    Iterator bIter = tree.insert(aIter, false, 1);
    {
        REQUIRE(tree.size() == 2);
        REQUIRE(tree.sentinelCount() == 4);

        integer correctSet[] = {1, 0};
        REQUIRE(same(tree, correctSet));
    }

    Iterator cIter = tree.insert(bIter, true, 2);
    unused(cIter);
    {
        REQUIRE(tree.size() == 3);
        REQUIRE(tree.sentinelCount() == 5);

        integer correctSet[] = {1, 2, 0};
        REQUIRE(same(tree, correctSet));
    }

    tree.rotate(aIter, true);
    {
        REQUIRE(tree.sentinelCount() == 5);

        integer correctSet[] = {1, 2, 0};
        REQUIRE(same(tree, correctSet));
    }

    Tre copyTree(tree);
    {
        REQUIRE(tree.sentinelCount() == 5);
        REQUIRE(copyTree.sentinelCount() == 5);
        REQUIRE(!copyTree.empty());
        REQUIRE(copyTree.size() == 3);
        REQUIRE(same(tree, copyTree));
    }

    tree.clear();
    {
        REQUIRE(copyTree.sentinelCount() == 5);
        REQUIRE(tree.sentinelCount() == 1);
        REQUIRE(tree.empty());
        REQUIRE(tree.size() == 0);
    }

    tree = copyTree;
    {
        REQUIRE(copyTree.sentinelCount() == 5);
        REQUIRE(tree.sentinelCount() == 5);
        REQUIRE(!tree.empty());
        REQUIRE(tree.size() == 3);
        REQUIRE(same(tree, copyTree));
    }

    copyTree = std::move(tree);
    {
        REQUIRE(copyTree.sentinelCount() == 2);
        REQUIRE(tree.sentinelCount() == 4);
        integer correctSet[] = {1, 2, 0};
        REQUIRE(tree.empty());
        REQUIRE(tree.size() == 0);
        REQUIRE(!copyTree.empty());
        REQUIRE(copyTree.size() == 3);
        REQUIRE(same(copyTree, correctSet));
    }

    {
        Tre anotherTree(std::move(copyTree));
        {
            REQUIRE(copyTree.sentinelCount() == 1);
            REQUIRE(tree.sentinelCount() == 4);
            REQUIRE(anotherTree.sentinelCount() == 2);
            integer correctSet[] = {1, 2, 0};
            REQUIRE(copyTree.empty());
            REQUIRE(copyTree.size() == 0);
            REQUIRE(!anotherTree.empty());
            REQUIRE(anotherTree.size() == 3);
            REQUIRE(same(anotherTree, correctSet));
        }
    }
    {
        REQUIRE(tree.sentinelCount() == 1);
    }
}

TEST_CASE("Insert (Tree)")
{
    Tre tree;
    Iterator aIter = tree.insertRoot(0);
    Iterator bIter = tree.insert(aIter, false, 1);
    Iterator cIter = tree.insert(bIter, true, 2);
    unused(cIter);
    {
        integer correctSet[] = {1, 2, 0};
        REQUIRE(same(tree, correctSet));
    }

    Iterator newIter = tree.insert(bIter, false, tree);
    {
        integer correctSet[] = {1, 2, 0, 1, 2, 0};
        REQUIRE(same(tree, correctSet));
    }

    Tre detached = tree.detach(newIter);
    {
        integer correctSet[] = {1, 2, 0};
        REQUIRE(same(tree, correctSet));
        REQUIRE(tree.size() == 3);
        REQUIRE(same(detached, correctSet));
        REQUIRE(detached.size() == 3);
    }
}

TEST_CASE("NoData (Tree)")
{
    Tree<void> tree;
    tree.insertRoot();
}

TEST_CASE("Data (Tree)")
{
    Tre tree;
    Iterator aIter = tree.insertRoot(0);
    {
        REQUIRE(*aIter == 0);
        REQUIRE(aIter->label == 0);
    }
}

namespace
{

        template <typename Iter>
        void testIterator()
        {
            Tre tree;
            Iter aIter = tree.insertRoot(0);
            Iter bIter = tree.insert(aIter, false, 1);
            Iter cIter = tree.insert(bIter, true, 2);

            // Finding the leftmost.
            {
                Iter iter = aIter.leftMost();
                REQUIRE(iter == bIter);
            }
            {
                Iter iter = bIter.leftMost();
                REQUIRE(iter == bIter);
            }
            {
                Iter iter = tree.end().leftMost();
                REQUIRE(iter == tree.end());
            }
            {
                Iter iter = cIter.leftMost();
                REQUIRE(iter == cIter);
            }

            // Finding the rightmost.
            {
                Iter iter = aIter.rightMost();
                REQUIRE(iter == aIter);
            }
            {
                Iter iter = bIter.rightMost();
                REQUIRE(iter == cIter);
            }
            {
                Iter iter = tree.end().rightMost();
                REQUIRE(iter == tree.end());
            }
            {
                Iter iter = cIter.rightMost();
                REQUIRE(iter == cIter);
            }

            // Finding the root.
            {
                Iter iter = cIter.root();
                REQUIRE(iter == tree.root());
            }
            {
                Iter iter = bIter.root();
                REQUIRE(iter == tree.root());
            }
            {
                Iter iter = aIter.root();
                REQUIRE(iter == tree.root());
            }
            {
                Iter iter = tree.end().root();
                ++iter;
                REQUIRE(iter == tree.end());
            }
            {
                Iter iter = tree.end().root();
                REQUIRE(iter == tree.end());
            }

            // Wrapping behaviour.
            {
                // The beginning wraps around to the one-past-end.
                Iter iter = tree.begin();
                --iter;
                REQUIRE(iter == tree.end());
            }
            {
                // The one-past one-past-end stays where it is.
                Iter iter = tree.end();
                ++iter;
                REQUIRE(iter == tree.end());
            }
        }

        void print(const Tre& that)
        {
            ConstRange range = that.crange();
            while(!range.empty())
            {
                std::cout << range.front() << ", ";
                range.pop_back();
            }

            std::cout << "end." << std::endl;
        }

}

TEST_CASE("Iterator (Tree)")
{
    testIterator<ConstIterator>();
    testIterator<Iterator>();
}