From 0959df18960db166ab3f8ca10128df807a3769d0 Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Thu, 27 Apr 2023 09:30:49 -0700 Subject: [PATCH] Flesh out move assignment tests --- test/cfoa/assign_tests.cpp | 194 +++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) diff --git a/test/cfoa/assign_tests.cpp b/test/cfoa/assign_tests.cpp index d527eb46..8734433f 100644 --- a/test/cfoa/assign_tests.cpp +++ b/test/cfoa/assign_tests.cpp @@ -7,11 +7,17 @@ #include #if defined(__clang__) && defined(__has_warning) + #if __has_warning("-Wself-assign-overloaded") #pragma clang diagnostic ignored "-Wself-assign-overloaded" #endif + +#if __has_warning("-Wself-move") +#pragma clang diagnostic ignored "-Wself-move" #endif +#endif /* defined(__clang__) && defined(__has_warning) */ + test::seed_t initialize_seed{2762556623}; using test::default_generator; @@ -64,6 +70,43 @@ template struct pocca_allocator bool operator!=(pocca_allocator const& rhs) const { return x_ != rhs.x_; } }; +template struct pocma_allocator +{ + using propagate_on_container_move_assignment = std::true_type; + + int x_ = -1; + + using value_type = T; + + pocma_allocator() = default; + pocma_allocator(pocma_allocator const&) = default; + pocma_allocator(pocma_allocator&&) = default; + + pocma_allocator(int const x) : x_{x} {} + + pocma_allocator& operator=(pocma_allocator const& rhs) + { + if (this != &rhs) { + x_ = rhs.x_; + } + return *this; + } + + template pocma_allocator(pocma_allocator const& rhs) : x_{rhs.x_} + { + } + + T* allocate(std::size_t n) + { + return static_cast(::operator new(n * sizeof(T))); + } + + void deallocate(T* p, std::size_t) { ::operator delete(p); } + + bool operator==(pocma_allocator const& rhs) const { return x_ == rhs.x_; } + bool operator!=(pocma_allocator const& rhs) const { return x_ != rhs.x_; } +}; + namespace { template void copy_assign(G gen, test::random_generator rg) { @@ -476,6 +519,157 @@ namespace { old_cc + (num_threads * 2 * reference_map.size())); } check_raii_counts(); + + // lhs non-empty, rhs non-empty, unequal allocators, no propagation + { + raii::reset_counts(); + + map_type x(values.begin(), values.end(), values.size(), hasher(1), + key_equal(2), allocator_type(3)); + + auto const old_size = x.size(); + auto const old_cc = +raii::copy_constructor; + auto const old_mc = +raii::move_constructor; + + std::atomic num_transfers{0}; + + thread_runner(values, [&x, &values, &num_transfers, &reference_map]( + boost::span s) { + (void)s; + + map_type y(values.begin(), values.end(), values.size(), hasher(2), + key_equal(1), allocator_type(13)); + + BOOST_TEST( + !boost::allocator_is_always_equal::type::value); + + BOOST_TEST(!boost::allocator_propagate_on_container_move_assignment< + allocator_type>::type::value); + + BOOST_TEST(!y.empty()); + BOOST_TEST(x.get_allocator() != y.get_allocator()); + + y = std::move(x); + if (y.hash_function() == hasher(1)) { + ++num_transfers; + test_matches_reference(y, reference_map); + + BOOST_TEST_EQ(y.key_eq(), key_equal(2)); + } else { + BOOST_TEST_EQ(y.hash_function(), hasher(2)); + BOOST_TEST_EQ(y.key_eq(), key_equal(1)); + } + + BOOST_TEST(x.empty()); + + BOOST_TEST_EQ(x.hash_function(), hasher(2)); + BOOST_TEST_EQ(x.key_eq(), key_equal(1)); + BOOST_TEST(x.get_allocator() != y.get_allocator()); + }); + + BOOST_TEST_EQ(num_transfers, 1u); + + BOOST_TEST_EQ( + raii::destructor, 2 * 2 * old_size + num_threads * 2 * old_size); + BOOST_TEST_EQ(raii::copy_assignment, 0u); + BOOST_TEST_EQ(raii::move_assignment, 0u); + BOOST_TEST_EQ(raii::move_constructor, old_mc + 2 * old_size); + BOOST_TEST_EQ(raii::copy_constructor, + old_cc + (num_threads * 2 * reference_map.size())); + } + check_raii_counts(); + + // lhs non-empty, rhs non-empty, pocma + { + raii::reset_counts(); + + using pocma_allocator_type = + pocma_allocator >; + + using pocma_map_type = boost::unordered::concurrent_flat_map; + + pocma_map_type x(values.begin(), values.end(), values.size(), hasher(1), + key_equal(2), pocma_allocator_type(3)); + + auto const old_size = x.size(); + auto const old_cc = +raii::copy_constructor; + auto const old_mc = +raii::move_constructor; + + std::atomic num_transfers{0}; + + thread_runner(values, [&x, &values, &num_transfers, &reference_map]( + boost::span s) { + (void)s; + + pocma_map_type y(values.begin(), values.end(), values.size(), hasher(2), + key_equal(1), pocma_allocator_type(13)); + + BOOST_TEST(!y.empty()); + BOOST_TEST(x.get_allocator() != y.get_allocator()); + + y = std::move(x); + if (y.hash_function() == hasher(1)) { + ++num_transfers; + test_matches_reference(y, reference_map); + + BOOST_TEST_EQ(y.key_eq(), key_equal(2)); + } else { + BOOST_TEST_EQ(y.hash_function(), hasher(2)); + BOOST_TEST_EQ(y.key_eq(), key_equal(1)); + } + + BOOST_TEST(x.empty()); + + BOOST_TEST_EQ(x.hash_function(), hasher(2)); + BOOST_TEST_EQ(x.key_eq(), key_equal(1)); + BOOST_TEST(x.get_allocator() == y.get_allocator()); + }); + + BOOST_TEST_EQ(num_transfers, 1u); + + BOOST_TEST_EQ( + raii::destructor, 2 * old_size + num_threads * 2 * old_size); + BOOST_TEST_EQ(raii::copy_assignment, 0u); + BOOST_TEST_EQ(raii::move_assignment, 0u); + BOOST_TEST_EQ(raii::move_constructor, old_mc); + BOOST_TEST_EQ(raii::copy_constructor, + old_cc + (num_threads * 2 * reference_map.size())); + } + check_raii_counts(); + + // self-assign + { + raii::reset_counts(); + + map_type x(values.begin(), values.end(), values.size(), hasher(1), + key_equal(2), allocator_type(3)); + + auto const old_cc = +raii::copy_constructor; + auto const old_mc = +raii::move_constructor; + + thread_runner( + values, [&x, &reference_map](boost::span s) { + (void)s; + + x = std::move(x); + + BOOST_TEST(!x.empty()); + + BOOST_TEST_EQ(x.hash_function(), hasher(1)); + BOOST_TEST_EQ(x.key_eq(), key_equal(2)); + BOOST_TEST(x.get_allocator() == allocator_type(3)); + + test_matches_reference(x, reference_map); + }); + + BOOST_TEST_EQ(raii::destructor, 0); + BOOST_TEST_EQ(raii::copy_assignment, 0u); + BOOST_TEST_EQ(raii::move_assignment, 0u); + BOOST_TEST_EQ(raii::move_constructor, old_mc); + BOOST_TEST_EQ(raii::copy_constructor, old_cc); + } + check_raii_counts(); } } // namespace