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