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