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>
save(Archive & ar,const unsigned int) const42 void save(Archive & ar, const unsigned int /* file_version */) const {
43 ar << BOOST_SERIALIZATION_NVP(x);
44 }
45 template<class Archive>
load(Archive & ar,const unsigned int)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;
operator ==(const A & rhs) const52 bool operator==(const A & rhs) const {
53 return x == rhs.x;
54 }
A()55 A(){++count;} // default constructor
~A()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>
save(Archive & ar,const unsigned int) const67 void save(Archive & ar, const unsigned int /* file_version */ )const {
68 ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(A);
69 }
70 template<class Archive>
load(Archive & ar,const unsigned int)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;
B()77 B() : A() {};
~B()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>
save(const char * testfile,const T & spa)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>
load(const char * testfile,T & spa)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>
save_and_load(const T & spa)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 orignal saved type - this tests backward
113 // archive compatibility
114 boost::shared_ptr<A> spa1;
115 load(testfile, spa1);
116
117 BOOST_CHECK(
118 (spa.get() == NULL && spa1.get() == NULL)
119 || * spa == * spa1
120 );
121 std::remove(testfile);
122 }
123
124 template<class T>
save2(const char * testfile,const T & first,const T & second)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>
load2(const char * testfile,T & first,T & second)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>
save_and_load2(T & first,T & second)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, first1, second1);
165
166 BOOST_CHECK(first1 == second1);
167 std::remove(testfile);
168 }
169
170 template<class T>
save3(const char * testfile,const T & first,const T & second,const T & third)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>
load3(const char * testfile,T & first,T & second,T & third)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 // correcttly restored.
197 ia >> BOOST_SERIALIZATION_NVP(first);
198 ia >> BOOST_SERIALIZATION_NVP(second);
199 }
200
201 // This does the tests
test_main(int,char * [])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(spa, 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(spa, spa1);
226
227 // obj of type B gets destroyed
228 // as smart_ptr goes out of scope
229 return EXIT_SUCCESS;
230 }
231