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#if _MSC_VER
18#define _SCL_SECURE_NO_WARNINGS
19#endif
20
21#include "harness_defs.h"
22#if !(__TBB_TEST_SECONDARY && __TBB_CPP11_STD_PLACEHOLDERS_LINKAGE_BROKEN)
23
24#define __TBB_EXTRA_DEBUG 1
25#include "tbb/concurrent_unordered_set.h"
26#include "harness_assert.h"
27
28#if __TBB_TEST_SECONDARY
29
30#include "harness_runtime_loader.h"
31
32#else // __TBB_TEST_SECONDARY
33#if __TBB_INITIALIZER_LISTS_PRESENT
34// These operator== are used implicitly in test_initializer_list.h.
35// For some unknown reason clang is not able to find the if they a declared after the
36// inclusion of test_initializer_list.h.
37template<typename container_type>
38bool equal_containers( container_type const& lhs, container_type const& rhs );
39template<typename T>
40bool operator==(tbb::concurrent_unordered_set<T> const& lhs, tbb::concurrent_unordered_set<T> const& rhs) {
41 return equal_containers( lhs, rhs );
42}
43
44template<typename T>
45bool operator==(tbb::concurrent_unordered_multiset<T> const& lhs, tbb::concurrent_unordered_multiset<T> const& rhs) {
46 return equal_containers( lhs, rhs );
47}
48#endif /* __TBB_INITIALIZER_LISTS_PRESENT */
49#include "test_concurrent_unordered_common.h"
50
51typedef tbb::concurrent_unordered_set<int, tbb::tbb_hash<int>, std::equal_to<int>, MyAllocator> MySet;
52typedef tbb::concurrent_unordered_set<int, degenerate_hash<int>, std::equal_to<int>, MyAllocator> MyDegenerateSet;
53typedef tbb::concurrent_unordered_set<check_type<int>, tbb::tbb_hash<check_type<int> >, std::equal_to<check_type<int> >, MyAllocator> MyCheckedSet;
54typedef tbb::concurrent_unordered_set<FooWithAssign, tbb::tbb_hash<Foo>, std::equal_to<FooWithAssign>, MyAllocator> MyCheckedStateSet;
55typedef tbb::concurrent_unordered_multiset<int, tbb::tbb_hash<int>, std::equal_to<int>, MyAllocator> MyMultiSet;
56typedef tbb::concurrent_unordered_multiset<int, degenerate_hash<int>, std::equal_to<int>, MyAllocator> MyDegenerateMultiSet;
57typedef tbb::concurrent_unordered_multiset<check_type<int>, tbb::tbb_hash<check_type<int> >, std::equal_to<check_type<int> >, MyAllocator> MyCheckedMultiSet;
58
59#if __TBB_CPP11_RVALUE_REF_PRESENT
60struct cu_set_type : unordered_move_traits_base {
61 template<typename element_type, typename allocator_type>
62 struct apply {
63 typedef tbb::concurrent_unordered_set<element_type, tbb::tbb_hash<element_type>, std::equal_to<element_type>, allocator_type > type;
64 };
65
66 typedef FooIterator init_iterator_type;
67};
68
69struct cu_multiset_type : unordered_move_traits_base {
70 template<typename element_type, typename allocator_type>
71 struct apply {
72 typedef tbb::concurrent_unordered_multiset<element_type, tbb::tbb_hash<element_type>, std::equal_to<element_type>, allocator_type > type;
73 };
74
75 typedef FooIterator init_iterator_type;
76};
77#endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
78struct UnorderedSetTypesTester {
79 template <bool defCtorPresent, typename value_type>
80 void check( const std::list<value_type> &lst ) {
81 TypeTester< defCtorPresent, tbb::concurrent_unordered_set<value_type, tbb::tbb_hash<value_type>, Harness::IsEqual>,
82 tbb::concurrent_unordered_set< value_type, tbb::tbb_hash<value_type>, Harness::IsEqual, debug_allocator<value_type> > >( lst );
83 TypeTester< defCtorPresent, tbb::concurrent_unordered_multiset<value_type, tbb::tbb_hash<value_type>, Harness::IsEqual>,
84 tbb::concurrent_unordered_multiset< value_type, tbb::tbb_hash<value_type>, Harness::IsEqual, debug_allocator<value_type> > >( lst );
85 }
86};
87
88void TestTypes( ) {
89 TestSetCommonTypes<UnorderedSetTypesTester>();
90
91#if __TBB_CPP11_RVALUE_REF_PRESENT && __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_SMART_POINTERS_PRESENT
92 // Regression test for a problem with excessive requirements of emplace()
93 test_emplace_insert<tbb::concurrent_unordered_set< test::unique_ptr<int> >,
94 tbb::internal::false_type>( new int, new int );
95 test_emplace_insert<tbb::concurrent_unordered_multiset< test::unique_ptr<int> >,
96 tbb::internal::false_type>( new int, new int );
97#endif /*__TBB_CPP11_RVALUE_REF_PRESENT && __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_SMART_POINTERS_PRESENT*/
98}
99
100#endif // __TBB_TEST_SECONDARY
101
102#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
103template <template <typename ...> typename TSet>
104void TestDeductionGuides() {
105 using ComplexType = const std::string *;
106 std::vector<ComplexType> v;
107 std::string s = "s";
108 auto l = { ComplexType(&s), ComplexType(&s)};
109
110 // check TSet(InputIterator,InputIterator)
111 TSet s1(v.begin(), v.end());
112 static_assert(std::is_same<decltype(s1), TSet<ComplexType>>::value);
113
114 // check TSet(InputIterator,InputIterator, size_t, Hasher)
115 TSet s2(v.begin(), v.end(), 5, std::hash<ComplexType>());
116 static_assert(std::is_same<decltype(s2), TSet<ComplexType, std::hash<ComplexType>>>::value);
117
118 // check TSet(InputIterator,InputIterator, size_t, Hasher, Equality)
119 TSet s3(v.begin(), v.end(), 5, std::hash<ComplexType>(), std::less<ComplexType>());
120 static_assert(std::is_same<decltype(s3), TSet<ComplexType, std::hash<ComplexType>,
121 std::less<ComplexType>>>::value);
122
123 // check TSet(InputIterator,InputIterator, size_t, Hasher, Equality, Allocator)
124 TSet s4(v.begin(), v.end(), 5, std::hash<ComplexType>(), std::less<ComplexType>(),
125 std::allocator<ComplexType>());
126 static_assert(std::is_same<decltype(s4), TSet<ComplexType, std::hash<ComplexType>,
127 std::less<ComplexType>, std::allocator<ComplexType>>>::value);
128
129 // check TSet(InputIterator,InputIterator, size_t, Allocator)
130 TSet s5(v.begin(), v.end(), 5, std::allocator<ComplexType>());
131 static_assert(std::is_same<decltype(s5), TSet<ComplexType, tbb::tbb_hash<ComplexType>,
132 std::equal_to<ComplexType>, std::allocator<ComplexType>>>::value);
133
134 // check TSet(InputIterator,InputIterator, size_t, Hasher, Allocator)
135 TSet s6(v.begin(), v.end(), 5, std::hash<ComplexType>(), std::allocator<ComplexType>());
136 static_assert(std::is_same<decltype(s6), TSet<ComplexType, std::hash<ComplexType>,
137 std::equal_to<ComplexType>, std::allocator<ComplexType>>>::value);
138
139 // check TSet(std::initializer_list)
140 TSet s7(l);
141 static_assert(std::is_same<decltype(s7), TSet<ComplexType>>::value);
142
143 // check TSet(std::initializer_list, size_t, Hasher)
144 TSet s8(l, 5, std::hash<ComplexType>());
145 static_assert(std::is_same<decltype(s8), TSet<ComplexType, std::hash<ComplexType>>>::value);
146
147 // check TSet(std::initializer_list, size_t, Hasher, Equality)
148 TSet s9(l, 5, std::hash<ComplexType>(), std::less<ComplexType>());
149 static_assert(std::is_same<decltype(s9), TSet<ComplexType, std::hash<ComplexType>,
150 std::less<ComplexType>>>::value);
151
152 // check TSet(std::initializer_list, size_t, Hasher, Equality, Allocator)
153 TSet s10(l, 5, std::hash<ComplexType>(), std::less<ComplexType>(), std::allocator<ComplexType>());
154 static_assert(std::is_same<decltype(s10), TSet<ComplexType, std::hash<ComplexType>,
155 std::less<ComplexType>, std::allocator<ComplexType>>>::value);
156
157 // check TSet(std::initializer_list, size_t, Allocator)
158 TSet s11(l, 5, std::allocator<ComplexType>());
159 static_assert(std::is_same<decltype(s11), TSet<ComplexType, tbb::tbb_hash<ComplexType>,
160 std::equal_to<ComplexType>, std::allocator<ComplexType>>>::value);
161
162 // check TSet(std::initializer_list, size_t, Hasher, Allocator)
163 TSet s12(l, 5, std::hash<ComplexType>(), std::allocator<ComplexType>());
164 static_assert(std::is_same<decltype(s12), TSet<ComplexType, std::hash<ComplexType>,
165 std::equal_to<ComplexType>, std::allocator<ComplexType>>>::value);
166
167 // check TSet(TSet &)
168 TSet s13(s1);
169 static_assert(std::is_same<decltype(s13), decltype(s1)>::value);
170
171 // check TSet(TSet &, Allocator)
172 TSet s14(s5, std::allocator<ComplexType>());
173 static_assert(std::is_same<decltype(s14), decltype(s5)>::value);
174
175 // check TSet(TSet &&)
176 TSet s15(std::move(s1));
177 static_assert(std::is_same<decltype(s15), decltype(s1)>::value);
178
179 // check TSet(TSet &&, Allocator)
180 TSet s16(std::move(s5), std::allocator<ComplexType>());
181 static_assert(std::is_same<decltype(s16), decltype(s5)>::value);
182}
183#endif
184
185#if !__TBB_TEST_SECONDARY
186#define INITIALIZATION_TIME_TEST_NAMESPACE initialization_time_test
187#define TEST_INITIALIZATION_TIME_OPERATIONS_NAME test_initialization_time_operations
188void test_initialization_time_operations_external();
189#else
190#define INITIALIZATION_TIME_TEST_NAMESPACE initialization_time_test_external
191#define TEST_INITIALIZATION_TIME_OPERATIONS_NAME test_initialization_time_operations_external
192#endif
193
194namespace INITIALIZATION_TIME_TEST_NAMESPACE {
195 tbb::concurrent_unordered_set<int> static_init_time_set;
196 int any_non_zero_value = 89432;
197 bool static_init_time_inserted = (static_init_time_set.insert( any_non_zero_value )).second;
198 bool static_init_time_found = ((static_init_time_set.find( any_non_zero_value )) != static_init_time_set.end( ));
199}
200void TEST_INITIALIZATION_TIME_OPERATIONS_NAME( ) {
201 using namespace INITIALIZATION_TIME_TEST_NAMESPACE;
202#define LOCATION ",in function: " __TBB_STRING(TEST_INITIALIZATION_TIME_OPERATIONS_NAME)
203 ASSERT( static_init_time_inserted, "failed to insert an item during initialization of global objects" LOCATION );
204 ASSERT( static_init_time_found, "failed to find an item during initialization of global objects" LOCATION );
205
206 bool static_init_time_found_in_main = ((static_init_time_set.find( any_non_zero_value )) != static_init_time_set.end( ));
207 ASSERT( static_init_time_found_in_main, "failed to find during main() an item inserted during initialization of global objects" LOCATION );
208#undef LOCATION
209}
210
211#if !__TBB_TEST_SECONDARY
212int TestMain() {
213 test_machine( );
214
215 test_basic<MySet>( "concurrent unordered Set" );
216 test_basic<MyDegenerateSet>( "concurrent unordered degenerate Set" );
217 test_concurrent<MySet>("concurrent unordered Set");
218 test_concurrent<MyDegenerateSet>( "concurrent unordered degenerate Set" );
219 test_basic<MyMultiSet>("concurrent unordered MultiSet");
220 test_basic<MyDegenerateMultiSet>("concurrent unordered degenerate MultiSet");
221 test_concurrent<MyMultiSet>( "concurrent unordered MultiSet" );
222 test_concurrent<MyDegenerateMultiSet>("concurrent unordered degenerate MultiSet");
223 test_concurrent<MyMultiSet>( "concurrent unordered MultiSet asymptotic", true );
224
225 { Check<MyCheckedSet::value_type> checkit; test_basic<MyCheckedSet>( "concurrent_unordered_set (checked)" ); }
226 { Check<MyCheckedSet::value_type> checkit; test_concurrent<MyCheckedSet>( "concurrent unordered set (checked)" ); }
227 test_basic<MyCheckedStateSet>("concurrent unordered set (checked element state)", tbb::internal::true_type());
228 test_concurrent<MyCheckedStateSet>("concurrent unordered set (checked element state)");
229
230 { Check<MyCheckedMultiSet::value_type> checkit; test_basic<MyCheckedMultiSet>("concurrent_unordered_multiset (checked)"); }
231 { Check<MyCheckedMultiSet::value_type> checkit; test_concurrent<MyCheckedMultiSet>( "concurrent unordered multiset (checked)" ); }
232
233 test_initialization_time_operations( );
234#if !__TBB_CPP11_STD_PLACEHOLDERS_LINKAGE_BROKEN
235 test_initialization_time_operations_external( );
236#else
237 REPORT( "Known issue: global objects initialization time tests skipped.\n" );
238#endif //!__TBB_CPP11_STD_PLACEHOLDERS_LINKING_BROKEN
239
240#if __TBB_INITIALIZER_LISTS_PRESENT
241 TestInitList< tbb::concurrent_unordered_set<int>,
242 tbb::concurrent_unordered_multiset<int> >( {1,2,3,4,5} );
243#endif
244
245#if __TBB_RANGE_BASED_FOR_PRESENT
246 TestRangeBasedFor<MySet>();
247 TestRangeBasedFor<MyMultiSet>();
248#endif
249
250#if __TBB_CPP11_RVALUE_REF_PRESENT
251 test_rvalue_ref_support<cu_set_type>( "concurrent unordered set" );
252 test_rvalue_ref_support<cu_multiset_type>( "concurrent unordered multiset" );
253#endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
254
255 TestTypes();
256
257#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
258 TestDeductionGuides<tbb::concurrent_unordered_set>();
259 TestDeductionGuides<tbb::concurrent_unordered_multiset>();
260#endif
261
262#if __TBB_UNORDERED_NODE_HANDLE_PRESENT
263 node_handling::TestNodeHandling<MySet>();
264 node_handling::TestNodeHandling<MyMultiSet>();
265 node_handling::TestMerge<MySet, MyMultiSet>(10000);
266 node_handling::TestMerge<MySet, MyDegenerateSet>(10000);
267#endif /*__TBB_UNORDERED_NODE_HANDLE_PRESENT*/
268
269 return Harness::Done;
270}
271#endif //#if !__TBB_TEST_SECONDARY
272#endif //!(__TBB_TEST_SECONDARY && __TBB_CPP11_STD_PLACEHOLDERS_LINKAGE_BROKEN)
273