1 //
2 //  esft_regtest.cpp
3 //
4 //  A regression test for enable_shared_from_this
5 //
6 //  Copyright (c) 2008 Peter Dimov
7 //
8 //  Distributed under the Boost Software License, Version 1.0.
9 //
10 //  See accompanying file LICENSE_1_0.txt or copy at
11 //  http://www.boost.org/LICENSE_1_0.txt)
12 //
13 
14 #include <boost/enable_shared_from_this.hpp>
15 #include <boost/shared_ptr.hpp>
16 #include <boost/weak_ptr.hpp>
17 #include <boost/detail/lightweight_test.hpp>
18 #include <memory>
19 #include <string>
20 
21 class X: public boost::enable_shared_from_this< X >
22 {
23 private:
24 
25     int destroyed_;
26     int deleted_;
27     int expected_;
28 
29 private:
30 
31     X( X const& );
32     X& operator=( X const& );
33 
34 public:
35 
36     static int instances;
37 
38 public:
39 
X(int expected)40     explicit X( int expected ): destroyed_( 0 ), deleted_( 0 ), expected_( expected )
41     {
42         ++instances;
43     }
44 
~X()45     ~X()
46     {
47         BOOST_TEST( deleted_ == expected_ );
48         BOOST_TEST( destroyed_ == 0 );
49         ++destroyed_;
50         --instances;
51     }
52 
53     typedef void (*deleter_type)( X* );
54 
deleter(X * px)55     static void deleter( X * px )
56     {
57         ++px->deleted_;
58     }
59 
deleter2(X * px)60     static void deleter2( X * px )
61     {
62         ++px->deleted_;
63         delete px;
64     }
65 };
66 
67 int X::instances = 0;
68 
test()69 void test()
70 {
71     BOOST_TEST( X::instances == 0 );
72 
73     {
74         X x( 0 );
75         BOOST_TEST( X::instances == 1 );
76     }
77 
78     BOOST_TEST( X::instances == 0 );
79 
80     {
81         std::auto_ptr<X> px( new X( 0 ) );
82         BOOST_TEST( X::instances == 1 );
83     }
84 
85     BOOST_TEST( X::instances == 0 );
86 
87     {
88         boost::shared_ptr<X> px( new X( 0 ) );
89         BOOST_TEST( X::instances == 1 );
90 
91         boost::weak_ptr<X> wp( px );
92         BOOST_TEST( !wp.expired() );
93 
94         px.reset();
95 
96         BOOST_TEST( wp.expired() );
97     }
98 
99     BOOST_TEST( X::instances == 0 );
100 
101     {
102         X x( 1 );
103         boost::shared_ptr<X> px( &x, X::deleter );
104         BOOST_TEST( X::instances == 1 );
105 
106         X::deleter_type * pd = boost::get_deleter<X::deleter_type>( px );
107         BOOST_TEST( pd != 0 && *pd == X::deleter );
108 
109         boost::weak_ptr<X> wp( px );
110         BOOST_TEST( !wp.expired() );
111 
112         px.reset();
113 
114         BOOST_TEST( wp.expired() );
115     }
116 
117     BOOST_TEST( X::instances == 0 );
118 
119     {
120         boost::shared_ptr<X> px( new X( 1 ), X::deleter2 );
121         BOOST_TEST( X::instances == 1 );
122 
123         X::deleter_type * pd = boost::get_deleter<X::deleter_type>( px );
124         BOOST_TEST( pd != 0 && *pd == X::deleter2 );
125 
126         boost::weak_ptr<X> wp( px );
127         BOOST_TEST( !wp.expired() );
128 
129         px.reset();
130 
131         BOOST_TEST( wp.expired() );
132     }
133 
134     BOOST_TEST( X::instances == 0 );
135 }
136 
137 struct V: public boost::enable_shared_from_this<V>
138 {
~VV139     virtual ~V() {}
140     std::string m_;
141 };
142 
143 struct V2
144 {
~V2V2145     virtual ~V2() {}
146     std::string m2_;
147 };
148 
149 struct W: V2, V
150 {
151 };
152 
test2()153 void test2()
154 {
155     boost::shared_ptr<W> p( new W );
156 }
157 
test3()158 void test3()
159 {
160     V * p = new W;
161     boost::shared_ptr<void> pv( p );
162     BOOST_TEST( pv.get() == p );
163     BOOST_TEST( pv.use_count() == 1 );
164 }
165 
166 struct null_deleter
167 {
operator ()null_deleter168     void operator()( void const* ) const {}
169 };
170 
test4()171 void test4()
172 {
173     boost::shared_ptr<V> pv( new V );
174     boost::shared_ptr<V> pv2( pv.get(), null_deleter() );
175     BOOST_TEST( pv2.get() == pv.get() );
176     BOOST_TEST( pv2.use_count() == 1 );
177 }
178 
test5()179 void test5()
180 {
181     V v;
182 
183     boost::shared_ptr<V> p1( &v, null_deleter() );
184     BOOST_TEST( p1.get() == &v );
185     BOOST_TEST( p1.use_count() == 1 );
186 
187     try
188     {
189         p1->shared_from_this();
190     }
191     catch( ... )
192     {
193         BOOST_ERROR( "p1->shared_from_this() failed" );
194     }
195 
196     p1.reset();
197 
198     boost::shared_ptr<V> p2( &v, null_deleter() );
199     BOOST_TEST( p2.get() == &v );
200     BOOST_TEST( p2.use_count() == 1 );
201 
202     try
203     {
204         p2->shared_from_this();
205     }
206     catch( ... )
207     {
208         BOOST_ERROR( "p2->shared_from_this() failed" );
209     }
210 }
211 
main()212 int main()
213 {
214     test();
215     test2();
216     test3();
217     test4();
218     test5();
219 
220     return boost::report_errors();
221 }
222