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