2005-11-05 17:24:20 +00:00
// Copyright Daniel James 2005. Use, modification, and distribution are
// 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)
#include "./containers.hpp"
#define BOOST_AUTO_TEST_MAIN
#include <boost/test/auto_unit_test.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/limits.hpp>
#include <boost/test/test_tools.hpp>
#include "./helpers/unit_test.hpp"
#include "./helpers/random_values.hpp"
#include "./equivalent.hpp"
#include "./check_return_type.hpp"
typedef double comparison_type ;
// 23.1/5
template < class X , class T >
void container_tests ( X * , T * )
{
typedef typename X :: iterator iterator ;
typedef typename X :: const_iterator const_iterator ;
typedef typename X :: difference_type difference_type ;
typedef typename X :: size_type size_type ;
2005-11-09 21:11:28 +00:00
typedef typename iterator :: value_type iterator_value_type ;
typedef typename const_iterator :: value_type const_iterator_value_type ;
typedef typename iterator :: difference_type iterator_difference_type ;
typedef typename const_iterator :: difference_type const_iterator_difference_type ;
typedef typename X :: value_type value_type ;
typedef typename X :: reference reference ;
typedef typename X :: const_reference const_reference ;
BOOST_MPL_ASSERT (( boost :: is_same < value_type , T > ));
2005-11-05 17:24:20 +00:00
// TODO: Actually 'lvalue of T'/'const lvalue of T'
2005-11-09 21:11:28 +00:00
BOOST_MPL_ASSERT (( boost :: is_same < reference , T &> ));
BOOST_MPL_ASSERT (( boost :: is_same < const_reference , T const &> ));
2005-11-05 17:24:20 +00:00
// TODO: Iterator checks.
2005-11-09 21:11:28 +00:00
BOOST_MPL_ASSERT (( boost :: is_same < iterator_value_type , T > ));
2005-11-05 17:24:20 +00:00
BOOST_MPL_ASSERT_NOT (( boost :: is_same < boost :: BOOST_ITERATOR_CATEGORY < iterator > , std :: output_iterator_tag > ));
BOOST_MPL_ASSERT (( boost :: is_convertible < iterator , const_iterator > ));
2005-11-09 21:11:28 +00:00
BOOST_MPL_ASSERT (( boost :: is_same < const_iterator_value_type , T > ));
BOOST_MPL_ASSERT_NOT (( boost :: is_same < boost :: BOOST_ITERATOR_CATEGORY < const_iterator > , std :: output_iterator_tag > ));
2005-11-05 17:24:20 +00:00
BOOST_MPL_ASSERT (( boost :: mpl :: bool_ < std :: numeric_limits < difference_type >:: is_signed > ));
BOOST_MPL_ASSERT (( boost :: mpl :: bool_ < std :: numeric_limits < difference_type >:: is_integer > ));
2005-11-09 21:11:28 +00:00
BOOST_MPL_ASSERT (( boost :: is_same < iterator_difference_type , difference_type > ));
BOOST_MPL_ASSERT (( boost :: is_same < const_iterator_difference_type , difference_type > ));
2005-11-05 17:24:20 +00:00
BOOST_MPL_ASSERT_NOT (( boost :: mpl :: bool_ < std :: numeric_limits < size_type >:: is_signed > ));
BOOST_MPL_ASSERT (( boost :: mpl :: bool_ < std :: numeric_limits < size_type >:: is_integer > ));
BOOST_CHECK (( comparison_type )( std :: numeric_limits < size_type >:: max )()
> ( comparison_type )( std :: numeric_limits < difference_type >:: max )());
{
X u ;
BOOST_CHECK ( u . size () == 0 );
BOOST_CHECK ( X (). size () == 0 );
}
}
template < class X >
void container_tests2 ( X & a )
{
// 23.1/5 continued
typedef typename X :: iterator iterator ;
typedef typename X :: const_iterator const_iterator ;
typedef typename X :: difference_type difference_type ;
typedef typename X :: size_type size_type ;
2005-11-09 21:11:28 +00:00
typedef typename X :: allocator_type allocator_type ;
2005-11-05 17:24:20 +00:00
test :: unordered_equivalence_tester < X > equivalent ( a );
{
X u ( a );
equivalent . test ( u );
}
{
X u = a ;
equivalent . test ( u );
}
// Test that destructor destructs all elements (already done by test::allocator/test::member?).
{
X const & a_const = a ;
check_return_type < iterator >:: equals ( a . begin ());
check_return_type < const_iterator >:: equals ( a_const . begin ());
check_return_type < iterator >:: equals ( a . end ());
check_return_type < const_iterator >:: equals ( a_const . end ());
}
// No tests for ==, != since they're not required for unordered containers.
{
X b ;
a . swap ( b );
BOOST_CHECK ( a . empty ());
equivalent . test ( b );
a . swap ( b );
equivalent . test ( a );
BOOST_CHECK ( b . empty ());
}
{
X u ;
X & r = u ;
check_return_type < X >:: equals_ref ( r = a );
equivalent . test ( r );
}
{
check_return_type < size_type >:: equals ( a . size ());
BOOST_CHECK_EQUAL ( a . size (), ( size_type ) std :: distance ( a . begin (), a . end ()));
}
{
check_return_type < size_type >:: equals ( a . max_size ());
// TODO: Check that a.max_size() == size of the largest possible container
// How do I do that? test::allocator checks that allocations don't exceed
// that allocator's maximum size. Could check that max_size() works, and
// that max_size() + 1 doesn't. Only practicle for small max_size though -
// and it might be possible to implement unordered containers such that
// max_size() > alloc.max_size(). Or is it?
}
{
check_return_type < bool >:: convertible ( a . empty ());
BOOST_CHECK_EQUAL ( a . empty (), a . size () == 0 );
}
// 23.1/7
{
if ( a . empty ())
BOOST_CHECK ( a . begin () == a . end ());
}
// 23.1/8
{
iterator i = a . begin (), j = a . end ();
const_iterator ci = a . begin (), cj = a . end ();
if ( a . empty ()) {
BOOST_CHECK ( i == j );
BOOST_CHECK ( i == cj );
BOOST_CHECK ( ci == j );
BOOST_CHECK ( ci == cj );
BOOST_CHECK ( ! ( i != j ));
BOOST_CHECK ( ! ( i != cj ));
BOOST_CHECK ( ! ( ci != j ));
BOOST_CHECK ( ! ( ci != cj ));
}
else {
BOOST_CHECK ( ! ( i == j ));
BOOST_CHECK ( ! ( i == cj ));
BOOST_CHECK ( ! ( ci == j ));
BOOST_CHECK ( ! ( ci == cj ));
BOOST_CHECK ( i != j );
BOOST_CHECK ( i != cj );
BOOST_CHECK ( ci != j );
BOOST_CHECK ( ci != cj );
}
}
// TODO: 23.1/9 - Make sure this is checked for all constructors.
{
2005-11-09 21:11:28 +00:00
check_return_type < allocator_type >:: equals ( a . get_allocator ());
2005-11-05 17:24:20 +00:00
}
// TODO: 23.1/11 - Exception safety:
// No erase function throws an exception.
// No copy constructor or assignment operator of a returned iterator throws an exception.
// No swap() function throws an exception unless that exception is thrown by the copy constructor of assignment operator of the container's Compare object.
// No swap() function invalidates any references, pointers, or iterators referring to the elements of the containers being swapped.
//
// TODO: 21.1/12
//
// Unless otherwise specified - iterators not invalidated, values not changed.
}
BOOST_AUTO_UNIT_TEST ( basic_tests )
{
// I don't use the normal template mechanism here, as I want to specify the
// member type explicitly.
container_tests (( boost :: unordered_set < int >* ) 0 , ( int * ) 0 );
container_tests (( boost :: unordered_map < int , float >* ) 0 , ( std :: pair < int const , float >* ) 0 );
container_tests (( boost :: unordered_multiset < std :: string >* ) 0 , ( std :: string * ) 0 );
container_tests (( boost :: unordered_multimap < test :: member , char *>* ) 0 ,
( std :: pair < test :: member const , char *>* ) 0 );
}
struct test_structure { int * x ; };
META_FUNC_TEST_CASE ( basic_tests_2 , Container )
{
Container a ;
container_tests2 ( a );
{
test :: random_values < Container > values1 (( std :: min )( 10u , a . max_size ()));
Container b ( values1 . begin (), values1 . end ());
container_tests2 ( b );
}
{
test :: random_values < Container > values2 (( std :: min )( 1000u , a . max_size ()));
Container c ( values2 . begin (), values2 . end ());
container_tests2 ( c );
}
{
test :: random_values < Container > values3 (( std :: min )( 100000u , a . max_size ()));
Container d ( values3 . begin (), values3 . end ());
container_tests2 ( d );
}
}
AUTO_META_TESTS (
( basic_tests_2 ),
CONTAINER_SEQ
)