1 // smart pointer test program ----------------------------------------------//
2
3 // Copyright Beman Dawes 1998, 1999. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7 // See http://www.boost.org/libs/smart_ptr for documentation.
8
9 // Revision History
10 // 24 May 01 use Boost test library for error detection, reporting, add tests
11 // for operations on incomplete types (Beman Dawes)
12 // 29 Nov 99 added std::swap and associative container tests (Darin Adler)
13 // 25 Sep 99 added swap tests
14 // 20 Jul 99 header name changed to .hpp
15 // 20 Apr 99 additional error tests added.
16
17 #include <boost/config.hpp>
18
19 #if defined(BOOST_MSVC)
20
21 # pragma warning(disable: 4786) // identifier truncated in debug info
22 # pragma warning(disable: 4710) // function not inlined
23 # pragma warning(disable: 4711) // function selected for automatic inline expansion
24 # pragma warning(disable: 4514) // unreferenced inline removed
25
26 #if (BOOST_MSVC >= 1310)
27 # pragma warning(disable: 4675) // resolved overload found with Koenig lookup
28 #endif
29
30 #endif
31
32 #ifdef __BORLANDC__
33 # pragma warn -8092 // template argument passed to 'find' is not an iterator
34 #endif
35
36 #include <boost/smart_ptr.hpp>
37
38 #include <boost/detail/lightweight_test.hpp>
39
40 #include <iostream>
41 #include <set>
42 #include <string.h>
43
44 class Incomplete;
45
get_ptr(boost::shared_ptr<Incomplete> & incomplete)46 Incomplete * get_ptr( boost::shared_ptr<Incomplete>& incomplete )
47 {
48 return incomplete.get();
49 }
50
51 template<class T>
ck(const T * v1,T v2)52 void ck( const T* v1, T v2 ) { BOOST_TEST( *v1 == v2 ); }
53
54 namespace {
55 int UDT_use_count; // independent of pointer maintained counts
56 }
57
58 // user defined type -------------------------------------------------------//
59
60 class UDT {
61 long value_;
62 public:
UDT(long value=0)63 explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; }
~UDT()64 ~UDT() {
65 --UDT_use_count;
66 std::cout << "UDT with value " << value_ << " being destroyed\n";
67 }
value() const68 long value() const { return value_; }
value(long v)69 void value( long v ) { value_ = v;; }
70 }; // UDT
71
72 // tests on incomplete types -----------------------------------------------//
73
74 // Certain smart pointer operations are specified to work on incomplete types,
75 // and some uses depend upon this feature. These tests verify compilation
76 // only - the functions aren't actually invoked.
77
78 class Incomplete;
79
check_incomplete(boost::scoped_ptr<Incomplete> & incomplete)80 Incomplete * check_incomplete( boost::scoped_ptr<Incomplete>& incomplete )
81 {
82 return incomplete.get();
83 }
84
check_incomplete(boost::shared_ptr<Incomplete> & incomplete,boost::shared_ptr<Incomplete> & i2)85 Incomplete * check_incomplete( boost::shared_ptr<Incomplete>& incomplete,
86 boost::shared_ptr<Incomplete>& i2 )
87 {
88 incomplete.swap(i2);
89 std::cout << incomplete.use_count() << ' ' << incomplete.unique() << '\n';
90 return incomplete.get();
91 }
92
93 // This isn't a very systematic test; it just hits some of the basics.
94
test()95 void test()
96 {
97 BOOST_TEST( UDT_use_count == 0 ); // reality check
98
99 // test scoped_ptr with a built-in type
100 long * lp = new long;
101 boost::scoped_ptr<long> sp ( lp );
102 BOOST_TEST( sp.get() == lp );
103 BOOST_TEST( lp == sp.get() );
104 BOOST_TEST( &*sp == lp );
105
106 *sp = 1234568901L;
107 BOOST_TEST( *sp == 1234568901L );
108 BOOST_TEST( *lp == 1234568901L );
109 ck( static_cast<long*>(sp.get()), 1234568901L );
110 ck( lp, *sp );
111
112 sp.reset();
113 BOOST_TEST( sp.get() == 0 );
114
115 // test scoped_ptr with a user defined type
116 boost::scoped_ptr<UDT> udt_sp ( new UDT( 999888777 ) );
117 BOOST_TEST( udt_sp->value() == 999888777 );
118 udt_sp.reset();
119 udt_sp.reset( new UDT( 111222333 ) );
120 BOOST_TEST( udt_sp->value() == 111222333 );
121 udt_sp.reset( new UDT( 333222111 ) );
122 BOOST_TEST( udt_sp->value() == 333222111 );
123
124 // test scoped_array with a build-in type
125 char * sap = new char [ 100 ];
126 boost::scoped_array<char> sa ( sap );
127 BOOST_TEST( sa.get() == sap );
128 BOOST_TEST( sap == sa.get() );
129
130 strcpy( sa.get(), "Hot Dog with mustard and relish" );
131 BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 );
132 BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 );
133
134 BOOST_TEST( sa[0] == 'H' );
135 BOOST_TEST( sa[30] == 'h' );
136
137 sa[0] = 'N';
138 sa[4] = 'd';
139 BOOST_TEST( strcmp( sap, "Not dog with mustard and relish" ) == 0 );
140
141 sa.reset();
142 BOOST_TEST( sa.get() == 0 );
143
144 // test shared_ptr with a built-in type
145 int * ip = new int;
146 boost::shared_ptr<int> cp ( ip );
147 BOOST_TEST( ip == cp.get() );
148 BOOST_TEST( cp.use_count() == 1 );
149
150 *cp = 54321;
151 BOOST_TEST( *cp == 54321 );
152 BOOST_TEST( *ip == 54321 );
153 ck( static_cast<int*>(cp.get()), 54321 );
154 ck( static_cast<int*>(ip), *cp );
155
156 boost::shared_ptr<int> cp2 ( cp );
157 BOOST_TEST( ip == cp2.get() );
158 BOOST_TEST( cp.use_count() == 2 );
159 BOOST_TEST( cp2.use_count() == 2 );
160
161 BOOST_TEST( *cp == 54321 );
162 BOOST_TEST( *cp2 == 54321 );
163 ck( static_cast<int*>(cp2.get()), 54321 );
164 ck( static_cast<int*>(ip), *cp2 );
165
166 boost::shared_ptr<int> cp3 ( cp );
167 BOOST_TEST( cp.use_count() == 3 );
168 BOOST_TEST( cp2.use_count() == 3 );
169 BOOST_TEST( cp3.use_count() == 3 );
170 cp.reset();
171 BOOST_TEST( cp2.use_count() == 2 );
172 BOOST_TEST( cp3.use_count() == 2 );
173 cp.reset( new int );
174 *cp = 98765;
175 BOOST_TEST( *cp == 98765 );
176 *cp3 = 87654;
177 BOOST_TEST( *cp3 == 87654 );
178 BOOST_TEST( *cp2 == 87654 );
179 cp.swap( cp3 );
180 BOOST_TEST( *cp == 87654 );
181 BOOST_TEST( *cp2 == 87654 );
182 BOOST_TEST( *cp3 == 98765 );
183 cp.swap( cp3 );
184 BOOST_TEST( *cp == 98765 );
185 BOOST_TEST( *cp2 == 87654 );
186 BOOST_TEST( *cp3 == 87654 );
187 cp2 = cp2;
188 BOOST_TEST( cp2.use_count() == 2 );
189 BOOST_TEST( *cp2 == 87654 );
190 cp = cp2;
191 BOOST_TEST( cp2.use_count() == 3 );
192 BOOST_TEST( *cp2 == 87654 );
193 BOOST_TEST( cp.use_count() == 3 );
194 BOOST_TEST( *cp == 87654 );
195
196 #if defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP )
197 using boost::swap;
198 #endif
199
200 boost::shared_ptr<int> cp4;
201 swap( cp2, cp4 );
202 BOOST_TEST( cp4.use_count() == 3 );
203 BOOST_TEST( *cp4 == 87654 );
204 BOOST_TEST( cp2.get() == 0 );
205
206 std::set< boost::shared_ptr<int> > scp;
207 scp.insert(cp4);
208 BOOST_TEST( scp.find(cp4) != scp.end() );
209 BOOST_TEST( scp.find(cp4) == scp.find( boost::shared_ptr<int>(cp4) ) );
210
211 // test shared_array with a built-in type
212 char * cap = new char [ 100 ];
213 boost::shared_array<char> ca ( cap );
214 BOOST_TEST( ca.get() == cap );
215 BOOST_TEST( cap == ca.get() );
216 BOOST_TEST( &ca[0] == cap );
217
218 strcpy( ca.get(), "Hot Dog with mustard and relish" );
219 BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 );
220 BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 );
221
222 BOOST_TEST( ca[0] == 'H' );
223 BOOST_TEST( ca[30] == 'h' );
224
225 boost::shared_array<char> ca2 ( ca );
226 boost::shared_array<char> ca3 ( ca2 );
227
228 ca[0] = 'N';
229 ca[4] = 'd';
230 BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 );
231 BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 );
232 BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 );
233 BOOST_TEST( ca.use_count() == 3 );
234 BOOST_TEST( ca2.use_count() == 3 );
235 BOOST_TEST( ca3.use_count() == 3 );
236 ca2.reset();
237 BOOST_TEST( ca.use_count() == 2 );
238 BOOST_TEST( ca3.use_count() == 2 );
239 BOOST_TEST( ca2.use_count() == 0 );
240
241 ca.reset();
242 BOOST_TEST( ca.get() == 0 );
243
244 boost::shared_array<char> ca4;
245 swap( ca3, ca4 );
246 BOOST_TEST( ca4.use_count() == 1 );
247 BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 );
248 BOOST_TEST( ca3.get() == 0 );
249
250 std::set< boost::shared_array<char> > sca;
251 sca.insert(ca4);
252 BOOST_TEST( sca.find(ca4) != sca.end() );
253 BOOST_TEST( sca.find(ca4) == sca.find( boost::shared_array<char>(ca4) ) );
254
255 // test shared_array with user defined type
256 boost::shared_array<UDT> udta ( new UDT[3] );
257
258 udta[0].value( 111 );
259 udta[1].value( 222 );
260 udta[2].value( 333 );
261 boost::shared_array<UDT> udta2 ( udta );
262
263 BOOST_TEST( udta[0].value() == 111 );
264 BOOST_TEST( udta[1].value() == 222 );
265 BOOST_TEST( udta[2].value() == 333 );
266 BOOST_TEST( udta2[0].value() == 111 );
267 BOOST_TEST( udta2[1].value() == 222 );
268 BOOST_TEST( udta2[2].value() == 333 );
269 udta2.reset();
270 BOOST_TEST( udta2.get() == 0 );
271 BOOST_TEST( udta.use_count() == 1 );
272 BOOST_TEST( udta2.use_count() == 0 );
273
274 BOOST_TEST( UDT_use_count == 4 ); // reality check
275
276 // test shared_ptr with a user defined type
277 UDT * up = new UDT;
278 boost::shared_ptr<UDT> sup ( up );
279 BOOST_TEST( up == sup.get() );
280 BOOST_TEST( sup.use_count() == 1 );
281
282 sup->value( 54321 ) ;
283 BOOST_TEST( sup->value() == 54321 );
284 BOOST_TEST( up->value() == 54321 );
285
286 boost::shared_ptr<UDT> sup2;
287 sup2 = sup;
288 BOOST_TEST( sup2->value() == 54321 );
289 BOOST_TEST( sup.use_count() == 2 );
290 BOOST_TEST( sup2.use_count() == 2 );
291 sup2 = sup2;
292 BOOST_TEST( sup2->value() == 54321 );
293 BOOST_TEST( sup.use_count() == 2 );
294 BOOST_TEST( sup2.use_count() == 2 );
295
296 std::cout << "OK\n";
297
298 new char[12345]; // deliberate memory leak to verify leaks detected
299 }
300
main()301 int main()
302 {
303 test();
304 return boost::report_errors();
305 }
306