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