Unit tests for unordered containers.

[SVN r2731]
This commit is contained in:
Daniel James
2005-11-05 17:24:20 +00:00
parent 431c5b76e5
commit 8214c43060
59 changed files with 5242 additions and 0 deletions

63
test/Jamfile.v2 Normal file
View File

@ -0,0 +1,63 @@
# 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)
import testing ;
project unordered-test
: requirements
<toolset>intel-linux:"<cxxflags>-strict_ansi -cxxlib-icc"
# <debug-symbols>off
# TODO: Make this an option:
<define>REDUCED_TESTS
;
lib helpers
:
[ glob helpers/*.cpp ]
;
framework = helpers/<link>static /boost/test//boost_unit_test_framework ;
test-suite helpers-test
:
[ run-fail helpers-test/simple_test.cpp $(framework) ]
[ run-fail helpers-test/allocator_test.cpp $(framework) ]
[ run helpers-test/exception_test.cpp $(framework) ]
;
test-suite compile-tests
:
[ compile-fail const_local_iterator_fail_test.cpp ]
[ compile-fail const_iterator_fail_test.cpp ]
[ compile-fail set_assign_fail_test.cpp ]
[ compile type_tests.cpp ]
[ run concept_test.cpp ]
;
test-suite basic-tests
:
[ run container_tests.cpp $(framework) ]
[ run iterator_tests.cpp $(framework) ]
[ run next_prime_tests.cpp $(framework) ]
[ run max_load_factor_test.cpp $(framework) ]
;
test-suite less-base-tests
:
[ run construct_tests.cpp $(framework) ]
[ run find_tests.cpp $(framework) ]
[ run count_tests.cpp $(framework) ]
[ run equal_range_tests.cpp $(framework) ]
[ run copy_construct_tests.cpp $(framework) ]
[ run swap_tests1.cpp $(framework) ]
[ run swap_tests2.cpp $(framework) ]
[ run swap_tests3.cpp $(framework) ]
[ run assign_tests.cpp $(framework) ]
[ run clear_tests.cpp $(framework) ]
[ run erase_tests.cpp $(framework) ]
[ run insert_tests.cpp $(framework) ]
[ run map_operator_tests.cpp $(framework) ]
;

86
test/assign_tests.cpp Normal file
View File

@ -0,0 +1,86 @@
// 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 "./helpers/unit_test.hpp"
#include "./helpers/exception_test.hpp"
#include "./helpers/random_values.hpp"
#include "./helpers/constructors.hpp"
#include "./helpers/constructors.hpp"
#include "./helpers/equivalent.hpp"
#include "./invariant.hpp"
const int num_values = 50;
META_FUNC_TEST_CASE(assign_test1, Container)
{
test::constructors<Container> constructor;
test::random_values<Container> values(num_values);
Container x(values.begin(), values.end(), 0,
constructor.hasher(55), constructor.key_equal(55),
constructor.allocator(10));
x.max_load_factor(0.1);
EXCEPTION_TEST(10000)
{
DEACTIVATE_EXCEPTIONS;
Container y;
INVARIANT_CHECK(y);
ACTIVATE_EXCEPTIONS;
BOOST_CHECKPOINT("y = x");
y = x;
{
DEACTIVATE_EXCEPTIONS;
BOOST_CHECK_EQUAL(y.size(), x.size());
BOOST_CHECK(test::equivalent(y.hash_function(), x.hash_function()));
BOOST_CHECK(test::equivalent(y.key_eq(), x.key_eq()));
BOOST_CHECK_EQUAL(y.max_load_factor(), x.max_load_factor());
BOOST_CHECK(test::equivalent(y.get_allocator(), constructor.allocator()));
BOOST_CHECK(y.load_factor() <= y.max_load_factor());
test::check_invariants();
}
BOOST_CHECKPOINT("y = y");
y = y;
{
DEACTIVATE_EXCEPTIONS;
BOOST_CHECK_EQUAL(y.size(), x.size());
BOOST_CHECK(test::equivalent(y.hash_function(), x.hash_function()));
BOOST_CHECK(test::equivalent(y.key_eq(), x.key_eq()));
BOOST_CHECK_EQUAL(y.max_load_factor(), x.max_load_factor());
BOOST_CHECK(test::equivalent(y.get_allocator(), constructor.allocator()));
BOOST_CHECK(y.load_factor() <= y.max_load_factor());
test::check_invariants();
}
BOOST_CHECKPOINT("y = Container(values.begin(), values.end())");
y = Container(values.begin(), values.end());
{
DEACTIVATE_EXCEPTIONS;
BOOST_CHECK_EQUAL(y.size(), x.size());
BOOST_CHECK(test::equivalent(y.hash_function(), constructor.hasher()));
BOOST_CHECK(test::equivalent(y.key_eq(), constructor.key_equal()));
BOOST_CHECK_EQUAL(y.max_load_factor(), 1.0);
BOOST_CHECK(test::equivalent(y.get_allocator(), constructor.allocator()));
BOOST_CHECK(y.load_factor() <= 1.0);
test::check_invariants();
}
}
EXCEPTION_TEST_END
}
AUTO_META_TESTS(
(assign_test1),
CONTAINER_SEQ
)

207
test/basic_tests.cpp Normal file
View File

@ -0,0 +1,207 @@
// 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"
typedef double comparison_type;
template <class T1>
struct check_return_type
{
template <class T2>
static void equals(T2)
{
BOOST_MPL_ASSERT((boost::is_same<T1, T2>));
}
template <class T2>
static void equals_ref(T2&)
{
BOOST_MPL_ASSERT((boost::is_same<T1, T2>));
}
template <class T2>
static void convertible(T2)
{
BOOST_MPL_ASSERT((boost::is_convertible<T2, T1>));
}
};
// 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;
BOOST_MPL_ASSERT((boost::is_same<typename X::value_type, T>));
// TODO: Actually 'lvalue of T'
BOOST_MPL_ASSERT((boost::is_same<typename X::reference, T&>));
BOOST_MPL_ASSERT((boost::is_same<typename X::const_reference, T const&>));
// TODO: Iterator checks.
BOOST_MPL_ASSERT((boost::is_same<typename iterator::value_type, T>));
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>));
BOOST_MPL_ASSERT((boost::is_same<typename const_iterator::value_type, T>));
BOOST_MPL_ASSERT_NOT((boost::is_same<boost::BOOST_ITERATOR_CATEGORY<typename X::const_iterator>, std::output_iterator_tag>));
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>));
BOOST_MPL_ASSERT((boost::is_same<typename iterator::difference_type, difference_type>));
BOOST_MPL_ASSERT((boost::is_same<typename const_iterator::difference_type, difference_type>));
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);
}
}
template <class X>
void container_tests2(X& a)
{
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;
{
X u(a);
// BOOST_CHECK_EQUAL(a, u);
}
{
X u = a;
// BOOST_CHECK_EQUAL(a, u);
}
// Test that destructor destructs all elements
{
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);
a.swap(b);
}
{
X u;
X& r = u;
check_return_type<X>::equals_ref(r = a);
}
{
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());
}
{
check_return_type<bool>::convertible(a.empty());
BOOST_CHECK_EQUAL(a.empty(), a.size() == 0);
}
// TODO: member function size return number of elements.
// Semantics determined by constructors/inserts/erases.
// ie. will be tested in their tests.
// begin() returns first element.
// end() return past the end iterator.
// Can't really test this for unordered containers.
{
if(a.empty())
BOOST_CHECK(a.begin() == a.end());
}
// TODO: test that const_iterator can replace iterator in comparisons.
// TODO: test allocators
// No need to test reversible.
// Exceptions:
// No copy constructor or assignment operator of a returned iterator throws an exception.
// No swap() function invalidates any references, pointers, or iterators referring to the elements of the containers being swapped.
// Unless otherwise specified, iterators are not invalidated, and the values of objects aren't 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
)

View File

@ -0,0 +1,36 @@
// 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)
#if !defined(BOOST_UNORDERED_TESTS_CHECK_RETURN_TYPE_HEADER)
#define BOOST_UNORDERED_TESTS_CHECK_RETURN_TYPE_HEADER
#include <boost/mpl/assert.hpp>
template <class T1>
struct check_return_type
{
template <class T2>
static int equals(T2)
{
BOOST_MPL_ASSERT((boost::is_same<T1, T2>));
return 0;
}
template <class T2>
static int equals_ref(T2&)
{
BOOST_MPL_ASSERT((boost::is_same<T1, T2>));
return 0;
}
template <class T2>
static int convertible(T2)
{
BOOST_MPL_ASSERT((boost::is_convertible<T2, T1>));
return 0;
}
};
#endif

32
test/clear_tests.cpp Normal file
View File

@ -0,0 +1,32 @@
// 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 "./helpers/unit_test.hpp"
#include "./helpers/random_values.hpp"
#include "./helpers/constructors.hpp"
#include "./invariant.hpp"
META_FUNC_TEST_CASE(clear_test, Container)
{
test::constructors<Container> constructor;
test::random_values<Container> values(100);
Container x(values.begin(), values.end(), 0,
constructor.hasher(55), constructor.key_equal(55),
constructor.allocator(10));
x.clear();
BOOST_CHECK(x.empty());
test::invariant_check(x);
}
AUTO_META_TESTS(
(clear_test),
CONTAINER_SEQ
)

32
test/concept_test.cpp Normal file
View File

@ -0,0 +1,32 @@
#include <boost/concept_check.hpp>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
int main()
{
using namespace boost;
typedef boost::unordered_set<int> UnorderedSet;
typedef boost::unordered_multiset<int> UnorderedMultiSet;
typedef boost::unordered_map<int, int> UnorderedMap;
typedef boost::unordered_multimap<int, int> UnorderedMultiMap;
function_requires< UnorderedAssociativeContainerConcept<UnorderedSet> >();
function_requires< SimpleAssociativeContainerConcept<UnorderedSet> >();
function_requires< UniqueAssociativeContainerConcept<UnorderedSet> >();
function_requires< UnorderedAssociativeContainerConcept<UnorderedMultiSet> >();
function_requires< SimpleAssociativeContainerConcept<UnorderedMultiSet> >();
function_requires< MultipleAssociativeContainerConcept<UnorderedMultiSet> >();
function_requires< UnorderedAssociativeContainerConcept<UnorderedMap> >();
function_requires< UniqueAssociativeContainerConcept<UnorderedMap> >();
function_requires< PairAssociativeContainerConcept<UnorderedMap> >();
function_requires< UnorderedAssociativeContainerConcept<UnorderedMultiMap> >();
function_requires< MultipleAssociativeContainerConcept<UnorderedMultiMap> >();
function_requires< PairAssociativeContainerConcept<UnorderedMultiMap> >();
return 0;
}

View File

@ -0,0 +1,16 @@
// 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 <boost/unordered_map.hpp>
void func()
{
typedef boost::unordered_map<int, int> map;
typedef map::iterator iterator;
typedef map::const_iterator const_iterator;
const_iterator x;
iterator y(x);
}

View File

@ -0,0 +1,18 @@
// 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 <boost/unordered_map.hpp>
void func()
{
// This is only required to fail for unordered maps & multimaps as for sets
// and multisets both iterator and const_iterator are const.
typedef boost::unordered_map<int, int> map;
typedef map::local_iterator local_iterator;
typedef map::const_local_iterator const_local_iterator;
const_local_iterator x;
local_iterator y(x);
}

273
test/construct_tests.cpp Normal file
View File

@ -0,0 +1,273 @@
// 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 "./helpers/unit_test.hpp"
#include "./helpers/exception_test.hpp"
#include "./helpers/random_values.hpp"
#include "./helpers/input_iterator_adaptor.hpp"
#include "./helpers/constructors.hpp"
#include "./helpers/equivalent.hpp"
#include "./invariant.hpp"
META_FUNC_TEST_CASE(empty_construct_test1, Container)
{
test::constructors<Container> constructor;
EXCEPTION_TEST(1000)
{
// TR1 6.3.1/9 row 4
Container x(100, constructor.hasher(55), constructor.key_equal(55));
BOOST_CHECK(x.bucket_count() >= 100);
BOOST_CHECK(test::equivalent(x.hash_function(), constructor.hasher(55)));
BOOST_CHECK(test::equivalent(x.key_eq(), constructor.key_equal(55)));
// TODO: Where?
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator()));
BOOST_CHECK_EQUAL(x.max_load_factor(), 1.0);
test::invariant_check(x);
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(empty_construct_test2, Container)
{
test::constructors<Container> constructor;
EXCEPTION_TEST(1000)
{
// TR1 6.3.1/9 row 5
// I can only use the default hasher here - as it'll match the default
// key_equal.
Container x(100, constructor.hasher());
BOOST_CHECK(x.empty());
BOOST_CHECK(x.bucket_count() >= 100);
BOOST_CHECK(test::equivalent(x.hash_function(), constructor.hasher()));
BOOST_CHECK(test::equivalent(x.key_eq(), constructor.key_equal()));
// TODO: Where?
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator()));
BOOST_CHECK_EQUAL(x.max_load_factor(), 1.0);
test::invariant_check(x);
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(empty_construct_test3, Container)
{
test::constructors<Container> constructor;
EXCEPTION_TEST(1000)
{
// TR1 6.3.1/9 row 6
Container x(200);
BOOST_CHECK(x.empty());
BOOST_CHECK(x.bucket_count() >= 200);
BOOST_CHECK(test::equivalent(x.hash_function(), constructor.hasher()));
BOOST_CHECK(test::equivalent(x.key_eq(), constructor.key_equal()));
// TODO: Where?
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator()));
BOOST_CHECK_EQUAL(x.max_load_factor(), 1.0);
test::invariant_check(x);
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(empty_construct_test4, Container)
{
test::constructors<Container> constructor;
EXCEPTION_TEST(1000)
{
// TR1 6.3.1/9 row 7
Container x;
BOOST_CHECK(x.empty());
BOOST_CHECK(test::equivalent(x.hash_function(), constructor.hasher()));
BOOST_CHECK(test::equivalent(x.key_eq(), constructor.key_equal()));
// TODO: Where?
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator()));
BOOST_CHECK_EQUAL(x.max_load_factor(), 1.0);
test::invariant_check(x);
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(empty_construct_test5, Container)
{
test::constructors<Container> constructor;
EXCEPTION_TEST(1000)
{
// TODO: Where?
Container x(100, constructor.hasher(55), constructor.key_equal(55), constructor.allocator(10));
BOOST_CHECK(x.empty());
BOOST_CHECK(x.bucket_count() >= 100);
BOOST_CHECK(test::equivalent(x.hash_function(), constructor.hasher(55)));
BOOST_CHECK(test::equivalent(x.key_eq(), constructor.key_equal(55)));
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator(10)));
BOOST_CHECK_EQUAL(x.max_load_factor(), 1.0);
test::invariant_check(x);
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(range_construct_test1, Container)
{
test::constructors<Container> constructor;
test::random_values<Container> values(10);
EXCEPTION_TEST(1000)
{
// TR1 6.3.1/9 row 8
Container x(values.begin(), values.end(), 100,
constructor.hasher(55), constructor.key_equal(55));
BOOST_CHECK(x.bucket_count() >= 100);
BOOST_CHECK(test::equivalent(x.hash_function(), constructor.hasher(55)));
BOOST_CHECK(test::equivalent(x.key_eq(), constructor.key_equal(55)));
// TODO: Check that values are in container.
// TODO: Where?
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator()));
BOOST_CHECK_EQUAL(x.max_load_factor(), 1.0);
test::invariant_check(x);
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(range_construct_test2, Container)
{
test::constructors<Container> constructor;
test::random_values<Container> values(10);
EXCEPTION_TEST(1000)
{
// TR1 6.3.1/9 row 9
Container x(values.begin(), values.end(), 100, constructor.hasher());
BOOST_CHECK(x.bucket_count() >= 100);
BOOST_CHECK(test::equivalent(x.hash_function(), constructor.hasher()));
BOOST_CHECK(test::equivalent(x.key_eq(), constructor.key_equal()));
// TODO: Check that values are in container.
// TODO: Where?
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator()));
BOOST_CHECK_EQUAL(x.max_load_factor(), 1.0);
test::invariant_check(x);
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(range_construct_test3, Container)
{
test::constructors<Container> constructor;
test::random_values<Container> values(20);
EXCEPTION_TEST(1000)
{
// TR1 6.3.1/9 row 10
Container x(values.begin(), values.end(), 10);
BOOST_CHECK(x.bucket_count() >= 10);
BOOST_CHECK(test::equivalent(x.hash_function(), constructor.hasher()));
BOOST_CHECK(test::equivalent(x.key_eq(), constructor.key_equal()));
// TODO: Check that values are in container.
// TODO: Where?
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator()));
BOOST_CHECK_EQUAL(x.max_load_factor(), 1.0);
test::invariant_check(x);
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(range_construct_test4, Container)
{
test::constructors<Container> constructor;
test::random_values<Container> values(20);
EXCEPTION_TEST(1000)
{
// TR1 6.3.1/9 row 11
Container x(values.begin(), values.end());
BOOST_CHECK(test::equivalent(x.hash_function(), constructor.hasher()));
BOOST_CHECK(test::equivalent(x.key_eq(), constructor.key_equal()));
// TODO: Check that values are in container.
// TODO: Where?
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator()));
BOOST_CHECK_EQUAL(x.max_load_factor(), 1.0);
test::invariant_check(x);
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(range_construct_test5, Container)
{
test::constructors<Container> constructor;
test::random_values<Container> values(10);
EXCEPTION_TEST(1000)
{
// TODO: Where?
Container x(values.begin(), values.end(), 10,
constructor.hasher(55), constructor.key_equal(55), constructor.allocator(10));
BOOST_CHECK(x.bucket_count() >= 10);
BOOST_CHECK(test::equivalent(x.hash_function(), constructor.hasher(55)));
BOOST_CHECK(test::equivalent(x.key_eq(), constructor.key_equal(55)));
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator(10)));
BOOST_CHECK_EQUAL(x.max_load_factor(), 1.0);
test::invariant_check(x);
}
EXCEPTION_TEST_END
}
// TODO: I should probably just make all the tests run from an input iterator.
META_FUNC_TEST_CASE(input_iterator_construct_test1, Container)
{
test::random_values<Container> values(10);
EXCEPTION_TEST(1000)
{
Container x(
test::make_input_iterator(values.begin()),
test::make_input_iterator(values.end())
);
BOOST_CHECK_EQUAL(x.max_load_factor(), 1.0);
test::invariant_check(x);
}
EXCEPTION_TEST_END
}
AUTO_META_TESTS(
(empty_construct_test1)(empty_construct_test2)(empty_construct_test3)
(empty_construct_test4)(empty_construct_test5)
(range_construct_test1)(range_construct_test2)(range_construct_test3)
(range_construct_test4)(range_construct_test5)
(input_iterator_construct_test1),
CONTAINER_SEQ
)

228
test/container_tests.cpp Normal file
View File

@ -0,0 +1,228 @@
// 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;
BOOST_MPL_ASSERT((boost::is_same<typename X::value_type, T>));
// TODO: Actually 'lvalue of T'/'const lvalue of T'
BOOST_MPL_ASSERT((boost::is_same<typename X::reference, T&>));
BOOST_MPL_ASSERT((boost::is_same<typename X::const_reference, T const&>));
// TODO: Iterator checks.
BOOST_MPL_ASSERT((boost::is_same<typename iterator::value_type, T>));
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>));
BOOST_MPL_ASSERT((boost::is_same<typename const_iterator::value_type, T>));
BOOST_MPL_ASSERT_NOT((boost::is_same<boost::BOOST_ITERATOR_CATEGORY<typename X::const_iterator>, std::output_iterator_tag>));
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>));
BOOST_MPL_ASSERT((boost::is_same<typename iterator::difference_type, difference_type>));
BOOST_MPL_ASSERT((boost::is_same<typename const_iterator::difference_type, difference_type>));
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;
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.
{
check_return_type<typename X::allocator_type>::equals(a.get_allocator());
}
// 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
)

76
test/containers.hpp Normal file
View File

@ -0,0 +1,76 @@
// 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)
#if !defined(BOOST_UNORDERED_TESTS_CONTAINERS_HEADER)
#define BOOST_UNORDERED_TESTS_CONTAINERS_HEADER
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include <boost/type_traits/broken_compiler_spec.hpp>
#include <string>
#include "./helpers/allocator.hpp"
#include "./helpers/functional.hpp"
#include "./helpers/member.hpp"
typedef boost::unordered_set<
test::member
> test_set;
typedef boost::unordered_multiset<
test::member, test::hash, test::equals,
test::allocator<test::member>
> test_multiset;
typedef boost::unordered_map<
test::member, test::member, test::hash, test::equals,
test::allocator<std::pair<test::member const, test::member> >
> test_map;
typedef boost::unordered_multimap<
test::member, test::member, test::hash, test::equals,
test::minimal_allocator<std::pair<test::member const, test::member> >
> test_multimap;
typedef boost::unordered_set<
int, test::hash, test::equals,
test::allocator<int>
> set_int;
typedef boost::unordered_multiset<
std::string, test::hash, test::equals,
test::allocator<std::string>
> multiset_string;
typedef boost::unordered_map<
test::member, std::string, test::hash, test::equals,
test::allocator<std::pair<test::member const, std::string> >
> map_member_string;
typedef boost::unordered_multimap<
int, test::member, test::hash, test::equals,
test::allocator<std::pair<int const, test::member> >
> multimap_int_member;
typedef boost::unordered_map<
char, test::member, test::hash, test::equals,
test::allocator<std::pair<char const, test::member> >
> map_char_member;
typedef boost::unordered_multiset<
char, test::hash, test::equals,
test::allocator<char>
> multiset_char;
typedef std::pair<test::member, std::string> pair1;
typedef std::pair<int, test::member> pair2;
typedef std::pair<char, test::member> pair3;
BOOST_TT_BROKEN_COMPILER_SPEC(std::string)
BOOST_TT_BROKEN_COMPILER_SPEC(pair1)
BOOST_TT_BROKEN_COMPILER_SPEC(pair2)
BOOST_TT_BROKEN_COMPILER_SPEC(pair3)
BOOST_TT_BROKEN_COMPILER_SPEC(test::member)
#ifdef REDUCED_TESTS
#define CONTAINER_SEQ \
(test_set)(test_multiset)(test_map)(test_multimap)
#else
#define CONTAINER_SEQ \
(set_int)(multiset_string)(map_member_string) \
(multimap_int_member)(map_char_member)(multiset_char)
#endif
#endif

View File

@ -0,0 +1,119 @@
// 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 "./helpers/unit_test.hpp"
#include "./helpers/exception_test.hpp"
#include "./helpers/random_values.hpp"
#include "./helpers/constructors.hpp"
#include "./equivalent.hpp"
#include "./invariant.hpp"
// 23.1/5 + TR1 6.3.1/9 row 12
META_FUNC_TEST_CASE(empty_copy_test1, X)
{
X x;
test::unordered_equivalence_tester<X> equivalent(x);
EXCEPTION_TEST(1000)
{
X y(x);
equivalent.test(y);
test::invariant_check(y);
}
EXCEPTION_TEST_END
test::invariant_check(x);
}
META_FUNC_TEST_CASE(empty_copy_test2, X)
{
test::constructors<X> constructor;
X x(100, constructor.hasher(55), constructor.key_equal(55), constructor.allocator(10));
x.max_load_factor(4.0);
test::unordered_equivalence_tester<X> equivalent(x);
EXCEPTION_TEST(1000)
{
X y(x);
equivalent.test(y);
test::invariant_check(y);
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(range_copy_construct,X)
{
test::constructors<X> constructor;
test::random_values<X> values(10);
X x(values.begin(), values.end(), 100,
constructor.hasher(55), constructor.key_equal(55), constructor.allocator(10));
x.max_load_factor(4.0);
test::unordered_equivalence_tester<X> equivalent(x);
EXCEPTION_TEST(1000)
{
X y(x);
equivalent.test(y);
test::invariant_check(y);
}
EXCEPTION_TEST_END
}
template <class X>
void check_container(X const& x, test::unordered_equivalence_tester<X> const& equivalent)
{
equivalent.test(x);
test::invariant_check(x);
}
META_FUNC_TEST_CASE(anon_copy_construct, X)
{
test::constructors<X> constructor;
test::random_values<X> values(10);
X x(values.begin(), values.end(), 100,
constructor.hasher(55), constructor.key_equal(55), constructor.allocator(10));
x.max_load_factor(4.0);
test::unordered_equivalence_tester<X> equivalent(x);
EXCEPTION_TEST(1000)
{
check_container(X(x), equivalent);
}
EXCEPTION_TEST_END
}
template <class X>
X return_container(X const& x)
{
return x;
}
META_FUNC_TEST_CASE(copy_from_return,X)
{
test::random_values<X> values(10);
X x(values.begin(), values.end());
test::unordered_equivalence_tester<X> equivalent(x);
EXCEPTION_TEST(1000)
{
X y(return_container(x));
equivalent.test(y);
test::invariant_check(y);
}
EXCEPTION_TEST_END
}
AUTO_META_TESTS(
(empty_copy_test1)(empty_copy_test2)(range_copy_construct)
(anon_copy_construct)(copy_from_return),
CONTAINER_SEQ
)

65
test/count_tests.cpp Normal file
View File

@ -0,0 +1,65 @@
// 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 "./helpers/unit_test.hpp"
#include "./helpers/random_values.hpp"
META_FUNC_TEST_CASE(count_const_test, Container)
{
test::random_values<Container> values(500);
typedef typename test::random_values<Container>::iterator iterator;
Container const x(values.begin(), values.end());
for(iterator it = values.begin(); it != values.end(); ++it)
{
BOOST_CHECK_EQUAL(x.count(values.get_key(*it)), values.key_count(*it));
}
typedef typename test::random_values<Container>::value_type value_type;
test::generator<value_type> generator;
for(int i = 0; i < 500; ++i)
{
value_type value = generator();
BOOST_CHECK_EQUAL(x.count(values.get_key(value)), values.key_count(value));
}
}
META_FUNC_TEST_CASE(count_nonconst_test, Container)
{
test::random_values<Container> values(500);
typedef typename test::random_values<Container>::iterator iterator;
Container x(values.begin(), values.end());
for(iterator it = values.begin(); it != values.end(); ++it)
{
BOOST_CHECK_EQUAL(x.count(values.get_key(*it)), values.key_count(*it));
}
}
META_FUNC_TEST_CASE(empty_test, Container)
{
typedef test::random_values<Container> random_values;
typedef typename random_values::value_type value_type;
test::generator<value_type> generator;
Container x;
for(int i = 0; i < 500; ++i)
{
BOOST_CHECK_EQUAL(x.count(random_values::get_key(generator())), 0u);
}
}
AUTO_META_TESTS(
(count_const_test)(count_nonconst_test)(empty_test),
CONTAINER_SEQ
)

100
test/equal_range_tests.cpp Normal file
View File

@ -0,0 +1,100 @@
// 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 "./helpers/unit_test.hpp"
#include "./helpers/random_values.hpp"
template <class InputIt, class OutputIt, class Condition>
OutputIt copy_if(InputIt begin, InputIt end, OutputIt out, Condition cond)
{
for(;begin != end; ++begin)
{
if(cond(*begin)) {
*out = *begin;
++out;
}
}
return out;
}
template <class Iterator, class RandomValues, class Value>
void compare(std::pair<Iterator, Iterator> const& range,
RandomValues const& values, Value const& v)
{
typedef typename RandomValues::value_type value_type;
typedef std::vector<value_type> value_container;
value_container range_values(range.first, range.second);
value_container orig_values;
copy_if(values.begin(), values.end(), std::back_inserter(orig_values),
values.key_match(v));
if(values.is_unique()) {
if(orig_values.empty()) {
BOOST_CHECK_EQUAL(range_values.size(), 0u);
}
else {
BOOST_CHECK_EQUAL(range_values.size(), 1u);
BOOST_CHECK(orig_values.front() == *range_values.begin());
}
}
else {
std::sort(range_values.begin(), range_values.end());
std::sort(orig_values.begin(), orig_values.end());
BOOST_CHECK_EQUAL(range_values.size(), orig_values.size());
if(range_values.size() == orig_values.size())
BOOST_CHECK(std::equal(range_values.begin(), range_values.end(),
orig_values.begin()));
}
}
META_FUNC_TEST_CASE(const_test, Container)
{
test::random_values<Container> values(500);
typedef test::random_values<Container> random_values;
typedef typename random_values::iterator iterator;
Container const x(values.begin(), values.end());
for(iterator it = values.begin(); it != values.end(); ++it)
{
compare(x.equal_range(values.get_key(*it)),
values, values.get_key(*it));
}
typedef typename random_values::value_type value_type;
test::generator<value_type> generator;
for(int i = 0; i < 500; ++i)
{
value_type v = generator();
compare(x.equal_range(values.get_key(v)),
values, values.get_key(v));
}
}
META_FUNC_TEST_CASE(nonconst_test, Container)
{
test::random_values<Container> values(500);
typedef typename test::random_values<Container>::iterator iterator;
Container const x(values.begin(), values.end());
for(iterator it = values.begin(); it != values.end(); ++it)
{
compare(x.equal_range(values.get_key(*it)),
values, values.get_key(*it));
}
}
AUTO_META_TESTS(
(const_test)(nonconst_test),
CONTAINER_SEQ
)

112
test/equivalent.hpp Normal file
View File

@ -0,0 +1,112 @@
// 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)
#if !defined(BOOST_UNORDERED_TESTS_EQUIVALENT_HEADER)
#define BOOST_UNORDERED_TESTS_EQUIVALENT_HEADER
#include "./helpers/strong.hpp"
#include "./helpers/equivalent.hpp"
#include "./helpers/metafunctions.hpp"
#include "./helpers/less.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <vector>
#include <algorithm>
namespace test
{
struct equals2_t
{
template <class X, class Y>
bool operator()(X const& x, Y const& y)
{
return x == y;
}
template <class X1, class X2, class Y1, class Y2>
bool operator()(std::pair<X1, X2> const& x, std::pair<Y1, Y2> const& y)
{
return x.first == y.first && x.second == y.second;
}
} equals2;
template <class Container>
class unordered_equivalence_tester
{
typename Container::size_type size_;
typename Container::hasher hasher_;
typename Container::key_equal key_equal_;
float max_load_factor_;
std::vector<typename non_const_value_type<Container>::type> values_;
public:
unordered_equivalence_tester(Container const &x)
: size_(x.size()),
hasher_(x.hash_function()), key_equal_(x.key_eq()),
max_load_factor_(x.max_load_factor()),
values_(x.begin(), x.end())
{
std::sort(values_.begin(), values_.end(),
test::compare());
}
void test(Container const& x) const
{
BOOST_CHECK(size_ == x.size());
BOOST_CHECK(test::equivalent(hasher_, x.hash_function()));
BOOST_CHECK(test::equivalent(key_equal_, x.key_eq()));
BOOST_CHECK(max_load_factor_ == x.max_load_factor());
BOOST_CHECK(values_.size() == x.size());
if(values_.size() == x.size()) {
std::vector<typename non_const_value_type<Container>::type>
copy(x.begin(), x.end());
std::sort(copy.begin(), copy.end(), test::compare());
BOOST_CHECK(
std::equal(values_.begin(), values_.end(), copy.begin(),
equals2));
}
}
private:
unordered_equivalence_tester();
};
}
#if 0
namespace boost
{
template <class T, class Hash, class Pred, class Alloc>
test::strong_tester_ptr create_tester_impl(
boost::unordered_set<T, Hash, Pred, Alloc> const& x, int)
{
return test::strong_tester_ptr(new test::unordered_strong_tester<
boost::unordered_set<T, Hash, Pred, Alloc> >(x));
}
template <class T, class Hash, class Pred, class Alloc>
test::strong_tester_ptr create_tester_impl(
boost::unordered_multiset<T, Hash, Pred, Alloc> const& x, int)
{
return test::strong_tester_ptr(new test::unordered_strong_tester<
boost::unordered_multiset<T, Hash, Pred, Alloc> >(x));
}
template <class K, class T, class Hash, class Pred, class Alloc>
test::strong_tester_ptr create_tester_impl(
boost::unordered_map<K, T, Hash, Pred, Alloc> const& x, int)
{
return test::strong_tester_ptr(new test::unordered_strong_tester<
boost::unordered_map<K, T, Hash, Pred, Alloc> >(x));
}
template <class K, class T, class Hash, class Pred, class Alloc>
test::strong_tester_ptr create_tester_impl(
boost::unordered_multimap<K, T, Hash, Pred, Alloc> const& x, int)
{
return test::strong_tester_ptr(new test::unordered_strong_tester<
boost::unordered_multimap<K, T, Hash, Pred, Alloc> >(x));
}
}
#endif
#endif

190
test/erase_tests.cpp Normal file
View File

@ -0,0 +1,190 @@
// 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/next_prior.hpp>
#include "./helpers/unit_test.hpp"
#include "./helpers/exception_test.hpp"
#include "./helpers/random_values.hpp"
#include "./helpers/constructors.hpp"
#include "./invariant.hpp"
META_FUNC_TEST_CASE(range_erase_test,Container)
{
test::constructors<Container> constructor;
test::random_values<Container> values(100);
typedef typename Container::iterator iterator;
{
Container x(values.begin(), values.end(), 0,
constructor.hasher(55),
constructor.key_equal(55),
constructor.allocator(10));
const std::size_t size = x.size();
INVARIANT_CHECK(x);
iterator pos;
// Should be no throw.
ACTIVATE_EXCEPTIONS;
BOOST_CHECKPOINT("Erase nothing from the beginning");
BOOST_CHECK(x.begin() == x.erase(x.begin(), x.begin()));
BOOST_CHECK_EQUAL(x.size(), size);
test::check_invariants();
BOOST_CHECKPOINT("Erase nothing from the end");
BOOST_CHECK(x.end() == x.erase(x.end(), x.end()));
BOOST_CHECK_EQUAL(x.size(), size);
test::check_invariants();
BOOST_CHECKPOINT("Erase nothing from the middle");
BOOST_CHECK(boost::next(x.begin(), 4) == x.erase(
boost::next(x.begin(), 4),
boost::next(x.begin(), 4)));
BOOST_CHECK_EQUAL(x.size(), size);
test::check_invariants();
BOOST_CHECKPOINT("Erase 3 from the middle");
pos = x.erase(boost::next(x.begin(), 1), boost::next(x.begin(), 4));
BOOST_CHECK(boost::next(x.begin(), 1) == pos);
BOOST_CHECK_EQUAL(x.size(), size - 3);
test::check_invariants();
BOOST_CHECKPOINT("Erase all but the first 1");
pos = x.erase(boost::next(x.begin(), 1), x.end());
BOOST_CHECK(x.end() == pos);
BOOST_CHECK_EQUAL(x.size(), 1u);
test::check_invariants();
}
{
Container x(values.begin(), values.end());
const std::size_t size = x.size();
INVARIANT_CHECK(x);
iterator pos;
// Should be no throw.
ACTIVATE_EXCEPTIONS;
BOOST_CHECKPOINT("Erase first 2");
pos = x.erase(x.begin(), boost::next(x.begin(), 2));
BOOST_CHECK(x.begin() == pos);
BOOST_CHECK_EQUAL(x.size(), size - 2);
test::check_invariants();
}
{
Container x(values.begin(), values.end());
INVARIANT_CHECK(x);
iterator pos;
// Should be no throw.
ACTIVATE_EXCEPTIONS;
BOOST_CHECKPOINT("Erase all");
pos = x.erase(x.begin(), x.end());
BOOST_CHECK(x.begin() == pos && x.end() == pos);
BOOST_CHECK(x.empty());
test::check_invariants();
}
}
META_FUNC_TEST_CASE(erase_by_key_test,Container)
{
test::constructors<Container> constructor;
test::sorted_random_values<Container> values(10);
// Exceptions only from the hash function.
EXCEPTION_TEST(1000)
{
DEACTIVATE_EXCEPTIONS;
Container x(values.begin(), values.end(), 0,
constructor.hasher(55),
constructor.key_equal(55),
constructor.allocator(10));
INVARIANT_CHECK(x);
for(int i = 0; i < 10; i += values.count(values[i])) {
std::size_t key_count = values.key_count(values[i]);
{
ACTIVATE_EXCEPTIONS;
BOOST_CHECK_EQUAL(key_count,
x.erase(values.get_key(values[i])));
}
BOOST_CHECK(x.find(values.get_key(values[i])) == x.end());
BOOST_CHECK_EQUAL(0u, x.erase(values.get_key(values[i])));
}
BOOST_CHECK(x.empty());
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(erase_subrange_test,Container)
{
test::random_values<Container> values(100);
Container x(values.begin(), values.end());
// Should be no throw.
ACTIVATE_EXCEPTIONS;
typedef typename Container::const_iterator const_iterator;
typedef typename Container::iterator iterator;
std::size_t length = x.size();
std::size_t begin_index = length / 2;
std::size_t end_index = (length + begin_index) / 2;
std::size_t sub_begin_index = (end_index - begin_index) / 4;
std::size_t sub_end_index = sub_begin_index * 3;
const_iterator begin = boost::next(x.begin(), begin_index);
const_iterator end = boost::next(x.begin(), end_index);
iterator pos = x.erase(boost::next(begin, sub_begin_index),
boost::next(begin, sub_end_index));
BOOST_CHECK(pos == boost::next(x.begin(), begin_index + sub_begin_index));
BOOST_CHECK(pos == boost::next(begin, sub_begin_index));
BOOST_CHECK_EQUAL(
(end_index - begin_index) - (sub_end_index - sub_begin_index),
static_cast<std::size_t>(std::distance(begin, end)));
test::invariant_check(x);
}
META_FUNC_TEST_CASE(erase_by_iterator_test,Container)
{
test::random_values<Container> values(100);
Container x(values.begin(), values.end());
INVARIANT_CHECK(x);
std::size_t size = x.size();
typedef typename Container::iterator iterator;
// Should be no throw.
ACTIVATE_EXCEPTIONS;
while(!x.empty()) {
using namespace std;
int index = rand() % x.size();
iterator pos = x.erase(boost::next(x.begin(), index));
--size;
BOOST_CHECK_EQUAL(size, x.size());
BOOST_CHECK(boost::next(x.begin(), index) == pos);
test::check_invariants();
}
}
AUTO_META_TESTS(
(range_erase_test)(erase_by_key_test)(erase_subrange_test)
(erase_by_iterator_test),
CONTAINER_SEQ
)

78
test/find_tests.cpp Normal file
View File

@ -0,0 +1,78 @@
// 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 "./helpers/unit_test.hpp"
#include "./helpers/random_values.hpp"
META_FUNC_TEST_CASE(find_const_test,Container)
{
test::random_values<Container> values(500);
typedef typename test::random_values<Container>::iterator iterator;
Container const x(values.begin(), values.end());
for(iterator it = values.begin(); it != values.end(); ++it)
{
typename Container::const_iterator pos = x.find(values.get_key(*it));
BOOST_CHECK(pos != x.end());
BOOST_CHECK(values.get_key(*pos) == values.get_key(*it));
}
}
META_FUNC_TEST_CASE(find_nonconst_test,Container)
{
test::random_values<Container> values(500);
typedef typename test::random_values<Container>::iterator iterator;
Container x(values.begin(), values.end());
for(iterator it = values.begin(); it != values.end(); ++it)
{
typename Container::iterator pos = x.find(values.get_key(*it));
BOOST_CHECK(pos != x.end());
BOOST_CHECK(values.get_key(*pos) == values.get_key(*it));
}
}
META_FUNC_TEST_CASE(missing_test,Container)
{
test::random_values<Container> values(10);
Container x(values.begin(), values.end());
typedef typename test::random_values<Container>::value_type value_type;
test::generator<value_type> generator;
for(int i = 0; i < 500; ++i)
{
value_type const value = generator();
bool const present_in_values = values.find(value) != values.end();
bool const present_in_container = x.find(values.get_key(value))
!= x.end();
BOOST_CHECK(present_in_values == present_in_container);
}
}
META_FUNC_TEST_CASE(empty_test,Container)
{
typedef test::random_values<Container> random_values;
typedef typename random_values::value_type value_type;
test::generator<value_type> generator;
Container x;
for(int i = 0; i < 500; ++i)
{
BOOST_CHECK(x.find(random_values::get_key(generator())) == x.end());
}
}
AUTO_META_TESTS(
(find_const_test)(find_nonconst_test)(missing_test)(empty_test),
CONTAINER_SEQ
)

View File

@ -0,0 +1,12 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_ACCESSORS_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_ACCESSORS_HEADER
namespace test
{
}

209
test/helpers/allocator.cpp Normal file
View File

@ -0,0 +1,209 @@
// 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 "./config.hpp"
#include "./allocator.hpp"
#include "./exception_trigger.hpp"
#include "./exception.hpp"
#include <boost/test/test_tools.hpp>
#include <map>
#if !defined(BOOST_OLD_IOSTREAMS)
# include <ostream>
#else
# include <ostream.h>
#endif
namespace test
{
namespace
{
const unsigned int max_track = 1000;
struct allocate_details
{
int tag;
std::size_t length;
allocate_details()
: tag(0), length(0) {}
allocate_details(int t, int l)
: tag(t), length(l) {}
};
std::map<void*, allocate_details> allocate_map;
unsigned int reference_count = 0;
unsigned int alloc_count = 0;
static void ref()
{
++reference_count;
}
static void unref()
{
if(--reference_count == 0) {
BOOST_CHECK_MESSAGE(alloc_count == 0 && allocate_map.empty(),
"Memory leak found");
allocate_map.clear();
}
}
}
allocator_base::allocator_base(int x)
: tag(x)
{
ref();
}
allocator_base::allocator_base(allocator_base const& x)
: tag(x.tag)
{
ref();
}
allocator_base::~allocator_base()
{
unref();
}
allocator_base::size_type allocator_base::max_size() const
{
return (std::numeric_limits<size_type>::max)();
}
void* allocator_base::allocate(size_type n, void const*, size_type size)
{
BOOST_CHECK(n <= max_size());
exception_trigger((allocator_exception*) 0);
// TODO: This is not exception safe.
void* ptr = ::operator new(n * size);
++alloc_count;
if(allocate_map.size() < max_track)
allocate_map[ptr] = allocate_details(tag, n);
return ptr;
}
void allocator_base::construct(void* ptr)
{
exception_trigger((allocator_exception*) 0);
}
void allocator_base::destroy(void* ptr)
{
}
void allocator_base::deallocate(void* ptr, size_type n)
{
BOOST_CHECK(n <= max_size());
if(allocate_map.find(ptr) == allocate_map.end()) {
if(alloc_count <= allocate_map.size())
BOOST_ERROR("Deallocating unknown pointer.");
} else {
// TODO: This is not exception safe.
BOOST_CHECK_EQUAL(allocate_map[ptr].tag, tag);
BOOST_CHECK_EQUAL(allocate_map[ptr].length, n);
allocate_map.erase(ptr);
::operator delete(ptr);
}
--alloc_count;
}
void allocator_base::swap(allocator_base& x)
{
std::swap(tag, x. tag);
}
std::ostream& operator<<(std::ostream& out, allocator_base const& x)
{
out<<"Test Allocator("<<x.tag<<")\n";
return out;
}
bool allocator_equals(allocator_base const& x, allocator_base const& y)
{
return x.tag == y.tag;
}
//////////////////////////////////////////////////////////////////////////////
minimal_allocator_base::minimal_allocator_base(int x)
: tag(x)
{
ref();
}
minimal_allocator_base::minimal_allocator_base(minimal_allocator_base const& x)
: tag(x.tag)
{
ref();
}
minimal_allocator_base::~minimal_allocator_base()
{
unref();
}
minimal_allocator_base::size_type minimal_allocator_base::max_size() const
{
return (std::numeric_limits<size_type>::max)() / 4;
}
void* minimal_allocator_base::allocate(size_type n, void const*, size_type size)
{
BOOST_CHECK(n <= max_size());
exception_trigger((allocator_exception*) 0);
// TODO: This is not exception safe.
void* ptr = ::operator new(n * size);
allocate_map[ptr] = allocate_details(tag, n);
return ptr;
}
void minimal_allocator_base::construct(void* ptr)
{
exception_trigger((allocator_exception*) 0);
}
void minimal_allocator_base::destroy(void* ptr)
{
}
void minimal_allocator_base::deallocate(void* ptr, size_type n)
{
BOOST_CHECK(n <= max_size());
if(allocate_map.find(ptr) == allocate_map.end()) {
BOOST_ERROR("Deallocating unknown pointer.");
} else {
// TODO: This is not exception safe.
BOOST_CHECK_EQUAL(allocate_map[ptr].tag, tag);
BOOST_CHECK_EQUAL(allocate_map[ptr].length, n);
allocate_map.erase(ptr);
::operator delete(ptr);
}
}
void minimal_allocator_base::swap(minimal_allocator_base& x)
{
std::swap(tag, x. tag);
}
std::ostream& operator<<(std::ostream& out, minimal_allocator_base const& x)
{
out<<"Minimal Allocator("<<x.tag<<")\n";
return out;
}
bool allocator_equals(minimal_allocator_base const& x, minimal_allocator_base const& y)
{
return x.tag == y.tag;
}
}

376
test/helpers/allocator.hpp Normal file
View File

@ -0,0 +1,376 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_ALLOCATOR_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_ALLOCATOR_HEADER
#include <iosfwd>
#include <cstddef>
#include <boost/limits.hpp>
namespace test
{
struct allocator_base
{
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
int tag;
allocator_base(int x);
allocator_base(allocator_base const&);
~allocator_base();
size_type max_size() const;
void* allocate(size_type, void const*, size_type);
void construct(void*);
void destroy(void*);
void deallocate(void*, size_type);
void swap(allocator_base&);
private:
allocator_base& operator=(allocator_base const&);
};
std::ostream& operator<<(std::ostream&, allocator_base const&);
bool allocator_equals(allocator_base const& x, allocator_base const& y);
template <class T>
struct allocator : allocator_base
{
typedef T* pointer;
typedef T const* const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
template <class T1>
struct rebind
{
typedef allocator<T1> other;
};
pointer address(reference x) const
{
return &x;
}
const_pointer address(const_reference x) const
{
return &x;
}
allocator(int x = 1) : allocator_base(x) {}
template <class T1>
allocator(allocator<T1> const& x) : allocator_base(x) {}
allocator(allocator const& x) : allocator_base(x) {}
~allocator() {}
pointer allocate(size_type n, T const* hint = 0)
{
return static_cast<pointer>(
allocator_base::allocate(n, hint, sizeof(T)));
}
void construct(pointer ptr, T const& x)
{
allocator_base::construct(ptr);
new((void*)ptr)T(x);
}
void destroy(pointer ptr)
{
allocator_base::destroy(ptr);
ptr->~T();
}
void deallocate(pointer ptr, size_type n)
{
allocator_base::deallocate(ptr, n);
}
};
template <class T>
inline bool operator==(allocator<T> const& x, allocator<T> const& y)
{
return test::allocator_equals(x, y);
}
template <class T>
inline bool operator!=(allocator<T> const& x, allocator<T> const& y)
{
return !test::allocator_equals(x, y);
}
template <class T>
void swap(allocator<T>& x, allocator<T>& y)
{
x.swap(y);
}
template <class T>
allocator<T> create_allocator(allocator<T>*)
{
return allocator<T>();
}
template <class T>
allocator<T> create_allocator(allocator<T>*, int x)
{
return allocator<T>(x);
}
template <class T> struct minimal_allocator;
typedef unsigned short minimal_size_type;
template <class Ptr, class T>
class minimal_pointer_base
{
protected:
typedef minimal_pointer_base<Ptr, T> pointer_base;
minimal_pointer_base() : ptr_(0) {}
explicit minimal_pointer_base(T* ptr) : ptr_(ptr) {}
~minimal_pointer_base() {}
Ptr& get() { return *static_cast<Ptr*>(this); }
T* ptr_;
public:
typedef void (minimal_pointer_base::*bool_type)() const;
void this_type_does_not_support_comparisons() const {}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
Ptr& operator++() { ++ptr_; return get(); }
Ptr operator++(int) { Ptr tmp(get()); ++ptr_; return tmp; }
Ptr operator+(minimal_size_type s) const
{
return Ptr(ptr_ + s);
}
T& operator[](minimal_size_type s) const
{
return ptr_[s];
}
operator bool_type() const
{
return ptr_ ?
&minimal_pointer_base::this_type_does_not_support_comparisons
: 0;
}
bool operator!() const { return !ptr_; }
bool operator==(Ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(Ptr const& x) const { return ptr_ != x.ptr_; }
bool operator<(Ptr const& x) const { return ptr_ < x.ptr_; }
bool operator>(Ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(Ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(Ptr const& x) const { return ptr_ >= x.ptr_; }
friend std::ostream& operator<<(std::ostream& out, minimal_pointer_base const& x)
{
out<<x.ptr_;
return out;
}
};
template <class T> class minimal_pointer;
template <class T> class minimal_const_pointer;
template <class T>
class minimal_pointer
: public minimal_pointer_base<minimal_pointer<T>, T>
{
friend struct minimal_allocator<T>;
friend class minimal_pointer_base<minimal_pointer<T>, T>;
friend class minimal_const_pointer<T>;
typedef typename minimal_pointer::pointer_base base;
minimal_pointer(T* ptr) : base(ptr) {}
typedef minimal_const_pointer<T> const_pointer;
typedef minimal_pointer<T> pointer;
public:
minimal_pointer() : base() {}
bool operator==(pointer const& x) const { return base::operator==(x); }
bool operator!=(pointer const& x) const { return base::operator!=(x); }
bool operator<(pointer const& x) const { return base::operator<(x);}
bool operator>(pointer const& x) const { return base::operator>(x);}
bool operator<=(pointer const& x) const { return base::operator<=(x);}
bool operator>=(pointer const& x) const { return base::operator<=(x);}
bool operator==(const_pointer const& x) const { return x == *this; }
bool operator!=(const_pointer const& x) const { return x != *this; }
bool operator<(const_pointer const& x) const { return x > *this; }
bool operator>(const_pointer const& x) const { return x < *this; }
bool operator<=(const_pointer const& x) const { return x >= *this; }
bool operator>=(const_pointer const& x) const { return x <= *this; }
};
template <class T>
class minimal_const_pointer
: public minimal_pointer_base<minimal_const_pointer<T>, T const>
{
friend struct minimal_allocator<T>;
friend class minimal_pointer_base<minimal_const_pointer<T>, T const>;
typedef typename minimal_const_pointer::pointer_base base;
minimal_const_pointer(T* ptr) : base(ptr) {}
typedef minimal_const_pointer<T> const_pointer;
typedef minimal_pointer<T> pointer;
public:
minimal_const_pointer() : base() {}
minimal_const_pointer(minimal_pointer<T> const& x) : base(x.ptr_) {}
bool operator==(const_pointer const& x) const { return base::operator==(x); }
bool operator!=(const_pointer const& x) const { return base::operator!=(x); }
bool operator<(const_pointer const& x) const { return base::operator<(x);}
bool operator>(const_pointer const& x) const { return base::operator>(x);}
bool operator<=(const_pointer const& x) const { return base::operator<=(x);}
bool operator>=(const_pointer const& x) const { return base::operator<=(x);}
bool operator==(pointer const& x) const { return operator==(const_pointer(x)); }
bool operator!=(pointer const& x) const { return operator!=(const_pointer(x)); }
bool operator<(pointer const& x) const { return operator<(const_pointer(x));}
bool operator>(pointer const& x) const { return operator>(const_pointer(x));}
bool operator<=(pointer const& x) const { return operator<=(const_pointer(x));}
bool operator>=(pointer const& x) const { return operator<=(const_pointer(x));}
};
struct minimal_allocator_base
{
typedef minimal_size_type size_type;
typedef std::ptrdiff_t difference_type;
int tag;
minimal_allocator_base(int x);
minimal_allocator_base(minimal_allocator_base const&);
~minimal_allocator_base();
size_type max_size() const;
void* allocate(size_type, void const*, size_type);
void construct(void*);
void destroy(void*);
void deallocate(void*, size_type);
void swap(minimal_allocator_base&);
private:
minimal_allocator_base& operator=(minimal_allocator_base const&);
};
std::ostream& operator<<(std::ostream&, minimal_allocator_base const&);
bool allocator_equals(minimal_allocator_base const&, minimal_allocator_base const&);
template <class T>
struct minimal_allocator : minimal_allocator_base
{
typedef minimal_pointer<T> pointer;
typedef minimal_const_pointer<T> const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
template <class U>
struct rebind
{
typedef minimal_allocator<U> other;
};
pointer address(reference r)
{
return pointer(&r);
}
const_pointer address(const_reference r)
{
return const_pointer(&r);
}
pointer allocate(size_type n)
{
return pointer(static_cast<T*>(
minimal_allocator_base::allocate(n, 0, sizeof(T))));
}
pointer allocate(size_type n, const_pointer u)
{
return pointer(static_cast<T*>(
minimal_allocator_base::allocate(n, u.ptr_, sizeof(T))));
}
void deallocate(pointer p, size_type n)
{
minimal_allocator_base::deallocate(p.ptr_, n);
}
minimal_allocator()
: minimal_allocator_base(0)
{
}
explicit minimal_allocator(int tag)
: minimal_allocator_base(tag)
{
}
template <class Y>
minimal_allocator(minimal_allocator<Y> const& x)
: minimal_allocator_base(x)
{
}
minimal_allocator(minimal_allocator const& x)
: minimal_allocator_base(x)
{
}
void construct(pointer p, T const& t)
{
minimal_allocator_base::construct(p.ptr_);
new((void*)p.ptr_) T(t);
}
void destroy(pointer p)
{
minimal_allocator_base::destroy(p.ptr_);
((T*)p.ptr_)->~T();
}
private:
minimal_allocator& operator=(minimal_allocator const&);
};
template <class T>
inline bool operator==(minimal_allocator<T> const& x, minimal_allocator<T> const& y)
{
return test::allocator_equals(x, y);
}
template <class T>
inline bool operator!=(minimal_allocator<T> const& x, minimal_allocator<T> const& y)
{
return !test::allocator_equals(x, y);
}
template <class T>
void swap(minimal_allocator<T>& x, minimal_allocator<T>& y)
{
x.swap(y);
}
template <class T>
minimal_allocator<T> create_allocator(minimal_allocator<T>*)
{
return minimal_allocator<T>();
}
template <class T>
minimal_allocator<T> create_allocator(minimal_allocator<T>*, int x)
{
return minimal_allocator<T>(x);
}
}
#endif

31
test/helpers/base.cpp Normal file
View File

@ -0,0 +1,31 @@
// 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 "./base.hpp"
#include <vector>
#include <algorithm>
namespace test
{
namespace
{
std::vector<void(*)()> end_checks;
}
void register_end_check(void(*check)())
{
end_checks.push_back(check);
}
void call_check(void(*check)())
{
check();
}
void end()
{
std::for_each(end_checks.begin(), end_checks.end(), call_check);
}
}

15
test/helpers/base.hpp Normal file
View File

@ -0,0 +1,15 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_BASE_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_BASE_HEADER
namespace test
{
void register_end_check(void(*)());
void end();
}
#endif

18
test/helpers/config.hpp Normal file
View File

@ -0,0 +1,18 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_CONFIG_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_CONFIG_HEADER
#include <boost/config.hpp>
// From Boost.Dynamic Bitset:
// support for pre 3.0 libstdc++ - thanks Phil Edwards!
#if defined (__STL_CONFIG_H) && !defined (__STL_USE_NEW_IOSTREAMS)
# define BOOST_OLD_IOSTREAMS
#endif
#endif

View File

@ -0,0 +1,69 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_CONSTRUCTORS_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_CONSTRUCTORS_HEADER
namespace test
{
template <class Allocator>
Allocator create_allocator(Allocator*, int = 0)
{
return Allocator();
}
template <class Hasher>
Hasher create_hasher(Hasher*, int = 0)
{
return Hasher();
}
template <class KeyEqual>
KeyEqual create_key_equal(KeyEqual*, int = 0)
{
return KeyEqual();
}
template <class Container>
class constructors
{
public:
typedef typename Container::allocator_type allocator_type;
typedef typename Container::hasher hasher_type;
typedef typename Container::key_equal key_equal_type;
allocator_type allocator() const
{
return create_allocator((allocator_type*) 0);
}
allocator_type allocator(int x) const
{
return create_allocator((allocator_type*) 0, x);
}
hasher_type hasher() const
{
return create_hasher((hasher_type*) 0);
}
hasher_type hasher(int x) const
{
return create_hasher((hasher_type*) 0, x);
}
key_equal_type key_equal() const
{
return create_key_equal((key_equal_type*) 0);
}
key_equal_type key_equal(int x) const
{
return create_key_equal((key_equal_type*) 0, x);
}
};
}
#endif

View File

@ -0,0 +1,45 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_EQUIVALENT_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_EQUIVALENT_HEADER
#include <functional>
#include <boost/functional/hash.hpp>
namespace test
{
template <class T>
bool equivalent_impl(std::equal_to<T>, std::equal_to<T>, int)
{
return true;
}
template <class T>
bool equivalent_impl(boost::hash<T>, boost::hash<T>, int)
{
return true;
}
template <class T>
bool equivalent_impl(T const& x, T const& y, float)
{
return x == y;
}
template <class T>
bool equivalent(T const& x, T const& y)
{
return equivalent_impl(x, y, 0);
}
template <class X1, class X2, class Y1, class Y2>
bool equivalent(std::pair<X1, X2> const& x, std::pair<Y1, Y2> const& y)
{
return equivalent(x.first, y.first) && equivalent(x.second, y.second);
}
}
#endif

View File

@ -0,0 +1,85 @@
// 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 "./exception.hpp"
namespace test
{
exception::exception()
: message_("Triggered test exception")
{
}
exception::exception(char const* message)
: message_(message)
{
}
char const* exception::what() const throw()
{
return message_;
}
hash_exception::hash_exception()
: exception("Triggered hash exception")
{
}
hash_exception::hash_exception(char const* message)
: exception(message)
{
}
hash_copy_exception::hash_copy_exception()
: hash_exception("Triggered hash copy exception")
{
}
hash_copy_exception::hash_copy_exception(char const* message)
: hash_exception(message)
{
}
pred_exception::pred_exception()
: exception("Triggered pred exception")
{
}
pred_exception::pred_exception(char const* message)
: exception(message)
{
}
pred_copy_exception::pred_copy_exception()
: pred_exception("Triggered pred copy exception")
{
}
pred_copy_exception::pred_copy_exception(char const* message)
: pred_exception(message)
{
}
allocator_exception::allocator_exception()
: exception("Triggered pred exception")
{
}
allocator_exception::allocator_exception(char const* message)
: exception(message)
{
}
allocator_copy_exception::allocator_copy_exception()
: allocator_exception("Triggered pred copy exception")
{
}
allocator_copy_exception::allocator_copy_exception(char const* message)
: allocator_exception(message)
{
}
}

View File

@ -0,0 +1,60 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_EXCEPTION_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_EXCEPTION_HEADER
#include <exception>
namespace test
{
// Exception Handling
struct exception : std::exception
{
char const* message_;
exception();
exception(char const*);
char const* what() const throw();
};
struct hash_exception : exception
{
hash_exception();
hash_exception(char const*);
};
struct hash_copy_exception : hash_exception
{
hash_copy_exception();
hash_copy_exception(char const*);
};
struct pred_exception : exception
{
pred_exception();
pred_exception(char const*);
};
struct pred_copy_exception : pred_exception
{
pred_copy_exception();
pred_copy_exception(char const*);
};
struct allocator_exception : exception
{
allocator_exception();
allocator_exception(char const*);
};
struct allocator_copy_exception : allocator_exception
{
allocator_copy_exception();
allocator_copy_exception(char const*);
};
}
#endif

View File

@ -0,0 +1,108 @@
// 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 "./exception_test.hpp"
#include <boost/test/test_tools.hpp>
#include <cassert>
#include <cstdlib>
namespace test
{
// TODO: (Writing this here instead of the headers to avoid recompiling
// the world)
//
// There are some major design flaws with the exception testing code,
// apart from global variables that is.
namespace
{
int num_iterations = 0;
int current_iteration = 0;
int trigger_count = 0;
int max_trigger_count = 0;
bool failed = false;
bool exception_testing = false;
bool exceptions_active = false;
}
void exception_start(int n)
{
num_iterations = n;
current_iteration = 0;
max_trigger_count = 0;
trigger_count = 0;
failed = false;
exception_testing = true;
exceptions_active = true;
}
void exception_loop()
{
BOOST_CHECK(exceptions_active);
++current_iteration;
max_trigger_count = trigger_count;
exception_testing = failed;
exceptions_active = failed;
trigger_count = 0;
failed = false;
}
bool exception_loop_test()
{
if(exception_testing && current_iteration == num_iterations) {
BOOST_ERROR("Too many iterations");
return false;
}
else {
return exception_testing;
}
}
void exception_failure()
{
failed = true;
}
bool true_once()
{
++trigger_count;
return !exception_testing || trigger_count > max_trigger_count;
}
bool exception_trigger_test()
{
++trigger_count;
return exception_testing && exceptions_active
&& trigger_count > max_trigger_count;
}
void exception_trigger()
{
if(exception_trigger_test()) throw exception();
}
void exception_trigger(char const* message)
{
if(exception_trigger_test()) throw exception(message);
}
bool exceptions_activate(bool value)
{
bool old = exceptions_active;
exceptions_active = value;
return old;
}
exception_control::exception_control(bool value)
: old_value(exceptions_activate(value))
{
}
exception_control::~exception_control()
{
exceptions_activate(old_value);
}
}

View File

@ -0,0 +1,33 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_EXCEPTION_TEST_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_EXCEPTION_TEST_HEADER
#include <boost/preprocessor/cat.hpp>
#include <exception>
#include "./exception.hpp"
#include "./exception_trigger.hpp"
#include "./base.hpp"
namespace test
{
void exception_start(int);
bool exception_loop_test();
void exception_loop();
void exception_failure();
bool true_once();
}
#define EXCEPTION_TEST(count) \
for(::test::exception_start(count); ::test::exception_loop_test(); \
::test::exception_loop()) \
try
#define EXCEPTION_TEST_END \
catch(::test::exception const&) { ::test::exception_failure(); }
#endif

View File

@ -0,0 +1,49 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_EXCEPTION_TRIGGER_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_EXCEPTION_TRIGGER_HEADER
#include <boost/preprocessor/cat.hpp>
namespace test
{
// Exception Handling
bool exception_trigger_test();
void exception_trigger();
void exception_trigger(char const*);
template <class T>
void exception_trigger(T*)
{
if(exception_trigger_test()) throw T();
}
template <class T>
void exception_trigger(T*, char const* msg)
{
if(exception_trigger_test()) throw T(msg);
}
struct exception_control
{
bool old_value;
exception_control(bool);
~exception_control();
};
}
#define ACTIVATE_EXCEPTIONS \
::test::exception_control BOOST_PP_CAT(ACTIVATE_EXCEPTIONS_, __LINE__) \
(true)
#define DEACTIVATE_EXCEPTIONS \
::test::exception_control BOOST_PP_CAT(ACTIVATE_EXCEPTIONS_, __LINE__) \
(false)
#endif

140
test/helpers/functional.cpp Normal file
View File

@ -0,0 +1,140 @@
// 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 "./config.hpp"
#include "./functional.hpp"
#include "./exception.hpp"
#include "./exception_trigger.hpp"
#include <cstddef>
#include <string>
#if !defined(BOOST_OLD_IOSTREAMS)
# include <ostream>
#else
# include <ostream.h>
#endif
namespace test
{
// Hash
hash::hash(int x)
: offset(x) {}
hash::hash(hash const& x)
: offset(x.offset)
{
exception_trigger((hash_copy_exception*) 0);
}
hash& hash::operator=(hash const& x)
{
exception_trigger((hash_copy_exception*) 0);
offset = x.offset;
exception_trigger((hash_copy_exception*) 0);
return *this;
}
std::size_t hash::calculate_hash(std::size_t x) const
{
exception_trigger((hash_exception*) 0);
return x + offset;
}
std::size_t hash::operator()(char const* x) const
{
return calculate_hash(boost::hash<std::string>()(x));
}
bool hash::operator==(hash const& x) const
{
return offset == x.offset;
}
std::ostream& operator<<(std::ostream& out, hash x)
{
out<<"Test Hash("<<x.offset<<")\n";
return out;
}
hash create_hasher(hash*)
{
return hash();
}
hash create_hasher(hash*, int x)
{
return hash(x);
}
// Equals
equals::equals(int x)
: tag(x) {}
equals::equals(equals const& x)
: tag(x.tag)
{
exception_trigger((pred_copy_exception*) 0);
}
equals& equals::operator=(equals const& x)
{
exception_trigger((pred_copy_exception*) 0);
tag = x.tag;
exception_trigger((pred_copy_exception*) 0);
return *this;
}
bool equals::calculate_equals(bool x) const
{
exception_trigger((pred_exception*) 0);
return x;
}
bool equals::operator()(char const* x, char const* y) const
{
return calculate_equals(std::string(x) == std::string(y));
}
bool equals::operator==(equals const& x) const
{
return tag == x.tag;
}
std::ostream& operator<<(std::ostream& out, equals x)
{
out<<"Test Equals("<<x.tag<<")\n";
return out;
}
equals create_key_equal(equals*)
{
return equals();
}
equals create_key_equal(equals*, int x)
{
return equals(x);
}
less::less(int x)
: tag(x)
{
}
bool less::operator()(char const* x, char const* y) const
{
return std::string(x) < std::string(y);
}
std::ostream& operator<<(std::ostream& out, less x)
{
out<<"Test Less("<<x.tag<<")\n";
return out;
}
}

View File

@ -0,0 +1,80 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_FUNCTIONAL_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_FUNCTIONAL_HEADER
#include <iosfwd>
#include <boost/functional/hash.hpp>
namespace test
{
struct hash
{
int offset;
explicit hash(int x = 1);
hash(hash const&);
hash& operator=(hash const&);
std::size_t calculate_hash(std::size_t) const;
template <class T>
std::size_t operator()(T const& x) const
{
return calculate_hash(boost::hash<T>()(x));
}
std::size_t operator()(char const* x) const;
bool operator==(hash const& x) const;
};
std::ostream& operator<<(std::ostream& out, hash x);
hash create_hasher(hash*);
hash create_hasher(hash*, int x);
struct equals
{
int tag;
explicit equals(int x = 1);
equals(equals const&);
equals& operator=(equals const&);
bool calculate_equals(bool) const;
template <class T1, class T2>
bool operator()(T1 const& x, T2 const& y) const
{
return calculate_equals(x == y);
}
bool operator()(char const*, char const*) const;
bool operator==(equals const& x) const;
};
std::ostream& operator<<(std::ostream& out, equals x);
equals create_key_equal(equals*);
equals create_key_equal(equals*, int x);
struct less
{
int tag;
explicit less(int x = 0);
template <class T1, class T2>
bool operator()(T1 const& x, T2 const& y) const
{
return x < y;
}
bool operator()(char const*, char const*) const;
};
std::ostream& operator<<(std::ostream& out, less x);
}
#endif

View File

@ -0,0 +1,43 @@
// 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 "generators.hpp"
// Generators
namespace test
{
int generate(int const*)
{
using namespace std;
return rand();
}
char generate(char const*)
{
using namespace std;
return (char)(rand() % 26) + 'a';
}
std::string generate(std::string const*)
{
using namespace std;
static test::generator<char> char_gen;
std::string result;
int length = rand() % 10;
for(int i = 0; i < length; ++i)
result += char_gen();
//std::generate_n(
// std::back_inserter(result),
// rand() % 10,
// char_gen);
return result;
}
}

View File

@ -0,0 +1,41 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_GENERATORS_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_GENERATORS_HEADER
#include <cstdlib>
#include <string>
#include <utility>
namespace test
{
int generate(int const*);
char generate(char const*);
std::string generate(std::string const*);
template <class T1, class T2> std::pair<T1, T2> generate(
std::pair<T1, T2> const*);
template <class T>
struct generator
{
typedef T value_type;
value_type operator()()
{
return generate((T const*) 0);
}
};
template <class T1, class T2>
std::pair<T1, T2> generate(std::pair<T1, T2> const*)
{
static generator<T1> g1;
static generator<T2> g2;
return std::pair<T1, T2>(g1(), g2());
}
}
#endif

View File

@ -0,0 +1,35 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER
#include <boost/iterator_adaptors.hpp>
namespace test
{
template <class Iterator>
struct input_iterator_adaptor
: boost::iterator_adaptor<
input_iterator_adaptor<Iterator>, Iterator,
boost::use_default, std::input_iterator_tag>
{
typedef boost::iterator_adaptor<
input_iterator_adaptor<Iterator>, Iterator,
boost::use_default, std::input_iterator_tag> base;
explicit input_iterator_adaptor(Iterator it = Iterator())
: base(it) {}
};
template <class Iterator>
input_iterator_adaptor<Iterator> make_input_iterator(Iterator it)
{
return input_iterator_adaptor<Iterator>(it);
}
}
#endif

View File

@ -0,0 +1,54 @@
// 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 <boost/config.hpp>
#include "./invariant_checker.hpp"
#include <set>
#include <algorithm>
#include <boost/functional.hpp>
namespace test
{
namespace
{
typedef std::set<invariant_checker_base*> check_set;
check_set checks;
}
invariant_checker_base::invariant_checker_base()
{
}
invariant_checker_base::~invariant_checker_base()
{
}
void check_invariants()
{
// This was causing compile errors on Visual C++, because check
// has return type void.
//std::for_each(checks.begin(), checks.end(),
// boost::mem_fun(&invariant_checker_base::check));
check_set::iterator end = checks.end();
for(check_set::iterator it = checks.begin(); it != end; ++it)
(*it)->check();
}
void invariant_add(invariant_checker_base* check)
{
checks.insert(check);
}
void invariant_remove(invariant_checker_base* check)
{
checks.erase(check);
}
void initial_check(invariant_checker_base const& x)
{
x.check();
}
}

View File

@ -0,0 +1,78 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_INVARIANT_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_INVARIANT_HEADER
#include <boost/preprocessor/cat.hpp>
#include "./exception_trigger.hpp"
namespace test
{
struct invariant_checker_base
{
invariant_checker_base();
virtual void check() const = 0;
protected:
virtual ~invariant_checker_base();
};
void check_invariants();
void invariant_add(invariant_checker_base*);
void invariant_remove(invariant_checker_base*);
template <class T>
struct invariant_checker : invariant_checker_base
{
T& object_;
invariant_checker(T& o) : object_(o)
{
invariant_add(this);
}
~invariant_checker()
{
check();
invariant_remove(this);
}
void check() const
{
DEACTIVATE_EXCEPTIONS;
invariant_impl(object_);
}
};
// On compilers without RVO check() will be called multiple times.
// No big deal I suppose.
template <class T>
invariant_checker<T> make_invariant_checker(T& o)
{
return invariant_checker<T>(o);
}
// Calling this also prevents an unused variable warning when using
// an invariant checker.
void initial_check(::test::invariant_checker_base const&);
// A one time invariant check.
template <class T>
void invariant_check(T const& x)
{
DEACTIVATE_EXCEPTIONS;
invariant_impl(x);
}
}
#define INVARIANT_CHECK(o) \
INVARIANT_CHECK2(o, BOOST_PP_CAT(invariant_checker_, __LINE__))
#define INVARIANT_CHECK2(o, name) \
::test::invariant_checker_base const& name = \
::test::make_invariant_checker(o); \
::test::initial_check(name)
#endif

37
test/helpers/less.hpp Normal file
View File

@ -0,0 +1,37 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_LESS_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_LESS_HEADER
#include <utility>
namespace test
{
template <class T>
bool compare_impl(T const& x, T const& y, float)
{
return x < y;
}
template <class T1, class T2>
bool compare_impl(std::pair<T1, T2> const& x,
std::pair<T1, T2> const& y, int)
{
return x.first < y.first ||
(x.first == y.first && x.second < y.second);
}
struct compare {
template <class T>
bool operator()(T const& x, T const& y)
{
return compare_impl(x, y, 0);
}
};
}
#endif

79
test/helpers/member.cpp Normal file
View File

@ -0,0 +1,79 @@
// 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 "./config.hpp"
#include "./member.hpp"
#include "./exception_trigger.hpp"
#include "./generators.hpp"
#if !defined(BOOST_OLD_IOSTREAMS)
# include <ostream>
#else
# include <ostream.h>
#endif
namespace test
{
member::member(int x)
: value(x)
{
exception_trigger();
}
member::member(member const& x)
: value(x.value)
{
exception_trigger();
}
member& member::operator=(member const& x)
{
exception_trigger();
value = x.value;
exception_trigger();
return *this;
}
member::~member()
{
value = -1;
}
bool member::operator==(member const& x) const
{
exception_trigger();
return value == x.value;
}
bool member::operator<(member const& x) const
{
exception_trigger();
return value < x.value;
}
std::ostream& operator<<(std::ostream& out, member const& x)
{
out<<"Test class("<<x.value<<")";
return out;
}
test::member generate(test::member const*)
{
return test::member(test::generator<int>()());
}
}
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace test
#else
namespace boost
#endif
{
std::size_t hash_value(test::member const& x)
{
return x.value;
}
}

40
test/helpers/member.hpp Normal file
View File

@ -0,0 +1,40 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_MEMBER_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_MEMBER_HEADER
#include <iosfwd>
#include <cstddef>
namespace test
{
struct member
{
int value;
explicit member(int x = 0);
member(member const&);
member& operator=(member const&);
~member();
bool operator==(member const&) const;
bool operator<(member const&) const;
};
std::ostream& operator<<(std::ostream&, member const&);
test::member generate(test::member const*);
}
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace test
#else
namespace boost
#endif
{
std::size_t hash_value(test::member const& x);
}
#endif

View File

@ -0,0 +1,100 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_METAFUNCTIONS_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_METAFUNCTIONS_HEADER
#include <boost/config.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
namespace test
{
struct unordered_set_type { char x[100]; };
struct unordered_multiset_type { char x[200]; };
struct unordered_map_type { char x[300]; };
struct unordered_multimap_type { char x[400]; };
template <class V, class H, class P, class A>
unordered_set_type container_type(
boost::unordered_set<V, H, P, A> const*);
template <class V, class H, class P, class A>
unordered_multiset_type container_type(
boost::unordered_multiset<V, H, P, A> const*);
template <class K, class M, class H, class P, class A>
unordered_map_type container_type(
boost::unordered_map<K, M, H, P, A> const*);
template <class K, class M, class H, class P, class A>
unordered_multimap_type container_type(
boost::unordered_multimap<K, M, H, P, A> const*);
template <class Container>
struct is_set
{
BOOST_STATIC_CONSTANT(bool, value =
sizeof(container_type((Container const*)0))
== sizeof(unordered_set_type) ||
sizeof(container_type((Container const*)0))
== sizeof(unordered_multiset_type)
);
};
template <class Container>
struct is_map
{
BOOST_STATIC_CONSTANT(bool, value =
sizeof(container_type((Container const*)0))
== sizeof(unordered_map_type) ||
sizeof(container_type((Container const*)0))
== sizeof(unordered_multimap_type)
);
};
template <class Container>
struct has_unique_keys
{
BOOST_STATIC_CONSTANT(bool, value =
sizeof(container_type((Container const*)0))
== sizeof(unordered_set_type) ||
sizeof(container_type((Container const*)0))
== sizeof(unordered_map_type)
);
};
template <class Container>
struct has_equivalent_keys
{
BOOST_STATIC_CONSTANT(bool, value =
sizeof(container_type((Container const*)0))
== sizeof(unordered_multiset_type) ||
sizeof(container_type((Container const*)0))
== sizeof(unordered_multimap_type)
);
};
// Non Const Value Type
template <class Container>
struct map_non_const_value_type
{
typedef std::pair<
typename Container::key_type,
typename Container::mapped_type> type;
};
template <class Container>
struct non_const_value_type
: boost::mpl::eval_if<is_map<Container>,
map_non_const_value_type<Container>,
boost::mpl::identity<typename Container::value_type> >
{
};
}
#endif

View File

@ -0,0 +1,203 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_RANDOM_VALUES_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_RANDOM_VALUES_HEADER
#include "./generators.hpp"
#include "./metafunctions.hpp"
#include <vector>
#include <algorithm>
#include <iterator>
namespace test
{
template <class Container>
struct accessors
{
// get_key
//
// Given either the value_type or the key_type returns the key.
static typename Container::key_type const&
get_key(typename Container::key_type const& x)
{
return x;
}
template <class K, class M>
static typename Container::key_type const&
get_key(std::pair<K, M> const& x)
{
return x.first;
}
static typename Container::value_type const&
get_mapped(typename Container::key_type const& x)
{
return x;
}
template <class K, class M>
static M const&
get_mapped(std::pair<K, M> const& x)
{
return x.second;
}
};
template <class Container>
struct random_values : public accessors<Container>
{
typedef accessors<Container> base;
typedef typename non_const_value_type<Container>::type value_type;
typedef typename Container::key_type key_type;
std::vector<value_type> values_;
typedef typename std::vector<value_type>::iterator iterator;
typedef typename std::vector<value_type>::const_iterator const_iterator;
explicit random_values(std::size_t count)
{
values_.reserve(count);
std::generate_n(std::back_inserter(values_),
count, test::generator<value_type>());
}
iterator begin() { return values_.begin(); }
iterator end() { return values_.end(); }
const_iterator begin() const { return values_.begin(); }
const_iterator end() const { return values_.end(); }
value_type const& operator[](std::size_t i) const { return values_[i]; }
struct key_matcher0
{
template <class X, class Y>
bool operator()(X const& x, Y const& y) const
{
return base::get_key(x) == base::get_key(y);
}
};
// No, I don't know why didn't I just use bind.
struct key_matcher1
{
key_type x;
key_matcher1(key_type const& x) : x(x) {}
bool operator()(key_type const& y)
{
return x == y;
}
template <class M>
bool operator()(std::pair<key_type, M> const& y)
{
return x == y.first;
}
};
static key_matcher0 key_match()
{
return key_matcher0();
}
static key_matcher1 key_match(key_type const& x)
{
return key_matcher1(x);
}
template <class M>
static key_matcher1 key_match(std::pair<key_type, M> const& x)
{
return key_matcher1(x.first);
}
template <class K>
iterator find(K const& x)
{
return std::find_if(values_.begin(), values_.end(), key_match(x));
}
template <class K>
std::size_t count(K const& x)
{
return std::count_if(values_.begin(), values_.end(),
key_match(x));
}
template <class K>
std::size_t key_count(K const& x)
{
if(has_unique_keys<Container>::value)
return find(x) != values_.end();
else
return count(x);
}
static bool is_unique()
{
return has_unique_keys<Container>::value;
}
};
template <class Container>
struct sorted_random_values : public random_values<Container>
{
typedef random_values<Container> base;
typedef typename base::value_type value_type;
typedef typename base::key_type key_type;
typedef typename base::iterator iterator;
typedef typename base::const_iterator const_iterator;
explicit sorted_random_values(std::size_t count)
: base(count)
{
std::stable_sort(this->begin(), this->end());
}
struct key_compare0
{
template <class X, class Y>
bool operator()(X const& x, Y const& y) const
{
return base::get_key(x) < base::get_key(y);
}
};
static key_compare0 key_compare()
{
return key_compare0();
}
template <class K>
iterator find(K const& x)
{
iterator pos = std::lower_bound(this->begin(), this->end(), x, key_compare());
return this->key_match()(x, *pos) ? pos : this->end();
}
template <class K>
std::size_t count(K const& x)
{
std::pair<iterator, iterator> range =
std::equal_range(this->begin(), this->end(), x, key_compare());
return range.second - range.first;
}
template <class K>
std::size_t key_count(K const& x)
{
if(has_unique_keys<Container>::value)
return find(x) != this->end();
else
return count(x);
}
};
}
#endif

32
test/helpers/strong.cpp Normal file
View File

@ -0,0 +1,32 @@
// 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 "./strong.hpp"
#include <boost/test/test_tools.hpp>
namespace test
{
strong_tester::strong_tester() : dismissed_(false) {}
strong_tester::~strong_tester() { BOOST_CHECK(dismissed_); }
void strong_tester::dismiss() const { dismissed_ = true; }
bool strong_tester::is_dismissed() const { return dismissed_; }
void strong_tester::call_test() {
if(!is_dismissed())
{
DEACTIVATE_EXCEPTIONS;
try {
test();
} catch(...) {
BOOST_ERROR("Exception thrown in strong test.");
}
dismissed_ = true;
}
}
strong_test_holder::strong_test_holder(strong_tester_ptr const& x) : ptr_(x) {}
strong_test_holder::~strong_test_holder() { ptr_->call_test(); }
bool strong_test_holder::is_dismissed() const { return ptr_->is_dismissed(); }
void strong_test_holder::dismiss() { ptr_->dismiss(); }
}

78
test/helpers/strong.hpp Normal file
View File

@ -0,0 +1,78 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_STRONG_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_STRONG_HEADER
#include <boost/shared_ptr.hpp>
#include "./exception_trigger.hpp"
namespace test
{
class strong_tester
{
mutable bool dismissed_;
protected:
strong_tester();
public:
virtual ~strong_tester();
void dismiss() const;
bool is_dismissed() const;
void call_test();
virtual void test() = 0;
};
template <class T>
class default_strong_tester
: public strong_tester
{
T const& reference;
T copy;
public:
default_strong_tester(T const& x) : reference(x), copy(x) {}
void test()
{
BOOST_CHECK(reference == copy);
}
};
typedef boost::shared_ptr<strong_tester> strong_tester_ptr;
//template <class T>
//strong_tester_ptr create_tester_impl(T const& x, float)
//{
// return strong_tester_ptr(new default_strong_tester<T>(x));
//}
template <class T>
strong_tester_ptr create_tester(T const& x)
{
DEACTIVATE_EXCEPTIONS;
return create_tester_impl(x, 0);
}
class strong_test_holder
{
strong_tester_ptr ptr_;
public:
strong_test_holder(strong_tester_ptr const&);
~strong_test_holder();
bool is_dismissed() const;
void dismiss();
private:
strong_test_holder(strong_test_holder const&);
strong_test_holder& operator=(strong_test_holder const&);
};
}
#define STRONG_TEST_ANON(x) \
STRONG_TEST(BOOST_PP_CAT(STRONG_TEST_tester, __LINE__), x)
#define STRONG_TEST(tester, x) \
for(::test::strong_test_holder tester(::test::create_tester(x)); \
!tester.is_dismissed(); tester.dismiss())
#endif

View File

@ -0,0 +1,77 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_AUTO_UNIT_TEST_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_AUTO_UNIT_TEST_HEADER
#include "./base.hpp"
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/cat.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/for_each_product.hpp>
#define AUTO_UNIT_TEST(name) \
AUTO_UNIT_TEST2(name, BOOST_PP_CAT(name##_, impl))
#define AUTO_UNIT_TEST2(name, impl_name) \
void impl_name(); \
BOOST_AUTO_UNIT_TEST(name) \
{ \
impl_name(); \
::test::end(); \
} \
void impl_name()
#define AUTO_TEMPLATE_TEST(name, T, type_seq) \
AUTO_TEMPLATE_TEST2(name, BOOST_PP_CAT(name##_, impl), T, type_seq)
#define AUTO_TEMPLATE_TEST2(name, impl_name, T, type_seq) \
template <class T> \
void impl_name(); \
BOOST_PP_SEQ_FOR_EACH(AUTO_TEMPLATE_TEST_OP, name, type_seq) \
template <class T> \
void impl_name()
#define AUTO_TEMPLATE_TEST_OP(r, name, type) \
static boost::unit_test::ut_detail::auto_unit_test_registrar \
BOOST_PP_CAT(test_registrar_##name##_, type) \
( BOOST_TEST_CASE( BOOST_PP_CAT(name##_, impl)<type> ) );
#define META_FUNC_TEST_CASE(name, T) \
META_FUNC_TEST_CASE2(name, T, BOOST_PP_CAT(name##_, impl))
#define META_FUNC_TEST_CASE2(name, T, impl_name) \
template <class T> \
void impl_name(T* = 0); \
template <class T> \
void name(T* x = 0) { \
impl_name(x); \
::test::end(); \
} \
template <class T> \
void impl_name(T*)
#define RUN_TEST_OP(r, product) \
RUN_TEST_OP2( \
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(1, product)) \
), \
BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_SEQ_ELEM(1, product) \
)
#define RUN_TEST_OP2(name, test_func, type) \
BOOST_AUTO_UNIT_TEST(name) \
{ \
test_func((type*) 0); \
::test::end(); \
}
#define AUTO_META_TESTS(test_seq, param_seq) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(RUN_TEST_OP, (test_seq)(param_seq))
#endif

193
test/insert_tests.cpp Normal file
View File

@ -0,0 +1,193 @@
// 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/next_prior.hpp>
#include "./helpers/unit_test.hpp"
#include "./helpers/exception_test.hpp"
#include "./helpers/random_values.hpp"
#include "./helpers/input_iterator_adaptor.hpp"
#include "./strong.hpp"
#include "./invariant.hpp"
META_FUNC_TEST_CASE(insert_individual,Container)
{
test::random_values<Container> values(100);
EXCEPTION_TEST(1000)
{
DEACTIVATE_EXCEPTIONS;
Container x;
INVARIANT_CHECK(x);
ACTIVATE_EXCEPTIONS;
for(typename test::random_values<Container>::iterator
it = values.begin(); it != values.end(); ++it)
{
STRONG_TEST(tester, x) {
try {
x.insert(*it);
} catch(test::hash_exception) {
tester.dismiss();
throw;
}
}
DEACTIVATE_EXCEPTIONS;
typename Container::iterator pos = x.find(values.get_key(*it));
BOOST_CHECK(pos != x.end() &&
x.key_eq()(values.get_key(*pos), values.get_key(*it)));
}
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(insert_with_previous_item_hint,Container)
{
test::random_values<Container> values(10);
EXCEPTION_TEST(1000)
{
DEACTIVATE_EXCEPTIONS;
Container x;
INVARIANT_CHECK(x);
ACTIVATE_EXCEPTIONS;
typename Container::const_iterator prev = x.begin();
for(typename test::random_values<Container>::iterator
it = values.begin(); it != values.end(); ++it)
{
x.insert(prev, *it);
typename Container::iterator pos = x.find(values.get_key(*it));
BOOST_CHECK(pos != x.end() &&
x.key_eq()(values.get_key(*pos), values.get_key(*it)));
prev = pos;
}
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(insert_with_begin_hint,Container)
{
test::random_values<Container> values(10);
EXCEPTION_TEST(1000)
{
DEACTIVATE_EXCEPTIONS;
Container x;
INVARIANT_CHECK(x);
ACTIVATE_EXCEPTIONS;
for(typename test::random_values<Container>::iterator
it = values.begin(); it != values.end(); ++it)
{
x.insert(x.begin(), *it);
typename Container::iterator pos = x.find(values.get_key(*it));
BOOST_CHECK(pos != x.end() &&
x.key_eq()(values.get_key(*pos), values.get_key(*it)));
}
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(insert_with_end_hint,Container)
{
test::random_values<Container> values(10);
EXCEPTION_TEST(1000)
{
DEACTIVATE_EXCEPTIONS;
Container x;
INVARIANT_CHECK(x);
ACTIVATE_EXCEPTIONS;
for(typename test::random_values<Container>::iterator
it = values.begin(); it != values.end(); ++it)
{
x.insert(x.end(), *it);
typename Container::iterator pos = x.find(values.get_key(*it));
BOOST_CHECK(pos != x.end() &&
x.key_eq()(values.get_key(*pos), values.get_key(*it)));
}
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(insert_with_random_hint,Container)
{
test::random_values<Container> values(10);
EXCEPTION_TEST(1000)
{
DEACTIVATE_EXCEPTIONS;
Container x;
INVARIANT_CHECK(x);
ACTIVATE_EXCEPTIONS;
for(typename test::random_values<Container>::iterator
it = values.begin(); it != values.end(); ++it)
{
using namespace std;
x.insert(boost::next(x.begin(), rand() % (x.size() + 1)), *it);
typename Container::iterator pos = x.find(values.get_key(*it));
BOOST_CHECK(pos != x.end() &&
x.key_eq()(values.get_key(*pos), values.get_key(*it)));
}
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(insert_range,Container)
{
test::random_values<Container> values(10);
EXCEPTION_TEST(1000)
{
DEACTIVATE_EXCEPTIONS;
Container x;
INVARIANT_CHECK(x);
ACTIVATE_EXCEPTIONS;
x.insert(values.begin(), values.end());
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(insert_range_input_iterator,Container)
{
test::random_values<Container> values(10);
EXCEPTION_TEST(1000)
{
DEACTIVATE_EXCEPTIONS;
Container x;
INVARIANT_CHECK(x);
ACTIVATE_EXCEPTIONS;
x.insert(test::make_input_iterator(values.begin()),
test::make_input_iterator(values.end()));
}
EXCEPTION_TEST_END
}
AUTO_META_TESTS(
(insert_individual)(insert_with_previous_item_hint)(insert_with_begin_hint)
(insert_with_end_hint)(insert_with_random_hint)(insert_range)
(insert_range_input_iterator),
CONTAINER_SEQ
)

128
test/invariant.hpp Normal file
View File

@ -0,0 +1,128 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_CONTAINER_INVARIANT_HEADER)
#define BOOST_UNORDERED_TEST_CONTAINER_INVARIANT_HEADER
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <boost/test/test_tools.hpp>
#include "./helpers/invariant_checker.hpp"
#include "./helpers/functional.hpp"
namespace test
{
template <class Key, class Pred>
bool check_matches(Key const&, Pred const&)
{
return true;
}
bool check_matches(hash const& h, equals const& p)
{
// TODO: This isn't actually true - change functional so that it is.
BOOST_CHECK_EQUAL(h.offset, p.tag);
return true;
}
template <class Container>
void invariant_check_container(Container const& x)
{
// Check that the begin and end iterators match the container size.
// (And also that you can iterate through all the elements).
BOOST_CHECK_EQUAL((std::size_t) std::distance(x.begin(), x.end()),
x.size());
BOOST_CHECK(check_matches(x.hash_function(), x.key_eq()));
// It is possible for this to legally fail, eg. if you
// set max_load_factor to lower than the current load factor and
// don't give the table a chance to rehash.
BOOST_WARN(x.load_factor() <= x.max_load_factor());
}
template <class Container>
void invariant_check_set(Container const& x)
{
invariant_check_container(x);
// Check that the elements are in the correct buckets.
std::size_t count = 0;
std::size_t bucket_count = x.bucket_count();
for(std::size_t i = 0; i < bucket_count; ++i) {
std::size_t bucket_size = 0;
for(typename Container::const_local_iterator j = x.begin(i);
j != x.end(i); ++j)
{
++bucket_size;
BOOST_CHECK_EQUAL(i, x.bucket(*j));
BOOST_CHECK_EQUAL(i,
x.hash_function()(*j) % bucket_count);
}
BOOST_CHECK_EQUAL(bucket_size, x.bucket_size(i));
count += bucket_size;
}
// Check that the size matches what we've just seen.
BOOST_CHECK_EQUAL(count, x.size());
}
template <class Container>
void invariant_check_map(Container const& x)
{
invariant_check_container(x);
// Check that the elements are in the correct buckets.
std::size_t count = 0;
std::size_t bucket_count = x.bucket_count();
for(std::size_t i = 0; i < bucket_count; ++i) {
std::size_t bucket_size = 0;
for(typename Container::const_local_iterator j = x.begin(i);
j != x.end(i); ++j)
{
++bucket_size;
BOOST_CHECK_EQUAL(i, x.bucket(j->first));
BOOST_CHECK_EQUAL(i,
x.hash_function()(j->first) % bucket_count);
}
BOOST_CHECK_EQUAL(bucket_size, x.bucket_size(i));
count += bucket_size;
}
// Check that the size matches what we've just seen.
BOOST_CHECK_EQUAL(count, x.size());
}
}
namespace boost
{
template <class T, class Hash, class Pred, class Alloc>
void invariant_impl(boost::unordered_set<T, Hash, Pred, Alloc> const& x)
{
test::invariant_check_set(x);
}
template <class T, class Hash, class Pred, class Alloc>
void invariant_impl(boost::unordered_multiset<T, Hash, Pred, Alloc> const& x)
{
test::invariant_check_set(x);
}
template <class K, class T, class Hash, class Pred, class Alloc>
void invariant_impl(boost::unordered_map<K, T, Hash, Pred, Alloc> const& x)
{
test::invariant_check_map(x);
}
template <class K, class T, class Hash, class Pred, class Alloc>
void invariant_impl(boost::unordered_multimap<K, T, Hash, Pred, Alloc> const& x)
{
test::invariant_check_map(x);
}
}
#endif

141
test/iterator_tests.cpp Normal file
View File

@ -0,0 +1,141 @@
// 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 <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#define BOOST_AUTO_TEST_MAIN
#include <boost/test/auto_unit_test.hpp>
// TODO: Add these headers to new_iterator_tests.hpp
#include <boost/mpl/and.hpp>
#include <boost/detail/is_incrementable.hpp>
#include <boost/iterator/new_iterator_tests.hpp>
#include <boost/next_prior.hpp>
#include <algorithm>
#include <string>
#include "./helpers/unit_test.hpp"
BOOST_AUTO_UNIT_TEST(iterator_tests)
{
boost::unordered_set<std::pair<std::string, std::string> > set;
boost::unordered_multiset<float> multiset;
boost::unordered_map<int, int> map;
boost::unordered_multimap<char *, std::pair<int, int> > multimap;
set.insert(std::pair<std::string const, std::string>("Anthony","Cleopatra"));
set.insert(std::pair<std::string const, std::string>("Victoria","Albert"));
set.insert(std::pair<std::string const, std::string>("Pete","Dud"));
set.insert(std::pair<std::string const, std::string>("Blair","Brown"));
set.insert(std::pair<std::string const, std::string>("John","Yoko"));
set.insert(std::pair<std::string const, std::string>("Charles","Diana"));
set.insert(std::pair<std::string const, std::string>("Marx","Engels"));
set.insert(std::pair<std::string const, std::string>("Sid","Nancy"));
set.insert(std::pair<std::string const, std::string>("Lucy","Ricky"));
set.insert(std::pair<std::string const, std::string>("George","Mildred"));
set.insert(std::pair<std::string const, std::string>("Fanny","Alexander"));
set.insert(std::pair<std::string const, std::string>("Den","Angie"));
set.insert(std::pair<std::string const, std::string>("Sonny","Cher"));
set.insert(std::pair<std::string const, std::string>("Bonnie","Clyde"));
set.insert(std::pair<std::string const, std::string>("Punch","Judy"));
set.insert(std::pair<std::string const, std::string>("Powell","Pressburger"));
set.insert(std::pair<std::string const, std::string>("Jekyll","Hyde"));
multiset.insert(0.434321);
multiset.insert(443421);
multiset.insert(0.434321);
map[98] = 3;
map[99] = 4;
map[2000] = 788421;
map[2001] = 2;
static char* strings1 = "Banjo\0Banjo\0Ukulele";
static char* strings[] = {
strings1,
strings1 + 6,
strings1 + 12
};
BOOST_CHECK(std::string(strings[0]) == std::string(strings[1]));
BOOST_CHECK(strings[0] != strings[1]);
multimap.insert(std::make_pair(strings[0], std::make_pair(5,6)));
multimap.insert(std::make_pair(strings[1], std::make_pair(85,32)));
multimap.insert(std::make_pair(strings[1], std::make_pair(91,142)));
multimap.insert(std::make_pair(strings[2], std::make_pair(12,3)));
multimap.insert(std::make_pair(strings[2], std::make_pair(10,94)));
multimap.insert(std::make_pair(strings[2], std::make_pair(345,42)));
BOOST_CHECK_EQUAL(multimap.count(strings[0]), 1);
BOOST_CHECK_EQUAL(multimap.count(strings[1]), 2);
BOOST_CHECK_EQUAL(multimap.count(strings[2]), 3);
boost::forward_readable_iterator_test(set.begin(), set.end(),
*set.begin(), *boost::next(set.begin()));
boost::forward_readable_iterator_test(multiset.begin(), multiset.end(),
*multiset.begin(), *boost::next(multiset.begin()));
boost::forward_readable_iterator_test(map.begin(), map.end(),
*map.begin(), *boost::next(map.begin()));
boost::forward_readable_iterator_test(multimap.begin(), multimap.end(),
*multimap.begin(), *boost::next(multimap.begin()));
}
BOOST_AUTO_UNIT_TEST(rubbish_iterator_test)
{
typedef boost::unordered_map<int, int> map;
typedef map::local_iterator local_iterator;
typedef map::const_local_iterator const_local_iterator;
typedef map::iterator iterator;
typedef map::const_iterator const_iterator;
map m;
iterator it;
const_iterator const_it(it);
local_iterator local;
const_local_iterator const_local(local);
m[10] = 3;
m[25] = 5;
m[2] = 21;
it = m.begin();
const_it = m.begin();
map::size_type index = m.bucket(10);
local = m.begin(index);
const_local = m.begin(index);
BOOST_CHECK(it == const_it);
BOOST_CHECK(const_it == it);
BOOST_CHECK(local == const_local);
BOOST_CHECK(const_local == local);
BOOST_CHECK(it++ == const_it);
BOOST_CHECK(local++ == const_local);
BOOST_CHECK(it != const_it);
BOOST_CHECK(const_it != it);
BOOST_CHECK(local != const_local);
BOOST_CHECK(const_local != local);
BOOST_CHECK(++const_it == it);
BOOST_CHECK(++const_local == local);
it = m.begin();
int values[3];
std::pair<int const, int> const& r1= *it++;
values[0] = r1.second;
values[1] = it++->second;
values[2] = it++->second;
BOOST_CHECK(it == m.end());
std::sort(values, values+3);
BOOST_CHECK_EQUAL(values[0], 3);
BOOST_CHECK_EQUAL(values[1], 5);
BOOST_CHECK_EQUAL(values[2], 21);
}

View File

@ -0,0 +1,69 @@
// 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/next_prior.hpp>
#include "./helpers/unit_test.hpp"
#include "./helpers/exception_test.hpp"
#include "./helpers/random_values.hpp"
#include "./helpers/input_iterator_adaptor.hpp"
#include "./strong.hpp"
#include "./invariant.hpp"
// TODO: This is just the first insert test slightly modified, should do better.
META_FUNC_TEST_CASE(insert_individual,Container)
{
test::random_values<Container> values(100);
EXCEPTION_TEST(1000)
{
DEACTIVATE_EXCEPTIONS;
Container x;
INVARIANT_CHECK(x);
ACTIVATE_EXCEPTIONS;
for(typename test::random_values<Container>::iterator
it = values.begin(); it != values.end(); ++it)
{
typename Container::value_type::second_type* ref;
// Looking at TR1 I can't find this requirement anywhere, but it
// would seem silly not to require it so I think it's either an
// omission or I haven't looked hard enough.
STRONG_TEST(tester, x) {
try {
ref = &x[it->first];
} catch(test::hash_exception) {
tester.dismiss();
throw;
}
}
DEACTIVATE_EXCEPTIONS;
*ref = it->second;
typename Container::iterator pos = x.find(values.get_key(*it));
BOOST_CHECK(pos != x.end() &&
x.key_eq()(values.get_key(*pos), values.get_key(*it)) &&
test::equivalent(*it, *pos));
}
}
EXCEPTION_TEST_END
}
typedef boost::unordered_map<int, int> map1;
typedef boost::unordered_map<test::member, test::member, test::hash, test::equals, test::allocator<int> > map2;
AUTO_META_TESTS(
(insert_individual),
(map1)(map2)
)

View File

@ -0,0 +1,170 @@
// 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 <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#define BOOST_AUTO_TEST_MAIN
#include <boost/test/auto_unit_test.hpp>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/limits.hpp>
// If the bucket count is higher than the upper bounds in this file, it's not a
// bug (but it's not that great either). There are also some tests on when the
// number of buckets is increased on an insert, these tests are checking that
// some implementation details are working - if the implementation is changed
// they can be removed.
//
// TODO: the argument to max_load_factor is just a hint, so test against the
// container's actual max_load_factor.
BOOST_AUTO_UNIT_TEST(test_rehash)
{
boost::counting_iterator<int> begin(0);
boost::counting_iterator<int> end(1000);
boost::unordered_set<int> x1(begin, end);
BOOST_CHECK(x1.bucket_count() >= 1000);
BOOST_WARN(x1.bucket_count() < 2000);
x1.max_load_factor(0.5);
x1.rehash(0);
BOOST_CHECK(x1.bucket_count() >= 2000);
BOOST_WARN(x1.bucket_count() < 4000);
x1.rehash(0);
BOOST_CHECK(x1.bucket_count() >= 2000);
BOOST_WARN(x1.bucket_count() < 4000);
x1.max_load_factor(2.0);
x1.rehash(0);
BOOST_CHECK(x1.bucket_count() >= 500);
BOOST_WARN(x1.bucket_count() < 1000);
x1.rehash(1500);
BOOST_CHECK(x1.bucket_count() >= 1500);
BOOST_WARN(x1.bucket_count() < 3000);
x1.max_load_factor(0.5);
x1.rehash(0);
BOOST_CHECK(x1.bucket_count() >= 2000);
BOOST_WARN(x1.bucket_count() < 4000);
}
BOOST_AUTO_UNIT_TEST(test_insert_range)
{
boost::counting_iterator<int> begin(0);
boost::counting_iterator<int> end(1000);
boost::unordered_set<int> x1(begin, end);
BOOST_CHECK(x1.bucket_count() >= 1000);
BOOST_WARN(x1.bucket_count() < 2000);
x1.clear();
x1.max_load_factor(0.5);
x1.rehash(0);
x1.insert(begin, end);
BOOST_CHECK(x1.bucket_count() >= 2000);
BOOST_WARN(x1.bucket_count() < 4000);
x1.clear();
x1.max_load_factor(2.0);
x1.rehash(0);
x1.insert(begin, end);
BOOST_CHECK(x1.bucket_count() >= 500);
BOOST_WARN(x1.bucket_count() < 1000);
}
BOOST_AUTO_UNIT_TEST(test_insert)
{
boost::unordered_map<int, int> x1;
size_t i;
for(i = 0; i < 1000; ++i)
{
size_t old_bucket_count = x1.bucket_count();
x1[i] = i;
BOOST_CHECK(i <= x1.bucket_count());
BOOST_CHECK(x1.bucket_count() == old_bucket_count ||
x1.size() >= old_bucket_count);
// This isn't really required:
BOOST_WARN(x1.size() < x1.bucket_count());
}
x1.clear();
x1.max_load_factor(2.0);
x1.rehash(0);
for(i = 0; i < 1000; ++i)
{
size_t old_bucket_count = x1.bucket_count();
x1[i] = i;
BOOST_CHECK(i <= x1.bucket_count() * 2);
BOOST_CHECK(x1.bucket_count() == old_bucket_count ||
x1.size() >= old_bucket_count * 2);
// This isn't really required:
BOOST_WARN(x1.size() < x1.bucket_count() * 2);
}
x1.clear();
x1.rehash(0);
x1.max_load_factor(0.5);
for(i = 0; i < 1000; ++i)
{
size_t old_bucket_count = x1.bucket_count();
x1[i] = i;
BOOST_CHECK(i * 2 <= x1.bucket_count());
BOOST_CHECK(x1.bucket_count() == old_bucket_count ||
x1.size() * 2 >= old_bucket_count);
// This isn't really required:
BOOST_WARN(x1.size() * 2 < x1.bucket_count());
}
}
BOOST_AUTO_UNIT_TEST(test_large_mlf)
{
boost::unordered_set<int> x1;
x1.max_load_factor(static_cast<float>(
(std::numeric_limits<boost::unordered_set<int>::size_type>::max)()
) * 10);
boost::unordered_map<int, int>::size_type bucket_count = x1.bucket_count();
for(int i = 0; i < 1000; ++i)
{
x1.insert(i);
BOOST_CHECK(x1.bucket_count() == bucket_count);
}
boost::counting_iterator<int> begin(1000);
boost::counting_iterator<int> end(2000);
x1.insert(begin, end);
BOOST_CHECK(x1.bucket_count() == bucket_count);
}
BOOST_AUTO_UNIT_TEST(test_infinite_mlf)
{
if(std::numeric_limits<float>::has_infinity)
{
boost::unordered_set<int> x1;
x1.max_load_factor(std::numeric_limits<float>::infinity());
boost::unordered_map<int, int>::size_type bucket_count = x1.bucket_count();
for(int i = 0; i < 1000; ++i)
{
x1.insert(i);
BOOST_CHECK(x1.bucket_count() == bucket_count);
}
boost::counting_iterator<int> begin(1000);
boost::counting_iterator<int> end(2000);
x1.insert(begin, end);
BOOST_CHECK(x1.bucket_count() == bucket_count);
}
}

18
test/next_prime_tests.cpp Normal file
View File

@ -0,0 +1,18 @@
// 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 <boost/unordered/detail/hash_table.hpp>
#define BOOST_AUTO_TEST_MAIN
#include <boost/test/auto_unit_test.hpp>
BOOST_AUTO_UNIT_TEST(next_prime_test)
{
BOOST_CHECK_EQUAL(53ul, boost::unordered_detail::next_prime(0));
BOOST_CHECK_EQUAL(53ul, boost::unordered_detail::next_prime(52));
BOOST_CHECK_EQUAL(53ul, boost::unordered_detail::next_prime(53));
BOOST_CHECK_EQUAL(97ul, boost::unordered_detail::next_prime(54));
BOOST_CHECK_EQUAL(98317ul, boost::unordered_detail::next_prime(50000ul));
}

View File

@ -0,0 +1,14 @@
// 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 <boost/unordered_set.hpp>
void func()
{
boost::unordered_set<int> x;
x.insert(10);
boost::unordered_set<int>::iterator it = x.begin();
*x = 25;
}

102
test/strong.hpp Normal file
View File

@ -0,0 +1,102 @@
// 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)
#if !defined(BOOST_UNORDERED_TESTS_STRONG_HEADER)
#define BOOST_UNORDERED_TESTS_STRONG_HEADER
#include "./helpers/strong.hpp"
#include "./helpers/equivalent.hpp"
#include "./helpers/metafunctions.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <deque>
#include <algorithm>
namespace test
{
struct equals_t
{
template <class X, class Y>
bool operator()(X const& x, Y const& y)
{
return x == y;
}
template <class X1, class X2, class Y1, class Y2>
bool operator()(std::pair<X1, X2> const& x, std::pair<Y1, Y2> const& y)
{
return x.first == y.first && x.second == y.second;
}
} equals1;
template <class Container>
class unordered_strong_tester
: public strong_tester
{
Container const& reference_;
typename Container::size_type size_;
typename Container::hasher hasher_;
typename Container::key_equal key_equal_;
std::deque<typename non_const_value_type<Container>::type> values_;
public:
unordered_strong_tester(Container const &x)
: reference_(x), size_(x.size()),
hasher_(x.hash_function()), key_equal_(x.key_eq()),
values_(x.begin(), x.end())
{
}
void test()
{
BOOST_CHECK(size_ == reference_.size());
BOOST_CHECK(test::equivalent(hasher_, reference_.hash_function()));
BOOST_CHECK(test::equivalent(key_equal_, reference_.key_eq()));
BOOST_CHECK(values_.size() == reference_.size());
BOOST_CHECK(values_.size() == reference_.size() &&
std::equal(values_.begin(), values_.end(), reference_.begin(), equals1));
}
private:
unordered_strong_tester();
};
}
namespace boost
{
template <class T, class Hash, class Pred, class Alloc>
test::strong_tester_ptr create_tester_impl(
boost::unordered_set<T, Hash, Pred, Alloc> const& x, int)
{
return test::strong_tester_ptr(new test::unordered_strong_tester<
boost::unordered_set<T, Hash, Pred, Alloc> >(x));
}
template <class T, class Hash, class Pred, class Alloc>
test::strong_tester_ptr create_tester_impl(
boost::unordered_multiset<T, Hash, Pred, Alloc> const& x, int)
{
return test::strong_tester_ptr(new test::unordered_strong_tester<
boost::unordered_multiset<T, Hash, Pred, Alloc> >(x));
}
template <class K, class T, class Hash, class Pred, class Alloc>
test::strong_tester_ptr create_tester_impl(
boost::unordered_map<K, T, Hash, Pred, Alloc> const& x, int)
{
return test::strong_tester_ptr(new test::unordered_strong_tester<
boost::unordered_map<K, T, Hash, Pred, Alloc> >(x));
}
template <class K, class T, class Hash, class Pred, class Alloc>
test::strong_tester_ptr create_tester_impl(
boost::unordered_multimap<K, T, Hash, Pred, Alloc> const& x, int)
{
return test::strong_tester_ptr(new test::unordered_strong_tester<
boost::unordered_multimap<K, T, Hash, Pred, Alloc> >(x));
}
}
#endif

120
test/swap_tests.hpp Normal file
View File

@ -0,0 +1,120 @@
// 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 <stdexcept>
#include "./helpers/unit_test.hpp"
#include "./helpers/exception_test.hpp"
#include "./helpers/random_values.hpp"
#include "./helpers/constructors.hpp"
#include "./helpers/equivalent.hpp"
#include "./invariant.hpp"
META_FUNC_TEST_CASE(swap_test1, Container)
{
test::constructors<Container> constructor;
test::random_values<Container> values_x(10);
test::random_values<Container> values_y(10);
EXCEPTION_TEST(1000)
{
DEACTIVATE_EXCEPTIONS;
Container x(values_x.begin(), values_x.end(), 0,
constructor.hasher(55), constructor.key_equal(55), constructor.allocator(10));
x.max_load_factor(0.5);
Container y(values_y.begin(), values_y.end(), 0,
constructor.hasher(23), constructor.key_equal(23), constructor.allocator(12));
y.max_load_factor(2.0);
INVARIANT_CHECK(x);
INVARIANT_CHECK(y);
ACTIVATE_EXCEPTIONS;
if(BOOST_UNORDERED_SWAP_METHOD == 1
&& !test::equivalent(x.get_allocator(), y.get_allocator())) {
BOOST_CHECK_THROW(x.swap(y), std::runtime_error);
}
else {
#if BOOST_UNORDERED_SWAP_METHOD == 2
// Swap Method 2 can't meet TR1's exception specifications. Sigh.
x.swap(y);
#else
try {
x.swap(y);
}
catch (test::hash_copy_exception&) {
throw;
}
catch (test::pred_copy_exception&) {
throw;
}
catch (...) {
BOOST_ERROR("Only the copy constructor/assigned of the hash "
"and predicate objects are allowed to throw in swap.");
throw;
}
#endif
BOOST_CHECK(test::equivalent(x.hash_function(), constructor.hasher(23)));
BOOST_CHECK(test::equivalent(x.key_eq(), constructor.key_equal(23)));
BOOST_CHECK_EQUAL(x.max_load_factor(), 2.0);
#if BOOST_UNORDERED_SWAP_METHOD == 2
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator(10)));
#else
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator(12)));
#endif
BOOST_CHECK(test::equivalent(y.hash_function(), constructor.hasher(55)));
BOOST_CHECK(test::equivalent(y.key_eq(), constructor.key_equal(55)));
BOOST_CHECK_EQUAL(y.max_load_factor(), 0.5);
#if BOOST_UNORDERED_SWAP_METHOD == 2
BOOST_CHECK(test::equivalent(y.get_allocator(), constructor.allocator(12)));
#else
BOOST_CHECK(test::equivalent(y.get_allocator(), constructor.allocator(10)));
#endif
}
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(self_swap, Container)
{
test::constructors<Container> constructor;
test::random_values<Container> values_x(10);
EXCEPTION_TEST(1000)
{
DEACTIVATE_EXCEPTIONS;
Container x(values_x.begin(), values_x.end(), 0,
constructor.hasher(55), constructor.key_equal(55),
constructor.allocator(10));
x.max_load_factor(0.5);
INVARIANT_CHECK(x);
ACTIVATE_EXCEPTIONS;
x.swap(x);
BOOST_CHECK(test::equivalent(x.hash_function(), constructor.hasher(55)));
BOOST_CHECK(test::equivalent(x.key_eq(), constructor.key_equal(55)));
BOOST_CHECK_EQUAL(x.max_load_factor(), 0.5);
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator(10)));
}
EXCEPTION_TEST_END
}
AUTO_META_TESTS(
(swap_test1)(self_swap),
CONTAINER_SEQ
)

102
test/swap_tests.ipp Normal file
View File

@ -0,0 +1,102 @@
// 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 <stdexcept>
#include "./helpers/unit_test.hpp"
#include "./helpers/exception_test.hpp"
#include "./helpers/random_values.hpp"
#include "./helpers/constructors.hpp"
#include "./helpers/equivalent.hpp"
#include "./invariant.hpp"
META_FUNC_TEST_CASE(swap_test1, Container)
{
test::constructors<Container> constructor;
test::random_values<Container> values_x(10);
test::random_values<Container> values_y(10);
EXCEPTION_TEST(1000)
{
DEACTIVATE_EXCEPTIONS;
Container x(values_x.begin(), values_x.end(), 0,
constructor.hasher(55), constructor.key_equal(55), constructor.allocator(10));
x.max_load_factor(0.5);
Container y(values_y.begin(), values_y.end(), 0,
constructor.hasher(23), constructor.key_equal(23), constructor.allocator(12));
y.max_load_factor(2.0);
INVARIANT_CHECK(x);
INVARIANT_CHECK(y);
ACTIVATE_EXCEPTIONS;
if(BOOST_UNORDERED_SWAP_METHOD == 1
&& !test::equivalent(x.get_allocator(), y.get_allocator())) {
BOOST_CHECK_THROW(x.swap(y), std::runtime_error);
}
else {
x.swap(y);
BOOST_CHECK(test::equivalent(x.hash_function(), constructor.hasher(23)));
BOOST_CHECK(test::equivalent(x.key_eq(), constructor.key_equal(23)));
BOOST_CHECK_EQUAL(x.max_load_factor(), 2.0);
#if BOOST_UNORDERED_SWAP_METHOD == 2
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator(10)));
#else
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator(12)));
#endif
BOOST_CHECK(test::equivalent(y.hash_function(), constructor.hasher(55)));
BOOST_CHECK(test::equivalent(y.key_eq(), constructor.key_equal(55)));
BOOST_CHECK_EQUAL(y.max_load_factor(), 0.5);
#if BOOST_UNORDERED_SWAP_METHOD == 2
BOOST_CHECK(test::equivalent(y.get_allocator(), constructor.allocator(12)));
#else
BOOST_CHECK(test::equivalent(y.get_allocator(), constructor.allocator(10)));
#endif
}
}
EXCEPTION_TEST_END
}
META_FUNC_TEST_CASE(self_swap, Container)
{
test::constructors<Container> constructor;
test::random_values<Container> values_x(10);
EXCEPTION_TEST(1000)
{
DEACTIVATE_EXCEPTIONS;
Container x(values_x.begin(), values_x.end(), 0,
constructor.hasher(55), constructor.key_equal(55),
constructor.allocator(10));
x.max_load_factor(0.5);
INVARIANT_CHECK(x);
ACTIVATE_EXCEPTIONS;
x.swap(x);
BOOST_CHECK(test::equivalent(x.hash_function(), constructor.hasher(55)));
BOOST_CHECK(test::equivalent(x.key_eq(), constructor.key_equal(55)));
BOOST_CHECK_EQUAL(x.max_load_factor(), 0.5);
BOOST_CHECK(test::equivalent(x.get_allocator(), constructor.allocator(10)));
}
EXCEPTION_TEST_END
}
AUTO_META_TESTS(
(swap_test1)(self_swap),
CONTAINER_SEQ
)

7
test/swap_tests1.cpp Normal file
View File

@ -0,0 +1,7 @@
// 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)
#define BOOST_UNORDERED_SWAP_METHOD 1
#include "./swap_tests.hpp"

7
test/swap_tests2.cpp Normal file
View File

@ -0,0 +1,7 @@
// 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)
#define BOOST_UNORDERED_SWAP_METHOD 2
#include "./swap_tests.hpp"

7
test/swap_tests3.cpp Normal file
View File

@ -0,0 +1,7 @@
// 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)
#define BOOST_UNORDERED_SWAP_METHOD 3
#include "./swap_tests.hpp"

206
test/type_tests.cpp Normal file
View File

@ -0,0 +1,206 @@
// 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 <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/mpl/assert.hpp>
#include "./helpers/functional.hpp"
template <class Container, class Iterator>
struct iterator_checks
{
typedef Iterator iterator;
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_value<iterator>::type,
typename Container::value_type>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_reference<iterator>::type,
typename Container::reference>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_pointer<iterator>::type,
typename Container::pointer>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_difference<iterator>::type,
typename Container::difference_type>));
};
template <class Container, class ConstIterator>
struct const_iterator_checks
{
typedef ConstIterator const_iterator;
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_value<const_iterator>::type,
typename Container::value_type>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_reference<const_iterator>::type,
typename Container::const_reference>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_pointer<const_iterator>::type,
typename Container::const_pointer>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_difference<const_iterator>::type,
typename Container::difference_type>));
};
template <class Container, class Key, class Hash,
class Pred, class AllocatorType>
struct unordered_typedef_checks
{
typedef typename Container::iterator iterator;
typedef typename Container::const_iterator const_iterator;
typedef typename Container::local_iterator local_iterator;
typedef typename Container::const_local_iterator const_local_iterator;
// 6.3.1/9 rows 1-3
BOOST_MPL_ASSERT((boost::is_same<
Key,
typename Container::key_type>));
BOOST_MPL_ASSERT((boost::is_same<
Hash,
typename Container::hasher>));
BOOST_MPL_ASSERT((boost::is_same<
Pred,
typename Container::key_equal>));
// 6.3.1/9 rows 4-5
// TODO: A local_iterator may be used to iterate through a single
// bucket but may not be used to iterate across buckets.
BOOST_MPL_ASSERT((boost::is_same<
typename boost::BOOST_ITERATOR_CATEGORY<local_iterator>::type,
typename boost::BOOST_ITERATOR_CATEGORY<iterator>::type>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_value<local_iterator>::type,
typename boost::iterator_value<iterator>::type>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_difference<local_iterator>::type,
typename boost::iterator_difference<iterator>::type>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_pointer<local_iterator>::type,
typename boost::iterator_pointer<iterator>::type>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_reference<local_iterator>::type,
typename boost::iterator_reference<iterator>::type>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::BOOST_ITERATOR_CATEGORY<const_local_iterator>::type,
typename boost::BOOST_ITERATOR_CATEGORY<const_iterator>::type>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_value<const_local_iterator>::type,
typename boost::iterator_value<const_iterator>::type>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_difference<const_local_iterator>::type,
typename boost::iterator_difference<const_iterator>::type>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_pointer<const_local_iterator>::type,
typename boost::iterator_pointer<const_iterator>::type>));
BOOST_MPL_ASSERT((boost::is_same<
typename boost::iterator_reference<const_local_iterator>::type,
typename boost::iterator_reference<const_iterator>::type>));
// TODO: Is this ever specified?
BOOST_MPL_ASSERT((boost::is_same<
AllocatorType,
typename Container::allocator_type>));
BOOST_MPL_ASSERT((boost::is_same<
typename AllocatorType::pointer,
typename Container::pointer>));
BOOST_MPL_ASSERT((boost::is_same<
typename AllocatorType::const_pointer,
typename Container::const_pointer>));
BOOST_MPL_ASSERT((boost::is_same<
typename AllocatorType::reference,
typename Container::reference>));
BOOST_MPL_ASSERT((boost::is_same<
typename AllocatorType::const_reference,
typename Container::const_reference>));
};
template <class Container, class Key, class T, class Hash, class Pred, class AllocatorType>
struct unordered_map_checks
{
unordered_typedef_checks<Container, Key, Hash, Pred, AllocatorType> c1;
iterator_checks<Container, typename Container::iterator> c2;
const_iterator_checks<Container, typename Container::const_iterator> c3;
iterator_checks<Container, typename Container::local_iterator> c4;
const_iterator_checks<Container, typename Container::const_local_iterator> c5;
// 6.3.1/7
BOOST_MPL_ASSERT((boost::is_same<
typename Container::value_type,
std::pair<const typename Container::key_type, T> >));
};
template <class Container, class V, class Hash, class Pred, class AllocatorType>
struct unordered_set_checks
{
unordered_typedef_checks<Container, V, Hash, Pred, AllocatorType> c1;
const_iterator_checks<Container, typename Container::iterator> c2;
const_iterator_checks<Container, typename Container::const_iterator> c3;
const_iterator_checks<Container, typename Container::local_iterator> c4;
const_iterator_checks<Container, typename Container::const_local_iterator> c5;
// 6.3.1/7
BOOST_MPL_ASSERT((boost::is_same<
typename Container::value_type,
typename Container::key_type>));
};
unordered_set_checks<
boost::unordered_multiset<int>, int,
boost::hash<int>, std::equal_to<int>, std::allocator<int>
> int_multiset_check;
unordered_set_checks<
boost::unordered_multiset<std::string, test::hash, test::less>,
std::string, test::hash, test::less, std::allocator<std::string>
> custom_string_multiset_check;
unordered_set_checks<
boost::unordered_set<int>, int,
boost::hash<int>, std::equal_to<int>, std::allocator<int>
> int_set_check;
unordered_set_checks<
boost::unordered_set<std::string, test::hash, test::less>,
std::string, test::hash, test::less, std::allocator<std::string>
> custom_string_set_check;
unordered_map_checks<
boost::unordered_map<std::string, int>, std::string, int,
boost::hash<std::string>, std::equal_to<std::string>,
std::allocator<std::pair<std::string const, int> >
> string_int_check;
unordered_map_checks<
boost::unordered_map<char const*, std::string, test::hash, test::less>,
char const*, std::string,
test::hash, test::less,
std::allocator<std::pair<char const* const, std::string> >
> custom_check;
unordered_map_checks<
boost::unordered_multimap<int, int>,
int, int,
boost::hash<int>, std::equal_to<int>,
std::allocator<std::pair<int const, int> >
> int_int_multi_check;
unordered_map_checks<
boost::unordered_multimap<std::string, int>,
std::string, int,
boost::hash<std::string>, std::equal_to<std::string>,
std::allocator<std::pair<std::string const, int> >
> string_int_multi_check;
unordered_map_checks<
boost::unordered_multimap<float, std::string, test::hash, test::less>,
float, std::string,
test::hash, test::less,
std::allocator<std::pair<float const, std::string> >
> custom_multi_check;