Ticket #3080: test_shared_ptr_multi_base.cpp

File test_shared_ptr_multi_base.cpp, 7.2 KB (added by Takatoshi Kondo <kondo@…>, 13 years ago)

TestCode

Line 
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 - David Tonge .
5// (C) Copyright 2009 Takatoshi Kondo.
6// Use, modification and distribution is subject to the Boost Software
7// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8// http://www.boost.org/LICENSE_1_0.txt)
9//
10// See http://www.boost.org for updates, documentation, and revision history.
11
12#include <cstddef> // NULL
13#include <cstdio> // remove
14#include <fstream>
15
16#include <boost/config.hpp>
17#if defined(BOOST_NO_STDC_NAMESPACE)
18namespace std{
19 using ::remove;
20}
21#endif
22#include <boost/type_traits/broken_compiler_spec.hpp>
23
24#include <boost/serialization/shared_ptr.hpp>
25#include <boost/serialization/weak_ptr.hpp>
26#include <boost/serialization/nvp.hpp>
27#include <boost/shared_ptr.hpp>
28#include <boost/weak_ptr.hpp>
29#include <boost/serialization/serialization.hpp>
30#include <boost/archive/xml_oarchive.hpp>
31#include <boost/archive/xml_iarchive.hpp>
32#include <boost/serialization/nvp.hpp>
33#include <boost/serialization/export.hpp>
34#include <boost/serialization/shared_ptr.hpp>
35#include <boost/serialization/weak_ptr.hpp>
36
37#include "test_tools.hpp"
38
39struct Base1 {
40 Base1() {}
41 Base1(int x) : m_x(1 + x) {}
42 virtual ~Base1() {}
43 int m_x;
44 // serialize
45 friend class boost::serialization::access;
46 template<class Archive>
47 void serialize(Archive &ar, const unsigned int /* file_version */)
48 {
49 ar & BOOST_SERIALIZATION_NVP(m_x);
50 }
51};
52
53//BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(Base1)
54BOOST_SERIALIZATION_SHARED_PTR(Base1)
55
56struct Base2 {
57 Base2() {}
58 Base2(int x) : m_x(2 + x) {}
59 int m_x;
60 virtual ~Base2() {}
61 // serialize
62 friend class boost::serialization::access;
63 template<class Archive>
64 void serialize(Archive &ar, const unsigned int /* file_version */)
65 {
66 ar & BOOST_SERIALIZATION_NVP(m_x);
67 }
68};
69
70//BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(Base2)
71BOOST_SERIALIZATION_SHARED_PTR(Base2)
72
73struct Base3 {
74 Base3() {}
75 Base3(int x) : m_x(3 + x) {}
76 virtual ~Base3() {}
77 int m_x;
78 // serialize
79 friend class boost::serialization::access;
80 template<class Archive>
81 void serialize(Archive &ar, const unsigned int /* file_version */)
82 {
83 ar & BOOST_SERIALIZATION_NVP(m_x);
84 }
85};
86
87//BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(Base3)
88BOOST_SERIALIZATION_SHARED_PTR(Base3)
89
90// Sub is a subclass of Base1, Base1 and Base3.
91struct Sub:public Base1, public Base2, public Base3 {
92 Sub() {}
93 Sub(int x) :
94 Base1(x),
95 Base2(x),
96 m_x(x)
97 {}
98 virtual ~Sub() {}
99 int m_x;
100 // serialize
101 friend class boost::serialization::access;
102 template<class Archive>
103 void serialize(Archive &ar, const unsigned int /* file_version */)
104 {
105 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base1);
106 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base2);
107 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base3);
108 ar & BOOST_SERIALIZATION_NVP(m_x);
109 }
110};
111
112// Sub needs to be exported because its serialized via a base class pointer
113BOOST_CLASS_EXPORT(Sub)
114BOOST_SERIALIZATION_SHARED_PTR(Sub)
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
144// Serialization sequence
145// First, shared_ptr
146// Second, weak_ptr
147template <class FIRST, class SECOND>
148void shared_weak(
149 boost::shared_ptr<FIRST>& first,
150 boost::weak_ptr<SECOND>& second
151){
152 const char * testfile = boost::archive::tmpnam(NULL);
153 BOOST_REQUIRE(NULL != testfile);
154 int firstm = first->m_x;
155 int secondm = second.lock()->m_x;
156 save2(testfile, first, second);
157
158 // Clear the pointers, thereby destroying the objects they contain
159 second.reset();
160 first.reset();
161
162 load2(testfile, first, second);
163
164 // Check data member
165 BOOST_CHECK(firstm == first->m_x);
166 BOOST_CHECK(secondm == second.lock()->m_x);
167 // Check pointer to vtable
168 BOOST_CHECK(boost::dynamic_pointer_cast<Sub>(first));
169 BOOST_CHECK(boost::dynamic_pointer_cast<Sub>(second.lock()));
170 std::remove(testfile);
171}
172
173// Serialization sequence
174// First, weak_ptr
175// Second, shared_ptr
176template <class FIRST, class SECOND>
177void weak_shared(
178 boost::weak_ptr<FIRST>& first,
179 boost::shared_ptr<SECOND>& second
180){
181 const char * testfile = boost::archive::tmpnam(NULL);
182 BOOST_REQUIRE(NULL != testfile);
183 int firstm = first.lock()->m_x;
184 int secondm = second->m_x;
185 save2(testfile, first, second);
186
187 // Clear the pointers, thereby destroying the objects they contain
188 first.reset();
189 second.reset();
190
191 load2(testfile, first, second);
192
193 // Check data member
194 BOOST_CHECK(firstm == first.lock()->m_x);
195 BOOST_CHECK(secondm == second->m_x);
196 // Check pointer to vtable
197 BOOST_CHECK(boost::dynamic_pointer_cast<Sub>(first.lock()));
198 BOOST_CHECK(boost::dynamic_pointer_cast<Sub>(second));
199 std::remove(testfile);
200}
201
202// This does the tests
203int test_main(int /* argc */, char * /* argv */[])
204{
205 // Both Sub
206 boost::shared_ptr<Sub> tc1_sp(new Sub(10));
207 boost::weak_ptr<Sub> tc1_wp(tc1_sp);
208 shared_weak(tc1_sp, tc1_wp);
209 weak_shared(tc1_wp, tc1_sp);
210
211 // Sub and Base1
212 boost::shared_ptr<Sub> tc2_sp(new Sub(10));
213 boost::weak_ptr<Base1> tc2_wp(tc2_sp);
214 shared_weak(tc2_sp, tc2_wp);
215 weak_shared(tc2_wp, tc2_sp);
216
217 // Sub and Base2
218 boost::shared_ptr<Sub> tc3_sp(new Sub(10));
219 boost::weak_ptr<Base2> tc3_wp(tc3_sp);
220 shared_weak(tc3_sp, tc3_wp);
221 weak_shared(tc3_wp, tc3_sp);
222
223 // Sub and Base3
224 boost::shared_ptr<Sub> tc4_sp(new Sub(10));
225 boost::weak_ptr<Base3> tc4_wp(tc4_sp);
226 shared_weak(tc4_sp, tc4_wp);
227 weak_shared(tc4_wp, tc4_sp);
228
229 // Base1 and Base2
230 boost::shared_ptr<Sub> tc5_sp_tmp(new Sub(10));
231 boost::shared_ptr<Base1> tc5_sp(tc5_sp_tmp);
232 boost::weak_ptr<Base2> tc5_wp(tc5_sp_tmp);
233 tc5_sp_tmp.reset();
234 shared_weak(tc5_sp, tc5_wp);
235 weak_shared(tc5_wp, tc5_sp);
236
237 // Base2 and Base3
238 boost::shared_ptr<Sub> tc6_sp_tmp(new Sub(10));
239 boost::shared_ptr<Base2> tc6_sp(tc6_sp_tmp);
240 boost::weak_ptr<Base3> tc6_wp(tc6_sp_tmp);
241 tc6_sp_tmp.reset();
242 shared_weak(tc6_sp, tc6_wp);
243 weak_shared(tc6_wp, tc6_sp);
244
245 // Base3 and Base1
246 boost::shared_ptr<Sub> tc7_sp_tmp(new Sub(10));
247 boost::shared_ptr<Base3> tc7_sp(tc7_sp_tmp);
248 boost::weak_ptr<Base1> tc7_wp(tc7_sp_tmp);
249 tc7_sp_tmp.reset();
250 shared_weak(tc7_sp, tc7_wp);
251 weak_shared(tc7_wp, tc7_sp);
252
253 return EXIT_SUCCESS;
254}