1/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2// test_unregistered.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 <fstream>
12
13#include <cstddef> // NULL
14#include <cstdio> // remove
15#include <cstring> // strcmp
16#include <boost/config.hpp>
17#if defined(BOOST_NO_STDC_NAMESPACE)
18namespace std{
19 using ::remove;
20}
21#endif
22
23#include "test_tools.hpp"
24
25#include <boost/archive/archive_exception.hpp>
26#include <boost/serialization/base_object.hpp>
27#include <boost/serialization/type_info_implementation.hpp>
28#include <boost/core/no_exceptions_support.hpp>
29
30class polymorphic_base
31{
32 friend class boost::serialization::access;
33 template<class Archive>
34 void serialize(Archive & /* ar */, const unsigned int /* file_version */){
35 }
36public:
37 virtual ~polymorphic_base(){};
38};
39
40class polymorphic_derived1 : public polymorphic_base
41{
42 friend class boost::serialization::access;
43 template<class Archive>
44 void serialize(Archive &ar, const unsigned int /* file_version */){
45 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(polymorphic_base);
46 }
47};
48
49class polymorphic_derived2 : public polymorphic_base
50{
51 friend class boost::serialization::access;
52 template<class Archive>
53 void serialize(Archive &ar, const unsigned int /* file_version */){
54 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(polymorphic_base);
55 }
56};
57
58struct type1 {
59 template<typename Archive>
60 void serialize(Archive&, unsigned int ver) {
61 BOOST_CHECK(ver == 1);
62 }
63};
64struct type2 {
65 template<typename Archive>
66 void serialize(Archive&, unsigned int ver) {
67 BOOST_CHECK(ver == 2);
68 }
69};
70
71BOOST_CLASS_VERSION(type1, 1);
72BOOST_CLASS_VERSION(type2, 2);
73
74// save unregistered polymorphic classes
75void save_unregistered1(const char *testfile)
76{
77 test_ostream os(testfile, TEST_STREAM_FLAGS);
78 test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
79
80 polymorphic_base *rb1 = new polymorphic_derived1;
81
82 // registration IS necessary when serializing a polymorphic class
83 // through pointer to the base class
84 bool except = false;
85 BOOST_TRY {
86 oa << BOOST_SERIALIZATION_NVP(rb1);
87 }
88 BOOST_CATCH(boost::archive::archive_exception const& aex){
89 except = true;
90 }
91 BOOST_CATCH_END
92 BOOST_CHECK_MESSAGE(except, "lack of registration not detected !");
93
94 delete rb1;
95}
96
97// note: the corresponding save function above will not result in
98// valid archive - hence, the following code which attempts to load
99// and archive will fail. Leave this as a reminder not to do this
100#if 0
101// load unregistered polymorphic classes
102void load_unregistered1(const char *testfile)
103{
104 std::ifstream is(testfile);
105 boost::archive::iarchive ia(is);
106
107 polymorphic_base *rb1(NULL);
108
109 // registration IS necessary when serializing a polymorphic class
110 // through pointer to the base class
111 bool except = false;
112 BOOST_TRY {
113 ia >> BOOST_SERIALIZATION_NVP(rb1);
114 }
115 BOOST_CATCH(boost::archive::archive_exception const& aex){
116 except = true;
117 BOOST_CHECK_MESSAGE(
118 NULL == rb1,
119 "failed load resulted in a non-null pointer"
120 );
121 }
122 BOOST_CATCH_END
123 BOOST_CHECK_MESSAGE(except, "lack of registration not detected !");
124
125 delete rb1;
126}
127#endif
128
129// save unregistered polymorphic classes
130void save_unregistered2(const char *testfile)
131{
132 test_ostream os(testfile, TEST_STREAM_FLAGS);
133 test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
134
135 polymorphic_derived1 *rd1 = new polymorphic_derived1;
136
137 // registration is NOT necessary when serializing a polymorphic class
138 // through pointer to a derived class
139 bool except = false;
140 BOOST_TRY {
141 oa << BOOST_SERIALIZATION_NVP(rd1);
142 }
143 BOOST_CATCH(boost::archive::archive_exception const& aex){
144 except = true;
145 }
146 BOOST_CATCH_END
147 BOOST_CHECK_MESSAGE(! except, "registration not detected !");
148
149 delete rd1;
150}
151
152// note: the corresponding save function above will not result in
153// valid archive - hence, the following code which attempts to load
154// and archive will fail. Leave this as a reminder not to do this
155// load unregistered polymorphic classes
156void load_unregistered2(const char *testfile)
157{
158 test_istream is(testfile, TEST_STREAM_FLAGS);
159 test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
160
161 polymorphic_derived1 *rd1 = NULL;
162
163 // registration is NOT necessary when serializing a polymorphic class
164 // or through pointer to a derived class
165 bool except = false;
166 BOOST_TRY {
167 ia >> BOOST_SERIALIZATION_NVP(rd1);
168 }
169 BOOST_CATCH(boost::archive::archive_exception const& aex){
170 except = true;
171 BOOST_CHECK_MESSAGE(
172 NULL == rd1,
173 "failed load resulted in a non-null pointer"
174 );
175 }
176 BOOST_CATCH_END
177 BOOST_CHECK_MESSAGE(! except, "registration not detected !");
178
179 delete rd1;
180}
181
182// save registered polymorphic class
183void save_registered(const char *testfile)
184{
185 test_ostream os(testfile, TEST_STREAM_FLAGS);
186 test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
187
188 polymorphic_base *rb1 = new polymorphic_derived1;
189 polymorphic_base *rb2 = new polymorphic_derived2;
190
191 // registration (forward declaration) will permit correct serialization
192 // through a pointer to a base class
193 oa.register_type(static_cast<polymorphic_derived1 *>(NULL));
194 oa.register_type(static_cast<polymorphic_derived2 *>(NULL));
195 oa << BOOST_SERIALIZATION_NVP(rb1);
196 oa << BOOST_SERIALIZATION_NVP(rb2);
197
198 delete rb1;
199 delete rb2;
200}
201
202// load registered polymorphic class
203void load_registered(const char *testfile)
204{
205 test_istream is(testfile, TEST_STREAM_FLAGS);
206 test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
207
208 polymorphic_base *rb1 = NULL;
209 polymorphic_base *rb2 = NULL;
210
211 // registration (forward declaration) will permit correct serialization
212 // through a pointer to a base class
213 ia.register_type(static_cast<polymorphic_derived1 *>(NULL));
214 ia.register_type(static_cast<polymorphic_derived2 *>(NULL));
215
216 ia >> BOOST_SERIALIZATION_NVP(rb1);
217
218 BOOST_CHECK_MESSAGE(NULL != rb1, "Load resulted in NULL pointer");
219 BOOST_CHECK_MESSAGE(
220 boost::serialization::type_info_implementation<
221 polymorphic_derived1
222 >::type::get_const_instance()
223 ==
224 * boost::serialization::type_info_implementation<
225 polymorphic_base
226 >::type::get_const_instance().get_derived_extended_type_info(*rb1),
227 "restored pointer b1 not of correct type"
228 );
229
230 ia >> BOOST_SERIALIZATION_NVP(rb2);
231 BOOST_CHECK_MESSAGE(NULL != rb2, "Load resulted in NULL pointer");
232 BOOST_CHECK_MESSAGE(
233 boost::serialization::type_info_implementation<
234 polymorphic_derived2
235 >::type::get_const_instance()
236 ==
237 * boost::serialization::type_info_implementation<
238 polymorphic_base
239 >::type::get_const_instance().get_derived_extended_type_info(*rb2),
240 "restored pointer b2 not of correct type"
241 );
242
243 delete rb1;
244 delete rb2;
245}
246
247// store a pointer from slot0
248void save_unregistered_pointer(const char *testfile)
249{
250 test_ostream os(testfile, TEST_STREAM_FLAGS);
251 test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
252
253 oa.register_type(static_cast<type2 *>(NULL));
254
255 type1 instance1;
256 type2 *pointer2 = new type2;
257
258 BOOST_TRY {
259 oa & BOOST_SERIALIZATION_NVP(instance1) & BOOST_SERIALIZATION_NVP(pointer2);
260 }
261 BOOST_CATCH(...) {
262 BOOST_CHECK_MESSAGE(false, "unexpected exception");
263 }
264 BOOST_CATCH_END
265
266 delete pointer2;
267}
268
269// load a pointer from slot0 which has no pointer serializer
270void load_unregistered_pointer(const char *testfile)
271{
272 test_istream is(testfile);
273 test_iarchive ia(is);
274
275 type1 instance1;
276 type2 *pointer2(NULL);
277
278 bool except = false;
279 BOOST_TRY {
280 ia & BOOST_SERIALIZATION_NVP(instance1) & BOOST_SERIALIZATION_NVP(pointer2);
281 }
282 BOOST_CATCH(boost::archive::archive_exception const& aex){
283 except = true;
284 BOOST_CHECK_MESSAGE(
285 std::strcmp(aex.what(), "unregistered class") == 0,
286 "incorrect exception"
287 );
288 }
289 BOOST_CATCH_END
290 BOOST_CHECK_MESSAGE(except, "lack of registration not detected !");
291 BOOST_CHECK_MESSAGE(NULL == pointer2, "expected failed load");
292
293 delete pointer2;
294}
295
296int
297test_main( int /* argc */, char* /* argv */[] )
298{
299 const char * testfile = boost::archive::tmpnam(NULL);
300 BOOST_REQUIRE(NULL != testfile);
301 save_unregistered1(testfile);
302// load_unregistered1(testfile);
303 save_unregistered2(testfile);
304 load_unregistered2(testfile);
305 save_registered(testfile);
306 load_registered(testfile);
307 save_unregistered_pointer(testfile);
308 load_unregistered_pointer(testfile);
309 std::remove(filename: testfile);
310 return EXIT_SUCCESS;
311}
312
313// EOF
314

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