summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/unordered/test/exception
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/exception
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/exception')
-rw-r--r--src/boost/libs/unordered/test/exception/assign_exception_tests.cpp185
-rw-r--r--src/boost/libs/unordered/test/exception/constructor_exception_tests.cpp212
-rw-r--r--src/boost/libs/unordered/test/exception/containers.hpp44
-rw-r--r--src/boost/libs/unordered/test/exception/copy_exception_tests.cpp110
-rw-r--r--src/boost/libs/unordered/test/exception/erase_exception_tests.cpp55
-rw-r--r--src/boost/libs/unordered/test/exception/insert_exception_tests.cpp416
-rw-r--r--src/boost/libs/unordered/test/exception/merge_exception_tests.cpp108
-rw-r--r--src/boost/libs/unordered/test/exception/move_assign_exception_tests.cpp132
-rw-r--r--src/boost/libs/unordered/test/exception/rehash_exception_tests.cpp133
-rw-r--r--src/boost/libs/unordered/test/exception/swap_exception_tests.cpp145
10 files changed, 1540 insertions, 0 deletions
diff --git a/src/boost/libs/unordered/test/exception/assign_exception_tests.cpp b/src/boost/libs/unordered/test/exception/assign_exception_tests.cpp
new file mode 100644
index 00000000..c62bf8ab
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/assign_exception_tests.cpp
@@ -0,0 +1,185 @@
+
+// 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)
+
+#include "./containers.hpp"
+
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable : 4512) // assignment operator could not be generated
+#endif
+
+test::seed_t initialize_seed(12847);
+
+template <class T> struct self_assign_base : public test::exception_base
+{
+ test::random_values<T> values;
+ self_assign_base(std::size_t count = 0) : values(count, test::limited_range)
+ {
+ }
+
+ typedef T data_type;
+ T init() const { return T(values.begin(), values.end()); }
+
+ void run(T& x) const
+ {
+ x = x;
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, values);
+ test::check_equivalent_keys(x);
+ }
+
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
+ {
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct self_assign_test1 : self_assign_base<T>
+{
+};
+
+template <class T> struct self_assign_test2 : self_assign_base<T>
+{
+ self_assign_test2() : self_assign_base<T>(100) {}
+};
+
+template <class T> struct assign_base : public test::exception_base
+{
+ test::random_values<T> x_values, y_values;
+ T x, y;
+
+ typedef typename T::hasher hasher;
+ typedef typename T::key_equal key_equal;
+ typedef typename T::allocator_type allocator_type;
+
+ assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
+ : x_values(), y_values(),
+ x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
+ y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
+ {
+ x.max_load_factor(mlf1);
+ y.max_load_factor(mlf2);
+ }
+
+ typedef T data_type;
+ T init() const { return T(x); }
+
+ void run(T& x1) const
+ {
+ x1 = y;
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x1, y_values);
+ test::check_equivalent_keys(x1);
+ }
+
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
+ {
+ test::check_equivalent_keys(x1);
+
+ // If the container is empty at the point of the exception, the
+ // internal structure is hidden, this exposes it, at the cost of
+ // messing up the data.
+ if (x_values.size()) {
+ T& x2 = const_cast<T&>(x1);
+ x2.emplace(*x_values.begin());
+ test::check_equivalent_keys(x2);
+ }
+ }
+};
+
+template <class T> struct assign_values : assign_base<T>
+{
+ assign_values(unsigned int count1, unsigned int count2, int tag1, int tag2,
+ test::random_generator gen = test::default_generator, float mlf1 = 1.0,
+ float mlf2 = 1.0)
+ : assign_base<T>(tag1, tag2, mlf1, mlf2)
+ {
+ this->x_values.fill(count1, gen);
+ this->y_values.fill(count2, gen);
+ this->x.insert(this->x_values.begin(), this->x_values.end());
+ this->y.insert(this->y_values.begin(), this->y_values.end());
+ }
+};
+
+template <class T> struct assign_test1 : assign_values<T>
+{
+ assign_test1() : assign_values<T>(0, 0, 0, 0) {}
+};
+
+template <class T> struct assign_test2 : assign_values<T>
+{
+ assign_test2() : assign_values<T>(60, 0, 0, 0) {}
+};
+
+template <class T> struct assign_test2a : assign_values<T>
+{
+ assign_test2a() : assign_values<T>(60, 0, 0, 0, test::limited_range) {}
+};
+
+template <class T> struct assign_test3 : assign_values<T>
+{
+ assign_test3() : assign_values<T>(0, 60, 0, 0) {}
+};
+
+template <class T> struct assign_test3a : assign_values<T>
+{
+ assign_test3a() : assign_values<T>(0, 60, 0, 0, test::limited_range) {}
+};
+
+template <class T> struct assign_test4 : assign_values<T>
+{
+ assign_test4() : assign_values<T>(10, 10, 1, 2) {}
+};
+
+template <class T> struct assign_test4a : assign_values<T>
+{
+ assign_test4a() : assign_values<T>(10, 100, 1, 2) {}
+};
+
+template <class T> struct assign_test4b : assign_values<T>
+{
+ assign_test4b() : assign_values<T>(10, 100, 1, 2, test::limited_range) {}
+};
+
+template <class T> struct assign_test5 : assign_values<T>
+{
+ assign_test5()
+ : assign_values<T>(5, 60, 0, 0, test::default_generator, 1.0f, 0.1f)
+ {
+ }
+};
+
+template <class T> struct equivalent_test1 : assign_base<T>
+{
+ equivalent_test1() : assign_base<T>(0, 0)
+ {
+ test::random_values<T> x_values2(10);
+ this->x_values.insert(x_values2.begin(), x_values2.end());
+ this->x_values.insert(x_values2.begin(), x_values2.end());
+ test::random_values<T> y_values2(10);
+ this->y_values.insert(y_values2.begin(), y_values2.end());
+ this->y_values.insert(y_values2.begin(), y_values2.end());
+ this->x.insert(this->x_values.begin(), this->x_values.end());
+ this->y.insert(this->y_values.begin(), this->y_values.end());
+ }
+};
+
+// clang-format off
+EXCEPTION_TESTS_REPEAT(5,
+ (self_assign_test1)(self_assign_test2)
+ (assign_test1)(assign_test2)(assign_test2a)
+ (assign_test3)(assign_test3a)
+ (assign_test4)(assign_test4a)(assign_test4b)
+ (assign_test5)
+ (equivalent_test1),
+ CONTAINER_SEQ)
+// clang-format on
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/exception/constructor_exception_tests.cpp b/src/boost/libs/unordered/test/exception/constructor_exception_tests.cpp
new file mode 100644
index 00000000..3dfebcef
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/constructor_exception_tests.cpp
@@ -0,0 +1,212 @@
+
+// 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)
+
+#include "./containers.hpp"
+
+#include "../helpers/input_iterator.hpp"
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+
+template <typename T> inline void avoid_unused_warning(T const&) {}
+
+test::seed_t initialize_seed(91274);
+
+struct objects
+{
+ test::exception::object obj;
+ test::exception::hash hash;
+ test::exception::equal_to equal_to;
+ test::exception::allocator<test::exception::object> allocator;
+};
+
+template <class T> struct construct_test1 : public objects, test::exception_base
+{
+ void run() const
+ {
+ T x;
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(x.empty());
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct construct_test2 : public objects, test::exception_base
+{
+ void run() const
+ {
+ T x(300);
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(x.empty());
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct construct_test3 : public objects, test::exception_base
+{
+ void run() const
+ {
+ T x(0, hash);
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(x.empty());
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct construct_test4 : public objects, test::exception_base
+{
+ void run() const
+ {
+ T x(0, hash, equal_to);
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(x.empty());
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct construct_test5 : public objects, test::exception_base
+{
+ void run() const
+ {
+ T x(50, hash, equal_to, allocator);
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(x.empty());
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct construct_test6 : public objects, test::exception_base
+{
+ void run() const
+ {
+ T x(allocator);
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(x.empty());
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct range : public test::exception_base
+{
+ test::random_values<T> values;
+
+ range() : values(5, test::limited_range) {}
+ range(unsigned int count) : values(count, test::limited_range) {}
+};
+
+template <class T> struct range_construct_test1 : public range<T>, objects
+{
+ void run() const
+ {
+ T x(this->values.begin(), this->values.end());
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct range_construct_test2 : public range<T>, objects
+{
+ void run() const
+ {
+ T x(this->values.begin(), this->values.end(), 0);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct range_construct_test3 : public range<T>, objects
+{
+ void run() const
+ {
+ T x(this->values.begin(), this->values.end(), 0, hash);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct range_construct_test4 : public range<T>, objects
+{
+ void run() const
+ {
+ T x(this->values.begin(), this->values.end(), 100, hash, equal_to);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+// Need to run at least one test with a fairly large number
+// of objects in case it triggers a rehash.
+template <class T> struct range_construct_test5 : public range<T>, objects
+{
+ range_construct_test5() : range<T>(60) {}
+
+ void run() const
+ {
+ T x(this->values.begin(), this->values.end(), 0, hash, equal_to, allocator);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct input_range_construct_test : public range<T>, objects
+{
+ input_range_construct_test() : range<T>(60) {}
+
+ void run() const
+ {
+ typename test::random_values<T>::const_iterator begin =
+ this->values.begin(),
+ end = this->values.end();
+ T x(test::input_iterator(begin), test::input_iterator(end), 0, hash,
+ equal_to, allocator);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct copy_range_construct_test : public range<T>, objects
+{
+ copy_range_construct_test() : range<T>(60) {}
+
+ void run() const
+ {
+ T x(test::copy_iterator(this->values.begin()),
+ test::copy_iterator(this->values.end()), 0, hash, equal_to, allocator);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+// clang-format off
+EXCEPTION_TESTS(
+ (construct_test1)(construct_test2)(construct_test3)(construct_test4)
+ (construct_test5)(construct_test6)(range_construct_test1)
+ (range_construct_test2)(range_construct_test3)(range_construct_test4)
+ (range_construct_test5)(input_range_construct_test)
+ (copy_range_construct_test),
+ CONTAINER_SEQ)
+// clang-format on
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/exception/containers.hpp b/src/boost/libs/unordered/test/exception/containers.hpp
new file mode 100644
index 00000000..c3b34be2
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/containers.hpp
@@ -0,0 +1,44 @@
+
+// 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_map.hpp>
+#include <boost/unordered_set.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../objects/exception.hpp"
+
+typedef boost::unordered_set<test::exception::object, test::exception::hash,
+ test::exception::equal_to,
+ test::exception::allocator<test::exception::object> >
+ test_set;
+typedef boost::unordered_multiset<test::exception::object,
+ test::exception::hash, test::exception::equal_to,
+ test::exception::allocator2<test::exception::object> >
+ test_multiset;
+typedef boost::unordered_map<test::exception::object, test::exception::object,
+ test::exception::hash, test::exception::equal_to,
+ test::exception::allocator2<test::exception::object> >
+ test_map;
+typedef boost::unordered_multimap<test::exception::object,
+ test::exception::object, test::exception::hash, test::exception::equal_to,
+ test::exception::allocator<test::exception::object> >
+ test_multimap;
+typedef boost::unordered_set<
+ std::pair<test::exception::object, test::exception::object>,
+ test::exception::hash, test::exception::equal_to,
+ test::exception::allocator<test::exception::object> >
+ test_pair_set;
+typedef boost::unordered_multiset<
+ std::pair<test::exception::object, test::exception::object>,
+ test::exception::hash, test::exception::equal_to,
+ test::exception::allocator2<test::exception::object> >
+ test_pair_multiset;
+
+#define CONTAINER_SEQ (test_set)(test_multiset)(test_map)(test_multimap)
+#define CONTAINER_PAIR_SEQ \
+ (test_pair_set)(test_pair_multiset)(test_map)(test_multimap)
diff --git a/src/boost/libs/unordered/test/exception/copy_exception_tests.cpp b/src/boost/libs/unordered/test/exception/copy_exception_tests.cpp
new file mode 100644
index 00000000..6149235a
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/copy_exception_tests.cpp
@@ -0,0 +1,110 @@
+
+// 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)
+
+#include "./containers.hpp"
+
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+
+template <typename T> inline void avoid_unused_warning(T const&) {}
+
+test::seed_t initialize_seed(73041);
+
+template <class T> struct copy_test1 : public test::exception_base
+{
+ T x;
+
+ void run() const
+ {
+ T y(x);
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(y.empty());
+ test::check_equivalent_keys(y);
+ }
+};
+
+template <class T> struct copy_test2 : public test::exception_base
+{
+ test::random_values<T> values;
+ T x;
+
+ copy_test2() : values(5, test::limited_range), x(values.begin(), values.end())
+ {
+ }
+
+ void run() const
+ {
+ T y(x);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(y, this->values);
+ test::check_equivalent_keys(y);
+ }
+};
+
+template <class T> struct copy_test3 : public test::exception_base
+{
+ test::random_values<T> values;
+ T x;
+
+ copy_test3() : values(100), x(values.begin(), values.end()) {}
+
+ void run() const
+ {
+ T y(x);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(y, this->values);
+ test::check_equivalent_keys(y);
+ }
+};
+
+template <class T> struct copy_test3a : public test::exception_base
+{
+ test::random_values<T> values;
+ T x;
+
+ copy_test3a()
+ : values(100, test::limited_range), x(values.begin(), values.end())
+ {
+ }
+
+ void run() const
+ {
+ T y(x);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(y, this->values);
+ test::check_equivalent_keys(y);
+ }
+};
+
+template <class T> struct copy_with_allocator_test : public test::exception_base
+{
+ test::random_values<T> values;
+ T x;
+ test::exception::allocator<test::exception::object> allocator;
+
+ copy_with_allocator_test() : values(100), x(values.begin(), values.end()) {}
+
+ void run() const
+ {
+ T y(x, allocator);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(y, this->values);
+ test::check_equivalent_keys(y);
+ }
+};
+
+// clang-format off
+EXCEPTION_TESTS(
+ (copy_test1)(copy_test2)(copy_test3)(copy_test3a)(copy_with_allocator_test),
+ CONTAINER_SEQ)
+// clang-format on
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/exception/erase_exception_tests.cpp b/src/boost/libs/unordered/test/exception/erase_exception_tests.cpp
new file mode 100644
index 00000000..0f2c1eb6
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/erase_exception_tests.cpp
@@ -0,0 +1,55 @@
+
+// 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)
+
+#include "./containers.hpp"
+
+#include "../helpers/helpers.hpp"
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+
+test::seed_t initialize_seed(835193);
+
+template <class T> struct erase_test_base : public test::exception_base
+{
+ test::random_values<T> values;
+ erase_test_base(unsigned int count = 5) : values(count, test::limited_range)
+ {
+ }
+
+ typedef T data_type;
+
+ data_type init() const { return T(values.begin(), values.end()); }
+
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
+ {
+ std::string scope(test::scope);
+
+ BOOST_TEST(scope.find("hash::") != std::string::npos ||
+ scope.find("equal_to::") != std::string::npos ||
+ scope == "operator==(object, object)");
+
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct erase_by_key_test1 : public erase_test_base<T>
+{
+ void run(T& x) const
+ {
+ typedef typename test::random_values<T>::const_iterator iterator;
+
+ for (iterator it = this->values.begin(), end = this->values.end();
+ it != end; ++it) {
+ x.erase(test::get_key<T>(*it));
+ }
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(x.empty());
+ test::check_equivalent_keys(x);
+ }
+};
+
+EXCEPTION_TESTS((erase_by_key_test1), CONTAINER_SEQ)
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/exception/insert_exception_tests.cpp b/src/boost/libs/unordered/test/exception/insert_exception_tests.cpp
new file mode 100644
index 00000000..79074c5e
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/insert_exception_tests.cpp
@@ -0,0 +1,416 @@
+
+// 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)
+#include "./containers.hpp"
+
+#include "../helpers/helpers.hpp"
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/strong.hpp"
+#include "../helpers/tracker.hpp"
+#include <cmath>
+#include <string>
+
+test::seed_t initialize_seed(747373);
+
+// Fill in a container so that it's about to rehash
+template <typename T> void rehash_prep(T& x)
+{
+ using namespace std;
+ typedef typename T::size_type size_type;
+
+ x.max_load_factor(0.25);
+ size_type bucket_count = x.bucket_count();
+ size_type initial_elements = static_cast<size_type>(
+ ceil((double)bucket_count * (double)x.max_load_factor()) - 1);
+ test::random_values<T> v(initial_elements);
+ x.insert(v.begin(), v.end());
+ BOOST_TEST(bucket_count == x.bucket_count());
+}
+
+// Overload to generate inserters that need type information.
+
+template <typename Inserter, typename T>
+Inserter generate(Inserter inserter, T&)
+{
+ return inserter;
+}
+
+// Get the iterator returned from an insert/emplace.
+
+template <typename T> T get_iterator(T const& x) { return x; }
+
+template <typename T> T get_iterator(std::pair<T, bool> const& x)
+{
+ return x.first;
+}
+
+// Generic insert exception test for typical single element inserts..
+
+template <typename T, typename Inserter, typename Values>
+void insert_exception_test_impl(T x, Inserter insert, Values const& v)
+{
+ test::strong<T> strong;
+
+ test::ordered<T> tracker;
+ tracker.insert(x.begin(), x.end());
+
+ try {
+ ENABLE_EXCEPTIONS;
+
+ for (typename Values::const_iterator it = v.begin(); it != v.end(); ++it) {
+ strong.store(x, test::detail::tracker.count_allocations);
+ insert(x, it);
+ }
+ } catch (...) {
+ test::check_equivalent_keys(x);
+ insert.exception_check(x, strong);
+ throw;
+ }
+
+ test::check_equivalent_keys(x);
+ insert.track(tracker, v.begin(), v.end());
+ tracker.compare(x);
+}
+
+// Simple insert exception test
+
+template <typename T, typename Inserter>
+void insert_exception_test(T*, Inserter insert, test::random_generator gen)
+{
+ for (int i = 0; i < 5; ++i) {
+ test::random_values<T> v(10, gen);
+ T x;
+
+ EXCEPTION_LOOP(insert_exception_test_impl(x, generate(insert, x), v));
+ }
+}
+
+// Insert into a container which is about to hit its max load, so that it
+// rehashes.
+
+template <typename T, typename Inserter>
+void insert_rehash_exception_test(
+ T*, Inserter insert, test::random_generator gen)
+{
+ for (int i = 0; i < 5; ++i) {
+ T x;
+ rehash_prep(x);
+
+ test::random_values<T> v2(5, gen);
+ EXCEPTION_LOOP(insert_exception_test_impl(x, generate(insert, x), v2));
+ }
+}
+
+// Various methods for inserting a single element
+
+struct inserter_base
+{
+ template <typename T> void exception_check(T& x, test::strong<T>& strong)
+ {
+ std::string scope(test::scope);
+
+ if (scope.find("hash::operator()") == std::string::npos)
+ strong.test(x, test::detail::tracker.count_allocations);
+ }
+
+ template <typename T, typename Iterator>
+ void track(T& tracker, Iterator begin, Iterator end)
+ {
+ tracker.insert(begin, end);
+ }
+};
+
+struct insert_lvalue_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.insert(*it);
+ }
+} insert_lvalue;
+
+struct insert_lvalue_begin_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.insert(x.begin(), *it);
+ }
+} insert_lvalue_begin;
+
+struct insert_lvalue_end_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.insert(x.end(), *it);
+ }
+} insert_lvalue_end;
+
+template <typename T> struct insert_lvalue_pos_type_impl : inserter_base
+{
+ typename T::iterator pos;
+
+ insert_lvalue_pos_type_impl(T& x) : pos(x.begin()) {}
+
+ template <typename Iterator> void operator()(T& x, Iterator it)
+ {
+ pos = get_iterator(x.insert(pos, *it));
+ }
+};
+
+struct insert_lvalue_pos_type
+{
+ template <typename T>
+ friend insert_lvalue_pos_type_impl<T> generate(insert_lvalue_pos_type, T& x)
+ {
+ return insert_lvalue_pos_type_impl<T>(x);
+ }
+} insert_lvalue_pos;
+
+struct insert_single_item_range_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.insert(it, test::next(it));
+ }
+} insert_single_item_range;
+
+struct emplace_lvalue_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.emplace(*it);
+ }
+} emplace_lvalue;
+
+struct emplace_lvalue_begin_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.emplace_hint(x.begin(), *it);
+ }
+} emplace_lvalue_begin;
+
+struct emplace_lvalue_end_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.emplace_hint(x.end(), *it);
+ }
+} emplace_lvalue_end;
+
+template <typename T> struct emplace_lvalue_pos_type_impl : inserter_base
+{
+ typename T::iterator pos;
+
+ emplace_lvalue_pos_type_impl(T& x) : pos(x.begin()) {}
+
+ template <typename Iterator> void operator()(T& x, Iterator it)
+ {
+ pos = get_iterator(x.emplace_hint(pos, *it));
+ }
+};
+
+struct emplace_lvalue_pos_type
+{
+ template <typename T>
+ friend emplace_lvalue_pos_type_impl<T> generate(emplace_lvalue_pos_type, T& x)
+ {
+ return emplace_lvalue_pos_type_impl<T>(x);
+ }
+} emplace_lvalue_pos;
+
+// Run the exception tests in various combinations.
+
+test_set* test_set_;
+test_multiset* test_multiset_;
+test_map* test_map_;
+test_multimap* test_multimap_;
+
+using test::default_generator;
+using test::limited_range;
+using test::generate_collisions;
+
+// clang-format off
+UNORDERED_TEST(insert_exception_test,
+ ((test_set_)(test_multiset_)(test_map_)(test_multimap_))
+ ((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
+ (insert_lvalue_pos)(insert_single_item_range)
+ (emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
+ (emplace_lvalue_pos)
+ )
+ ((default_generator)(limited_range)(generate_collisions))
+)
+
+UNORDERED_TEST(insert_rehash_exception_test,
+ ((test_set_)(test_multiset_)(test_map_)(test_multimap_))
+ ((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
+ (insert_lvalue_pos)(insert_single_item_range)
+ (emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
+ (emplace_lvalue_pos)
+ )
+ ((default_generator)(limited_range)(generate_collisions))
+)
+// clang-format on
+
+// Repeat insert tests with pairs
+
+struct pair_emplace_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.emplace(boost::unordered::piecewise_construct,
+ boost::make_tuple(it->first), boost::make_tuple(it->second));
+ }
+} pair_emplace;
+
+struct pair_emplace2_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.emplace_hint(x.begin(), boost::unordered::piecewise_construct,
+ boost::make_tuple(it->first),
+ boost::make_tuple(it->second.tag1_, it->second.tag2_));
+ }
+} pair_emplace2;
+
+test_pair_set* test_pair_set_;
+test_pair_multiset* test_pair_multiset_;
+
+// clang-format off
+UNORDERED_TEST(insert_exception_test,
+ ((test_pair_set_)(test_pair_multiset_)(test_map_)(test_multimap_))
+ ((pair_emplace)(pair_emplace2))
+ ((default_generator)(limited_range)(generate_collisions))
+)
+UNORDERED_TEST(insert_rehash_exception_test,
+ ((test_pair_set_)(test_pair_multiset_)(test_map_)(test_multimap_))
+ ((pair_emplace)(pair_emplace2))
+ ((default_generator)(limited_range)(generate_collisions))
+)
+// clang-format on
+
+// Test inserting using operator[]
+
+struct try_emplace_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.try_emplace(it->first, it->second);
+ }
+} try_emplace;
+
+struct try_emplace2_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.try_emplace(it->first, it->second.tag1_, it->second.tag2_);
+ }
+} try_emplace2;
+
+struct map_inserter_base
+{
+ template <typename T> void exception_check(T& x, test::strong<T>& strong)
+ {
+ std::string scope(test::scope);
+
+ if (scope.find("hash::operator()") == std::string::npos &&
+ scope.find("::operator=") == std::string::npos)
+ strong.test(x, test::detail::tracker.count_allocations);
+ }
+
+ template <typename T, typename Iterator>
+ void track(T& tracker, Iterator begin, Iterator end)
+ {
+ for (; begin != end; ++begin) {
+ tracker[begin->first] = begin->second;
+ }
+ }
+};
+
+struct map_insert_operator_type : map_inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x[it->first] = it->second;
+ }
+} map_insert_operator;
+
+struct map_insert_or_assign_type : map_inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.insert_or_assign(it->first, it->second);
+ }
+} map_insert_or_assign;
+
+// clang-format off
+UNORDERED_TEST(insert_exception_test,
+ ((test_map_))
+ ((try_emplace)(try_emplace2)(map_insert_operator)(map_insert_or_assign))
+ ((default_generator)(limited_range)(generate_collisions))
+)
+UNORDERED_TEST(insert_rehash_exception_test,
+ ((test_map_))
+ ((try_emplace)(try_emplace2)(map_insert_operator)(map_insert_or_assign))
+ ((default_generator)(limited_range)(generate_collisions))
+)
+// clang-format on
+
+// Range insert tests
+
+template <typename T, typename Values>
+void insert_range_exception_test_impl(T x, Values const& v)
+{
+ test::ordered<T> tracker;
+ tracker.insert(x.begin(), x.end());
+
+ try {
+ ENABLE_EXCEPTIONS;
+ x.insert(v.begin(), v.end());
+ } catch (...) {
+ test::check_equivalent_keys(x);
+ throw;
+ }
+
+ test::check_equivalent_keys(x);
+ tracker.insert(v.begin(), v.end());
+ tracker.compare(x);
+}
+
+template <typename T>
+void insert_range_exception_test(T*, test::random_generator gen)
+{
+ for (int i = 0; i < 5; ++i) {
+ test::random_values<T> v(10, gen);
+ T x;
+
+ EXCEPTION_LOOP(insert_range_exception_test_impl(x, v));
+ }
+}
+
+template <typename T>
+void insert_range_rehash_exception_test(T*, test::random_generator gen)
+{
+ for (int i = 0; i < 5; ++i) {
+ T x;
+ rehash_prep(x);
+
+ test::random_values<T> v2(5, gen);
+ EXCEPTION_LOOP(insert_range_exception_test_impl(x, v2));
+ }
+}
+
+// clang-format off
+UNORDERED_TEST(insert_range_exception_test,
+ ((test_set_)(test_multiset_)(test_map_)(test_multimap_))
+ ((default_generator)(limited_range)(generate_collisions))
+)
+
+UNORDERED_TEST(insert_range_rehash_exception_test,
+ ((test_set_)(test_multiset_)(test_map_)(test_multimap_))
+ ((default_generator)(limited_range)(generate_collisions))
+)
+// clang-format on
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/exception/merge_exception_tests.cpp b/src/boost/libs/unordered/test/exception/merge_exception_tests.cpp
new file mode 100644
index 00000000..2cf7faf4
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/merge_exception_tests.cpp
@@ -0,0 +1,108 @@
+
+// Copyright 2017-2018 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 "../helpers/exception_test.hpp"
+#include "../helpers/invariants.hpp"
+#include "../helpers/metafunctions.hpp"
+#include "../helpers/random_values.hpp"
+#include "./containers.hpp"
+
+template <typename T1, typename T2> void merge_exception_test(T1 x, T2 y)
+{
+ std::size_t size = x.size() + y.size();
+
+ try {
+ ENABLE_EXCEPTIONS;
+ x.merge(y);
+ } catch (...) {
+ test::check_equivalent_keys(x);
+ test::check_equivalent_keys(y);
+ throw;
+ }
+
+ // Not a full check, just want to make sure the merge completed.
+ BOOST_TEST(size == x.size() + y.size());
+ if (y.size()) {
+ BOOST_TEST(test::has_unique_keys<T1>::value);
+ for (typename T2::iterator it = y.begin(); it != y.end(); ++it) {
+ BOOST_TEST(x.find(test::get_key<T2>(*it)) != x.end());
+ }
+ }
+ test::check_equivalent_keys(x);
+ test::check_equivalent_keys(y);
+}
+
+template <typename T1, typename T2>
+void merge_exception_test(T1 const*, T2 const*, std::size_t count12, int tag12,
+ test::random_generator gen1, test::random_generator gen2)
+{
+ std::size_t count1 = count12 / 256;
+ std::size_t count2 = count12 % 256;
+ int tag1 = tag12 / 256;
+ int tag2 = tag12 % 256;
+ test::random_values<T1> v1(count1, gen1);
+ test::random_values<T2> v2(count2, gen2);
+ T1 x(v1.begin(), v1.end(), 0, test::exception::hash(tag1),
+ test::exception::equal_to(tag1));
+ T2 y(v2.begin(), v2.end(), 0, test::exception::hash(tag2),
+ test::exception::equal_to(tag2));
+
+ EXCEPTION_LOOP(merge_exception_test(x, y))
+}
+
+boost::unordered_set<test::exception::object, test::exception::hash,
+ test::exception::equal_to,
+ test::exception::allocator<test::exception::object> >* test_set_;
+boost::unordered_multiset<test::exception::object, test::exception::hash,
+ test::exception::equal_to,
+ test::exception::allocator<test::exception::object> >* test_multiset_;
+boost::unordered_map<test::exception::object, test::exception::object,
+ test::exception::hash, test::exception::equal_to,
+ test::exception::allocator2<test::exception::object> >* test_map_;
+boost::unordered_multimap<test::exception::object, test::exception::object,
+ test::exception::hash, test::exception::equal_to,
+ test::exception::allocator2<test::exception::object> >* test_multimap_;
+
+using test::default_generator;
+using test::generate_collisions;
+using test::limited_range;
+
+// clang-format off
+UNORDERED_MULTI_TEST(set_merge, merge_exception_test,
+ ((test_set_)(test_multiset_))
+ ((test_set_)(test_multiset_))
+ ((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
+ ((0x0000)(0x0001)(0x0102))
+ ((default_generator)(limited_range))
+ ((default_generator)(limited_range))
+)
+UNORDERED_MULTI_TEST(map_merge, merge_exception_test,
+ ((test_map_)(test_multimap_))
+ ((test_map_)(test_multimap_))
+ ((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
+ ((0x0101)(0x0200)(0x0201))
+ ((default_generator)(limited_range))
+ ((default_generator)(limited_range))
+)
+// Run fewer generate_collisions tests, as they're slow.
+UNORDERED_MULTI_TEST(set_merge_collisions, merge_exception_test,
+ ((test_set_)(test_multiset_))
+ ((test_set_)(test_multiset_))
+ ((0x0a0a))
+ ((0x0202)(0x0100)(0x0201))
+ ((generate_collisions))
+ ((generate_collisions))
+)
+UNORDERED_MULTI_TEST(map_merge_collisions, merge_exception_test,
+ ((test_map_)(test_multimap_))
+ ((test_map_)(test_multimap_))
+ ((0x0a0a))
+ ((0x0000)(0x0002)(0x0102))
+ ((generate_collisions))
+ ((generate_collisions))
+)
+// clang-format on
+
+RUN_TESTS_QUIET()
diff --git a/src/boost/libs/unordered/test/exception/move_assign_exception_tests.cpp b/src/boost/libs/unordered/test/exception/move_assign_exception_tests.cpp
new file mode 100644
index 00000000..6beb6820
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/move_assign_exception_tests.cpp
@@ -0,0 +1,132 @@
+
+// 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)
+
+#include "./containers.hpp"
+
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+
+#if defined(BOOST_MSVC)
+#pragma warning( \
+ disable : 4512) // move_assignment operator could not be generated
+#endif
+
+test::seed_t initialize_seed(12847);
+
+template <class T> struct move_assign_base : public test::exception_base
+{
+ test::random_values<T> x_values, y_values;
+ T x, y;
+
+ typedef typename T::hasher hasher;
+ typedef typename T::key_equal key_equal;
+ typedef typename T::allocator_type allocator_type;
+
+ move_assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
+ : x_values(), y_values(),
+ x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
+ y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
+ {
+ x.max_load_factor(mlf1);
+ y.max_load_factor(mlf2);
+ }
+
+ typedef T data_type;
+ T init() const { return T(x); }
+ void run(T& x1) const
+ {
+ test::exceptions_enable disable_exceptions(false);
+ T y1 = y;
+ disable_exceptions.release();
+ x1 = boost::move(y1);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x1, y_values);
+ test::check_equivalent_keys(x1);
+ }
+
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
+ {
+ test::check_equivalent_keys(x1);
+
+ // If the container is empty at the point of the exception, the
+ // internal structure is hidden, this exposes it, at the cost of
+ // messing up the data.
+ if (x_values.size()) {
+ T& x2 = const_cast<T&>(x1);
+ x2.emplace(*x_values.begin());
+ test::check_equivalent_keys(x2);
+ }
+ }
+};
+
+template <class T> struct move_assign_values : move_assign_base<T>
+{
+ move_assign_values(unsigned int count1, unsigned int count2, int tag1,
+ int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
+ : move_assign_base<T>(tag1, tag2, mlf1, mlf2)
+ {
+ this->x_values.fill(count1, test::limited_range);
+ this->y_values.fill(count2, test::limited_range);
+ this->x.insert(this->x_values.begin(), this->x_values.end());
+ this->y.insert(this->y_values.begin(), this->y_values.end());
+ }
+};
+
+template <class T> struct move_assign_test1 : move_assign_values<T>
+{
+ move_assign_test1() : move_assign_values<T>(0, 0, 0, 0) {}
+};
+
+template <class T> struct move_assign_test2 : move_assign_values<T>
+{
+ move_assign_test2() : move_assign_values<T>(60, 0, 0, 0) {}
+};
+
+template <class T> struct move_assign_test3 : move_assign_values<T>
+{
+ move_assign_test3() : move_assign_values<T>(0, 60, 0, 0) {}
+};
+
+template <class T> struct move_assign_test4 : move_assign_values<T>
+{
+ move_assign_test4() : move_assign_values<T>(10, 10, 1, 2) {}
+};
+
+template <class T> struct move_assign_test4a : move_assign_values<T>
+{
+ move_assign_test4a() : move_assign_values<T>(10, 100, 1, 2) {}
+};
+
+template <class T> struct move_assign_test5 : move_assign_values<T>
+{
+ move_assign_test5() : move_assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {}
+};
+
+template <class T> struct equivalent_test1 : move_assign_base<T>
+{
+ equivalent_test1() : move_assign_base<T>(0, 0)
+ {
+ test::random_values<T> x_values2(10, test::limited_range);
+ this->x_values.insert(x_values2.begin(), x_values2.end());
+ this->x_values.insert(x_values2.begin(), x_values2.end());
+ test::random_values<T> y_values2(10, test::limited_range);
+ this->y_values.insert(y_values2.begin(), y_values2.end());
+ this->y_values.insert(y_values2.begin(), y_values2.end());
+ this->x.insert(this->x_values.begin(), this->x_values.end());
+ this->y.insert(this->y_values.begin(), this->y_values.end());
+ }
+};
+
+// clang-format off
+EXCEPTION_TESTS(
+ (move_assign_test1)(move_assign_test2)(move_assign_test3)
+ (move_assign_test4)(move_assign_test4a)(move_assign_test5)
+ (equivalent_test1),
+ CONTAINER_SEQ)
+// clang-format on
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/exception/rehash_exception_tests.cpp b/src/boost/libs/unordered/test/exception/rehash_exception_tests.cpp
new file mode 100644
index 00000000..a927d136
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/rehash_exception_tests.cpp
@@ -0,0 +1,133 @@
+
+// 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)
+
+#include "./containers.hpp"
+
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/strong.hpp"
+#include "../helpers/tracker.hpp"
+#include <string>
+
+test::seed_t initialize_seed(3298597);
+
+template <class T> struct rehash_test_base : public test::exception_base
+{
+ test::random_values<T> values;
+ unsigned int n;
+ rehash_test_base(unsigned int count = 100, unsigned int n_ = 0)
+ : values(count, test::limited_range), n(n_)
+ {
+ }
+
+ typedef T data_type;
+ typedef test::strong<T> strong_type;
+
+ data_type init() const
+ {
+ T x(values.begin(), values.end(), n);
+ return x;
+ }
+
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION(
+ T const& x, strong_type const& strong) const
+ {
+ std::string scope(test::scope);
+
+ if (scope.find("hash::operator()") == std::string::npos &&
+ scope.find("equal_to::operator()") == std::string::npos &&
+ scope != "operator==(object, object)")
+ strong.test(x);
+
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct rehash_test0 : rehash_test_base<T>
+{
+ rehash_test0() : rehash_test_base<T>(0) {}
+ void run(T& x) const
+ {
+ x.rehash(0);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct rehash_test1 : rehash_test_base<T>
+{
+ rehash_test1() : rehash_test_base<T>(0) {}
+ void run(T& x) const
+ {
+ x.rehash(200);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct rehash_test2 : rehash_test_base<T>
+{
+ rehash_test2() : rehash_test_base<T>(0, 200) {}
+ void run(T& x) const
+ {
+ x.rehash(0);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct rehash_test3 : rehash_test_base<T>
+{
+ rehash_test3() : rehash_test_base<T>(10, 0) {}
+ void run(T& x) const
+ {
+ x.rehash(200);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct rehash_test4 : rehash_test_base<T>
+{
+ rehash_test4() : rehash_test_base<T>(10, 200) {}
+ void run(T& x) const
+ {
+ x.rehash(0);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct rehash_test5 : rehash_test_base<T>
+{
+ rehash_test5() : rehash_test_base<T>(200, 10) {}
+ void run(T& x) const
+ {
+ x.rehash(0);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+// clang-format off
+EXCEPTION_TESTS(
+ (rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(rehash_test4)
+ (rehash_test5),
+ CONTAINER_SEQ)
+// clang-format on
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/exception/swap_exception_tests.cpp b/src/boost/libs/unordered/test/exception/swap_exception_tests.cpp
new file mode 100644
index 00000000..1569e814
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/swap_exception_tests.cpp
@@ -0,0 +1,145 @@
+
+// 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)
+
+#include "./containers.hpp"
+
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable : 4512) // assignment operator could not be generated
+#endif
+
+test::seed_t initialize_seed(9387);
+
+template <class T> struct self_swap_base : public test::exception_base
+{
+ test::random_values<T> values;
+ self_swap_base(std::size_t count = 0) : values(count, test::limited_range) {}
+
+ typedef T data_type;
+ T init() const { return T(values.begin(), values.end()); }
+
+ void run(T& x) const
+ {
+ x.swap(x);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
+ {
+ std::string scope(test::scope);
+
+ // TODO: In C++11 exceptions are only allowed in the swap function.
+ BOOST_TEST(scope == "hash::hash(hash)" ||
+ scope == "hash::operator=(hash)" ||
+ scope == "equal_to::equal_to(equal_to)" ||
+ scope == "equal_to::operator=(equal_to)");
+
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct self_swap_test1 : self_swap_base<T>
+{
+};
+
+template <class T> struct self_swap_test2 : self_swap_base<T>
+{
+ self_swap_test2() : self_swap_base<T>(100) {}
+};
+
+template <class T> struct swap_base : public test::exception_base
+{
+ const test::random_values<T> x_values, y_values;
+ const T initial_x, initial_y;
+
+ typedef typename T::hasher hasher;
+ typedef typename T::key_equal key_equal;
+ typedef typename T::allocator_type allocator_type;
+
+ swap_base(unsigned int count1, unsigned int count2, int tag1, int tag2)
+ : x_values(count1, test::limited_range),
+ y_values(count2, test::limited_range),
+ initial_x(x_values.begin(), x_values.end(), 0, hasher(tag1),
+ key_equal(tag1), allocator_type(tag1)),
+ initial_y(y_values.begin(), y_values.end(), 0, hasher(tag2),
+ key_equal(tag2),
+ allocator_type(T::allocator_type::propagate_on_container_swap::value
+ ? tag2
+ : tag1))
+ {
+ }
+
+ struct data_type
+ {
+ data_type(T const& x_, T const& y_) : x(x_), y(y_) {}
+
+ T x, y;
+ };
+
+ data_type init() const { return data_type(initial_x, initial_y); }
+
+ void run(data_type& d) const
+ {
+ try {
+ d.x.swap(d.y);
+ } catch (std::runtime_error&) {
+ }
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(d.x, this->y_values);
+ test::check_equivalent_keys(d.x);
+ test::check_container(d.y, this->x_values);
+ test::check_equivalent_keys(d.y);
+ }
+
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION(data_type const& d) const
+ {
+ std::string scope(test::scope);
+
+ // TODO: In C++11 exceptions are only allowed in the swap function.
+ BOOST_TEST(scope == "hash::hash(hash)" ||
+ scope == "hash::operator=(hash)" ||
+ scope == "equal_to::equal_to(equal_to)" ||
+ scope == "equal_to::operator=(equal_to)");
+
+ test::check_equivalent_keys(d.x);
+ test::check_equivalent_keys(d.y);
+ }
+};
+
+template <class T> struct swap_test1 : swap_base<T>
+{
+ swap_test1() : swap_base<T>(0, 0, 0, 0) {}
+};
+
+template <class T> struct swap_test2 : swap_base<T>
+{
+ swap_test2() : swap_base<T>(60, 0, 0, 0) {}
+};
+
+template <class T> struct swap_test3 : swap_base<T>
+{
+ swap_test3() : swap_base<T>(0, 60, 0, 0) {}
+};
+
+template <class T> struct swap_test4 : swap_base<T>
+{
+ swap_test4() : swap_base<T>(10, 10, 1, 2) {}
+};
+
+// clang-format off
+EXCEPTION_TESTS(
+ (self_swap_test1)(self_swap_test2)
+ (swap_test1)(swap_test2)(swap_test3)(swap_test4),
+ CONTAINER_SEQ)
+// clang-format on
+
+RUN_TESTS()