forked from boostorg/unordered
Unit tests for unordered containers.
[SVN r2731]
This commit is contained in:
63
test/Jamfile.v2
Normal file
63
test/Jamfile.v2
Normal 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
86
test/assign_tests.cpp
Normal 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
207
test/basic_tests.cpp
Normal 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
|
||||
)
|
36
test/check_return_type.hpp
Normal file
36
test/check_return_type.hpp
Normal 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
32
test/clear_tests.cpp
Normal 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
32
test/concept_test.cpp
Normal 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;
|
||||
}
|
16
test/const_iterator_fail_test.cpp
Normal file
16
test/const_iterator_fail_test.cpp
Normal 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);
|
||||
}
|
18
test/const_local_iterator_fail_test.cpp
Normal file
18
test/const_local_iterator_fail_test.cpp
Normal 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
273
test/construct_tests.cpp
Normal 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
228
test/container_tests.cpp
Normal 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
76
test/containers.hpp
Normal 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
|
119
test/copy_construct_tests.cpp
Normal file
119
test/copy_construct_tests.cpp
Normal 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
65
test/count_tests.cpp
Normal 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
100
test/equal_range_tests.cpp
Normal 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
112
test/equivalent.hpp
Normal 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
190
test/erase_tests.cpp
Normal 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
78
test/find_tests.cpp
Normal 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
|
||||
)
|
12
test/helpers/accessors.hpp
Normal file
12
test/helpers/accessors.hpp
Normal 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
209
test/helpers/allocator.cpp
Normal 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
376
test/helpers/allocator.hpp
Normal 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
31
test/helpers/base.cpp
Normal 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
15
test/helpers/base.hpp
Normal 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
18
test/helpers/config.hpp
Normal 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
|
69
test/helpers/constructors.hpp
Normal file
69
test/helpers/constructors.hpp
Normal 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
|
45
test/helpers/equivalent.hpp
Normal file
45
test/helpers/equivalent.hpp
Normal 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
|
85
test/helpers/exception.cpp
Normal file
85
test/helpers/exception.cpp
Normal 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
60
test/helpers/exception.hpp
Normal file
60
test/helpers/exception.hpp
Normal 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
|
108
test/helpers/exception_test.cpp
Normal file
108
test/helpers/exception_test.cpp
Normal 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);
|
||||
}
|
||||
}
|
33
test/helpers/exception_test.hpp
Normal file
33
test/helpers/exception_test.hpp
Normal 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
|
49
test/helpers/exception_trigger.hpp
Normal file
49
test/helpers/exception_trigger.hpp
Normal 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
140
test/helpers/functional.cpp
Normal 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;
|
||||
}
|
||||
}
|
80
test/helpers/functional.hpp
Normal file
80
test/helpers/functional.hpp
Normal 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
|
43
test/helpers/generators.cpp
Normal file
43
test/helpers/generators.cpp
Normal 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;
|
||||
}
|
||||
}
|
41
test/helpers/generators.hpp
Normal file
41
test/helpers/generators.hpp
Normal 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
|
35
test/helpers/input_iterator_adaptor.hpp
Normal file
35
test/helpers/input_iterator_adaptor.hpp
Normal 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
|
||||
|
54
test/helpers/invariant_checker.cpp
Normal file
54
test/helpers/invariant_checker.cpp
Normal 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();
|
||||
}
|
||||
}
|
78
test/helpers/invariant_checker.hpp
Normal file
78
test/helpers/invariant_checker.hpp
Normal 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
37
test/helpers/less.hpp
Normal 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
79
test/helpers/member.cpp
Normal 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
40
test/helpers/member.hpp
Normal 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
|
100
test/helpers/metafunctions.hpp
Normal file
100
test/helpers/metafunctions.hpp
Normal 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
|
||||
|
203
test/helpers/random_values.hpp
Normal file
203
test/helpers/random_values.hpp
Normal 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
32
test/helpers/strong.cpp
Normal 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
78
test/helpers/strong.hpp
Normal 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
|
77
test/helpers/unit_test.hpp
Normal file
77
test/helpers/unit_test.hpp
Normal 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
193
test/insert_tests.cpp
Normal 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
128
test/invariant.hpp
Normal 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
141
test/iterator_tests.cpp
Normal 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);
|
||||
}
|
69
test/map_operator_tests.cpp
Normal file
69
test/map_operator_tests.cpp
Normal 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)
|
||||
)
|
170
test/max_load_factor_test.cpp
Normal file
170
test/max_load_factor_test.cpp
Normal 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
18
test/next_prime_tests.cpp
Normal 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));
|
||||
}
|
14
test/set_assign_fail_test.cpp
Normal file
14
test/set_assign_fail_test.cpp
Normal 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
102
test/strong.hpp
Normal 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
120
test/swap_tests.hpp
Normal 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
102
test/swap_tests.ipp
Normal 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
7
test/swap_tests1.cpp
Normal 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
7
test/swap_tests2.cpp
Normal 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
7
test/swap_tests3.cpp
Normal 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
206
test/type_tests.cpp
Normal 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;
|
Reference in New Issue
Block a user