summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/unordered/test/helpers
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/unordered/test/helpers
parentInitial commit. (diff)
downloadceph-upstream.tar.xz
ceph-upstream.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/unordered/test/helpers')
-rw-r--r--src/boost/libs/unordered/test/helpers/check_return_type.hpp33
-rw-r--r--src/boost/libs/unordered/test/helpers/count.hpp89
-rw-r--r--src/boost/libs/unordered/test/helpers/equivalent.hpp96
-rw-r--r--src/boost/libs/unordered/test/helpers/exception_test.hpp348
-rw-r--r--src/boost/libs/unordered/test/helpers/fwd.hpp32
-rw-r--r--src/boost/libs/unordered/test/helpers/generators.hpp93
-rw-r--r--src/boost/libs/unordered/test/helpers/helpers.hpp56
-rw-r--r--src/boost/libs/unordered/test/helpers/input_iterator.hpp165
-rw-r--r--src/boost/libs/unordered/test/helpers/invariants.hpp130
-rw-r--r--src/boost/libs/unordered/test/helpers/list.hpp327
-rw-r--r--src/boost/libs/unordered/test/helpers/memory.hpp189
-rw-r--r--src/boost/libs/unordered/test/helpers/metafunctions.hpp30
-rw-r--r--src/boost/libs/unordered/test/helpers/postfix.hpp10
-rw-r--r--src/boost/libs/unordered/test/helpers/prefix.hpp11
-rw-r--r--src/boost/libs/unordered/test/helpers/random_values.hpp109
-rw-r--r--src/boost/libs/unordered/test/helpers/strong.hpp42
-rw-r--r--src/boost/libs/unordered/test/helpers/test.hpp201
-rw-r--r--src/boost/libs/unordered/test/helpers/tracker.hpp138
18 files changed, 2099 insertions, 0 deletions
diff --git a/src/boost/libs/unordered/test/helpers/check_return_type.hpp b/src/boost/libs/unordered/test/helpers/check_return_type.hpp
new file mode 100644
index 00000000..1c70a8c7
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/check_return_type.hpp
@@ -0,0 +1,33 @@
+
+// Copyright 2005-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace test {
+ template <class T1> struct check_return_type
+ {
+ template <class T2> static void equals(T2)
+ {
+ BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
+ }
+
+ template <class T2> static void equals_ref(T2&)
+ {
+ BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
+ }
+
+ template <class T2> static void convertible(T2)
+ {
+ BOOST_STATIC_ASSERT((boost::is_convertible<T2, T1>::value));
+ }
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/count.hpp b/src/boost/libs/unordered/test/helpers/count.hpp
new file mode 100644
index 00000000..90372dca
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/count.hpp
@@ -0,0 +1,89 @@
+
+// Copyright 2008-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD)
+#define BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD
+
+#include <boost/core/lightweight_test.hpp>
+
+namespace test {
+ struct object_count
+ {
+ int instances;
+ int constructions;
+
+ object_count() : instances(0), constructions(0) {}
+ void reset() { *this = object_count(); }
+
+ void construct()
+ {
+ ++instances;
+ ++constructions;
+ }
+
+ void destruct()
+ {
+ if (instances == 0) {
+ BOOST_ERROR("Unbalanced constructions.");
+ } else {
+ --instances;
+ }
+ }
+
+ bool operator==(object_count const& x) const
+ {
+ return instances == x.instances && constructions == x.constructions;
+ }
+
+ bool operator!=(object_count const& x) const { return !(*this == x); }
+
+ friend std::ostream& operator<<(std::ostream& out, object_count const& c)
+ {
+ out << "[instances: " << c.instances
+ << ", constructions: " << c.constructions << "]";
+ return out;
+ }
+ };
+
+ // This won't be a problem as I'm only using a single compile unit
+ // in each test (this is actually require by the minimal test
+ // framework).
+ //
+ // boostinspect:nounnamed
+ namespace {
+ object_count global_object_count;
+ }
+
+ struct counted_object
+ {
+ counted_object() { global_object_count.construct(); }
+ counted_object(counted_object const&) { global_object_count.construct(); }
+ ~counted_object() { global_object_count.destruct(); }
+ };
+
+ struct check_instances
+ {
+ int instances_;
+ int constructions_;
+
+ check_instances()
+ : instances_(global_object_count.instances),
+ constructions_(global_object_count.constructions)
+ {
+ }
+ ~check_instances()
+ {
+ BOOST_TEST(global_object_count.instances == instances_);
+ }
+
+ int instances() const { return global_object_count.instances - instances_; }
+ int constructions() const
+ {
+ return global_object_count.constructions - constructions_;
+ }
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/equivalent.hpp b/src/boost/libs/unordered/test/helpers/equivalent.hpp
new file mode 100644
index 00000000..bd27d8df
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/equivalent.hpp
@@ -0,0 +1,96 @@
+
+// Copyright 2005-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(BOOST_UNORDERED_TESTS_EQUIVALENT_HEADER)
+#define BOOST_UNORDERED_TESTS_EQUIVALENT_HEADER
+
+#include "./fwd.hpp"
+#include "./list.hpp"
+#include "./metafunctions.hpp"
+#include <algorithm>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/unordered_map.hpp>
+#include <boost/unordered_set.hpp>
+
+namespace test {
+ template <class T1, class T2>
+ bool equivalent_impl(T1 const& x, T2 const& y, base_type)
+ {
+ return x == y;
+ }
+
+ template <class T>
+ bool equivalent_impl(
+ boost::hash<T> const&, boost::hash<T> const&, derived_type)
+ {
+ return true;
+ }
+
+ template <class T>
+ bool equivalent_impl(
+ std::equal_to<T> const&, std::equal_to<T> const&, derived_type)
+ {
+ return true;
+ }
+
+ template <class T1, class T2, class T3, class T4>
+ bool equivalent_impl(
+ std::pair<T1, T2> const& x1, std::pair<T3, T4> const& x2, derived_type)
+ {
+ return equivalent_impl(x1.first, x2.first, derived) &&
+ equivalent_impl(x1.second, x2.second, derived);
+ }
+
+ struct equivalent_type
+ {
+ equivalent_type() {}
+
+ template <class T1, class T2>
+ bool operator()(T1 const& x, T2 const& y) const
+ {
+ return equivalent_impl(x, y, derived);
+ }
+ };
+
+ const equivalent_type equivalent;
+
+ 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 test::list<typename Container::value_type> value_list;
+ value_list 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())
+ {
+ values_.sort();
+ }
+
+ 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;
+
+ value_list copy(x.begin(), x.end());
+ copy.sort();
+ return values_ == copy;
+ }
+
+ private:
+ unordered_equivalence_tester();
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/exception_test.hpp b/src/boost/libs/unordered/test/helpers/exception_test.hpp
new file mode 100644
index 00000000..8984eee9
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/exception_test.hpp
@@ -0,0 +1,348 @@
+
+// Copyright 2006-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(BOOST_UNORDERED_EXCEPTION_TEST_HEADER)
+#define BOOST_UNORDERED_EXCEPTION_TEST_HEADER
+
+#include "./count.hpp"
+#include "./test.hpp"
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/seq/elem.hpp>
+#include <boost/preprocessor/seq/for_each_product.hpp>
+
+#define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
+ UNORDERED_AUTO_TEST (name) { \
+ test_func<type> fixture; \
+ ::test::lightweight::exception_safety( \
+ fixture, BOOST_STRINGIZE(test_func<type>)); \
+ }
+
+#define UNORDERED_EXCEPTION_TEST_CASE_REPEAT(name, test_func, n, type) \
+ UNORDERED_AUTO_TEST (name) { \
+ for (unsigned i = 0; i < n; ++i) { \
+ test_func<type> fixture; \
+ ::test::lightweight::exception_safety( \
+ fixture, BOOST_STRINGIZE(test_func<type>)); \
+ } \
+ }
+
+#define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
+
+#define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
+
+#define EXCEPTION_TESTS(test_seq, param_seq) \
+ BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, (test_seq)((1))(param_seq))
+
+#define EXCEPTION_TESTS_REPEAT(n, test_seq, param_seq) \
+ BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, (test_seq)((n))(param_seq))
+
+#define EXCEPTION_TESTS_OP(r, product) \
+ UNORDERED_EXCEPTION_TEST_CASE_REPEAT( \
+ BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
+ BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(2, product))), \
+ BOOST_PP_SEQ_ELEM(0, product), BOOST_PP_SEQ_ELEM(1, product), \
+ BOOST_PP_SEQ_ELEM(2, product))
+
+#define UNORDERED_SCOPE(scope_name) \
+ for (::test::scope_guard unordered_test_guard(BOOST_STRINGIZE(scope_name)); \
+ !unordered_test_guard.dismissed(); unordered_test_guard.dismiss())
+
+#define UNORDERED_EPOINT(name) \
+ if (::test::exceptions_enabled) { \
+ UNORDERED_EPOINT_IMPL(name); \
+ }
+
+#define ENABLE_EXCEPTIONS \
+ ::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(true)
+
+#define DISABLE_EXCEPTIONS \
+ ::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(false)
+
+namespace test {
+ static char const* scope = "";
+ bool exceptions_enabled = false;
+
+ class scope_guard
+ {
+ scope_guard& operator=(scope_guard const&);
+ scope_guard(scope_guard const&);
+
+ char const* old_scope_;
+ char const* scope_;
+ bool dismissed_;
+
+ public:
+ scope_guard(char const* name)
+ : old_scope_(scope), scope_(name), dismissed_(false)
+ {
+ scope = scope_;
+ }
+
+ ~scope_guard()
+ {
+ if (dismissed_)
+ scope = old_scope_;
+ }
+
+ void dismiss() { dismissed_ = true; }
+
+ bool dismissed() const { return dismissed_; }
+ };
+
+ class exceptions_enable
+ {
+ exceptions_enable& operator=(exceptions_enable const&);
+ exceptions_enable(exceptions_enable const&);
+
+ bool old_value_;
+ bool released_;
+
+ public:
+ exceptions_enable(bool enable)
+ : old_value_(exceptions_enabled), released_(false)
+ {
+ exceptions_enabled = enable;
+ }
+
+ ~exceptions_enable()
+ {
+ if (!released_) {
+ exceptions_enabled = old_value_;
+ released_ = true;
+ }
+ }
+
+ void release()
+ {
+ if (!released_) {
+ exceptions_enabled = old_value_;
+ released_ = true;
+ }
+ }
+ };
+
+ struct exception_base
+ {
+ struct data_type
+ {
+ };
+ struct strong_type
+ {
+ template <class T> void store(T const&) {}
+ template <class T> void test(T const&) const {}
+ };
+ data_type init() const { return data_type(); }
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION() const {}
+ };
+
+ template <class T, class P1, class P2, class T2>
+ inline void call_ignore_extra_parameters(
+ void (T::*fn)() const, T2 const& obj, P1&, P2&)
+ {
+ (obj.*fn)();
+ }
+
+ template <class T, class P1, class P2, class T2>
+ inline void call_ignore_extra_parameters(
+ void (T::*fn)(P1&) const, T2 const& obj, P1& p1, P2&)
+ {
+ (obj.*fn)(p1);
+ }
+
+ template <class T, class P1, class P2, class T2>
+ inline void call_ignore_extra_parameters(
+ void (T::*fn)(P1&, P2&) const, T2 const& obj, P1& p1, P2& p2)
+ {
+ (obj.*fn)(p1, p2);
+ }
+
+ template <class T> T const& constant(T const& x) { return x; }
+
+ template <class Test> class test_runner
+ {
+ Test const& test_;
+ bool exception_in_check_;
+
+ test_runner(test_runner const&);
+ test_runner& operator=(test_runner const&);
+
+ public:
+ test_runner(Test const& t) : test_(t), exception_in_check_(false) {}
+ void run()
+ {
+ DISABLE_EXCEPTIONS;
+ test::check_instances check;
+ test::scope = "";
+ typename Test::data_type x(test_.init());
+ typename Test::strong_type strong;
+ strong.store(x);
+ try {
+ ENABLE_EXCEPTIONS;
+ call_ignore_extra_parameters<Test, typename Test::data_type,
+ typename Test::strong_type>(&Test::run, test_, x, strong);
+ } catch (...) {
+ try {
+ DISABLE_EXCEPTIONS;
+ call_ignore_extra_parameters<Test, typename Test::data_type const,
+ typename Test::strong_type const>(
+ &Test::check, test_, constant(x), constant(strong));
+ } catch (...) {
+ exception_in_check_ = true;
+ }
+ throw;
+ }
+ }
+ void end()
+ {
+ if (exception_in_check_) {
+ BOOST_ERROR("Unexcpected exception in test_runner check call.");
+ }
+ }
+ };
+
+ // Quick exception testing based on lightweight test
+
+ namespace lightweight {
+ static int iteration;
+ static int count;
+
+ struct test_exception
+ {
+ char const* name;
+ test_exception(char const* n) : name(n) {}
+ };
+
+ struct test_failure
+ {
+ };
+
+ void epoint(char const* name)
+ {
+ ++count;
+ if (count == iteration) {
+ throw test_exception(name);
+ }
+ }
+
+ template <class Test>
+ void exception_safety(Test const& f, char const* /*name*/)
+ {
+ test_runner<Test> runner(f);
+
+ iteration = 0;
+ bool success = false;
+ unsigned int failure_count = 0;
+ char const* error_msg = 0;
+ do {
+ int error_count = boost::detail::test_errors();
+ ++iteration;
+ count = 0;
+
+ try {
+ runner.run();
+ success = true;
+ } catch (test_failure) {
+ error_msg = "test_failure caught.";
+ break;
+ } catch (test_exception e) {
+ if (error_count != boost::detail::test_errors()) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << "Iteration: " << iteration
+ << " Error found for epoint: " << e.name << std::endl;
+ }
+ } catch (...) {
+ error_msg = "Unexpected exception.";
+ break;
+ }
+
+ if (error_count != boost::detail::test_errors()) {
+ ++failure_count;
+ }
+ } while (!success && failure_count < 5);
+
+ if (error_msg) {
+ BOOST_ERROR(error_msg);
+ }
+ runner.end();
+ }
+
+ //
+ // An alternative way to run exception tests.
+ // See merge_exception_tests.cpp for an example.
+
+ struct exception_looper
+ {
+ bool success;
+ unsigned int failure_count;
+ char const* error_msg;
+ int error_count;
+
+ exception_looper() : success(false), failure_count(0), error_msg(0) {}
+
+ void start() { iteration = 0; }
+
+ bool loop_condition() const
+ {
+ return !error_msg && !success && failure_count < 5;
+ }
+
+ void start_iteration()
+ {
+ error_count = boost::detail::test_errors();
+ ++iteration;
+ count = 0;
+ }
+
+ void successful_run() { success = true; }
+
+ void test_failure_caught(test_failure const&)
+ {
+ error_msg = "test_failure caught.";
+ }
+
+ void test_exception_caught(test_exception const& e)
+ {
+ if (error_count != boost::detail::test_errors()) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << "Iteration: " << iteration
+ << " Error found for epoint: " << e.name << std::endl;
+ }
+ }
+
+ void unexpected_exception_caught()
+ {
+ error_msg = "Unexpected exception.";
+ }
+
+ void end()
+ {
+ if (error_msg) {
+ BOOST_ERROR(error_msg);
+ }
+ }
+ };
+
+#define EXCEPTION_LOOP(op) \
+ test::lightweight::exception_looper looper; \
+ looper.start(); \
+ while (looper.loop_condition()) { \
+ looper.start_iteration(); \
+ try { \
+ op; \
+ looper.successful_run(); \
+ } catch (test::lightweight::test_failure e) { \
+ looper.test_failure_caught(e); \
+ } catch (test::lightweight::test_exception e) { \
+ looper.test_exception_caught(e); \
+ } catch (...) { \
+ looper.unexpected_exception_caught(); \
+ } \
+ } \
+ looper.end();
+ }
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/fwd.hpp b/src/boost/libs/unordered/test/helpers/fwd.hpp
new file mode 100644
index 00000000..a5657e01
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/fwd.hpp
@@ -0,0 +1,32 @@
+
+// Copyright 2006-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_FWD_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_FWD_HEADER
+
+#include <string>
+
+namespace test {
+ typedef enum {
+ default_generator,
+ generate_collisions,
+ limited_range
+ } random_generator;
+
+ int generate(int const*, random_generator);
+ char generate(char const*, random_generator);
+ signed char generate(signed char const*, random_generator);
+ std::string generate(std::string const*, random_generator);
+ float generate(float const*, random_generator);
+
+ struct base_type
+ {
+ } base;
+ struct derived_type : base_type
+ {
+ } derived;
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/generators.hpp b/src/boost/libs/unordered/test/helpers/generators.hpp
new file mode 100644
index 00000000..c9ed42bd
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/generators.hpp
@@ -0,0 +1,93 @@
+
+// Copyright 2005-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This uses std::rand to generate random values for tests.
+// Which is not good as different platforms will be running different tests.
+// It would be much better to use Boost.Random, but it doesn't
+// support all the compilers that I want to test on.
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_GENERATORS_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_GENERATORS_HEADER
+
+#include "./fwd.hpp"
+#include <boost/type_traits/add_const.hpp>
+#include <cstdlib>
+#include <stdexcept>
+#include <string>
+#include <utility>
+
+namespace test {
+ struct seed_t
+ {
+ seed_t(unsigned int x)
+ {
+ using namespace std;
+ srand(x);
+ }
+ };
+
+ std::size_t random_value(std::size_t max)
+ {
+ using namespace std;
+ return static_cast<std::size_t>(rand()) % max;
+ }
+
+ inline int generate(int const*, random_generator g)
+ {
+ using namespace std;
+ int value = rand();
+ if (g == limited_range) {
+ value = value % 100;
+ }
+ return value;
+ }
+
+ inline char generate(char const*, random_generator)
+ {
+ using namespace std;
+ return static_cast<char>((rand() >> 1) % (128 - 32) + 32);
+ }
+
+ inline signed char generate(signed char const*, random_generator)
+ {
+ using namespace std;
+ return static_cast<signed char>(rand());
+ }
+
+ inline std::string generate(std::string const*, random_generator g)
+ {
+ using namespace std;
+
+ char* char_ptr = 0;
+
+ std::string result;
+
+ if (g == limited_range) {
+ std::size_t length = test::random_value(2) + 2;
+
+ char const* strings[] = {"'vZh(3~ms", "%m", "_Y%U", "N'Y", "4,J_J"};
+ for (std::size_t i = 0; i < length; ++i) {
+ result += strings[random_value(sizeof(strings) / sizeof(strings[0]))];
+ }
+ } else {
+ std::size_t length = test::random_value(10) + 1;
+ for (std::size_t i = 0; i < length; ++i) {
+ result += generate(char_ptr, g);
+ }
+ }
+
+ return result;
+ }
+
+ float generate(float const*, random_generator g)
+ {
+ using namespace std;
+ int x = 0;
+ int value = generate(&x, g);
+ return (float)value / (float)RAND_MAX;
+ }
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/helpers.hpp b/src/boost/libs/unordered/test/helpers/helpers.hpp
new file mode 100644
index 00000000..146dea4d
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/helpers.hpp
@@ -0,0 +1,56 @@
+
+// Copyright 2006-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_HEADER
+
+#include <iterator>
+
+namespace test {
+ template <class Container> struct get_key_impl
+ {
+ typedef typename Container::key_type key_type;
+
+ static key_type const& get_key(key_type const& x) { return x; }
+
+ template <class T>
+ static key_type const& get_key(std::pair<key_type, T> const& x, char = 0)
+ {
+ return x.first;
+ }
+
+ template <class T>
+ static key_type const& get_key(
+ std::pair<key_type const, T> const& x, unsigned char = 0)
+ {
+ return x.first;
+ }
+ };
+
+ template <class Container, class T>
+ inline typename Container::key_type const& get_key(T const& x)
+ {
+ return get_key_impl<Container>::get_key(x);
+ }
+
+ // test::next
+ //
+ // Increments an iterator by 1 or a given value.
+ // Like boost::next, but simpler.
+ // Mainly because boost::next uses an MPL file
+ // which causes warnings.
+
+ template <typename Iterator> Iterator next(Iterator it) { return ++it; }
+
+ template <typename Iterator, typename IntType>
+ Iterator next(Iterator it, IntType x)
+ {
+ std::advance(it,
+ static_cast<typename std::iterator_traits<Iterator>::difference_type>(x));
+ return it;
+ }
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/input_iterator.hpp b/src/boost/libs/unordered/test/helpers/input_iterator.hpp
new file mode 100644
index 00000000..7a938a50
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/input_iterator.hpp
@@ -0,0 +1,165 @@
+
+// Copyright 2005-2010 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER
+
+#include <boost/config.hpp>
+#include <iterator>
+
+namespace test {
+ template <class Iterator> struct proxy
+ {
+ typedef typename Iterator::value_type value_type;
+
+ explicit proxy(value_type const& v) : v_(v) {}
+ proxy(proxy const& x) : v_(x.v_) {}
+ operator value_type const&() const { return v_; }
+
+ value_type v_;
+
+ private:
+ proxy& operator=(proxy const&);
+ };
+
+ template <class Iterator> struct input_iterator_adaptor
+ {
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+ typedef typename std::iterator_traits<Iterator>::pointer pointer;
+ typedef proxy<Iterator> reference;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::input_iterator_tag iterator_category;
+
+ input_iterator_adaptor() : base_() {}
+ explicit input_iterator_adaptor(Iterator& it) : base_(&it) {}
+ proxy<Iterator> operator*() const { return proxy<Iterator>(**base_); }
+ value_type* operator->() const { return &**base_; }
+ input_iterator_adaptor& operator++()
+ {
+ ++*base_;
+ return *this;
+ }
+ // input_iterator_adaptor operator++(int) {
+ //}
+ bool operator==(input_iterator_adaptor const& x) const
+ {
+ return *base_ == *x.base_;
+ }
+ bool operator!=(input_iterator_adaptor const& x) const
+ {
+ return *base_ != *x.base_;
+ }
+
+ private:
+ Iterator* base_;
+ };
+
+ template <class Iterator>
+ input_iterator_adaptor<Iterator> input_iterator(Iterator& it)
+ {
+ return input_iterator_adaptor<Iterator>(it);
+ }
+
+ template <class Iterator> struct copy_iterator_adaptor
+ {
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+ typedef
+ typename std::iterator_traits<Iterator>::difference_type difference_type;
+ typedef typename std::iterator_traits<Iterator>::iterator_category
+ iterator_category;
+ typedef typename std::iterator_traits<Iterator>::pointer pointer;
+ typedef proxy<Iterator> reference;
+
+ copy_iterator_adaptor() : base_() {}
+ explicit copy_iterator_adaptor(Iterator const& it) : base_(it) {}
+ value_type operator*() const { return *base_; }
+ value_type* operator->() const { return &*base_; }
+ value_type operator[](difference_type d) { return base_[d]; }
+ copy_iterator_adaptor& operator++()
+ {
+ ++base_;
+ return *this;
+ }
+ copy_iterator_adaptor operator++(int)
+ {
+ copy_iterator_adaptor tmp(*this);
+ ++base_;
+ return tmp;
+ }
+ copy_iterator_adaptor& operator--()
+ {
+ --base_;
+ return *this;
+ }
+ copy_iterator_adaptor operator--(int)
+ {
+ copy_iterator_adaptor tmp(*this);
+ --base_;
+ return tmp;
+ }
+ copy_iterator_adaptor operator+=(difference_type x)
+ {
+ base_ += x;
+ return *this;
+ }
+ copy_iterator_adaptor operator-=(difference_type x)
+ {
+ base_ -= x;
+ return *this;
+ }
+ copy_iterator_adaptor operator+(difference_type n)
+ {
+ return copy_iterator_adaptor(base_ + n);
+ }
+ copy_iterator_adaptor operator-(difference_type n)
+ {
+ return copy_iterator_adaptor(base_ - n);
+ }
+ friend copy_iterator_adaptor operator+(
+ difference_type n, copy_iterator_adaptor x)
+ {
+ return x + n;
+ }
+ difference_type operator-(copy_iterator_adaptor const& other)
+ {
+ return base_ - other.base_;
+ }
+ bool operator==(copy_iterator_adaptor const& x) const
+ {
+ return base_ == x.base_;
+ }
+ bool operator!=(copy_iterator_adaptor const& x) const
+ {
+ return base_ != x.base_;
+ }
+ bool operator<(copy_iterator_adaptor const& x) const
+ {
+ return base_ < x.base_;
+ }
+ bool operator>(copy_iterator_adaptor const& x) const
+ {
+ return base_ > x.base_;
+ }
+ bool operator<=(copy_iterator_adaptor const& x) const
+ {
+ return base_ <= x.base_;
+ }
+ bool operator>=(copy_iterator_adaptor const& x) const
+ {
+ return base_ >= x.base_;
+ }
+
+ private:
+ Iterator base_;
+ };
+
+ template <class Iterator>
+ copy_iterator_adaptor<Iterator> copy_iterator(Iterator const& it)
+ {
+ return copy_iterator_adaptor<Iterator>(it);
+ }
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/invariants.hpp b/src/boost/libs/unordered/test/helpers/invariants.hpp
new file mode 100644
index 00000000..a555da60
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/invariants.hpp
@@ -0,0 +1,130 @@
+
+// Copyright 2006-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// 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 "./helpers.hpp"
+#include "./metafunctions.hpp"
+#include <cmath>
+#include <set>
+
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning(disable : 4267) // conversion from 'size_t' to 'unsigned int',
+ // possible loss of data
+#endif
+
+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, std::less<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 occurred 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_.insert(key).second)
+ BOOST_ERROR("Elements with equivalent keys aren't adjacent.");
+
+ // 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.");
+ std::cerr << x1.count(key) << "," << count << "\n";
+ }
+
+ // 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);
+
+ unsigned int count_checked = 0;
+ for (; lit != lend && !eq(get_key<X>(*lit), key); ++lit) {
+ ++count_checked;
+ }
+
+ if (lit == lend) {
+ BOOST_ERROR("Unable to find element with a local_iterator");
+ std::cerr << "Checked: " << count_checked << " elements" << std::endl;
+ } else {
+ 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;
+ }
+ }
+ }
+ };
+
+ // Check that size matches up.
+
+ if (x1.size() != size) {
+ BOOST_ERROR("x1.size() doesn't match actual size.");
+ std::cout << x1.size() << "/" << size << std::endl;
+ }
+
+ // Check the load factor.
+
+ float load_factor = size == 0 ? 0
+ : static_cast<float>(size) /
+ static_cast<float>(x1.bucket_count());
+ using namespace std;
+ if (fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64)
+ BOOST_ERROR("x1.load_factor() doesn't match actual load_factor.");
+
+ // Check that size in the buckets matches up.
+
+ typename X::size_type bucket_size = 0;
+
+ for (typename X::size_type i = 0; i < x1.bucket_count(); ++i) {
+ for (typename X::const_local_iterator begin2 = x1.begin(i),
+ end2 = x1.end(i);
+ begin2 != end2; ++begin2) {
+ ++bucket_size;
+ }
+ }
+
+ if (x1.size() != bucket_size) {
+ BOOST_ERROR("x1.size() doesn't match bucket size.");
+ std::cout << x1.size() << "/" << bucket_size << std::endl;
+ }
+ }
+}
+
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/list.hpp b/src/boost/libs/unordered/test/helpers/list.hpp
new file mode 100644
index 00000000..d39c766e
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/list.hpp
@@ -0,0 +1,327 @@
+
+// Copyright 2008-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Gratuitous single linked list.
+//
+// Sadly some STL implementations aren't up to scratch and I need a simple
+// cross-platform container. So here it is.
+
+#if !defined(UNORDERED_TEST_LIST_HEADER)
+#define UNORDERED_TEST_LIST_HEADER
+
+#include <boost/limits.hpp>
+#include <functional>
+#include <iterator>
+
+namespace test {
+ template <typename It1, typename It2>
+ bool equal(It1 begin, It1 end, It2 compare)
+ {
+ for (; begin != end; ++begin, ++compare)
+ if (*begin != *compare)
+ return false;
+ return true;
+ }
+
+ template <typename It1, typename It2, typename Pred>
+ bool equal(It1 begin, It1 end, It2 compare, Pred predicate)
+ {
+ for (; begin != end; ++begin, ++compare)
+ if (!predicate(*begin, *compare))
+ return false;
+ return true;
+ }
+
+ template <typename T> class list;
+
+ namespace test_detail {
+ template <typename T> class list_node;
+ template <typename T> class list_data;
+ template <typename T> class list_iterator;
+ template <typename T> class list_const_iterator;
+
+ template <typename T> class list_node
+ {
+ list_node(list_node const&);
+ list_node& operator=(list_node const&);
+
+ public:
+ T value_;
+ list_node* next_;
+
+ list_node(T const& v) : value_(v), next_(0) {}
+ list_node(T const& v, list_node* n) : value_(v), next_(n) {}
+ };
+
+ template <typename T> class list_data
+ {
+ public:
+ typedef list_node<T> node;
+ typedef unsigned int size_type;
+
+ node* first_;
+ node** last_ptr_;
+ size_type size_;
+
+ list_data() : first_(0), last_ptr_(&first_), size_(0) {}
+
+ ~list_data()
+ {
+ while (first_) {
+ node* tmp = first_;
+ first_ = first_->next_;
+ delete tmp;
+ }
+ }
+
+ private:
+ list_data(list_data const&);
+ list_data& operator=(list_data const&);
+ };
+
+ template <typename T> class list_iterator
+ {
+ friend class list_const_iterator<T>;
+ friend class test::list<T>;
+ typedef list_node<T> node;
+ typedef list_const_iterator<T> const_iterator;
+
+ node* ptr_;
+
+ public:
+ typedef T value_type;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef int difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ list_iterator() : ptr_(0) {}
+ explicit list_iterator(node* x) : ptr_(x) {}
+
+ T& operator*() const { return ptr_->value_; }
+ T* operator->() const { return &ptr_->value_; }
+ list_iterator& operator++()
+ {
+ ptr_ = ptr_->next_;
+ return *this;
+ }
+ list_iterator operator++(int)
+ {
+ list_iterator tmp = *this;
+ ptr_ = ptr_->next_;
+ return tmp;
+ }
+ bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
+ bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
+ };
+
+ template <typename T> class list_const_iterator
+ {
+ friend class list_iterator<T>;
+ friend class test::list<T>;
+ typedef list_node<T> node;
+ typedef list_iterator<T> iterator;
+ typedef list_const_iterator<T> const_iterator;
+
+ node* ptr_;
+
+ public:
+ typedef T value_type;
+ typedef T const* pointer;
+ typedef T const& reference;
+ typedef int difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ list_const_iterator() : ptr_(0) {}
+ list_const_iterator(list_iterator<T> const& x) : ptr_(x.ptr_) {}
+
+ T const& operator*() const { return ptr_->value_; }
+ T const* operator->() const { return &ptr_->value_; }
+
+ list_const_iterator& operator++()
+ {
+ ptr_ = ptr_->next_;
+ return *this;
+ }
+
+ list_const_iterator operator++(int)
+ {
+ list_const_iterator tmp = *this;
+ ptr_ = ptr_->next_;
+ return tmp;
+ }
+
+ bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
+
+ bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
+ };
+ }
+
+ template <typename T> class list
+ {
+ typedef test::test_detail::list_data<T> data;
+ typedef test::test_detail::list_node<T> node;
+ data data_;
+
+ public:
+ typedef T value_type;
+ typedef value_type& reference;
+ typedef value_type const& const_reference;
+ typedef unsigned int size_type;
+
+ typedef test::test_detail::list_iterator<T> iterator;
+ typedef test::test_detail::list_const_iterator<T> const_iterator;
+
+ list() : data_() {}
+
+ list(list const& other) : data_() { insert(other.begin(), other.end()); }
+
+ template <class InputIterator>
+ list(InputIterator i, InputIterator j) : data_()
+ {
+ insert(i, j);
+ }
+
+ list& operator=(list const& other)
+ {
+ clear();
+ insert(other.begin(), other.end());
+ return *this;
+ }
+
+ iterator begin() { return iterator(data_.first_); }
+ iterator end() { return iterator(); }
+ const_iterator begin() const { return iterator(data_.first_); }
+ const_iterator end() const { return iterator(); }
+ const_iterator cbegin() const { return iterator(data_.first_); }
+ const_iterator cend() const { return iterator(); }
+
+ template <class InputIterator> void insert(InputIterator i, InputIterator j)
+ {
+ for (; i != j; ++i)
+ push_back(*i);
+ }
+
+ void push_front(value_type const& v)
+ {
+ data_.first_ = new node(v, data_.first_);
+ if (!data_.size_)
+ data_.last_ptr_ = &(*data_.last_ptr_)->next_;
+ ++data_.size_;
+ }
+
+ void push_back(value_type const& v)
+ {
+ *data_.last_ptr_ = new node(v);
+ data_.last_ptr_ = &(*data_.last_ptr_)->next_;
+ ++data_.size_;
+ }
+
+ void clear()
+ {
+ while (data_.first_) {
+ node* tmp = data_.first_;
+ data_.first_ = data_.first_->next_;
+ --data_.size_;
+ delete tmp;
+ }
+ data_.last_ptr_ = &data_.first_;
+ }
+
+ void erase(const_iterator i, const_iterator j)
+ {
+ node** ptr = &data_.first_;
+
+ while (*ptr != i.ptr_) {
+ ptr = &(*ptr)->next_;
+ }
+
+ while (*ptr != j.ptr_) {
+ node* to_delete = *ptr;
+ *ptr = (*ptr)->next_;
+ --data_.size_;
+ delete to_delete;
+ }
+
+ if (!*ptr)
+ data_.last_ptr_ = ptr;
+ }
+
+ bool empty() const { return !data_.size_; }
+
+ size_type size() const { return data_.size_; }
+
+ void sort() { sort(std::less<T>()); }
+
+ template <typename Less> void sort(Less less = Less())
+ {
+ if (!empty())
+ merge_sort(
+ &data_.first_, (std::numeric_limits<size_type>::max)(), less);
+ }
+
+ bool operator==(list const& y) const
+ {
+ return size() == y.size() && test::equal(begin(), end(), y.begin());
+ }
+
+ bool operator!=(list const& y) const { return !(*this == y); }
+
+ private:
+ template <typename Less>
+ node** merge_sort(node** l, size_type recurse_limit, Less less)
+ {
+ node** ptr = &(*l)->next_;
+ for (size_type count = 0; count < recurse_limit && *ptr; ++count) {
+ ptr = merge_adjacent_ranges(l, ptr, merge_sort(ptr, count, less), less);
+ }
+ return ptr;
+ }
+
+ template <typename Less>
+ node** merge_adjacent_ranges(
+ node** first, node** second, node** third, Less less)
+ {
+ for (;;) {
+ for (;;) {
+ if (first == second)
+ return third;
+ if (less((*second)->value_, (*first)->value_))
+ break;
+ first = &(*first)->next_;
+ }
+
+ swap_adjacent_ranges(first, second, third);
+ first = &(*first)->next_;
+
+ // Since the two ranges we just swapped, the order is now:
+ // first...third...second
+
+ for (;;) {
+ if (first == third)
+ return second;
+ if (!less((*first)->value_, (*third)->value_))
+ break;
+ first = &(*first)->next_;
+ }
+
+ swap_adjacent_ranges(first, third, second);
+ first = &(*first)->next_;
+ }
+ }
+
+ void swap_adjacent_ranges(node** first, node** second, node** third)
+ {
+ node* tmp = *first;
+ *first = *second;
+ *second = *third;
+ *third = tmp;
+ if (!*second)
+ data_.last_ptr_ = second;
+ }
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/memory.hpp b/src/boost/libs/unordered/test/helpers/memory.hpp
new file mode 100644
index 00000000..22946cc2
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/memory.hpp
@@ -0,0 +1,189 @@
+
+// Copyright 2006-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(BOOST_UNORDERED_TEST_MEMORY_HEADER)
+#define BOOST_UNORDERED_TEST_MEMORY_HEADER
+
+#include "../helpers/test.hpp"
+#include <boost/assert.hpp>
+#include <boost/unordered/detail/implementation.hpp>
+#include <map>
+#include <memory>
+
+namespace test {
+ namespace detail {
+ struct memory_area
+ {
+ void const* start;
+ void const* end;
+
+ memory_area(void const* s, void const* e) : start(s), end(e)
+ {
+ BOOST_ASSERT(start != end);
+ }
+ };
+
+ struct memory_track
+ {
+ explicit memory_track(int tag = -1) : constructed_(0), tag_(tag) {}
+
+ int constructed_;
+ int tag_;
+ };
+
+ // This is a bit dodgy as it defines overlapping
+ // areas as 'equal', so this isn't a total ordering.
+ // But it is for non-overlapping memory regions - which
+ // is what'll be stored.
+ //
+ // All searches will be for areas entirely contained by
+ // a member of the set - so it should find the area that contains
+ // the region that is searched for.
+
+ struct memory_area_compare
+ {
+ bool operator()(memory_area const& x, memory_area const& y) const
+ {
+ return x.end <= y.start;
+ }
+ };
+
+ struct memory_tracker
+ {
+ typedef std::map<memory_area, memory_track, memory_area_compare,
+ std::allocator<std::pair<memory_area const, memory_track> > >
+ allocated_memory_type;
+
+ allocated_memory_type allocated_memory;
+ unsigned int count_allocators;
+ unsigned int count_allocations;
+ unsigned int count_constructions;
+ bool tracking_constructions;
+
+ memory_tracker()
+ : count_allocators(0), count_allocations(0), count_constructions(0),
+ tracking_constructions(true)
+ {
+ }
+
+ ~memory_tracker() { BOOST_TEST(count_allocators == 0); }
+
+ void allocator_ref()
+ {
+ if (count_allocators == 0) {
+ count_allocations = 0;
+ count_constructions = 0;
+ allocated_memory.clear();
+ }
+ ++count_allocators;
+ }
+
+ void allocator_unref()
+ {
+ BOOST_TEST(count_allocators > 0);
+ if (count_allocators > 0) {
+ --count_allocators;
+ if (count_allocators == 0) {
+ bool no_allocations_left = (count_allocations == 0);
+ bool no_constructions_left = (count_constructions == 0);
+ bool allocated_memory_empty = allocated_memory.empty();
+
+ // Clearing the data before the checks terminate the
+ // tests.
+ count_allocations = 0;
+ count_constructions = 0;
+ allocated_memory.clear();
+
+ BOOST_TEST(no_allocations_left);
+ BOOST_TEST(no_constructions_left);
+ BOOST_TEST(allocated_memory_empty);
+ }
+ }
+ }
+
+ void track_allocate(void* ptr, std::size_t n, std::size_t size, int tag)
+ {
+ if (n == 0) {
+ BOOST_ERROR("Allocating 0 length array.");
+ } else {
+ ++count_allocations;
+ allocated_memory.insert(std::pair<memory_area const, memory_track>(
+ memory_area(ptr, (char*)ptr + n * size), memory_track(tag)));
+ }
+ }
+
+ void track_deallocate(void* ptr, std::size_t n, std::size_t size, int tag,
+ bool check_tag_ = true)
+ {
+ allocated_memory_type::iterator pos =
+ allocated_memory.find(memory_area(ptr, (char*)ptr + n * size));
+ if (pos == allocated_memory.end()) {
+ BOOST_ERROR("Deallocating unknown pointer.");
+ } else {
+ BOOST_TEST(pos->first.start == ptr);
+ BOOST_TEST(pos->first.end == (char*)ptr + n * size);
+ if (check_tag_)
+ BOOST_TEST(pos->second.tag_ == tag);
+ allocated_memory.erase(pos);
+ }
+ BOOST_TEST(count_allocations > 0);
+ if (count_allocations > 0)
+ --count_allocations;
+ }
+
+ void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
+ {
+ if (tracking_constructions) {
+ ++count_constructions;
+ }
+ }
+
+ void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
+ {
+ if (tracking_constructions) {
+ BOOST_TEST(count_constructions > 0);
+ if (count_constructions > 0)
+ --count_constructions;
+ }
+ }
+ };
+ }
+
+ namespace detail {
+ // This won't be a problem as I'm only using a single compile unit
+ // in each test (this is actually required by the minimal test
+ // framework).
+ //
+ // boostinspect:nounnamed
+ namespace {
+ test::detail::memory_tracker tracker;
+ }
+ }
+
+ namespace detail {
+ struct disable_construction_tracking
+ {
+ bool old_value;
+
+ disable_construction_tracking()
+ : old_value(detail::tracker.tracking_constructions)
+ {
+ test::detail::tracker.tracking_constructions = false;
+ }
+
+ ~disable_construction_tracking()
+ {
+ test::detail::tracker.tracking_constructions = old_value;
+ }
+
+ private:
+ disable_construction_tracking(disable_construction_tracking const&);
+ disable_construction_tracking& operator=(
+ disable_construction_tracking const&);
+ };
+ }
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/metafunctions.hpp b/src/boost/libs/unordered/test/helpers/metafunctions.hpp
new file mode 100644
index 00000000..f5f13851
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/metafunctions.hpp
@@ -0,0 +1,30 @@
+
+// Copyright 2005-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#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>
+
+namespace test {
+ template <class Container>
+ struct is_set : public boost::is_same<typename Container::key_type,
+ typename Container::value_type>
+ {
+ };
+
+ template <class Container> struct has_unique_keys
+ {
+ static char flip(typename Container::iterator const&);
+ static long flip(std::pair<typename Container::iterator, bool> const&);
+ BOOST_STATIC_CONSTANT(bool,
+ value = sizeof(long) ==
+ sizeof(flip(
+ ((Container*)0)->insert(*(typename Container::value_type*)0))));
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/postfix.hpp b/src/boost/libs/unordered/test/helpers/postfix.hpp
new file mode 100644
index 00000000..ca14ae71
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/postfix.hpp
@@ -0,0 +1,10 @@
+
+// Copyright 2012 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Include this after the boost headers, but before other test headers.
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/prefix.hpp b/src/boost/libs/unordered/test/helpers/prefix.hpp
new file mode 100644
index 00000000..fe757025
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/prefix.hpp
@@ -0,0 +1,11 @@
+
+// Copyright 2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if defined(_WIN32_WCE)
+// The standard windows mobile headers trigger this warning so I disable it
+// before doing anything else.
+#pragma warning(disable : 4201) // nonstandard extension used :
+ // nameless struct/union
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/random_values.hpp b/src/boost/libs/unordered/test/helpers/random_values.hpp
new file mode 100644
index 00000000..d139d180
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/random_values.hpp
@@ -0,0 +1,109 @@
+
+// Copyright 2005-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_RANDOM_VALUES_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_RANDOM_VALUES_HEADER
+
+#include "./generators.hpp"
+#include "./list.hpp"
+#include "./metafunctions.hpp"
+#include <algorithm>
+#include <boost/detail/select_type.hpp>
+
+namespace test {
+ template <class X> struct unordered_generator_set
+ {
+ typedef typename X::value_type value_type;
+
+ random_generator type_;
+
+ unordered_generator_set(random_generator type) : type_(type) {}
+
+ template <class T> void fill(T& x, std::size_t len)
+ {
+ value_type* value_ptr = 0;
+ len += x.size();
+
+ for (std::size_t i = 0; i < len; ++i) {
+ value_type value = generate(value_ptr, type_);
+
+ std::size_t count =
+ type_ == generate_collisions ? random_value(5) + 1 : 1;
+
+ for (std::size_t j = 0; j < count; ++j) {
+ x.push_back(value);
+ }
+ }
+ }
+ };
+
+ template <class X> struct unordered_generator_map
+ {
+ typedef typename X::key_type key_type;
+ typedef typename X::mapped_type mapped_type;
+
+ random_generator type_;
+
+ unordered_generator_map(random_generator type) : type_(type) {}
+
+ template <class T> void fill(T& x, std::size_t len)
+ {
+ key_type* key_ptr = 0;
+ mapped_type* mapped_ptr = 0;
+
+ for (std::size_t i = 0; i < len; ++i) {
+ key_type key = generate(key_ptr, type_);
+
+ std::size_t count =
+ type_ == generate_collisions ? random_value(5) + 1 : 1;
+
+ for (std::size_t j = 0; j < count; ++j) {
+ x.push_back(std::pair<key_type const, mapped_type>(
+ key, generate(mapped_ptr, type_)));
+ }
+ }
+ }
+ };
+
+ template <class X>
+ struct unordered_generator_base
+ : public boost::detail::if_true<test::is_set<X>::value>::
+ BOOST_NESTED_TEMPLATE then<test::unordered_generator_set<X>,
+ test::unordered_generator_map<X> >
+ {
+ };
+
+ template <class X>
+ struct unordered_generator : public unordered_generator_base<X>::type
+ {
+ typedef typename unordered_generator_base<X>::type base;
+
+ unordered_generator(random_generator const& type = default_generator)
+ : base(type)
+ {
+ }
+ };
+
+ template <class X>
+ struct random_values : public test::list<typename X::value_type>
+ {
+ random_values() {}
+
+ explicit random_values(std::size_t count,
+ test::random_generator const& generator = test::default_generator)
+ {
+ fill(count, generator);
+ }
+
+ void fill(std::size_t count,
+ test::random_generator const& generator = test::default_generator)
+ {
+ test::unordered_generator<X> gen(generator);
+ gen.fill(*this, count);
+ }
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/strong.hpp b/src/boost/libs/unordered/test/helpers/strong.hpp
new file mode 100644
index 00000000..3c936133
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/strong.hpp
@@ -0,0 +1,42 @@
+
+// Copyright 2005-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_STRONG_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_STRONG_HEADER
+
+#include "./equivalent.hpp"
+#include "./exception_test.hpp"
+#include "./list.hpp"
+#include <boost/config.hpp>
+#include <iterator>
+
+namespace test {
+ template <class X> class strong
+ {
+ typedef test::list<typename X::value_type> values_type;
+ values_type values_;
+ unsigned int allocations_;
+
+ public:
+ void store(X const& x, unsigned int allocations = 0)
+ {
+ DISABLE_EXCEPTIONS;
+ values_.clear();
+ values_.insert(x.cbegin(), x.cend());
+ allocations_ = allocations;
+ }
+
+ void test(X const& x, unsigned int allocations = 0) const
+ {
+ if (!(x.size() == values_.size() && test::equal(x.cbegin(), x.cend(),
+ values_.begin(), test::equivalent)))
+ BOOST_ERROR("Strong exception safety failure.");
+ if (allocations != allocations_)
+ BOOST_ERROR("Strong exception failure: extra allocations.");
+ }
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/test.hpp b/src/boost/libs/unordered/test/helpers/test.hpp
new file mode 100644
index 00000000..5534f811
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/test.hpp
@@ -0,0 +1,201 @@
+
+// Copyright 2006-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(BOOST_UNORDERED_TEST_TEST_HEADER)
+#define BOOST_UNORDERED_TEST_TEST_HEADER
+
+#include <boost/core/lightweight_test.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/stringize.hpp>
+
+#define UNORDERED_AUTO_TEST(x) \
+ struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base \
+ { \
+ BOOST_PP_CAT(x, _type) \
+ () : ::test::registered_test_base(BOOST_PP_STRINGIZE(x)) \
+ { \
+ ::test::get_state().add_test(this); \
+ } \
+ void run(); \
+ }; \
+ BOOST_PP_CAT(x, _type) x; \
+ void BOOST_PP_CAT(x, _type)::run()
+
+#define RUN_TESTS() \
+ int main(int, char**) \
+ { \
+ BOOST_UNORDERED_TEST_COMPILER_INFO() \
+ ::test::get_state().run_tests(); \
+ return boost::report_errors(); \
+ }
+
+#define RUN_TESTS_QUIET() \
+ int main(int, char**) \
+ { \
+ BOOST_UNORDERED_TEST_COMPILER_INFO() \
+ ::test::get_state().run_tests(true); \
+ return boost::report_errors(); \
+ }
+
+#define UNORDERED_SUB_TEST(x) \
+ for (int UNORDERED_SUB_TEST_VALUE = ::test::get_state().start_sub_test(x); \
+ UNORDERED_SUB_TEST_VALUE; \
+ UNORDERED_SUB_TEST_VALUE = \
+ ::test::get_state().end_sub_test(x, UNORDERED_SUB_TEST_VALUE))
+
+namespace test {
+
+ struct registered_test_base
+ {
+ registered_test_base* next;
+ char const* name;
+ explicit registered_test_base(char const* n) : name(n) {}
+ virtual void run() = 0;
+ virtual ~registered_test_base() {}
+ };
+
+ struct state
+ {
+ bool is_quiet;
+ registered_test_base* first_test;
+ registered_test_base* last_test;
+
+ state() : is_quiet(false), first_test(0), last_test(0) {}
+
+ void add_test(registered_test_base* test)
+ {
+ if (last_test) {
+ last_test->next = test;
+ } else {
+ first_test = test;
+ }
+ last_test = test;
+ }
+
+ void run_tests(bool quiet = false)
+ {
+ is_quiet = quiet;
+
+ for (registered_test_base* i = first_test; i; i = i->next) {
+ int error_count = boost::detail::test_errors();
+ if (!quiet) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Running " << i->name << "\n"
+ << std::flush;
+ }
+ i->run();
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << std::flush;
+ if (quiet && error_count != boost::detail::test_errors()) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in: " << i->name << "\n"
+ << std::flush;
+ }
+ }
+ }
+
+ int start_sub_test(char const* name)
+ {
+ if (!is_quiet) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Sub-test: " << name << "\n"
+ << std::flush;
+ }
+ // Add one because it's used as a loop condition.
+ return boost::detail::test_errors() + 1;
+ }
+
+ int end_sub_test(char const* name, int value)
+ {
+ if (is_quiet && value != boost::detail::test_errors() + 1) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in sub-test: " << name << "\n"
+ << std::flush;
+ }
+ return 0;
+ }
+ };
+
+ // Get the currnet translation unit's test state.
+ static inline state& get_state()
+ {
+ static state instance;
+ return instance;
+ }
+}
+
+#if defined(__cplusplus)
+#define BOOST_UNORDERED_CPLUSPLUS __cplusplus
+#else
+#define BOOST_UNORDERED_CPLUSPLUS "(not defined)"
+#endif
+
+#define BOOST_UNORDERED_TEST_COMPILER_INFO() \
+ { \
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM \
+ << "Compiler: " << BOOST_COMPILER << "\n" \
+ << "Library: " << BOOST_STDLIB << "\n" \
+ << "__cplusplus: " << BOOST_UNORDERED_CPLUSPLUS << "\n\n" \
+ << "BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT: " \
+ << BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT << "\n" \
+ << "BOOST_UNORDERED_EMPLACE_LIMIT: " << BOOST_UNORDERED_EMPLACE_LIMIT \
+ << "\n" \
+ << "BOOST_UNORDERED_USE_ALLOCATOR_TRAITS: " \
+ << BOOST_UNORDERED_USE_ALLOCATOR_TRAITS << "\n" \
+ << "BOOST_UNORDERED_CXX11_CONSTRUCTION: " \
+ << BOOST_UNORDERED_CXX11_CONSTRUCTION << "\n\n" \
+ << std::flush; \
+ }
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/seq/fold_left.hpp>
+#include <boost/preprocessor/seq/for_each_product.hpp>
+#include <boost/preprocessor/seq/seq.hpp>
+#include <boost/preprocessor/seq/to_tuple.hpp>
+
+// Run test with every combination of the parameters (a sequence of sequences)
+#define UNORDERED_TEST(name, parameters) \
+ BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((1))parameters)
+
+#define UNORDERED_TEST_REPEAT(name, n, parameters) \
+ BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((n))parameters)
+
+#define UNORDERED_TEST_OP(r, product) \
+ UNORDERED_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \
+ BOOST_PP_SEQ_ELEM(1, product), \
+ BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product)))
+
+#define UNORDERED_TEST_OP2(name, n, params) \
+ UNORDERED_AUTO_TEST ( \
+ BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params)) { \
+ for (int i = 0; i < n; ++i) \
+ name BOOST_PP_SEQ_TO_TUPLE(params); \
+ }
+
+#define UNORDERED_TEST_OP_JOIN(s, state, elem) \
+ BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem))
+
+#define UNORDERED_MULTI_TEST(name, impl, parameters) \
+ UNORDERED_MULTI_TEST_REPEAT(name, impl, 1, parameters)
+
+#define UNORDERED_MULTI_TEST_REPEAT(name, impl, n, parameters) \
+ UNORDERED_AUTO_TEST (name) { \
+ BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
+ UNORDERED_MULTI_TEST_OP, ((impl))((n))parameters) \
+ }
+
+#define UNORDERED_MULTI_TEST_OP(r, product) \
+ UNORDERED_MULTI_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \
+ BOOST_PP_SEQ_ELEM(1, product), \
+ BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product)))
+
+// Need to wrap UNORDERED_SUB_TEST in a block to avoid an msvc bug.
+// https://support.microsoft.com/en-gb/help/315481/bug-too-many-unnested-loops-incorrectly-causes-a-c1061-compiler-error-in-visual-c
+#define UNORDERED_MULTI_TEST_OP2(name, n, params) \
+ { \
+ UNORDERED_SUB_TEST(BOOST_PP_STRINGIZE( \
+ BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params))) \
+ { \
+ for (int i = 0; i < n; ++i) \
+ name BOOST_PP_SEQ_TO_TUPLE(params); \
+ } \
+ }
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/tracker.hpp b/src/boost/libs/unordered/test/helpers/tracker.hpp
new file mode 100644
index 00000000..0f86ba6f
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/tracker.hpp
@@ -0,0 +1,138 @@
+
+// Copyright 2006-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// 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 "../objects/fwd.hpp"
+#include "./equivalent.hpp"
+#include "./helpers.hpp"
+#include "./list.hpp"
+#include "./metafunctions.hpp"
+#include <algorithm>
+#include <iterator>
+#include <map>
+#include <set>
+
+namespace test {
+ template <typename 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 test::list<typename X1::value_type> value_list;
+ value_list values1(x1.begin(), x1.end());
+ value_list values2(x2.begin(), x2.end());
+ values1.sort();
+ values2.sort();
+ BOOST_TEST(values1.size() == values2.size() &&
+ test::equal(values1.begin(), values1.end(), values2.begin(),
+ test::equivalent));
+ }
+
+ template <class X1, class X2, class T>
+ void compare_pairs(X1 const& x1, X2 const& x2, T*)
+ {
+ test::list<T> values1(x1.first, x1.second);
+ test::list<T> values2(x2.first, x2.second);
+ values1.sort();
+ values2.sort();
+ BOOST_TEST(values1.size() == values2.size() &&
+ test::equal(values1.begin(), values1.end(), values2.begin(),
+ test::equivalent));
+ }
+
+ template <typename X, bool is_set = test::is_set<X>::value,
+ bool has_unique_keys = test::has_unique_keys<X>::value>
+ struct ordered_base;
+
+ template <typename X> struct ordered_base<X, true, true>
+ {
+ typedef std::set<typename X::value_type,
+ typename equals_to_compare<typename X::key_equal>::type>
+ type;
+ };
+
+ template <typename X> struct ordered_base<X, true, false>
+ {
+ typedef std::multiset<typename X::value_type,
+ typename equals_to_compare<typename X::key_equal>::type>
+ type;
+ };
+
+ template <typename X> struct ordered_base<X, false, true>
+ {
+ typedef std::map<typename X::key_type, typename X::mapped_type,
+ typename equals_to_compare<typename X::key_equal>::type>
+ type;
+ };
+
+ template <typename X> struct ordered_base<X, false, false>
+ {
+ typedef std::multimap<typename X::key_type, typename X::mapped_type,
+ typename equals_to_compare<typename X::key_equal>::type>
+ type;
+ };
+
+ 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& kc) : base(kc) {}
+
+ 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 X::value_type*)0);
+ }
+
+ template <class It> void insert_range(It b, It e)
+ {
+ while (b != e) {
+ this->insert(*b);
+ ++b;
+ }
+ }
+ };
+
+ template <class Equals>
+ typename equals_to_compare<Equals>::type create_compare(Equals const&)
+ {
+ typename equals_to_compare<Equals>::type x;
+ return x;
+ }
+
+ 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_range(values.begin(), values.end());
+ tracker.compare(container);
+ }
+}
+
+#endif