• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2008. 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 #ifndef BOOST_CONTAINER_PROPAGATE_ALLOCATOR_TEST_HPP
11 #define BOOST_CONTAINER_PROPAGATE_ALLOCATOR_TEST_HPP
12 
13 #include <boost/container/detail/config_begin.hpp>
14 #include <boost/core/lightweight_test.hpp>
15 #include "dummy_test_allocator.hpp"
16 
17 #include <iostream>
18 
19 namespace boost{
20 namespace container {
21 namespace test{
22 
23 template<class Selector>
24 struct alloc_propagate_base;
25 
26 template<class T, class Allocator, class Selector>
27 class alloc_propagate_wrapper
28    : public alloc_propagate_base<Selector>::template apply<T, Allocator>::type
29 {
30    BOOST_COPYABLE_AND_MOVABLE(alloc_propagate_wrapper)
31 
32    public:
33    typedef typename alloc_propagate_base
34       <Selector>::template apply<T, Allocator>::type  Base;
35 
36    typedef typename Base::allocator_type  allocator_type;
37    typedef typename Base::value_type      value_type;
38    typedef typename Base::size_type       size_type;
39 
alloc_propagate_wrapper()40    alloc_propagate_wrapper()
41       : Base()
42    {}
43 
alloc_propagate_wrapper(const allocator_type & a)44    explicit alloc_propagate_wrapper(const allocator_type &a)
45       : Base(a)
46    {}
47 /*
48    //sequence containers only
49    explicit alloc_propagate_wrapper(size_type n, const value_type &v, const allocator_type &a)
50       : Base(n, v, a)
51    {}
52 
53    alloc_propagate_wrapper(size_type n, const allocator_type &a)
54       : Base(n, a)
55    {}*/
56 
57    template<class Iterator>
alloc_propagate_wrapper(Iterator b,Iterator e,const allocator_type & a)58    alloc_propagate_wrapper(Iterator b, Iterator e, const allocator_type &a)
59       : Base(b, e, a)
60    {}
61 
62    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
alloc_propagate_wrapper(std::initializer_list<value_type> il,const allocator_type & a)63    alloc_propagate_wrapper(std::initializer_list<value_type> il, const allocator_type& a)
64       : Base(il, a)
65    {}
66 /*
67    //associative containers only
68    alloc_propagate_wrapper(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
69       : Base(il, comp, a)
70    {}*/
71 
72    #endif
73 
alloc_propagate_wrapper(const alloc_propagate_wrapper & x)74    alloc_propagate_wrapper(const alloc_propagate_wrapper &x)
75       : Base(x)
76    {}
77 
alloc_propagate_wrapper(const alloc_propagate_wrapper & x,const allocator_type & a)78    alloc_propagate_wrapper(const alloc_propagate_wrapper &x, const allocator_type &a)
79       : Base(x, a)
80    {}
81 
alloc_propagate_wrapper(BOOST_RV_REF (alloc_propagate_wrapper)x)82    alloc_propagate_wrapper(BOOST_RV_REF(alloc_propagate_wrapper) x)
83       : Base(boost::move(static_cast<Base&>(x)))
84    {}
85 
alloc_propagate_wrapper(BOOST_RV_REF (alloc_propagate_wrapper)x,const allocator_type & a)86    alloc_propagate_wrapper(BOOST_RV_REF(alloc_propagate_wrapper) x, const allocator_type &a)
87       : Base(boost::move(static_cast<Base&>(x)), a)
88    {}
89 
operator =(BOOST_COPY_ASSIGN_REF (alloc_propagate_wrapper)x)90    alloc_propagate_wrapper &operator=(BOOST_COPY_ASSIGN_REF(alloc_propagate_wrapper) x)
91    {  this->Base::operator=((const Base &)x);  return *this; }
92 
operator =(BOOST_RV_REF (alloc_propagate_wrapper)x)93    alloc_propagate_wrapper &operator=(BOOST_RV_REF(alloc_propagate_wrapper) x)
94    {  this->Base::operator=(boost::move(static_cast<Base&>(x)));  return *this; }
95 
swap(alloc_propagate_wrapper & x)96    void swap(alloc_propagate_wrapper &x)
97    {  this->Base::swap(x);  }
98 };
99 
100 template<class T>
101 struct get_real_stored_allocator
102 {
103    typedef typename T::stored_allocator_type type;
104 };
105 
106 template<class Container>
107 void test_propagate_allocator_allocator_arg();
108 
109 template<class Selector>
test_propagate_allocator()110 bool test_propagate_allocator()
111 {
112    {
113       typedef propagation_test_allocator<char, true, true, true, true, true>  AlwaysPropagate;
114       typedef alloc_propagate_wrapper<char, AlwaysPropagate, Selector>  PropagateCont;
115       typedef typename get_real_stored_allocator<typename PropagateCont::Base>::type StoredAllocator;
116       {
117          //////////////////////////////////////////
118          //Test AlwaysPropagate allocator propagation
119          //////////////////////////////////////////
120 
121          //default constructor
122          StoredAllocator::reset_unique_id(111);
123          PropagateCont c;  //stored 112
124          BOOST_TEST (c.get_stored_allocator().id_ == 112);
125          BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
126          BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
127          BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
128          BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
129          BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
130       }
131       {
132          //copy constructor
133          StoredAllocator::reset_unique_id(222);
134          PropagateCont c; //stored 223
135          BOOST_TEST (c.get_stored_allocator().id_ == 223);
136          //propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler).
137          //For allocators that copy in select_on_container_copy_construction, at least we must have a copy
138          PropagateCont c2(c); //should propagate 223
139          BOOST_TEST (c2.get_stored_allocator().id_ == 223);
140          BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 1);
141          BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
142          BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
143          BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
144          BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
145       }
146       {
147          //move constructor
148          StoredAllocator::reset_unique_id(333);
149          PropagateCont c; //stored 334
150          BOOST_TEST (c.get_stored_allocator().id_ == 334);
151          PropagateCont c2(boost::move(c)); //should propagate 334
152          BOOST_TEST (c2.get_stored_allocator().id_ == 334);
153          BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
154          BOOST_TEST (c2.get_stored_allocator().ctr_moves_ > 0);
155          BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
156          BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
157          BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
158       }
159       {
160          //copy assign
161          StoredAllocator::reset_unique_id(444);
162          PropagateCont c; //stored 445
163          BOOST_TEST (c.get_stored_allocator().id_ == 445);
164          PropagateCont c2; //stored 446
165          BOOST_TEST (c2.get_stored_allocator().id_ == 446);
166          c2 = c; //should propagate 445
167          BOOST_TEST (c2.get_stored_allocator().id_ == 445);
168          BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
169          BOOST_TEST (c2.get_stored_allocator().ctr_moves_  == 0);
170          BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 1);
171          BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
172          BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
173       }
174       {
175          //move assign
176          StoredAllocator::reset_unique_id(555);
177          PropagateCont c; //stored 556
178          BOOST_TEST (c.get_stored_allocator().id_ == 556);
179          PropagateCont c2; //stored 557
180          BOOST_TEST (c2.get_stored_allocator().id_ == 557);
181          c = boost::move(c2); //should propagate 557
182          BOOST_TEST (c.get_stored_allocator().id_ == 557);
183          BOOST_TEST (c.get_stored_allocator().ctr_copies_    == 0);
184          BOOST_TEST (c.get_stored_allocator().ctr_moves_     == 0);
185          BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
186          BOOST_TEST (c.get_stored_allocator().assign_moves_ == 1);
187          BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
188       }
189       {
190          //swap
191          StoredAllocator::reset_unique_id(666);
192          PropagateCont c; //stored 667
193          BOOST_TEST (c.get_stored_allocator().id_ == 667);
194          PropagateCont c2; //stored 668
195          BOOST_TEST (c2.get_stored_allocator().id_ == 668);
196          c.swap(c2);
197          BOOST_TEST (c2.get_stored_allocator().ctr_copies_    == 0);
198          BOOST_TEST (c.get_stored_allocator().ctr_copies_    == 0);
199          BOOST_TEST (c2.get_stored_allocator().ctr_moves_     == 0);
200          BOOST_TEST (c.get_stored_allocator().ctr_moves_     == 0);
201          BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
202          BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
203          BOOST_TEST (c2.get_stored_allocator().assign_moves_  == 0);
204          BOOST_TEST (c.get_stored_allocator().assign_moves_  == 0);
205          BOOST_TEST (c2.get_stored_allocator().swaps_  == 1);
206          BOOST_TEST (c.get_stored_allocator().swaps_  == 1);
207       }
208       //And now allocator argument constructors
209       test_propagate_allocator_allocator_arg<PropagateCont>();
210    }
211 
212    //////////////////////////////////////////
213    //Test NeverPropagate allocator propagation
214    //////////////////////////////////////////
215    {
216       typedef propagation_test_allocator<char, false, false, false, false, true> NeverPropagate;
217       typedef alloc_propagate_wrapper<char, NeverPropagate, Selector>      NoPropagateCont;
218       typedef typename get_real_stored_allocator<typename NoPropagateCont::Base>::type StoredAllocator;
219       {
220          //default constructor
221          StoredAllocator::reset_unique_id(111);
222          NoPropagateCont c; //stored 112
223          BOOST_TEST (c.get_stored_allocator().id_ == 112);
224          BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
225          BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
226          BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
227          BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
228          BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
229       }
230       {
231          //copy constructor
232          //propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler)
233          //For allocators that don't copy in select_on_container_copy_construction we must have a default
234          //construction
235          StoredAllocator::reset_unique_id(222);
236          NoPropagateCont c; //stored 223
237          BOOST_TEST (c.get_stored_allocator().id_ == 223);
238          NoPropagateCont c2(c); //should NOT propagate 223
239          BOOST_TEST (c2.get_stored_allocator().id_ == 224);
240          BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 0);
241          BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
242          BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
243          BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
244          BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
245       }
246       {
247          //move constructor
248          StoredAllocator::reset_unique_id(333);
249          NoPropagateCont c; //stored 334
250          BOOST_TEST (c.get_stored_allocator().id_ == 334);
251          NoPropagateCont c2(boost::move(c)); // should NOT propagate 334
252          BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 0);
253          BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
254          BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
255          BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
256          BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
257       }
258       {
259          //copy assign
260          StoredAllocator::reset_unique_id(444);
261          NoPropagateCont c; //stored 445
262          NoPropagateCont c2; //stored 446
263          c2 = c; // should NOT propagate 445
264          BOOST_TEST (c2.get_stored_allocator().id_ == 446);
265          BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
266          BOOST_TEST (c2.get_stored_allocator().ctr_moves_  == 0);
267          BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
268          BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
269          BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
270       }
271       {
272          //move assign
273          StoredAllocator::reset_unique_id(555);
274          NoPropagateCont c; //stored 556
275          NoPropagateCont c2; //stored 557
276          c2 = c; // should NOT propagate 556
277          BOOST_TEST (c2.get_stored_allocator().id_ == 557);
278          BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
279          BOOST_TEST (c2.get_stored_allocator().ctr_moves_  == 0);
280          BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
281          BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
282          BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
283       }
284       //And now allocator argument constructors
285       test_propagate_allocator_allocator_arg<NoPropagateCont>();
286    }
287    {
288       //Don't use unequal ids as unequal allocators -------------------------|,
289       //because swap requires equal allocators                               v
290       typedef propagation_test_allocator<char, false, false, false, false, false> NeverPropagate;
291       typedef alloc_propagate_wrapper<char, NeverPropagate, Selector>      NoPropagateCont;
292       typedef typename get_real_stored_allocator<typename NoPropagateCont::Base>::type StoredAllocator;
293       {
294          //swap
295          StoredAllocator::reset_unique_id(666);
296          NoPropagateCont c; //stored 667
297          BOOST_TEST (c.get_stored_allocator().id_ == 667);
298          NoPropagateCont c2; //stored 668
299          BOOST_TEST (c2.get_stored_allocator().id_ == 668);
300          c2.swap(c); // should NOT swap 667 and 668
301          BOOST_TEST (c2.get_stored_allocator().id_ == 668);
302          BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
303          BOOST_TEST (c2.get_stored_allocator().ctr_moves_  == 0);
304          BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
305          BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
306          BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
307          BOOST_TEST (c.get_stored_allocator().id_ == 667);
308          BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
309          BOOST_TEST (c.get_stored_allocator().ctr_moves_  == 0);
310          BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
311          BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
312          BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
313       }
314    }
315 
316    return report_errors() == 0;
317 }
318 
319 template<class Container>
test_propagate_allocator_allocator_arg()320 void test_propagate_allocator_allocator_arg()
321 {
322    typedef typename Container::allocator_type         allocator_type;
323    typedef typename get_real_stored_allocator<typename Container::Base>::type StoredAllocator;
324 
325    {  //The allocator must be always propagated
326       //allocator constructor
327       allocator_type::reset_unique_id(111);
328       const allocator_type & a = allocator_type(); //stored 112
329       Container c(a); //should propagate 112
330       BOOST_TEST (c.get_stored_allocator().id_ == 112);
331       BOOST_TEST (c.get_stored_allocator().ctr_copies_ > 0);
332       BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
333       BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
334       BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
335       BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
336    }
337    {
338       //copy allocator constructor
339       StoredAllocator::reset_unique_id(999);
340       Container c;
341       //stored_allocator_type could be the same type as allocator_type
342       //so reset it again to get a predictable result
343       allocator_type::reset_unique_id(222);
344       Container c2(c, allocator_type()); //should propagate 223
345       BOOST_TEST (c2.get_stored_allocator().id_ == 223);
346       BOOST_TEST (c2.get_stored_allocator().ctr_copies_ > 0);
347       BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
348       BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
349       BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
350       BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
351    }
352    {
353       //move allocator constructor
354       StoredAllocator::reset_unique_id(999);
355       Container c;
356       //stored_allocator_type could be the same type as allocator_type
357       //so reset it again to get a predictable result
358       allocator_type::reset_unique_id(333);
359       Container c2(boost::move(c), allocator_type()); //should propagate 334
360       BOOST_TEST (c2.get_stored_allocator().id_ == 334);
361       BOOST_TEST (c2.get_stored_allocator().ctr_copies_ > 0);
362       BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
363       BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
364       BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
365       BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
366    }
367 }
368 
369 }  //namespace test{
370 }  //namespace container {
371 }  //namespace boost{
372 
373 #include <boost/container/detail/config_end.hpp>
374 
375 #endif   //#ifndef BOOST_CONTAINER_PROPAGATE_ALLOCATOR_TEST_HPP
376