• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
18 namespace 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 
30 class polymorphic_base
31 {
32     friend class boost::serialization::access;
33     template<class Archive>
serialize(Archive &,const unsigned int)34     void serialize(Archive & /* ar */, const unsigned int /* file_version */){
35     }
36 public:
~polymorphic_base()37     virtual ~polymorphic_base(){};
38 };
39 
40 class polymorphic_derived1 : public polymorphic_base
41 {
42     friend class boost::serialization::access;
43     template<class Archive>
serialize(Archive & ar,const unsigned int)44     void serialize(Archive &ar, const unsigned int /* file_version */){
45         ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(polymorphic_base);
46     }
47 };
48 
49 class polymorphic_derived2 : public polymorphic_base
50 {
51     friend class boost::serialization::access;
52     template<class Archive>
serialize(Archive & ar,const unsigned int)53     void serialize(Archive &ar, const unsigned int /* file_version */){
54         ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(polymorphic_base);
55     }
56 };
57 
58 struct type1 {
59     template<typename Archive>
serializetype160     void serialize(Archive&, unsigned int ver) {
61         BOOST_CHECK(ver == 1);
62     }
63 };
64 struct type2 {
65     template<typename Archive>
serializetype266     void serialize(Archive&, unsigned int ver) {
67         BOOST_CHECK(ver == 2);
68     }
69 };
70 
71 BOOST_CLASS_VERSION(type1, 1);
72 BOOST_CLASS_VERSION(type2, 2);
73 
74 // save unregistered polymorphic classes
save_unregistered1(const char * testfile)75 void 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
102 void 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
save_unregistered2(const char * testfile)130 void 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
load_unregistered2(const char * testfile)156 void 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
save_registered(const char * testfile)183 void 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
load_registered(const char * testfile)203 void 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
save_unregistered_pointer(const char * testfile)248 void 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
load_unregistered_pointer(const char * testfile)270 void 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 
296 int
test_main(int,char * [])297 test_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(testfile);
310     return EXIT_SUCCESS;
311 }
312 
313 // EOF
314