diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 4849bdfa..8b3b7a5a 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -1516,7 +1516,7 @@ construct_from_args(Alloc& alloc, std::pair* address, BOOST_FWD_REF(A0), { boost::unordered::detail::func::destroy( boost::addressof(address->first)); - BOOST_RETHROW; + BOOST_RETHROW } BOOST_CATCH_END } @@ -1551,7 +1551,7 @@ inline typename enable_if, void>::type construct_from_args( { boost::unordered::detail::func::destroy( boost::addressof(address->first)); - BOOST_RETHROW; + BOOST_RETHROW } BOOST_CATCH_END } @@ -1630,7 +1630,7 @@ inline void construct_from_args(Alloc& alloc, std::pair* address, { boost::unordered::detail::func::destroy( boost::addressof(address->first)); - BOOST_RETHROW; + BOOST_RETHROW } BOOST_CATCH_END } @@ -1841,7 +1841,7 @@ construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k) { boost::unordered::detail::func::destroy( boost::addressof(a.node_->value_ptr()->first)); - BOOST_RETHROW; + BOOST_RETHROW } BOOST_CATCH_END return a.release(); @@ -1865,7 +1865,7 @@ construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m) { boost::unordered::detail::func::destroy( boost::addressof(a.node_->value_ptr()->first)); - BOOST_RETHROW; + BOOST_RETHROW } BOOST_CATCH_END return a.release(); @@ -1890,7 +1890,7 @@ construct_node_pair_from_args( { boost::unordered::detail::func::destroy( boost::addressof(a.node_->value_ptr()->first)); - BOOST_RETHROW; + BOOST_RETHROW } BOOST_CATCH_END return a.release(); @@ -4274,7 +4274,10 @@ inline void table::rehash_impl(std::size_t num_buckets) } } } - BOOST_CATCH(...) { delete_nodes(prev, node_pointer()); } + BOOST_CATCH(...) { + delete_nodes(prev, node_pointer()); + BOOST_RETHROW + } BOOST_CATCH_END } diff --git a/test/exception/assign_exception_tests.cpp b/test/exception/assign_exception_tests.cpp index 3295a4e8..2b39bf74 100644 --- a/test/exception/assign_exception_tests.cpp +++ b/test/exception/assign_exception_tests.cpp @@ -7,6 +7,7 @@ #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 @@ -21,7 +22,13 @@ template struct self_assign_base : public test::exception_base typedef T data_type; T init() const { return T(values.begin(), values.end()); } - void run(T& x) const { x = x; } + + void run(T& x) const { + x = x; + 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); @@ -57,7 +64,13 @@ template struct assign_base : public test::exception_base typedef T data_type; T init() const { return T(x); } - void run(T& x1) const { x1 = y; } + + void run(T& x1) const { + x1 = y; + 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); diff --git a/test/exception/constructor_exception_tests.cpp b/test/exception/constructor_exception_tests.cpp index db5023f7..e4a12420 100644 --- a/test/exception/constructor_exception_tests.cpp +++ b/test/exception/constructor_exception_tests.cpp @@ -7,6 +7,8 @@ #include "../helpers/input_iterator.hpp" #include "../helpers/random_values.hpp" +#include "../helpers/invariants.hpp" +#include "../helpers/tracker.hpp" template inline void avoid_unused_warning(T const&) {} @@ -25,7 +27,8 @@ template struct construct_test1 : public objects, test::exception_base void run() const { T x; - avoid_unused_warning(x); + BOOST_TEST(x.empty()); + test::check_equivalent_keys(x); } }; @@ -34,7 +37,8 @@ template struct construct_test2 : public objects, test::exception_base void run() const { T x(300); - avoid_unused_warning(x); + BOOST_TEST(x.empty()); + test::check_equivalent_keys(x); } }; @@ -43,7 +47,8 @@ template struct construct_test3 : public objects, test::exception_base void run() const { T x(0, hash); - avoid_unused_warning(x); + BOOST_TEST(x.empty()); + test::check_equivalent_keys(x); } }; @@ -52,7 +57,8 @@ template struct construct_test4 : public objects, test::exception_base void run() const { T x(0, hash, equal_to); - avoid_unused_warning(x); + BOOST_TEST(x.empty()); + test::check_equivalent_keys(x); } }; @@ -61,7 +67,8 @@ template struct construct_test5 : public objects, test::exception_base void run() const { T x(50, hash, equal_to, allocator); - avoid_unused_warning(x); + BOOST_TEST(x.empty()); + test::check_equivalent_keys(x); } }; @@ -70,7 +77,8 @@ template struct construct_test6 : public objects, test::exception_base void run() const { T x(allocator); - avoid_unused_warning(x); + BOOST_TEST(x.empty()); + test::check_equivalent_keys(x); } }; @@ -87,7 +95,8 @@ template struct range_construct_test1 : public range, objects void run() const { T x(this->values.begin(), this->values.end()); - avoid_unused_warning(x); + test::check_container(x, this->values); + test::check_equivalent_keys(x); } }; @@ -96,7 +105,8 @@ template struct range_construct_test2 : public range, objects void run() const { T x(this->values.begin(), this->values.end(), 0); - avoid_unused_warning(x); + test::check_container(x, this->values); + test::check_equivalent_keys(x); } }; @@ -105,7 +115,8 @@ template struct range_construct_test3 : public range, objects void run() const { T x(this->values.begin(), this->values.end(), 0, hash); - avoid_unused_warning(x); + test::check_container(x, this->values); + test::check_equivalent_keys(x); } }; @@ -114,7 +125,8 @@ template struct range_construct_test4 : public range, objects void run() const { T x(this->values.begin(), this->values.end(), 100, hash, equal_to); - avoid_unused_warning(x); + test::check_container(x, this->values); + test::check_equivalent_keys(x); } }; @@ -128,7 +140,8 @@ template struct range_construct_test5 : public range, objects { T x(this->values.begin(), this->values.end(), 0, hash, equal_to, allocator); - avoid_unused_warning(x); + test::check_container(x, this->values); + test::check_equivalent_keys(x); } }; @@ -143,7 +156,8 @@ template struct input_range_construct_test : public range, objects end = this->values.end(); T x(test::input_iterator(begin), test::input_iterator(end), 0, hash, equal_to, allocator); - avoid_unused_warning(x); + test::check_container(x, this->values); + test::check_equivalent_keys(x); } }; @@ -156,7 +170,8 @@ template struct copy_range_construct_test : public range, objects T x(test::copy_iterator(this->values.begin()), test::copy_iterator(this->values.end()), 0, hash, equal_to, allocator); - avoid_unused_warning(x); + test::check_container(x, this->values); + test::check_equivalent_keys(x); } }; diff --git a/test/exception/copy_exception_tests.cpp b/test/exception/copy_exception_tests.cpp index 9bb87eca..2faa7e84 100644 --- a/test/exception/copy_exception_tests.cpp +++ b/test/exception/copy_exception_tests.cpp @@ -6,6 +6,8 @@ #include "./containers.hpp" #include "../helpers/random_values.hpp" +#include "../helpers/invariants.hpp" +#include "../helpers/tracker.hpp" template inline void avoid_unused_warning(T const&) {} @@ -18,7 +20,8 @@ template struct copy_test1 : public test::exception_base void run() const { T y(x); - avoid_unused_warning(y); + BOOST_TEST(y.empty()); + test::check_equivalent_keys(y); } }; @@ -32,7 +35,8 @@ template struct copy_test2 : public test::exception_base void run() const { T y(x); - avoid_unused_warning(y); + test::check_container(y, this->values); + test::check_equivalent_keys(y); } }; @@ -46,7 +50,8 @@ template struct copy_test3 : public test::exception_base void run() const { T y(x); - avoid_unused_warning(y); + test::check_container(y, this->values); + test::check_equivalent_keys(y); } }; @@ -61,7 +66,8 @@ template struct copy_with_allocator_test : public test::exception_base void run() const { T y(x, allocator); - avoid_unused_warning(y); + test::check_container(y, this->values); + test::check_equivalent_keys(y); } }; diff --git a/test/exception/erase_exception_tests.cpp b/test/exception/erase_exception_tests.cpp index a939ded3..719ceb87 100644 --- a/test/exception/erase_exception_tests.cpp +++ b/test/exception/erase_exception_tests.cpp @@ -43,6 +43,9 @@ template struct erase_by_key_test1 : public erase_test_base it != end; ++it) { x.erase(test::get_key(*it)); } + + BOOST_TEST(x.empty()); + test::check_equivalent_keys(x); } }; diff --git a/test/exception/insert_exception_tests.cpp b/test/exception/insert_exception_tests.cpp index f8d635de..b43ece5c 100644 --- a/test/exception/insert_exception_tests.cpp +++ b/test/exception/insert_exception_tests.cpp @@ -2,13 +2,14 @@ // 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 #include "../helpers/helpers.hpp" #include "../helpers/invariants.hpp" #include "../helpers/random_values.hpp" #include "../helpers/strong.hpp" +#include "../helpers/tracker.hpp" #include #include @@ -54,6 +55,10 @@ template struct emplace_test1 : public insert_test_base strong.store(x, test::detail::tracker.count_allocations); x.emplace(*it); } + + DISABLE_EXCEPTIONS; + test::check_container(x, this->values); + test::check_equivalent_keys(x); } }; @@ -72,6 +77,10 @@ template struct insert_test1 : public insert_test_base strong.store(x, test::detail::tracker.count_allocations); x.insert(*it); } + + DISABLE_EXCEPTIONS; + test::check_container(x, this->values); + test::check_equivalent_keys(x); } }; @@ -88,12 +97,23 @@ template struct insert_test2 : public insert_test_base strong.store(x, test::detail::tracker.count_allocations); x.insert(x.begin(), *it); } + + DISABLE_EXCEPTIONS; + test::check_container(x, this->values); + test::check_equivalent_keys(x); } }; template struct insert_test3 : public insert_test_base { - void run(T& x) const { x.insert(this->values.begin(), this->values.end()); } + void run(T& x) const + { + x.insert(this->values.begin(), this->values.end()); + + DISABLE_EXCEPTIONS; + test::check_container(x, this->values); + test::check_equivalent_keys(x); + } void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const { @@ -114,6 +134,10 @@ template struct insert_test4 : public insert_test_base strong.store(x, test::detail::tracker.count_allocations); x.insert(it, test::next(it)); } + + DISABLE_EXCEPTIONS; + test::check_container(x, this->values); + test::check_equivalent_keys(x); } }; @@ -147,17 +171,30 @@ template struct insert_test_rehash1 : public insert_test_base int count = 0; BOOST_DEDUCED_TYPENAME T::const_iterator pos = x.cbegin(); + test::list v; + { + DISABLE_EXCEPTIONS; + v.insert(x.begin(), x.end()); + } + for (BOOST_DEDUCED_TYPENAME test::random_values::const_iterator it = test::next(this->values.begin(), x.size()), end = this->values.end(); it != end && count < 10; ++it, ++count) { strong.store(x, test::detail::tracker.count_allocations); pos = x.insert(pos, *it); + + DISABLE_EXCEPTIONS; + v.push_back(*it); } // This isn't actually a failure, but it means the test isn't doing its // job. BOOST_TEST(x.bucket_count() != bucket_count); + + DISABLE_EXCEPTIONS; + test::check_container(x, v); + test::check_equivalent_keys(x); } }; @@ -170,17 +207,30 @@ template struct insert_test_rehash2 : public insert_test_rehash1 BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count(); int count = 0; + test::list v; + { + DISABLE_EXCEPTIONS; + v.insert(x.begin(), x.end()); + } + for (BOOST_DEDUCED_TYPENAME test::random_values::const_iterator it = test::next(this->values.begin(), x.size()), end = this->values.end(); it != end && count < 10; ++it, ++count) { strong.store(x, test::detail::tracker.count_allocations); x.insert(*it); + + DISABLE_EXCEPTIONS; + v.push_back(*it); } // This isn't actually a failure, but it means the test isn't doing its // job. BOOST_TEST(x.bucket_count() != bucket_count); + + DISABLE_EXCEPTIONS; + test::check_container(x, v); + test::check_equivalent_keys(x); } }; @@ -218,6 +268,14 @@ template struct insert_test_rehash3 : public insert_test_base void run(T& x) const { BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count(); + test::list v; + + { + DISABLE_EXCEPTIONS; + v.insert(x.begin(), x.end()); + v.insert(test::next(this->values.begin(), x.size()), + test::next(this->values.begin(), x.size() + 20)); + } x.insert(test::next(this->values.begin(), x.size()), test::next(this->values.begin(), x.size() + 20)); @@ -225,6 +283,10 @@ template struct insert_test_rehash3 : public insert_test_base // This isn't actually a failure, but it means the test isn't doing its // job. BOOST_TEST(x.bucket_count() != bucket_count); + + DISABLE_EXCEPTIONS; + test::check_container(x, v); + test::check_equivalent_keys(x); } void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const @@ -263,6 +325,10 @@ template struct pair_emplace_test1 : public insert_test_base x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(it->first), boost::make_tuple(it->second)); } + + DISABLE_EXCEPTIONS; + test::check_container(x, this->values); + test::check_equivalent_keys(x); } }; @@ -281,6 +347,10 @@ template struct pair_emplace_test2 : public insert_test_base boost::make_tuple(it->first), boost::make_tuple(it->second.tag1_, it->second.tag2_)); } + + DISABLE_EXCEPTIONS; + test::check_container(x, this->values); + test::check_equivalent_keys(x); } }; diff --git a/test/exception/move_assign_exception_tests.cpp b/test/exception/move_assign_exception_tests.cpp index 9a8d122b..048ab102 100644 --- a/test/exception/move_assign_exception_tests.cpp +++ b/test/exception/move_assign_exception_tests.cpp @@ -7,6 +7,7 @@ #include "../helpers/invariants.hpp" #include "../helpers/random_values.hpp" +#include "../helpers/tracker.hpp" #include #if defined(BOOST_MSVC) @@ -42,7 +43,11 @@ template struct move_assign_base : public test::exception_base T y1 = y; disable_exceptions.release(); x1 = boost::move(y1); + + 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); diff --git a/test/exception/rehash_exception_tests.cpp b/test/exception/rehash_exception_tests.cpp index a65ebae9..ae31f397 100644 --- a/test/exception/rehash_exception_tests.cpp +++ b/test/exception/rehash_exception_tests.cpp @@ -8,6 +8,7 @@ #include "../helpers/invariants.hpp" #include "../helpers/random_values.hpp" #include "../helpers/strong.hpp" +#include "../helpers/tracker.hpp" #include #include @@ -49,34 +50,76 @@ template struct rehash_test_base : public test::exception_base template struct rehash_test0 : rehash_test_base { rehash_test0() : rehash_test_base(0) {} - void run(T& x) const { x.rehash(0); } + void run(T& x) const + { + x.rehash(0); + DISABLE_EXCEPTIONS; + test::check_container(x, this->values); + test::check_equivalent_keys(x); + } }; template struct rehash_test1 : rehash_test_base { rehash_test1() : rehash_test_base(0) {} - void run(T& x) const { x.rehash(200); } + void run(T& x) const + { + x.rehash(200); + DISABLE_EXCEPTIONS; + test::check_container(x, this->values); + test::check_equivalent_keys(x); + } }; template struct rehash_test2 : rehash_test_base { rehash_test2() : rehash_test_base(0, 200) {} - void run(T& x) const { x.rehash(0); } + void run(T& x) const + { + x.rehash(0); + DISABLE_EXCEPTIONS; + test::check_container(x, this->values); + test::check_equivalent_keys(x); + } }; template struct rehash_test3 : rehash_test_base { rehash_test3() : rehash_test_base(10, 0) {} - void run(T& x) const { x.rehash(200); } + void run(T& x) const + { + x.rehash(200); + DISABLE_EXCEPTIONS; + test::check_container(x, this->values); + test::check_equivalent_keys(x); + } }; template struct rehash_test4 : rehash_test_base { rehash_test4() : rehash_test_base(10, 200) {} - void run(T& x) const { x.rehash(0); } + void run(T& x) const + { + x.rehash(0); + DISABLE_EXCEPTIONS; + test::check_container(x, this->values); + test::check_equivalent_keys(x); + } }; -EXCEPTION_TESTS( - (rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(rehash_test4), +template struct rehash_test5 : rehash_test_base +{ + rehash_test5() : rehash_test_base(200, 10) {} + void run(T& x) const + { + x.rehash(0); + DISABLE_EXCEPTIONS; + test::check_container(x, this->values); + test::check_equivalent_keys(x); + } +}; + +EXCEPTION_TESTS((rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)( + rehash_test4)(rehash_test5), CONTAINER_SEQ) RUN_TESTS() diff --git a/test/exception/swap_exception_tests.cpp b/test/exception/swap_exception_tests.cpp index 12ba6403..13ee18b3 100644 --- a/test/exception/swap_exception_tests.cpp +++ b/test/exception/swap_exception_tests.cpp @@ -7,6 +7,7 @@ #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 @@ -21,7 +22,15 @@ template struct self_swap_base : public test::exception_base typedef T data_type; T init() const { return T(values.begin(), values.end()); } - void run(T& x) const { x.swap(x); } + + 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); @@ -82,7 +91,14 @@ template struct swap_base : public test::exception_base 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); diff --git a/test/objects/exception.hpp b/test/objects/exception.hpp index e76ac477..017c88da 100644 --- a/test/objects/exception.hpp +++ b/test/objects/exception.hpp @@ -11,6 +11,7 @@ #include "../helpers/count.hpp" #include "../helpers/fwd.hpp" #include "../helpers/memory.hpp" +#include "../objects/fwd.hpp" #include #include #include @@ -311,6 +312,55 @@ class equal_to } }; +class less +{ + int tag_; + + public: + less(int t = 0) : tag_(t) {} + + less(less const& x) : tag_(x.tag_) {} + + bool operator()(object const& x1, object const& x2) const + { + return less_impl(x1, x2); + } + + bool operator()(std::pair const& x1, + std::pair const& x2) const + { + if (less_impl(x1.first, x2.first)) { + return true; + } + if (!less_impl(x1.first, x2.first)) { + return false; + } + return less_impl(x1.second, x2.second); + } + + bool less_impl(object const& x1, object const& x2) const + { + switch (tag_) { + case 1: + return x1.tag1_ < x2.tag1_; + case 2: + return x1.tag2_ < x2.tag2_; + default: + return x1 < x2; + } + } + + friend bool operator==(less const& x1, less const& x2) + { + return x1.tag_ == x2.tag_; + } + + friend bool operator!=(less const& x1, less const& x2) + { + return x1.tag_ != x2.tag_; + } +}; + template class allocator { public: @@ -672,6 +722,14 @@ inline bool operator!=(allocator2 const& x, allocator2 const& y) } } +namespace test { +template struct equals_to_compare; +template <> struct equals_to_compare +{ + typedef test::exception::less type; +}; +} + // Workaround for ADL deficient compilers #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) namespace test {