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

source code of boost/libs/move/test/unique_ptr_movector.cpp