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 #define TBB_DEFINE_STD_HASH_SPECIALIZATIONS 1 18 #include <tbb/concurrent_unordered_set.h> 19 #include "common/concurrent_unordered_common.h" 20 21 //! \file test_concurrent_unordered_set.cpp 22 //! \brief Test for [containers.concurrent_unordered_set containers.concurrent_unordered_multiset] specifications 23 24 template <typename... Args> 25 struct AllowMultimapping<tbb::concurrent_unordered_multiset<Args...>> : std::true_type {}; 26 27 template <typename Value> 28 using MyAllocator = LocalCountingAllocator<std::allocator<Value>>; 29 30 using move_support_tests::FooWithAssign; 31 32 using set_type = tbb::concurrent_unordered_set<int, std::hash<int>, std::equal_to<int>, MyAllocator<int>>; 33 using multiset_type = tbb::concurrent_unordered_multiset<int, std::hash<int>, std::equal_to<int>, MyAllocator<int>>; 34 using degenerate_set_type = tbb::concurrent_unordered_set<int, degenerate_hash<int>, std::equal_to<int>, MyAllocator<int>>; 35 using degenerate_multiset_type = tbb::concurrent_unordered_multiset<int, degenerate_hash<int>, std::equal_to<int>, MyAllocator<int>>; 36 37 using checked_set_type = tbb::concurrent_unordered_set<CheckType<int>, std::hash<CheckType<int>>, std::equal_to<CheckType<int>>, MyAllocator<CheckType<int>>>; 38 using checked_multiset_type = tbb::concurrent_unordered_multiset<CheckType<int>, std::hash<CheckType<int>>, 39 std::equal_to<CheckType<int>>, MyAllocator<CheckType<int>>>; 40 using checked_state_set_type = tbb::concurrent_unordered_set<FooWithAssign, std::hash<FooWithAssign>, std::equal_to<FooWithAssign>, 41 MyAllocator<FooWithAssign>>; 42 using checked_state_multiset_type = tbb::concurrent_unordered_multiset<FooWithAssign, std::hash<FooWithAssign>, std::equal_to<FooWithAssign>, 43 MyAllocator<FooWithAssign>>; 44 45 struct CusetTraits : UnorderedMoveTraitsBase { 46 template <typename T, typename Allocator> 47 using container_type = tbb::concurrent_unordered_set<T, std::hash<T>, std::equal_to<T>, Allocator>; 48 49 template <typename T> 50 using container_value_type = T; 51 52 using init_iterator_type = move_support_tests::FooIterator; 53 }; // struct CusetTraits 54 55 struct CumultisetTraits : UnorderedMoveTraitsBase { 56 template <typename T, typename Allocator> 57 using container_type = tbb::concurrent_unordered_multiset<T, std::hash<T>, std::equal_to<T>, Allocator>; 58 59 template <typename T> 60 using container_value_type = T; 61 62 using init_iterator_type = move_support_tests::FooIterator; 63 }; // struct CumultisetTraits 64 65 struct UnorderedSetTypesTester { 66 template <bool DefCtorPresent, typename ValueType> 67 void check( const std::list<ValueType>& lst ) { 68 TypeTester<DefCtorPresent, tbb::concurrent_unordered_set<ValueType, std::hash<ValueType>, utils::IsEqual>>(lst); 69 TypeTester<DefCtorPresent, tbb::concurrent_unordered_multiset<ValueType, std::hash<ValueType>, utils::IsEqual>>(lst); 70 } 71 }; 72 73 void test_specific_types() { 74 test_set_specific_types<UnorderedSetTypesTester>(); 75 76 // Regressiong test for a problem with excessive requirements of emplace() 77 test_emplace_insert<tbb::concurrent_unordered_set<test::unique_ptr<int>>, 78 std::false_type>(new int, new int); 79 test_emplace_insert<tbb::concurrent_unordered_multiset<test::unique_ptr<int>>, 80 std::false_type>(new int, new int); 81 } 82 83 //! \brief \ref stress \ref error_guessing 84 TEST_CASE("basic test for concurrent_unordered_set with degenerate hash") { 85 test_basic<degenerate_set_type>(); 86 } 87 88 //! \brief \ref stress \ref error_guessing 89 TEST_CASE("basic test for concurrent_unordered_multiset with degenerate hash") { 90 test_basic<degenerate_multiset_type>(); 91 } 92 93 //! \brief \ref resource_usage 94 TEST_CASE("basic test for concurrent_unordered_set with elements ctor and dtor check") { 95 Checker<checked_set_type::value_type> checker; 96 test_basic<checked_set_type>(); 97 } 98 99 //! \brief \ref resource_usage 100 TEST_CASE("basic test for concurrent_unordered_multiset with elements ctor and dtor check") { 101 Checker<checked_multiset_type::value_type> checker; 102 test_basic<checked_multiset_type>(); 103 } 104 105 //! \brief \ref resource_usage 106 TEST_CASE("basic test for concurrent_unordered_set with elements state check") { 107 test_basic<checked_state_set_type, /*CheckState = */std::true_type>(); 108 } 109 110 //! \brief \ref resource_usage 111 TEST_CASE("basic test for concurrent_unordered_multiset with elements state check") { 112 test_basic<checked_state_multiset_type, /*CheckState = */std::true_type>(); 113 } 114 115 //! \brief \ref stress \ref error_guessing 116 TEST_CASE("multithreading support in concurrent_unordered_set with degenerate hash") { 117 test_concurrent<degenerate_set_type>(); 118 } 119 120 //! \brief \ref stress \ref error_guessing 121 TEST_CASE("multithreading support in concurrent_unordered_multiset with degenerate hash") { 122 test_concurrent<degenerate_multiset_type>(); 123 } 124 125 //! \brief \ref stress \ref error_guessing 126 TEST_CASE("multithreading support in concurrent_unordered_multiset with no unique keys") { 127 test_concurrent<multiset_type>(true); 128 } 129 130 //! \brief \ref stress \ref error_guessing 131 TEST_CASE("multithreading support in concurrent_unordered_multiset with degenerate hash and no unique keys") { 132 test_concurrent<degenerate_multiset_type>(true); 133 } 134 135 //! \brief \ref resource_usage 136 TEST_CASE("multithreading support in concurrent_unordered_set with elements ctor and dtor check") { 137 Checker<checked_set_type::value_type> checker; 138 test_concurrent<checked_set_type>(); 139 } 140 141 //! \brief \ref resource_usage 142 TEST_CASE("multithreading support in concurrent_unordered_multiset with elements ctor and dtor check") { 143 Checker<checked_multiset_type::value_type> checker; 144 test_concurrent<checked_multiset_type>(); 145 } 146 147 //! \brief \ref resource_usage 148 TEST_CASE("multithreading support in concurrent_unordered_set with elements state check") { 149 test_concurrent<checked_state_set_type>(); 150 } 151 152 //! \brief \ref resource_usage 153 TEST_CASE("multithreading support in concurrent_unordered_multiset with elements state check") { 154 test_concurrent<checked_state_multiset_type>(); 155 } 156 157 //! \brief \ref interface \ref error_guessing 158 TEST_CASE("range based for support in concurrent_unordered_set") { 159 test_range_based_for_support<set_type>(); 160 } 161 162 //! \brief \ref interface \ref error_guessing 163 TEST_CASE("range based for support in concurrent_unordered_multiset") { 164 test_range_based_for_support<multiset_type>(); 165 } 166 167 //! \brief \ref stress \ref error_guessing 168 TEST_CASE("merge and concurrent merge in concurrent_unordered_set and set with degenerate hash") { 169 node_handling_tests::test_merge<set_type, degenerate_set_type>(1000); 170 } 171 172 //! \brief \ref regression 173 TEST_CASE("concurrent_unordered_set/multiset with specific key types") { 174 test_specific_types(); 175 } 176 177 //! \brief \ref error_guessing 178 TEST_CASE("concurrent_unordered_set with std::scoped_allocator_adaptor") { 179 test_scoped_allocator<CusetTraits>(); 180 } 181 182 //! \brief \ref error_guessing 183 TEST_CASE("concurrent_unordered_multiset with std::scoped_allocator_adaptor") { 184 test_scoped_allocator<CumultisetTraits>(); 185 } 186 187 //! \brief \ref error_guessing 188 TEST_CASE("concurrent_unordered_set::swap with not always equal allocator") { 189 using not_always_equal_alloc_set_type = tbb::concurrent_unordered_set<int, std::hash<int>, std::equal_to<int>, 190 NotAlwaysEqualAllocator<int>>; 191 test_swap_not_always_equal_allocator<not_always_equal_alloc_set_type>(); 192 } 193 194 //! \brief \ref error_guessing 195 TEST_CASE("concurrent_unordered_multiset::swap with not always equal allocator") { 196 using not_always_equal_alloc_mset_type = tbb::concurrent_unordered_multiset<int, std::hash<int>, std::equal_to<int>, 197 NotAlwaysEqualAllocator<int>>; 198 test_swap_not_always_equal_allocator<not_always_equal_alloc_mset_type>(); 199 } 200 201 #if __TBB_USE_EXCEPTIONS 202 //! \brief \ref error_guessing 203 TEST_CASE("concurrent_unordered_set throwing copy constructor") { 204 using exception_set_type = tbb::concurrent_unordered_set<ThrowOnCopy>; 205 test_exception_on_copy_ctor<exception_set_type>(); 206 } 207 208 //! \brief \ref error_guessing 209 TEST_CASE("concurrent_unordered_multimap throwing copy constructor") { 210 using exception_mset_type = tbb::concurrent_unordered_multiset<ThrowOnCopy>; 211 test_exception_on_copy_ctor<exception_mset_type>(); 212 } 213 #endif // __TBB_USE_EXCEPTIONS 214