diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/unordered/test/exception | |
parent | Initial commit. (diff) | |
download | ceph-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')
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() |