1 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
2 | // test_shared_ptr.cpp |
3 | |
4 | // (C) Copyright 2002 Robert Ramey- http://www.rrsd.com - David Tonge . |
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 <fstream> |
13 | |
14 | #include <cstdio> // remove |
15 | #include <boost/config.hpp> |
16 | #if defined(BOOST_NO_STDC_NAMESPACE) |
17 | namespace std{ |
18 | using ::remove; |
19 | } |
20 | #endif |
21 | |
22 | #include "test_tools.hpp" |
23 | |
24 | #include <boost/serialization/shared_ptr_132.hpp> |
25 | #include <boost/serialization/shared_ptr.hpp> |
26 | #include <boost/serialization/weak_ptr.hpp> |
27 | #include <boost/serialization/split_member.hpp> |
28 | |
29 | #include <boost/preprocessor/stringize.hpp> |
30 | |
31 | #include <boost/serialization/nvp.hpp> |
32 | #include <boost/serialization/export.hpp> |
33 | |
34 | // This is a simple class. It contains a counter of the number |
35 | // of objects of this class which have been instantiated. |
36 | class A |
37 | { |
38 | private: |
39 | friend class boost::serialization::access; |
40 | int x; |
41 | template<class Archive> |
42 | void save(Archive & ar, const unsigned int /* file_version */) const { |
43 | ar << BOOST_SERIALIZATION_NVP(x); |
44 | } |
45 | template<class Archive> |
46 | void load(Archive & ar, const unsigned int /* file_version */) { |
47 | ar >> BOOST_SERIALIZATION_NVP(x); |
48 | } |
49 | BOOST_SERIALIZATION_SPLIT_MEMBER() |
50 | public: |
51 | static int count; |
52 | bool operator==(const A & rhs) const { |
53 | return x == rhs.x; |
54 | } |
55 | A(){++count;} // default constructor |
56 | virtual ~A(){--count;} // default destructor |
57 | }; |
58 | |
59 | BOOST_SERIALIZATION_SHARED_PTR(A) |
60 | |
61 | // B is a subclass of A |
62 | class B : public A |
63 | { |
64 | private: |
65 | friend class boost::serialization::access; |
66 | template<class Archive> |
67 | void save(Archive & ar, const unsigned int /* file_version */ )const { |
68 | ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(A); |
69 | } |
70 | template<class Archive> |
71 | void load(Archive & ar, const unsigned int /* file_version */){ |
72 | ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(A); |
73 | } |
74 | BOOST_SERIALIZATION_SPLIT_MEMBER() |
75 | public: |
76 | static int count; |
77 | B() : A() {}; |
78 | virtual ~B() {}; |
79 | }; |
80 | |
81 | // B needs to be exported because its serialized via a base class pointer |
82 | BOOST_SHARED_POINTER_EXPORT(B) |
83 | BOOST_SERIALIZATION_SHARED_PTR(B) |
84 | |
85 | int A::count = 0; |
86 | |
87 | template<class T> |
88 | void save(const char * testfile, const T & spa) |
89 | { |
90 | test_ostream os(testfile, TEST_STREAM_FLAGS); |
91 | test_oarchive oa(os, TEST_ARCHIVE_FLAGS); |
92 | oa << BOOST_SERIALIZATION_NVP(spa); |
93 | } |
94 | |
95 | template<class T> |
96 | void load(const char * testfile, T & spa) |
97 | { |
98 | test_istream is(testfile, TEST_STREAM_FLAGS); |
99 | test_iarchive ia(is, TEST_ARCHIVE_FLAGS); |
100 | ia >> BOOST_SERIALIZATION_NVP(spa); |
101 | } |
102 | |
103 | // trivial test |
104 | template<class T> |
105 | void save_and_load(const T & spa) |
106 | { |
107 | const char * testfile = boost::archive::tmpnam(NULL); |
108 | BOOST_REQUIRE(NULL != testfile); |
109 | save(testfile, spa); |
110 | |
111 | // note that we're loading to a current version of shared_ptr |
112 | // regardless of the original saved type - this tests backward |
113 | // archive compatibility |
114 | boost::shared_ptr<A> spa1; |
115 | load(testfile, spa&: spa1); |
116 | |
117 | BOOST_CHECK( |
118 | (spa.get() == NULL && spa1.get() == NULL) |
119 | || * spa == * spa1 |
120 | ); |
121 | std::remove(filename: testfile); |
122 | } |
123 | |
124 | template<class T> |
125 | void save2( |
126 | const char * testfile, |
127 | const T & first, |
128 | const T & second |
129 | ){ |
130 | test_ostream os(testfile, TEST_STREAM_FLAGS); |
131 | test_oarchive oa(os, TEST_ARCHIVE_FLAGS); |
132 | oa << BOOST_SERIALIZATION_NVP(first); |
133 | oa << BOOST_SERIALIZATION_NVP(second); |
134 | } |
135 | |
136 | template<class T> |
137 | void load2( |
138 | const char * testfile, |
139 | T & first, |
140 | T & second) |
141 | { |
142 | test_istream is(testfile, TEST_STREAM_FLAGS); |
143 | test_iarchive ia(is, TEST_ARCHIVE_FLAGS); |
144 | ia >> BOOST_SERIALIZATION_NVP(first); |
145 | ia >> BOOST_SERIALIZATION_NVP(second); |
146 | } |
147 | |
148 | // Run tests by serializing two shared_ptrs into an archive, |
149 | // clearing them (deleting the objects) and then reloading the |
150 | // objects back from an archive. |
151 | template<class T> |
152 | void save_and_load2(T & first, T & second) |
153 | { |
154 | const char * testfile = boost::archive::tmpnam(NULL); |
155 | BOOST_REQUIRE(NULL != testfile); |
156 | |
157 | save2(testfile, first, second); |
158 | |
159 | // Clear the pointers, thereby destroying the objects they contain |
160 | first.reset(); |
161 | second.reset(); |
162 | |
163 | boost::shared_ptr<A> first1, second1; |
164 | load2(testfile, first&: first1, second&: second1); |
165 | |
166 | BOOST_CHECK(first1 == second1); |
167 | std::remove(filename: testfile); |
168 | } |
169 | |
170 | template<class T> |
171 | void save3( |
172 | const char * testfile, |
173 | const T & first, |
174 | const T & second, |
175 | const T & third |
176 | ){ |
177 | test_ostream os(testfile, TEST_STREAM_FLAGS); |
178 | test_oarchive oa(os, TEST_ARCHIVE_FLAGS); |
179 | oa << BOOST_SERIALIZATION_NVP(third); |
180 | oa << BOOST_SERIALIZATION_NVP(first); |
181 | oa << BOOST_SERIALIZATION_NVP(second); |
182 | } |
183 | |
184 | template<class T> |
185 | void load3( |
186 | const char * testfile, |
187 | T & first, |
188 | T & second, |
189 | T & third |
190 | ){ |
191 | test_istream is(testfile, TEST_STREAM_FLAGS); |
192 | test_iarchive ia(is, TEST_ARCHIVE_FLAGS); |
193 | // note that we serialize the weak pointer first |
194 | ia >> BOOST_SERIALIZATION_NVP(third); |
195 | // inorder to test that a temporarily solitary weak pointer |
196 | // correctly restored. |
197 | ia >> BOOST_SERIALIZATION_NVP(first); |
198 | ia >> BOOST_SERIALIZATION_NVP(second); |
199 | } |
200 | |
201 | // This does the tests |
202 | int test_main(int /* argc */, char * /* argv */[]) |
203 | { |
204 | // These are our shared_ptrs |
205 | boost_132::shared_ptr<A> spa; |
206 | |
207 | // trivial test 1 |
208 | save_and_load(spa); |
209 | |
210 | //trivial test 2 |
211 | spa.reset(); |
212 | spa = boost_132::shared_ptr<A>(new A); |
213 | save_and_load(spa); |
214 | |
215 | // Try to save and load pointers to As, to a text archive |
216 | spa = boost_132::shared_ptr<A>(new A); |
217 | boost_132::shared_ptr<A> spa1 = spa; |
218 | save_and_load2(first&: spa, second&: spa1); |
219 | |
220 | // Try to save and load pointers to Bs, to a text archive |
221 | spa = boost_132::shared_ptr<A>(new B); |
222 | save_and_load(spa); |
223 | |
224 | spa1 = spa; |
225 | save_and_load2(first&: spa, second&: spa1); |
226 | |
227 | // obj of type B gets destroyed |
228 | // as smart_ptr goes out of scope |
229 | return EXIT_SUCCESS; |
230 | } |
231 | |