1 /*
2     Copyright (c) 2019-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 #ifndef NOMINMAX
18 #define NOMINMAX
19 #endif
20 #include "oneapi/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<oneapi::tbb::concurrent_multiset<Args...>> : std::true_type {};
32 
33 template <typename Key>
34 using Allocator = LocalCountingAllocator<std::allocator<Key>>;
35 
36 using set_type = oneapi::tbb::concurrent_set<int, std::less<int>, Allocator<int>>;
37 using multiset_type = oneapi::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, oneapi::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 
109     TSet set5(init_list);
110     static_assert(std::is_same_v<decltype(set5), TSet<int>>, "Wrong");
111 
112     TSet set6(init_list, compare);
113     static_assert(std::is_same_v<decltype(set6), TSet<int, decltype(compare)>>, "Wrong");
114 
115     TSet set7(init_list, allocator);
116     static_assert(std::is_same_v<decltype(set7), TSet<int, std::less<int>, decltype(allocator)>>, "Wrong");
117 
118     TSet set8(init_list, compare, allocator);
119     static_assert(std::is_same_v<decltype(set8), TSet<int, decltype(compare), decltype(allocator)>>, "Wrong");
120 }
121 #endif /*__TBB_CPP17_DEDUCTION_GUIDES_PRESENT*/
122 
123 template <template <typename...> class SetType>
124 void test_heterogeneous_functions() {
125     check_heterogeneous_functions_key_int<SetType, int>();
126     check_heterogeneous_functions_key_string<SetType, std::string>();
127     check_heterogeneous_bound_functions<SetType<int, TransparentLess>>();
128 }
129 
130 struct COSetTraits : OrderedMoveTraitsBase {
131     template <typename T, typename Allocator>
132     using container_type = oneapi::tbb::concurrent_set<T, std::less<T>, Allocator>;
133 
134     template <typename T>
135     using container_value_type = T;
136 
137     using init_iterator_type = move_support_tests::FooIterator;
138 }; // struct COSetTraits
139 
140 struct COMultisetTraits : OrderedMoveTraitsBase {
141     template <typename T, typename Allocator>
142     using container_type = oneapi::tbb::concurrent_multiset<T, std::less<T>, Allocator>;
143 
144     template <typename T>
145     using container_value_type = T;
146 
147     using init_iterator_type = move_support_tests::FooIterator;
148 }; // struct COMultisetTraits
149 
150 //! Testing concurrent_set member types
151 //! \brief \ref interface \ref requirement
152 TEST_CASE("concurrent_set member types") {
153     test_member_types<oneapi::tbb::concurrent_set>();
154 }
155 
156 //! Testing multithreading support in concurrent_set
157 //! \brief \ref requirement
158 TEST_CASE("concurrent_set multithreading support") {
159     test_concurrent<set_type>();
160 }
161 
162 //! Testing move constructors and assignment operator in concurrent_set
163 //! \brief \ref interface \ref requirement
164 TEST_CASE("concurrent_set move semantics support") {
165     test_rvalue_ref_support<COSetTraits>();
166 }
167 
168 //! Testing std::initializer_list constructors and modifiers in concurrent_set
169 //! \brief \ref interface \ref requirement
170 TEST_CASE("std::initializer_list support in concurrent_set") {
171     test_initializer_list_support<set_type>({1, 2, 3, 4});
172 }
173 
174 //! Testing node handling in concurrent_set
175 //! \brief \ref interface \ref requirement
176 TEST_CASE("node handling support in concurrent_set") {
177     node_handling_tests::test_node_handling_support<set_type>();
178 }
179 
180 //! Testing std::allocator_traits support in concurrent_set
181 //! \brief \ref interface \ref requirement
182 TEST_CASE("std::allocator_traits support in concurrent_set") {
183     test_allocator_traits_support<COSetTraits>();
184 }
185 
186 //! Testing heterogeneous overloads in concurrent_set
187 //! \brief \ref interface \ref requirement
188 TEST_CASE("heterogeneous overloads in concurrent_set") {
189     test_heterogeneous_functions<oneapi::tbb::concurrent_set>();
190 }
191 
192 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
193 //! Testing Class Template Argument Deduction in concurrent_set
194 //! \brief \ref interface \ref requirement
195 TEST_CASE("CTAD support in concurrent_set") {
196     test_deduction_guides<oneapi::tbb::concurrent_set>();
197 }
198 #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
199 
200 //! Testing comparison operators in concurrent_set
201 //! \brief \ref interface \ref requirement
202 TEST_CASE("test concurrent_set comparisons") {
203     test_set_comparisons<oneapi::tbb::concurrent_set>();
204 }
205 
206 //! Testing concurrent_multiset member types
207 //! \brief \ref interface \ref requirement
208 TEST_CASE("concurrent_multiset member types") {
209     test_member_types<oneapi::tbb::concurrent_multiset>();
210 }
211 
212 //! Testing requirements of concurrent_multiset
213 //! \brief \ref interface \ref requirement
214 TEST_CASE("concurrent_multiset requirements") {
215     test_basic<multiset_type>();
216 }
217 
218 //! Testing multithreading support in concurrent_multiset
219 //! \brief \ref requirement
220 TEST_CASE("concurrent_multiset multithreading support") {
221     test_concurrent<multiset_type>();
222 }
223 
224 //! Testing move constructors and assignment operator in concurrent_multiset
225 //! \brief \ref interface \ref requirement
226 TEST_CASE("concurrent_multiset multithreading support") {
227     test_rvalue_ref_support<COMultisetTraits>();
228 }
229 
230 //! Testing std::initializer_list constructors and modifiers in concurrent_multiset
231 //! \brief \ref interface \ref requirement
232 TEST_CASE("std::initializer_list support in concurrent_multimap") {
233     test_initializer_list_support<multiset_type>({1, 2, 3, 4, 4});
234 }
235 
236 //! Testing node handling support in concurrent_multiset
237 //! \brief \ref interface \ref requirement
238 TEST_CASE("node handling support in concurrent_multiset") {
239     node_handling_tests::test_node_handling_support<multiset_type>();
240 }
241 
242 //! Testing std::allocator_traits support in concurrent_multiset
243 //! \brief \ref interface \ref requirement
244 TEST_CASE("std::allocator_traits support in concurrent_multiset") {
245     test_allocator_traits_support<COMultisetTraits>();
246 }
247 
248 //! Testing heterogeneous overloads in concurrent_multiset
249 //! \brief \ref interface \ref requirement
250 TEST_CASE("heterogeneous overloads in concurrent_multiset") {
251     test_heterogeneous_functions<oneapi::tbb::concurrent_multiset>();
252 }
253 
254 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
255 //! Testing Class Template Argument Deduction in concurrent_multiset
256 //! \brief \ref interface \ref requirement
257 TEST_CASE("CTAD support in concurrent_multiset") {
258     test_deduction_guides<oneapi::tbb::concurrent_multiset>();
259 }
260 #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
261 
262 //! Testing comparison operators in concurrent_multiset
263 //! \brief \ref interface \ref requirement
264 TEST_CASE("test concurrent_set comparisons") {
265     test_set_comparisons<oneapi::tbb::concurrent_multiset>();
266 }
267 
268 //! Testing of merge operations in concurrent_set and concurrent_multiset
269 //! \brief \ref interface \ref requirement
270 TEST_CASE("merge operations") {
271     node_handling_tests::test_merge<set_type, multiset_type>(1000);
272 }
273