///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2007-2009 // // 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. // ///////////////////////////////////////////////////////////////////////////// #ifndef BOOST_INTRUSIVE_TEST_CONTAINER_HPP #define BOOST_INTRUSIVE_TEST_CONTAINER_HPP #include #include namespace boost { namespace intrusive { namespace test { template struct is_unordered { static const bool value = false; }; template struct has_const_overloads { static const bool value = true; }; template< class Container > void test_container( Container & c ) { typedef typename Container::value_type value_type; typedef typename Container::iterator iterator; typedef typename Container::const_iterator const_iterator; typedef typename Container::reference reference; typedef typename Container::const_reference const_reference; typedef typename Container::pointer pointer; typedef typename Container::const_pointer const_pointer; typedef typename Container::difference_type difference_type; typedef typename Container::size_type size_type; typedef typename Container::difference_type difference_type; typedef typename Container::size_type size_type; typedef typename Container::value_traits value_traits; const size_type num_elem = c.size(); BOOST_TEST( c.empty() == (num_elem == 0) ); { iterator it(c.begin()), itend(c.end()); size_type i; for(i = 0; i < num_elem; ++i){ ++it; } BOOST_TEST( it == c.end() ); BOOST_TEST( c.size() == i ); } //Check iterator conversion BOOST_TEST( const_iterator(c.begin()) == c.cbegin() ); { const_iterator it(c.cbegin()), itend(c.cend()); size_type i; for(i = 0; i < num_elem; ++i){ ++it; } BOOST_TEST( it == c.cend() ); BOOST_TEST( c.size() == i ); } } template< class Container, class Data > void test_sequence_container(Container & c, Data & d) { assert( d.size() > 2 ); c.clear(); BOOST_TEST( c.size() == 0 ); BOOST_TEST( c.empty() ); { typename Data::iterator i = d.begin(); c.insert( c.begin(), *i ); c.insert( c.end(), *(++i) ); } BOOST_TEST( c.size() == 2 ); BOOST_TEST( !c.empty() ); typename Container::iterator i; i = c.erase( c.begin() ); BOOST_TEST( c.size() == 1 ); { typename Data::iterator i = d.begin(); ++++i; c.insert( c.begin(), *(i) ); } i = c.erase( c.begin(), c.end() ); BOOST_TEST( i == c.end() ); BOOST_TEST( c.empty() ); c.insert( c.begin(), *d.begin() ); BOOST_TEST( c.size() == 1 ); BOOST_TEST( c.begin() != c.end() ); i = c.erase_and_dispose( c.begin(), detail::null_disposer() ); BOOST_TEST( i == c.begin() ); c.assign(d.begin(), d.end()); BOOST_TEST( c.size() == d.size() ); c.clear(); BOOST_TEST( c.size() == 0 ); BOOST_TEST( c.empty() ); } template< class Container, class Data > void test_common_unordered_and_associative_container(Container & c, Data & d, boost::intrusive::detail::true_ unordered) { (void)unordered; typedef typename Container::size_type size_type; assert( d.size() > 2 ); c.clear(); c.insert(d.begin(), d.end()); for( typename Data::const_iterator di = d.begin(), de = d.end(); di != de; ++di ) { BOOST_TEST( c.find(*di) != c.end() ); } typename Data::const_iterator db = d.begin(); typename Data::const_iterator da = db++; size_type old_size = c.size(); c.erase(*da, c.hash_function(), c.key_eq()); BOOST_TEST( c.size() == old_size-1 ); //This should not eras anyone size_type second_erase = c.erase_and_dispose ( *da, c.hash_function(), c.key_eq(), detail::null_disposer() ); BOOST_TEST( second_erase == 0 ); BOOST_TEST( c.count(*da, c.hash_function(), c.key_eq()) == 0 ); BOOST_TEST( c.count(*db, c.hash_function(), c.key_eq()) != 0 ); BOOST_TEST( c.find(*da, c.hash_function(), c.key_eq()) == c.end() ); BOOST_TEST( c.find(*db, c.hash_function(), c.key_eq()) != c.end() ); BOOST_TEST( c.equal_range(*db, c.hash_function(), c.key_eq()).first != c.end() ); c.clear(); BOOST_TEST( c.equal_range(*da, c.hash_function(), c.key_eq()).first == c.end() ); } template< class Container, class Data > void test_common_unordered_and_associative_container(Container & c, Data & d, boost::intrusive::detail::false_ unordered) { (void)unordered; typedef typename Container::size_type size_type; assert( d.size() > 2 ); c.clear(); c.insert(d.begin(), d.end()); for( typename Data::const_iterator di = d.begin(), de = d.end(); di != de; ++di ) { BOOST_TEST( c.find(*di, c.key_comp()) != c.end() ); } typename Data::const_iterator db = d.begin(); typename Data::const_iterator da = db++; size_type old_size = c.size(); c.erase(*da, c.key_comp()); BOOST_TEST( c.size() == old_size-1 ); //This should not eras anyone size_type second_erase = c.erase_and_dispose( *da, c.key_comp(), detail::null_disposer() ); BOOST_TEST( second_erase == 0 ); BOOST_TEST( c.count(*da, c.key_comp()) == 0 ); BOOST_TEST( c.count(*db, c.key_comp()) != 0 ); BOOST_TEST( c.find(*da, c.key_comp()) == c.end() ); BOOST_TEST( c.find(*db, c.key_comp()) != c.end() ); BOOST_TEST( c.equal_range(*db, c.key_comp()).first != c.end() ); c.clear(); BOOST_TEST( c.equal_range(*da, c.key_comp()).first == c.end() ); } template< class Container, class Data > void test_common_unordered_and_associative_container(Container & c, Data & d) { { typedef typename Container::size_type size_type; assert( d.size() > 2 ); c.clear(); c.insert(d.begin(), d.end()); for( typename Data::const_iterator di = d.begin(), de = d.end(); di != de; ++di ) { BOOST_TEST( c.find(*di) != c.end() ); } typename Data::const_iterator db = d.begin(); typename Data::const_iterator da = db++; size_type old_size = c.size(); c.erase(*da); BOOST_TEST( c.size() == old_size-1 ); //This should not eras anyone size_type second_erase = c.erase_and_dispose( *da, detail::null_disposer() ); BOOST_TEST( second_erase == 0 ); BOOST_TEST( c.count(*da) == 0 ); BOOST_TEST( c.count(*db) != 0 ); BOOST_TEST( c.find(*da) == c.end() ); BOOST_TEST( c.find(*db) != c.end() ); BOOST_TEST( c.equal_range(*db).first != c.end() ); c.clear(); BOOST_TEST( c.equal_range(*da).first == c.end() ); } typedef detail::bool_::value> enabler; test_common_unordered_and_associative_container(c, d, enabler()); } template< class Container, class Data > void test_associative_container_invariants(Container & c, Data & d, boost::intrusive::detail::true_type) { typedef typename Container::const_iterator const_iterator; for( typename Data::const_iterator di = d.begin(), de = d.end(); di != de; ++di) { const_iterator ci = c.find(*di); BOOST_TEST( ci != c.end() ); BOOST_TEST( ! c.value_comp()(*ci, *di) ); const_iterator cil = c.lower_bound(*di); const_iterator ciu = c.upper_bound(*di); std::pair er = c.equal_range(*di); BOOST_TEST( cil == er.first ); BOOST_TEST( ciu == er.second ); if(ciu != c.end()){ BOOST_TEST( c.value_comp()(*cil, *ciu) ); } if(c.count(*di) > 1){ const_iterator ci_next = cil; ++ci_next; for( ; ci_next != ciu; ++cil, ++ci_next){ BOOST_TEST( !c.value_comp()(*ci_next, *cil) ); } } } } template< class Container, class Data > void test_associative_container_invariants(Container &, Data &, boost::intrusive::detail::false_type) {} template< class Container, class Data > void test_associative_container_invariants(Container & c, Data & d) { using namespace boost::intrusive; typedef typename detail::remove_const::type Type; typedef detail::bool_::value> enabler; test_associative_container_invariants(c, d, enabler()); } template< class Container, class Data > void test_associative_container(Container & c, Data & d) { typedef typename Container::const_iterator const_iterator; assert( d.size() > 2 ); c.clear(); c.insert(d.begin(),d.end()); test_associative_container_invariants(c, d); const Container & cr = c; test_associative_container_invariants(cr, d); } template< class Container, class Data > void test_unordered_associative_container_invariants(Container & c, Data & d, boost::intrusive::detail::true_type) { typedef typename Container::size_type size_type; typedef typename Container::const_iterator const_iterator; for( typename Data::const_iterator di = d.begin(), de = d.end() ; di != de ; ++di ){ const_iterator i = c.find(*di); size_type nb = c.bucket(*i); size_type bucket_elem = std::distance(c.begin(nb), c.end(nb)); BOOST_TEST( bucket_elem == c.bucket_size(nb) ); BOOST_TEST( &*c.local_iterator_to(*c.find(*di)) == &*i ); std::pair er = c.equal_range(*di); size_type cnt = std::distance(er.first, er.second); BOOST_TEST( cnt == c.count(*di)); if(cnt > 1) for(const_iterator n = er.first, i = n++, e = er.second; n != e; ++i, ++n){ BOOST_TEST( c.key_eq()(*i, *n) ); BOOST_TEST( c.hash_function()(*i) == c.hash_function()(*n) ); } } size_type blen = c.bucket_count(); size_type total_objects = 0; for(size_type i = 0; i < blen; ++i){ total_objects += c.bucket_size(i); } BOOST_TEST( total_objects == c.size() ); } template< class Container, class Data > void test_unordered_associative_container_invariants(Container &, Data &, boost::intrusive::detail::false_type) {} template< class Container, class Data > void test_unordered_associative_container_invariants(Container & c, Data & d) { using namespace boost::intrusive; typedef typename detail::remove_const::type Type; typedef detail::bool_::value> enabler; test_unordered_associative_container_invariants(c, d, enabler()); } template< class Container, class Data > void test_unordered_associative_container(Container & c, Data & d) { c.clear(); c.insert( d.begin(), d.end() ); test_unordered_associative_container_invariants(c, d); const Container & cr = c; test_unordered_associative_container_invariants(cr, d); } template< class Container, class Data > void test_unique_container(Container & c, Data & d) { typedef typename Container::value_type value_type; c.clear(); c.insert(d.begin(),d.end()); typename Container::size_type old_size = c.size(); value_type v(*d.begin()); c.insert(v); BOOST_TEST( c.size() == old_size ); c.clear(); } template< class Container, class Data > void test_non_unique_container(Container & c, Data & d) { typedef typename Container::value_type value_type; c.clear(); c.insert(d.begin(),d.end()); typename Container::size_type old_size = c.size(); value_type v(*d.begin()); c.insert(v); BOOST_TEST( c.size() == (old_size+1) ); c.clear(); } }}} #endif //#ifndef BOOST_INTRUSIVE_TEST_CONTAINER_HPP