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
19namespace boost{
20namespace container {
21namespace test{
22
23template<class Selector>
24struct alloc_propagate_base;
25
26template<class T, class Allocator, class Selector>
27class 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
40 alloc_propagate_wrapper()
41 : Base()
42 {}
43
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>
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)
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
74 alloc_propagate_wrapper(const alloc_propagate_wrapper &x)
75 : Base(x)
76 {}
77
78 alloc_propagate_wrapper(const alloc_propagate_wrapper &x, const allocator_type &a)
79 : Base(x, a)
80 {}
81
82 alloc_propagate_wrapper(BOOST_RV_REF(alloc_propagate_wrapper) x)
83 : Base(boost::move(static_cast<Base&>(x)))
84 {}
85
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
90 alloc_propagate_wrapper &operator=(BOOST_COPY_ASSIGN_REF(alloc_propagate_wrapper) x)
91 { this->Base::operator=((const Base &)x); return *this; }
92
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
96 void swap(alloc_propagate_wrapper &x)
97 { this->Base::swap(x); }
98};
99
100template<class T>
101struct get_real_stored_allocator
102{
103 typedef typename T::stored_allocator_type type;
104};
105
106template<class Container>
107void test_propagate_allocator_allocator_arg();
108
109template<class Selector>
110bool 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
319template<class Container>
320void 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

source code of boost/libs/container/test/propagate_allocator_test.hpp