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