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(795610904);
78
79 template <class X>
80 void bucket_constructor(X*)
81 {
82 raii::reset_counts();
83
84 bool was_thrown = false;
85
86 enable_exceptions();
87 for (std::size_t i = 0; i < alloc_throw_threshold; ++i) {
88 try {
89 X m(128);
90 } catch (...) {
91 was_thrown = true;
92 }
93 }
94 disable_exceptions();
95
96 BOOST_TEST(was_thrown);
97 }
98
99 template <class X, class GF>
100 void iterator_range(X*, GF gen_factory, test::random_generator rg)
101 {
102 using allocator_type = typename X::allocator_type;
103
104 auto gen = gen_factory.template get<X>();
105 auto values = make_random_values(1024 * 16, [&] { return gen(rg); });
106
107 {
108 raii::reset_counts();
109
110 bool was_thrown = false;
111
112 enable_exceptions();
113 try {
114 X x(values.begin(), values.end(), 0, hasher(1), key_equal(2),
115 allocator_type(3));
116 } catch (...) {
117 was_thrown = true;
118 }
119 disable_exceptions();
120
121 BOOST_TEST(was_thrown);
122 check_raii_counts();
123 }
124
125 {
126 raii::reset_counts();
127
128 bool was_thrown = false;
129
130 enable_exceptions();
131 try {
132 X x(values.begin(), values.end(), allocator_type(3));
133 } catch (...) {
134 was_thrown = true;
135 }
136 disable_exceptions();
137
138 BOOST_TEST(was_thrown);
139 check_raii_counts();
140 }
141
142 {
143 raii::reset_counts();
144
145 bool was_thrown = false;
146
147 enable_exceptions();
148 try {
149 X x(
150 values.begin(), values.end(), values.size(), allocator_type(3));
151 } catch (...) {
152 was_thrown = true;
153 }
154 disable_exceptions();
155
156 BOOST_TEST(was_thrown);
157 check_raii_counts();
158 }
159
160 {
161 raii::reset_counts();
162
163 bool was_thrown = false;
164
165 enable_exceptions();
166 try {
167 X x(values.begin(), values.end(), values.size(), hasher(1),
168 allocator_type(3));
169 } catch (...) {
170 was_thrown = true;
171 }
172 disable_exceptions();
173
174 BOOST_TEST(was_thrown);
175 check_raii_counts();
176 }
177 }
178
179 template <class X, class GF>
180 void copy_constructor(X*, GF gen_factory, test::random_generator rg)
181 {
182 using allocator_type = typename X::allocator_type;
183
184 auto gen = gen_factory.template get<X>();
185 auto values = make_random_values(1024 * 16, [&] { return gen(rg); });
186
187 {
188 raii::reset_counts();
189
190 bool was_thrown = false;
191
192 try {
193 X x(values.begin(), values.end(), 0);
194
195 enable_exceptions();
196 X y(x);
197 } catch (...) {
198 was_thrown = true;
199 }
200 disable_exceptions();
201
202 BOOST_TEST(was_thrown);
203 check_raii_counts();
204 }
205
206 {
207 raii::reset_counts();
208
209 bool was_thrown = false;
210
211 try {
212 X x(values.begin(), values.end(), 0);
213
214 enable_exceptions();
215 X y(x, allocator_type(4));
216 } catch (...) {
217 was_thrown = true;
218 }
219 disable_exceptions();
220
221 BOOST_TEST(was_thrown);
222 check_raii_counts();
223 }
224 }
225
226 template <class X, class GF>
227 void move_constructor(X*, GF gen_factory, test::random_generator rg)
228 {
229 using allocator_type = typename X::allocator_type;
230
231 auto gen = gen_factory.template get<X>();
232 auto values = make_random_values(1024 * 16, [&] { return gen(rg); });
233
234 {
235 raii::reset_counts();
236
237 bool was_thrown = false;
238
239 try {
240 X x(values.begin(), values.end(), 0);
241
242 enable_exceptions();
243 X y(std::move(x), allocator_type(4));
244 } catch (...) {
245 was_thrown = true;
246 }
247 disable_exceptions();
248
249 BOOST_TEST(was_thrown);
250 check_raii_counts();
251 }
252 }
253
254 template <class X, class IL>
255 void initializer_list_bucket_count(std::pair<X*, IL> p)
256 {
257 using allocator_type = typename X::allocator_type;
258
259 auto init_list = p.second;
260
261 {
262 raii::reset_counts();
263 unsigned num_throws = 0;
264
265 enable_exceptions();
266 for (std::size_t i = 0; i < throw_threshold; ++i) {
267 try {
268 X x(init_list, 0, hasher(1), key_equal(2), allocator_type(3));
269 } catch (...) {
270 ++num_throws;
271 }
272 }
273 disable_exceptions();
274
275 BOOST_TEST_GT(num_throws, 0u);
276 check_raii_counts();
277 }
278
279 {
280 raii::reset_counts();
281 unsigned num_throws = 0;
282
283 enable_exceptions();
284 for (std::size_t i = 0; i < alloc_throw_threshold * 2; ++i) {
285 try {
286 X x(init_list, allocator_type(3));
287 } catch (...) {
288 ++num_throws;
289 }
290 }
291 disable_exceptions();
292
293 BOOST_TEST_GT(num_throws, 0u);
294 check_raii_counts();
295 }
296
297 {
298 raii::reset_counts();
299 unsigned num_throws = 0;
300
301 enable_exceptions();
302 for (std::size_t i = 0; i < alloc_throw_threshold * 2; ++i) {
303 try {
304 X x(init_list, init_list.size() * 2, allocator_type(3));
305 } catch (...) {
306 ++num_throws;
307 }
308 }
309 disable_exceptions();
310
311 BOOST_TEST_GT(num_throws, 0u);
312 check_raii_counts();
313 }
314
315 {
316 raii::reset_counts();
317 unsigned num_throws = 0;
318
319 enable_exceptions();
320 for (std::size_t i = 0; i < throw_threshold; ++i) {
321 try {
322 X x(init_list, init_list.size() * 2, hasher(1), allocator_type(3));
323 } catch (...) {
324 ++num_throws;
325 }
326 }
327 disable_exceptions();
328
329 BOOST_TEST_GT(num_throws, 0u);
330 check_raii_counts();
331 }
332 }
333} // namespace
334
335using test::default_generator;
336using test::limited_range;
337using test::sequential;
338
339// clang-format off
340UNORDERED_TEST(
341 bucket_constructor,
342 ((test_map)(test_set)))
343
344UNORDERED_TEST(
345 iterator_range,
346 ((test_map)(test_set))
347 ((exception_value_type_generator_factory))
348 ((default_generator)(sequential)(limited_range)))
349
350UNORDERED_TEST(
351 copy_constructor,
352 ((test_map)(test_set))
353 ((exception_value_type_generator_factory))
354 ((default_generator)(sequential)))
355
356UNORDERED_TEST(
357 move_constructor,
358 ((test_map)(test_set))
359 ((exception_value_type_generator_factory))
360 ((default_generator)(sequential)))
361
362UNORDERED_TEST(
363 initializer_list_bucket_count,
364 ((test_map_and_init_list)(test_set_and_init_list)))
365// clang-format on
366
367RUN_TESTS()
368

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