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 22 #include "oneapi/tbb/concurrent_unordered_set.h" 23 #include <common/test.h> 24 #include <common/utils.h> 25 #include <common/concurrent_unordered_common.h> 26 #include <memory> 27 #include <type_traits> 28 29 //! \file conformance_concurrent_unordered_set.cpp 30 //! \brief Test for [containers.concurrent_unordered_set containers.concurrent_unordered_multiset] specifications 31 32 template <typename... Args> 33 struct AllowMultimapping<oneapi::tbb::concurrent_unordered_multiset<Args...>> : std::true_type {}; 34 35 template <typename Key> 36 using Allocator = LocalCountingAllocator<std::allocator<Key>>; 37 38 using set_type = oneapi::tbb::concurrent_unordered_set<int, std::hash<int>, std::equal_to<int>, Allocator<int>>; 39 using multiset_type = oneapi::tbb::concurrent_unordered_multiset<int, std::hash<int>, std::equal_to<int>, Allocator<int>>; 40 41 template <template <typename...> class ContainerType> 42 void test_member_types() { 43 using default_container_type = ContainerType<int>; 44 static_assert(std::is_same<typename default_container_type::hasher, std::hash<int>>::value, 45 "Incorrect default template hasher"); 46 static_assert(std::is_same<typename default_container_type::key_equal, std::equal_to<int>>::value, 47 "Incorrect default template key equality"); 48 static_assert(std::is_same<typename default_container_type::allocator_type, oneapi::tbb::tbb_allocator<int>>::value, 49 "Incorrect default template allocator"); 50 51 auto test_hasher = [](const int&)->std::size_t { return 0; }; 52 auto test_equality = [](const int&, const int&)->bool { return true; }; 53 using test_allocator_type = std::allocator<int>; 54 55 using container_type = ContainerType<int, decltype(test_hasher), decltype(test_equality), test_allocator_type>; 56 57 static_assert(std::is_same<typename container_type::key_type, int>::value, 58 "Incorrect container key_type member type"); 59 static_assert(std::is_same<typename container_type::value_type, int>::value, 60 "Incorrect container value_type member type"); 61 62 static_assert(std::is_unsigned<typename container_type::size_type>::value, 63 "Incorrect container size_type member type"); 64 static_assert(std::is_signed<typename container_type::difference_type>::value, 65 "Incorrect container difference_type member type"); 66 67 static_assert(std::is_same<typename container_type::hasher, decltype(test_hasher)>::value, 68 "Incorrect container hasher member type"); 69 static_assert(std::is_same<typename container_type::key_equal, decltype(test_equality)>::value, 70 "Incorrect container key_equal member type"); 71 72 using transparent_container_type = ContainerType<int, hasher_with_transparent_key_equal, 73 std::equal_to<int>, test_allocator_type>; 74 75 static_assert(std::is_same<typename transparent_container_type::key_equal, transparent_key_equality>::value, 76 "Incorrect container key_equal member type"); 77 static_assert(std::is_same<typename container_type::allocator_type, test_allocator_type>::value, 78 "Incorrect container allocator_type member type"); 79 80 using value_type = typename container_type::value_type; 81 static_assert(std::is_same<typename container_type::reference, value_type&>::value, 82 "Incorrect container reference member type"); 83 static_assert(std::is_same<typename container_type::const_reference, const value_type&>::value, 84 "Incorrect container const_reference member type"); 85 using allocator_type = typename container_type::allocator_type; 86 static_assert(std::is_same<typename container_type::pointer, typename std::allocator_traits<allocator_type>::pointer>::value, 87 "Incorrect container pointer member type"); 88 static_assert(std::is_same<typename container_type::const_pointer, typename std::allocator_traits<allocator_type>::const_pointer>::value, 89 "Incorrect container const_pointer member type"); 90 91 static_assert(utils::is_forward_iterator<typename container_type::iterator>::value, 92 "Incorrect container iterator member type"); 93 static_assert(!std::is_const<typename container_type::iterator::value_type>::value, 94 "Incorrect container iterator member type"); 95 static_assert(utils::is_forward_iterator<typename container_type::const_iterator>::value, 96 "Incorrect container const_iterator member type"); 97 static_assert(std::is_const<typename container_type::const_iterator::value_type>::value, 98 "Incorrect container iterator member type"); 99 static_assert(utils::is_forward_iterator<typename container_type::local_iterator>::value, 100 "Incorrect container local_iterator member type"); 101 static_assert(!std::is_const<typename container_type::local_iterator::value_type>::value, 102 "Incorrect container local_iterator member type"); 103 static_assert(utils::is_forward_iterator<typename container_type::const_local_iterator>::value, 104 "Incorrect container const_local_iterator member type"); 105 static_assert(std::is_const<typename container_type::const_local_iterator::value_type>::value, 106 "Incorrect container const_local_iterator member type"); 107 } 108 109 struct CusetTraits : UnorderedMoveTraitsBase { 110 template <typename T, typename Allocator> 111 using container_type = oneapi::tbb::concurrent_unordered_set<T, std::hash<T>, std::equal_to<T>, Allocator>; 112 113 template <typename T> 114 using container_value_type = T; 115 116 using init_iterator_type = move_support_tests::FooIterator; 117 }; // struct CusetTraits 118 119 struct CumultisetTraits : UnorderedMoveTraitsBase { 120 template <typename T, typename Allocator> 121 using container_type = oneapi::tbb::concurrent_unordered_multiset<T, std::hash<T>, std::equal_to<T>, Allocator>; 122 123 template <typename T> 124 using container_value_type = T; 125 126 using init_iterator_type = move_support_tests::FooIterator; 127 }; // struct CumultisetTraits 128 129 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 130 template <template <typename ...> typename TSet> 131 void test_deduction_guides() { 132 using ComplexType = const std::string *; 133 std::vector<ComplexType> v; 134 std::string s = "s"; 135 auto l = { ComplexType(&s), ComplexType(&s)}; 136 using custom_allocator_type = std::allocator<ComplexType>; 137 138 // check TSet(InputIterator,InputIterator) 139 TSet s1(v.begin(), v.end()); 140 static_assert(std::is_same<decltype(s1), TSet<ComplexType>>::value); 141 142 // check TSet(InputIterator,InputIterator, size_t, Hasher) 143 TSet s2(v.begin(), v.end(), 5, degenerate_hash<ComplexType>()); 144 static_assert(std::is_same<decltype(s2), TSet<ComplexType, degenerate_hash<ComplexType>>>::value); 145 146 // check TSet(InputIterator,InputIterator, size_t, Hasher, Equality) 147 TSet s3(v.begin(), v.end(), 5, degenerate_hash<ComplexType>(), std::less<ComplexType>()); 148 static_assert(std::is_same<decltype(s3), TSet<ComplexType, degenerate_hash<ComplexType>, 149 std::less<ComplexType>>>::value); 150 151 // check TSet(InputIterator,InputIterator, size_t, Hasher, Equality, Allocator) 152 TSet s4(v.begin(), v.end(), 5, degenerate_hash<ComplexType>(), std::less<ComplexType>(), 153 custom_allocator_type{}); 154 static_assert(std::is_same<decltype(s4), TSet<ComplexType, degenerate_hash<ComplexType>, 155 std::less<ComplexType>, custom_allocator_type>>::value); 156 157 // check TSet(InputIterator,InputIterator, size_t, Allocator) 158 TSet s5(v.begin(), v.end(), 5, custom_allocator_type{}); 159 static_assert(std::is_same<decltype(s5), TSet<ComplexType, std::hash<ComplexType>, 160 std::equal_to<ComplexType>, custom_allocator_type>>::value); 161 162 // check TSet(InputIterator,InputIterator, size_t, Hasher, Allocator) 163 TSet s6(v.begin(), v.end(), 5, degenerate_hash<ComplexType>(), custom_allocator_type{}); 164 static_assert(std::is_same<decltype(s6), TSet<ComplexType, degenerate_hash<ComplexType>, 165 std::equal_to<ComplexType>, custom_allocator_type>>::value); 166 167 // check TSet(std::initializer_list) 168 TSet s7(l); 169 static_assert(std::is_same<decltype(s7), TSet<ComplexType>>::value); 170 171 // check TSet(std::initializer_list, size_t, Hasher) 172 TSet s8(l, 5, degenerate_hash<ComplexType>()); 173 static_assert(std::is_same<decltype(s8), TSet<ComplexType, degenerate_hash<ComplexType>>>::value); 174 175 // check TSet(std::initializer_list, size_t, Hasher, Equality) 176 TSet s9(l, 5, degenerate_hash<ComplexType>(), std::less<ComplexType>()); 177 static_assert(std::is_same<decltype(s9), TSet<ComplexType, degenerate_hash<ComplexType>, 178 std::less<ComplexType>>>::value); 179 180 // check TSet(std::initializer_list, size_t, Hasher, Equality, Allocator) 181 TSet s10(l, 5, degenerate_hash<ComplexType>(), std::less<ComplexType>(), custom_allocator_type{}); 182 static_assert(std::is_same<decltype(s10), TSet<ComplexType, degenerate_hash<ComplexType>, 183 std::less<ComplexType>, custom_allocator_type>>::value); 184 185 // check TSet(std::initializer_list, size_t, Allocator) 186 TSet s11(l, 5, custom_allocator_type{}); 187 static_assert(std::is_same<decltype(s11), TSet<ComplexType, std::hash<ComplexType>, 188 std::equal_to<ComplexType>, custom_allocator_type>>::value); 189 190 // check TSet(std::initializer_list, size_t, Hasher, Allocator) 191 TSet s12(l, 5, std::hash<ComplexType>(), custom_allocator_type{}); 192 static_assert(std::is_same<decltype(s12), TSet<ComplexType, std::hash<ComplexType>, 193 std::equal_to<ComplexType>, custom_allocator_type>>::value); 194 195 // check TSet(TSet &) 196 TSet s13(s1); 197 static_assert(std::is_same<decltype(s13), decltype(s1)>::value); 198 199 // check TSet(TSet &, Allocator) 200 TSet s14(s5, custom_allocator_type{}); 201 // TODO: investigate why no implicit deduction guides generated for this ctor 202 static_assert(std::is_same<decltype(s14), decltype(s5)>::value); 203 204 // check TSet(TSet &&) 205 TSet s15(std::move(s1)); 206 static_assert(std::is_same<decltype(s15), decltype(s1)>::value); 207 208 // check TSet(TSet &&, Allocator) 209 TSet s16(std::move(s5), custom_allocator_type{}); 210 // TODO: investigate why no implicit deduction guides generated for this ctor 211 static_assert(std::is_same<decltype(s16), decltype(s5)>::value); 212 } 213 #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 214 215 //! Testing concurrent_unordered_set member types 216 //! \brief \ref interface \ref requirement 217 TEST_CASE("concurrent_unordered_set member types") { 218 test_member_types<oneapi::tbb::concurrent_unordered_set>(); 219 } 220 221 //! Testing requirements of concurrent_unordered_set 222 //! \brief \ref interface \ref requirement 223 TEST_CASE("concurrent_unordered_set requirements") { 224 test_basic<set_type>(); 225 } 226 227 //! Testing multithreading support in concurrent_unordered_set 228 //! \brief \ref requirement 229 TEST_CASE("concurrent_unordered_set multithreading support") { 230 test_concurrent<set_type>(); 231 } 232 233 //! Testing move constructors and assignment operator in concurrent_unordered_set 234 //! \brief \ref interface \ref requirement 235 TEST_CASE("concurrent_unordered_set move semantics support") { 236 test_rvalue_ref_support<CusetTraits>(); 237 } 238 239 //! Testing std::initializer_list constructors and modifiers in concurrent_unordered_set 240 //! \brief \ref interface \ref requirement 241 TEST_CASE("std::initializer_list support in concurrent_unordered_set") { 242 test_initializer_list_support<set_type>({1, 2, 3, 4, 5}); 243 } 244 245 //! Testing node handling in concurrent_unordered_set 246 //! \brief \ref interface \ref requirement 247 TEST_CASE("node handling support in concurrent_unordered_set") { 248 node_handling_tests::test_node_handling_support<set_type>(); 249 } 250 251 //! Testing std::allocator_traits support in concurrent_unordered_set 252 //! \brief \ref interface \ref requirement 253 TEST_CASE("std::allocator_traits support in concurrent_unordered_set") { 254 test_allocator_traits_support<CusetTraits>(); 255 } 256 257 //! Testing heterogeneous overloads in concurrent_unordered_set 258 //! \brief \ref interface \ref requirement 259 TEST_CASE("heterogeneous overloads in concurrent_unordered_set") { 260 check_heterogeneous_functions_key_int<oneapi::tbb::concurrent_unordered_set, int>(); 261 check_heterogeneous_functions_key_string<oneapi::tbb::concurrent_unordered_set, std::string>(); 262 } 263 264 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 265 //! Testing Class Template Argument Deduction in concurrent_unordered_set 266 //! \brief \ref interface \ref requirement 267 TEST_CASE("CTAD support in concurrent_unordered_set") { 268 test_deduction_guides<oneapi::tbb::concurrent_unordered_set>(); 269 } 270 #endif 271 272 //! Testing comparisons in concurrent_unordered_set 273 //! \brief \ref interface \ref requirement 274 TEST_CASE("concurrent_unordered_set comparisons") { 275 test_set_comparisons<oneapi::tbb::concurrent_unordered_set>(); 276 } 277 278 //! Testing concurrent_unordered_multiset member types 279 //! \brief \ref interface \ref requirement 280 TEST_CASE("concurrent_unordered_multiset member types") { 281 test_member_types<oneapi::tbb::concurrent_unordered_multiset>(); 282 } 283 284 //! Testing requirements of concurrent_unordered_multiset 285 //! \brief \ref interface \ref requirement 286 TEST_CASE("concurrent_unordered_multiset requirements") { 287 test_basic<multiset_type>(); 288 } 289 290 //! Testing move constructors and assignment operator in concurrent_unordered_multiset 291 //! \brief \ref requirement 292 TEST_CASE("concurrent_unordered_multiset multithreading support") { 293 test_concurrent<multiset_type>(); 294 } 295 296 //! Testing move constructors and assignment operator in concurrent_unordered_multiset 297 //! \brief \ref interface \ref requirement 298 TEST_CASE("concurrent_unordered_multiset move semantics support") { 299 test_rvalue_ref_support<CumultisetTraits>(); 300 } 301 302 //! Testing std::initializer_list constructors and modifiers in concurrent_unordered_multiset 303 //! \brief \ref interface \ref requirement 304 TEST_CASE("std::initializer_list support in concurrent_unordered_multiset") { 305 test_initializer_list_support<multiset_type>({1, 2, 3, 4, 5, 5}); 306 } 307 308 //! Testing node handling support in concurrent_unordered_multiset 309 //! \brief \ref interface \ref requirement 310 TEST_CASE("node handling support in concurrent_unordered_multiset") { 311 node_handling_tests::test_node_handling_support<multiset_type>(); 312 } 313 314 //! Testing std::allocator_traits support in concurrent_unordered_multiset 315 //! \brief \ref interface \ref requirement 316 TEST_CASE("std::allocator_traits support in concurrent_unordered_multiset") { 317 test_allocator_traits_support<CumultisetTraits>(); 318 } 319 320 //! Testing heterogeneous overloads in concurrent_unordered_multiset 321 //! \brief \ref interface \ref requirement 322 TEST_CASE("heterogeneous overloads in concurrent_unordered_multiset") { 323 check_heterogeneous_functions_key_int<oneapi::tbb::concurrent_unordered_multiset, int>(); 324 check_heterogeneous_functions_key_string<oneapi::tbb::concurrent_unordered_multiset, std::string>(); 325 } 326 327 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 328 //! Testing Class Template Argument Deduction in concurrent_unordered_multiset 329 //! \brief \ref interface \ref requirement 330 TEST_CASE("CTAD support in concurrent_unordered_multiset") { 331 test_deduction_guides<oneapi::tbb::concurrent_unordered_multiset>(); 332 } 333 #endif 334 335 //! Testing comparisons in concurrent_unordered_multiset 336 //! \brief \ref interface \ref requirement 337 TEST_CASE("concurrent_unordered_multiset comparisons") { 338 test_set_comparisons<oneapi::tbb::concurrent_unordered_multiset>(); 339 } 340 341 //! Testing of merge operation in concurrent_unordered_set and concurrent_unordered_multiset 342 //! \brief \ref interface \ref requirement 343 TEST_CASE("merge operations") { 344 node_handling_tests::test_merge<set_type, multiset_type>(1000); 345 } 346