1 /*
2     Copyright (c) 2019-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 #ifndef NOMINMAX
18 #define NOMINMAX
19 #endif
20 #include <tbb/concurrent_set.h>
21 #include <common/test.h>
22 #include <common/utils.h>
23 #include <common/concurrent_ordered_common.h>
24 #include <memory>
25 #include <type_traits>
26 
27 //! \file conformance_concurrent_set.cpp
28 //! \brief Test for [containers.concurrent_set containers.concurrent_multiset] specifications
29 
30 template <typename... Args>
31 struct AllowMultimapping<tbb::concurrent_multiset<Args...>> : std::true_type {};
32 
33 template <typename Key>
34 using Allocator = LocalCountingAllocator<std::allocator<Key>>;
35 
36 using set_type = tbb::concurrent_set<int, std::less<int>, Allocator<int>>;
37 using multiset_type = tbb::concurrent_multiset<int, std::less<int>, Allocator<int>>;
38 
39 template <template <typename...> class ContainerType>
40 void test_member_types() {
41     using default_container_type = ContainerType<int>;
42     static_assert(std::is_same<typename default_container_type::key_compare, std::less<int>>::value,
43                   "Incorrect default template comparator");
44     static_assert(std::is_same<typename default_container_type::allocator_type, tbb::tbb_allocator<int>>::value,
45                   "Incorrect default template allocator");
46 
47     auto test_comparator = [](const int&, const int&)->bool { return true; };
48     using test_allocator_type = std::allocator<int>;
49 
50     using container_type = ContainerType<int, decltype(test_comparator), test_allocator_type>;
51 
52     static_assert(std::is_same<typename container_type::key_type, int>::value,
53                   "Incorrect container key_type member type");
54     static_assert(std::is_same<typename container_type::value_type, int>::value,
55                   "Incorrect container value_type member type");
56 
57     static_assert(std::is_unsigned<typename container_type::size_type>::value,
58                   "Incorrect container size_type member type");
59     static_assert(std::is_signed<typename container_type::difference_type>::value,
60                   "Incorrect container difference_type member type");
61 
62     static_assert(std::is_same<typename container_type::key_compare, decltype(test_comparator)>::value,
63                   "Incorrect container key_compare member type");
64     static_assert(std::is_same<typename container_type::allocator_type, test_allocator_type>::value,
65                   "Incorrect container allocator_type member type");
66 
67     using value_type = typename container_type::value_type;
68     static_assert(std::is_same<typename container_type::reference, value_type&>::value,
69                   "Incorrect container reference member type");
70     static_assert(std::is_same<typename container_type::const_reference, const value_type&>::value,
71                   "Incorrect container const_reference member type");
72     using allocator_type = typename container_type::allocator_type;
73     static_assert(std::is_same<typename container_type::pointer, typename std::allocator_traits<allocator_type>::pointer>::value,
74                   "Incorrect container pointer member type");
75     static_assert(std::is_same<typename container_type::const_pointer, typename std::allocator_traits<allocator_type>::const_pointer>::value,
76                   "Incorrect container const_pointer member type");
77 
78     static_assert(utils::is_forward_iterator<typename container_type::iterator>::value,
79                   "Incorrect container iterator member type");
80     static_assert(!std::is_const<typename container_type::iterator::value_type>::value,
81                   "Incorrect container iterator member type");
82     static_assert(utils::is_forward_iterator<typename container_type::const_iterator>::value,
83                   "Incorrect container const_iterator member type");
84     static_assert(std::is_const<typename container_type::const_iterator::value_type>::value,
85                   "Incorrect container const_iterator member type");
86 }
87 
88 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
89 template <template <typename ...> typename TSet>
90 void test_deduction_guides() {
91     std::vector<int> vc({1, 2, 3});
92     TSet set(vc.begin(), vc.end());
93     static_assert(std::is_same_v<decltype(set), TSet<int>>, "Wrong");
94 
95     std::greater<int> compare;
96     std::allocator<int> allocator;
97 
98     TSet set2(vc.begin(), vc.end(), compare);
99     static_assert(std::is_same_v<decltype(set2), TSet<int, decltype(compare)>>, "Wrong");
100 
101     TSet set3(vc.begin(), vc.end(), allocator);
102     static_assert(std::is_same_v<decltype(set3), TSet<int, std::less<int>, decltype(allocator)>>, "Wrong");
103 
104     TSet set4(vc.begin(), vc.end(), compare, allocator);
105     static_assert(std::is_same_v<decltype(set4), TSet<int, decltype(compare), decltype(allocator)>>, "Wrong");
106 
107     auto init_list = { int(1), int(2), int(3) };
108     TSet set5(init_list);
109     static_assert(std::is_same_v<decltype(set5), TSet<int>>, "Wrong");
110 
111     TSet set6(init_list, compare);
112     static_assert(std::is_same_v<decltype(set6), TSet<int, decltype(compare)>>, "Wrong");
113 
114     TSet set7(init_list, allocator);
115     static_assert(std::is_same_v<decltype(set7), TSet<int, std::less<int>, decltype(allocator)>>, "Wrong");
116 
117     TSet set8(init_list, compare, allocator);
118     static_assert(std::is_same_v<decltype(set8), TSet<int, decltype(compare), decltype(allocator)>>, "Wrong");
119 }
120 #endif /*__TBB_CPP17_DEDUCTION_GUIDES_PRESENT*/
121 
122 template <template <typename...> class SetType>
123 void test_heterogeneous_functions() {
124     check_heterogeneous_functions_key_int<SetType, int>();
125     check_heterogeneous_functions_key_string<SetType, std::string>();
126     check_heterogeneous_bound_functions<SetType<int, TransparentLess>>();
127 }
128 
129 struct COSetTraits : OrderedMoveTraitsBase {
130     template <typename T, typename Allocator>
131     using container_type = tbb::concurrent_set<T, std::less<T>, Allocator>;
132 
133     template <typename T>
134     using container_value_type = T;
135 
136     using init_iterator_type = move_support_tests::FooIterator;
137 }; // struct COSetTraits
138 
139 struct COMultisetTraits : OrderedMoveTraitsBase {
140     template <typename T, typename Allocator>
141     using container_type = tbb::concurrent_multiset<T, std::less<T>, Allocator>;
142 
143     template <typename T>
144     using container_value_type = T;
145 
146     using init_iterator_type = move_support_tests::FooIterator;
147 }; // struct COMultisetTraits
148 
149 //! Testing concurrent_set member types
150 //! \brief \ref interface \ref requirement
151 TEST_CASE("concurrent_set member types") {
152     test_member_types<tbb::concurrent_set>();
153 }
154 
155 //! Testing multithreading support in concurrent_set
156 //! \brief \ref requirement
157 TEST_CASE("concurrent_set multithreading support") {
158     test_concurrent<set_type>();
159 }
160 
161 //! Testing move constructors and assignment operator in concurrent_set
162 //! \brief \ref interface \ref requirement
163 TEST_CASE("concurrent_set move semantics support") {
164     test_rvalue_ref_support<COSetTraits>();
165 }
166 
167 //! Testing std::initializer_list constructors and modifiers in concurrent_set
168 //! \brief \ref interface \ref requirement
169 TEST_CASE("std::initializer_list support in concurrent_set") {
170     test_initializer_list_support<set_type>({1, 2, 3, 4});
171 }
172 
173 //! Testing node handling in concurrent_set
174 //! \brief \ref interface \ref requirement
175 TEST_CASE("node handling support in concurrent_set") {
176     node_handling_tests::test_node_handling_support<set_type>();
177 }
178 
179 //! Testing std::allocator_traits support in concurrent_set
180 //! \brief \ref interface \ref requirement
181 TEST_CASE("std::allocator_traits support in concurrent_set") {
182     test_allocator_traits_support<COSetTraits>();
183 }
184 
185 //! Testing heterogeneous overloads in concurrent_set
186 //! \brief \ref interface \ref requirement
187 TEST_CASE("heterogeneous overloads in concurrent_set") {
188     test_heterogeneous_functions<tbb::concurrent_set>();
189 }
190 
191 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
192 //! Testing Class Template Argument Deduction in concurrent_set
193 //! \brief \ref interface \ref requirement
194 TEST_CASE("CTAD support in concurrent_set") {
195     test_deduction_guides<tbb::concurrent_set>();
196 }
197 #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
198 
199 //! Testing comparison operators in concurrent_set
200 //! \brief \ref interface \ref requirement
201 TEST_CASE("test concurrent_set comparisons") {
202     test_set_comparisons<tbb::concurrent_set>();
203 }
204 
205 //! Testing concurrent_multiset member types
206 //! \brief \ref interface \ref requirement
207 TEST_CASE("concurrent_multiset member types") {
208     test_member_types<tbb::concurrent_multiset>();
209 }
210 
211 //! Testing requirements of concurrent_multiset
212 //! \brief \ref interface \ref requirement
213 TEST_CASE("concurrent_multiset requirements") {
214     test_basic<multiset_type>();
215 }
216 
217 //! Testing multithreading support in concurrent_multiset
218 //! \brief \ref requirement
219 TEST_CASE("concurrent_multiset multithreading support") {
220     test_concurrent<multiset_type>();
221 }
222 
223 //! Testing move constructors and assignment operator in concurrent_multiset
224 //! \brief \ref interface \ref requirement
225 TEST_CASE("concurrent_multiset multithreading support") {
226     test_rvalue_ref_support<COMultisetTraits>();
227 }
228 
229 //! Testing std::initializer_list constructors and modifiers in concurrent_multiset
230 //! \brief \ref interface \ref requirement
231 TEST_CASE("std::initializer_list support in concurrent_multimap") {
232     test_initializer_list_support<multiset_type>({1, 2, 3, 4, 4});
233 }
234 
235 //! Testing node handling support in concurrent_multiset
236 //! \brief \ref interface \ref requirement
237 TEST_CASE("node handling support in concurrent_multiset") {
238     node_handling_tests::test_node_handling_support<multiset_type>();
239 }
240 
241 //! Testing std::allocator_traits support in concurrent_multiset
242 //! \brief \ref interface \ref requirement
243 TEST_CASE("std::allocator_traits support in concurrent_multiset") {
244     test_allocator_traits_support<COMultisetTraits>();
245 }
246 
247 //! Testing heterogeneous overloads in concurrent_multiset
248 //! \brief \ref interface \ref requirement
249 TEST_CASE("heterogeneous overloads in concurrent_multiset") {
250     test_heterogeneous_functions<tbb::concurrent_multiset>();
251 }
252 
253 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
254 //! Testing Class Template Argument Deduction in concurrent_multiset
255 //! \brief \ref interface \ref requirement
256 TEST_CASE("CTAD support in concurrent_multiset") {
257     test_deduction_guides<tbb::concurrent_multiset>();
258 }
259 #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
260 
261 //! Testing comparison operators in concurrent_multiset
262 //! \brief \ref interface \ref requirement
263 TEST_CASE("test concurrent_set comparisons") {
264     test_set_comparisons<tbb::concurrent_multiset>();
265 }
266 
267 //! Testing of merge operations in concurrent_set and concurrent_multiset
268 //! \brief \ref interface \ref requirement
269 TEST_CASE("merge operations") {
270     node_handling_tests::test_merge<set_type, multiset_type>(1000);
271 }
272