1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // (C) Copyright Ion Gaztanaga 2004-2013. Distributed under the Boost |
4 | // Software License, Version 1.0. (See accompanying file |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | // |
7 | // See http://www.boost.org/libs/container for documentation. |
8 | // |
9 | ////////////////////////////////////////////////////////////////////////////// |
10 | #include <memory> |
11 | #include <deque> |
12 | #include <iostream> |
13 | #include <list> |
14 | |
15 | #include <boost/container/deque.hpp> |
16 | #include <boost/container/allocator.hpp> |
17 | |
18 | #include "print_container.hpp" |
19 | #include "check_equal_containers.hpp" |
20 | #include "dummy_test_allocator.hpp" |
21 | #include "movable_int.hpp" |
22 | #include <boost/move/utility_core.hpp> |
23 | #include <boost/move/iterator.hpp> |
24 | #include <boost/container/detail/mpl.hpp> |
25 | #include <boost/container/detail/type_traits.hpp> |
26 | #include <string> |
27 | #include "emplace_test.hpp" |
28 | #include "propagate_allocator_test.hpp" |
29 | #include "vector_test.hpp" |
30 | #include "default_init_test.hpp" |
31 | #include "../../intrusive/test/iterator_test.hpp" |
32 | |
33 | using namespace boost::container; |
34 | |
35 | //Function to check if both sets are equal |
36 | template<class V1, class V2> |
37 | bool deque_copyable_only(V1 &, V2 &, dtl::false_type) |
38 | { |
39 | return true; |
40 | } |
41 | |
42 | //Function to check if both sets are equal |
43 | template<class V1, class V2> |
44 | bool deque_copyable_only(V1 &cntdeque, V2 &stddeque, dtl::true_type) |
45 | { |
46 | typedef typename V1::value_type IntType; |
47 | std::size_t size = cntdeque.size(); |
48 | stddeque.insert(stddeque.end(), 50u, 1); |
49 | cntdeque.insert(cntdeque.end(), 50u, IntType(1)); |
50 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
51 | { |
52 | IntType move_me(1); |
53 | stddeque.insert(stddeque.begin()+std::ptrdiff_t(size)/2, 50u, 1); |
54 | cntdeque.insert(cntdeque.begin()+std::ptrdiff_t(size/2), 50u, boost::move(move_me)); |
55 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
56 | } |
57 | { |
58 | IntType move_me(2); |
59 | cntdeque.assign(cntdeque.size()/2, boost::move(move_me)); |
60 | stddeque.assign(stddeque.size()/2, 2); |
61 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
62 | } |
63 | { |
64 | IntType move_me(1); |
65 | stddeque.clear(); |
66 | cntdeque.clear(); |
67 | stddeque.insert(stddeque.begin(), 50u, 1); |
68 | cntdeque.insert(cntdeque.begin(), 50u, boost::move(move_me)); |
69 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
70 | stddeque.insert(stddeque.begin()+20, 50u, 1); |
71 | cntdeque.insert(cntdeque.begin()+20, 50u, boost::move(move_me)); |
72 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
73 | stddeque.insert(stddeque.begin()+20, 20u, 1); |
74 | cntdeque.insert(cntdeque.begin()+20, 20u, boost::move(move_me)); |
75 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
76 | } |
77 | { |
78 | IntType move_me(1); |
79 | stddeque.clear(); |
80 | cntdeque.clear(); |
81 | stddeque.insert(stddeque.end(), 50u, 1); |
82 | cntdeque.insert(cntdeque.end(), 50u, boost::move(move_me)); |
83 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
84 | stddeque.insert(stddeque.end()-20, 50u, 1); |
85 | cntdeque.insert(cntdeque.end()-20, 50u, boost::move(move_me)); |
86 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
87 | stddeque.insert(stddeque.end()-20, 20u, 1); |
88 | cntdeque.insert(cntdeque.end()-20, 20u, boost::move(move_me)); |
89 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
90 | } |
91 | |
92 | return true; |
93 | } |
94 | |
95 | //Test recursive structures |
96 | class recursive_deque |
97 | { |
98 | public: |
99 | |
100 | recursive_deque (const recursive_deque &x) |
101 | : deque_(x.deque_) |
102 | {} |
103 | |
104 | recursive_deque & operator=(const recursive_deque &x) |
105 | { this->deque_ = x.deque_; return *this; } |
106 | |
107 | int id_; |
108 | deque<recursive_deque> deque_; |
109 | deque<recursive_deque>::iterator it_; |
110 | deque<recursive_deque>::const_iterator cit_; |
111 | deque<recursive_deque>::reverse_iterator rit_; |
112 | deque<recursive_deque>::const_reverse_iterator crit_; |
113 | }; |
114 | |
115 | template<class IntType> |
116 | bool do_test() |
117 | { |
118 | //Test for recursive types |
119 | { |
120 | deque<recursive_deque> recursive_deque_deque; |
121 | } |
122 | |
123 | { |
124 | //Now test move semantics |
125 | deque<recursive_deque> original; |
126 | deque<recursive_deque> move_ctor(boost::move(t&: original)); |
127 | deque<recursive_deque> move_assign; |
128 | move_assign = boost::move(t&: move_ctor); |
129 | move_assign.swap(x&: original); |
130 | } |
131 | |
132 | //Alias deque types |
133 | typedef deque<IntType> MyCntDeque; |
134 | typedef std::deque<int> MyStdDeque; |
135 | const int max = 100; |
136 | { |
137 | ::boost::movelib::unique_ptr<MyCntDeque> const pcntdeque = ::boost::movelib::make_unique<MyCntDeque>(); |
138 | ::boost::movelib::unique_ptr<MyStdDeque> const pstddeque = ::boost::movelib::make_unique<MyStdDeque>(); |
139 | MyCntDeque &cntdeque = *pcntdeque; |
140 | MyStdDeque &stddeque = *pstddeque; |
141 | for(int i = 0; i < max*100; ++i){ |
142 | IntType move_me(i); |
143 | cntdeque.insert(cntdeque.end(), boost::move(move_me)); |
144 | stddeque.insert(position: stddeque.end(), x: i); |
145 | } |
146 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
147 | |
148 | cntdeque.clear(); |
149 | stddeque.clear(); |
150 | |
151 | for(int i = 0; i < max*100; ++i){ |
152 | IntType move_me(i); |
153 | cntdeque.push_back(boost::move(move_me)); |
154 | stddeque.push_back(x: i); |
155 | } |
156 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
157 | |
158 | cntdeque.clear(); |
159 | stddeque.clear(); |
160 | |
161 | for(int i = 0; i < max*100; ++i){ |
162 | IntType move_me(i); |
163 | cntdeque.push_front(boost::move(move_me)); |
164 | stddeque.push_front(x: i); |
165 | } |
166 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
167 | |
168 | typename MyCntDeque::iterator it; |
169 | typename MyCntDeque::const_iterator cit = it; |
170 | (void)cit; |
171 | |
172 | cntdeque.erase(cntdeque.begin()++); |
173 | stddeque.erase(position: stddeque.begin()++); |
174 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
175 | |
176 | cntdeque.erase(cntdeque.begin()); |
177 | stddeque.erase(position: stddeque.begin()); |
178 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
179 | |
180 | { |
181 | //Initialize values |
182 | IntType aux_vect[50]; |
183 | for(int i = 0; i < 50; ++i){ |
184 | IntType move_me (-1); |
185 | aux_vect[i] = boost::move(move_me); |
186 | } |
187 | int aux_vect2[50]; |
188 | for(int i = 0; i < 50; ++i){ |
189 | aux_vect2[i] = -1; |
190 | } |
191 | |
192 | cntdeque.insert(cntdeque.end() |
193 | ,boost::make_move_iterator(&aux_vect[0]) |
194 | ,boost::make_move_iterator(aux_vect + 50)); |
195 | stddeque.insert(position: stddeque.end(), first: aux_vect2, last: aux_vect2 + 50); |
196 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
197 | |
198 | for(int i = 0; i < 50; ++i){ |
199 | IntType move_me (i); |
200 | aux_vect[i] = boost::move(move_me); |
201 | } |
202 | for(int i = 0; i < 50; ++i){ |
203 | aux_vect2[i] = i; |
204 | } |
205 | |
206 | cntdeque.insert(cntdeque.begin()+std::ptrdiff_t(cntdeque.size()) |
207 | ,boost::make_move_iterator(&aux_vect[0]) |
208 | ,boost::make_move_iterator(aux_vect + 50)); |
209 | stddeque.insert(position: stddeque.begin()+std::ptrdiff_t(stddeque.size()), first: aux_vect2, last: aux_vect2 + 50); |
210 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
211 | |
212 | for(int i = 0, j = static_cast<int>(cntdeque.size()); i < j; ++i){ |
213 | cntdeque.erase(cntdeque.begin()); |
214 | stddeque.erase(position: stddeque.begin()); |
215 | } |
216 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
217 | } |
218 | { |
219 | IntType aux_vect[50]; |
220 | for(int i = 0; i < 50; ++i){ |
221 | IntType move_me(-1); |
222 | aux_vect[i] = boost::move(move_me); |
223 | } |
224 | int aux_vect2[50]; |
225 | for(int i = 0; i < 50; ++i){ |
226 | aux_vect2[i] = -1; |
227 | } |
228 | cntdeque.insert(cntdeque.begin() |
229 | ,boost::make_move_iterator(&aux_vect[0]) |
230 | ,boost::make_move_iterator(aux_vect + 50)); |
231 | stddeque.insert(position: stddeque.begin(), first: aux_vect2, last: aux_vect2 + 50); |
232 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
233 | } |
234 | |
235 | if(!deque_copyable_only(cntdeque, stddeque |
236 | ,dtl::bool_<boost::container::test::is_copyable<IntType>::value>())){ |
237 | return false; |
238 | } |
239 | |
240 | cntdeque.erase(cntdeque.begin()); |
241 | stddeque.erase(position: stddeque.begin()); |
242 | |
243 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
244 | |
245 | for(int i = 0; i < max; ++i){ |
246 | IntType move_me(i); |
247 | cntdeque.insert(cntdeque.begin(), boost::move(move_me)); |
248 | stddeque.insert(position: stddeque.begin(), x: i); |
249 | } |
250 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; |
251 | |
252 | //Test insertion from list |
253 | { |
254 | std::list<int> l(50, int(1)); |
255 | cntdeque.insert(cntdeque.begin(), l.begin(), l.end()); |
256 | stddeque.insert(position: stddeque.begin(), first: l.begin(), last: l.end()); |
257 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; |
258 | cntdeque.assign(l.begin(), l.end()); |
259 | stddeque.assign(first: l.begin(), last: l.end()); |
260 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; |
261 | } |
262 | |
263 | cntdeque.resize(100); |
264 | stddeque.resize(new_size: 100); |
265 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; |
266 | |
267 | cntdeque.resize(200); |
268 | stddeque.resize(new_size: 200); |
269 | if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; |
270 | } |
271 | |
272 | #ifndef BOOST_CONTAINER_NO_CXX17_CTAD |
273 | //Check Constructor Template Auto Deduction |
274 | { |
275 | auto gold = MyStdDeque{ 1, 2, 3 }; |
276 | auto test = deque(gold.begin(), gold.end()); |
277 | if(!test::CheckEqualContainers(cont_a: gold, cont_b: test)) return false; |
278 | } |
279 | { |
280 | auto gold = MyStdDeque{ 1, 2, 3 }; |
281 | auto test = deque(gold.begin(), gold.end(), new_allocator<int>()); |
282 | if(!test::CheckEqualContainers(cont_a: gold, cont_b: test)) return false; |
283 | } |
284 | #endif |
285 | |
286 | std::cout << std::endl << "Test OK!" << std::endl; |
287 | return true; |
288 | } |
289 | |
290 | template<class VoidAllocator> |
291 | struct GetAllocatorCont |
292 | { |
293 | template<class ValueType> |
294 | struct apply |
295 | { |
296 | typedef deque< ValueType |
297 | , typename allocator_traits<VoidAllocator> |
298 | ::template portable_rebind_alloc<ValueType>::type |
299 | > type; |
300 | }; |
301 | }; |
302 | |
303 | template<class VoidAllocator> |
304 | int test_cont_variants() |
305 | { |
306 | typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont; |
307 | typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont; |
308 | typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont; |
309 | typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont; |
310 | |
311 | if(test::vector_test<MyCont>()) |
312 | return 1; |
313 | if(test::vector_test<MyMoveCont>()) |
314 | return 1; |
315 | if(test::vector_test<MyCopyMoveCont>()) |
316 | return 1; |
317 | if(test::vector_test<MyCopyCont>()) |
318 | return 1; |
319 | return 0; |
320 | } |
321 | |
322 | struct boost_container_deque; |
323 | |
324 | namespace boost { namespace container { namespace test { |
325 | |
326 | template<> |
327 | struct alloc_propagate_base<boost_container_deque> |
328 | { |
329 | template <class T, class Allocator> |
330 | struct apply |
331 | { |
332 | typedef boost::container::deque<T, Allocator> type; |
333 | }; |
334 | }; |
335 | |
336 | }}} //namespace boost::container::test |
337 | |
338 | int main () |
339 | { |
340 | if(!do_test<int>()) |
341 | return 1; |
342 | |
343 | if(!do_test<test::movable_int>()) |
344 | return 1; |
345 | |
346 | if(!do_test<test::movable_and_copyable_int>()) |
347 | return 1; |
348 | |
349 | if(!do_test<test::copyable_int>()) |
350 | return 1; |
351 | |
352 | //Test non-copy-move operations |
353 | { |
354 | deque<test::non_copymovable_int> d; |
355 | d.emplace_back(); |
356 | d.emplace_front(args: 1); |
357 | d.resize(new_size: 10); |
358 | d.resize(new_size: 1); |
359 | } |
360 | |
361 | //////////////////////////////////// |
362 | // Allocator implementations |
363 | //////////////////////////////////// |
364 | // std:allocator |
365 | if(test_cont_variants< std::allocator<void> >()){ |
366 | std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl; |
367 | return 1; |
368 | } |
369 | // boost::container::allocator |
370 | if(test_cont_variants< allocator<void> >()){ |
371 | std::cerr << "test_cont_variants< allocator<void> > failed" << std::endl; |
372 | return 1; |
373 | } |
374 | //////////////////////////////////// |
375 | // Default init test |
376 | //////////////////////////////////// |
377 | if(!test::default_init_test< deque<int, test::default_init_allocator<int> > >()){ |
378 | std::cerr << "Default init test failed" << std::endl; |
379 | return 1; |
380 | } |
381 | |
382 | //////////////////////////////////// |
383 | // Emplace testing |
384 | //////////////////////////////////// |
385 | const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE); |
386 | |
387 | if(!boost::container::test::test_emplace |
388 | < deque<test::EmplaceInt>, Options>()) |
389 | return 1; |
390 | //////////////////////////////////// |
391 | // Allocator propagation testing |
392 | //////////////////////////////////// |
393 | if(!boost::container::test::test_propagate_allocator<boost_container_deque>()) |
394 | return 1; |
395 | |
396 | //////////////////////////////////// |
397 | // Initializer lists testing |
398 | //////////////////////////////////// |
399 | if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for |
400 | < boost::container::deque<int> >()) { |
401 | return 1; |
402 | } |
403 | |
404 | //////////////////////////////////// |
405 | // Iterator testing |
406 | //////////////////////////////////// |
407 | { |
408 | typedef boost::container::deque<int> cont_int; |
409 | cont_int a; a.push_back(x: 0); a.push_back(x: 1); a.push_back(x: 2); |
410 | boost::intrusive::test::test_iterator_random< cont_int >(c&: a); |
411 | if(boost::report_errors() != 0) { |
412 | return 1; |
413 | } |
414 | } |
415 | |
416 | //////////////////////////////////// |
417 | // has_trivial_destructor_after_move testing |
418 | //////////////////////////////////// |
419 | // default allocator |
420 | { |
421 | typedef boost::container::deque<int> cont; |
422 | typedef cont::allocator_type allocator_type; |
423 | typedef boost::container::allocator_traits<allocator_type>::pointer pointer; |
424 | BOOST_CONTAINER_STATIC_ASSERT_MSG(!(boost::has_trivial_destructor_after_move<cont>::value != |
425 | boost::has_trivial_destructor_after_move<allocator_type>::value && |
426 | boost::has_trivial_destructor_after_move<pointer>::value) |
427 | , "has_trivial_destructor_after_move(std::allocator) test failed" ); |
428 | } |
429 | // std::allocator |
430 | { |
431 | typedef boost::container::deque<int, std::allocator<int> > cont; |
432 | typedef cont::allocator_type allocator_type; |
433 | typedef boost::container::allocator_traits<allocator_type>::pointer pointer; |
434 | BOOST_CONTAINER_STATIC_ASSERT_MSG(!(boost::has_trivial_destructor_after_move<cont>::value != |
435 | boost::has_trivial_destructor_after_move<allocator_type>::value && |
436 | boost::has_trivial_destructor_after_move<pointer>::value) |
437 | , "has_trivial_destructor_after_move(std::allocator) test failed" ); |
438 | } |
439 | |
440 | return 0; |
441 | } |
442 | |