1/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2// test_shared_ptr_multi_base.cpp
3
4// (C) Copyright 2002 Robert Ramey- http://www.rrsd.com and Takatoshi Kondo.
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)
17namespace std{
18 using ::remove;
19}
20#endif
21
22#include <boost/serialization/nvp.hpp>
23#include <boost/serialization/export.hpp>
24
25#include <boost/serialization/shared_ptr.hpp>
26#include <boost/serialization/weak_ptr.hpp>
27
28#include "test_tools.hpp"
29
30struct Base1 {
31 Base1() {}
32 Base1(int x) : m_x(1 + x) {}
33 virtual ~Base1(){
34 }
35 int m_x;
36 // serialize
37 friend class boost::serialization::access;
38 template<class Archive>
39 void serialize(Archive &ar, const unsigned int /* file_version */)
40 {
41 ar & BOOST_SERIALIZATION_NVP(m_x);
42 }
43};
44
45struct Base2 {
46 Base2() {}
47 Base2(int x) : m_x(2 + x) {}
48 int m_x;
49 virtual ~Base2(){
50 }
51 // serialize
52 friend class boost::serialization::access;
53 template<class Archive>
54 void serialize(Archive &ar, const unsigned int /* file_version */)
55 {
56 ar & BOOST_SERIALIZATION_NVP(m_x);
57 }
58};
59
60struct Base3 {
61 Base3() {}
62 Base3(int x) : m_x(3 + x) {}
63 virtual ~Base3(){
64 }
65 int m_x;
66 // serialize
67 friend class boost::serialization::access;
68 template<class Archive>
69 void serialize(Archive &ar, const unsigned int /* file_version */)
70 {
71 ar & BOOST_SERIALIZATION_NVP(m_x);
72 }
73};
74
75// Sub is a subclass of Base1, Base1 and Base3.
76struct Sub:public Base1, public Base2, public Base3 {
77 static int count;
78 Sub() {
79 ++count;
80 }
81 Sub(int x) :
82 Base1(x),
83 Base2(x),
84 m_x(x)
85 {
86 ++count;
87 }
88 Sub(const Sub & rhs) :
89 m_x(rhs.m_x)
90 {
91 ++count;
92 }
93 virtual ~Sub() {
94 assert(0 < count);
95 --count;
96 }
97 int m_x;
98 // serialize
99 friend class boost::serialization::access;
100 template<class Archive>
101 void serialize(Archive &ar, const unsigned int /* file_version */)
102 {
103 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base1);
104 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base2);
105 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base3);
106 ar & BOOST_SERIALIZATION_NVP(m_x);
107 }
108};
109
110// Sub needs to be exported because its serialized via a base class pointer
111BOOST_CLASS_EXPORT(Sub)
112BOOST_SERIALIZATION_SHARED_PTR(Sub)
113
114int Sub::count = 0;
115
116template <class FIRST, class SECOND>
117void save2(
118 const char * testfile,
119 const FIRST& first,
120 const SECOND& second
121){
122 test_ostream os(testfile, TEST_STREAM_FLAGS);
123 test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
124 oa << BOOST_SERIALIZATION_NVP(first);
125 oa << BOOST_SERIALIZATION_NVP(second);
126}
127
128template <class FIRST, class SECOND>
129void load2(
130 const char * testfile,
131 FIRST& first,
132 SECOND& second)
133{
134 test_istream is(testfile, TEST_STREAM_FLAGS);
135 test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
136 ia >> BOOST_SERIALIZATION_NVP(first);
137 ia >> BOOST_SERIALIZATION_NVP(second);
138}
139
140// Run tests by serializing two shared_ptrs into an archive,
141// clearing them (deleting the objects) and then reloading the
142// objects back from an archive.
143
144template<class T, class U>
145boost::shared_ptr<T> dynamic_pointer_cast(boost::shared_ptr<U> const & u)
146BOOST_NOEXCEPT
147{
148 return boost::dynamic_pointer_cast<T>(u);
149}
150
151#ifndef BOOST_NO_CXX11_SMART_PTR
152template<class T, class U>
153std::shared_ptr<T> dynamic_pointer_cast(std::shared_ptr<U> const & u)
154BOOST_NOEXCEPT
155{
156 return std::dynamic_pointer_cast<T>(u);
157}
158#endif
159
160// Serialization sequence
161// First, shared_ptr
162// Second, weak_ptr
163template <class SP, class WP>
164void shared_weak(
165 SP & first,
166 WP & second
167){
168 const char * testfile = boost::archive::tmpnam(NULL);
169 BOOST_REQUIRE(NULL != testfile);
170 int firstm = first->m_x;
171
172 BOOST_REQUIRE(! second.expired());
173 int secondm = second.lock()->m_x;
174 save2(testfile, first, second);
175
176 // Clear the pointers, thereby destroying the objects they contain
177 second.reset();
178 first.reset();
179
180 load2(testfile, first, second);
181 BOOST_CHECK(! second.expired());
182
183 // Check data member
184 BOOST_CHECK(firstm == first->m_x);
185 BOOST_CHECK(secondm == second.lock()->m_x);
186 // Check pointer to vtable
187 BOOST_CHECK(::dynamic_pointer_cast<Sub>(first));
188 BOOST_CHECK(::dynamic_pointer_cast<Sub>(second.lock()));
189
190 std::remove(filename: testfile);
191}
192
193// Serialization sequence
194// First, weak_ptr
195// Second, shared_ptr
196template <class WP, class SP>
197void weak_shared(
198 WP & first,
199 SP & second
200){
201 const char * testfile = boost::archive::tmpnam(NULL);
202 BOOST_REQUIRE(NULL != testfile);
203 BOOST_CHECK(! first.expired());
204 int firstm = first.lock()->m_x;
205 int secondm = second->m_x;
206 save2(testfile, first, second);
207
208 // Clear the pointers, thereby destroying the objects they contain
209 first.reset();
210 second.reset();
211
212 load2(testfile, first, second);
213 BOOST_CHECK(! first.expired());
214
215 // Check data member
216 BOOST_CHECK(firstm == first.lock()->m_x);
217 BOOST_CHECK(secondm == second->m_x);
218 // Check pointer to vtable
219 BOOST_CHECK(::dynamic_pointer_cast<Sub>(first.lock()));
220 BOOST_CHECK(::dynamic_pointer_cast<Sub>(second));
221
222 std::remove(filename: testfile);
223}
224
225// This does the tests
226template<template<class T> class SPT, template<class T> class WPT>
227bool test(){
228 // Both Sub
229 SPT<Sub> tc1_sp(new Sub(10));
230 WPT<Sub> tc1_wp(tc1_sp);
231 shared_weak(tc1_sp, tc1_wp);
232 weak_shared(tc1_wp, tc1_sp);
233 tc1_sp.reset();
234 BOOST_CHECK(0 == Sub::count);
235
236 // Sub and Base1
237 SPT<Sub> tc2_sp(new Sub(10));
238 WPT<Base1> tc2_wp(tc2_sp);
239 shared_weak(tc2_sp, tc2_wp);
240 weak_shared(tc2_wp, tc2_sp);
241 tc2_sp.reset();
242 BOOST_CHECK(0 == Sub::count);
243
244 // Sub and Base2
245 SPT<Sub> tc3_sp(new Sub(10));
246 WPT<Base2> tc3_wp(tc3_sp);
247 shared_weak(tc3_sp, tc3_wp);
248 weak_shared(tc3_wp, tc3_sp);
249 tc3_sp.reset();
250 BOOST_CHECK(0 == Sub::count);
251
252 // Sub and Base3
253 SPT<Sub> tc4_sp(new Sub(10));
254 WPT<Base3> tc4_wp(tc4_sp);
255 shared_weak(tc4_sp, tc4_wp);
256 weak_shared(tc4_wp, tc4_sp);
257 tc4_sp.reset();
258 BOOST_CHECK(0 == Sub::count);
259
260 // Base1 and Base2
261 SPT<Sub> tc5_sp_tmp(new Sub(10));
262 SPT<Base1> tc5_sp(tc5_sp_tmp);
263 WPT<Base2> tc5_wp(tc5_sp_tmp);
264 tc5_sp_tmp.reset();
265 shared_weak(tc5_sp, tc5_wp);
266 weak_shared(tc5_wp, tc5_sp);
267 tc5_sp.reset();
268 BOOST_CHECK(0 == Sub::count);
269
270 // Base2 and Base3
271 SPT<Sub> tc6_sp_tmp(new Sub(10));
272 SPT<Base2> tc6_sp(tc6_sp_tmp);
273 WPT<Base3> tc6_wp(tc6_sp_tmp);
274 tc6_sp_tmp.reset();
275 shared_weak(tc6_sp, tc6_wp);
276 weak_shared(tc6_wp, tc6_sp);
277 tc6_sp.reset();
278 BOOST_CHECK(0 == Sub::count);
279
280 // Base3 and Base1
281 SPT<Sub> tc7_sp_tmp(new Sub(10));
282 SPT<Base3> tc7_sp(tc7_sp_tmp);
283 WPT<Base1> tc7_wp(tc7_sp_tmp);
284 tc7_sp_tmp.reset();
285 shared_weak(tc7_sp, tc7_wp);
286 weak_shared(tc7_wp, tc7_sp);
287 tc7_sp.reset();
288 BOOST_CHECK(0 == Sub::count);
289
290 return true;
291}
292
293// This does the tests
294int test_main(int /* argc */, char * /* argv */[])
295{
296 bool result = true;
297 result &= test<boost::shared_ptr, boost::weak_ptr>();
298 #ifndef BOOST_NO_CXX11_SMART_PTR
299 result &= test<std::shared_ptr, std::weak_ptr>();
300 #endif
301 return result ? EXIT_SUCCESS : EXIT_FAILURE;
302}
303

source code of boost/libs/serialization/test/test_shared_ptr_multi_base.cpp