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>
test_member_types()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>
test_deduction_guides()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