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