blob: ece216b2e2386dbbb9332dda1fd0edad3fa5c5c2 [file] [log] [blame]
Brian Silverman1f5d3982018-08-04 23:37:52 -07001//////////////////////////////////////////////////////////////////////////////
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
34namespace bml = ::boost::movelib;
35namespace bmupmu = ::boost::move_upmu;
36
37////////////////////////////////
38// unique_ptr_ctor_move_defdel
39////////////////////////////////
40
41namespace 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
46void 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
89namespace 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
94void 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
141namespace 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
146void 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
201namespace 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
206void 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
261namespace 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
266void 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
332namespace 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
337void 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
407namespace 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
412bml::unique_ptr<A> source1()
413{ return bml::unique_ptr<A>(new A); }
414
415bml::unique_ptr<A[]> source1_unbounded_array()
416{ return bml::unique_ptr<A[]> (new A[2]); }
417
418bml::unique_ptr<A[2]> source1_bounded_array()
419{ return bml::unique_ptr<A[2]> (new A[2]); }
420
421void sink1(bml::unique_ptr<A>)
422{}
423
424void sink1_unbounded_array(bml::unique_ptr<A[]>)
425{}
426
427void sink1_bounded_array(bml::unique_ptr<A[2]>)
428{}
429
430bml::unique_ptr<A, move_constr_deleter<A> > source2()
431{ return bml::unique_ptr<A, move_constr_deleter<A> > (new A); }
432
433bml::unique_ptr<A[], move_constr_deleter<A[]> > source2_unbounded_array()
434{ return bml::unique_ptr<A[], move_constr_deleter<A[]> >(new A[2]); }
435
436bml::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
439void sink2(bml::unique_ptr<A, move_constr_deleter<A> >)
440{}
441
442void sink2_unbounded_array(bml::unique_ptr<A[], move_constr_deleter<A[]> >)
443{}
444
445void sink2_bounded_array(bml::unique_ptr<A[2], move_constr_deleter<A[2]> >)
446{}
447
448bml::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
454bml::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
460bml::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
466void sink3(bml::unique_ptr<A, def_constr_deleter<A>&> )
467{}
468
469void sink3_unbounded_array(bml::unique_ptr<A[], def_constr_deleter<A[]>&> )
470{}
471
472void sink3_bounded_array(bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> )
473{}
474
475void 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////////////////////////////////
502int 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"