1/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2// test_reset_object_address.cpp
3
4// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
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#include <sstream>
10#include <cassert>
11#include <cstdlib> // for rand()
12#include <cstddef> // size_t
13
14#include <boost/config.hpp>
15#if defined(BOOST_NO_STDC_NAMESPACE)
16namespace std{
17 using ::rand;
18 using ::size_t;
19}
20#endif
21
22#include "test_tools.hpp"
23
24#include <boost/archive/text_oarchive.hpp>
25#include <boost/archive/text_iarchive.hpp>
26#include <boost/archive/polymorphic_text_oarchive.hpp>
27#include <boost/archive/polymorphic_text_iarchive.hpp>
28
29#include <boost/serialization/list.hpp>
30#include <boost/serialization/access.hpp>
31
32// Someday, maybe all tests will be converted to the unit test framework.
33// but for now use the text execution monitor to be consistent with all
34// the other tests.
35
36// simple test of untracked value
37#include "A.hpp"
38#include "A.ipp"
39
40void test1(){
41 std::stringstream ss;
42 const A a;
43 {
44 boost::archive::text_oarchive oa(ss);
45 oa << a;
46 ss.flush();
47 }
48 A a1;
49 {
50 boost::archive::text_iarchive ia(ss);
51 // load to temporary
52 A a2;
53 ia >> a2;
54 BOOST_CHECK_EQUAL(a, a2);
55 // move to final destination
56 a1 = a2;
57 ia.reset_object_address(new_address: & a1, old_address: & a2);
58 }
59 BOOST_CHECK_EQUAL(a, a1);
60}
61
62// simple test of tracked value
63class B {
64 friend class boost::serialization::access;
65 int m_i;
66 template<class Archive>
67 void serialize(Archive &ar, const unsigned int /*file_version*/){
68 ar & m_i;
69 }
70public:
71 bool operator==(const B & rhs) const {
72 return m_i == rhs.m_i;
73 }
74 B() :
75 m_i(std::rand())
76 {}
77};
78
79//BOOST_TEST_DONT_PRINT_LOG_VALUE( B )
80
81void test2(){
82 std::stringstream ss;
83 B const b;
84 B const * const b_ptr = & b;
85 BOOST_CHECK_EQUAL(& b, b_ptr);
86 {
87 boost::archive::text_oarchive oa(ss);
88 oa << b;
89 oa << b_ptr;
90 ss.flush();
91 }
92 B b1;
93 B * b1_ptr;
94 {
95 boost::archive::text_iarchive ia(ss);
96 // load to temporary
97 B b2;
98 ia >> b2;
99 BOOST_CHECK_EQUAL(b, b2);
100 // move to final destination
101 b1 = b2;
102 ia.reset_object_address(new_address: & b1, old_address: & b2);
103 ia >> b1_ptr;
104 }
105 BOOST_CHECK_EQUAL(b, b1);
106 BOOST_CHECK_EQUAL(& b1, b1_ptr);
107}
108
109// check that nested member values are properly moved
110class D {
111 friend class boost::serialization::access;
112 template<class Archive>
113 void serialize(Archive &ar, const unsigned int /*file_version*/){
114 ar & m_b;
115 }
116public:
117 B m_b;
118 bool operator==(const D & rhs) const {
119 return m_b == rhs.m_b;
120 }
121 D(){}
122};
123
124//BOOST_TEST_DONT_PRINT_LOG_VALUE( D )
125
126void test3(){
127 std::stringstream ss;
128 D const d;
129 B const * const b_ptr = & d.m_b;
130 {
131 boost::archive::text_oarchive oa(ss);
132 oa << d;
133 oa << b_ptr;
134 ss.flush();
135 }
136 D d1;
137 B * b1_ptr;
138 {
139 boost::archive::text_iarchive ia(ss);
140 D d2;
141 ia >> d2;
142 d1 = d2;
143 ia.reset_object_address(new_address: & d1, old_address: & d2);
144 ia >> b1_ptr;
145 }
146 BOOST_CHECK_EQUAL(d, d1);
147 BOOST_CHECK_EQUAL(* b_ptr, * b1_ptr);
148}
149
150// check that data pointed to by pointer members is NOT moved
151class E {
152 int m_i;
153 friend class boost::serialization::access;
154 template<class Archive>
155 void serialize(Archive &ar, const unsigned int /*file_version*/){
156 ar & m_i;
157 }
158public:
159 bool operator==(const E &rhs) const {
160 return m_i == rhs.m_i;
161 }
162 E() :
163 m_i(std::rand())
164 {}
165 E(const E & rhs) :
166 m_i(rhs.m_i)
167 {}
168};
169//BOOST_TEST_DONT_PRINT_LOG_VALUE( E )
170
171// check that moves don't move stuff pointed to
172class F {
173 friend class boost::serialization::access;
174 E * m_eptr;
175 template<class Archive>
176 void serialize(Archive &ar, const unsigned int /*file_version*/){
177 ar & m_eptr;
178 }
179public:
180 bool operator==(const F &rhs) const {
181 return *m_eptr == *rhs.m_eptr;
182 }
183 F & operator=(const F & rhs) {
184 * m_eptr = * rhs.m_eptr;
185 return *this;
186 }
187 F(){
188 m_eptr = new E;
189 }
190 F(const F & rhs){
191 *this = rhs;
192 }
193 ~F(){
194 delete m_eptr;
195 }
196};
197
198//BOOST_TEST_DONT_PRINT_LOG_VALUE( F )
199
200void test4(){
201 std::stringstream ss;
202 const F f;
203 {
204 boost::archive::text_oarchive oa(ss);
205 oa << f;
206 ss.flush();
207 }
208 F f1;
209 {
210 boost::archive::text_iarchive ia(ss);
211 F f2;
212 ia >> f2;
213 f1 = f2;
214 ia.reset_object_address(new_address: & f1, old_address: & f2);
215 }
216 BOOST_CHECK_EQUAL(f, f1);
217}
218
219// check that multiple moves keep track of the correct target
220class G {
221 friend class boost::serialization::access;
222 A m_a1;
223 A m_a2;
224 A *m_pa2;
225 template<class Archive>
226 void save(Archive &ar, const unsigned int /*file_version*/) const {
227 ar << m_a1;
228 ar << m_a2;
229 ar << m_pa2;
230 }
231 template<class Archive>
232 void load(Archive &ar, const unsigned int /*file_version*/){
233 A a; // temporary A
234 ar >> a;
235 m_a1 = a;
236 ar.reset_object_address(& m_a1, & a);
237 ar >> a;
238 m_a2 = a;
239 ar.reset_object_address(& m_a2, & a);
240 ar & m_pa2;
241 }
242 BOOST_SERIALIZATION_SPLIT_MEMBER()
243public:
244 bool operator==(const G &rhs) const {
245 return
246 m_a1 == rhs.m_a1
247 && m_a2 == rhs.m_a2
248 && *m_pa2 == *rhs.m_pa2;
249 }
250 G & operator=(const G & rhs) {
251 m_a1 = rhs.m_a1;
252 m_a2 = rhs.m_a2;
253 m_pa2 = & m_a2;
254 return *this;
255 }
256 G(){
257 m_pa2 = & m_a2;
258 }
259 G(const G & rhs){
260 *this = rhs;
261 }
262 ~G(){}
263};
264
265//BOOST_TEST_DONT_PRINT_LOG_VALUE( G )
266
267void test5(){
268 std::stringstream ss;
269 const G g;
270 {
271 boost::archive::text_oarchive oa(ss);
272 oa << g;
273 ss.flush();
274 }
275 G g1;
276 {
277 boost::archive::text_iarchive ia(ss);
278 ia >> g1;
279 }
280 BOOST_CHECK_EQUAL(g, g1);
281}
282
283// joaquin's test - this tests the case where rest_object_address
284// is applied to an item which in fact is not tracked so that
285// the call is in fact superfluous.
286struct foo
287{
288 int x;
289
290private:
291 friend class boost::serialization::access;
292
293 template<class Archive>
294 void serialize(Archive &,const unsigned int)
295 {
296 }
297};
298
299struct bar
300{
301 foo f[2];
302 foo* pf[2];
303
304private:
305 friend class boost::serialization::access;
306 BOOST_SERIALIZATION_SPLIT_MEMBER()
307
308 template<class Archive>
309 void save(Archive& ar,const unsigned int)const
310 {
311 for(int i=0;i<2;++i){
312 ar<<f[i].x;
313 ar<<f[i];
314 }
315 for(int j=0;j<2;++j){
316 ar<<pf[j];
317 }
318 }
319
320 template<class Archive>
321 void load(Archive& ar,const unsigned int)
322 {
323 for(int i=0;i<2;++i){
324 int x;
325 ar>>x;
326 f[i].x=x;
327 ar.reset_object_address(&f[i].x,&x);
328 ar>>f[i];
329 }
330 for(int j=0;j<2;++j){
331 ar>>pf[j];
332 }
333 }
334};
335
336int test6()
337{
338 bar b;
339 b.f[0].x=0;
340 b.f[1].x=1;
341 b.pf[0]=&b.f[0];
342 b.pf[1]=&b.f[1];
343
344 std::ostringstream oss;
345 {
346 boost::archive::text_oarchive oa(oss);
347 oa<<const_cast<const bar&>(b);
348 oss.flush();
349 }
350
351 bar b1;
352 b1.pf[0]=0;
353 b1.pf[1]=0;
354
355 std::istringstream iss(oss.str());
356 boost::archive::text_iarchive ia(iss);
357 ia>>b1;
358 BOOST_CHECK(b1.pf[0]==&b1.f[0]&&b1.pf[1]==&b1.f[1]);
359
360 return 0;
361}
362
363// test one of the collections
364void test7(){
365 std::stringstream ss;
366 B const b;
367 B const * const b_ptr = & b;
368 BOOST_CHECK_EQUAL(& b, b_ptr);
369 {
370 std::list<const B *> l;
371 l.push_back(x: b_ptr);
372 boost::archive::text_oarchive oa(ss);
373 oa << const_cast<const std::list<const B *> &>(l);
374 ss.flush();
375 }
376 B b1;
377 {
378 std::list<B *> l;
379 boost::archive::text_iarchive ia(ss);
380 ia >> l;
381 delete l.front(); // prevent memory leak
382 }
383}
384
385// test one of the collections with polymorphic archive
386void test8(){
387 std::stringstream ss;
388 B const b;
389 B const * const b_ptr = & b;
390 BOOST_CHECK_EQUAL(& b, b_ptr);
391 {
392 std::list<const B *> l;
393 l.push_back(x: b_ptr);
394 boost::archive::polymorphic_text_oarchive oa(ss);
395 boost::archive::polymorphic_oarchive & poa = oa;
396 poa << const_cast<const std::list<const B *> &>(l);
397 }
398 B b1;
399 {
400 std::list<B *> l;
401 boost::archive::polymorphic_text_iarchive ia(ss);
402 boost::archive::polymorphic_iarchive & pia = ia;
403 pia >> l;
404 delete l.front(); // prevent memory leak
405 }
406}
407
408int test_main(int /* argc */, char * /* argv */[])
409{
410 test1();
411 test2();
412 test3();
413 test4();
414 test5();
415 test6();
416 test7();
417 test8();
418 return EXIT_SUCCESS;
419}
420

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