• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Howard Hinnant 2009
4 // (C) Copyright Ion Gaztanaga 2014-2014.
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // (See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 //
10 // See http://www.boost.org/libs/move for documentation.
11 //
12 //////////////////////////////////////////////////////////////////////////////
13 #include <boost/move/utility_core.hpp>
14 #include <boost/move/unique_ptr.hpp>
15 #include <boost/static_assert.hpp>
16 #include <boost/core/lightweight_test.hpp>
17 
18 //////////////////////////////////////////////
19 //
20 // The initial implementation of these tests
21 // was written by Howard Hinnant.
22 //
23 // These test were later refactored grouping
24 // and porting them to Boost.Move.
25 //
26 // Many thanks to Howard for releasing his C++03
27 // unique_ptr implementation with such detailed
28 // test cases.
29 //
30 //////////////////////////////////////////////
31 
32 #include "unique_ptr_test_utils_beg.hpp"
33 
34 namespace bml = ::boost::movelib;
35 namespace bmupmu = ::boost::move_upmu;
36 
37 ////////////////////////////////
38 //   unique_ptr_ctor_move_defdel
39 ////////////////////////////////
40 
41 namespace unique_ptr_ctor_move_defdel{
42 
43 // test converting move ctor.  Should only require a MoveConstructible deleter, or if
44 //    deleter is a reference, not even that.
45 
test()46 void test()
47 {
48    //Single unique_ptr
49    reset_counters();
50    {
51    bml::unique_ptr<A> s(new A);
52    A* p = s.get();
53    bml::unique_ptr<A> s2(boost::move(s));
54    BOOST_TEST(s2.get() == p);
55    BOOST_TEST(s.get() == 0);
56    BOOST_TEST(A::count == 1);
57    }
58    BOOST_TEST(A::count == 0);
59    //Unbounded array unique_ptr
60    reset_counters();
61    {
62    bml::unique_ptr<A[]> s(new A[2]);
63    A* p = s.get();
64    bml::unique_ptr<A[]> s2(boost::move(s));
65    BOOST_TEST(s2.get() == p);
66    BOOST_TEST(s.get() == 0);
67    BOOST_TEST(A::count == 2);
68    }
69    BOOST_TEST(A::count == 0);
70    //Bounded array unique_ptr
71    reset_counters();
72    {
73    bml::unique_ptr<A[2]> s(new A[2]);
74    A* p = s.get();
75    bml::unique_ptr<A[2]> s2(boost::move(s));
76    BOOST_TEST(s2.get() == p);
77    BOOST_TEST(s.get() == 0);
78    BOOST_TEST(A::count == 2);
79    }
80    BOOST_TEST(A::count == 0);
81 }
82 
83 }  //namespace unique_ptr_ctor_move_defdel{
84 
85 ////////////////////////////////
86 //   unique_ptr_ctor_move_movedel
87 ////////////////////////////////
88 
89 namespace unique_ptr_ctor_move_movedel{
90 
91 // test converting move ctor.  Should only require a MoveConstructible deleter, or if
92 //    deleter is a reference, not even that.
93 
test()94 void test()
95 {
96    //Single unique_ptr
97    reset_counters();
98    {
99    bml::unique_ptr<A, move_constr_deleter<A> > s(new A);
100    A* p = s.get();
101    bml::unique_ptr<A, move_constr_deleter<A> > s2 = boost::move(s);
102    BOOST_TEST(s2.get() == p);
103    BOOST_TEST(s.get() == 0);
104    BOOST_TEST(A::count == 1);
105    BOOST_TEST(s2.get_deleter().state() == 5);
106    BOOST_TEST(s.get_deleter().state() == 0);
107    }
108    BOOST_TEST(A::count == 0);
109    //Unbounded array unique_ptr
110    reset_counters();
111    {
112    bml::unique_ptr<A[], move_constr_deleter<A[]> > s(new A[2]);
113    A* p = s.get();
114    bml::unique_ptr<A[], move_constr_deleter<A[]> > s2 = boost::move(s);
115    BOOST_TEST(s2.get() == p);
116    BOOST_TEST(s.get() == 0);
117    BOOST_TEST(A::count == 2);
118    BOOST_TEST(s2.get_deleter().state() == 5);
119    BOOST_TEST(s.get_deleter().state() == 0);
120    }
121    BOOST_TEST(A::count == 0);
122    //Bounded array unique_ptr
123    reset_counters();
124    {
125    bml::unique_ptr<A[2]> s(new A[2]);
126    A* p = s.get();
127    bml::unique_ptr<A[2]> s2 = boost::move(s);
128    BOOST_TEST(s2.get() == p);
129    BOOST_TEST(s.get() == 0);
130    BOOST_TEST(A::count == 2);
131    }
132    BOOST_TEST(A::count == 0);
133 }
134 
135 }  //namespace unique_ptr_ctor_move_movedel{
136 
137 ////////////////////////////////
138 //   unique_ptr_ctor_move_dfctrdelref
139 ////////////////////////////////
140 
141 namespace unique_ptr_ctor_move_dfctrdelref{
142 
143 // test converting move ctor.  Should only require a MoveConstructible deleter, or if
144 //    deleter is a reference, not even that.
145 
test()146 void test()
147 {
148    //Single unique_ptr
149    reset_counters();
150    {
151    def_constr_deleter<A> d;
152    bml::unique_ptr<A, def_constr_deleter<A>&> s(new A, d);
153    A* p = s.get();
154    bml::unique_ptr<A, def_constr_deleter<A>&> s2 = boost::move(s);
155    BOOST_TEST(s2.get() == p);
156    BOOST_TEST(s.get() == 0);
157    BOOST_TEST(A::count == 1);
158    d.set_state(6);
159    BOOST_TEST(s2.get_deleter().state() == d.state());
160    BOOST_TEST(s.get_deleter().state() ==  d.state());
161    }
162    BOOST_TEST(A::count == 0);
163    //Unbounded array unique_ptr
164    reset_counters();
165    {
166    def_constr_deleter<A[]> d;
167    bml::unique_ptr<A[], def_constr_deleter<A[]>&> s(new A[2], d);
168    A* p = s.get();
169    bml::unique_ptr<A[], def_constr_deleter<A[]>&> s2 = boost::move(s);
170    BOOST_TEST(s2.get() == p);
171    BOOST_TEST(s.get() == 0);
172    BOOST_TEST(A::count == 2);
173    d.set_state(6);
174    BOOST_TEST(s2.get_deleter().state() == d.state());
175    BOOST_TEST(s.get_deleter().state() ==  d.state());
176    }
177    BOOST_TEST(A::count == 0);
178    //Bounded array unique_ptr
179    reset_counters();
180    {
181    def_constr_deleter<A[2]> d;
182    bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> s(new A[2], d);
183    A* p = s.get();
184    bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> s2(boost::move(s));
185    BOOST_TEST(s2.get() == p);
186    BOOST_TEST(s.get() == 0);
187    BOOST_TEST(A::count == 2);
188    d.set_state(6);
189    BOOST_TEST(s2.get_deleter().state() == d.state());
190    BOOST_TEST(s.get_deleter().state() ==  d.state());
191    }
192    BOOST_TEST(A::count == 0);
193 }
194 
195 }  //namespace unique_ptr_ctor_move_dfctrdelref{
196 
197 ////////////////////////////////
198 //   unique_ptr_ctor_move_convert_defdel
199 ////////////////////////////////
200 
201 namespace unique_ptr_ctor_move_convert_defdel{
202 
203 // test converting move ctor.  Should only require a MoveConstructible deleter, or if
204 //    deleter is a reference, not even that.
205 
test()206 void test()
207 {
208    //Single unique_ptr
209    reset_counters();
210    {
211    bml::unique_ptr<B> s(new B);
212    A* p = s.get();
213    bml::unique_ptr<A> s2(boost::move(s));
214    BOOST_TEST(s2.get() == p);
215    BOOST_TEST(s.get() == 0);
216    BOOST_TEST(A::count == 1);
217    BOOST_TEST(B::count == 1);
218    }
219    BOOST_TEST(A::count == 0);
220    BOOST_TEST(B::count == 0);
221    //Unbounded array unique_ptr
222    reset_counters();
223    {
224    bml::unique_ptr<A[]> s(new A[2]);
225    A* p = s.get();
226    bml::unique_ptr<const volatile A[]> s2(boost::move(s));
227    BOOST_TEST(s2.get() == p);
228    BOOST_TEST(s.get() == 0);
229    BOOST_TEST(A::count == 2);
230    }
231    BOOST_TEST(A::count == 0);
232 
233    //Bounded array unique_ptr
234    reset_counters();
235    {
236    bml::unique_ptr<A[2]> s(new A[2]);
237    A* p = s.get();
238    bml::unique_ptr<const volatile A[2]> s2(boost::move(s));
239    BOOST_TEST(s2.get() == p);
240    BOOST_TEST(s.get() == 0);
241    BOOST_TEST(A::count == 2);
242    }
243    BOOST_TEST(A::count == 0);
244    {
245    bml::unique_ptr<A[2]> s(new A[2]);
246    A* p = s.get();
247    bml::unique_ptr<const volatile A[]> s2(boost::move(s));
248    BOOST_TEST(s2.get() == p);
249    BOOST_TEST(s.get() == 0);
250    BOOST_TEST(A::count == 2);
251    }
252    BOOST_TEST(A::count == 0);
253 }
254 
255 }  //namespace unique_ptr_ctor_move_convert_defdel{
256 
257 ////////////////////////////////
258 //   unique_ptr_ctor_move_convert_movedel
259 ////////////////////////////////
260 
261 namespace unique_ptr_ctor_move_convert_movedel{
262 
263 // test converting move ctor.  Should only require a MoveConstructible deleter, or if
264 //    deleter is a reference, not even that.
265 
test()266 void test()
267 {
268    //Single unique_ptr
269    reset_counters();
270    BOOST_STATIC_ASSERT((bmupmu::is_convertible<B, A>::value));
271    {
272    bml::unique_ptr<B, move_constr_deleter<B> > s(new B);
273    A* p = s.get();
274    bml::unique_ptr<A, move_constr_deleter<A> > s2(boost::move(s));
275    BOOST_TEST(s2.get() == p);
276    BOOST_TEST(s.get() == 0);
277    BOOST_TEST(A::count == 1);
278    BOOST_TEST(B::count == 1);
279    BOOST_TEST(s2.get_deleter().state() == 5);
280    BOOST_TEST(s.get_deleter().state() == 0);
281    }
282    BOOST_TEST(A::count == 0);
283    BOOST_TEST(B::count == 0);
284    //Unbounded array unique_ptr
285    reset_counters();
286    {
287    bml::unique_ptr<const A[], move_constr_deleter<const A[]> > s(new const A[2]);
288    const A* p = s.get();
289    bml::unique_ptr<const volatile A[], move_constr_deleter<const volatile A[]> > s2(boost::move(s));
290    BOOST_TEST(s2.get() == p);
291    BOOST_TEST(s.get() == 0);
292    BOOST_TEST(A::count == 2);
293    BOOST_TEST(s2.get_deleter().state() == 5);
294    BOOST_TEST(s.get_deleter().state() == 0);
295    }
296    BOOST_TEST(A::count == 0);
297    BOOST_TEST(B::count == 0);
298    //Bounded array unique_ptr
299    reset_counters();
300    {
301    bml::unique_ptr<const A[2], move_constr_deleter<const A[2]> > s(new const A[2]);
302    const A* p = s.get();
303    bml::unique_ptr<const volatile A[2], move_constr_deleter<const volatile A[2]> > s2(boost::move(s));
304    BOOST_TEST(s2.get() == p);
305    BOOST_TEST(s.get() == 0);
306    BOOST_TEST(A::count == 2);
307    BOOST_TEST(s2.get_deleter().state() == 5);
308    BOOST_TEST(s.get_deleter().state() == 0);
309    }
310    BOOST_TEST(A::count == 0);
311    BOOST_TEST(B::count == 0);
312    {
313    bml::unique_ptr<const A[2], move_constr_deleter<const A[2]> > s(new const A[2]);
314    const A* p = s.get();
315    bml::unique_ptr<const volatile A[], move_constr_deleter<const volatile A[]> > s2(boost::move(s));
316    BOOST_TEST(s2.get() == p);
317    BOOST_TEST(s.get() == 0);
318    BOOST_TEST(A::count == 2);
319    BOOST_TEST(s2.get_deleter().state() == 5);
320    BOOST_TEST(s.get_deleter().state() == 0);
321    }
322    BOOST_TEST(A::count == 0);
323    BOOST_TEST(B::count == 0);
324 }
325 
326 }  //namespace unique_ptr_ctor_move_convert_movedel{
327 
328 ////////////////////////////////
329 //   unique_ptr_ctor_move_convert_dfctrdelref
330 ////////////////////////////////
331 
332 namespace unique_ptr_ctor_move_convert_dfctrdelref{
333 
334 // test converting move ctor.  Should only require a MoveConstructible deleter, or if
335 //    deleter is a reference, not even that.
336 
test()337 void test()
338 {
339    //Single unique_ptr
340    reset_counters();
341    {
342    def_constr_deleter<A> d;
343    bml::unique_ptr<B, def_constr_deleter<A>&> s(new B, d);
344    A* p = s.get();
345    bml::unique_ptr<A, def_constr_deleter<A>&> s2(boost::move(s));
346    BOOST_TEST(s2.get() == p);
347    BOOST_TEST(s.get() == 0);
348    BOOST_TEST(A::count == 1);
349    BOOST_TEST(B::count == 1);
350    d.set_state(6);
351    BOOST_TEST(s2.get_deleter().state() == d.state());
352    BOOST_TEST(s.get_deleter().state() ==  d.state());
353    }
354    BOOST_TEST(A::count == 0);
355    BOOST_TEST(B::count == 0);
356    //Unbounded array unique_ptr
357    reset_counters();
358    {
359    def_constr_deleter<volatile A[]> d;
360    bml::unique_ptr<A[], def_constr_deleter<volatile A[]>&> s(new A[2], d);
361    A* p = s.get();
362    bml::unique_ptr<volatile A[], def_constr_deleter<volatile A[]>&> s2(boost::move(s));
363    BOOST_TEST(s2.get() == p);
364    BOOST_TEST(s.get() == 0);
365    BOOST_TEST(A::count == 2);
366    d.set_state(6);
367    BOOST_TEST(s2.get_deleter().state() == d.state());
368    BOOST_TEST(s.get_deleter().state() ==  d.state());
369    }
370    BOOST_TEST(A::count == 0);
371    //Bounded array unique_ptr
372    reset_counters();
373    {
374    def_constr_deleter<volatile A[2]> d;
375    bml::unique_ptr<A[2], def_constr_deleter<volatile A[2]>&> s(new A[2], d);
376    A* p = s.get();
377    bml::unique_ptr<volatile A[2], def_constr_deleter<volatile A[2]>&> s2(boost::move(s));
378    BOOST_TEST(s2.get() == p);
379    BOOST_TEST(s.get() == 0);
380    BOOST_TEST(A::count == 2);
381    d.set_state(6);
382    BOOST_TEST(s2.get_deleter().state() == d.state());
383    BOOST_TEST(s.get_deleter().state() ==  d.state());
384    }
385    BOOST_TEST(A::count == 0);
386    {
387    def_constr_deleter<volatile A[]> d;
388    bml::unique_ptr<A[2], def_constr_deleter<volatile A[]>&> s(new A[2], d);
389    A* p = s.get();
390    bml::unique_ptr<volatile A[], def_constr_deleter<volatile A[]>&> s2(boost::move(s));
391    BOOST_TEST(s2.get() == p);
392    BOOST_TEST(s.get() == 0);
393    BOOST_TEST(A::count == 2);
394    d.set_state(6);
395    BOOST_TEST(s2.get_deleter().state() == d.state());
396    BOOST_TEST(s.get_deleter().state() ==  d.state());
397    }
398    BOOST_TEST(A::count == 0);
399 }
400 
401 }  //namespace unique_ptr_ctor_move_convert_dfctrdelref{
402 
403 ////////////////////////////////
404 //   unique_ptr_ctor_move_sourcesink
405 ////////////////////////////////
406 
407 namespace unique_ptr_ctor_move_sourcesink{
408 
409 // test move ctor.  Should only require a MoveConstructible deleter, or if
410 //    deleter is a reference, not even that.
411 
source1()412 bml::unique_ptr<A> source1()
413 {  return bml::unique_ptr<A>(new A);  }
414 
source1_unbounded_array()415 bml::unique_ptr<A[]> source1_unbounded_array()
416 {  return bml::unique_ptr<A[]> (new A[2]);  }
417 
source1_bounded_array()418 bml::unique_ptr<A[2]> source1_bounded_array()
419 {  return bml::unique_ptr<A[2]> (new A[2]);  }
420 
sink1(bml::unique_ptr<A>)421 void sink1(bml::unique_ptr<A>)
422 {}
423 
sink1_unbounded_array(bml::unique_ptr<A[]>)424 void sink1_unbounded_array(bml::unique_ptr<A[]>)
425 {}
426 
sink1_bounded_array(bml::unique_ptr<A[2]>)427 void sink1_bounded_array(bml::unique_ptr<A[2]>)
428 {}
429 
source2()430 bml::unique_ptr<A, move_constr_deleter<A> > source2()
431 {  return bml::unique_ptr<A, move_constr_deleter<A> > (new A);  }
432 
source2_unbounded_array()433 bml::unique_ptr<A[], move_constr_deleter<A[]> > source2_unbounded_array()
434 {  return bml::unique_ptr<A[], move_constr_deleter<A[]> >(new A[2]);  }
435 
source2_bounded_array()436 bml::unique_ptr<A[2], move_constr_deleter<A[2]> > source2_bounded_array()
437 {  return bml::unique_ptr<A[2], move_constr_deleter<A[2]> >(new A[2]);  }
438 
sink2(bml::unique_ptr<A,move_constr_deleter<A>>)439 void sink2(bml::unique_ptr<A, move_constr_deleter<A> >)
440 {}
441 
sink2_unbounded_array(bml::unique_ptr<A[],move_constr_deleter<A[]>>)442 void sink2_unbounded_array(bml::unique_ptr<A[], move_constr_deleter<A[]> >)
443 {}
444 
sink2_bounded_array(bml::unique_ptr<A[2],move_constr_deleter<A[2]>>)445 void sink2_bounded_array(bml::unique_ptr<A[2], move_constr_deleter<A[2]> >)
446 {}
447 
source3()448 bml::unique_ptr<A, def_constr_deleter<A>&> source3()
449 {
450    static def_constr_deleter<A> d;
451    return bml::unique_ptr<A, def_constr_deleter<A>&>(new A, d);
452 }
453 
source3_unbounded_array()454 bml::unique_ptr<A[], def_constr_deleter<A[]>&> source3_unbounded_array()
455 {
456    static def_constr_deleter<A[]> d;
457    return bml::unique_ptr<A[], def_constr_deleter<A[]>&>(new A[2], d);
458 }
459 
source3_bounded_array()460 bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> source3_bounded_array()
461 {
462    static def_constr_deleter<A[2]> d;
463    return bml::unique_ptr<A[2], def_constr_deleter<A[2]>&>(new A[2], d);
464 }
465 
sink3(bml::unique_ptr<A,def_constr_deleter<A> &>)466 void sink3(bml::unique_ptr<A, def_constr_deleter<A>&> )
467 {}
468 
sink3_unbounded_array(bml::unique_ptr<A[],def_constr_deleter<A[]> &>)469 void sink3_unbounded_array(bml::unique_ptr<A[], def_constr_deleter<A[]>&> )
470 {}
471 
sink3_bounded_array(bml::unique_ptr<A[2],def_constr_deleter<A[2]> &>)472 void sink3_bounded_array(bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> )
473 {}
474 
test()475 void test()
476 {
477    //Single unique_ptr
478    reset_counters();
479    sink1(source1());
480    sink2(source2());
481    sink3(source3());
482    BOOST_TEST(A::count == 0);
483    //Unbounded array unique_ptr
484    reset_counters();
485    sink1_unbounded_array(source1_unbounded_array());
486    sink2_unbounded_array(source2_unbounded_array());
487    sink3_unbounded_array(source3_unbounded_array());
488    BOOST_TEST(A::count == 0);
489    //Bbounded array unique_ptr
490    reset_counters();
491    sink1_bounded_array(source1_bounded_array());
492    sink2_bounded_array(source2_bounded_array());
493    sink3_bounded_array(source3_bounded_array());
494    BOOST_TEST(A::count == 0);
495 }
496 
497 }  //namespace unique_ptr_ctor_move_sourcesink{
498 
499 ////////////////////////////////
500 //             main
501 ////////////////////////////////
main()502 int main()
503 {
504    //Move Constructor
505    unique_ptr_ctor_move_defdel::test();
506    unique_ptr_ctor_move_movedel::test();
507    unique_ptr_ctor_move_dfctrdelref::test();
508    unique_ptr_ctor_move_convert_defdel::test();
509    unique_ptr_ctor_move_convert_movedel::test();
510    unique_ptr_ctor_move_convert_dfctrdelref::test();
511    unique_ptr_ctor_move_sourcesink::test();
512 
513    //Test results
514    return boost::report_errors();
515 }
516 
517 #include "unique_ptr_test_utils_end.hpp"
518