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 BOOST_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/core/lightweight_test.hpp> |
41 | |
42 | #include <iostream> |
43 | #include <set> |
44 | #include <string.h> |
45 | |
46 | class Incomplete; |
47 | |
48 | Incomplete * get_ptr( boost::shared_ptr<Incomplete>& incomplete ) |
49 | { |
50 | return incomplete.get(); |
51 | } |
52 | |
53 | template<class T> |
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: |
65 | explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; } |
66 | ~UDT() { |
67 | --UDT_use_count; |
68 | std::cout << "UDT with value " << value_ << " being destroyed\n" ; |
69 | } |
70 | long value() const { return value_; } |
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 | |
82 | Incomplete * check_incomplete( boost::scoped_ptr<Incomplete>& incomplete ) |
83 | { |
84 | return incomplete.get(); |
85 | } |
86 | |
87 | Incomplete * check_incomplete( boost::shared_ptr<Incomplete>& incomplete, |
88 | boost::shared_ptr<Incomplete>& i2 ) |
89 | { |
90 | incomplete.swap(other&: 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 | |
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( v1: static_cast<long*>(sp.get()), v2: 1234568901L ); |
112 | ck( v1: lp, v2: *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( p: new UDT( 111222333 ) ); |
122 | BOOST_TEST( udt_sp->value() == 111222333 ); |
123 | udt_sp.reset( p: 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( dest: sa.get(), src: "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( v1: static_cast<int*>(cp.get()), v2: 54321 ); |
156 | ck( v1: static_cast<int*>(ip), v2: *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( v1: static_cast<int*>(cp2.get()), v2: 54321 ); |
166 | ck( v1: static_cast<int*>(ip), v2: *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( p: 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( other&: cp3 ); |
182 | BOOST_TEST( *cp == 87654 ); |
183 | BOOST_TEST( *cp2 == 87654 ); |
184 | BOOST_TEST( *cp3 == 98765 ); |
185 | cp.swap( other&: 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( a&: cp2, b&: 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(x: 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( dest: ca.get(), src: "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( a&: ca3, b&: 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(x: 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( v: 111 ); |
261 | udta[1].value( v: 222 ); |
262 | udta[2].value( v: 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( v: 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 | |
301 | int main() |
302 | { |
303 | test(); |
304 | return boost::report_errors(); |
305 | } |
306 | |