diff options
Diffstat (limited to 'src/boost/libs/container/test/node_handle_test.cpp')
-rw-r--r-- | src/boost/libs/container/test/node_handle_test.cpp | 633 |
1 files changed, 633 insertions, 0 deletions
diff --git a/src/boost/libs/container/test/node_handle_test.cpp b/src/boost/libs/container/test/node_handle_test.cpp new file mode 100644 index 00000000..3c263794 --- /dev/null +++ b/src/boost/libs/container/test/node_handle_test.cpp @@ -0,0 +1,633 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2016-2016. 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) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include <boost/core/lightweight_test.hpp> +#include <boost/static_assert.hpp> +#include <boost/container/node_handle.hpp> +#include <boost/container/new_allocator.hpp> +#include <boost/move/utility_core.hpp> +#include <boost/move/adl_move_swap.hpp> +#include <boost/container/detail/pair_key_mapped_of_value.hpp> + +using namespace ::boost::container; + +enum EAllocState +{ + DefaultConstructed, + MoveConstructed, + MoveAssigned, + CopyConstructed, + CopyAssigned, + Swapped, + Destructed +}; + +template<class Node> +class trace_allocator + : public new_allocator<Node> +{ + BOOST_COPYABLE_AND_MOVABLE(trace_allocator) + + typedef new_allocator<Node> base_t; + + public: + + struct propagate_on_container_move_assignment + { + static const bool value = true; + }; + + struct propagate_on_container_swap + { + static const bool value = true; + }; + + //!Obtains an new_allocator that allocates + //!objects of type T2 + template<class T2> + struct rebind + { + typedef trace_allocator<T2> other; + }; + + explicit trace_allocator(unsigned value = 999) + : m_state(DefaultConstructed), m_value(value) + { + ++count; + } + + trace_allocator(BOOST_RV_REF(trace_allocator) other) + : base_t(boost::move(BOOST_MOVE_BASE(base_t, other))), m_state(MoveConstructed), m_value(other.m_value) + { + ++count; + } + + trace_allocator(const trace_allocator &other) + : base_t(other), m_state(CopyConstructed), m_value(other.m_value) + { + ++count; + } + + trace_allocator & operator=(BOOST_RV_REF(trace_allocator) other) + { + m_value = other.m_value; + m_state = MoveAssigned; + return *this; + } + + template<class OtherNode> + trace_allocator(const trace_allocator<OtherNode> &other) + : m_state(CopyConstructed), m_value(other.m_value) + { + ++count; + } + + template<class OtherNode> + trace_allocator & operator=(BOOST_COPY_ASSIGN_REF(trace_allocator<OtherNode>) other) + { + m_value = other.m_value; + m_state = CopyAssigned; + return *this; + } + + ~trace_allocator() + { + m_value = 0u-1u; + m_state = Destructed; + --count; + } + + void swap(trace_allocator &other) + { + boost::adl_move_swap(m_value, other.m_value); + m_state = other.m_state = Swapped; + } + + friend void swap(trace_allocator &left, trace_allocator &right) + { + left.swap(right); + } + + EAllocState m_state; + unsigned m_value; + + static unsigned int count; + + static void reset_count() + { count = 0; } +}; + +template<class Node> +unsigned int trace_allocator<Node>::count = 0; + +template<class T> +struct node +{ + typedef T value_type; + value_type value; + + value_type &get_data() { return value; } + const value_type &get_data() const { return value; } + + node() + { + ++count; + } + + ~node() + { + --count; + } + + static unsigned int count; + + static void reset_count() + { count = 0; } +}; + +template<class T1, class T2> +struct value +{ + T1 first; + T2 second; +}; + +template<class T> +unsigned int node<T>::count = 0; + + +//Common types +typedef value<int, unsigned> test_pair; +typedef pair_key_mapped_of_value<int, unsigned> key_mapped_t; +typedef node<test_pair> node_t; +typedef trace_allocator< node_t > node_alloc_t; +typedef node_handle<node_alloc_t, void> node_handle_set_t; +typedef node_handle<node_alloc_t, key_mapped_t> node_handle_map_t; +typedef allocator_traits<node_alloc_t>::portable_rebind_alloc<test_pair>::type value_allocator_type; + +void test_types() +{ + //set + BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_set_t::value_type, test_pair>::value )); + BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_set_t::key_type, test_pair>::value )); + BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_set_t::mapped_type, test_pair>::value )); + BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_set_t::allocator_type, value_allocator_type>::value )); + + //map + BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_map_t::value_type, test_pair>::value )); + BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_map_t::key_type, int>::value )); + BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_map_t::mapped_type, unsigned>::value )); + BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_map_t::allocator_type, value_allocator_type>::value )); +} + +void test_default_constructor() +{ + node_alloc_t::reset_count(); + { + node_handle_set_t nh; + BOOST_TEST(node_alloc_t::count == 0); + } + BOOST_TEST(node_alloc_t::count == 0); +} + +void test_arg_constructor() +{ + //With non-null pointer + node_alloc_t::reset_count(); + node_t::reset_count(); + { + const node_alloc_t al; + BOOST_TEST(node_alloc_t::count == 1); + { + node_handle_set_t nh(new node_t, al); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 2); + } + BOOST_TEST(node_alloc_t::count == 1); + } + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); + + //With null pointer + node_alloc_t::reset_count(); + node_t::reset_count(); + { + const node_alloc_t al; + BOOST_TEST(node_alloc_t::count == 1); + { + node_handle_set_t nh(0, al); + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 1); + } + BOOST_TEST(node_alloc_t::count == 1); + BOOST_TEST(node_t::count == 0); + } + BOOST_TEST(node_alloc_t::count == 0); +} + +void test_move_constructor() +{ + //With non-null pointer + node_alloc_t::reset_count(); + node_t::reset_count(); + { + const node_alloc_t al; + BOOST_TEST(node_alloc_t::count == 1); + { + node_t *const from_ptr = new node_t; + node_handle_set_t nh(from_ptr, al); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 2); + { + node_handle_set_t nh2(boost::move(nh)); + BOOST_TEST(nh.empty()); + BOOST_TEST(!nh2.empty()); + BOOST_TEST(nh2.get() == from_ptr); + BOOST_TEST(nh2.node_alloc().m_state == MoveConstructed); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 2); + } + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 1); + } + BOOST_TEST(node_alloc_t::count == 1); + } + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); + + //With null pointer + node_alloc_t::reset_count(); + node_t::reset_count(); + { + const node_alloc_t al; + BOOST_TEST(node_alloc_t::count == 1); + { + node_handle_set_t nh; + { + node_handle_set_t nh2(boost::move(nh)); + BOOST_TEST(nh.empty()); + BOOST_TEST(nh2.empty()); + BOOST_TEST(node_alloc_t::count == 1); + } + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 1); + } + BOOST_TEST(node_alloc_t::count == 1); + } + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); +} + +void test_related_constructor() +{ + //With non-null pointer + node_alloc_t::reset_count(); + node_t::reset_count(); + { + const node_alloc_t al; + BOOST_TEST(node_alloc_t::count == 1); + { + node_t *const from_ptr = new node_t; + node_handle_map_t nh(from_ptr, al); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 2); + { + node_handle_set_t nh2(boost::move(nh)); + BOOST_TEST(nh.empty()); + BOOST_TEST(!nh2.empty()); + BOOST_TEST(nh2.get() == from_ptr); + BOOST_TEST(nh2.node_alloc().m_state == MoveConstructed); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 2); + } + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 1); + } + BOOST_TEST(node_alloc_t::count == 1); + } + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); + + //With null pointer + node_alloc_t::reset_count(); + node_t::reset_count(); + { + const node_alloc_t al; + BOOST_TEST(node_alloc_t::count == 1); + { + node_handle_set_t nh; + { + node_handle_map_t nh2(boost::move(nh)); + BOOST_TEST(nh.empty()); + BOOST_TEST(nh2.empty()); + BOOST_TEST(node_alloc_t::count == 1); + } + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 1); + } + BOOST_TEST(node_alloc_t::count == 1); + } + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); +} + +void test_move_assignment() +{ + //empty = full + { + node_alloc_t::reset_count(); + node_t::reset_count(); + node_t *const from_ptr = new node_t; + node_handle_set_t nh_from(from_ptr, node_alloc_t()); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + + node_handle_set_t nh_to; + BOOST_TEST(nh_to.empty()); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + + nh_to = boost::move(nh_from); + + BOOST_TEST(nh_from.empty()); + BOOST_TEST(!nh_to.empty()); + BOOST_TEST(nh_to.get() == from_ptr); + BOOST_TEST(nh_to.node_alloc().m_state == MoveConstructed); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + } + + //empty = empty + { + node_alloc_t::reset_count(); + node_t::reset_count(); + + node_handle_set_t nh_from; + BOOST_TEST(nh_from.empty()); + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); + + node_handle_set_t nh_to; + BOOST_TEST(nh_to.empty()); + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); + + nh_to = boost::move(nh_from); + + BOOST_TEST(nh_from.empty()); + BOOST_TEST(nh_to.empty()); + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); + } + + //full = empty + { + node_alloc_t::reset_count(); + node_t::reset_count(); + + node_handle_set_t nh_from; + BOOST_TEST(nh_from.empty()); + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); + + node_handle_set_t nh_to(new node_t, node_alloc_t()); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + + nh_to = boost::move(nh_from); + + BOOST_TEST(nh_from.empty()); + BOOST_TEST(nh_to.empty()); + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); + } + + //full = full + { + node_alloc_t::reset_count(); + node_t::reset_count(); + + node_t *const from_ptr = new node_t; + node_handle_set_t nh_from(from_ptr, node_alloc_t()); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + + node_handle_set_t nh_to(new node_t, node_alloc_t()); + BOOST_TEST(node_t::count == 2); + BOOST_TEST(node_alloc_t::count == 2); + + nh_to = boost::move(nh_from); + + BOOST_TEST(nh_from.empty()); + BOOST_TEST(!nh_to.empty()); + BOOST_TEST(nh_to.get() == from_ptr); + BOOST_TEST(nh_to.node_alloc().m_state == MoveAssigned); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + } +} + +void test_value_key_mapped() +{ + //value() + { + node_t *from_ptr = new node_t; + const node_handle_set_t nh_from(from_ptr, node_alloc_t()); + from_ptr->value.first = -99; + from_ptr->value.second = 99; + BOOST_TEST(nh_from.value().first == -99); + BOOST_TEST(nh_from.value().second == 99); + } + //key()/mapped() + { + node_t *from_ptr = new node_t; + const node_handle_map_t nh_from(from_ptr, node_alloc_t()); + from_ptr->value.first = -98; + from_ptr->value.second = 98; + BOOST_TEST(nh_from.key() == -98); + BOOST_TEST(nh_from.mapped() == 98); + } +} + +void test_get_allocator() +{ + const node_handle_set_t nh(new node_t, node_alloc_t(888)); + allocator_traits<node_alloc_t>::portable_rebind_alloc<test_pair>::type a = nh.get_allocator(); + BOOST_TEST(a.m_value == 888); +} + +void test_bool_conversion_empty() +{ + const node_handle_set_t nh(new node_t, node_alloc_t(777)); + const node_handle_set_t nh_null; + BOOST_TEST(nh && !nh_null); + BOOST_TEST(!(!nh || nh_null)); + BOOST_TEST(!nh.empty() && nh_null.empty()); + BOOST_TEST(!(nh.empty() || !nh_null.empty())); +} + +void test_swap() +{ + //empty.swap(full) + { + node_alloc_t::reset_count(); + node_t::reset_count(); + node_t *const from_ptr = new node_t; + node_handle_set_t nh_from(from_ptr, node_alloc_t()); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + + node_handle_set_t nh_to; + BOOST_TEST(nh_to.empty()); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + + nh_to.swap(nh_from); + + BOOST_TEST(nh_from.empty()); + BOOST_TEST(!nh_to.empty()); + BOOST_TEST(nh_to.get() == from_ptr); + BOOST_TEST(nh_to.node_alloc().m_state == MoveConstructed); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + } + + //empty.swap(empty) + { + node_alloc_t::reset_count(); + node_t::reset_count(); + + node_handle_set_t nh_from; + BOOST_TEST(nh_from.empty()); + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); + + node_handle_set_t nh_to; + BOOST_TEST(nh_to.empty()); + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); + + nh_to.swap(nh_from); + + BOOST_TEST(nh_from.empty()); + BOOST_TEST(nh_to.empty()); + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); + } + + //full.swap(empty) + { + node_alloc_t::reset_count(); + node_t::reset_count(); + + node_handle_set_t nh_from; + BOOST_TEST(nh_from.empty()); + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); + + node_t *const to_ptr = new node_t; + node_handle_set_t nh_to(to_ptr, node_alloc_t()); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + + nh_to.swap(nh_from); + + BOOST_TEST(!nh_from.empty()); + BOOST_TEST(nh_from.node_alloc().m_state == MoveConstructed); + BOOST_TEST(nh_from.get() == to_ptr); + BOOST_TEST(nh_to.empty()); + + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + } + + //full.swap(full) + { + node_alloc_t::reset_count(); + node_t::reset_count(); + + node_t *const from_ptr = new node_t; + node_handle_set_t nh_from(from_ptr, node_alloc_t()); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + + node_t *const to_ptr = new node_t; + node_handle_set_t nh_to(to_ptr, node_alloc_t()); + BOOST_TEST(node_t::count == 2); + BOOST_TEST(node_alloc_t::count == 2); + + nh_to.swap(nh_from); + + BOOST_TEST(!nh_from.empty()); + BOOST_TEST(nh_from.get() == to_ptr); + BOOST_TEST(nh_from.node_alloc().m_state == Swapped); + + BOOST_TEST(!nh_to.empty()); + BOOST_TEST(nh_to.get() == from_ptr); + BOOST_TEST(nh_to.node_alloc().m_state == Swapped); + + BOOST_TEST(node_t::count == 2); + BOOST_TEST(node_alloc_t::count == 2); + } +} + +void test_get_release() +{ + //get() + { + node_alloc_t::reset_count(); + node_t::reset_count(); + + node_t *const ptr = new node_t; + const node_handle_set_t nh(ptr, node_alloc_t()); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + + BOOST_TEST(nh.get() == ptr); + BOOST_TEST(!nh.empty()); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + } + BOOST_TEST(node_t::count == 0); + BOOST_TEST(node_alloc_t::count == 0); + + //release() + { + node_alloc_t::reset_count(); + node_t::reset_count(); + + node_t *const ptr = new node_t; + node_handle_set_t nh(ptr, node_alloc_t()); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 1); + + BOOST_TEST(nh.release() == ptr); + BOOST_TEST(nh.empty()); + BOOST_TEST(node_t::count == 1); + BOOST_TEST(node_alloc_t::count == 0); + delete ptr; + } + BOOST_TEST(node_t::count == 0); +} + +int main() +{ + test_types(); + test_default_constructor(); + test_arg_constructor(); + test_move_constructor(); + test_related_constructor(); + test_move_assignment(); + test_value_key_mapped(); + test_get_allocator(); + test_bool_conversion_empty(); + test_swap(); + test_get_release(); + return ::boost::report_errors(); +} |