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