| 1 | /* |
| 2 | Copyright (c) 2005-2019 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 | #define 1 |
| 18 | #if _MSC_VER |
| 19 | #define _SCL_SECURE_NO_WARNINGS |
| 20 | #endif |
| 21 | |
| 22 | #include "tbb/concurrent_unordered_map.h" |
| 23 | #if __TBB_INITIALIZER_LISTS_PRESENT |
| 24 | // These operator== are used implicitly in test_initializer_list.h. |
| 25 | // For some unknown reason clang is not able to find the if they a declared after the |
| 26 | // inclusion of test_initializer_list.h. |
| 27 | template<typename container_type> |
| 28 | bool equal_containers( container_type const& lhs, container_type const& rhs ); |
| 29 | template<typename Key, typename Value> |
| 30 | bool operator==( tbb::concurrent_unordered_map<Key, Value> const& lhs, tbb::concurrent_unordered_map<Key, Value> const& rhs ) { |
| 31 | return equal_containers( lhs, rhs ); |
| 32 | } |
| 33 | template<typename Key, typename Value> |
| 34 | bool operator==( tbb::concurrent_unordered_multimap<Key, Value> const& lhs, tbb::concurrent_unordered_multimap<Key, Value> const& rhs ) { |
| 35 | return equal_containers( lhs, rhs ); |
| 36 | } |
| 37 | #endif /* __TBB_INITIALIZER_LISTS_PRESENT */ |
| 38 | #include "test_concurrent_unordered_common.h" |
| 39 | |
| 40 | typedef tbb::concurrent_unordered_map<int, int, tbb::tbb_hash<int>, std::equal_to<int>, MyAllocator> MyMap; |
| 41 | typedef tbb::concurrent_unordered_map<int, int, degenerate_hash<int>, std::equal_to<int>, MyAllocator> MyDegenerateMap; |
| 42 | typedef tbb::concurrent_unordered_map<int, check_type<int>, tbb::tbb_hash<int>, std::equal_to<int>, MyAllocator> MyCheckedMap; |
| 43 | typedef tbb::concurrent_unordered_map<intptr_t, FooWithAssign, tbb::tbb_hash<intptr_t>, std::equal_to<intptr_t>, MyAllocator> MyCheckedStateMap; |
| 44 | typedef tbb::concurrent_unordered_multimap<int, int, tbb::tbb_hash<int>, std::equal_to<int>, MyAllocator> MyMultiMap; |
| 45 | typedef tbb::concurrent_unordered_multimap<int, int, degenerate_hash<int>, std::equal_to<int>, MyAllocator> MyDegenerateMultiMap; |
| 46 | typedef tbb::concurrent_unordered_multimap<int, check_type<int>, tbb::tbb_hash<int>, std::equal_to<int>, MyAllocator> MyCheckedMultiMap; |
| 47 | |
| 48 | template <> |
| 49 | struct SpecialTests <MyMap> { |
| 50 | static void Test( const char *str ) { |
| 51 | SpecialMapTests<MyMap>(str); |
| 52 | } |
| 53 | }; |
| 54 | |
| 55 | template <> |
| 56 | struct SpecialTests <MyMultiMap> { |
| 57 | static void Test( const char *str ) { |
| 58 | SpecialMultiMapTests<MyMultiMap>(str); |
| 59 | } |
| 60 | }; |
| 61 | |
| 62 | #if __TBB_CPP11_RVALUE_REF_PRESENT |
| 63 | struct cu_map_type : unordered_move_traits_base { |
| 64 | template<typename element_type, typename allocator_type> |
| 65 | struct apply { |
| 66 | typedef tbb::concurrent_unordered_map<element_type, element_type, tbb::tbb_hash<element_type>, std::equal_to<element_type>, allocator_type > type; |
| 67 | }; |
| 68 | |
| 69 | typedef FooPairIterator init_iterator_type; |
| 70 | }; |
| 71 | |
| 72 | struct cu_multimap_type : unordered_move_traits_base { |
| 73 | template<typename element_type, typename allocator_type> |
| 74 | struct apply { |
| 75 | typedef tbb::concurrent_unordered_multimap<element_type, element_type, tbb::tbb_hash<element_type>, std::equal_to<element_type>, allocator_type > type; |
| 76 | }; |
| 77 | |
| 78 | typedef FooPairIterator init_iterator_type; |
| 79 | }; |
| 80 | #endif /* __TBB_CPP11_RVALUE_REF_PRESENT */ |
| 81 | |
| 82 | template <bool defCtorPresent, typename Key, typename Element, typename Hasher, typename Equality, typename Allocator> |
| 83 | void TestMapSpecificMethods( tbb::concurrent_unordered_map<Key, Element, Hasher, Equality, Allocator> &c, |
| 84 | const typename tbb::concurrent_unordered_map<Key, Element, Hasher, Equality, Allocator>::value_type &value ) { |
| 85 | TestMapSpecificMethodsImpl<defCtorPresent>(c, value); |
| 86 | } |
| 87 | |
| 88 | struct UnorderedMapTypesTester{ |
| 89 | template <bool defCtorPresent, typename ValueType> |
| 90 | void check( const std::list<ValueType> &lst ) { |
| 91 | typedef typename ValueType::first_type KeyType; |
| 92 | typedef typename ValueType::second_type ElemType; |
| 93 | TypeTester< defCtorPresent, tbb::concurrent_unordered_map< KeyType, ElemType, tbb::tbb_hash<KeyType>, Harness::IsEqual>, |
| 94 | tbb::concurrent_unordered_map< KeyType, ElemType, tbb::tbb_hash<KeyType>, Harness::IsEqual, debug_allocator<ValueType> > >( lst ); |
| 95 | TypeTester< defCtorPresent, tbb::concurrent_unordered_multimap< KeyType, ElemType, tbb::tbb_hash<KeyType>, Harness::IsEqual>, |
| 96 | tbb::concurrent_unordered_multimap< KeyType, ElemType, tbb::tbb_hash<KeyType>, Harness::IsEqual, debug_allocator<ValueType> > >( lst ); |
| 97 | } |
| 98 | }; |
| 99 | |
| 100 | void TestTypes() { |
| 101 | TestMapCommonTypes<UnorderedMapTypesTester>(); |
| 102 | |
| 103 | #if __TBB_CPP11_RVALUE_REF_PRESENT && __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_SMART_POINTERS_PRESENT |
| 104 | // Regression test for a problem with excessive requirements of emplace() |
| 105 | test_emplace_insert<tbb::concurrent_unordered_map< int*, test::unique_ptr<int> >, |
| 106 | tbb::internal::false_type>( new int, new int ); |
| 107 | test_emplace_insert<tbb::concurrent_unordered_multimap< int*, test::unique_ptr<int> >, |
| 108 | tbb::internal::false_type>( new int, new int ); |
| 109 | #endif /*__TBB_CPP11_RVALUE_REF_PRESENT && __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_SMART_POINTERS_PRESENT*/ |
| 110 | } |
| 111 | |
| 112 | #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT |
| 113 | template <template <typename...> typename TMap> |
| 114 | void TestDeductionGuides() { |
| 115 | using ComplexType = std::pair<int, std::string>; |
| 116 | using ComplexTypeConst = std::pair<const int, std::string>; |
| 117 | std::vector<ComplexType> v; |
| 118 | auto l = { ComplexTypeConst(1, "one" ), ComplexTypeConst(2, "two" )}; |
| 119 | |
| 120 | // check TMap(InputIterator, InputIterator) |
| 121 | TMap m0(v.begin(), v.end()); |
| 122 | static_assert(std::is_same<decltype(m0), TMap<int, std::string>>::value); |
| 123 | |
| 124 | // check TMap(InputIterator, InputIterator, size_t) |
| 125 | TMap m1(v.begin(), v.end(), 1); |
| 126 | static_assert(std::is_same<decltype(m1), TMap<int, std::string>>::value); |
| 127 | |
| 128 | |
| 129 | // check TMap(InputIterator, InputIterator, size_t, Hasher) |
| 130 | TMap m2(v.begin(), v.end(), 4, std::hash<int>()); |
| 131 | static_assert(std::is_same<decltype(m2), TMap<int, std::string, std::hash<int>>>::value); |
| 132 | |
| 133 | // check TMap(InputIterator, InputIterator, size_t, Hasher, Equality) |
| 134 | TMap m3(v.begin(), v.end(), 4, std::hash<int>(), std::less<int>()); |
| 135 | static_assert(std::is_same<decltype(m3), TMap<int, std::string, std::hash<int>, std::less<int>>>::value); |
| 136 | |
| 137 | // check TMap(InputIterator, InputIterator, size_t, Hasher, Equality, Allocator) |
| 138 | TMap m4(v.begin(), v.end(), 4, std::hash<int>(), std::less<int>(), std::allocator<int>()); |
| 139 | static_assert(std::is_same<decltype(m4), TMap<int, std::string, std::hash<int>, |
| 140 | std::less<int>, std::allocator<int>>>::value); |
| 141 | |
| 142 | // check TMap(InputIterator, InputIterator, size_t, Allocator) |
| 143 | TMap m5(v.begin(), v.end(), 5, std::allocator<int>()); |
| 144 | static_assert(std::is_same<decltype(m5), TMap<int, std::string, tbb::tbb_hash<int>, |
| 145 | std::equal_to<int>, std::allocator<int>>>::value); |
| 146 | |
| 147 | // check TMap(InputIterator, InputIterator, size_t, Hasher, Allocator) |
| 148 | TMap m6(v.begin(), v.end(), 4, std::hash<int>(), std::allocator<int>()); |
| 149 | static_assert(std::is_same<decltype(m6), TMap<int, std::string, std::hash<int>, |
| 150 | std::equal_to<int>, std::allocator<int>>>::value); |
| 151 | |
| 152 | // check TMap(std::initializer_list) |
| 153 | TMap m7(l); |
| 154 | static_assert(std::is_same<decltype(m7), TMap<int, std::string>>::value); |
| 155 | |
| 156 | // check TMap(std::initializer_list, size_t) |
| 157 | TMap m8(l, 1); |
| 158 | static_assert(std::is_same<decltype(m8), TMap<int, std::string>>::value); |
| 159 | |
| 160 | // check TMap(std::initializer_list, size_t, Hasher) |
| 161 | TMap m9(l, 4, std::hash<int>()); |
| 162 | static_assert(std::is_same<decltype(m9), TMap<int, std::string, std::hash<int>>>::value); |
| 163 | |
| 164 | // check TMap(std::initializer_list, size_t, Hasher, Equality) |
| 165 | TMap m10(l, 4, std::hash<int>(), std::less<int>()); |
| 166 | static_assert(std::is_same<decltype(m10), TMap<int, std::string, std::hash<int>, std::less<int>>>::value); |
| 167 | |
| 168 | // check TMap(std::initializer_list, size_t, Hasher, Equality, Allocator) |
| 169 | TMap m11(l, 4, std::hash<int>(), std::less<int>(), std::allocator<int>()); |
| 170 | static_assert(std::is_same<decltype(m11), TMap<int, std::string, std::hash<int>, |
| 171 | std::less<int>, std::allocator<int>>>::value); |
| 172 | |
| 173 | // check TMap(std::initializer_list, size_t, Allocator) |
| 174 | TMap m12(l, 4, std::allocator<int>()); |
| 175 | static_assert(std::is_same<decltype(m12), TMap<int, std::string, tbb::tbb_hash<int>, |
| 176 | std::equal_to<int>, std::allocator<int>>>::value); |
| 177 | |
| 178 | // check TMap(std::initializer_list, size_t, Hasher, Allocator) |
| 179 | TMap m13(l, 4, std::hash<int>(), std::allocator<int>()); |
| 180 | static_assert(std::is_same<decltype(m13), TMap<int, std::string, std::hash<int>, |
| 181 | std::equal_to<int>, std::allocator<int>>>::value); |
| 182 | |
| 183 | // check TMap(TMap &) |
| 184 | TMap m14(m1); |
| 185 | static_assert(std::is_same<decltype(m14), decltype(m1)>::value); |
| 186 | |
| 187 | // check TMap(TMap &, Allocator) |
| 188 | TMap m15(m5, std::allocator<int>()); |
| 189 | static_assert(std::is_same<decltype(m15), decltype(m5)>::value); |
| 190 | |
| 191 | // check TMap(TMap &&) |
| 192 | TMap m16(std::move(m1)); |
| 193 | static_assert(std::is_same<decltype(m16), decltype(m1)>::value); |
| 194 | |
| 195 | // check TMap(TMap &&, Allocator) |
| 196 | TMap m17(std::move(m5), std::allocator<int>()); |
| 197 | static_assert(std::is_same<decltype(m17), decltype(m5)>::value); |
| 198 | } |
| 199 | #endif |
| 200 | |
| 201 | int TestMain() { |
| 202 | test_machine(); |
| 203 | |
| 204 | test_basic<MyMap>( "concurrent unordered Map" ); |
| 205 | test_basic<MyDegenerateMap>( "concurrent unordered degenerate Map" ); |
| 206 | test_concurrent<MyMap>( "concurrent unordered Map" ); |
| 207 | test_concurrent<MyDegenerateMap>( "concurrent unordered degenerate Map" ); |
| 208 | test_basic<MyMultiMap>( "concurrent unordered MultiMap" ); |
| 209 | test_basic<MyDegenerateMultiMap>( "concurrent unordered degenerate MultiMap" ); |
| 210 | test_concurrent<MyMultiMap>( "concurrent unordered MultiMap" ); |
| 211 | test_concurrent<MyDegenerateMultiMap>( "concurrent unordered degenerate MultiMap" ); |
| 212 | test_concurrent<MyMultiMap>( "concurrent unordered MultiMap asymptotic" , true ); |
| 213 | |
| 214 | { Check<MyCheckedMap::value_type> checkit; test_basic<MyCheckedMap>( "concurrent unordered map (checked)" ); } |
| 215 | { Check<MyCheckedMap::value_type> checkit; test_concurrent<MyCheckedMap>( "concurrent unordered map (checked)" ); } |
| 216 | test_basic<MyCheckedStateMap>("concurrent unordered map (checked state of elements)" , tbb::internal::true_type()); |
| 217 | test_concurrent<MyCheckedStateMap>("concurrent unordered map (checked state of elements)" ); |
| 218 | |
| 219 | { Check<MyCheckedMultiMap::value_type> checkit; test_basic<MyCheckedMultiMap>( "concurrent unordered MultiMap (checked)" ); } |
| 220 | { Check<MyCheckedMultiMap::value_type> checkit; test_concurrent<MyCheckedMultiMap>( "concurrent unordered MultiMap (checked)" ); } |
| 221 | |
| 222 | #if __TBB_INITIALIZER_LISTS_PRESENT |
| 223 | TestInitList< tbb::concurrent_unordered_map<int, int>, |
| 224 | tbb::concurrent_unordered_multimap<int, int> >( {{1,1},{2,2},{3,3},{4,4},{5,5}} ); |
| 225 | #endif /* __TBB_INITIALIZER_LISTS_PRESENT */ |
| 226 | |
| 227 | #if __TBB_RANGE_BASED_FOR_PRESENT |
| 228 | TestRangeBasedFor<MyMap>(); |
| 229 | TestRangeBasedFor<MyMultiMap>(); |
| 230 | #endif |
| 231 | |
| 232 | #if __TBB_CPP11_RVALUE_REF_PRESENT |
| 233 | test_rvalue_ref_support<cu_map_type>( "concurrent unordered map" ); |
| 234 | test_rvalue_ref_support<cu_multimap_type>( "concurrent unordered multimap" ); |
| 235 | #endif /* __TBB_CPP11_RVALUE_REF_PRESENT */ |
| 236 | |
| 237 | #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT |
| 238 | TestDeductionGuides<tbb::concurrent_unordered_map>(); |
| 239 | TestDeductionGuides<tbb::concurrent_unordered_multimap>(); |
| 240 | #endif |
| 241 | |
| 242 | TestTypes(); |
| 243 | |
| 244 | #if __TBB_UNORDERED_NODE_HANDLE_PRESENT |
| 245 | node_handling::TestNodeHandling<MyMap>(); |
| 246 | node_handling::TestNodeHandling<MyMultiMap>(); |
| 247 | node_handling::TestMerge<MyMap, MyMultiMap>(10000); |
| 248 | node_handling::TestMerge<MyMap, MyDegenerateMap>(10000); |
| 249 | #endif /*__TBB_UNORDERED_NODE_HANDLE_PRESENT*/ |
| 250 | |
| 251 | return Harness::Done; |
| 252 | } |
| 253 | |