]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
2 | // test_shared_ptr.cpp | |
3 | ||
f67539c2 | 4 | // (C) Copyright 2002 Robert Ramey- http://www.rrsd.com - David Tonge . |
7c673cae FG |
5 | // Use, modification and distribution is subject to the Boost Software |
6 | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
7 | // http://www.boost.org/LICENSE_1_0.txt) | |
8 | // | |
9 | // See http://www.boost.org for updates, documentation, and revision history. | |
10 | ||
11 | #include <cstddef> // NULL | |
12 | #include <cstdio> // remove | |
13 | #include <fstream> | |
14 | ||
15 | #include <boost/config.hpp> | |
16 | #if defined(BOOST_NO_STDC_NAMESPACE) | |
f67539c2 | 17 | namespace std{ |
7c673cae FG |
18 | using ::remove; |
19 | } | |
20 | #endif | |
21 | ||
22 | #include <boost/serialization/nvp.hpp> | |
23 | #include <boost/serialization/export.hpp> | |
24 | #include <boost/serialization/shared_ptr.hpp> | |
25 | #include <boost/serialization/weak_ptr.hpp> | |
26 | ||
27 | #include "test_tools.hpp" | |
28 | ||
29 | // This is a simple class. It contains a counter of the number | |
30 | // of objects of this class which have been instantiated. | |
31 | class A | |
32 | { | |
33 | private: | |
34 | friend class boost::serialization::access; | |
35 | int x; | |
36 | template<class Archive> | |
37 | void serialize(Archive & ar, const unsigned int /* file_version */){ | |
38 | ar & BOOST_SERIALIZATION_NVP(x); | |
39 | } | |
40 | A(A const & rhs); | |
41 | A& operator=(A const & rhs); | |
42 | public: | |
43 | static int count; | |
44 | bool operator==(const A & rhs) const { | |
45 | return x == rhs.x; | |
46 | } | |
47 | A(){++count;} // default constructor | |
48 | virtual ~A(){--count;} // default destructor | |
49 | }; | |
50 | ||
51 | BOOST_SERIALIZATION_SHARED_PTR(A) | |
52 | ||
53 | int A::count = 0; | |
54 | ||
55 | // B is a subclass of A | |
56 | class B : public A | |
57 | { | |
58 | private: | |
59 | friend class boost::serialization::access; | |
60 | template<class Archive> | |
61 | void serialize(Archive & ar, const unsigned int /* file_version */){ | |
62 | ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(A); | |
63 | } | |
64 | public: | |
65 | static int count; | |
66 | B() : A() {}; | |
67 | virtual ~B() {}; | |
68 | }; | |
69 | ||
70 | // B needs to be exported because its serialized via a base class pointer | |
71 | BOOST_CLASS_EXPORT(B) | |
72 | BOOST_SERIALIZATION_SHARED_PTR(B) | |
73 | ||
74 | // test a non-polymorphic class | |
75 | class C | |
76 | { | |
77 | private: | |
78 | friend class boost::serialization::access; | |
79 | int z; | |
80 | template<class Archive> | |
81 | void serialize(Archive & ar, const unsigned int /* file_version */){ | |
82 | ar & BOOST_SERIALIZATION_NVP(z); | |
83 | } | |
84 | public: | |
85 | static int count; | |
86 | bool operator==(const C & rhs) const { | |
87 | return z == rhs.z; | |
88 | } | |
89 | C() : | |
90 | z(++count) // default constructor | |
91 | {} | |
92 | virtual ~C(){--count;} // default destructor | |
93 | }; | |
94 | ||
95 | int C::count = 0; | |
96 | ||
97 | template<class SP> | |
98 | void save(const char * testfile, const SP & spa) | |
99 | { | |
100 | test_ostream os(testfile, TEST_STREAM_FLAGS); | |
101 | test_oarchive oa(os, TEST_ARCHIVE_FLAGS); | |
102 | oa << BOOST_SERIALIZATION_NVP(spa); | |
103 | } | |
104 | ||
105 | template<class SP> | |
106 | void load(const char * testfile, SP & spa) | |
107 | { | |
108 | test_istream is(testfile, TEST_STREAM_FLAGS); | |
109 | test_iarchive ia(is, TEST_ARCHIVE_FLAGS); | |
110 | ia >> BOOST_SERIALIZATION_NVP(spa); | |
111 | } | |
112 | ||
113 | // trivial test | |
114 | template<class SP> | |
115 | void save_and_load(SP & spa) | |
116 | { | |
117 | const char * testfile = boost::archive::tmpnam(NULL); | |
118 | BOOST_REQUIRE(NULL != testfile); | |
119 | save(testfile, spa); | |
120 | SP spa1; | |
121 | load(testfile, spa1); | |
122 | ||
123 | BOOST_CHECK( | |
124 | (spa.get() == NULL && spa1.get() == NULL) | |
125 | || * spa == * spa1 | |
126 | ); | |
127 | std::remove(testfile); | |
128 | } | |
129 | ||
130 | template<class SP> | |
131 | void save2( | |
f67539c2 | 132 | const char * testfile, |
7c673cae FG |
133 | const SP & first, |
134 | const SP & second | |
135 | ){ | |
136 | test_ostream os(testfile, TEST_STREAM_FLAGS); | |
137 | test_oarchive oa(os, TEST_ARCHIVE_FLAGS); | |
138 | oa << BOOST_SERIALIZATION_NVP(first); | |
139 | oa << BOOST_SERIALIZATION_NVP(second); | |
140 | } | |
141 | ||
142 | template<class SP> | |
143 | void load2( | |
f67539c2 | 144 | const char * testfile, |
7c673cae FG |
145 | SP & first, |
146 | SP & second) | |
147 | { | |
148 | test_istream is(testfile, TEST_STREAM_FLAGS); | |
149 | test_iarchive ia(is, TEST_ARCHIVE_FLAGS); | |
150 | ia >> BOOST_SERIALIZATION_NVP(first); | |
151 | ia >> BOOST_SERIALIZATION_NVP(second); | |
152 | } | |
153 | ||
154 | // Run tests by serializing two shared_ptrs into an archive, | |
155 | // clearing them (deleting the objects) and then reloading the | |
156 | // objects back from an archive. | |
157 | template<class SP> | |
158 | void save_and_load2(SP & first, SP & second) | |
159 | { | |
160 | const char * testfile = boost::archive::tmpnam(NULL); | |
161 | BOOST_REQUIRE(NULL != testfile); | |
162 | ||
163 | save2(testfile, first, second); | |
164 | ||
165 | // Clear the pointers, thereby destroying the objects they contain | |
166 | first.reset(); | |
167 | second.reset(); | |
168 | ||
169 | load2(testfile, first, second); | |
170 | ||
171 | BOOST_CHECK(first == second); | |
172 | std::remove(testfile); | |
173 | } | |
174 | ||
175 | template<class SP, class WP> | |
176 | void save3( | |
f67539c2 | 177 | const char * testfile, |
7c673cae FG |
178 | SP & first, |
179 | SP & second, | |
180 | WP & third | |
181 | ){ | |
182 | test_ostream os(testfile, TEST_STREAM_FLAGS); | |
183 | test_oarchive oa(os, TEST_ARCHIVE_FLAGS); | |
184 | oa << BOOST_SERIALIZATION_NVP(third); | |
185 | oa << BOOST_SERIALIZATION_NVP(first); | |
186 | oa << BOOST_SERIALIZATION_NVP(second); | |
187 | } | |
188 | ||
189 | template<class SP, class WP> | |
190 | void load3( | |
f67539c2 | 191 | const char * testfile, |
7c673cae FG |
192 | SP & first, |
193 | SP & second, | |
194 | WP & third | |
195 | ){ | |
196 | test_istream is(testfile, TEST_STREAM_FLAGS); | |
197 | test_iarchive ia(is, TEST_ARCHIVE_FLAGS); | |
198 | // note that we serialize the weak pointer first | |
199 | ia >> BOOST_SERIALIZATION_NVP(third); | |
200 | // inorder to test that a temporarily solitary weak pointer | |
201 | // correctly restored. | |
202 | ia >> BOOST_SERIALIZATION_NVP(first); | |
203 | ia >> BOOST_SERIALIZATION_NVP(second); | |
204 | } | |
205 | ||
206 | template<class SP, class WP> | |
207 | void save_and_load3( | |
208 | SP & first, | |
209 | SP & second, | |
210 | WP & third | |
211 | ){ | |
212 | const char * testfile = boost::archive::tmpnam(NULL); | |
213 | BOOST_REQUIRE(NULL != testfile); | |
214 | ||
215 | save3(testfile, first, second, third); | |
216 | ||
217 | // Clear the pointers, thereby destroying the objects they contain | |
218 | first.reset(); | |
219 | second.reset(); | |
220 | third.reset(); | |
221 | ||
222 | load3(testfile, first, second, third); | |
223 | ||
224 | BOOST_CHECK(first == second); | |
225 | BOOST_CHECK(first == third.lock()); | |
226 | std::remove(testfile); | |
227 | } | |
228 | ||
229 | template<class SP> | |
230 | void save4(const char * testfile, const SP & spc) | |
231 | { | |
232 | test_ostream os(testfile, TEST_STREAM_FLAGS); | |
233 | test_oarchive oa(os, TEST_ARCHIVE_FLAGS); | |
234 | oa << BOOST_SERIALIZATION_NVP(spc); | |
235 | } | |
236 | ||
237 | template<class SP> | |
238 | void load4(const char * testfile, SP & spc) | |
239 | { | |
240 | test_istream is(testfile, TEST_STREAM_FLAGS); | |
241 | test_iarchive ia(is, TEST_ARCHIVE_FLAGS); | |
242 | ia >> BOOST_SERIALIZATION_NVP(spc); | |
243 | } | |
244 | ||
245 | // trivial test | |
246 | template<class SP> | |
247 | void save_and_load4(SP & spc) | |
248 | { | |
249 | const char * testfile = boost::archive::tmpnam(NULL); | |
250 | BOOST_REQUIRE(NULL != testfile); | |
251 | save4(testfile, spc); | |
252 | SP spc1; | |
253 | load4(testfile, spc1); | |
254 | ||
255 | BOOST_CHECK( | |
256 | (spc.get() == NULL && spc1.get() == NULL) | |
257 | || * spc == * spc1 | |
258 | ); | |
259 | std::remove(testfile); | |
260 | } | |
261 | ||
262 | // This does the tests | |
263 | template<template<class T> class SPT , template<class T> class WPT > | |
264 | bool test(){ | |
265 | { | |
266 | SPT<A> spa; | |
267 | // These are our shared_ptrs | |
268 | spa = SPT<A>(new A); | |
269 | SPT<A> spa1 = spa; | |
270 | spa1 = spa; | |
271 | } | |
272 | { | |
273 | // These are our shared_ptrs | |
274 | SPT<A> spa; | |
275 | ||
276 | // trivial test 1 | |
277 | save_and_load(spa); | |
f67539c2 | 278 | |
7c673cae FG |
279 | //trivival test 2 |
280 | spa = SPT<A>(new A); | |
281 | save_and_load(spa); | |
282 | ||
283 | // Try to save and load pointers to As | |
284 | spa = SPT<A>(new A); | |
285 | SPT<A> spa1 = spa; | |
286 | save_and_load2(spa, spa1); | |
287 | ||
288 | // Try to save and load pointers to Bs | |
289 | spa = SPT<A>(new B); | |
290 | spa1 = spa; | |
291 | save_and_load2(spa, spa1); | |
292 | ||
293 | // test a weak pointer | |
294 | spa = SPT<A>(new A); | |
295 | spa1 = spa; | |
296 | WPT<A> wp = spa; | |
297 | save_and_load3(spa, spa1, wp); | |
f67539c2 | 298 | |
7c673cae FG |
299 | // obj of type B gets destroyed |
300 | // as smart_ptr goes out of scope | |
301 | } | |
302 | BOOST_CHECK(A::count == 0); | |
303 | { | |
304 | // Try to save and load pointers to Cs | |
305 | SPT<C> spc; | |
306 | spc = SPT<C>(new C); | |
307 | save_and_load4(spc); | |
308 | } | |
309 | BOOST_CHECK(C::count == 0); | |
310 | return true; | |
311 | } | |
312 | // This does the tests | |
313 | int test_main(int /* argc */, char * /* argv */[]) | |
314 | { | |
315 | bool result = true; | |
316 | result &= test<boost::shared_ptr, boost::weak_ptr>(); | |
317 | #ifndef BOOST_NO_CXX11_SMART_PTR | |
318 | result &= test<std::shared_ptr, std::weak_ptr>(); | |
319 | #endif | |
320 | return result ? EXIT_SUCCESS : EXIT_FAILURE; | |
321 | } | |
322 |