1 2 // Copyright 2008-2009 Daniel James. 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt) 5 6 // clang-format off 7 #include "../helpers/prefix.hpp" 8 #include <boost/unordered_set.hpp> 9 #include <boost/unordered_map.hpp> 10 #include "../helpers/postfix.hpp" 11 // clang-format on 12 13 #include "../helpers/test.hpp" 14 #include "../objects/test.hpp" 15 #include "../objects/cxx11_allocator.hpp" 16 #include "../helpers/random_values.hpp" 17 #include "../helpers/tracker.hpp" 18 #include "../helpers/equivalent.hpp" 19 #include "../helpers/invariants.hpp" 20 21 #if defined(BOOST_MSVC) 22 #pragma warning(disable : 4127) // conditional expression is constant 23 #endif 24 25 namespace move_tests { 26 test::seed_t initialize_seed(98624); 27 #if defined(BOOST_UNORDERED_USE_MOVE) || \ 28 !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 29 #define BOOST_UNORDERED_TEST_MOVING 1 30 #else 31 #define BOOST_UNORDERED_TEST_MOVING 0 32 #endif 33 empty(T *)34 template <class T> T empty(T*) { return T(); } 35 36 template <class T> create(test::random_values<T> const & v,test::object_count & count)37 T create(test::random_values<T> const& v, test::object_count& count) 38 { 39 T x(v.begin(), v.end()); 40 count = test::global_object_count; 41 return x; 42 } 43 44 template <class T> create(test::random_values<T> const & v,test::object_count & count,typename T::hasher hf,typename T::key_equal eq,typename T::allocator_type al,float mlf)45 T create(test::random_values<T> const& v, test::object_count& count, 46 typename T::hasher hf, typename T::key_equal eq, 47 typename T::allocator_type al, float mlf) 48 { 49 T x(0, hf, eq, al); 50 x.max_load_factor(mlf); 51 x.insert(v.begin(), v.end()); 52 count = test::global_object_count; 53 return x; 54 } 55 56 template <class T> move_construct_tests1(T * ptr,test::random_generator const & generator)57 void move_construct_tests1(T* ptr, test::random_generator const& generator) 58 { 59 typename T::hasher hf; 60 typename T::key_equal eq; 61 typename T::allocator_type al; 62 63 { 64 test::check_instances check_; 65 66 T y(empty(ptr)); 67 BOOST_TEST(y.empty()); 68 BOOST_TEST(test::equivalent(y.hash_function(), hf)); 69 BOOST_TEST(test::equivalent(y.key_eq(), eq)); 70 BOOST_TEST(test::equivalent(y.get_allocator(), al)); 71 BOOST_TEST(y.max_load_factor() == 1.0); 72 test::check_equivalent_keys(y); 73 } 74 75 { 76 test::check_instances check_; 77 78 test::random_values<T> v(1000, generator); 79 test::object_count count; 80 T y(create(v, count)); 81 #if defined(BOOST_HAS_NRVO) 82 BOOST_TEST(count == test::global_object_count); 83 #endif 84 test::check_container(y, v); 85 test::check_equivalent_keys(y); 86 } 87 } 88 89 template <class T> move_assign_tests1(T *,test::random_generator const & generator)90 void move_assign_tests1(T*, test::random_generator const& generator) 91 { 92 { 93 test::check_instances check_; 94 95 test::random_values<T> v(500, generator); 96 test::object_count count; 97 T y; 98 y = create(v, count); 99 #if BOOST_UNORDERED_TEST_MOVING && defined(BOOST_HAS_NRVO) 100 BOOST_TEST(count == test::global_object_count); 101 #endif 102 test::check_container(y, v); 103 test::check_equivalent_keys(y); 104 } 105 } 106 107 template <class T> move_construct_tests2(T *,test::random_generator const & generator)108 void move_construct_tests2(T*, test::random_generator const& generator) 109 { 110 typename T::hasher hf(1); 111 typename T::key_equal eq(1); 112 typename T::allocator_type al(1); 113 typename T::allocator_type al2(2); 114 115 test::object_count count; 116 117 { 118 test::check_instances check_; 119 120 test::random_values<T> v(500, generator); 121 T y(create(v, count, hf, eq, al, 0.5)); 122 #if defined(BOOST_HAS_NRVO) 123 BOOST_TEST(count == test::global_object_count); 124 #endif 125 test::check_container(y, v); 126 BOOST_TEST(test::equivalent(y.hash_function(), hf)); 127 BOOST_TEST(test::equivalent(y.key_eq(), eq)); 128 BOOST_TEST(test::equivalent(y.get_allocator(), al)); 129 BOOST_TEST(y.max_load_factor() == 0.5); // Not necessarily required. 130 test::check_equivalent_keys(y); 131 } 132 133 { 134 test::check_instances check_; 135 136 // TODO: To do this correctly requires the fancy new allocator 137 // stuff. 138 test::random_values<T> v(500, generator); 139 T y(create(v, count, hf, eq, al, 2.0), al2); 140 BOOST_TEST(count != test::global_object_count); 141 test::check_container(y, v); 142 BOOST_TEST(test::equivalent(y.hash_function(), hf)); 143 BOOST_TEST(test::equivalent(y.key_eq(), eq)); 144 BOOST_TEST(test::equivalent(y.get_allocator(), al2)); 145 BOOST_TEST(y.max_load_factor() == 2.0); // Not necessarily required. 146 test::check_equivalent_keys(y); 147 } 148 149 { 150 test::check_instances check_; 151 152 test::random_values<T> v(25, generator); 153 T y(create(v, count, hf, eq, al, 1.0), al); 154 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 155 BOOST_TEST(count == test::global_object_count); 156 #elif defined(BOOST_HAS_NRVO) 157 BOOST_TEST( 158 static_cast<std::size_t>( 159 test::global_object_count.constructions - count.constructions) <= 160 (test::is_set<T>::value ? 1 : 2) * 161 (test::has_unique_keys<T>::value ? 25 : v.size())); 162 BOOST_TEST(count.instances == test::global_object_count.instances); 163 #else 164 BOOST_TEST( 165 static_cast<std::size_t>( 166 test::global_object_count.constructions - count.constructions) <= 167 (test::is_set<T>::value ? 2 : 4) * 168 (test::has_unique_keys<T>::value ? 25 : v.size())); 169 BOOST_TEST(count.instances == test::global_object_count.instances); 170 #endif 171 test::check_container(y, v); 172 BOOST_TEST(test::equivalent(y.hash_function(), hf)); 173 BOOST_TEST(test::equivalent(y.key_eq(), eq)); 174 BOOST_TEST(test::equivalent(y.get_allocator(), al)); 175 BOOST_TEST(y.max_load_factor() == 1.0); // Not necessarily required. 176 test::check_equivalent_keys(y); 177 } 178 } 179 180 template <class T> move_assign_tests2(T *,test::random_generator const & generator)181 void move_assign_tests2(T*, test::random_generator const& generator) 182 { 183 typename T::hasher hf(1); 184 typename T::key_equal eq(1); 185 typename T::allocator_type al1(1); 186 typename T::allocator_type al2(2); 187 typedef typename T::allocator_type allocator_type; 188 189 { 190 test::random_values<T> v(500, generator); 191 test::random_values<T> v2(0, generator); 192 T y(v.begin(), v.end(), 0, hf, eq, al1); 193 test::object_count count; 194 y = create(v2, count, hf, eq, al2, 2.0); 195 BOOST_TEST(y.empty()); 196 test::check_container(y, v2); 197 test::check_equivalent_keys(y); 198 BOOST_TEST(y.max_load_factor() == 2.0); 199 200 #if defined(BOOST_HAS_NRVO) 201 if (BOOST_UNORDERED_TEST_MOVING 202 ? (bool)allocator_type::is_propagate_on_move 203 : (bool)allocator_type::is_propagate_on_assign) { 204 BOOST_TEST(test::equivalent(y.get_allocator(), al2)); 205 } else { 206 BOOST_TEST(test::equivalent(y.get_allocator(), al1)); 207 } 208 #endif 209 } 210 211 { 212 test::random_values<T> v(500, generator); 213 test::object_count count; 214 T y(0, hf, eq, al1); 215 y = create(v, count, hf, eq, al2, 0.5); 216 #if defined(BOOST_HAS_NRVO) 217 if (BOOST_UNORDERED_TEST_MOVING && allocator_type::is_propagate_on_move) { 218 BOOST_TEST(count == test::global_object_count); 219 } 220 #endif 221 test::check_container(y, v); 222 test::check_equivalent_keys(y); 223 BOOST_TEST(y.max_load_factor() == 0.5); 224 225 #if defined(BOOST_HAS_NRVO) 226 if (BOOST_UNORDERED_TEST_MOVING 227 ? (bool)allocator_type::is_propagate_on_move 228 : (bool)allocator_type::is_propagate_on_assign) { 229 BOOST_TEST(test::equivalent(y.get_allocator(), al2)); 230 } else { 231 BOOST_TEST(test::equivalent(y.get_allocator(), al1)); 232 } 233 #endif 234 } 235 236 { 237 test::check_instances check_; 238 239 test::random_values<T> v(500, generator); 240 T y(0, hf, eq, al1); 241 242 T x(0, hf, eq, al2); 243 x.max_load_factor(0.25); 244 x.insert(v.begin(), v.end()); 245 246 test::object_count count = test::global_object_count; 247 y = boost::move(x); 248 if (BOOST_UNORDERED_TEST_MOVING && allocator_type::is_propagate_on_move) { 249 BOOST_TEST(count == test::global_object_count); 250 } 251 test::check_container(y, v); 252 test::check_equivalent_keys(y); 253 BOOST_TEST(y.max_load_factor() == 0.25); 254 255 if (BOOST_UNORDERED_TEST_MOVING 256 ? (bool)allocator_type::is_propagate_on_move 257 : (bool)allocator_type::is_propagate_on_assign) { 258 BOOST_TEST(test::equivalent(y.get_allocator(), al2)); 259 } else { 260 BOOST_TEST(test::equivalent(y.get_allocator(), al1)); 261 } 262 } 263 264 { 265 test::check_instances check_; 266 267 test::random_values<T> v1(1000, generator); 268 test::random_values<T> v2(200, generator); 269 270 T x(0, hf, eq, al2); 271 x.max_load_factor(0.5); 272 x.insert(v2.begin(), v2.end()); 273 274 test::object_count count1 = test::global_object_count; 275 276 T y(v1.begin(), v1.end(), 0, hf, eq, al1); 277 y = boost::move(x); 278 279 test::object_count count2 = test::global_object_count; 280 281 if (BOOST_UNORDERED_TEST_MOVING && allocator_type::is_propagate_on_move) { 282 BOOST_TEST(count1.instances == test::global_object_count.instances); 283 BOOST_TEST( 284 count2.constructions == test::global_object_count.constructions); 285 } 286 287 test::check_container(y, v2); 288 test::check_equivalent_keys(y); 289 BOOST_TEST(y.max_load_factor() == 0.5); 290 291 if (BOOST_UNORDERED_TEST_MOVING 292 ? (bool)allocator_type::is_propagate_on_move 293 : (bool)allocator_type::is_propagate_on_assign) { 294 BOOST_TEST(test::equivalent(y.get_allocator(), al2)); 295 } else { 296 BOOST_TEST(test::equivalent(y.get_allocator(), al1)); 297 } 298 } 299 } 300 301 boost::unordered_map<test::object, test::object, test::hash, test::equal_to, 302 std::allocator<test::object> >* test_map_std_alloc; 303 304 boost::unordered_set<test::object, test::hash, test::equal_to, 305 test::allocator2<test::object> >* test_set; 306 boost::unordered_multiset<test::object, test::hash, test::equal_to, 307 test::allocator1<test::object> >* test_multiset; 308 boost::unordered_map<test::object, test::object, test::hash, test::equal_to, 309 test::allocator1<test::object> >* test_map; 310 boost::unordered_multimap<test::object, test::object, test::hash, 311 test::equal_to, test::allocator2<test::object> >* test_multimap; 312 313 boost::unordered_set<test::object, test::hash, test::equal_to, 314 test::cxx11_allocator<test::object, test::propagate_move> >* 315 test_set_prop_move; 316 boost::unordered_multiset<test::object, test::hash, test::equal_to, 317 test::cxx11_allocator<test::object, test::propagate_move> >* 318 test_multiset_prop_move; 319 boost::unordered_map<test::object, test::object, test::hash, test::equal_to, 320 test::cxx11_allocator<test::object, test::propagate_move> >* 321 test_map_prop_move; 322 boost::unordered_multimap<test::object, test::object, test::hash, 323 test::equal_to, test::cxx11_allocator<test::object, test::propagate_move> >* 324 test_multimap_prop_move; 325 326 boost::unordered_set<test::object, test::hash, test::equal_to, 327 test::cxx11_allocator<test::object, test::no_propagate_move> >* 328 test_set_no_prop_move; 329 boost::unordered_multiset<test::object, test::hash, test::equal_to, 330 test::cxx11_allocator<test::object, test::no_propagate_move> >* 331 test_multiset_no_prop_move; 332 boost::unordered_map<test::object, test::object, test::hash, test::equal_to, 333 test::cxx11_allocator<test::object, test::no_propagate_move> >* 334 test_map_no_prop_move; 335 boost::unordered_multimap<test::object, test::object, test::hash, 336 test::equal_to, 337 test::cxx11_allocator<test::object, test::no_propagate_move> >* 338 test_multimap_no_prop_move; 339 340 using test::default_generator; 341 using test::generate_collisions; 342 using test::limited_range; 343 344 UNORDERED_TEST(move_construct_tests1, 345 ((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)( 346 test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)( 347 test_multimap_prop_move)(test_set_no_prop_move)( 348 test_multiset_no_prop_move)(test_map_no_prop_move)( 349 test_multimap_no_prop_move))( 350 (default_generator)(generate_collisions)(limited_range))) 351 UNORDERED_TEST(move_assign_tests1, 352 ((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)( 353 test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)( 354 test_multimap_prop_move)(test_set_no_prop_move)( 355 test_multiset_no_prop_move)(test_map_no_prop_move)( 356 test_multimap_no_prop_move))( 357 (default_generator)(generate_collisions)(limited_range))) 358 UNORDERED_TEST(move_construct_tests2, 359 ((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_move)( 360 test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)( 361 test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)( 362 test_multimap_no_prop_move))( 363 (default_generator)(generate_collisions)(limited_range))) 364 UNORDERED_TEST(move_assign_tests2, 365 ((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_move)( 366 test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)( 367 test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)( 368 test_multimap_no_prop_move))( 369 (default_generator)(generate_collisions)(limited_range))) 370 } 371 372 RUN_TESTS() 373