mirror of
https://github.com/boostorg/unordered.git
synced 2025-05-11 05:23:58 +00:00
Add some tests for the unordered associative containers.
[SVN r2954]
This commit is contained in:
parent
1301d774e0
commit
1be8ab0d30
7
test/Jamfile.v2
Normal file
7
test/Jamfile.v2
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
# Copyright Daniel James 2006. 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)
|
||||
|
||||
build-project container ;
|
||||
build-project unordered ;
|
@ -14,4 +14,5 @@ test-suite container-tests
|
||||
:
|
||||
[ run set_compile.cpp ]
|
||||
[ run map_compile.cpp ]
|
||||
[ run simple_tests.cpp ]
|
||||
;
|
||||
|
75
test/helpers/equivalent.hpp
Normal file
75
test/helpers/equivalent.hpp
Normal file
@ -0,0 +1,75 @@
|
||||
|
||||
// Copyright Daniel James 2005-2006. 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 <boost/unordered_map.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include "./metafunctions.hpp"
|
||||
|
||||
namespace test
|
||||
{
|
||||
template <class T>
|
||||
bool equivalent(T const& x, T const& y) {
|
||||
return x == y;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool equivalent(boost::hash<T> const&, boost::hash<T> const&) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool equivalent(std::equal_to<T> const&, std::equal_to<T> const&) {
|
||||
return true;
|
||||
}
|
||||
|
||||
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_;
|
||||
|
||||
typedef typename non_const_value_type<Container>::type value_type;
|
||||
std::vector<value_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_()
|
||||
{
|
||||
// Can't initialise values_ straight from x because of Visual C++ 6
|
||||
values_.reserve(x.size());
|
||||
std::copy(x.begin(), x.end(), std::back_inserter(values_));
|
||||
|
||||
std::sort(values_.begin(), values_.end());
|
||||
}
|
||||
|
||||
bool operator()(Container const& x) const
|
||||
{
|
||||
if(!((size_ == x.size()) &&
|
||||
(test::equivalent(hasher_, x.hash_function())) &&
|
||||
(test::equivalent(key_equal_, x.key_eq())) &&
|
||||
(max_load_factor_ == x.max_load_factor()) &&
|
||||
(values_.size() == x.size()))) return false;
|
||||
|
||||
std::vector<value_type> copy;
|
||||
copy.reserve(x.size());
|
||||
std::copy(x.begin(), x.end(), std::back_inserter(copy));
|
||||
std::sort(copy.begin(), copy.end());
|
||||
return(std::equal(values_.begin(), values_.end(), copy.begin()));
|
||||
}
|
||||
private:
|
||||
unordered_equivalence_tester();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
20
test/helpers/fwd.hpp
Normal file
20
test/helpers/fwd.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
// Copyright Daniel James 2006. 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_FWD_HEADER)
|
||||
#define BOOST_UNORDERED_TEST_HELPERS_FWD_HEADER
|
||||
|
||||
namespace test
|
||||
{
|
||||
int generate(int const*);
|
||||
char generate(char const*);
|
||||
std::string generate(std::string*);
|
||||
float generate(float const*);
|
||||
template <class T1, class T2>
|
||||
std::pair<T1, T2> generate(std::pair<T1, T2>*);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
88
test/helpers/generators.hpp
Normal file
88
test/helpers/generators.hpp
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
// Copyright Daniel James 2005-2006. 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)
|
||||
|
||||
// A crude wrapper round Boost.Random to make life easier.
|
||||
|
||||
#if !defined(BOOST_UNORDERED_TEST_HELPERS_GENERATORS_HEADER)
|
||||
#define BOOST_UNORDERED_TEST_HELPERS_GENERATORS_HEADER
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/random/inversive_congruential.hpp>
|
||||
#include <boost/random/uniform_int.hpp>
|
||||
#include <boost/random/lagged_fibonacci.hpp>
|
||||
#include <boost/random/uniform_real.hpp>
|
||||
#include <boost/random/variate_generator.hpp>
|
||||
|
||||
#include "./fwd.hpp"
|
||||
|
||||
namespace test
|
||||
{
|
||||
typedef boost::hellekalek1995 integer_generator_type;
|
||||
typedef boost::lagged_fibonacci607 real_generator_type;
|
||||
|
||||
template <class T>
|
||||
struct generator
|
||||
{
|
||||
typedef T value_type;
|
||||
value_type operator()()
|
||||
{
|
||||
return generate((T const*) 0);
|
||||
}
|
||||
};
|
||||
|
||||
inline int generate(int const*)
|
||||
{
|
||||
static boost::variate_generator<integer_generator_type, boost::uniform_int<> >
|
||||
vg((integer_generator_type()), boost::uniform_int<>(0, 1000));
|
||||
return vg();
|
||||
}
|
||||
|
||||
inline char generate(char const*)
|
||||
{
|
||||
static boost::variate_generator<integer_generator_type, boost::uniform_int<char> >
|
||||
vg((integer_generator_type()), boost::uniform_int<char>(32, 128));
|
||||
return vg();
|
||||
}
|
||||
|
||||
inline 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;
|
||||
}
|
||||
|
||||
float generate(float const*)
|
||||
{
|
||||
static boost::variate_generator<real_generator_type, boost::uniform_real<float> >
|
||||
vg((real_generator_type()), boost::uniform_real<float>());
|
||||
return vg();
|
||||
}
|
||||
|
||||
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
|
30
test/helpers/helpers.hpp
Normal file
30
test/helpers/helpers.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
// Copyright Daniel James 2006. 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_HEADER)
|
||||
#define BOOST_UNORDERED_TEST_HELPERS_HEADER
|
||||
|
||||
namespace test
|
||||
{
|
||||
template <class Container>
|
||||
inline typename Container::key_type get_key(typename Container::key_type const& x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
template <class Container, class T>
|
||||
inline typename Container::key_type get_key(std::pair<typename Container::key_type const, T> const& x)
|
||||
{
|
||||
return x.first;
|
||||
}
|
||||
|
||||
template <class Container, class T>
|
||||
inline typename Container::key_type get_key(std::pair<typename Container::key_type, T> const& x)
|
||||
{
|
||||
return x.first;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
82
test/helpers/invariants.hpp
Normal file
82
test/helpers/invariants.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
|
||||
// Copyright Daniel James 2006. 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)
|
||||
|
||||
// This header contains metafunctions/functions to get the equivalent
|
||||
// associative container for an unordered container, and compare the contents.
|
||||
|
||||
#if !defined(BOOST_UNORDERED_TEST_HELPERS_INVARIANT_HEADER)
|
||||
#define BOOST_UNORDERED_TEST_HELPERS_INVARIANT_HEADER
|
||||
|
||||
#include <set>
|
||||
#include "./metafunctions.hpp"
|
||||
#include "./helpers.hpp"
|
||||
|
||||
namespace test
|
||||
{
|
||||
template <class X>
|
||||
void check_equivalent_keys(X const& x1)
|
||||
{
|
||||
typename X::key_equal eq = x1.key_eq();
|
||||
typedef typename X::key_type key_type;
|
||||
std::set<key_type> found_;
|
||||
|
||||
typename X::const_iterator it = x1.begin(), end = x1.end();
|
||||
typename X::size_type size = 0;
|
||||
while(it != end) {
|
||||
// First test that the current key has not occured before, required
|
||||
// to test either that keys are unique or that equivalent keys are
|
||||
// adjacent. (6.3.1/6)
|
||||
key_type key = get_key<X>(*it);
|
||||
if(found_.find(key) != found_.end())
|
||||
BOOST_ERROR("Elements with equivalent keys aren't adjacent.");
|
||||
found_.insert(key);
|
||||
|
||||
// Iterate over equivalent keys, counting them.
|
||||
unsigned int count = 0;
|
||||
do {
|
||||
++it;
|
||||
++count;
|
||||
++size;
|
||||
} while(it != end && eq(get_key<X>(*it), key));
|
||||
|
||||
// If the container has unique keys, test that there's only one.
|
||||
// Since the previous test makes sure that all equivalent keys are
|
||||
// adjacent, this is all the equivalent keys - so the test is
|
||||
// sufficient. (6.3.1/6 again).
|
||||
if(test::has_unique_keys<X>::value && count != 1)
|
||||
BOOST_ERROR("Non-unique key.");
|
||||
|
||||
if(x1.count(key) != count)
|
||||
BOOST_ERROR("Incorrect output of count.");
|
||||
|
||||
// Check that the keys are in the correct bucket and are adjacent in
|
||||
// the bucket.
|
||||
typename X::size_type bucket = x1.bucket(key);
|
||||
typename X::const_local_iterator lit = x1.begin(bucket), lend = x1.end(bucket);
|
||||
for(; lit != lend && !eq(get_key<X>(*lit), key); ++lit) continue;
|
||||
if(lit == lend)
|
||||
BOOST_ERROR("Unable to find element with a local_iterator");
|
||||
unsigned int count2 = 0;
|
||||
for(; lit != lend && eq(get_key<X>(*lit), key); ++lit) ++count2;
|
||||
if(count != count2)
|
||||
BOOST_ERROR("Element count doesn't match local_iterator.");
|
||||
for(; lit != lend; ++lit) {
|
||||
if(eq(get_key<X>(*lit), key)) {
|
||||
BOOST_ERROR("Non-adjacent element with equivalent key in bucket.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Finally, check that size matches up.
|
||||
if(x1.size() != size)
|
||||
BOOST_ERROR("x1.size() doesn't match actual size.");
|
||||
if(static_cast<float>(size) / x1.bucket_count() != x1.load_factor())
|
||||
BOOST_ERROR("x1.load_factor() doesn't match actual load_factor.");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
103
test/helpers/metafunctions.hpp
Normal file
103
test/helpers/metafunctions.hpp
Normal file
@ -0,0 +1,103 @@
|
||||
|
||||
// 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/type_traits/is_same.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/bool.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
|
||||
: public boost::is_same<
|
||||
typename Container::key_type,
|
||||
typename Container::value_type> {};
|
||||
|
||||
template <class Container>
|
||||
struct is_map
|
||||
: public boost::mpl::not_<is_set<Container> > {};
|
||||
|
||||
struct yes_type { char x[100]; };
|
||||
struct no_type { char x[200]; };
|
||||
|
||||
template <class V, class H, class P, class A>
|
||||
yes_type has_unique_key_impl(
|
||||
boost::unordered_set<V, H, P, A> const*);
|
||||
template <class V, class H, class P, class A>
|
||||
no_type has_unique_key_impl(
|
||||
boost::unordered_multiset<V, H, P, A> const*);
|
||||
template <class K, class M, class H, class P, class A>
|
||||
yes_type has_unique_key_impl(
|
||||
boost::unordered_map<K, M, H, P, A> const*);
|
||||
template <class K, class M, class H, class P, class A>
|
||||
no_type has_unique_key_impl(
|
||||
boost::unordered_multimap<K, M, H, P, A> const*);
|
||||
|
||||
template <class Container>
|
||||
struct has_unique_keys
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value =
|
||||
sizeof(has_unique_key_impl((Container const*)0))
|
||||
== sizeof(yes_type));
|
||||
};
|
||||
|
||||
template <class Container>
|
||||
struct has_equivalent_keys
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value =
|
||||
sizeof(has_unique_key_impl((Container const*)0))
|
||||
== sizeof(no_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
|
||||
|
29
test/helpers/random_values.hpp
Normal file
29
test/helpers/random_values.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
// Copyright Daniel James 2005-2006. 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 <vector>
|
||||
#include <algorithm>
|
||||
#include "./generators.hpp"
|
||||
#include "./metafunctions.hpp"
|
||||
|
||||
namespace test
|
||||
{
|
||||
template <class X>
|
||||
struct random_values
|
||||
: public std::vector<typename non_const_value_type<X>::type>
|
||||
{
|
||||
random_values(int count) {
|
||||
typedef typename non_const_value_type<X>::type value_type;
|
||||
static test::generator<value_type> gen;
|
||||
this->reserve(count);
|
||||
std::generate_n(std::back_inserter(*this), count, gen);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
146
test/helpers/tracker.hpp
Normal file
146
test/helpers/tracker.hpp
Normal file
@ -0,0 +1,146 @@
|
||||
|
||||
// Copyright Daniel James 2006. 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)
|
||||
|
||||
// This header contains metafunctions/functions to get the equivalent
|
||||
// associative container for an unordered container, and compare the contents.
|
||||
|
||||
#if !defined(BOOST_UNORDERED_TEST_HELPERS_TRACKER_HEADER)
|
||||
#define BOOST_UNORDERED_TEST_HELPERS_TRACKER_HEADER
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include "../objects/fwd.hpp"
|
||||
#include "./metafunctions.hpp"
|
||||
#include "./helpers.hpp"
|
||||
|
||||
namespace test
|
||||
{
|
||||
template <class X>
|
||||
struct equals_to_compare
|
||||
{
|
||||
typedef std::less<typename X::first_argument_type> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct equals_to_compare<test::equal_to>
|
||||
{
|
||||
typedef test::less type;
|
||||
};
|
||||
|
||||
template <class X1, class X2>
|
||||
void compare_range(X1 const& x1, X2 const& x2)
|
||||
{
|
||||
typedef typename non_const_value_type<X1>::type value_type;
|
||||
std::vector<value_type> values1, values2;
|
||||
values1.reserve(x1.size());
|
||||
values2.reserve(x2.size());
|
||||
std::copy(x1.begin(), x1.end(), std::back_inserter(values1));
|
||||
std::copy(x2.begin(), x2.end(), std::back_inserter(values2));
|
||||
std::sort(values1.begin(), values1.end());
|
||||
std::sort(values2.begin(), values2.end());
|
||||
BOOST_TEST(values1 == values2);
|
||||
}
|
||||
|
||||
template <class X1, class X2, class T>
|
||||
void compare_pairs(X1 const& x1, X2 const& x2, T*)
|
||||
{
|
||||
std::vector<T> values1, values2;
|
||||
values1.reserve(std::distance(x1.first, x1.second));
|
||||
values2.reserve(std::distance(x2.first, x2.second));
|
||||
std::copy(x1.first, x1.second, std::back_inserter(values1));
|
||||
std::copy(x2.first, x2.second, std::back_inserter(values2));
|
||||
std::sort(values1.begin(), values1.end());
|
||||
std::sort(values2.begin(), values2.end());
|
||||
BOOST_TEST(values1 == values2);
|
||||
}
|
||||
|
||||
template <class X>
|
||||
struct ordered_set
|
||||
: public boost::mpl::if_<
|
||||
test::has_unique_keys<X>,
|
||||
std::set<typename X::value_type,
|
||||
typename equals_to_compare<typename X::key_equal>::type>,
|
||||
std::multiset<typename X::value_type,
|
||||
typename equals_to_compare<typename X::key_equal>::type>
|
||||
> {};
|
||||
|
||||
template <class X>
|
||||
struct ordered_map
|
||||
: public boost::mpl::if_<
|
||||
test::has_unique_keys<X>,
|
||||
std::map<typename X::key_type, typename X::mapped_type,
|
||||
typename equals_to_compare<typename X::key_equal>::type>,
|
||||
std::multimap<typename X::key_type, typename X::mapped_type,
|
||||
typename equals_to_compare<typename X::key_equal>::type>
|
||||
> {};
|
||||
|
||||
template <class X>
|
||||
struct ordered_base
|
||||
: public boost::mpl::eval_if<
|
||||
test::is_set<X>,
|
||||
test::ordered_set<X>,
|
||||
test::ordered_map<X> >
|
||||
{
|
||||
};
|
||||
|
||||
template <class X>
|
||||
class ordered : public ordered_base<X>::type
|
||||
{
|
||||
typedef typename ordered_base<X>::type base;
|
||||
public:
|
||||
typedef typename base::key_compare key_compare;
|
||||
|
||||
ordered()
|
||||
: base()
|
||||
{}
|
||||
|
||||
explicit ordered(key_compare const& compare)
|
||||
: base(compare)
|
||||
{}
|
||||
|
||||
void compare(X const& x)
|
||||
{
|
||||
compare_range(x, *this);
|
||||
}
|
||||
|
||||
void compare_key(X const& x, typename X::value_type const& val)
|
||||
{
|
||||
compare_pairs(
|
||||
x.equal_range(get_key<X>(val)),
|
||||
this->equal_range(get_key<X>(val)),
|
||||
(typename non_const_value_type<X>::type*) 0
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Equals>
|
||||
typename equals_to_compare<Equals>::type create_compare(
|
||||
Equals equals)
|
||||
{
|
||||
return typename equals_to_compare<Equals>::type();
|
||||
}
|
||||
|
||||
template <class X>
|
||||
ordered<X> create_ordered(X const& container)
|
||||
{
|
||||
return ordered<X>(create_compare(container.key_eq()));
|
||||
}
|
||||
|
||||
template <class X1, class X2>
|
||||
void check_container(X1 const& container, X2 const& values)
|
||||
{
|
||||
ordered<X1> tracker = create_ordered(container);
|
||||
tracker.insert(values.begin(), values.end());
|
||||
tracker.compare(container);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
18
test/objects/fwd.hpp
Normal file
18
test/objects/fwd.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
// Copyright Daniel James 2006. 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_FWD_HEADER)
|
||||
#define BOOST_UNORDERED_TEST_HELPERS_FWD_HEADER
|
||||
|
||||
namespace test
|
||||
{
|
||||
class object;
|
||||
class hash;
|
||||
class less;
|
||||
class equal_to;
|
||||
template <class T> class allocator;
|
||||
}
|
||||
|
||||
#endif
|
202
test/objects/test.hpp
Normal file
202
test/objects/test.hpp
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
// Copyright Daniel James 2006. 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_OBJECTS_HEADER)
|
||||
#define BOOST_UNORDERED_TEST_OBJECTS_HEADER
|
||||
|
||||
#include <cstddef>
|
||||
#include "../helpers/fwd.hpp"
|
||||
#include <ostream>
|
||||
|
||||
namespace test
|
||||
{
|
||||
// Note that the default hash function will work for any equal_to (but not
|
||||
// very well).
|
||||
class object;
|
||||
class hash;
|
||||
class less;
|
||||
class equal_to;
|
||||
template <class T> class allocator;
|
||||
|
||||
class object
|
||||
{
|
||||
friend class hash;
|
||||
friend class equal_to;
|
||||
friend class less;
|
||||
int tag1_, tag2_;
|
||||
public:
|
||||
explicit object(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {}
|
||||
|
||||
friend bool operator==(object const& x1, object const& x2) {
|
||||
return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
|
||||
}
|
||||
|
||||
friend bool operator!=(object const& x1, object const& x2) {
|
||||
return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_;
|
||||
}
|
||||
|
||||
friend bool operator<(object const& x1, object const& x2) {
|
||||
return x1.tag1_ < x2.tag1_ ||
|
||||
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
|
||||
}
|
||||
|
||||
|
||||
friend object generate(object const*) {
|
||||
int* x;
|
||||
return object(generate(x), generate(x));
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, object const& o)
|
||||
{
|
||||
return out<<"("<<o.tag1_<<","<<o.tag2_<<")";
|
||||
}
|
||||
};
|
||||
|
||||
class hash
|
||||
{
|
||||
int type_;
|
||||
public:
|
||||
explicit hash(int t = 0) : type_(t) {}
|
||||
|
||||
std::size_t operator()(object const& x) const {
|
||||
switch(type_) {
|
||||
case 1:
|
||||
return x.tag1_;
|
||||
case 2:
|
||||
return x.tag2_;
|
||||
default:
|
||||
return x.tag1_ + x.tag2_;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t operator()(int x) const {
|
||||
return x;
|
||||
}
|
||||
|
||||
friend bool operator==(hash const& x1, hash const& x2) {
|
||||
return x1.type_ == x2.type_;
|
||||
}
|
||||
|
||||
friend bool operator!=(hash const& x1, hash const& x2) {
|
||||
return x1.type_ != x2.type_;
|
||||
}
|
||||
};
|
||||
|
||||
class less
|
||||
{
|
||||
int type_;
|
||||
public:
|
||||
explicit less(int t = 0) : type_(t) {}
|
||||
|
||||
bool operator()(object const& x1, object const& x2) const {
|
||||
switch(type_) {
|
||||
case 1:
|
||||
return x1.tag1_ < x2.tag1_;
|
||||
case 2:
|
||||
return x1.tag2_ < x2.tag2_;
|
||||
default:
|
||||
return x1 < x2;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t operator()(int x1, int x2) const {
|
||||
return x1 < x2;
|
||||
}
|
||||
|
||||
friend bool operator==(less const& x1, less const& x2) {
|
||||
return x1.type_ == x2.type_;
|
||||
}
|
||||
};
|
||||
|
||||
class equal_to
|
||||
{
|
||||
int type_;
|
||||
public:
|
||||
explicit equal_to(int t = 0) : type_(t) {}
|
||||
|
||||
bool operator()(object const& x1, object const& x2) const {
|
||||
switch(type_) {
|
||||
case 1:
|
||||
return x1.tag1_ == x2.tag1_;
|
||||
case 2:
|
||||
return x1.tag2_ == x2.tag2_;
|
||||
default:
|
||||
return x1 == x2;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t operator()(int x1, int x2) const {
|
||||
return x1 == x2;
|
||||
}
|
||||
|
||||
friend bool operator==(equal_to const& x1, equal_to const& x2) {
|
||||
return x1.type_ == x2.type_;
|
||||
}
|
||||
|
||||
friend bool operator!=(equal_to const& x1, equal_to const& x2) {
|
||||
return x1.type_ != x2.type_;
|
||||
}
|
||||
|
||||
friend less create_compare(equal_to x) {
|
||||
return less(x.type_);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class allocator
|
||||
{
|
||||
public:
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef T* pointer;
|
||||
typedef T const* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef T const& const_reference;
|
||||
typedef T value_type;
|
||||
|
||||
template <class U> struct rebind { typedef allocator<U> other; };
|
||||
|
||||
explicit allocator(int t = 0) {}
|
||||
template <class Y> allocator(allocator<Y> const& x) {}
|
||||
allocator(allocator const&) {}
|
||||
~allocator() {}
|
||||
|
||||
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*>(::operator new(n * sizeof(T))));
|
||||
}
|
||||
|
||||
pointer allocate(size_type n, const_pointer u)
|
||||
{
|
||||
return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
|
||||
}
|
||||
|
||||
void deallocate(pointer p, size_type n)
|
||||
{
|
||||
::operator delete((void*) p);
|
||||
}
|
||||
|
||||
void construct(pointer p, T const& t) { new(p) T(t); }
|
||||
void destroy(pointer p) { p->~T(); }
|
||||
|
||||
size_type max_size() const { return 1000; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline bool operator==(allocator<T> const& x, allocator<T> const& y)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool operator!=(allocator<T> const& x, allocator<T> const& y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
23
test/unordered/Jamfile.v2
Normal file
23
test/unordered/Jamfile.v2
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
# Copyright Daniel James 2006. 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/unordered
|
||||
: requirements
|
||||
<toolset>intel-linux:"<cxxflags>-strict_ansi -cxxlib-icc"
|
||||
;
|
||||
|
||||
test-suite unordered-tests
|
||||
:
|
||||
[ run equivalent_keys_tests.cpp ]
|
||||
[ run compile_tests.cpp ]
|
||||
[ run constructor_tests.cpp ]
|
||||
[ run copy_tests.cpp ]
|
||||
[ run assign_tests.cpp ]
|
||||
[ run insert_tests.cpp ]
|
||||
[ run erase_tests.cpp ]
|
||||
[ run find_tests.cpp ]
|
||||
;
|
91
test/unordered/assign_tests.cpp
Normal file
91
test/unordered/assign_tests.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
|
||||
// Copyright Daniel James 2006. 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/detail/lightweight_test.hpp>
|
||||
#include "../objects/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/equivalent.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
template <class T>
|
||||
void assign_tests1(T* = 0)
|
||||
{
|
||||
typename T::hasher hf;
|
||||
typename T::key_equal eq;
|
||||
|
||||
std::cerr<<"assign_tests1.1\n";
|
||||
{
|
||||
T x;
|
||||
x = x;
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
}
|
||||
|
||||
std::cerr<<"assign_tests1.2\n";
|
||||
{
|
||||
test::random_values<T> v(1000);
|
||||
T x(v.begin(), v.end());
|
||||
|
||||
test::ordered<T> tracker = test::create_ordered(x);
|
||||
tracker.insert(v.begin(), v.end());
|
||||
|
||||
x = x;
|
||||
tracker.compare(x);
|
||||
|
||||
T y;
|
||||
y.max_load_factor(x.max_load_factor() / 20);
|
||||
y = x;
|
||||
tracker.compare(y);
|
||||
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void assign_tests2(T* = 0)
|
||||
{
|
||||
typename T::hasher hf;
|
||||
typename T::key_equal eq;
|
||||
typename T::hasher hf1(1);
|
||||
typename T::key_equal eq1(1);
|
||||
typename T::hasher hf2(2);
|
||||
typename T::key_equal eq2(2);
|
||||
|
||||
std::cerr<<"assign_tests2.1\n";
|
||||
{
|
||||
// TODO: Need to generate duplicates...
|
||||
test::random_values<T> v(1000);
|
||||
T x1(v.begin(), v.end(), 0, hf1, eq1);
|
||||
T x2(0, hf2, eq2);
|
||||
x2 = x1;
|
||||
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
|
||||
check_container(x2, v);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
assign_tests1((boost::unordered_set<int>*) 0);
|
||||
assign_tests1((boost::unordered_multiset<int>*) 0);
|
||||
assign_tests1((boost::unordered_map<int, int>*) 0);
|
||||
assign_tests1((boost::unordered_multimap<int, int>*) 0);
|
||||
|
||||
assign_tests1((boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
assign_tests1((boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
assign_tests1((boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
assign_tests1((boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
|
||||
assign_tests2((boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
assign_tests2((boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
assign_tests2((boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
assign_tests2((boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
297
test/unordered/compile_tests.cpp
Normal file
297
test/unordered/compile_tests.cpp
Normal file
@ -0,0 +1,297 @@
|
||||
|
||||
// Copyright Daniel James 2006. 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/concept_check.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
#include "../helpers/check_return_type.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "../objects/minimal.hpp"
|
||||
|
||||
template <class T> void sink(T const&) {}
|
||||
|
||||
template <class X, class Key>
|
||||
void unordered_set_test(X& r, Key const& k)
|
||||
{
|
||||
BOOST_MPL_ASSERT((boost::is_same<
|
||||
typename X::value_type,
|
||||
typename X::key_type>));
|
||||
}
|
||||
|
||||
template <class X, class Key, class T>
|
||||
void unordered_map_test(X& r, Key const& k, T const& t)
|
||||
{
|
||||
BOOST_MPL_ASSERT((boost::is_same<
|
||||
typename X::value_type,
|
||||
std::pair<const typename X::key_type, T> >));
|
||||
}
|
||||
|
||||
template <class X, class T>
|
||||
void unordered_unique_test(X& r, T const& t)
|
||||
{
|
||||
typedef typename X::iterator iterator;
|
||||
test::check_return_type<std::pair<iterator, bool> >::equals(r.insert(t));
|
||||
}
|
||||
|
||||
template <class X, class T>
|
||||
void unordered_equivalent_test(X& r, T const& t)
|
||||
{
|
||||
typedef typename X::iterator iterator;
|
||||
test::check_return_type<iterator>::equals(r.insert(t));
|
||||
}
|
||||
|
||||
template <class X, class Key, class T, class Hash, class Pred>
|
||||
void unordered_test(X& ref, Key& k, T& t, Hash& hf, Pred& eq)
|
||||
{
|
||||
typedef typename X::iterator iterator;
|
||||
typedef typename X::const_iterator const_iterator;
|
||||
typedef typename X::local_iterator local_iterator;
|
||||
typedef typename X::const_local_iterator const_local_iterator;
|
||||
|
||||
typedef typename X::key_type key_type;
|
||||
typedef typename X::hasher hasher;
|
||||
typedef typename X::key_equal key_equal;
|
||||
|
||||
BOOST_MPL_ASSERT((boost::is_same<Key, key_type>));
|
||||
boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
|
||||
boost::function_requires<boost::AssignableConcept<key_type> >();
|
||||
|
||||
BOOST_MPL_ASSERT((boost::is_same<Hash, hasher>));
|
||||
test::check_return_type<std::size_t>::equals(hf(k));
|
||||
|
||||
BOOST_MPL_ASSERT((boost::is_same<Pred, key_equal>));
|
||||
test::check_return_type<bool>::convertible(eq(k, k));
|
||||
// TODO: Pred is an equivalence relation. Doesn't really matter for these
|
||||
// tests.
|
||||
|
||||
boost::function_requires<boost::InputIteratorConcept<local_iterator> >();
|
||||
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_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::function_requires<boost::InputIteratorConcept<const_local_iterator> >();
|
||||
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_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 >));
|
||||
|
||||
X(10, hf, eq);
|
||||
X a(10, hf, eq);
|
||||
X(10, hf);
|
||||
X a2(10, hf);
|
||||
X(10);
|
||||
X a3(10);
|
||||
X();
|
||||
X a4();
|
||||
|
||||
typename X::value_type* i = 0;
|
||||
typename X::value_type* j = 0;
|
||||
|
||||
X(i, j, 10, hf, eq);
|
||||
X a5(i, j, 10, hf, eq);
|
||||
X(i, j, 10, hf);
|
||||
X a6(i, j, 10, hf);
|
||||
X(i, j, 10);
|
||||
X a7(i, j, 10);
|
||||
X(i, j);
|
||||
X a8(i, j);
|
||||
|
||||
X const b;
|
||||
sink(X(b));
|
||||
X a9(b);
|
||||
a = b;
|
||||
|
||||
test::check_return_type<hasher>::equals(b.hash_function());
|
||||
test::check_return_type<key_equal>::equals(b.key_eq());
|
||||
|
||||
iterator q = a.begin();
|
||||
const_iterator r = a.begin();
|
||||
test::check_return_type<iterator>::equals(a.insert(q, t));
|
||||
test::check_return_type<const_iterator>::equals(a.insert(r, t));
|
||||
|
||||
// TODO: void return?
|
||||
a.insert(i, j);
|
||||
test::check_return_type<typename X::size_type>::equals(a.erase(k));
|
||||
|
||||
BOOST_TEST(a.empty());
|
||||
if(a.empty()) {
|
||||
a.insert(t);
|
||||
q = a.begin();
|
||||
test::check_return_type<iterator>::equals(a.erase(q));
|
||||
}
|
||||
|
||||
BOOST_TEST(a.empty());
|
||||
if(a.empty()) {
|
||||
a.insert(t);
|
||||
r = a.begin();
|
||||
test::check_return_type<const_iterator>::equals(a.erase(r));
|
||||
}
|
||||
|
||||
iterator q1 = a.begin(), q2 = a.end();
|
||||
test::check_return_type<iterator>::equals(a.erase(q1, q2));
|
||||
|
||||
const_iterator r1 = a.begin(), r2 = a.end();
|
||||
test::check_return_type<const_iterator>::equals(a.erase(r1, r2));
|
||||
|
||||
// TODO: void return?
|
||||
a.clear();
|
||||
|
||||
test::check_return_type<iterator>::equals(a.find(k));
|
||||
test::check_return_type<const_iterator>::equals(b.find(k));
|
||||
test::check_return_type<typename X::size_type>::equals(b.count(k));
|
||||
test::check_return_type<std::pair<iterator, iterator> >::equals(
|
||||
a.equal_range(k));
|
||||
test::check_return_type<std::pair<const_iterator, const_iterator> >::equals(
|
||||
b.equal_range(k));
|
||||
test::check_return_type<typename X::size_type>::equals(b.bucket_count());
|
||||
test::check_return_type<typename X::size_type>::equals(b.max_bucket_count());
|
||||
test::check_return_type<typename X::size_type>::equals(b.bucket(k));
|
||||
test::check_return_type<typename X::size_type>::equals(b.bucket_size(0));
|
||||
|
||||
test::check_return_type<local_iterator>::equals(a.begin(0));
|
||||
test::check_return_type<const_local_iterator>::equals(b.begin(0));
|
||||
test::check_return_type<local_iterator>::equals(a.end(0));
|
||||
test::check_return_type<const_local_iterator>::equals(b.end(0));
|
||||
|
||||
test::check_return_type<float>::equals(b.load_factor());
|
||||
test::check_return_type<float>::equals(b.max_load_factor());
|
||||
a.max_load_factor((float) 2.0);
|
||||
a.rehash(100);
|
||||
}
|
||||
|
||||
void test1()
|
||||
{
|
||||
boost::hash<int> hash;
|
||||
std::equal_to<int> equal_to;
|
||||
int value = 0;
|
||||
std::pair<int const, int> map_value(0, 0);
|
||||
|
||||
std::cout<<"Test unordered_set.\n";
|
||||
|
||||
boost::unordered_set<int> set;
|
||||
|
||||
unordered_unique_test(set, value);
|
||||
unordered_set_test(set, value);
|
||||
unordered_test(set, value, value, hash, equal_to);
|
||||
|
||||
std::cout<<"Test unordered_multiset.\n";
|
||||
|
||||
boost::unordered_multiset<int> multiset;
|
||||
|
||||
unordered_equivalent_test(multiset, value);
|
||||
unordered_set_test(multiset, value);
|
||||
unordered_test(multiset, value, value, hash, equal_to);
|
||||
|
||||
std::cout<<"Test unordered_map.\n";
|
||||
|
||||
boost::unordered_map<int, int> map;
|
||||
|
||||
unordered_unique_test(map, map_value);
|
||||
unordered_map_test(map, value, value);
|
||||
unordered_test(map, value, map_value, hash, equal_to);
|
||||
|
||||
std::cout<<"Test unordered_multimap.\n";
|
||||
|
||||
boost::unordered_multimap<int, int> multimap;
|
||||
|
||||
unordered_equivalent_test(multimap, map_value);
|
||||
unordered_map_test(multimap, value, value);
|
||||
unordered_test(multimap, value, map_value, hash, equal_to);
|
||||
}
|
||||
|
||||
void test2()
|
||||
{
|
||||
test::minimal::assignable assignable
|
||||
= test::minimal::assignable::create();
|
||||
test::minimal::copy_constructible copy_constructible
|
||||
= test::minimal::copy_constructible::create();
|
||||
test::minimal::hash<test::minimal::assignable> hash
|
||||
= test::minimal::hash<test::minimal::assignable>::create();
|
||||
test::minimal::equal_to<test::minimal::assignable> equal_to
|
||||
= test::minimal::equal_to<test::minimal::assignable>::create();
|
||||
|
||||
typedef std::pair<test::minimal::assignable const,
|
||||
test::minimal::copy_constructible> map_value_type;
|
||||
map_value_type map_value(assignable, copy_constructible);
|
||||
|
||||
std::cout<<"Test unordered_set.\n";
|
||||
|
||||
boost::unordered_set<
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<test::minimal::assignable> > set;
|
||||
|
||||
unordered_unique_test(set, assignable);
|
||||
unordered_set_test(set, assignable);
|
||||
unordered_test(set, assignable, assignable, hash, equal_to);
|
||||
|
||||
std::cout<<"Test unordered_multiset.\n";
|
||||
|
||||
boost::unordered_multiset<
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<test::minimal::assignable> > multiset;
|
||||
|
||||
unordered_equivalent_test(multiset, assignable);
|
||||
unordered_set_test(multiset, assignable);
|
||||
unordered_test(multiset, assignable, assignable, hash, equal_to);
|
||||
|
||||
std::cout<<"Test unordered_map.\n";
|
||||
|
||||
boost::unordered_map<
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<map_value_type> > map;
|
||||
|
||||
unordered_unique_test(map, map_value);
|
||||
unordered_map_test(map, assignable, copy_constructible);
|
||||
unordered_test(map, assignable, map_value, hash, equal_to);
|
||||
|
||||
std::cout<<"Test unordered_multimap.\n";
|
||||
|
||||
boost::unordered_multimap<
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<map_value_type> > multimap;
|
||||
|
||||
unordered_equivalent_test(multimap, map_value);
|
||||
unordered_map_test(multimap, assignable, copy_constructible);
|
||||
unordered_test(multimap, assignable, map_value, hash, equal_to);
|
||||
}
|
||||
|
||||
int main() {
|
||||
test1();
|
||||
test2();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
202
test/unordered/constructor_tests.cpp
Normal file
202
test/unordered/constructor_tests.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
// Copyright Daniel James 2006. 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/detail/lightweight_test.hpp>
|
||||
#include "../objects/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/equivalent.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
template <class T>
|
||||
void constructor_tests1(T* = 0)
|
||||
{
|
||||
typename T::hasher hf;
|
||||
typename T::key_equal eq;
|
||||
|
||||
std::cerr<<"Construct 1\n";
|
||||
{
|
||||
T x(0, hf, eq);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 0);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 2\n";
|
||||
{
|
||||
T x(100, hf);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 100);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 3\n";
|
||||
{
|
||||
T x(2000);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 2000);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 4\n";
|
||||
{
|
||||
T x;
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 5\n";
|
||||
{
|
||||
test::random_values<T> v(1000);
|
||||
T x(v.begin(), v.end(), 10000, hf, eq);
|
||||
BOOST_TEST(x.bucket_count() >= 10000);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
check_container(x, v);
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 6\n";
|
||||
{
|
||||
test::random_values<T> v(10);
|
||||
T x(v.begin(), v.end(), 10000, hf);
|
||||
BOOST_TEST(x.bucket_count() >= 10000);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
check_container(x, v);
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 7\n";
|
||||
{
|
||||
test::random_values<T> v(100);
|
||||
T x(v.begin(), v.end(), 100);
|
||||
BOOST_TEST(x.bucket_count() >= 100);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
check_container(x, v);
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 8\n";
|
||||
{
|
||||
test::random_values<T> v(1);
|
||||
T x(v.begin(), v.end());
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
check_container(x, v);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void constructor_tests2(T* = 0)
|
||||
{
|
||||
typename T::hasher hf;
|
||||
typename T::hasher hf1(1);
|
||||
typename T::hasher hf2(2);
|
||||
typename T::key_equal eq;
|
||||
typename T::key_equal eq1(1);
|
||||
typename T::key_equal eq2(2);
|
||||
|
||||
std::cerr<<"Construct 1\n";
|
||||
{
|
||||
T x(10000, hf1, eq1);
|
||||
BOOST_TEST(x.bucket_count() >= 10000);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 2\n";
|
||||
{
|
||||
T x(100, hf1);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.bucket_count() >= 100);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 3\n";
|
||||
{
|
||||
test::random_values<T> v(100);
|
||||
T x(v.begin(), v.end(), 0, hf1, eq1);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
|
||||
check_container(x, v);
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 4\n";
|
||||
{
|
||||
test::random_values<T> v(5);
|
||||
T x(v.begin(), v.end(), 1000, hf1);
|
||||
BOOST_TEST(x.bucket_count() >= 1000);
|
||||
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
check_container(x, v);
|
||||
}
|
||||
|
||||
|
||||
std::cerr<<"Construct 5\n";
|
||||
{
|
||||
test::random_values<T> v(100);
|
||||
T x(v.begin(), v.end(), 0, hf, eq);
|
||||
T y(x.begin(), x.end(), 0, hf1, eq1);
|
||||
check_container(x, v);
|
||||
check_container(y, x);
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 6\n";
|
||||
{
|
||||
test::random_values<T> v(100);
|
||||
T x(v.begin(), v.end(), 0, hf1, eq1);
|
||||
T y(x.begin(), x.end(), 0, hf, eq);
|
||||
check_container(x, v);
|
||||
check_container(y, x);
|
||||
}
|
||||
|
||||
std::cerr<<"Construct 7\n";
|
||||
{
|
||||
test::random_values<T> v(100);
|
||||
T x(v.begin(), v.end(), 0, hf1, eq1);
|
||||
T y(x.begin(), x.end(), 0, hf2, eq2);
|
||||
check_container(x, v);
|
||||
check_container(y, x);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cerr<<"Test1 unordered_set<int>\n";
|
||||
constructor_tests1((boost::unordered_set<int>*) 0);
|
||||
std::cerr<<"Test1 unordered_multiset<int>\n";
|
||||
constructor_tests1((boost::unordered_multiset<int>*) 0);
|
||||
std::cerr<<"Test1 unordered_map<int, int>\n";
|
||||
constructor_tests1((boost::unordered_map<int, int>*) 0);
|
||||
std::cerr<<"Test1 unordered_multimap<int, int>\n";
|
||||
constructor_tests1((boost::unordered_multimap<int, int>*) 0);
|
||||
|
||||
std::cerr<<"Test1 unordered_set<test::object>\n";
|
||||
constructor_tests1((boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
std::cerr<<"Test1 unordered_multiset<test::object>\n";
|
||||
constructor_tests1((boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
std::cerr<<"Test1 unordered_map<test::object, test::object>\n";
|
||||
constructor_tests1((boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
std::cerr<<"Test1 unordered_multimap<test::object, test::object>\n";
|
||||
constructor_tests1((boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
|
||||
std::cerr<<"Test2 unordered_set<test::object>\n";
|
||||
constructor_tests2((boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
std::cerr<<"Test2 unordered_multiset<test::object>\n";
|
||||
constructor_tests2((boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
std::cerr<<"Test2 unordered_map<test::object, test::object>\n";
|
||||
constructor_tests2((boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
std::cerr<<"Test2 unordered_multimap<test::object, test::object>\n";
|
||||
constructor_tests2((boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
103
test/unordered/copy_tests.cpp
Normal file
103
test/unordered/copy_tests.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
|
||||
// Copyright Daniel James 2006. 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/detail/lightweight_test.hpp>
|
||||
#include "../objects/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/equivalent.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
|
||||
template <class T>
|
||||
void copy_construct_tests1(T* = 0)
|
||||
{
|
||||
typename T::hasher hf;
|
||||
typename T::key_equal eq;
|
||||
|
||||
{
|
||||
T x;
|
||||
T y(x);
|
||||
BOOST_TEST(y.empty());
|
||||
BOOST_TEST(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
{
|
||||
test::random_values<T> v(1000);
|
||||
|
||||
T x(v.begin(), v.end());
|
||||
T y(x);
|
||||
test::unordered_equivalence_tester<T> equivalent(x);
|
||||
equivalent(y);
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
{
|
||||
// In this test I drop the original containers max load factor, so it
|
||||
// is much lower than the load factor. The hash table is not allowed
|
||||
// to rehash, but the destination container should probably allocate
|
||||
// enough buckets to decrease the load factor appropriately. Although,
|
||||
// I don't think it has to.
|
||||
test::random_values<T> v(1000);
|
||||
T x(v.begin(), v.end());
|
||||
x.max_load_factor(x.load_factor() / 4);
|
||||
T y(x);
|
||||
test::unordered_equivalence_tester<T> equivalent(x);
|
||||
equivalent(y);
|
||||
// I don't think this is guaranteed:
|
||||
BOOST_TEST(y.load_factor() < y.max_load_factor());
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void copy_construct_tests2(T* ptr = 0)
|
||||
{
|
||||
copy_construct_tests1(ptr);
|
||||
|
||||
typename T::hasher hf(1);
|
||||
typename T::key_equal eq(1);
|
||||
|
||||
{
|
||||
// TODO: I could check how many buckets y has, it should be lower (QOI issue).
|
||||
T x(10000, hf, eq);
|
||||
T y(x);
|
||||
BOOST_TEST(y.empty());
|
||||
BOOST_TEST(test::equivalent(y.hash_function(), hf));
|
||||
BOOST_TEST(test::equivalent(y.key_eq(), eq));
|
||||
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
{
|
||||
// TODO: Invariant checks are especially important here.
|
||||
test::random_values<T> v(1000);
|
||||
|
||||
T x(v.begin(), v.end(), 0, hf, eq);
|
||||
T y(x);
|
||||
test::unordered_equivalence_tester<T> equivalent(x);
|
||||
equivalent(y);
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
copy_construct_tests1((boost::unordered_set<int>*) 0);
|
||||
copy_construct_tests1((boost::unordered_multiset<int>*) 0);
|
||||
copy_construct_tests1((boost::unordered_map<int, int>*) 0);
|
||||
copy_construct_tests1((boost::unordered_multimap<int, int>*) 0);
|
||||
|
||||
copy_construct_tests2((boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
copy_construct_tests2((boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
copy_construct_tests2((boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
copy_construct_tests2((boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
85
test/unordered/equivalent_keys_tests.cpp
Normal file
85
test/unordered/equivalent_keys_tests.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
|
||||
// Copyright Daniel James 2006. 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/detail/lightweight_test.hpp>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <deque>
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
template <class Container, class Iterator>
|
||||
void test_equal_insertion(Iterator begin, Iterator end)
|
||||
{
|
||||
typedef test::ordered<Container> tracker;
|
||||
|
||||
Container x1;
|
||||
tracker x2 = test::create_ordered(x1);
|
||||
|
||||
for(Iterator it = begin; it != end; ++it) {
|
||||
x1.insert(*it);
|
||||
x2.insert(*it);
|
||||
x2.compare_key(x1, *it);
|
||||
}
|
||||
|
||||
x2.compare(x1);
|
||||
test::check_equivalent_keys(x1);
|
||||
}
|
||||
|
||||
void set_tests()
|
||||
{
|
||||
int values[][5] = {
|
||||
{1},
|
||||
{54, 23},
|
||||
{-13, 65},
|
||||
{77, 77},
|
||||
{986, 25, 986}
|
||||
};
|
||||
|
||||
test_equal_insertion<boost::unordered_set<int> >(values[0], values[0] + 1);
|
||||
test_equal_insertion<boost::unordered_set<int> >(values[1], values[1] + 2);
|
||||
test_equal_insertion<boost::unordered_set<int> >(values[2], values[2] + 2);
|
||||
test_equal_insertion<boost::unordered_set<int> >(values[3], values[3] + 2);
|
||||
test_equal_insertion<boost::unordered_set<int> >(values[4], values[4] + 3);
|
||||
|
||||
test_equal_insertion<boost::unordered_multiset<int> >(values[0], values[0] + 1);
|
||||
test_equal_insertion<boost::unordered_multiset<int> >(values[1], values[1] + 2);
|
||||
test_equal_insertion<boost::unordered_multiset<int> >(values[2], values[2] + 2);
|
||||
test_equal_insertion<boost::unordered_multiset<int> >(values[3], values[3] + 2);
|
||||
test_equal_insertion<boost::unordered_multiset<int> >(values[4], values[4] + 3);
|
||||
}
|
||||
|
||||
void map_tests()
|
||||
{
|
||||
typedef std::deque<std::pair<int const, int> > values_type;
|
||||
values_type v[5];
|
||||
v[0].push_back(std::pair<int const, int>(1,1));
|
||||
v[1].push_back(std::pair<int const, int>(28,34));
|
||||
v[1].push_back(std::pair<int const, int>(16,58));
|
||||
v[1].push_back(std::pair<int const, int>(-124, 62));
|
||||
v[2].push_back(std::pair<int const, int>(432,12));
|
||||
v[2].push_back(std::pair<int const, int>(9,13));
|
||||
v[2].push_back(std::pair<int const, int>(432,24));
|
||||
|
||||
for(int i = 0; i < 5; ++i)
|
||||
test_equal_insertion<boost::unordered_map<int, int> >(
|
||||
v[i].begin(), v[i].end());
|
||||
|
||||
for(int i2 = 0; i2 < 5; ++i2)
|
||||
test_equal_insertion<boost::unordered_multimap<int, int> >(
|
||||
v[i2].begin(), v[i2].end());
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
set_tests();
|
||||
map_tests();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
140
test/unordered/erase_tests.cpp
Normal file
140
test/unordered/erase_tests.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
|
||||
// Copyright Daniel James 2006. 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/detail/lightweight_test.hpp>
|
||||
#include <boost/next_prior.hpp>
|
||||
#include "../objects/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/equivalent.hpp"
|
||||
#include "../helpers/helpers.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
template <class Container>
|
||||
void erase_tests1(Container* = 0)
|
||||
{
|
||||
std::cerr<<"Erase by key.\n";
|
||||
{
|
||||
test::random_values<Container> v(1000);
|
||||
Container x(v.begin(), v.end());
|
||||
for(typename test::random_values<Container>::iterator it = v.begin();
|
||||
it != v.end(); ++it)
|
||||
{
|
||||
std::size_t count = x.count(test::get_key<Container>(*it));
|
||||
std::size_t old_size = x.size();
|
||||
BOOST_TEST(count == x.erase(test::get_key<Container>(*it)));
|
||||
BOOST_TEST(x.size() == old_size - count);
|
||||
BOOST_TEST(x.count(test::get_key<Container>(*it)) == 0);
|
||||
BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr<<"erase(begin()).\n";
|
||||
{
|
||||
test::random_values<Container> v(1000);
|
||||
Container x(v.begin(), v.end());
|
||||
std::size_t size = x.size();
|
||||
while(size > 0 && !x.empty())
|
||||
{
|
||||
typename Container::key_type key = test::get_key<Container>(*x.begin());
|
||||
std::size_t count = x.count(key);
|
||||
typename Container::iterator pos = x.erase(x.begin());
|
||||
--size;
|
||||
BOOST_TEST(pos == x.begin());
|
||||
BOOST_TEST(x.count(key) == count - 1);
|
||||
BOOST_TEST(x.size() == size);
|
||||
}
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
|
||||
std::cerr<<"erase(random position).\n";
|
||||
{
|
||||
test::random_values<Container> v(1000);
|
||||
Container x(v.begin(), v.end());
|
||||
std::size_t size = x.size();
|
||||
while(size > 0 && !x.empty())
|
||||
{
|
||||
using namespace std;
|
||||
int index = rand() % x.size();
|
||||
typename Container::const_iterator prev, pos, next;
|
||||
if(index == 0) {
|
||||
prev = pos = x.begin();
|
||||
}
|
||||
else {
|
||||
prev = boost::next(x.begin(), index - 1);
|
||||
pos = boost::next(prev);
|
||||
}
|
||||
next = boost::next(pos);
|
||||
typename Container::key_type key = test::get_key<Container>(*x.begin());
|
||||
std::size_t count = x.count(key);
|
||||
BOOST_TEST(next == x.erase(pos));
|
||||
--size;
|
||||
if(size > 0)
|
||||
BOOST_TEST(next ==
|
||||
(index == 0 ? x.begin() : boost::next(prev)));
|
||||
BOOST_TEST(x.count(key) == count - 1);
|
||||
std::cerr<<x.count(key)<<"/"<<(count - 1)<<"\n";
|
||||
BOOST_TEST(x.size() == size);
|
||||
}
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
|
||||
std::cerr<<"erase(ranges).\n";
|
||||
{
|
||||
test::random_values<Container> v(500);
|
||||
Container x(v.begin(), v.end());
|
||||
|
||||
std::size_t size = x.size();
|
||||
|
||||
// I'm actually stretching it a little here, as the standard says it
|
||||
// returns 'the iterator immediately following the erase elements'
|
||||
// and if nothing is erased, then there's nothing to follow. But I
|
||||
// think this is the only sensible option...
|
||||
BOOST_TEST(x.erase(x.end(), x.end()) == x.end());
|
||||
BOOST_TEST(x.erase(x.begin(), x.begin()) == x.begin());
|
||||
BOOST_TEST(x.size() == size);
|
||||
|
||||
BOOST_TEST(x.erase(x.begin(), x.end()) == x.end());
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.begin() == x.end());
|
||||
|
||||
BOOST_TEST(x.erase(x.begin(), x.end()) == x.begin());
|
||||
}
|
||||
|
||||
// TODO: More range erase tests.
|
||||
|
||||
std::cerr<<"clear().\n";
|
||||
{
|
||||
test::random_values<Container> v(500);
|
||||
Container x(v.begin(), v.end());
|
||||
x.clear();
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(x.begin() == x.end());
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cerr<<"Erase unordered_set<int>.\n";
|
||||
erase_tests1((boost::unordered_set<int>*) 0);
|
||||
std::cerr<<"\nErase unordered_multiset<int>.\n";
|
||||
erase_tests1((boost::unordered_multiset<int>*) 0);
|
||||
std::cerr<<"\nErase unordered_map<int>.\n";
|
||||
erase_tests1((boost::unordered_map<int, int>*) 0);
|
||||
std::cerr<<"\nErase unordered_multimap<int>.\n";
|
||||
erase_tests1((boost::unordered_multimap<int, int>*) 0);
|
||||
|
||||
std::cerr<<"\nErase unordered_set<test::object,..>.\n";
|
||||
erase_tests1((boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
std::cerr<<"\nErase unordered_multiset<test::object,..>.\n";
|
||||
erase_tests1((boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
std::cerr<<"\nErase unordered_map<test::object,..>.\n";
|
||||
erase_tests1((boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
std::cerr<<"\nErase unordered_multimap<test::object,..>.\n";
|
||||
erase_tests1((boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
}
|
90
test/unordered/find_tests.cpp
Normal file
90
test/unordered/find_tests.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
|
||||
// Copyright Daniel James 2006. 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/detail/lightweight_test.hpp>
|
||||
#include "../objects/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/helpers.hpp"
|
||||
|
||||
template <class X>
|
||||
void find_tests1(X*)
|
||||
{
|
||||
{
|
||||
test::random_values<X> v(500);
|
||||
X x(v.begin(), v.end());
|
||||
X const& x_const = x;
|
||||
test::ordered<X> tracker = test::create_ordered(x);
|
||||
tracker.insert(v.begin(), v.end());
|
||||
|
||||
for(typename test::ordered<X>::const_iterator it =
|
||||
tracker.begin(); it != tracker.end(); ++it)
|
||||
{
|
||||
typename X::key_type key = test::get_key<X>(*it);
|
||||
typename X::iterator pos = x.find(key);
|
||||
typename X::const_iterator const_pos = x_const.find(key);
|
||||
BOOST_TEST(pos != x.end() &&
|
||||
x.key_eq()(key, test::get_key<X>(*pos)));
|
||||
BOOST_TEST(const_pos != x_const.end() &&
|
||||
x_const.key_eq()(key, test::get_key<X>(*const_pos)));
|
||||
|
||||
BOOST_TEST(x.count(key) == tracker.count(key));
|
||||
|
||||
test::compare_pairs(x.equal_range(key),
|
||||
tracker.equal_range(key),
|
||||
(typename test::non_const_value_type<X>::type*) 0);
|
||||
test::compare_pairs(x_const.equal_range(key),
|
||||
tracker.equal_range(key),
|
||||
(typename test::non_const_value_type<X>::type*) 0);
|
||||
}
|
||||
|
||||
test::random_values<X> v2(500);
|
||||
for(typename test::random_values<X>::const_iterator it =
|
||||
v2.begin(); it != v2.end(); ++it)
|
||||
{
|
||||
typename X::key_type key = test::get_key<X>(*it);
|
||||
if(tracker.find(test::get_key<X>(key)) == tracker.end())
|
||||
{
|
||||
BOOST_TEST(x.find(key) == x.end());
|
||||
BOOST_TEST(x_const.find(key) == x_const.end());
|
||||
BOOST_TEST(x.count(key) == 0);
|
||||
std::pair<typename X::iterator,
|
||||
typename X::iterator> range = x.equal_range(key);
|
||||
BOOST_TEST(range.first == range.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
X x;
|
||||
|
||||
test::random_values<X> v2(5);
|
||||
for(typename test::random_values<X>::const_iterator it =
|
||||
v2.begin(); it != v2.end(); ++it)
|
||||
{
|
||||
typename X::key_type key = test::get_key<X>(*it);
|
||||
BOOST_TEST(x.find(key) == x.end());
|
||||
BOOST_TEST(x.count(key) == 0);
|
||||
std::pair<typename X::iterator,
|
||||
typename X::iterator> range = x.equal_range(key);
|
||||
BOOST_TEST(range.first == range.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
find_tests1((boost::unordered_set<int>*) 0);
|
||||
find_tests1((boost::unordered_multiset<int>*) 0);
|
||||
find_tests1((boost::unordered_map<int, int>*) 0);
|
||||
find_tests1((boost::unordered_multimap<int, int>*) 0);
|
||||
|
||||
find_tests1((boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
find_tests1((boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
find_tests1((boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
find_tests1((boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
}
|
188
test/unordered/insert_tests.cpp
Normal file
188
test/unordered/insert_tests.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
|
||||
// Copyright Daniel James 2006. 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/detail/lightweight_test.hpp>
|
||||
#include <boost/next_prior.hpp>
|
||||
#include "../objects/test.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/equivalent.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
template <class Container>
|
||||
void unique_insert_tests1(Container* = 0)
|
||||
{
|
||||
std::cerr<<"insert(value) tests for containers with unique keys.\n";
|
||||
|
||||
Container x;
|
||||
test::ordered<Container> tracker = test::create_ordered(x);
|
||||
|
||||
test::random_values<Container> v(1000);
|
||||
for(typename test::random_values<Container>::iterator it = v.begin();
|
||||
it != v.end(); ++it)
|
||||
{
|
||||
std::pair<typename Container::iterator, bool> r1 = x.insert(*it);
|
||||
std::pair<typename test::ordered<Container>::iterator, bool> r2
|
||||
= tracker.insert(*it);
|
||||
|
||||
BOOST_TEST(r1.second == r2.second);
|
||||
BOOST_TEST(*r1.first == *r2.first);
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
void equivalent_insert_tests1(Container* = 0)
|
||||
{
|
||||
std::cerr<<"insert(value) tests for containers with equivalent keys.\n";
|
||||
|
||||
Container x;
|
||||
test::ordered<Container> tracker = test::create_ordered(x);
|
||||
|
||||
test::random_values<Container> v(1000);
|
||||
for(typename test::random_values<Container>::iterator it = v.begin();
|
||||
it != v.end(); ++it)
|
||||
{
|
||||
typename Container::iterator r1 = x.insert(*it);
|
||||
typename test::ordered<Container>::iterator r2 = tracker.insert(*it);
|
||||
|
||||
BOOST_TEST(*r1 == *r2);
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
void insert_tests2(Container* = 0)
|
||||
{
|
||||
typedef typename test::ordered<Container> tracker_type;
|
||||
typedef typename Container::iterator iterator;
|
||||
typedef typename Container::const_iterator const_iterator;
|
||||
typedef typename tracker_type::iterator tracker_iterator;
|
||||
|
||||
std::cerr<<"insert(begin(), value) tests.\n";
|
||||
|
||||
{
|
||||
Container x;
|
||||
tracker_type tracker = test::create_ordered(x);
|
||||
|
||||
test::random_values<Container> v(1000);
|
||||
for(typename test::random_values<Container>::iterator it = v.begin();
|
||||
it != v.end(); ++it)
|
||||
{
|
||||
iterator r1 = x.insert(x.begin(), *it);
|
||||
tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
|
||||
BOOST_TEST(*r1 == *r2);
|
||||
tracker.compare_key(x, *it);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr<<"insert(end(), value) tests.\n";
|
||||
|
||||
{
|
||||
Container x;
|
||||
Container const& x_const = x;
|
||||
tracker_type tracker = test::create_ordered(x);
|
||||
|
||||
test::random_values<Container> v(100);
|
||||
for(typename test::random_values<Container>::iterator it = v.begin();
|
||||
it != v.end(); ++it)
|
||||
{
|
||||
const_iterator r1 = x.insert(x_const.end(), *it);
|
||||
tracker_iterator r2 = tracker.insert(tracker.end(), *it);
|
||||
BOOST_TEST(*r1 == *r2);
|
||||
tracker.compare_key(x, *it);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr<<"insert(pos, value) tests.\n";
|
||||
|
||||
{
|
||||
Container x;
|
||||
const_iterator pos = x.begin();
|
||||
tracker_type tracker = test::create_ordered(x);
|
||||
|
||||
test::random_values<Container> v(1000);
|
||||
for(typename test::random_values<Container>::iterator it = v.begin();
|
||||
it != v.end(); ++it)
|
||||
{
|
||||
pos = x.insert(pos, *it);
|
||||
tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
|
||||
BOOST_TEST(*pos == *r2);
|
||||
tracker.compare_key(x, *it);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr<<"insert single item range tests.\n";
|
||||
|
||||
{
|
||||
Container x;
|
||||
tracker_type tracker = test::create_ordered(x);
|
||||
|
||||
test::random_values<Container> v(1000);
|
||||
for(typename test::random_values<Container>::iterator it = v.begin();
|
||||
it != v.end(); ++it)
|
||||
{
|
||||
x.insert(it, boost::next(it));
|
||||
tracker.insert(*it);
|
||||
tracker.compare_key(x, *it);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr<<"insert range tests.\n";
|
||||
|
||||
{
|
||||
Container x;
|
||||
const_iterator pos = x.begin();
|
||||
|
||||
test::random_values<Container> v(1000);
|
||||
x.insert(v.begin(), v.end());
|
||||
check_container(x, v);
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
unique_insert_tests1((boost::unordered_set<int>*) 0);
|
||||
equivalent_insert_tests1((boost::unordered_multiset<int>*) 0);
|
||||
unique_insert_tests1((boost::unordered_map<int, int>*) 0);
|
||||
equivalent_insert_tests1((boost::unordered_multimap<int, int>*) 0);
|
||||
|
||||
unique_insert_tests1((boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
equivalent_insert_tests1((boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
unique_insert_tests1((boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
equivalent_insert_tests1((boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
|
||||
insert_tests2((boost::unordered_set<int>*) 0);
|
||||
insert_tests2((boost::unordered_multiset<int>*) 0);
|
||||
insert_tests2((boost::unordered_map<int, int>*) 0);
|
||||
insert_tests2((boost::unordered_multimap<int, int>*) 0);
|
||||
|
||||
insert_tests2((boost::unordered_set<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
insert_tests2((boost::unordered_multiset<test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
insert_tests2((boost::unordered_map<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
insert_tests2((boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >*) 0);
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user