1// Copyright (C) 2023 Christian Mazakas
2// Copyright (C) 2023 Joaquin M Lopez Munoz
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#include "exception_helpers.hpp"
7
8#include <boost/unordered/concurrent_flat_map.hpp>
9#include <boost/unordered/concurrent_flat_set.hpp>
10
11using hasher = stateful_hash;
12using key_equal = stateful_key_equal;
13
14using map_type = boost::unordered::concurrent_flat_map<raii, raii, hasher,
15 key_equal, stateful_allocator<std::pair<raii const, raii> > >;
16
17using set_type = boost::unordered::concurrent_flat_set<raii, hasher,
18 key_equal, stateful_allocator<raii> >;
19
20map_type* test_map;
21set_type* test_set;
22
23std::initializer_list<map_type::value_type> map_init_list{
24 {raii{0}, raii{0}},
25 {raii{1}, raii{1}},
26 {raii{2}, raii{2}},
27 {raii{3}, raii{3}},
28 {raii{4}, raii{4}},
29 {raii{5}, raii{5}},
30 {raii{6}, raii{6}},
31 {raii{6}, raii{6}},
32 {raii{7}, raii{7}},
33 {raii{8}, raii{8}},
34 {raii{9}, raii{9}},
35 {raii{10}, raii{10}},
36 {raii{9}, raii{9}},
37 {raii{8}, raii{8}},
38 {raii{7}, raii{7}},
39 {raii{6}, raii{6}},
40 {raii{5}, raii{5}},
41 {raii{4}, raii{4}},
42 {raii{3}, raii{3}},
43 {raii{2}, raii{2}},
44 {raii{1}, raii{1}},
45 {raii{0}, raii{0}},
46};
47
48std::initializer_list<set_type::value_type> set_init_list{
49 raii{0},
50 raii{1},
51 raii{2},
52 raii{3},
53 raii{4},
54 raii{5},
55 raii{6},
56 raii{6},
57 raii{7},
58 raii{8},
59 raii{9},
60 raii{10},
61 raii{9},
62 raii{8},
63 raii{7},
64 raii{6},
65 raii{5},
66 raii{4},
67 raii{3},
68 raii{2},
69 raii{1},
70 raii{0},
71};
72
73auto test_map_and_init_list=std::make_pair(x&: test_map,y&: map_init_list);
74auto test_set_and_init_list=std::make_pair(x&: test_set,y&: set_init_list);
75
76namespace {
77 test::seed_t initialize_seed(1794114520);
78
79 template <class X, class GF>
80 void copy_assign(X*, GF gen_factory, test::random_generator rg)
81 {
82 using allocator_type = typename X::allocator_type;
83
84 auto gen = gen_factory.template get<X>();
85 auto values = make_random_values(1024 * 16, [&] { return gen(rg); });
86
87 {
88 raii::reset_counts();
89
90 unsigned num_throws = 0;
91
92 auto begin = values.begin();
93 auto mid =
94 values.begin() + static_cast<std::ptrdiff_t>(values.size() / 2);
95 auto end = values.end();
96
97 auto reference_cont = reference_container<X>(begin, mid);
98
99 X x(
100 begin, mid, values.size(), hasher(1), key_equal(2), allocator_type(3));
101
102 X y(
103 mid, end, values.size(), hasher(2), key_equal(1), allocator_type(4));
104
105 BOOST_TEST(!y.empty());
106
107 enable_exceptions();
108 for (std::size_t i = 0; i < 2 * alloc_throw_threshold; ++i) {
109 try {
110 y = x;
111 } catch (...) {
112 ++num_throws;
113 }
114 }
115
116 disable_exceptions();
117
118 BOOST_TEST_GT(num_throws, 0u);
119 test_fuzzy_matches_reference(y, reference_cont, rg);
120 }
121 check_raii_counts();
122 }
123
124 template <class X, class GF>
125 void move_assign(X*, GF gen_factory, test::random_generator rg)
126 {
127 using allocator_type = typename X::allocator_type;
128
129 auto gen = gen_factory.template get<X>();
130 auto values = make_random_values(1024 * 16, [&] { return gen(rg); });
131
132 {
133 raii::reset_counts();
134
135 unsigned num_throws = 0;
136
137 auto begin = values.begin();
138 auto mid =
139 values.begin() + static_cast<std::ptrdiff_t>(values.size() / 2);
140 auto end = values.end();
141
142 auto reference_cont = reference_container<X>(begin, mid);
143
144 BOOST_TEST(
145 !boost::allocator_is_always_equal<allocator_type>::type::value);
146
147 BOOST_TEST(!boost::allocator_propagate_on_container_move_assignment<
148 allocator_type>::type::value);
149
150 for (std::size_t i = 0; i < 2 * alloc_throw_threshold; ++i) {
151 disable_exceptions();
152
153 X x(begin, mid, values.size(), hasher(1), key_equal(2),
154 allocator_type(3));
155
156 X y(
157 mid, end, values.size(), hasher(2), key_equal(1), allocator_type(4));
158
159 enable_exceptions();
160 try {
161 y = std::move(x);
162 } catch (...) {
163 ++num_throws;
164 }
165 disable_exceptions();
166 test_fuzzy_matches_reference(y, reference_cont, rg);
167 }
168
169 BOOST_TEST_GT(num_throws, 0u);
170 }
171 check_raii_counts();
172 }
173
174 template <class X, class IL>
175 void intializer_list_assign(std::pair<X*, IL> p)
176 {
177 using allocator_type = typename X::allocator_type;
178
179 auto init_list = p.second;
180
181 {
182 raii::reset_counts();
183 unsigned num_throws = 0;
184
185 for (std::size_t i = 0; i < throw_threshold; ++i) {
186 X x(0, hasher(1), key_equal(2), allocator_type(3));
187 enable_exceptions();
188 try {
189 x = init_list;
190 } catch (...) {
191 ++num_throws;
192 }
193 disable_exceptions();
194 }
195
196 BOOST_TEST_GT(num_throws, 0u);
197 check_raii_counts();
198 }
199 }
200} // namespace
201
202using test::default_generator;
203using test::limited_range;
204using test::sequential;
205
206// clang-format off
207UNORDERED_TEST(
208 copy_assign,
209 ((test_map)(test_set))
210 ((exception_value_type_generator_factory))
211 ((default_generator)(sequential)(limited_range)))
212
213UNORDERED_TEST(
214 move_assign,
215 ((test_map)(test_set))
216 ((exception_value_type_generator_factory))
217 ((default_generator)(sequential)))
218
219UNORDERED_TEST(
220 intializer_list_assign,
221 ((test_map_and_init_list)(test_set_and_init_list)))
222// clang-format on
223
224RUN_TESTS()
225

source code of boost/libs/unordered/test/cfoa/exception_assign_tests.cpp