1
2// Copyright 2006-2009 Daniel James.
3// Copyright 2022-2023 Christian Mazakas.
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7#include "../helpers/unordered.hpp"
8
9#include "../helpers/test.hpp"
10#include "../objects/test.hpp"
11#include "../objects/cxx11_allocator.hpp"
12#include "../helpers/random_values.hpp"
13#include "../helpers/tracker.hpp"
14#include "../helpers/equivalent.hpp"
15
16#if defined(BOOST_MSVC)
17#pragma warning(disable : 4127) // conditional expression is constant
18#endif
19
20#if defined(__clang__) && defined(__has_warning)
21#if __has_warning("-Wself-assign-overloaded")
22#pragma clang diagnostic ignored "-Wself-assign-overloaded"
23#endif
24#endif
25
26namespace assign_tests {
27
28 test::seed_t initialize_seed(96785);
29
30 template <class T> void assign_tests1(T*, test::random_generator generator)
31 {
32 typename T::hasher hf;
33 typename T::key_equal eq;
34
35 BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.1\n";
36 {
37 test::check_instances check_;
38
39 T x;
40 x = x;
41 BOOST_TEST(x.empty());
42 BOOST_TEST(test::equivalent(x.hash_function(), hf));
43 BOOST_TEST(test::equivalent(x.key_eq(), eq));
44 }
45
46 BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.2\n";
47 {
48 test::check_instances check_;
49
50 test::random_values<T> v(1000, generator);
51 T x(v.begin(), v.end());
52
53 test::ordered<T> tracker = test::create_ordered(x);
54 tracker.insert_range(v.begin(), v.end());
55
56 x = x;
57 tracker.compare(x);
58
59 T y;
60 y.max_load_factor(x.max_load_factor() / 20);
61 float mlf = x.max_load_factor();
62 y = x;
63 tracker.compare(x);
64 tracker.compare(y);
65 BOOST_TEST(x.max_load_factor() == mlf);
66 BOOST_TEST(y.max_load_factor() == mlf);
67 BOOST_TEST(y.load_factor() <= y.max_load_factor());
68 }
69 }
70
71 template <class T> void assign_tests2(T*, test::random_generator generator)
72 {
73 typename T::hasher hf1(1);
74 typename T::hasher hf2(2);
75 typename T::key_equal eq1(1);
76 typename T::key_equal eq2(2);
77 typename T::allocator_type al1(1);
78 typename T::allocator_type al2(2);
79
80 typedef typename T::allocator_type allocator_type;
81
82 BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.0 - empty container\n";
83 {
84 test::check_instances check_;
85
86 T x1(0, hf1, eq1);
87 T x2(0, hf2, eq2);
88 x2 = x1;
89 BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
90 BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
91 BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
92 BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
93 test::check_container(x1, x2);
94 }
95
96 BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1\n";
97 {
98 test::check_instances check_;
99
100 test::random_values<T> v(1000, generator);
101 T x1(v.begin(), v.end(), 0, hf1, eq1);
102 T x2(0, hf2, eq2);
103 x2 = x1;
104 BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
105 BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
106 BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
107 BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
108 test::check_container(x1, v);
109 test::check_container(x2, v);
110 BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
111 }
112
113 BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1a\n";
114 {
115 test::check_instances check_;
116
117 test::random_values<T> v1(0, generator);
118 test::random_values<T> v2(1000, generator);
119 T x1(0, hf2, eq2);
120 T x2(v2.begin(), v2.end(), 0, hf1, eq1);
121 x2 = x1;
122 BOOST_TEST(test::equivalent(x1.hash_function(), hf2));
123 BOOST_TEST(test::equivalent(x1.key_eq(), eq2));
124 BOOST_TEST(test::equivalent(x2.hash_function(), hf2));
125 BOOST_TEST(test::equivalent(x2.key_eq(), eq2));
126 test::check_container(x1, v1);
127 test::check_container(x2, v1);
128 BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
129 }
130
131 BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.2\n";
132 {
133 test::check_instances check_;
134
135 test::random_values<T> v1(100, generator), v2(100, generator);
136 T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
137 T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
138 x2 = x1;
139 BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
140 BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
141 if (allocator_type::is_propagate_on_assign) {
142 BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
143 BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
144 } else {
145 BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
146 BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
147 }
148 test::check_container(x1, v1);
149 test::check_container(x2, v1);
150 BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
151 }
152
153 BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.3\n";
154 {
155 test::check_instances check_;
156
157 test::random_values<T> v1(100, generator), v2(1000, generator);
158 T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
159 T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
160 x2 = x1;
161 BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
162 BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
163 if (allocator_type::is_propagate_on_assign) {
164 BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
165 BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
166 } else {
167 BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
168 BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
169 }
170 test::check_container(x1, v1);
171 test::check_container(x2, v1);
172 BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
173 }
174
175 BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.4\n";
176 {
177 test::check_instances check_;
178
179 test::random_values<T> v1(1000, generator), v2(100, generator);
180 T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
181 T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
182 x2 = x1;
183 BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
184 BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
185 if (allocator_type::is_propagate_on_assign) {
186 BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
187 BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
188 } else {
189 BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
190 BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
191 }
192 test::check_container(x1, v1);
193 test::check_container(x2, v1);
194 BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
195 }
196
197 BOOST_LIGHTWEIGHT_TEST_OSTREAM << "gh205\n";
198 {
199 // https://github.com/boostorg/unordered/issues/205
200 {
201 // A=B
202 // assign no-allocated to empty-but-allocated
203 test::check_instances check_;
204
205 test::random_values<T> v1(1, generator);
206 T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
207 T x2(0, hf2, eq2, al2);
208 x1.clear();
209 x1 = x2;
210 BOOST_TEST(x1.empty());
211 BOOST_TEST(x1.begin() == x1.end());
212 BOOST_TEST(x2.empty());
213 BOOST_TEST(x2.begin() == x2.end());
214 }
215
216 {
217 // B=A
218 // assign empty-but-allocated to no-allocated
219 test::check_instances check_;
220
221 test::random_values<T> v1(1, generator);
222 T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
223 T x2(0, hf2, eq2, al2);
224 x1.clear();
225 x2 = x1;
226 BOOST_TEST(x2.empty());
227 BOOST_TEST(x2.begin() == x2.end());
228 BOOST_TEST(x1.empty());
229 BOOST_TEST(x1.begin() == x1.end());
230 }
231
232 {
233 // A=A
234 // assign empty-but-allocated to empty-but-allocated
235 test::check_instances check_;
236
237 test::random_values<T> v1(1, generator);
238 test::random_values<T> v2(1, generator);
239 T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
240 T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
241 x1.clear();
242 x2.clear();
243 x1 = x2;
244 BOOST_TEST(x1.empty());
245 BOOST_TEST(x1.begin() == x1.end());
246 BOOST_TEST(x2.empty());
247 BOOST_TEST(x2.begin() == x2.end());
248 }
249
250 {
251 // B=B
252 // assign no-allocated to no-allocated
253 test::check_instances check_;
254
255 T x1(0, hf1, eq1, al1);
256 T x2(0, hf2, eq2, al2);
257 x1 = x2;
258 BOOST_TEST(x2.empty());
259 BOOST_TEST(x2.begin() == x2.end());
260 BOOST_TEST(x1.empty());
261 BOOST_TEST(x1.begin() == x1.end());
262 }
263
264#ifdef BOOST_UNORDERED_FOA_TESTS
265 {
266 // check that optimized copying preserves the anti-drift mechanism
267 test::check_instances check_;
268
269 test::random_values<T> v1(2000, generator);
270 test::random_values<T> v2(2000, generator);
271 T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
272 T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
273
274 auto ml = x1.max_load();
275
276 while (ml == x1.max_load() && x1.size()) {
277 x1.erase(x1.begin());
278 };
279
280 BOOST_TEST_EQ(x1.bucket_count(), x2.bucket_count());
281
282 x2 = x1;
283
284 if (x1.max_load() != x2.max_load()) {
285 BOOST_TEST(boost::allocator_propagate_on_container_copy_assignment<
286 typename T::allocator_type>::type::value);
287 }
288 }
289#endif
290 }
291 }
292
293 using test::default_generator;
294 using test::generate_collisions;
295 using test::limited_range;
296
297 template <typename T> bool is_propagate(T*)
298 {
299 return T::allocator_type::is_propagate_on_assign;
300 }
301
302#ifdef BOOST_UNORDERED_FOA_TESTS
303 boost::unordered_flat_map<test::object, test::object, test::hash,
304 test::equal_to, std::allocator<test::object> >* test_map_std_alloc;
305 boost::unordered_node_map<test::object, test::object, test::hash,
306 test::equal_to, std::allocator<test::object> >* test_node_map_std_alloc;
307
308 boost::unordered_flat_set<test::object, test::hash, test::equal_to,
309 test::allocator1<test::object> >* test_set;
310 boost::unordered_node_set<test::object, test::hash, test::equal_to,
311 test::allocator1<test::object> >* test_node_set;
312 boost::unordered_flat_map<test::object, test::object, test::hash,
313 test::equal_to, test::allocator2<test::object> >* test_map;
314 boost::unordered_node_map<test::object, test::object, test::hash,
315 test::equal_to, test::allocator2<test::object> >* test_node_map;
316
317 boost::unordered_flat_set<test::object, test::hash, test::equal_to,
318 test::cxx11_allocator<test::object, test::propagate_assign> >*
319 test_set_prop_assign;
320 boost::unordered_node_set<test::object, test::hash, test::equal_to,
321 test::cxx11_allocator<test::object, test::propagate_assign> >*
322 test_node_set_prop_assign;
323 boost::unordered_flat_map<test::object, test::object, test::hash,
324 test::equal_to,
325 test::cxx11_allocator<test::object, test::propagate_assign> >*
326 test_map_prop_assign;
327 boost::unordered_node_map<test::object, test::object, test::hash,
328 test::equal_to,
329 test::cxx11_allocator<test::object, test::propagate_assign> >*
330 test_node_map_prop_assign;
331
332 boost::unordered_flat_set<test::object, test::hash, test::equal_to,
333 test::cxx11_allocator<test::object, test::no_propagate_assign> >*
334 test_set_no_prop_assign;
335 boost::unordered_node_set<test::object, test::hash, test::equal_to,
336 test::cxx11_allocator<test::object, test::no_propagate_assign> >*
337 test_node_set_no_prop_assign;
338 boost::unordered_flat_map<test::object, test::object, test::hash,
339 test::equal_to,
340 test::cxx11_allocator<test::object, test::no_propagate_assign> >*
341 test_map_no_prop_assign;
342 boost::unordered_node_map<test::object, test::object, test::hash,
343 test::equal_to,
344 test::cxx11_allocator<test::object, test::no_propagate_assign> >*
345 test_node_map_no_prop_assign;
346
347 UNORDERED_AUTO_TEST (check_traits) {
348 BOOST_TEST(!is_propagate(test_set));
349 BOOST_TEST(is_propagate(test_set_prop_assign));
350 BOOST_TEST(!is_propagate(test_set_no_prop_assign));
351
352 BOOST_TEST(!is_propagate(test_node_set));
353 BOOST_TEST(is_propagate(test_node_set_prop_assign));
354 BOOST_TEST(!is_propagate(test_node_set_no_prop_assign));
355 }
356
357 UNORDERED_TEST(assign_tests1,
358 ((test_map_std_alloc)(test_node_map_std_alloc)
359 (test_set)(test_node_set)
360 (test_map)(test_node_map)
361 (test_set_prop_assign)(test_node_set_prop_assign)
362 (test_map_prop_assign)(test_node_map_prop_assign)
363 (test_set_no_prop_assign)(test_node_set_no_prop_assign)
364 (test_map_no_prop_assign)(test_node_map_no_prop_assign))(
365 (default_generator)(generate_collisions)(limited_range)))
366
367 UNORDERED_TEST(assign_tests2,
368 ((test_set)(test_node_set)
369 (test_map)(test_node_map)
370 (test_set_prop_assign)(test_node_set_prop_assign)
371 (test_map_prop_assign)(test_node_map_prop_assign)
372 (test_set_no_prop_assign)(test_node_set_no_prop_assign)
373 (test_map_no_prop_assign)(test_node_map_no_prop_assign))(
374 (default_generator)(generate_collisions)(limited_range)))
375#else
376 boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
377 std::allocator<test::object> >* test_map_std_alloc;
378
379 boost::unordered_set<test::object, test::hash, test::equal_to,
380 test::allocator1<test::object> >* test_set;
381 boost::unordered_multiset<test::object, test::hash, test::equal_to,
382 test::allocator2<test::object> >* test_multiset;
383 boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
384 test::allocator2<test::object> >* test_map;
385 boost::unordered_multimap<test::object, test::object, test::hash,
386 test::equal_to, test::allocator1<test::object> >* test_multimap;
387
388 boost::unordered_set<test::object, test::hash, test::equal_to,
389 test::cxx11_allocator<test::object, test::propagate_assign> >*
390 test_set_prop_assign;
391 boost::unordered_multiset<test::object, test::hash, test::equal_to,
392 test::cxx11_allocator<test::object, test::propagate_assign> >*
393 test_multiset_prop_assign;
394 boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
395 test::cxx11_allocator<test::object, test::propagate_assign> >*
396 test_map_prop_assign;
397 boost::unordered_multimap<test::object, test::object, test::hash,
398 test::equal_to,
399 test::cxx11_allocator<test::object, test::propagate_assign> >*
400 test_multimap_prop_assign;
401
402 boost::unordered_set<test::object, test::hash, test::equal_to,
403 test::cxx11_allocator<test::object, test::no_propagate_assign> >*
404 test_set_no_prop_assign;
405 boost::unordered_multiset<test::object, test::hash, test::equal_to,
406 test::cxx11_allocator<test::object, test::no_propagate_assign> >*
407 test_multiset_no_prop_assign;
408 boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
409 test::cxx11_allocator<test::object, test::no_propagate_assign> >*
410 test_map_no_prop_assign;
411 boost::unordered_multimap<test::object, test::object, test::hash,
412 test::equal_to,
413 test::cxx11_allocator<test::object, test::no_propagate_assign> >*
414 test_multimap_no_prop_assign;
415
416 UNORDERED_AUTO_TEST (check_traits) {
417 BOOST_TEST(!is_propagate(test_set));
418 BOOST_TEST(is_propagate(test_set_prop_assign));
419 BOOST_TEST(!is_propagate(test_set_no_prop_assign));
420 }
421
422 UNORDERED_TEST(assign_tests1,
423 ((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
424 test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(
425 test_multimap_prop_assign)(test_set_no_prop_assign)(
426 test_multiset_no_prop_assign)(test_map_no_prop_assign)(
427 test_multimap_no_prop_assign))(
428 (default_generator)(generate_collisions)(limited_range)))
429
430 UNORDERED_TEST(
431 assign_tests2, ((test_set)(test_multiset)(test_map)(test_multimap)(
432 test_set_prop_assign)(test_multiset_prop_assign)(
433 test_map_prop_assign)(test_multimap_prop_assign)(
434 test_set_no_prop_assign)(test_multiset_no_prop_assign)(
435 test_map_no_prop_assign)(test_multimap_no_prop_assign))(
436 (default_generator)(generate_collisions)(limited_range)))
437#endif
438
439 UNORDERED_AUTO_TEST (assign_default_initializer_list) {
440 BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
441 std::initializer_list<std::pair<int const, int> > init;
442#ifdef BOOST_UNORDERED_FOA_TESTS
443 boost::unordered_flat_map<int, int> x1;
444 boost::unordered_node_map<int, int> x2;
445 x2[25] = 3;
446 x2[16] = 10;
447 BOOST_TEST(!x2.empty());
448 x2 = init;
449 BOOST_TEST(x2.empty());
450#else
451 boost::unordered_map<int, int> x1;
452#endif
453 x1[25] = 3;
454 x1[16] = 10;
455 BOOST_TEST(!x1.empty());
456 x1 = init;
457 BOOST_TEST(x1.empty());
458 }
459
460 UNORDERED_AUTO_TEST (assign_initializer_list) {
461 BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
462
463#ifdef BOOST_UNORDERED_FOA_TESTS
464 boost::unordered_flat_set<int> x;
465 boost::unordered_node_set<int> y;
466 y.insert(10);
467 y.insert(20);
468 y = {1, 2, -10};
469 BOOST_TEST(y.find(10) == y.end());
470 BOOST_TEST(y.find(-10) != y.end());
471#else
472 boost::unordered_set<int> x;
473#endif
474 x.insert(x: 10);
475 x.insert(x: 20);
476 x = {1, 2, -10};
477 BOOST_TEST(x.find(10) == x.end());
478 BOOST_TEST(x.find(-10) != x.end());
479 }
480}
481
482RUN_TESTS()
483

source code of boost/libs/unordered/test/unordered/assign_tests.cpp