// Header file for the test of the circular buffer library.

// Copyright (c) 2003-2008 Jan Gaspar

// Use, modification, and distribution is subject to 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)

#if !defined(BOOST_CIRCULAR_BUFFER_TEST_HPP)
#define BOOST_CIRCULAR_BUFFER_TEST_HPP

#if defined(_MSC_VER) && _MSC_VER >= 1200
    #pragma once
#endif

#define BOOST_CB_TEST

#include <boost/circular_buffer.hpp>
#include <boost/test/included/unit_test_framework.hpp>
#include <boost/iterator.hpp>
#include <iterator>
#include <numeric>
#include <vector>
#if !defined(BOOST_NO_EXCEPTIONS)
    #include <exception>
#endif

// Integer (substitute for int) - more appropriate for testing
class MyInteger {
private:
    int* m_pValue;
    static int ms_exception_trigger;
    void check_exception() {
        if (ms_exception_trigger > 0) {
            if (--ms_exception_trigger == 0) {
                delete m_pValue;
                m_pValue = 0;
#if !defined(BOOST_NO_EXCEPTIONS)
                throw std::exception();
#endif
            }
        }
    }
public:
    MyInteger() : m_pValue(new int(0)) { check_exception(); }
    MyInteger(int i) : m_pValue(new int(i)) { check_exception(); }
    MyInteger(const MyInteger& src) : m_pValue(new int(src)) { check_exception(); }
    ~MyInteger() { delete m_pValue; }
    MyInteger& operator = (const MyInteger& src) {
        if (this == &src)
            return *this;
        check_exception();
        delete m_pValue;
        m_pValue = new int(src);
        return *this;
    }
    operator int () const { return *m_pValue; }
    static void set_exception_trigger(int n) { ms_exception_trigger = n; }
};

// default constructible class
class MyDefaultConstructible
{
public:
    MyDefaultConstructible() : m_n(1) {}
    MyDefaultConstructible(int n) : m_n(n) {}
    int m_n;
};

// class counting instances of self
class InstanceCounter {
public:
    InstanceCounter() { increment(); }
    InstanceCounter(const InstanceCounter& y) { y.increment(); }
    ~InstanceCounter() { decrement(); }
    static int count() { return ms_count; }
private:
    void increment() const { ++ms_count; }
    void decrement() const { --ms_count; }
    static int ms_count;
};

// dummy class suitable for iterator referencing test
class Dummy {
public:
    enum DummyEnum {
        eVar,
        eFnc,
        eConst,
        eVirtual
    };
    Dummy() : m_n(eVar) {}
    DummyEnum fnc() { return eFnc; }
    DummyEnum const_fnc() const { return eConst; }
    virtual DummyEnum virtual_fnc() { return eVirtual; }
    DummyEnum m_n;
};

// simulator of an input iterator
struct MyInputIterator
: boost::iterator<std::input_iterator_tag, int, ptrdiff_t, int*, int&> {
    typedef std::vector<int>::iterator vector_iterator;
    typedef int value_type;
    typedef int* pointer;
    typedef int& reference;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    explicit MyInputIterator(const vector_iterator& it) : m_it(it) {}
    MyInputIterator& operator = (const MyInputIterator& it) {
        if (this == &it)
            return *this;
        m_it = it.m_it;
        return *this;
    }
    reference operator * () const { return *m_it; }
    pointer operator -> () const { return &(operator*()); }
    MyInputIterator& operator ++ () {
        ++m_it;
        return *this;
    }
    MyInputIterator operator ++ (int) {
        MyInputIterator tmp = *this;
        ++*this;
        return tmp;
    }
    bool operator == (const MyInputIterator& it) const { return m_it == it.m_it; }
    bool operator != (const MyInputIterator& it) const { return m_it != it.m_it; }
private:
    vector_iterator m_it;
};

#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR)

inline std::input_iterator_tag iterator_category(const MyInputIterator&) {
    return std::input_iterator_tag();
}
inline int* value_type(const MyInputIterator&) { return 0; }
inline ptrdiff_t* distance_type(const MyInputIterator&) { return 0; }

#endif // #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR)

using boost::unit_test::test_suite;
using namespace boost;
using namespace std;

#endif // #if !defined(BOOST_CIRCULAR_BUFFER_TEST_HPP)
