Imported Upstream version 1.51.0
[platform/upstream/boost.git] / libs / serialization / test / test_cyclic_ptrs.cpp
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/detail/no_exceptions_support.hpp>
24
25 #include <boost/serialization/nvp.hpp>
26 #include <boost/serialization/version.hpp>
27 #include <boost/serialization/base_object.hpp>
28
29 #include "A.hpp"
30 #include "A.ipp"
31
32 ///////////////////////////////////////////////////////
33 // class with a member which refers to itself
34 class J : public A
35 {
36 private:
37     friend class boost::serialization::access;
38     template<class Archive>
39     void serialize(Archive &ar, const unsigned int /* file_version */){
40         ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(A);
41         ar & BOOST_SERIALIZATION_NVP(j);
42     }
43 public:
44     bool operator==(const J &rhs) const;
45     J *j;
46     J(J *_j) : j(_j) {}
47     J() : j(NULL){}
48 };
49
50 BOOST_CLASS_VERSION(J, 6)
51
52 bool J::operator==(const J &rhs) const
53 {
54     return static_cast<const A &>(*this) == static_cast<const A &>(rhs);
55 }
56
57 ///////////////////////////////////////////////////////
58 // class with members that refer to each other
59 // this is an example of a class that, as written, cannot
60 // be serialized with this system.  The problem is that the
61 // serialization of the first member - j1 , provokes serialization
62 // of those objects which it points to either directly or indirectly.
63 // When those objects are subsequently serialized, it is discovered
64 // that have already been serialized through pointers.  This is
65 // detected by the system and an exception - pointer_conflict - 
66 // is thrown.  Permiting this to go undetected would result in the
67 // creation of multiple equal objects rather than the original
68 // structure.  
69 class K
70 {
71     J j1;
72     J j2;
73     J j3;
74     friend class boost::serialization::access;
75     template<class Archive>
76     void serialize(
77         Archive &ar,
78         const unsigned int /* file_version */
79     ){
80         ar & BOOST_SERIALIZATION_NVP(j1);
81         ar & BOOST_SERIALIZATION_NVP(j2);
82         ar & BOOST_SERIALIZATION_NVP(j3);
83     }
84 public:
85     bool operator==(const K &rhs) const;
86     K();
87 };
88
89 K::K()
90 : j1(&j2), j2(&j3), j3(&j1)
91 {
92 }
93
94 bool K::operator==(const K &rhs) const
95 {
96     return
97         j1.j == & j2
98         && j2.j == & j3
99         && j3.j == & j1
100         && j1 == rhs.j1
101         && j2 == rhs.j2
102         && j3 == rhs.j3
103     ;
104 }
105
106 int test_main( int /* argc */, char* /* argv */[] )
107 {
108     const char * testfile = boost::archive::tmpnam(NULL);
109     BOOST_REQUIRE(NULL != testfile);
110
111     K k;
112     boost::archive::archive_exception exception(
113         boost::archive::archive_exception::no_exception
114     );
115     {   
116         test_ostream os(testfile, TEST_STREAM_FLAGS);
117         test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
118         BOOST_TRY {
119             oa << BOOST_SERIALIZATION_NVP(k);
120         }
121         BOOST_CATCH (boost::archive::archive_exception ae){
122             exception = ae;
123         }
124         BOOST_CATCH_END
125         BOOST_CHECK(
126             exception.code == boost::archive::archive_exception::pointer_conflict
127         );
128     }
129     // if exception wasn't invoked
130     if(exception.code == boost::archive::archive_exception::no_exception){
131         // try to read the archive
132         test_istream is(testfile, TEST_STREAM_FLAGS);
133         test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
134         exception = boost::archive::archive_exception(
135             boost::archive::archive_exception::no_exception
136         );
137         BOOST_TRY {
138             ia >> BOOST_SERIALIZATION_NVP(k);
139         }
140         BOOST_CATCH (boost::archive::archive_exception ae){
141             exception = ae;
142         }
143         BOOST_CATCH_END
144         BOOST_CHECK(
145             exception.code == boost::archive::archive_exception::pointer_conflict
146         );
147     }
148     std::remove(testfile);
149     return EXIT_SUCCESS;
150 }
151
152 // EOF