• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2 // test_diamond.cpp
3 
4 // (C) Copyright 2002-2009 Vladimir Prus and Robert Ramey.
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 // test of serialization library for diamond inheritence situations
10 
11 #include <cstddef> // NULL
12 #include <fstream>
13 #include <iostream>
14 
15 #include <boost/config.hpp>
16 #include <cstdio> // remove
17 #if defined(BOOST_NO_STDC_NAMESPACE)
18 namespace std{
19     using ::remove;
20 }
21 #endif
22 
23 #include "test_tools.hpp"
24 
25 #include <boost/serialization/map.hpp>
26 #include <boost/serialization/utility.hpp>
27 #include <boost/serialization/split_member.hpp>
28 #include <boost/serialization/tracking.hpp>
29 #include <boost/serialization/base_object.hpp>
30 #include <boost/serialization/nvp.hpp>
31 #include <boost/serialization/export.hpp>
32 
33 int save_count = 0; // used to detect when base class is saved multiple times
34 int load_count = 0; // used to detect when base class is loaded multiple times
35 
36 class base {
37 public:
base()38     base() : i(0) {}
base(int i)39     base(int i) : i(i)
40     {
41         m[i] = "text";
42     }
43 
44     template<class Archive>
save(Archive & ar,const unsigned int) const45     void save(Archive &ar, const unsigned int /* file_version */) const
46     {
47         std::cout << "Saving base\n";
48         ar << BOOST_SERIALIZATION_NVP(i);
49         ar << BOOST_SERIALIZATION_NVP(m);
50         ++save_count;
51     }
52 
53     template<class Archive>
load(Archive & ar,const unsigned int)54     void load(Archive & ar, const unsigned int /* file_version */)
55     {
56         std::cout << "Restoring base\n";
57         ar >> BOOST_SERIALIZATION_NVP(i);
58         ar >> BOOST_SERIALIZATION_NVP(m);
59         ++load_count;
60     }
61 
62     BOOST_SERIALIZATION_SPLIT_MEMBER()
63 
64     bool operator==(const base& another) const
65     {
66         return i == another.i && m == another.m;
67     }
68     // make polymorphic by marking at least one function virtual
~base()69     virtual ~base() {};
70 private:
71     int i;
72     std::map<int, std::string> m;
73 };
74 
75 // note: the default is for object tracking to be performed if and only
76 // if and object of the corresponding class is anywhere serialized
77 // through a pointer.  In this example, that doesn't occur so
78 // by default, the shared base object wouldn't normally be tracked.
79 // This would leave to multiple save/load operation of the data in
80 // this shared base class.  This wouldn't cause an error, but it would
81 // be a waste of time.  So set the tracking behavior trait of the base
82 // class to always track serialized objects of that class.  This permits
83 // the system to detect and elminate redundent save/load operations.
84 // (It is concievable that this might someday be detected automatically
85 // but for now, this is not done so we have to rely on the programmer
86 // to specify this trait)
87 BOOST_CLASS_TRACKING(base, track_always)
88 
89 class derived1 : virtual public base {
90 public:
91     template<class Archive>
save(Archive & ar,const unsigned int) const92     void save(Archive &ar, const unsigned int /* file_version */) const
93     {
94         std::cout << "Saving derived1\n";
95         ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(base);
96     }
97 
98     template<class Archive>
load(Archive & ar,const unsigned int)99     void load(Archive & ar, const unsigned int /* file_version */)
100     {
101         std::cout << "Restoring derived1\n";
102         ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(base);
103     }
104 
105     BOOST_SERIALIZATION_SPLIT_MEMBER()
106 };
107 
108 class derived2 : virtual public base {
109 public:
110     template<class Archive>
save(Archive & ar,const unsigned int) const111     void save(Archive &ar, const unsigned int /* file_version */) const
112     {
113         std::cout << "Saving derived2\n";
114         ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(base);
115     }
116 
117     template<class Archive>
load(Archive & ar,const unsigned int)118     void load(Archive & ar, const unsigned int /* file_version */)
119     {
120         std::cout << "Restoring derived2\n";
121         ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(base);
122     }
123 
124     BOOST_SERIALIZATION_SPLIT_MEMBER()
125 };
126 
127 class final : public derived1, public derived2 {
128 public:
final()129     final() {}
final(int i)130     final(int i) : base(i) {}
131 
132     template<class Archive>
save(Archive & ar,const unsigned int) const133     void save(Archive &ar, const unsigned int /* file_version */) const
134     {
135         std::cout << "Saving final\n";
136         ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived1);
137         ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived2);
138     }
139 
140     template<class Archive>
load(Archive & ar,const unsigned int)141     void load(Archive & ar, const unsigned int /* file_version */)
142     {
143         std::cout << "Restoring final\n";
144         ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived1);
145         ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived2);
146     }
147 
148     BOOST_SERIALIZATION_SPLIT_MEMBER()
149 };
150 
BOOST_CLASS_EXPORT(final)151 BOOST_CLASS_EXPORT(final)
152 
153 int
154 test_main( int /* argc */, char* /* argv */[] )
155 {
156     const char * testfile = boost::archive::tmpnam(NULL);
157     BOOST_REQUIRE(NULL != testfile);
158 
159     const final b(3);
160     {
161         test_ostream ofs(testfile, TEST_STREAM_FLAGS);
162         test_oarchive oa(ofs);
163         oa << boost::serialization::make_nvp("b", b);
164     }
165 
166     final b2;
167     {
168         test_istream ifs(testfile, TEST_STREAM_FLAGS);
169         test_iarchive ia(ifs);
170         ia >> boost::serialization::make_nvp("b2", b2);
171     }
172     BOOST_CHECK(1 == save_count);
173     BOOST_CHECK(1 == load_count);
174     BOOST_CHECK(b2 == b);
175     std::remove(testfile);
176 
177     // do the same test with pointers
178     testfile = boost::archive::tmpnam(NULL);
179     BOOST_REQUIRE(NULL != testfile);
180 
181     save_count = 0;
182     load_count = 0;
183 
184     const base* bp = new final( 3 );
185     {
186         test_ostream ofs(testfile);
187         test_oarchive oa(ofs);
188         oa << BOOST_SERIALIZATION_NVP(bp);
189     }
190 
191     base* bp2;
192     {
193         test_istream ifs(testfile);
194         test_iarchive ia(ifs);
195         ia >> BOOST_SERIALIZATION_NVP(bp2);
196     }
197 
198     BOOST_CHECK(1 == save_count);
199     BOOST_CHECK(1 == load_count);
200     BOOST_CHECK(*bp2 == *bp);
201     delete bp;
202     std::remove(testfile);
203 
204     return EXIT_SUCCESS;
205 }
206