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