From 61f11a58ee491f260326c1ac827ae9dfdb9a1583 Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Tue, 23 May 2023 15:28:14 -0700 Subject: [PATCH] Push up failing test case for code review purposes --- test/Jamfile.v2 | 1 + test/cfoa/exception_constructor_tests.cpp | 172 ++++++++++++++++++++++ test/cfoa/exception_helpers.hpp | 12 +- 3 files changed, 179 insertions(+), 6 deletions(-) create mode 100644 test/cfoa/exception_constructor_tests.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 8d985b65..1a4a0627 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -192,6 +192,7 @@ local CFOA_TESTS = fwd_tests exception_insert_tests exception_erase_tests + exception_constructor_tests ; for local test in $(CFOA_TESTS) diff --git a/test/cfoa/exception_constructor_tests.cpp b/test/cfoa/exception_constructor_tests.cpp new file mode 100644 index 00000000..1a9bc653 --- /dev/null +++ b/test/cfoa/exception_constructor_tests.cpp @@ -0,0 +1,172 @@ +// Copyright (C) 2023 Christian Mazakas +// 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 "exception_helpers.hpp" + +#include + +using allocator_type = stateful_allocator >; + +using map_type = boost::unordered::concurrent_flat_map; + +namespace { + test::seed_t initialize_seed(795610904); + + UNORDERED_AUTO_TEST (bucket_constructor) { + raii::reset_counts(); + + bool was_thrown = false; + + enable_exceptions(); + for (std::size_t i = 0; i < alloc_throw_threshold; ++i) { + try { + map_type m(128); + } catch (...) { + was_thrown = true; + } + } + disable_exceptions(); + + BOOST_TEST(was_thrown); + } + + template + void iterator_bucket_count_constructor(G gen, test::random_generator rg) + { + auto values = make_random_values(1024 * 16, [&] { return gen(rg); }); + + raii::reset_counts(); + + bool was_thrown = false; + + enable_exceptions(); + try { + map_type x(values.begin(), values.end(), 0, stateful_hash(1), + stateful_key_equal(2), allocator_type(3)); + } catch (...) { + was_thrown = true; + } + disable_exceptions(); + + BOOST_TEST(was_thrown); + check_raii_counts(); + } + + template void copy_constructor(G gen, test::random_generator rg) + { + auto values = make_random_values(1024 * 16, [&] { return gen(rg); }); + + { + raii::reset_counts(); + + bool was_thrown = false; + + try { + map_type x(values.begin(), values.end(), 0); + + enable_exceptions(); + map_type y(x); + } catch (...) { + was_thrown = true; + } + disable_exceptions(); + + BOOST_TEST(was_thrown); + check_raii_counts(); + } + + { + raii::reset_counts(); + + bool was_thrown = false; + + try { + map_type x(values.begin(), values.end(), 0); + + enable_exceptions(); + map_type y(x, allocator_type(4)); + } catch (...) { + was_thrown = true; + } + disable_exceptions(); + + BOOST_TEST(was_thrown); + check_raii_counts(); + } + } + + template + void iterator_range_allocator_constructor(G gen, test::random_generator rg) + { + auto values = make_random_values(1024 * 16, [&] { return gen(rg); }); + + raii::reset_counts(); + + bool was_thrown = false; + + enable_exceptions(); + try { + map_type x(values.begin(), values.end(), allocator_type(3)); + } catch (...) { + was_thrown = true; + } + disable_exceptions(); + + BOOST_TEST(was_thrown); + check_raii_counts(); + } + + template void move_constructor(G gen, test::random_generator rg) + { + auto values = make_random_values(1024 * 16, [&] { return gen(rg); }); + + { + raii::reset_counts(); + + bool was_thrown = false; + + try { + map_type x(values.begin(), values.end(), 0); + + enable_exceptions(); + map_type y(std::move(x), allocator_type(4)); + } catch (...) { + was_thrown = true; + } + disable_exceptions(); + + BOOST_TEST(was_thrown); + check_raii_counts(); + } + } +} // namespace + +using test::default_generator; +using test::limited_range; +using test::sequential; + +// clang-format off +UNORDERED_TEST( + iterator_bucket_count_constructor, + ((exception_value_type_generator)) + ((default_generator)(sequential)(limited_range))) + +UNORDERED_TEST( + copy_constructor, + ((exception_value_type_generator)) + ((default_generator)(sequential))) + +UNORDERED_TEST( + iterator_range_allocator_constructor, + ((exception_value_type_generator)) + ((default_generator)(sequential)(limited_range))) + +UNORDERED_TEST( + move_constructor, + ((exception_value_type_generator)) + ((default_generator)(sequential))) +// clang-format on + +RUN_TESTS() diff --git a/test/cfoa/exception_helpers.hpp b/test/cfoa/exception_helpers.hpp index 554c3f2b..79bee58e 100644 --- a/test/cfoa/exception_helpers.hpp +++ b/test/cfoa/exception_helpers.hpp @@ -29,6 +29,7 @@ static std::size_t const num_threads = std::atomic_bool should_throw{false}; constexpr std::uint32_t throw_threshold = 2500; +constexpr std::uint32_t alloc_throw_threshold = 10; void enable_exceptions() { should_throw = true; } void disable_exceptions() { should_throw = false; } @@ -136,15 +137,16 @@ struct stateful_key_equal }; std::atomic stateful_key_equal::c{0}; +static std::atomic allocator_c = {}; + template struct stateful_allocator { int x_ = -1; - static std::atomic c; void throw_helper() const { - auto n = ++c; - if (should_throw && ((n + 1) % 10 == 0)) { + auto n = ++allocator_c; + if (should_throw && ((n + 1) % alloc_throw_threshold == 0)) { throw exception_tag{}; } } @@ -174,8 +176,6 @@ template struct stateful_allocator bool operator!=(stateful_allocator const& rhs) const { return x_ != rhs.x_; } }; -template std::atomic stateful_allocator::c = {}; - struct raii { static std::atomic default_constructor; @@ -289,7 +289,7 @@ struct raii stateful_hash::c = 0; stateful_key_equal::c = 0; - stateful_allocator::c = 0; + allocator_c = 0; } friend void swap(raii& lhs, raii& rhs) { std::swap(lhs.x_, rhs.x_); }