From 8522ff18e8255c343612f2849871eb9abe820b2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 12 Apr 2015 12:57:29 +0200 Subject: [PATCH] Add iterator test --- test/iterator_test.hpp | 376 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 test/iterator_test.hpp diff --git a/test/iterator_test.hpp b/test/iterator_test.hpp new file mode 100644 index 0000000..43af6ab --- /dev/null +++ b/test/iterator_test.hpp @@ -0,0 +1,376 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2015-2015. 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/intrusive for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +namespace boost{ namespace intrusive { namespace test{ + +////////////////////////////////////////////// +// +// Some traits to avoid special cases with +// containers without bidirectional iterators +// +////////////////////////////////////////////// +template +struct has_member_reverse_iterator +{ + typedef char yes_type; + struct no_type{ char _[2]; }; + + template static no_type test(...); + template static yes_type test(typename D::reverse_iterator const*); + static const bool value = sizeof(test(0)) == sizeof(yes_type); +}; + +template +struct has_member_const_reverse_iterator +{ + typedef char yes_type; + struct no_type{ char _[2]; }; + + template static no_type test(...); + template static yes_type test(typename D::const_reverse_iterator const*); + static const bool value = sizeof(test(0)) == sizeof(yes_type); +}; + +template::value> +struct get_reverse_iterator +{ + typedef typename C::reverse_iterator type; + static type begin(C &c) { return c.rbegin(); } + static type end(C &c) { return c.rend(); } +}; + +template +struct get_reverse_iterator +{ + typedef typename C::iterator type; + static type begin(C &c) { return c.begin(); } + static type end(C &c) { return c.end(); } +}; + +template::value> +struct get_const_reverse_iterator +{ + typedef typename C::const_reverse_iterator type; + static type begin(C &c) { return c.crbegin(); } + static type end(C &c) { return c.crend(); } +}; + +template +struct get_const_reverse_iterator +{ + typedef typename C::const_iterator type; + static type begin(C &c) { return c.cbegin(); } + static type end(C &c) { return c.cend(); } +}; + +////////////////////////////////////////////// +// +// Iterator tests +// +////////////////////////////////////////////// + +template +void test_iterator_operations(I b, I e) +{ + //Test the range is not empty + BOOST_TEST(b != e); + BOOST_TEST(!(b == e)); + { + I i; + I i2(b); //CopyConstructible + i = i2; //Assignable + //Destructible + (void)i; + (void)i2; + } + + typedef typename iterator_traits::reference reference; + reference r = *b; + (void)r; + typedef typename iterator_traits::pointer pointer; + pointer p = b.operator->(); + (void)p; + I &ri= ++b; + (void)ri; + const I &cri= b++; + (void)cri; +} + +template +void test_iterator_compatible(C &c) +{ + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + typedef typename get_reverse_iterator::type reverse_iterator; + typedef typename get_const_reverse_iterator::type const_reverse_iterator; + //Basic operations + test_iterator_operations(c. begin(), c. end()); + test_iterator_operations(c.cbegin(), c.cend()); + test_iterator_operations(get_reverse_iterator::begin(c), get_reverse_iterator::end(c)); + test_iterator_operations(get_const_reverse_iterator::begin(c), get_const_reverse_iterator::end(c)); + //Make sure dangeous conversions are not possible + BOOST_STATIC_ASSERT((!boost::container::container_detail::is_convertible::value)); + BOOST_STATIC_ASSERT((!boost::container::container_detail::is_convertible::value)); + //Test iterator conversions + { + const_iterator ci; + iterator i(c.begin()); + ci = i; + BOOST_ASSERT(ci == i); + BOOST_ASSERT(*ci == *i); + const_iterator ci2(i); + BOOST_ASSERT(ci2 == i); + BOOST_ASSERT(*ci2 == *i); + (void)ci2; + } + //Test reverse_iterator conversions + { + const_reverse_iterator cr; + reverse_iterator r(get_reverse_iterator::begin(c)); + cr = r; + BOOST_ASSERT(cr == r); + BOOST_ASSERT(*cr == *r); + const_reverse_iterator cr2(r); + BOOST_ASSERT(cr2 == r); + BOOST_ASSERT(*cr2 == *r); + (void)cr2; + } +} + +template +void test_iterator_input_and_compatible(C &c) +{ + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + typedef typename get_reverse_iterator::type reverse_iterator; + typedef typename get_const_reverse_iterator::type const_reverse_iterator; + typedef iterator_traits nit_traits; + typedef iterator_traits cit_traits; + typedef iterator_traits rnit_traits; + typedef iterator_traits crit_traits; + + using boost::move_detail::is_same; + //Trivial typedefs + BOOST_STATIC_ASSERT((!is_same::value)); + BOOST_STATIC_ASSERT((!is_same::value)); + //difference_type + typedef typename C::difference_type difference_type; + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + //value_type + typedef typename C::value_type value_type; + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + //pointer + typedef typename C::pointer pointer; + typedef typename C::const_pointer const_pointer; + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + //reference + typedef typename C::reference reference; + typedef typename C::const_reference const_reference; + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + //Dynamic tests + test_iterator_compatible(c); +} + +template +void test_iterator_forward_functions(C const &c, I const b, I const e) +{ + typedef typename C::size_type size_type; + { + size_type i = 0; + I it = b; + for(I it2 = b; i != c.size(); ++it, ++i){ + BOOST_TEST(it == it2++); + I ittmp(it); + BOOST_TEST(&++ittmp == &ittmp); + BOOST_TEST(ittmp == it2); + if(it2 != e){ + BOOST_TEST(*ittmp == *it2); + } + } + BOOST_TEST(i == c.size()); + BOOST_TEST(it == e); + } +} + +template +void test_iterator_forward_and_compatible(C &c) +{ + test_iterator_input_and_compatible(c); + test_iterator_forward_functions(c, c.begin(), c.end()); + test_iterator_forward_functions(c, c.cbegin(), c.cend()); + test_iterator_forward_functions(c, get_reverse_iterator::begin(c), get_reverse_iterator::end(c)); + test_iterator_forward_functions(c, get_const_reverse_iterator::begin(c), get_const_reverse_iterator::end(c)); +} + +template +void test_iterator_bidirectional_functions(C const &c, I const b, I const e) +{ + typedef typename C::size_type size_type; + { + size_type i = 0; + I it = e; + for(I it2 = e; i != c.size(); --it, ++i){ + BOOST_TEST(it == it2--); + I ittmp(it); + BOOST_TEST(&--ittmp == &ittmp); + BOOST_TEST(ittmp == it2); + BOOST_TEST(++ittmp == it); + if(it != e){ + BOOST_TEST(*ittmp == *it); + } + } + BOOST_TEST(i == c.size()); + BOOST_TEST(it == b); + } +} + +template +void test_iterator_bidirectional_and_compatible(C &c) +{ + test_iterator_forward_and_compatible(c); + test_iterator_bidirectional_functions(c, c.begin(), c.end()); + test_iterator_bidirectional_functions(c, c.cbegin(), c.cend()); + test_iterator_bidirectional_functions(c, c.rbegin(), c.rend()); + test_iterator_bidirectional_functions(c, c.crbegin(), c.crend()); +} + +template +void test_iterator_random_functions(C const &c, I const b, I const e) +{ + typedef typename C::size_type size_type; + { + I it = b; + for(size_type i = 0, m = c.size(); i != m; ++i, ++it){ + BOOST_TEST(i == size_type(it - b)); + BOOST_TEST(b[i] == *it); + BOOST_TEST(&b[i] == &*it); + BOOST_TEST((b + i) == it); + BOOST_TEST((i + b) == it); + BOOST_TEST(b == (it - i)); + BOOST_TEST((I(b)+=i) == it); + BOOST_TEST(b == (I(it)-=i)); + } + BOOST_TEST(c.size() == size_type(e - b)); + } + { + I it(b), itb(b); + if(b != e){ + for(++it; it != e; ++it){ + BOOST_TEST(itb < it); + BOOST_TEST(itb <= it); + BOOST_TEST(!(itb > it)); + BOOST_TEST(!(itb >= it)); + BOOST_TEST(it > itb); + BOOST_TEST(it >= itb); + BOOST_TEST(!(it < itb)); + BOOST_TEST(!(it <= itb)); + BOOST_TEST(it >= it); + BOOST_TEST(it <= it); + itb = it; + } + } + } +} + +template +void test_iterator_random_and_compatible(C &c) +{ + test_iterator_bidirectional_and_compatible(c); + test_iterator_random_functions(c, c.begin(), c.end()); + test_iterator_random_functions(c, c.cbegin(), c.cend()); + test_iterator_random_functions(c, c.rbegin(), c.rend()); + test_iterator_random_functions(c, c.crbegin(), c.crend()); +} + +//////////////////////// + +template +void test_iterator_forward(C &c) +{ + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + typedef typename C::reverse_iterator reverse_iterator; + typedef typename C::const_reverse_iterator const_reverse_iterator; + typedef iterator_traits nit_traits; + typedef iterator_traits cit_traits; + typedef iterator_traits rnit_traits; + typedef iterator_traits crit_traits; + + using boost::container::container_detail::is_same; + //iterator_category + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + //Test dynamic + test_iterator_forward_and_compatible(c); +} + +template +void test_iterator_bidirectional(C &c) +{ + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + typedef typename C::reverse_iterator reverse_iterator; + typedef typename C::const_reverse_iterator const_reverse_iterator; + typedef iterator_traits nit_traits; + typedef iterator_traits cit_traits; + typedef iterator_traits rnit_traits; + typedef iterator_traits crit_traits; + + using boost::container::container_detail::is_same; + //iterator_category + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + //Test dynamic + test_iterator_bidirectional_and_compatible(c); +} + +template +void test_iterator_random(C &c) +{ + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + typedef typename C::reverse_iterator reverse_iterator; + typedef typename C::const_reverse_iterator const_reverse_iterator; + typedef iterator_traits nit_traits; + typedef iterator_traits cit_traits; + typedef iterator_traits rnit_traits; + typedef iterator_traits crit_traits; + + using boost::container::container_detail::is_same; + //iterator_category + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + //Test dynamic + test_iterator_random_and_compatible(c); +} + +}}} //boost::container::test