From 9ebb705e7595a35b9591edb6c21a63e6cadbd4c8 Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Mon, 12 Sep 2022 09:32:09 -0700 Subject: [PATCH] Update noexcept_tests to cover both values of POCMA and to also test move-assigning into larger and smaller hash tables --- test/unordered/noexcept_tests.cpp | 157 +++++++++++++++++++++++++----- 1 file changed, 131 insertions(+), 26 deletions(-) diff --git a/test/unordered/noexcept_tests.cpp b/test/unordered/noexcept_tests.cpp index f623b8d4..bc1207a1 100644 --- a/test/unordered/noexcept_tests.cpp +++ b/test/unordered/noexcept_tests.cpp @@ -11,6 +11,7 @@ // clang-format on #include "../helpers/test.hpp" +#include "../helpers/fwd.hpp" #if defined(BOOST_MSVC) #pragma warning(push) @@ -247,37 +248,65 @@ namespace noexcept_tests { throwing_test_exception = false; } - UNORDERED_AUTO_TEST (test_nothrow_move_assign_when_noexcept) { - typedef boost::unordered_set - throwing_set; + template + void test_nothrow_move_assign_when_noexcept(T*, test::random_generator const&) + { + { + if (have_is_nothrow_move_assign) { + BOOST_TEST(boost::is_nothrow_move_assignable::value); + } - if (have_is_nothrow_move_assign) { - BOOST_TEST(boost::is_nothrow_move_assignable::value); + throwing_test_exception = false; + + T x1; + T x2; + x1.insert(10); + x1.insert(50); + for (int i = 0; i < 100; ++i) { + x2.insert(i); + } + + try { + throwing_test_exception = true; + + x2 = boost::move(x1); + BOOST_TEST(x2.size() == 2); + BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50); + BOOST_TEST(have_is_nothrow_move_assign); + } catch (test_exception) { + BOOST_TEST(!have_is_nothrow_move_assign); + } + + throwing_test_exception = false; } - throwing_test_exception = false; + { + if (have_is_nothrow_move_assign) { + BOOST_TEST(boost::is_nothrow_move_assignable::value); + } - throwing_set x1; - throwing_set x2; - x1.insert(10); - x1.insert(50); - for (int i = 0; i < 100; ++i) { - x2.insert(i); + throwing_test_exception = false; + + T x1; + T x2; + x1.insert(10); + x1.insert(50); + for (int i = 0; i < 100; ++i) { + x2.insert(i); + } + + try { + throwing_test_exception = true; + + x1 = boost::move(x2); + BOOST_TEST(x1.size() == 100); + BOOST_TEST(have_is_nothrow_move_assign); + } catch (test_exception) { + BOOST_TEST(!have_is_nothrow_move_assign); + } + + throwing_test_exception = false; } - - try { - throwing_test_exception = true; - - x2 = boost::move(x1); - BOOST_TEST(x2.size() == 2); - BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50); - BOOST_TEST(have_is_nothrow_move_assign); - } catch (test_exception) { - BOOST_TEST(!have_is_nothrow_move_assign); - } - - throwing_test_exception = false; } UNORDERED_AUTO_TEST (test_nothrow_swap_when_noexcept) { @@ -318,4 +347,80 @@ namespace noexcept_tests { #pragma warning(pop) #endif +template class allocator1 +{ + BOOST_COPYABLE_AND_MOVABLE(allocator1) + allocator1 operator=(BOOST_COPY_ASSIGN_REF(allocator1)); + allocator1 operator=(BOOST_RV_REF(allocator1)); + +public: + typedef T value_type; + + allocator1() {} + allocator1(allocator1 const&) {} + + template allocator1(allocator1 const&) {} + + T* allocate(std::size_t n) + { + noexcept_tests::test_throw("Allocate"); + return static_cast(::operator new(n * sizeof(T))); + } + + void deallocate(T* p, std::size_t) { ::operator delete(p); } + + friend bool operator==(allocator1 const&, allocator1 const&) { return true; } + friend bool operator!=(allocator1 const&, allocator1 const&) { return false; } +}; + +template class allocator2 +{ + BOOST_COPYABLE_AND_MOVABLE(allocator2) + allocator2 operator=(BOOST_COPY_ASSIGN_REF(allocator2)); +public: + typedef T value_type; + typedef boost::true_type propagate_on_container_move_assignment; + + allocator2() {} + allocator2(allocator2 const&) {} + + template allocator2(allocator2 const&) {} + + allocator2& operator=(BOOST_RV_REF(allocator2)) { return *this; } + + T* allocate(std::size_t n) + { + noexcept_tests::test_throw("Allocate"); + return static_cast(::operator new(n * sizeof(T))); + } + + void deallocate(T* p, std::size_t) { ::operator delete(p); } + + friend bool operator==(allocator2 const&, allocator2 const&) { return true; } + friend bool operator!=(allocator2 const&, allocator2 const&) { return false; } +}; + +UNORDERED_AUTO_TEST (prelim_allocator_checks) { + BOOST_TEST(boost::allocator_is_always_equal >::type::value); + BOOST_TEST(!boost::allocator_propagate_on_container_move_assignment< + allocator1 >::type::value); + + BOOST_TEST(boost::allocator_is_always_equal >::type::value); + BOOST_TEST(boost::allocator_propagate_on_container_move_assignment< + allocator2 >::type::value); +} + +boost::unordered_set >* + throwing_set_alloc1; + +boost::unordered_set >* + throwing_set_alloc2; + +using test::default_generator; + +UNORDERED_TEST(test_nothrow_move_assign_when_noexcept, + ((throwing_set_alloc1)(throwing_set_alloc2))((default_generator))) + RUN_TESTS()