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