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)
17namespace 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
33class J : public A
34{
35private:
36 friend class boost::serialization::access;
37 template<class Archive>
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 }
42public:
43 bool operator==(const J &rhs) const;
44 J *j;
45 J(J *_j) : j(_j) {}
46 J() : j(NULL){}
47};
48
49BOOST_CLASS_VERSION(J, 6)
50
51bool 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. Permitting this to go undetected would result in the
66// creation of multiple equal objects rather than the original
67// structure.
68class K
69{
70 J j1;
71 J j2;
72 J j3;
73 friend class boost::serialization::access;
74 template<class Archive>
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 }
83public:
84 bool operator==(const K &rhs) const;
85 K();
86};
87
88K::K()
89: j1(&j2), j2(&j3), j3(&j1)
90{
91}
92
93bool 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
105int 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(filename: testfile);
123 return EXIT_SUCCESS;
124}
125
126int 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(filename: testfile);
148 return EXIT_SUCCESS;
149}
150
151int 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(filename: testfile);
193 return EXIT_SUCCESS;
194}
195
196int test_main( int /* argc */, char* /* argv */[] ){
197 test1();
198 test2();
199 test3();
200 return EXIT_SUCCESS;
201}
202
203// EOF
204

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