• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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