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