1//
2// Boost.Pointer Container
3//
4// Copyright Thorsten Ottosen 2003-2005. Use, modification and
5// distribution is subject to the Boost Software License, Version
6// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
9// For more information, see http://www.boost.org/libs/ptr_container/
10//
11
12#include <boost/config.hpp>
13#ifdef BOOST_MSVC
14#pragma warning( disable: 4996 )
15#endif
16
17#include <boost/test/unit_test.hpp>
18#include <boost/archive/text_oarchive.hpp>
19#include <boost/archive/text_iarchive.hpp>
20#include <boost/archive/xml_iarchive.hpp>
21#include <boost/archive/xml_oarchive.hpp>
22#include <boost/functional/hash.hpp>
23#include <boost/ptr_container/ptr_container.hpp>
24#include <boost/ptr_container/serialize_ptr_container.hpp>
25#include <boost/serialization/export.hpp>
26#include <boost/serialization/base_object.hpp>
27#include <boost/serialization/utility.hpp>
28#include <boost/serialization/string.hpp>
29#include <fstream>
30#include <string>
31#include <cstdio>
32
33//
34// serialization helper: we can't save a non-const object
35//
36template< class T >
37inline T const& as_const( T const& r )
38{
39 return r;
40}
41
42//
43// used to customize tests for circular_buffer
44//
45template< class Cont >
46struct set_capacity
47{
48 void operator()( Cont& ) const
49 { }
50};
51
52template<class T>
53struct set_capacity< boost::ptr_circular_buffer<T> >
54{
55 void operator()( boost::ptr_circular_buffer<T>& c ) const
56 {
57 c.set_capacity( 100u );
58 }
59};
60
61//
62// class hierarchy
63//
64struct Base
65{
66 friend class boost::serialization::access;
67
68 int i;
69
70
71 template< class Archive >
72 void serialize( Archive& ar, const unsigned int /*version*/ )
73 {
74 ar & boost::serialization::make_nvp( n: "i", v&: i );
75 }
76
77 Base() : i(42)
78 { }
79
80 Base( int i ) : i(i)
81 { }
82
83 virtual ~Base()
84 { }
85};
86
87inline bool operator<( const Base& l, const Base& r )
88{
89 return l.i < r.i;
90}
91
92inline bool operator==( const Base& l, const Base& r )
93{
94 return l.i == r.i;
95}
96
97inline std::size_t hash_value( const Base& b )
98{
99 return boost::hash_value( v: b.i );
100}
101
102struct Derived : Base
103{
104 int i2;
105
106 template< class Archive >
107 void serialize( Archive& ar, const unsigned int /*version*/ )
108 {
109 ar & boost::serialization::make_nvp( n: "Base",
110 v&: boost::serialization::base_object<Base>( d&: *this ) );
111 ar & boost::serialization::make_nvp( n: "i2", v&: i2 );
112 }
113
114 Derived() : Base(42), i2(42)
115 { }
116
117 explicit Derived( int i2 ) : Base(0), i2(i2)
118 { }
119};
120
121BOOST_CLASS_EXPORT_GUID( Derived, "Derived" )
122
123//
124// test of containers
125//
126//
127
128template< class C, class T >
129void add( C& c, T* r, unsigned /*n*/ )
130{
131 c.insert( c.end(), r );
132}
133
134template< class U, class T >
135void add( boost::ptr_array<U,2>& c, T* r, unsigned n )
136{
137 c.replace( n, r );
138}
139
140template< class Cont, class OArchive, class IArchive >
141void test_serialization_helper()
142{
143 Cont vec;
144 set_capacity<Cont>()( vec );
145 add( vec, new Base( -1 ), 0u );
146 add( vec, new Derived( 1 ), 1u );
147 BOOST_CHECK_EQUAL( vec.size(), 2u );
148
149 std::string fn = std::tmpnam( 0 );
150
151 {
152 std::ofstream ofs( fn.c_str() );
153 OArchive oa(ofs);
154 oa << boost::serialization::make_nvp( "container", as_const(vec) );
155 }
156
157 Cont vec2;
158
159 {
160 std::ifstream ifs( fn.c_str(), std::ios::binary );
161 IArchive ia(ifs);
162 ia >> boost::serialization::make_nvp( "container", vec2 );
163 }
164
165 std::remove( filename: fn.c_str() );
166
167 BOOST_CHECK_EQUAL( vec.size(), vec2.size() );
168 BOOST_CHECK_EQUAL( (*vec2.begin()).i, -1 );
169 BOOST_CHECK_EQUAL( (*++vec2.begin()).i, 0 );
170
171 typename Cont::iterator i = vec2.begin();
172 ++i;
173 Derived* d = dynamic_cast<Derived*>( &*i );
174 BOOST_CHECK_EQUAL( d->i2, 1 );
175
176}
177
178template< class Cont, class OArchive, class IArchive >
179void test_serialization_unordered_set_helper()
180{
181 Cont vec;
182 set_capacity<Cont>()( vec );
183 add( vec, new Base( -1 ), 0u );
184 add( vec, new Derived( 1 ), 1u );
185 BOOST_CHECK_EQUAL( vec.size(), 2u );
186
187 std::string fn = std::tmpnam( 0 );
188
189 {
190 std::ofstream ofs( fn.c_str() );
191 OArchive oa(ofs);
192 oa << boost::serialization::make_nvp( "container", as_const(vec) );
193 }
194
195 Cont vec2;
196
197 {
198 std::ifstream ifs( fn.c_str(), std::ios::binary );
199 IArchive ia(ifs);
200 ia >> boost::serialization::make_nvp( "container", vec2 );
201 }
202
203 std::remove( filename: fn.c_str() );
204
205 BOOST_CHECK_EQUAL( vec.size(), vec2.size() );
206
207 typename Cont::iterator it = vec2.begin();
208
209 if( it->i == -1 )
210 {
211 ++it;
212
213 BOOST_CHECK_EQUAL( it->i, 0 );
214
215 Derived* d = dynamic_cast<Derived*>( &*it );
216 BOOST_CHECK_EQUAL( d->i2, 1 );
217 }
218 else
219 {
220 BOOST_CHECK_EQUAL( it->i, 0 );
221
222 Derived* d = dynamic_cast<Derived*>( &*it );
223 BOOST_CHECK_EQUAL( d->i2, 1 );
224
225 ++it;
226
227 BOOST_CHECK_EQUAL( it->i, -1 );
228 }
229}
230
231template< class Map, class OArchive, class IArchive >
232void test_serialization_map_helper()
233{
234 Map m;
235 std::string key1("key1"), key2("key2");
236 m.insert( key1, new Base( -1 ) );
237 m.insert( key2, new Derived( 1 ) );
238 BOOST_CHECK_EQUAL( m.size(), 2u );
239
240 std::string fn = std::tmpnam( 0 );
241
242 {
243 std::ofstream ofs( fn.c_str() );
244 OArchive oa(ofs);
245 oa << boost::serialization::make_nvp( "container", as_const(m) );
246 }
247
248 Map m2;
249
250 {
251 std::ifstream ifs( fn.c_str(), std::ios::binary );
252 IArchive ia(ifs);
253 ia >> boost::serialization::make_nvp( "container", m2 );
254 }
255
256 std::remove( filename: fn.c_str() );
257
258 BOOST_CHECK_EQUAL( m.size(), m2.size() );
259 BOOST_CHECK_EQUAL( m2.find(key1)->second->i, -1 );
260 BOOST_CHECK_EQUAL( m2.find(key2)->second->i, 0 );
261
262 typename Map::iterator i = m2.find(key2);
263 Derived* d = dynamic_cast<Derived*>( i->second );
264 BOOST_CHECK_EQUAL( d->i2, 1 );
265}
266
267//
268// basic test of hierarchy
269//
270void test_hierarchy()
271{
272 Base* p = new Derived();
273
274 std::string fn = std::tmpnam( 0 );
275
276 {
277 std::ofstream ofs( fn.c_str() );
278 boost::archive::text_oarchive oa(ofs);
279 oa << as_const(r: p);
280 }
281
282 Base* d = 0;
283
284 {
285 std::ifstream ifs( fn.c_str(), std::ios::binary );
286 boost::archive::text_iarchive ia(ifs);
287 ia >> d;
288 }
289
290 std::remove( filename: fn.c_str() );
291
292 BOOST_CHECK_EQUAL( p->i, d->i );
293 BOOST_CHECK( p != d );
294 BOOST_CHECK( dynamic_cast<Derived*>( d ) );
295 delete p;
296 delete d;
297}
298
299//
300// test initializer
301//
302void test_serialization()
303{
304 test_hierarchy();
305 test_serialization_helper< boost::ptr_deque<Base>,
306 boost::archive::text_oarchive,
307 boost::archive::text_iarchive >();
308 test_serialization_helper< boost::ptr_list<Base>,
309 boost::archive::text_oarchive,
310 boost::archive::text_iarchive>();
311 test_serialization_helper< boost::ptr_vector<Base>,
312 boost::archive::text_oarchive,
313 boost::archive::text_iarchive>();
314 test_serialization_helper< boost::ptr_vector<Base>,
315 boost::archive::xml_oarchive,
316 boost::archive::xml_iarchive>();
317 test_serialization_helper< boost::ptr_circular_buffer<Base>,
318 boost::archive::text_oarchive,
319 boost::archive::text_iarchive>();
320 test_serialization_helper< boost::ptr_circular_buffer<Base>,
321 boost::archive::xml_oarchive,
322 boost::archive::xml_iarchive>();
323 test_serialization_helper< boost::ptr_array<Base,2>,
324 boost::archive::text_oarchive,
325 boost::archive::text_iarchive>();
326 test_serialization_helper< boost::ptr_set<Base>,
327 boost::archive::text_oarchive,
328 boost::archive::text_iarchive>();
329 test_serialization_helper< boost::ptr_multiset<Base>,
330 boost::archive::text_oarchive,
331 boost::archive::text_iarchive>();
332
333 test_serialization_unordered_set_helper< boost::ptr_unordered_set<Base>,
334 boost::archive::text_oarchive,
335 boost::archive::text_iarchive>();
336 test_serialization_unordered_set_helper<boost::ptr_unordered_multiset<Base>,
337 boost::archive::text_oarchive,
338 boost::archive::text_iarchive>();
339
340 test_serialization_map_helper< boost::ptr_map<std::string,Base>,
341 boost::archive::text_oarchive,
342 boost::archive::text_iarchive>();
343 test_serialization_map_helper< boost::ptr_multimap<std::string,Base>,
344 boost::archive::text_oarchive,
345 boost::archive::text_iarchive>();
346
347 test_serialization_map_helper< boost::ptr_map<std::string,Base>,
348 boost::archive::xml_oarchive,
349 boost::archive::xml_iarchive>();
350 test_serialization_map_helper< boost::ptr_multimap<std::string,Base>,
351 boost::archive::xml_oarchive,
352 boost::archive::xml_iarchive>();
353
354 test_serialization_map_helper< boost::ptr_unordered_map<std::string,Base>,
355 boost::archive::text_oarchive,
356 boost::archive::text_iarchive>();
357 test_serialization_map_helper< boost::ptr_unordered_multimap<std::string,Base>,
358 boost::archive::text_oarchive,
359 boost::archive::text_iarchive>();
360
361 test_serialization_map_helper< boost::ptr_unordered_map<std::string,Base>,
362 boost::archive::xml_oarchive,
363 boost::archive::xml_iarchive>();
364 test_serialization_map_helper< boost::ptr_unordered_multimap<std::string,Base>,
365 boost::archive::xml_oarchive,
366 boost::archive::xml_iarchive>();
367
368}
369
370
371using boost::unit_test::test_suite;
372
373test_suite* init_unit_test_suite( int argc, char* argv[] )
374{
375 test_suite* test = BOOST_TEST_SUITE( "Pointer Container Test Suite" );
376
377 test->add( BOOST_TEST_CASE( &test_serialization ) );
378
379 return test;
380}
381

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