1 /* 2 Copyright (c) 2005-2021 Intel Corporation 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 #if __INTEL_COMPILER && _MSC_VER 18 #pragma warning(disable : 2586) // decorated name length exceeded, name was truncated 19 #endif 20 21 #include "oneapi/tbb/concurrent_unordered_map.h" 22 #include <common/test.h> 23 #include <common/utils.h> 24 #include <common/concurrent_unordered_common.h> 25 #include <memory> 26 #include <type_traits> 27 28 //! \file conformance_concurrent_unordered_map.cpp 29 //! \brief Test for [containers.concurrent_unordered_map containers.concurrent_unordered_multimap] specifications 30 31 template <typename... Args> 32 struct AllowMultimapping<oneapi::tbb::concurrent_unordered_multimap<Args...>> : std::true_type {}; 33 34 template <typename Key, typename Mapped> 35 using Allocator = LocalCountingAllocator<std::allocator<std::pair<const Key, Mapped>>>; 36 37 using map_type = oneapi::tbb::concurrent_unordered_map<int, int, std::hash<int>, std::equal_to<int>, Allocator<int, int>>; 38 using multimap_type = oneapi::tbb::concurrent_unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, Allocator<int, int>>; 39 40 template <> 41 struct SpecialTests<map_type> { 42 static void Test() { 43 SpecialMapTests<map_type>(); 44 } 45 }; 46 47 template <> 48 struct SpecialTests<multimap_type> { 49 static void Test() { 50 SpecialMultiMapTests<multimap_type>(); 51 } 52 }; 53 54 template <template <typename... > class ContainerType> 55 void test_member_types() { 56 using default_container_type = ContainerType<int, int>; 57 static_assert(std::is_same<typename default_container_type::hasher, std::hash<int>>::value, 58 "Incorrect default template hasher"); 59 static_assert(std::is_same<typename default_container_type::key_equal, std::equal_to<int>>::value, 60 "Incorrect default template key equality"); 61 static_assert(std::is_same<typename default_container_type::allocator_type, 62 oneapi::tbb::tbb_allocator<std::pair<const int, int>>>::value, 63 "Incorrect default template allocator"); 64 65 auto test_hasher = [](const int&)->std::size_t { return 0; }; 66 auto test_equality = [](const int&, const int&)->bool { return true; }; 67 using test_allocator_type = std::allocator<std::pair<const int, int>>; 68 69 using container_type = ContainerType<int, int, decltype(test_hasher), 70 decltype(test_equality), test_allocator_type>; 71 72 static_assert(std::is_same<typename container_type::key_type, int>::value, 73 "Incorrect container key_type member type"); 74 static_assert(std::is_same<typename container_type::mapped_type, int>::value, 75 "Incorrect container mapped_type member type"); 76 static_assert(std::is_same<typename container_type::value_type, std::pair<const int, int>>::value, 77 "Incorrect container value_type member type"); 78 79 static_assert(std::is_unsigned<typename container_type::size_type>::value, 80 "Incorrect container size_type member type"); 81 static_assert(std::is_signed<typename container_type::difference_type>::value, 82 "Incorrect container difference_type member type"); 83 84 static_assert(std::is_same<typename container_type::hasher, decltype(test_hasher)>::value, 85 "Incorrect container hasher member type"); 86 static_assert(std::is_same<typename container_type::key_equal, decltype(test_equality)>::value, 87 "Incorrect container key_equal member type"); 88 89 using transparent_container_type = ContainerType<int, int, hasher_with_transparent_key_equal, 90 std::equal_to<int>, test_allocator_type>; 91 92 static_assert(std::is_same<typename transparent_container_type::key_equal, transparent_key_equality>::value, 93 "Incorrect container key_equal member type"); 94 static_assert(std::is_same<typename container_type::allocator_type, test_allocator_type>::value, 95 "Incorrect container allocator_type member type"); 96 97 using value_type = typename container_type::value_type; 98 static_assert(std::is_same<typename container_type::reference, value_type&>::value, 99 "Incorrect container reference member type"); 100 static_assert(std::is_same<typename container_type::const_reference, const value_type&>::value, 101 "Incorrect container const_reference member type"); 102 using allocator_type = typename container_type::allocator_type; 103 static_assert(std::is_same<typename container_type::pointer, typename std::allocator_traits<allocator_type>::pointer>::value, 104 "Incorrect container pointer member type"); 105 static_assert(std::is_same<typename container_type::const_pointer, typename std::allocator_traits<allocator_type>::const_pointer>::value, 106 "Incorrect container const_pointer member type"); 107 108 static_assert(utils::is_forward_iterator<typename container_type::iterator>::value, 109 "Incorrect container iterator member type"); 110 static_assert(!std::is_const<typename container_type::iterator::value_type>::value, 111 "Incorrect container iterator member type"); 112 static_assert(utils::is_forward_iterator<typename container_type::const_iterator>::value, 113 "Incorrect container const_iterator member type"); 114 static_assert(std::is_const<typename container_type::const_iterator::value_type>::value, 115 "Incorrect container iterator member type"); 116 static_assert(utils::is_forward_iterator<typename container_type::local_iterator>::value, 117 "Incorrect container local_iterator member type"); 118 static_assert(!std::is_const<typename container_type::local_iterator::value_type>::value, 119 "Incorrect container local_iterator member type"); 120 static_assert(utils::is_forward_iterator<typename container_type::const_local_iterator>::value, 121 "Incorrect container const_local_iterator member type"); 122 static_assert(std::is_const<typename container_type::const_local_iterator::value_type>::value, 123 "Incorrect container const_local_iterator member type"); 124 } 125 126 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 127 template <template <typename...> typename TMap> 128 void test_deduction_guides() { 129 using ComplexType = std::pair<int, std::string>; 130 using ComplexTypeConst = std::pair<const int, std::string>; 131 std::vector<ComplexType> v; 132 auto l = { ComplexTypeConst(1, "one"), ComplexTypeConst(2, "two")}; 133 using custom_allocator_type = std::allocator<ComplexTypeConst>; 134 135 // check TMap(InputIterator, InputIterator) 136 TMap m0(v.begin(), v.end()); 137 static_assert(std::is_same<decltype(m0), TMap<int, std::string>>::value); 138 139 // check TMap(InputIterator, InputIterator, size_t) 140 TMap m1(v.begin(), v.end(), 1); 141 static_assert(std::is_same<decltype(m1), TMap<int, std::string>>::value); 142 143 // check TMap(InputIterator, InputIterator, size_t, Hasher) 144 TMap m2(v.begin(), v.end(), 4, degenerate_hash<int>()); 145 static_assert(std::is_same<decltype(m2), TMap<int, std::string, degenerate_hash<int>>>::value); 146 147 // check TMap(InputIterator, InputIterator, size_t, Hasher, Equality) 148 TMap m3(v.begin(), v.end(), 4, degenerate_hash<int>(), std::less<int>()); 149 static_assert(std::is_same<decltype(m3), TMap<int, std::string, degenerate_hash<int>, std::less<int>>>::value); 150 151 // check TMap(InputIterator, InputIterator, size_t, Hasher, Equality, Allocator) 152 TMap m4(v.begin(), v.end(), 4, degenerate_hash<int>(), std::less<int>(), custom_allocator_type{}); 153 static_assert(std::is_same<decltype(m4), TMap<int, std::string, degenerate_hash<int>, 154 std::less<int>, custom_allocator_type>>::value); 155 156 // check TMap(InputIterator, InputIterator, size_t, Allocator) 157 TMap m5(v.begin(), v.end(), 5, custom_allocator_type{}); 158 static_assert(std::is_same<decltype(m5), TMap<int, std::string, std::hash<int>, 159 std::equal_to<int>, custom_allocator_type>>::value); 160 161 // check TMap(InputIterator, InputIterator, size_t, Hasher, Allocator) 162 TMap m6(v.begin(), v.end(), 4, degenerate_hash<int>(), custom_allocator_type{}); 163 static_assert(std::is_same<decltype(m6), TMap<int, std::string, degenerate_hash<int>, 164 std::equal_to<int>, custom_allocator_type>>::value); 165 166 // check TMap(std::initializer_list) 167 TMap m7(l); 168 static_assert(std::is_same<decltype(m7), TMap<int, std::string>>::value); 169 170 // check TMap(std::initializer_list, size_t) 171 TMap m8(l, 1); 172 static_assert(std::is_same<decltype(m8), TMap<int, std::string>>::value); 173 174 // check TMap(std::initializer_list, size_t, Hasher) 175 TMap m9(l, 4, degenerate_hash<int>()); 176 static_assert(std::is_same<decltype(m9), TMap<int, std::string, degenerate_hash<int>>>::value); 177 178 // check TMap(std::initializer_list, size_t, Hasher, Equality) 179 TMap m10(l, 4, degenerate_hash<int>(), std::less<int>()); 180 static_assert(std::is_same<decltype(m10), TMap<int, std::string, degenerate_hash<int>, std::less<int>>>::value); 181 182 // check TMap(std::initializer_list, size_t, Hasher, Equality, Allocator) 183 TMap m11(l, 4, degenerate_hash<int>(), std::less<int>(), custom_allocator_type{}); 184 static_assert(std::is_same<decltype(m11), TMap<int, std::string, degenerate_hash<int>, 185 std::less<int>, custom_allocator_type>>::value); 186 187 // check TMap(std::initializer_list, size_t, Allocator) 188 TMap m12(l, 4, custom_allocator_type{}); 189 static_assert(std::is_same<decltype(m12), TMap<int, std::string, std::hash<int>, 190 std::equal_to<int>, custom_allocator_type>>::value); 191 192 // check TMap(std::initializer_list, size_t, Hasher, Allocator) 193 TMap m13(l, 4, degenerate_hash<int>(), custom_allocator_type{}); 194 static_assert(std::is_same<decltype(m13), TMap<int, std::string, degenerate_hash<int>, 195 std::equal_to<int>, custom_allocator_type>>::value); 196 197 // check TMap(TMap &) 198 TMap m14(m1); 199 static_assert(std::is_same<decltype(m14), decltype(m1)>::value); 200 201 // check TMap(TMap &, Allocator) 202 // TODO: investigate why no implicit deduction guides generated for this ctor 203 TMap m15(m5, custom_allocator_type{}); 204 static_assert(std::is_same<decltype(m15), decltype(m5)>::value); 205 206 // check TMap(TMap &&) 207 TMap m16(std::move(m1)); 208 static_assert(std::is_same<decltype(m16), decltype(m1)>::value); 209 210 // check TMap(TMap &&, Allocator) 211 // TODO: investigate why no implicit deduction guides generated for this ctor 212 TMap m17(std::move(m5), custom_allocator_type{}); 213 static_assert(std::is_same<decltype(m17), decltype(m5)>::value); 214 } 215 #endif 216 217 void test_heterogeneous_functions() { 218 check_heterogeneous_functions_key_int<oneapi::tbb::concurrent_unordered_map, int, int>(); 219 check_heterogeneous_functions_key_int<oneapi::tbb::concurrent_unordered_multimap, int, int>(); 220 check_heterogeneous_functions_key_string<oneapi::tbb::concurrent_unordered_map, std::string, std::string>(); 221 check_heterogeneous_functions_key_string<oneapi::tbb::concurrent_unordered_multimap, std::string, std::string>(); 222 } 223 224 struct CumapTraits : UnorderedMoveTraitsBase { 225 template <typename T, typename Allocator> 226 using container_type = oneapi::tbb::concurrent_unordered_map<T, T, std::hash<T>, std::equal_to<T>, Allocator>; 227 228 template <typename T> 229 using container_value_type = std::pair<const T, T>; 230 231 using init_iterator_type = move_support_tests::FooPairIterator; 232 }; // struct CumapTraits 233 234 struct CumultimapTraits : UnorderedMoveTraitsBase { 235 template <typename T, typename Allocator> 236 using container_type = oneapi::tbb::concurrent_unordered_multimap<T, T, std::hash<T>, std::equal_to<T>, Allocator>; 237 238 template <typename T> 239 using container_value_type = std::pair<const T, T>; 240 241 using init_iterator_type = move_support_tests::FooPairIterator; 242 }; // struct CumultimapTraits 243 244 //! Testing concurrent_unordered_map member types 245 //! \brief \ref interface \ref requirement 246 TEST_CASE("concurrent_unordered_map member types") { 247 test_member_types<oneapi::tbb::concurrent_unordered_map>(); 248 } 249 250 //! Testing requirements of concurrent_unordered_map 251 //! \brief \ref interface \ref requirement 252 TEST_CASE("concurrent_unordered_map requirements") { 253 test_basic<map_type>(); 254 } 255 256 //! Testing multithreading support in concurrent_unordered_map 257 //! \brief \ref requirement 258 TEST_CASE("concurrent_unordered_map multithreading support") { 259 test_concurrent<map_type>(); 260 } 261 262 //! Testing move constructors and assignment operator in concurrent_unordered_map 263 //! \brief \ref interface \ref requirement 264 TEST_CASE("concurrent_unordered_map move semantics support") { 265 test_rvalue_ref_support<CumapTraits>(); 266 } 267 268 //! Testing std::initializer_list constructors and modifiers in concurrent_unordered_map 269 //! \brief \ref interface \ref requirement 270 TEST_CASE("std::initializer_list support in concurrent_unordered_map") { 271 test_initializer_list_support<map_type>({{1, 1}, {2, 2}, {3, 3}, {4, 4}}); 272 } 273 274 //! Testing node handling in concurrent_unordered_map 275 //! \brief \ref interface \ref requirement 276 TEST_CASE("node handling support in concurrent_unordered_map") { 277 node_handling_tests::test_node_handling_support<map_type>(); 278 } 279 280 //! Testing std::allocator_traits support in concurrent_unordered_map 281 //! \brief \ref interface \ref requirement 282 TEST_CASE("std::allocator_traits support in concurrent_unordered_map") { 283 test_allocator_traits_support<CumapTraits>(); 284 } 285 286 //! Testing heterogeneous overloads in concurrent_unordered_map 287 //! \brief \ref interface \ref requirement 288 TEST_CASE("heterogeneous overloads in concurrent_unordered_map") { 289 check_heterogeneous_functions_key_int<oneapi::tbb::concurrent_unordered_map, int, int>(); 290 check_heterogeneous_functions_key_string<oneapi::tbb::concurrent_unordered_map, std::string, std::string>(); 291 } 292 293 //! Testing insert overloads with generic pair in concurrent_unordered_map 294 //! \brief \ref interface \ref requirement 295 TEST_CASE("insertion by generic pair in concurrent_unordered_map") { 296 test_insert_by_generic_pair<oneapi::tbb::concurrent_unordered_map>(); 297 } 298 299 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 300 //! Testing Class Template Argument Deduction in concurrent_unordered_map 301 //! \brief \ref interface \ref requirement 302 TEST_CASE("CTAD support in concurrent_unordered_map") { 303 test_deduction_guides<oneapi::tbb::concurrent_unordered_map>(); 304 } 305 #endif 306 307 //! Testing comparisons in concurrent_unordered_map 308 //! \brief \ref interface \ref requirement 309 TEST_CASE("concurrent_unordered_map comparisons") { 310 test_map_comparisons<oneapi::tbb::concurrent_unordered_map>(); 311 } 312 313 //! Testing concurrent_unordered_multimap member types 314 //! \brief \ref interface \ref requirement 315 TEST_CASE("concurrent_unordered_multimap member types") { 316 test_member_types<oneapi::tbb::concurrent_unordered_multimap>(); 317 } 318 319 //! Testing requirements of concurrent_unordered_multimap 320 //! \brief \ref interface \ref requirement 321 TEST_CASE("concurrent_unordered_multimap requirements") { 322 test_basic<multimap_type>(); 323 } 324 325 //! Testing multithreading support in concurrent_unordered_multimap 326 //! \brief \ref requirement 327 TEST_CASE("concurrent_unordered_multimap multithreading support") { 328 test_concurrent<multimap_type>(); 329 } 330 331 //! Testing move constructors and assignment operator in concurrent_unordered_multimap 332 //! \brief \ref interface \ref requirement 333 TEST_CASE("concurrent_unordered_multimap move semantics support") { 334 test_rvalue_ref_support<CumultimapTraits>(); 335 } 336 337 //! Testing std::initializer_list constructors and modifiers in concurrent_unordered_multimap 338 //! \brief \ref interface \ref requirement 339 TEST_CASE("std::initializer_list support in concurrent_unordered_multimap") { 340 test_initializer_list_support<multimap_type>({{1, 1}, {2, 2}, {3, 3}, {4, 4}, {4, 40}}); 341 } 342 343 //! Testing node handling support in concurrent_unordered_multimap 344 //! \brief \ref interface \ref requirement 345 TEST_CASE("node handling support in concurrent_unordered_multimap") { 346 node_handling_tests::test_node_handling_support<multimap_type>(); 347 } 348 349 //! Testing std::allocator_traits support in concurrent_unordered_multimap 350 //! \brief \ref interface \ref requirement 351 TEST_CASE("std::allocator_traits support in concurrent_unordered_multimap") { 352 test_allocator_traits_support<CumultimapTraits>(); 353 } 354 355 //! Testing heterogeneous overloads in concurrent_unordered_multimap 356 //! \brief \ref interface \ref requirement 357 TEST_CASE("heterogeneous overloads in concurrent_unordered_multimap") { 358 check_heterogeneous_functions_key_int<oneapi::tbb::concurrent_unordered_multimap, int, int>(); 359 check_heterogeneous_functions_key_string<oneapi::tbb::concurrent_unordered_multimap, std::string, std::string>(); 360 } 361 362 //! Testing insert overloads with generic pair in concurrent_unordered_multimap 363 //! \brief \ref interface \ref requirement 364 TEST_CASE("insertion by generic pair in concurrent_unordered_multimap") { 365 test_insert_by_generic_pair<oneapi::tbb::concurrent_unordered_multimap>(); 366 } 367 368 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 369 //! Testing Class Template Argument Deduction in concurrent_unordered_multimap 370 //! \brief \ref interface \ref requirement 371 TEST_CASE("CTAD support in concurrent_unordered_multimap") { 372 test_deduction_guides<oneapi::tbb::concurrent_unordered_multimap>(); 373 } 374 #endif 375 376 //! Testing comparisons in concurrent_unordered_multimap 377 //! \brief \ref interface \ref requirement 378 TEST_CASE("concurrent_unordered_multimap comparisons") { 379 test_map_comparisons<oneapi::tbb::concurrent_unordered_multimap>(); 380 } 381 382 //! Testing of merge operations in concurrent_unordered_map and concurrent_unordered_multimap 383 //! \brief \ref interface \ref requirement 384 TEST_CASE("merge operations") { 385 node_handling_tests::test_merge<map_type, multimap_type>(1000); 386 } 387