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 "oneapi/tbb/concurrent_map.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_map.cpp
28 //! \brief Test for [containers.concurrent_map containers.concurrent_multimap] specifications
29 
30 template <typename... Args>
31 struct AllowMultimapping<oneapi::tbb::concurrent_multimap<Args...>> : std::true_type {};
32 
33 template <typename Key, typename Mapped>
34 using Allocator = LocalCountingAllocator<std::allocator<std::pair<const Key, Mapped>>>;
35 
36 using map_type = oneapi::tbb::concurrent_map<int, int, std::less<int>, Allocator<int, int>>;
37 using multimap_type = oneapi::tbb::concurrent_multimap<int, int, std::less<int>, Allocator<int, int>>;
38 
39 template <>
40 struct SpecialTests<map_type> {
41     static void Test() {
42         SpecialMapTests<map_type>();
43     }
44 };
45 
46 template <>
47 struct SpecialTests<multimap_type> {
48     static void Test() {
49         SpecialMultiMapTests<multimap_type>();
50     }
51 };
52 
53 template <template <typename...> class ContainerType>
54 void test_member_types() {
55     using default_container_type = ContainerType<int, int>;
56     static_assert(std::is_same<typename default_container_type::key_compare, std::less<int>>::value,
57                   "Incorrect default template comparator");
58     static_assert(std::is_same<typename default_container_type::allocator_type, oneapi::tbb::tbb_allocator<std::pair<const int, int>>>::value,
59                   "Incorrect default template allocator");
60 
61     auto test_comparator = [](const int&, const int&)->bool { return true; };
62     using test_allocator_type = std::allocator<std::pair<const int, int>>;
63 
64     using container_type = ContainerType<int, int, decltype(test_comparator), test_allocator_type>;
65 
66     static_assert(std::is_same<typename container_type::key_type, int>::value,
67                   "Incorrect container key_type member type");
68     static_assert(std::is_same<typename container_type::mapped_type, int>::value,
69                   "Incorrect container mapped_type member type");
70     static_assert(std::is_same<typename container_type::value_type, std::pair<const int, int>>::value,
71                   "Incorrect container value_type member type");
72 
73     static_assert(std::is_unsigned<typename container_type::size_type>::value,
74                   "Incorrect container size_type member type");
75     static_assert(std::is_signed<typename container_type::difference_type>::value,
76                   "Incorrect container difference_type member type");
77 
78     static_assert(std::is_same<typename container_type::key_compare, decltype(test_comparator)>::value,
79                   "Incorrect container key_compare member type");
80     static_assert(std::is_same<typename container_type::allocator_type, test_allocator_type>::value,
81                   "Incorrect container allocator_type member type");
82 
83     using value_type = typename container_type::value_type;
84     static_assert(std::is_same<typename container_type::reference, value_type&>::value,
85                   "Incorrect container reference member type");
86     static_assert(std::is_same<typename container_type::const_reference, const value_type&>::value,
87                   "Incorrect container const_reference member type");
88     using allocator_type = typename container_type::allocator_type;
89     static_assert(std::is_same<typename container_type::pointer, typename std::allocator_traits<allocator_type>::pointer>::value,
90                   "Incorrect container pointer member type");
91     static_assert(std::is_same<typename container_type::const_pointer, typename std::allocator_traits<allocator_type>::const_pointer>::value,
92                   "Incorrect container const_pointer member type");
93 
94     static_assert(utils::is_forward_iterator<typename container_type::iterator>::value,
95                   "Incorrect container iterator member type");
96     static_assert(!std::is_const<typename container_type::iterator::value_type>::value,
97                   "Incorrect container iterator member type");
98     static_assert(utils::is_forward_iterator<typename container_type::const_iterator>::value,
99                   "Incorrect container const_iterator member type");
100     static_assert(std::is_const<typename container_type::const_iterator::value_type>::value,
101                   "Incorrect container const_iterator member type");
102 }
103 
104 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
105 template <template <typename...> typename TMap>
106 void test_deduction_guides() {
107     std::vector<std::pair<int, int>> v(10, {0, 0});
108     TMap map(v.begin(), v.end());
109     static_assert(std::is_same_v<decltype(map), TMap<int, int> >, "WRONG\n");
110 
111     std::greater<int> compare;
112     std::allocator<std::pair<const int, int>> allocator;
113     TMap map2(v.begin(), v.end(), compare);
114     static_assert(std::is_same_v<decltype(map2), TMap<int, int, decltype(compare)> >, "WRONG\n");
115 
116     TMap map3(v.begin(), v.end(), allocator);
117     static_assert(std::is_same_v<decltype(map3), TMap<int, int, std::less<int>, decltype(allocator)> >, "WRONG\n");
118 
119     TMap map4(v.begin(), v.end(), compare, allocator);
120     static_assert(std::is_same_v<decltype(map4), TMap<int, int, decltype(compare), decltype(allocator)> >, "WRONG\n");
121 
122     using pair_t = std::pair<const int, int>;
123     auto init = { pair_t{1, 1}, pair_t{2, 2}, pair_t{3, 3} };
124     TMap map5(init);
125     static_assert(std::is_same_v<decltype(map5), TMap<int, int> >, "WRONG\n");
126 
127     TMap map6(init, compare);
128     static_assert(std::is_same_v<decltype(map6), TMap<int, int, decltype(compare)> >, "WRONG\n");
129 
130     TMap map7(init, allocator);
131     static_assert(std::is_same_v<decltype(map7), TMap<int, int, std::less<int>, decltype(allocator)> >, "WRONG\n");
132 
133     TMap map8(init, compare, allocator);
134     static_assert(std::is_same_v<decltype(map8), TMap<int, int, decltype(compare), decltype(allocator)> >, "WRONG\n");
135 }
136 #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
137 
138 template <template <typename...> class MapType>
139 void test_heterogeneous_functions() {
140     check_heterogeneous_functions_key_int<MapType, int, int>();
141     check_heterogeneous_functions_key_string<MapType, std::string, std::string>();
142     check_heterogeneous_bound_functions<MapType<int, int, TransparentLess>>();
143 }
144 
145 struct COMapTraits : OrderedMoveTraitsBase {
146     template <typename T, typename Allocator>
147     using container_type = oneapi::tbb::concurrent_map<T, T, std::less<T>, Allocator>;
148 
149     template <typename T>
150     using container_value_type = std::pair<const T, T>;
151 
152     using init_iterator_type = move_support_tests::FooPairIterator;
153 }; // struct COMapTraits
154 
155 struct COMultimapTraits : OrderedMoveTraitsBase {
156     template <typename T, typename Allocator>
157     using container_type = oneapi::tbb::concurrent_multimap<T, T, std::less<T>, Allocator>;
158 
159     template <typename T>
160     using container_value_type = std::pair<const T, T>;
161 
162     using init_iterator_type = move_support_tests::FooPairIterator;
163 }; // struct COMultimapTraits
164 
165 //! Testing concurrent_map member types
166 //! \brief \ref interface \ref requirement
167 TEST_CASE("concurrent_map member types") {
168     test_member_types<oneapi::tbb::concurrent_map>();
169 }
170 
171 //! Testing requirements of concurrent_map
172 //! \brief \ref interface \ref requirement
173 TEST_CASE("concurrent_map requirements") {
174     test_basic<map_type>();
175 }
176 
177 //! Testing multithreading support in concurrent_map
178 //! \brief \ref requirement
179 TEST_CASE("concurrent_map multithreading support") {
180     test_concurrent<map_type>();
181 }
182 
183 //! Testing move constructors and assignment operator in concurrent_map
184 //! \brief \ref interface \ref requirement
185 TEST_CASE("concurrent_map move semantics support") {
186     test_rvalue_ref_support<COMapTraits>();
187 }
188 
189 //! Testing std::initializer_list constructors and modifiers in concurrent_map
190 //! \brief \ref interface \ref requirement
191 TEST_CASE("std::initializer_list support in concurrent_map") {
192     test_initializer_list_support<map_type>({{1, 1}, {2, 2}, {3, 3}, {4, 4}});
193 }
194 
195 //! Testing node handling in concurrent_map
196 //! \brief \ref interface \ref requirement
197 TEST_CASE("node handling support in concurrent_map") {
198     node_handling_tests::test_node_handling_support<map_type>();
199 }
200 
201 //! Testing std::allocator_traits support in concurrent_map
202 //! \brief \ref interface \ref requirement
203 TEST_CASE("std::allocator_traits support in concurrent_map") {
204     test_allocator_traits_support<COMapTraits>();
205 }
206 
207 //! Testing heterogeneous overloads in concurrent_map
208 //! \brief \ref interface \ref requirement
209 TEST_CASE("heterogeneous overloads in concurrent_map") {
210     test_heterogeneous_functions<oneapi::tbb::concurrent_map>();
211 }
212 
213 //! Testing insert overloads with generic pair in concurrent_map
214 //! \brief \ref interface \ref requirement
215 TEST_CASE("insertion by generic pair in concurrent_map") {
216     test_insert_by_generic_pair<oneapi::tbb::concurrent_map>();
217 }
218 
219 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
220 //! Testing Class Template Argument Deduction in concurrent_map
221 //! \brief \ref interface \ref requirement
222 TEST_CASE("CTAD support in concurrent_map") {
223     test_deduction_guides<oneapi::tbb::concurrent_map>();
224 }
225 #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
226 
227 //! Testing comparison operators in concurrent_map
228 //! \brief \ref interface \ref requirement
229 TEST_CASE("test concurrent_map comparisons") {
230     test_map_comparisons<oneapi::tbb::concurrent_map>();
231 }
232 
233 //! Testing concurrent_multimap member types
234 //! \brief \ref interface \ref requirement
235 TEST_CASE("concurrent_multimap member types") {
236     test_member_types<oneapi::tbb::concurrent_multimap>();
237 }
238 
239 //! Testing requirements of concurrent_multimap
240 //! \brief \ref interface \ref requirement
241 TEST_CASE("concurrent_multimap requirements") {
242     test_basic<multimap_type>();
243 }
244 
245 //! Testing multithreading support in concurrent_multimap
246 //! \brief \ref requirement
247 TEST_CASE("concurrent_multimap multithreading support") {
248     test_concurrent<multimap_type>();
249 }
250 
251 //! Testing move constructors and assignment operator in concurrent_multimap
252 //! \brief \ref interface \ref requirement
253 TEST_CASE("concurrent_multimap multithreading support") {
254     test_rvalue_ref_support<COMultimapTraits>();
255 }
256 
257 //! Testing std::initializer_list constructors and modifiers in concurrent_multimap
258 //! \brief \ref interface \ref requirement
259 TEST_CASE("std::initializer_list support in concurrent_multimap") {
260     test_initializer_list_support<multimap_type>({{1, 1}, {2, 2}, {3, 3}, {4, 4}, {4, 40}});
261 }
262 
263 //! Testing node handling support in concurrent_multimap
264 //! \brief \ref interface \ref requirement
265 TEST_CASE("node handling support in concurrent_multimap") {
266     node_handling_tests::test_node_handling_support<multimap_type>();
267 }
268 
269 //! Testing std::allocator_traits support in concurrent_multimap
270 //! \brief \ref interface \ref requirement
271 TEST_CASE("std::allocator_traits support in concurrent_multimap") {
272     test_allocator_traits_support<COMultimapTraits>();
273 }
274 
275 //! Testing heterogeneous overloads in concurrent_multimap
276 //! \brief \ref interface \ref requirement
277 TEST_CASE("heterogeneous overloads in concurrent_multimap") {
278     test_heterogeneous_functions<oneapi::tbb::concurrent_multimap>();
279 }
280 
281 //! Testing insert overloads with generic pair in concurrent_multimap
282 //! \brief \ref interface \ref requirement
283 TEST_CASE("insertion by generic pair in concurrent_multimap") {
284     test_insert_by_generic_pair<oneapi::tbb::concurrent_multimap>();
285 }
286 
287 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
288 //! Testing Class Template Argument Deduction in concurrent_multimap
289 //! \brief \ref interface \ref requirement
290 TEST_CASE("CTAD support in concurrent_multimap") {
291     test_deduction_guides<oneapi::tbb::concurrent_multimap>();
292 }
293 #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
294 
295 //! Testing comparison operators in concurrent_multimap
296 //! \brief \ref interface \ref requirement
297 TEST_CASE("test concurrent_multimap comparisons") {
298     test_map_comparisons<oneapi::tbb::concurrent_multimap>();
299 }
300 
301 //! Testing of merge operations in concurrent_map and concurrent_multimap
302 //! \brief \ref interface \ref requirement
303 TEST_CASE("merge operations") {
304     node_handling_tests::test_merge<map_type, multimap_type>(1000);
305 }
306