    // Copyright (C) 2003  Davis E. King (davis@dlib.net)
    // License: Boost Software License   See LICENSE.txt for the full license.
    #ifndef DLIB_BINARY_SEARCH_TREE_KERNEl_TEST_H_
    #define DLIB_BINARY_SEARCH_TREE_KERNEl_TEST_H_

    #include <sstream>
    #include <string>
    #include <cstdlib>
    #include <ctime>

    #include <dlib/memory_manager_global.h>
    #include <dlib/memory_manager_stateless.h>
    #include <dlib/binary_search_tree.h>
    #include "tester.h"

    namespace
    {

        using namespace test;
        using namespace std;
        using namespace dlib;

        logger dlog("test.binary_search_tree");

        template <
            typename bst
            >
        void binary_search_tree_kernel_test (
        )
        /*!
            requires
                - bst is an implementation of
                  binary_search_tree/binary_search_tree_kernel_abstract.h is instantiated
                  to map int to int
            ensures
                - runs tests on bst for compliance with the specs
        !*/
        {

            bst test, test2;

            srand(static_cast<unsigned int>(time(0)));

            DLIB_TEST(test.count(3) == 0);

            enumerable<map_pair<int,int> >& e = test;
            DLIB_TEST(e.at_start() == true);

            DLIB_TEST(test.count(3) == 0);

            for (int i = 0; i < 4; ++i)
            {
                DLIB_TEST(test.size() == 0);
                DLIB_TEST(test.count(3) == 0);
                DLIB_TEST(test.height() == 0);
                DLIB_TEST(test[5] == 0);
                DLIB_TEST(test[0] == 0);
                DLIB_TEST(test.at_start());
                DLIB_TEST(test.current_element_valid() == false);
                DLIB_TEST(test.count(3) == 0);

                DLIB_TEST(test.move_next() == false);
                DLIB_TEST(test.move_next() == false);
                DLIB_TEST(test.move_next() == false);
                DLIB_TEST(test.move_next() == false);
                DLIB_TEST(test.move_next() == false);
                DLIB_TEST(test.count(3) == 0);

                DLIB_TEST(test.at_start() == false);
                DLIB_TEST(test.current_element_valid() == false);

                test.clear();
                test.position_enumerator(5);
                DLIB_TEST(test.current_element_valid() == false);
                DLIB_TEST(test.at_start() == false);
                test.position_enumerator(5);
                DLIB_TEST(test.current_element_valid() == false);
                DLIB_TEST(test.at_start() == false);
                test.position_enumerator(9);
                DLIB_TEST(test.current_element_valid() == false);
                DLIB_TEST(test.at_start() == false);
                test.clear();
                test.position_enumerator(5);
                DLIB_TEST(test.current_element_valid() == false);
                DLIB_TEST(test.at_start() == false);
                test.position_enumerator(5);
                DLIB_TEST(test.current_element_valid() == false);
                DLIB_TEST(test.at_start() == false);
                test.position_enumerator(9);
                DLIB_TEST(test.current_element_valid() == false);
                DLIB_TEST(test.at_start() == false);
                test.clear();
                DLIB_TEST(test.at_start() == true);
                DLIB_TEST(test.current_element_valid() == false);

                DLIB_TEST(test.count(3) == 0);

                DLIB_TEST(test.size() == 0);
                DLIB_TEST(test.height() == 0);
                DLIB_TEST(test[5] == 0);
                DLIB_TEST(test[0] == 0);
                DLIB_TEST(const_cast<const bst&>(test)[5] == 0);
                DLIB_TEST(const_cast<const bst&>(test)[0] == 0);
                DLIB_TEST(test.at_start());
                DLIB_TEST(test.current_element_valid() == false);

                DLIB_TEST(test.move_next() == false);
                DLIB_TEST(test.move_next() == false);
                DLIB_TEST(test.move_next() == false);
                DLIB_TEST(test.move_next() == false);
                DLIB_TEST(test.move_next() == false);

                DLIB_TEST(test.at_start() == false);
                DLIB_TEST(test.current_element_valid() == false);

                DLIB_TEST(test.count(3) == 0);
                test.reset();
                DLIB_TEST(test.count(3) == 0);

                DLIB_TEST(test.at_start());
                DLIB_TEST(test.current_element_valid() == false);

                int a = 0, b = 0;

                for (int i = 0; i < 10000; ++i)
                {
                    a = ::rand()%1000;
                    int temp = a;
                    unsigned long count = test.count(a);
                    test.add(a,b);
                    DLIB_TEST(test.count(temp) == count+1);
                }

                {
                    unsigned long count = test.count(3);

                    a = 3; test.add(a,b); ++count;
                    DLIB_TEST(test.count(3) == count);
                    a = 3; test.add(a,b); ++count;
                    DLIB_TEST(test.count(3) == count);
                    a = 3; test.add(a,b); ++count;
                    DLIB_TEST(test.count(3) == count);
                    a = 3; test.add(a,b); ++count;
                    DLIB_TEST(test.count(3) == count);
                }

                test.clear();

                for (int i = 0; i < 10000; ++i)
                {
                    a = ::rand()&0x7FFF;
                    b = 0;
                    int temp = a;
                    unsigned long count = test.count(a);
                    test.add(a,b);
                    DLIB_TEST(test.count(temp) == count+1);
                }

                // serialize the state of test, then clear test, then
                // load the state back into test.
                ostringstream sout;
                serialize(test,sout);
                istringstream sin(sout.str());
                test.clear();
                deserialize(test,sin);

                DLIB_TEST(test.size() == 10000);
                DLIB_TEST(test.at_start() == true);
                DLIB_TEST(test.current_element_valid() == false);

                DLIB_TEST_MSG(test.height() > 13 && test.height() <= 26,"this is somewhat of an implementation dependent "
                             << "but really it should be in this range or the implementation is just crap");

                a = 0;
                unsigned long count = 0;
                while (test.move_next())
                {
                    DLIB_TEST_MSG(a <= test.element().key(),"the numers are out of order but they should be in order");
                    a = test.element().key();
                    ++count;

                    DLIB_TEST(test.at_start() == false);
                    DLIB_TEST(test.current_element_valid() == true);
                }

                DLIB_TEST(test.move_next() == false);
                DLIB_TEST(test.move_next() == false);
                DLIB_TEST(test.move_next() == false);

                DLIB_TEST(count == 10000);

                DLIB_TEST_MSG(test.height() > 13 && test.height() <= 26,"this is somewhat of an implementation dependent "
                             << "but really it should be in this range or the implementation is just crap");

                DLIB_TEST(test.at_start() == false);
                DLIB_TEST(test.current_element_valid() == false);
                DLIB_TEST(test.size() == 10000);

                swap(test,test2);

                test2.reset();
                count = 0;
                a = 0;
                while (test2.move_next())
                {
                    DLIB_TEST_MSG(a <= test2.element().key(),"the numers are out of order but they should be in order");
                    a = test2.element().key();
                    ++count;

                    DLIB_TEST(test2.at_start() == false);
                    DLIB_TEST(test2.current_element_valid() == true);

                    if (count == 5000)
                    {
                        break;
                    }
                }

                DLIB_TEST(test2.move_next() == true);
                DLIB_TEST(test2.move_next() == true);
                DLIB_TEST(test2.move_next() == true);

                test2.reset();

                count = 0;
                a = 0;
                while (test2.move_next())
                {
                    DLIB_TEST_MSG(a <= test2.element().key(),"the numers are out of order but they should be in order");
                    a = test2.element().key();
                    ++count;

                    DLIB_TEST(test2.at_start() == false);
                    DLIB_TEST(test2.current_element_valid() == true);
                }

                DLIB_TEST(count == 10000);
                DLIB_TEST(test2.move_next() == false);
                DLIB_TEST(test2.move_next() == false);
                DLIB_TEST(test2.move_next() == false);

                int last = 0;
                asc_pair_remover<int,int,typename bst::compare_type>& asdf = test2;
                DLIB_TEST(asdf.size() > 0);
                while (asdf.size() > 0)
                {
                    asdf.remove_any(a,b);
                    DLIB_TEST(last <= a);
                    last = a;
                    --count;
                    DLIB_TEST(asdf.size() == count);
                }

                DLIB_TEST(test2.size() == 0);
                DLIB_TEST(test2.height() ==0);
                DLIB_TEST(test2.at_start() == true);
                DLIB_TEST(test2.current_element_valid() == false);
                DLIB_TEST(test2.move_next() == false);
                DLIB_TEST(test2.move_next() == false);
                DLIB_TEST(test2.move_next() == false);

                for (int i = 0; i < 10000; ++i)
                {
                    a = i;
                    b = i;
                    test2.add(a,b);
                    DLIB_TEST(test2.size() == (unsigned int)(i +1));
                    DLIB_TEST(test2.count(i) == 1);
                }

                a = 0;
                test2.position_enumerator(a);
                DLIB_TEST(test2.at_start() == false);
                DLIB_TEST(test2.element().key() == a);
                DLIB_TEST(test2.element().value() == a);
                a = 0;
                test2.position_enumerator(a);
                DLIB_TEST(test2.element().key() == a);
                DLIB_TEST(test2.element().value() == a);
                a = 8;
                test2.position_enumerator(a);
                DLIB_TEST(test2.at_start() == false);
                DLIB_TEST(test2.element().key() == a);
                DLIB_TEST(test2.element().value() == a);
                a = 1;
                test2.position_enumerator(a);
                DLIB_TEST(test2.element().key() == a);
                DLIB_TEST(test2.element().value() == a);
                a = -29;
                test2.position_enumerator(a);
                DLIB_TEST(test2.element().key() == 0);
                DLIB_TEST(test2.element().value() == 0);
                a = 10000;
                test2.position_enumerator(a);
                DLIB_TEST(test2.at_start() == false);
                DLIB_TEST(test2.current_element_valid() == false);
                a = -29;
                test2.position_enumerator(a);
                DLIB_TEST(test2.element().key() == 0);
                DLIB_TEST(test2.element().value() == 0);
                a = 8;
                test2.position_enumerator(a);
                DLIB_TEST(test2.at_start() == false);
                DLIB_TEST(test2.element().key() == a);
                DLIB_TEST(test2.element().value() == a);
                test2.reset();

                DLIB_TEST_MSG(test2.height() > 13 && test2.height() <= 26,"this is somewhat of an implementation dependent "
                             << "but really it should be in this range or the implementation is just crap");

                DLIB_TEST(test2.at_start() == true);
                DLIB_TEST(test2.current_element_valid() == false);
                DLIB_TEST(test2.size() == 10000);

                for (int i = 0; i < 10000; ++i)
                {
                    DLIB_TEST(test2.move_next() == true);
                    DLIB_TEST(test2.element().key() == i);
                }

                DLIB_TEST_MSG(test2.height() > 13 && test2.height() <= 26,"this is somewhat of an implementation dependent "
                             << "but really it should be in this range or the implementation is just crap");

                DLIB_TEST(test2.at_start() == false);
                DLIB_TEST(test2.current_element_valid() == true);
                DLIB_TEST(test2.size() == 10000);

                DLIB_TEST(test2.move_next() == false);
                DLIB_TEST(test2.current_element_valid() == false);

                a = 3;
                test2.add(a,b);
                DLIB_TEST(test2.count(3) == 2);

                for (int i = 0; i < 10000; ++i)
                {
                    test2.remove(i,a,b);
                    DLIB_TEST(i == a);
                }
                test2.remove(3,a,b);

                DLIB_TEST(test2.size() == 0);
                DLIB_TEST(test2.height() == 0);
                DLIB_TEST(test2.at_start() == true);
                DLIB_TEST(test2.current_element_valid() == false);
                DLIB_TEST(test2.move_next() == false);
                DLIB_TEST(test2.at_start() == false);
                DLIB_TEST(test2.current_element_valid() == false);

                test2.clear();

                int m = 0;
                for (int i = 0; i < 10000; ++i)
                {
                    a = ::rand()&0x7FFF;
                    m = max(a,m);
                    test2.add(a,b);
                }

                DLIB_TEST(test2.at_start() == true);
                DLIB_TEST(test2.move_next() == true);
                DLIB_TEST(test2.at_start() == false);
                DLIB_TEST(test2.current_element_valid() == true);
                DLIB_TEST(test2.move_next() == true);
                DLIB_TEST(test2.current_element_valid() == true);
                DLIB_TEST(test2.move_next() == true);
                DLIB_TEST(test2.current_element_valid() == true);
                DLIB_TEST(test2.move_next() == true);
                DLIB_TEST(test2.current_element_valid() == true);
                DLIB_TEST(test2.at_start() == false);

                for (int i = 0; i < 10000; ++i)
                {
                    a = ::rand()&0xFFFF;
                    test2.position_enumerator(a);
                    if (test2[a])
                    {
                        DLIB_TEST(test2.element().key() == a);
                    }
                    else if (a <= m)
                    {
                        DLIB_TEST(test2.element().key() > a);
                    }
                }

                test2.clear();

                DLIB_TEST(test2.current_element_valid() == false);
                DLIB_TEST(test2.at_start() == true);
                DLIB_TEST(test2.move_next() == false);
                DLIB_TEST(test2.at_start() == false);
                DLIB_TEST(test2.current_element_valid() == false);
                DLIB_TEST(test2.move_next() == false);
                DLIB_TEST(test2.current_element_valid() == false);
                DLIB_TEST(test2.move_next() == false);
                DLIB_TEST(test2.current_element_valid() == false);
                DLIB_TEST(test2.at_start() == false);

                DLIB_TEST(test2.size() == 0);
                DLIB_TEST(test2.height() == 0);

                for (int i = 0; i < 20000; ++i)
                {
                    a = ::rand()&0x7FFF;
                    b = a;
                    test2.add(a,b);
                }

                DLIB_TEST(test2.size() == 20000);

                // remove a bunch of elements randomly
                int c;
                for (int i = 0; i < 50000; ++i)
                {
                    a = ::rand()&0x7FFF;
                    if (test2[a] != 0)
                    {
                        test2.remove(a,b,c);
                        DLIB_TEST(a == b);
                    }
                }

                // now add a bunch more
                for (int i = 0; i < 10000; ++i)
                {
                    a = ::rand()&0x7FFF;
                    b = a;
                    test2.add(a,b);
                }

                // now iterate over it all and then remove all elements
                {
                    int* array = new int[test2.size()];
                    int* tmp = array;
                    DLIB_TEST(test2.at_start() == true);
                    while (test2.move_next())
                    {
                        *tmp = test2.element().key();
                        ++tmp;
                    }

                    DLIB_TEST(test2.at_start() == false);
                    DLIB_TEST(test2.current_element_valid() == false);
                    DLIB_TEST(test2.move_next() == false);

                    tmp = array;
                    for (int i = 0; i < 10000; ++i)
                    {
                        DLIB_TEST(*test2[*tmp] == *tmp);
                        DLIB_TEST(*test2[*tmp] == *tmp);
                        DLIB_TEST(*test2[*tmp] == *tmp);
                        DLIB_TEST(*const_cast<const bst&>(test2)[*tmp] == *tmp);
                        ++tmp;
                    }

                    tmp = array;
                    while (test2.size() > 0)
                    {
                        unsigned long count = test2.count(*tmp);
                        test2.destroy(*tmp);
                        DLIB_TEST(test2.count(*tmp)+1 == count);
                        ++tmp;
                    }

                    DLIB_TEST(test2.at_start() == true);
                    DLIB_TEST(test2.current_element_valid() == false);
                    DLIB_TEST(test2.move_next() == false);
                    DLIB_TEST(test2.at_start() == false);
                    test.swap(test2);
                    test.reset();

                    delete [] array;
                }

                DLIB_TEST(test.size() == 0);
                DLIB_TEST(test.height() == 0);

                for (unsigned long i = 1; i < 100; ++i)
                {
                    a = 1234;
                    test.add(a,b);
                    DLIB_TEST(test.count(1234) == i);
                }

                test.clear();

                for (int m = 0; m < 3; ++m)
                {

                    test2.clear();

                    DLIB_TEST(test2.current_element_valid() == false);
                    DLIB_TEST(test2.at_start() == true);
                    DLIB_TEST(test2.move_next() == false);
                    DLIB_TEST(test2.at_start() == false);
                    DLIB_TEST(test2.current_element_valid() == false);
                    DLIB_TEST(test2.move_next() == false);
                    DLIB_TEST(test2.current_element_valid() == false);
                    DLIB_TEST(test2.move_next() == false);
                    DLIB_TEST(test2.current_element_valid() == false);
                    DLIB_TEST(test2.at_start() == false);

                    DLIB_TEST(test2.size() == 0);
                    DLIB_TEST(test2.height() == 0);

                    int counter = 0;
                    while (counter < 10000)
                    {
                        a = ::rand()&0x7FFF;
                        b = ::rand()&0x7FFF;
                        if (test2[a] == 0)
                        {
                            test2.add(a,b);
                            ++counter;
                        }

                    }

                    DLIB_TEST(test2.size() == 10000);

                    // remove a bunch of elements randomly
                    for (int i = 0; i < 20000; ++i)
                    {
                        a = ::rand()&0x7FFF;
                        if (test2[a] != 0)
                        {
                            test2.remove(a,b,c);
                            DLIB_TEST(a == b);
                        }
                    }

                    // now add a bunch more
                    for (int i = 0; i < 20000; ++i)
                    {
                        a = ::rand()&0x7FFF;
                        b = ::rand()&0x7FFF;
                        if (test2[a] == 0)
                            test2.add(a,b);
                    }

                    // now iterate over it all and then remove all elements
                    {
                        int* array = new int[test2.size()];
                        int* array_val = new int[test2.size()];
                        int* tmp = array;
                        int* tmp_val = array_val;
                        DLIB_TEST(test2.at_start() == true);
                        int count = 0;
                        while (test2.move_next())
                        {
                            *tmp = test2.element().key();
                            ++tmp;
                            *tmp_val = test2.element().value();
                            ++tmp_val;

                            DLIB_TEST(*test2[*(tmp-1)] == *(tmp_val-1));
                            ++count;
                        }

                        DLIB_TEST(count == (int)test2.size());
                        DLIB_TEST(test2.at_start() == false);
                        DLIB_TEST(test2.current_element_valid() == false);
                        DLIB_TEST(test2.move_next() == false);

                        tmp = array;
                        tmp_val = array_val;
                        for (unsigned long i = 0; i < test2.size(); ++i)
                        {
                            DLIB_TEST_MSG(*test2[*tmp] == *tmp_val,i);
                            DLIB_TEST(*test2[*tmp] == *tmp_val);
                            DLIB_TEST(*test2[*tmp] == *tmp_val);
                            DLIB_TEST(*const_cast<const bst&>(test2)[*tmp] == *tmp_val);
                            ++tmp;
                            ++tmp_val;
                        }

                        //  out << "\nsize:   " << test2.size() << endl;
                        //  out << "height: " << test2.height() << endl;

                        tmp = array;
                        while (test2.size() > 0)
                        {
                            unsigned long count = test2.count(*tmp);
                            test2.destroy(*tmp);
                            DLIB_TEST(test2.count(*tmp)+1 == count);
                            ++tmp;
                        }

                        DLIB_TEST(test2.at_start() == true);
                        DLIB_TEST(test2.current_element_valid() == false);
                        DLIB_TEST(test2.move_next() == false);
                        DLIB_TEST(test2.at_start() == false);
                        test.swap(test2);
                        test.reset();

                        delete [] array;
                        delete [] array_val;
                    }

                    DLIB_TEST(test.size() == 0);
                    DLIB_TEST(test.height() == 0);

                    for (unsigned long i = 1; i < 100; ++i)
                    {
                        a = 1234;
                        test.add(a,b);
                        DLIB_TEST(test.count(1234) == i);
                    }

                    test.clear();

                }

                a = 1;
                b = 2;

                test.add(a,b);

                test.position_enumerator(0);
                a = 0;
                b = 0;
                DLIB_TEST(test.height() == 1);
                test.remove_current_element(a,b);
                DLIB_TEST(a == 1);
                DLIB_TEST(b == 2);
                DLIB_TEST(test.at_start() == false);
                DLIB_TEST(test.current_element_valid() == false);
                DLIB_TEST(test.height() == 0);
                DLIB_TEST(test.size() == 0);

                a = 1;
                b = 2;
                test.add(a,b);
                a = 1;
                b = 2;
                test.add(a,b);

                test.position_enumerator(0);
                a = 0;
                b = 0;
                DLIB_TEST(test.height() == 2);
                test.remove_current_element(a,b);
                DLIB_TEST(a == 1);
                DLIB_TEST(b == 2);
                DLIB_TEST(test.at_start() == false);
                DLIB_TEST(test.current_element_valid() == true);
                DLIB_TEST(test.height() == 1);
                DLIB_TEST(test.size() == 1);

                test.remove_current_element(a,b);
                DLIB_TEST(a == 1);
                DLIB_TEST(b == 2);
                DLIB_TEST(test.at_start() == false);
                DLIB_TEST(test.current_element_valid() == false);
                DLIB_TEST(test.height() == 0);
                DLIB_TEST(test.size() == 0);

                for (int i = 0; i < 100; ++i)
                {
                    a = i;
                    b = i;
                    test.add(a,b);
                }

                DLIB_TEST(test.size() == 100);
                test.remove_last_in_order(a,b);
                DLIB_TEST(a == 99);
                DLIB_TEST(b == 99);
                DLIB_TEST(test.size() == 99);
                test.remove_last_in_order(a,b);
                DLIB_TEST(a == 98);
                DLIB_TEST(b == 98);
                DLIB_TEST(test.size() == 98);

                test.position_enumerator(-10);
                for (int i = 0; i < 97; ++i)
                {
                    DLIB_TEST(test.element().key() == i);
                    DLIB_TEST(test.element().value() == i);
                    DLIB_TEST(test.move_next());
                }
                DLIB_TEST(test.move_next() == false);
                DLIB_TEST(test.current_element_valid() == false);

                test.position_enumerator(10);
                for (int i = 10; i < 97; ++i)
                {
                    DLIB_TEST(test.element().key() == i);
                    DLIB_TEST(test.element().value() == i);
                    DLIB_TEST(test.move_next());
                }
                DLIB_TEST(test.move_next() == false);
                DLIB_TEST(test.current_element_valid() == false);

                test.reset();
                DLIB_TEST(test.at_start());
                DLIB_TEST(test.current_element_valid() == false);
                for (int i = 0; i < 98; ++i)
                {
                    DLIB_TEST(test.move_next());
                    DLIB_TEST(test.element().key() == i);
                    DLIB_TEST(test.element().value() == i);
                }
                DLIB_TEST_MSG(test.size() == 98, test.size());
                DLIB_TEST(test.move_next() == false);

                test.position_enumerator(98);
                DLIB_TEST(test.current_element_valid() == false);
                DLIB_TEST(test.at_start() == false);

                test.position_enumerator(50);
                DLIB_TEST(test.element().key() == 50);
                DLIB_TEST(test.element().value() == 50);
                DLIB_TEST(test[50] != 0);
                test.remove_current_element(a,b);
                DLIB_TEST(test[50] == 0);
                DLIB_TEST_MSG(test.size() == 97, test.size());
                DLIB_TEST(a == 50);
                DLIB_TEST(b == 50);
                DLIB_TEST(test.element().key() == 51);
                DLIB_TEST(test.element().value() == 51);
                DLIB_TEST(test.current_element_valid());
                test.remove_current_element(a,b);
                DLIB_TEST_MSG(test.size() == 96, test.size());
                DLIB_TEST(a == 51);
                DLIB_TEST(b == 51);
                DLIB_TEST_MSG(test.element().key() == 52,test.element().key());
                DLIB_TEST_MSG(test.element().value() == 52,test.element().value());
                DLIB_TEST(test.current_element_valid());
                test.remove_current_element(a,b);
                DLIB_TEST_MSG(test.size() == 95, test.size());
                DLIB_TEST(a == 52);
                DLIB_TEST(b == 52);
                DLIB_TEST_MSG(test.element().key() == 53,test.element().key());
                DLIB_TEST_MSG(test.element().value() == 53,test.element().value());
                DLIB_TEST(test.current_element_valid());
                test.position_enumerator(50);
                DLIB_TEST_MSG(test.element().key() == 53,test.element().key());
                DLIB_TEST_MSG(test.element().value() == 53,test.element().value());
                DLIB_TEST(test.current_element_valid());
                test.position_enumerator(51);
                DLIB_TEST_MSG(test.element().key() == 53,test.element().key());
                DLIB_TEST_MSG(test.element().value() == 53,test.element().value());
                DLIB_TEST(test.current_element_valid());
                test.position_enumerator(52);
                DLIB_TEST_MSG(test.element().key() == 53,test.element().key());
                DLIB_TEST_MSG(test.element().value() == 53,test.element().value());
                DLIB_TEST(test.current_element_valid());
                test.position_enumerator(53);
                DLIB_TEST_MSG(test.element().key() == 53,test.element().key());
                DLIB_TEST_MSG(test.element().value() == 53,test.element().value());
                DLIB_TEST(test.current_element_valid());

                test.reset();
                test.move_next();
                int lasta = -1, lastb = -1;
                count = 0;
                while (test.current_element_valid() )
                {
                    ++count;
                    int c = test.element().key();
                    int d = test.element().value();
                    test.remove_current_element(a,b);
                    DLIB_TEST(c == a);
                    DLIB_TEST(d == a);
                    DLIB_TEST(lasta < a);
                    DLIB_TEST(lastb < b);
                    lasta = a;
                    lastb = b;
                }
                DLIB_TEST_MSG(count == 95, count);
                DLIB_TEST(test.size() == 0);
                DLIB_TEST(test.height() == 0);

                test.clear();

                for (int i = 0; i < 1000; ++i)
                {
                    a = 1;
                    b = 1;
                    test.add(a,b);
                }

                for (int i = 0; i < 40; ++i)
                {
                    int num = ::rand()%800 + 1;
                    test.reset();
                    for (int j = 0; j < num; ++j)
                    {
                        DLIB_TEST(test.move_next());
                    }
                    DLIB_TEST_MSG(test.current_element_valid(),"size: " << test.size() << "   num: " << num);
                    test.remove_current_element(a,b);
                    DLIB_TEST_MSG(test.current_element_valid(),"size: " << test.size() << "   num: " << num);
                    test.remove_current_element(a,b);
                    test.position_enumerator(1);
                    if (test.current_element_valid())
                        test.remove_current_element(a,b);
                    DLIB_TEST(a == 1);
                    DLIB_TEST(b == 1);
                }

                test.clear();

            }

            test.clear();
            test2.clear();

        }

    }

    #endif // DLIB_BINARY_SEARCH_TREE_KERNEl_TEST_H_