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