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
33using namespace boost::container;
34
35//Function to check if both sets are equal
36template<class V1, class V2>
37bool deque_copyable_only(V1 &, V2 &, dtl::false_type)
38{
39 return true;
40}
41
42//Function to check if both sets are equal
43template<class V1, class V2>
44bool 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
96class recursive_deque
97{
98public:
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
115template<class IntType>
116bool 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
290template<class VoidAllocator>
291struct 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
303template<class VoidAllocator>
304int 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
322struct boost_container_deque;
323
324namespace boost { namespace container { namespace test {
325
326template<>
327struct 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
338int 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

source code of boost/libs/container/test/deque_test.cpp