• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2 // test_cyclic_ptrs.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 // should pass compilation and execution
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 #include <boost/core/no_exceptions_support.hpp>
24 
25 #include <boost/serialization/nvp.hpp>
26 #include <boost/serialization/base_object.hpp>
27 
28 #include "A.hpp"
29 #include "A.ipp"
30 
31 ///////////////////////////////////////////////////////
32 // class with a member which refers to itself
33 class J : public A
34 {
35 private:
36     friend class boost::serialization::access;
37     template<class Archive>
serialize(Archive & ar,const unsigned int)38     void serialize(Archive &ar, const unsigned int /* file_version */){
39         ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(A);
40         ar & BOOST_SERIALIZATION_NVP(j);
41     }
42 public:
43     bool operator==(const J &rhs) const;
44     J *j;
J(J * _j)45     J(J *_j) : j(_j) {}
J()46     J() : j(NULL){}
47 };
48 
49 BOOST_CLASS_VERSION(J, 6)
50 
operator ==(const J & rhs) const51 bool J::operator==(const J &rhs) const
52 {
53     return static_cast<const A &>(*this) == static_cast<const A &>(rhs);
54 }
55 
56 ///////////////////////////////////////////////////////
57 // class with members that refer to each other
58 // this is an example of a class that, as written, cannot
59 // be serialized with this system.  The problem is that the
60 // serialization of the first member - j1 , provokes serialization
61 // of those objects which it points to either directly or indirectly.
62 // When those objects are subsequently serialized, it is discovered
63 // that have already been serialized through pointers.  This is
64 // detected by the system and an exception - pointer_conflict -
65 // is thrown.  Permiting this to go undetected would result in the
66 // creation of multiple equal objects rather than the original
67 // structure.
68 class K
69 {
70     J j1;
71     J j2;
72     J j3;
73     friend class boost::serialization::access;
74     template<class Archive>
serialize(Archive & ar,const unsigned int)75     void serialize(
76         Archive &ar,
77         const unsigned int /* file_version */
78     ){
79         ar & BOOST_SERIALIZATION_NVP(j1);
80         ar & BOOST_SERIALIZATION_NVP(j2);
81         ar & BOOST_SERIALIZATION_NVP(j3);
82     }
83 public:
84     bool operator==(const K &rhs) const;
85     K();
86 };
87 
K()88 K::K()
89 : j1(&j2), j2(&j3), j3(&j1)
90 {
91 }
92 
operator ==(const K & rhs) const93 bool K::operator==(const K &rhs) const
94 {
95     return
96         j1.j == & j2
97         && j2.j == & j3
98         && j3.j == & j1
99         && j1 == rhs.j1
100         && j2 == rhs.j2
101         && j3 == rhs.j3
102     ;
103 }
104 
test1()105 int test1(){
106     const char * testfile = boost::archive::tmpnam(NULL);
107     BOOST_REQUIRE(NULL != testfile);
108 
109     J j1, j2;
110     {
111         test_ostream os(testfile, TEST_STREAM_FLAGS);
112         test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
113         oa << BOOST_SERIALIZATION_NVP(j1);
114     }
115     {
116         // try to read the archive
117         test_istream is(testfile, TEST_STREAM_FLAGS);
118         test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
119         ia >> BOOST_SERIALIZATION_NVP(j2);
120     }
121     BOOST_CHECK(j1 == j2);
122     std::remove(testfile);
123     return EXIT_SUCCESS;
124 }
125 
test2()126 int test2(){
127     const char * testfile = boost::archive::tmpnam(NULL);
128     BOOST_REQUIRE(NULL != testfile);
129 
130     J *j1 = new J;
131     j1->j = j1;
132     J *j2 = reinterpret_cast<J *>(0xBAADF00D);
133     {
134         test_ostream os(testfile, TEST_STREAM_FLAGS);
135         test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
136         oa << BOOST_SERIALIZATION_NVP(j1);
137     }
138     {
139         // try to read the archive
140         test_istream is(testfile, TEST_STREAM_FLAGS);
141         test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
142         ia >> BOOST_SERIALIZATION_NVP(j2);
143     }
144     BOOST_CHECK(*j1 == *j2);
145     delete j1;
146     BOOST_CHECK(j2 == j2->j);
147     std::remove(testfile);
148     return EXIT_SUCCESS;
149 }
150 
test3()151 int test3(){
152     const char * testfile = boost::archive::tmpnam(NULL);
153     BOOST_REQUIRE(NULL != testfile);
154 
155     K k;
156     boost::archive::archive_exception exception(
157         boost::archive::archive_exception::no_exception
158     );
159     {
160         test_ostream os(testfile, TEST_STREAM_FLAGS);
161         test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
162         BOOST_TRY {
163             oa << BOOST_SERIALIZATION_NVP(k);
164         }
165         BOOST_CATCH (boost::archive::archive_exception const& ae){
166             exception = ae;
167         }
168         BOOST_CATCH_END
169         BOOST_CHECK(
170             exception.code == boost::archive::archive_exception::pointer_conflict
171         );
172     }
173     // if exception wasn't invoked
174     if(exception.code == boost::archive::archive_exception::no_exception){
175         // try to read the archive
176         test_istream is(testfile, TEST_STREAM_FLAGS);
177         test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
178         exception = boost::archive::archive_exception(
179             boost::archive::archive_exception::no_exception
180         );
181         BOOST_TRY {
182             ia >> BOOST_SERIALIZATION_NVP(k);
183         }
184         BOOST_CATCH (boost::archive::archive_exception const& ae){
185             exception = ae;
186         }
187         BOOST_CATCH_END
188         BOOST_CHECK(
189             exception.code == boost::archive::archive_exception::pointer_conflict
190         );
191     }
192     std::remove(testfile);
193     return EXIT_SUCCESS;
194 }
195 
test_main(int,char * [])196 int test_main( int /* argc */, char* /* argv */[] ){
197     test1();
198     test2();
199     test3();
200     return EXIT_SUCCESS;
201 }
202 
203 // EOF
204