
// Copyright 2006-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include "../helpers/prefix.hpp"

#include "./containers.hpp"
#include <string>
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/strong.hpp"
#include <boost/utility.hpp>
#include <cmath>

test::seed_t seed(747373);

template <class T>
struct insert_test_base : public test::exception_base
{
    test::random_values<T> values;
    insert_test_base(unsigned int count = 5) : values(count) {}

    typedef T data_type;
    typedef test::strong<T> strong_type;

    data_type init() const {
        return T();
    }

    void check BOOST_PREVENT_MACRO_SUBSTITUTION(
        T const& x, strong_type const& strong) const
    {
        std::string scope(test::scope);

        if(scope.find("hash::operator()") == std::string::npos)
            strong.test(x, test::exception::detail::tracker.count_allocations);
        test::check_equivalent_keys(x);
    }
};

#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)

template <class T>
struct emplace_test1 : public insert_test_base<T>
{
    typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;

    void run(T& x, strong_type& strong) const {
        for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
            it = this->values.begin(), end = this->values.end();
            it != end; ++it)
        {
            strong.store(x, test::exception::detail::tracker.count_allocations);
            x.emplace(*it);
        }
    }
};

#endif

template <class T>
struct insert_test1 : public insert_test_base<T>
{
    typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;

    void run(T& x, strong_type& strong) const {
        for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
            it = this->values.begin(), end = this->values.end();
            it != end; ++it)
        {
            strong.store(x, test::exception::detail::tracker.count_allocations);
            x.insert(*it);
        }
    }
};

template <class T>
struct insert_test2 : public insert_test_base<T>
{
    typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;

    void run(T& x, strong_type& strong) const {
        for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
            it = this->values.begin(), end = this->values.end();
            it != end; ++it)
        {
            strong.store(x, test::exception::detail::tracker.count_allocations);
            x.insert(x.begin(), *it);
        }
    }
};

template <class T>
struct insert_test3 : public insert_test_base<T>
{
    void run(T& x) const {
        x.insert(this->values.begin(), this->values.end());
    }

    void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
        test::check_equivalent_keys(x);
    }
};

template <class T>
struct insert_test4 : public insert_test_base<T>
{
    typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;

    void run(T& x, strong_type& strong) const {
        for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
            it = this->values.begin(), end = this->values.end();
            it != end; ++it)
        {
            strong.store(x, test::exception::detail::tracker.count_allocations);
            x.insert(it, boost::next(it));
        }
    }
};

template <class T>
struct insert_test_rehash1 : public insert_test_base<T>
{
    typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;

    insert_test_rehash1() : insert_test_base<T>(1000) {}

    T init() const {
        using namespace std;
        typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;

        T x;
        x.max_load_factor(0.25);
        size_type bucket_count = x.bucket_count();
        size_type initial_elements = static_cast<size_type>(
            ceil(bucket_count * (double) x.max_load_factor()) - 1);
        BOOST_TEST(initial_elements < this->values.size());
        x.insert(this->values.begin(),
                boost::next(this->values.begin(), initial_elements));
        BOOST_TEST(bucket_count == x.bucket_count());
        return x;
    }

    void run(T& x, strong_type& strong) const {
        BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
        int count = 0;
        BOOST_DEDUCED_TYPENAME T::const_iterator pos = x.cbegin();

        for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
            it = boost::next(this->values.begin(), x.size()),
                end = this->values.end();
            it != end && count < 10; ++it, ++count)
        {
            strong.store(x, test::exception::detail::tracker.count_allocations);
            pos = x.insert(pos, *it);
        }

        // This isn't actually a failure, but it means the test isn't doing its
        // job.
        BOOST_TEST(x.bucket_count() != bucket_count);
    }
};

template <class T>
struct insert_test_rehash2 : public insert_test_rehash1<T>
{
    typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;

    void run(T& x, strong_type& strong) const {
        BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
        int count = 0;

        for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
            it = boost::next(this->values.begin(), x.size()),
                end = this->values.end();
            it != end && count < 10; ++it, ++count)
        {
            strong.store(x, test::exception::detail::tracker.count_allocations);
            x.insert(*it);
        }

        // This isn't actually a failure, but it means the test isn't doing its
        // job.
        BOOST_TEST(x.bucket_count() != bucket_count);
    }
};

template <class T>
struct insert_test_rehash3 : public insert_test_base<T>
{
    BOOST_DEDUCED_TYPENAME T::size_type mutable
        rehash_bucket_count, original_bucket_count;

    insert_test_rehash3() : insert_test_base<T>(1000) {}

    T init() const {
        using namespace std;
        typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;

        T x;
        x.max_load_factor(0.25);

        original_bucket_count = x.bucket_count();
        rehash_bucket_count = static_cast<size_type>(
            ceil(original_bucket_count * (double) x.max_load_factor())) - 1;

        size_type initial_elements =
            rehash_bucket_count > 5 ? rehash_bucket_count - 5 : 1;

        BOOST_TEST(initial_elements < this->values.size());
        x.insert(this->values.begin(),
                boost::next(this->values.begin(), initial_elements));
        BOOST_TEST(original_bucket_count == x.bucket_count());
        return x;
    }

    void run(T& x) const {
        BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();

        x.insert(boost::next(this->values.begin(), x.size()),
                boost::next(this->values.begin(), x.size() + 20));

        // This isn't actually a failure, but it means the test isn't doing its
        // job.
        BOOST_TEST(x.bucket_count() != bucket_count);
    }

    void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
        if(x.size() < rehash_bucket_count) {
            //BOOST_TEST(x.bucket_count() == original_bucket_count);
        }
        test::check_equivalent_keys(x);
    }
};

#define BASIC_TESTS \
    (insert_test1)(insert_test2)(insert_test3)(insert_test4) \
    (insert_test_rehash1)(insert_test_rehash2)(insert_test_rehash3)

#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
#define ALL_TESTS (emplace_test1)BASIC_TESTS
#else
#define ALL_TESTS BASIC_TESTS
#endif


RUN_EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ)
