1 //
2 //  sp_array_n_test.cpp
3 //
4 //  Copyright (c) 2012 Peter Dimov
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 
11 #include <boost/shared_ptr.hpp>
12 #include <boost/weak_ptr.hpp>
13 #include <boost/enable_shared_from_this.hpp>
14 #include <boost/detail/lightweight_test.hpp>
15 #include <memory>
16 #include <utility>
17 
18 class X: public boost::enable_shared_from_this< X >
19 {
20 public:
21 
22     static int allocations;
23     static int instances;
24 
X()25     X()
26     {
27         ++instances;
28     }
29 
~X()30     ~X()
31     {
32         --instances;
33     }
34 
operator new[](std::size_t n)35     void* operator new[]( std::size_t n )
36     {
37         ++allocations;
38         return ::operator new[]( n );
39     }
40 
operator delete[](void * p)41     void operator delete[]( void* p )
42     {
43         --allocations;
44         ::operator delete[]( p );
45     }
46 
47 private:
48 
49     X( X const& );
50     X& operator=( X const& );
51 };
52 
53 int X::allocations = 0;
54 int X::instances = 0;
55 
56 template< class T> class array_deleter
57 {
58 public:
59 
60     static int calls;
61 
operator ()(T * p) const62     void operator()( T * p ) const
63     {
64         ++calls;
65         delete[] p;
66     }
67 
68 private:
69 
70     template< class Y > void operator()( Y * p ) const;
71 };
72 
73 template< class T > int array_deleter< T >::calls = 0;
74 
main()75 int main()
76 {
77     BOOST_TEST( X::allocations == 0 );
78     BOOST_TEST( X::instances == 0 );
79 
80     {
81         boost::shared_ptr<X[3]> px;
82         BOOST_TEST( !px );
83 
84         BOOST_TEST( X::allocations == 0 );
85         BOOST_TEST( X::instances == 0 );
86 
87         boost::shared_ptr<X[3]> px2( new X[ 3 ] );
88         BOOST_TEST( px2 );
89 
90         try
91         {
92             px2[0].shared_from_this();
93             BOOST_ERROR( "px2[0].shared_from_this() failed to throw" );
94         }
95         catch( boost::bad_weak_ptr const& )
96         {
97         }
98         catch( ... )
99         {
100             BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" );
101         }
102 
103         BOOST_TEST( X::allocations == 1 );
104         BOOST_TEST( X::instances == 3 );
105 
106         {
107             X & rx = px2[ 0 ];
108             BOOST_TEST( &rx == px2.get() );
109         }
110 
111         boost::shared_ptr<X const[3]> px3( px2 );
112         BOOST_TEST( px3 == px2 );
113         BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) );
114 
115         {
116             X const & rx = px3[ 1 ];
117             BOOST_TEST( &rx == px3.get() + 1 );
118         }
119 
120         px3.reset();
121         px3 = px2;
122         BOOST_TEST( px3 == px2 );
123         BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) );
124 
125         boost::shared_ptr<X volatile[3]> px4( px2 );
126         BOOST_TEST( px4 == px2 );
127         BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) );
128 
129         {
130             X volatile & rx = px4[ 2 ];
131             BOOST_TEST( &rx == px4.get() + 2 );
132         }
133 
134         px4.reset();
135         px4 = px2;
136         BOOST_TEST( px4 == px2 );
137         BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) );
138 
139         boost::shared_ptr<void> px5( px2 );
140         BOOST_TEST( px5 == px2 );
141         BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) );
142 
143         px5.reset();
144         px5 = px2;
145         BOOST_TEST( px5 == px2 );
146         BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) );
147 
148         boost::weak_ptr<X[3]> wp( px );
149         BOOST_TEST( wp.lock() == px );
150 
151         boost::weak_ptr<X[3]> wp2( px2 );
152         BOOST_TEST( wp2.lock() == px2 );
153 
154         wp2.reset();
155         wp2 = px2;
156         BOOST_TEST( wp2.lock() == px2 );
157 
158         boost::weak_ptr<X const[3]> wp3( px2 );
159         BOOST_TEST( wp3.lock() == px2 );
160 
161         wp3.reset();
162         wp3 = px2;
163         BOOST_TEST( wp3.lock() == px2 );
164 
165         boost::weak_ptr<X volatile[3]> wp4( px2 );
166         BOOST_TEST( wp4.lock() == px2 );
167 
168         wp4.reset();
169         wp4 = px2;
170         BOOST_TEST( wp4.lock() == px2 );
171 
172         boost::weak_ptr<void> wp5( px2 );
173         BOOST_TEST( wp5.lock() == px2 );
174 
175         wp5.reset();
176         wp5 = px2;
177         BOOST_TEST( wp5.lock() == px2 );
178 
179         px2.reset();
180 
181         BOOST_TEST( X::allocations == 1 );
182         BOOST_TEST( X::instances == 3 );
183 
184         px3.reset();
185         px4.reset();
186         px5.reset();
187 
188         BOOST_TEST( X::allocations == 0 );
189         BOOST_TEST( X::instances == 0 );
190 
191         BOOST_TEST( wp2.lock() == 0 );
192         BOOST_TEST( wp3.lock() == 0 );
193         BOOST_TEST( wp4.lock() == 0 );
194         BOOST_TEST( wp5.lock() == 0 );
195     }
196 
197     {
198         boost::shared_ptr<X[5]> px( new X[ 5 ], array_deleter< X >() );
199         BOOST_TEST( X::allocations == 1 );
200         BOOST_TEST( X::instances == 5 );
201 
202         try
203         {
204             px[0].shared_from_this();
205             BOOST_ERROR( "px[0].shared_from_this() failed to throw" );
206         }
207         catch( boost::bad_weak_ptr const& )
208         {
209         }
210         catch( ... )
211         {
212             BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" );
213         }
214 
215         px.reset();
216 
217         BOOST_TEST( X::allocations == 0 );
218         BOOST_TEST( X::instances == 0 );
219         BOOST_TEST( array_deleter< X >::calls == 1 );
220     }
221 
222     {
223         boost::shared_ptr<X[6]> px( new X[ 6 ], array_deleter< X >(), std::allocator< X >() );
224         BOOST_TEST( X::allocations == 1 );
225         BOOST_TEST( X::instances == 6 );
226 
227         try
228         {
229             px[0].shared_from_this();
230             BOOST_ERROR( "px[0].shared_from_this() failed to throw" );
231         }
232         catch( boost::bad_weak_ptr const& )
233         {
234         }
235         catch( ... )
236         {
237             BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" );
238         }
239 
240         px.reset();
241 
242         BOOST_TEST( X::allocations == 0 );
243         BOOST_TEST( X::instances == 0 );
244         BOOST_TEST( array_deleter< X >::calls == 2 );
245     }
246 
247     return boost::report_errors();
248 }
249