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 //
36 template< class T >
as_const(T const & r)37 inline T const& as_const( T const& r )
38 {
39 return r;
40 }
41
42 //
43 // used to customize tests for circular_buffer
44 //
45 template< class Cont >
46 struct set_capacity
47 {
operator ()set_capacity48 void operator()( Cont& ) const
49 { }
50 };
51
52 template<class T>
53 struct set_capacity< boost::ptr_circular_buffer<T> >
54 {
operator ()set_capacity55 void operator()( boost::ptr_circular_buffer<T>& c ) const
56 {
57 c.set_capacity( 100u );
58 }
59 };
60
61 //
62 // class hierarchy
63 //
64 struct Base
65 {
66 friend class boost::serialization::access;
67
68 int i;
69
70
71 template< class Archive >
serializeBase72 void serialize( Archive& ar, const unsigned int /*version*/ )
73 {
74 ar & boost::serialization::make_nvp( "i", i );
75 }
76
BaseBase77 Base() : i(42)
78 { }
79
BaseBase80 Base( int i ) : i(i)
81 { }
82
~BaseBase83 virtual ~Base()
84 { }
85 };
86
operator <(const Base & l,const Base & r)87 inline bool operator<( const Base& l, const Base& r )
88 {
89 return l.i < r.i;
90 }
91
operator ==(const Base & l,const Base & r)92 inline bool operator==( const Base& l, const Base& r )
93 {
94 return l.i == r.i;
95 }
96
hash_value(const Base & b)97 inline std::size_t hash_value( const Base& b )
98 {
99 return boost::hash_value( b.i );
100 }
101
102 struct Derived : Base
103 {
104 int i2;
105
106 template< class Archive >
serializeDerived107 void serialize( Archive& ar, const unsigned int /*version*/ )
108 {
109 ar & boost::serialization::make_nvp( "Base",
110 boost::serialization::base_object<Base>( *this ) );
111 ar & boost::serialization::make_nvp( "i2", i2 );
112 }
113
DerivedDerived114 Derived() : Base(42), i2(42)
115 { }
116
DerivedDerived117 explicit Derived( int i2 ) : Base(0), i2(i2)
118 { }
119 };
120
121 BOOST_CLASS_EXPORT_GUID( Derived, "Derived" )
122
123 //
124 // test of containers
125 //
126 //
127
128 template< class C, class T >
add(C & c,T * r,unsigned)129 void add( C& c, T* r, unsigned /*n*/ )
130 {
131 c.insert( c.end(), r );
132 }
133
134 template< class U, class T >
add(boost::ptr_array<U,2> & c,T * r,unsigned n)135 void add( boost::ptr_array<U,2>& c, T* r, unsigned n )
136 {
137 c.replace( n, r );
138 }
139
140 template< class Cont, class OArchive, class IArchive >
test_serialization_helper()141 void 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( 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
178 template< class Cont, class OArchive, class IArchive >
test_serialization_unordered_set_helper()179 void 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( fn.c_str() );
204
205 BOOST_CHECK_EQUAL( vec.size(), vec2.size() );
206 BOOST_CHECK_EQUAL( (*vec2.begin()).i, -1 );
207 BOOST_CHECK_EQUAL( (*++vec2.begin()).i, 0 );
208 }
209
210 template< class Map, class OArchive, class IArchive >
test_serialization_map_helper()211 void test_serialization_map_helper()
212 {
213 Map m;
214 std::string key1("key1"), key2("key2");
215 m.insert( key1, new Base( -1 ) );
216 m.insert( key2, new Derived( 1 ) );
217 BOOST_CHECK_EQUAL( m.size(), 2u );
218
219 std::string fn = std::tmpnam( 0 );
220
221 {
222 std::ofstream ofs( fn.c_str() );
223 OArchive oa(ofs);
224 oa << boost::serialization::make_nvp( "container", as_const(m) );
225 }
226
227 Map m2;
228
229 {
230 std::ifstream ifs( fn.c_str(), std::ios::binary );
231 IArchive ia(ifs);
232 ia >> boost::serialization::make_nvp( "container", m2 );
233 }
234
235 std::remove( fn.c_str() );
236
237 BOOST_CHECK_EQUAL( m.size(), m2.size() );
238 BOOST_CHECK_EQUAL( m2.find(key1)->second->i, -1 );
239 BOOST_CHECK_EQUAL( m2.find(key2)->second->i, 0 );
240
241 typename Map::iterator i = m2.find(key2);
242 Derived* d = dynamic_cast<Derived*>( i->second );
243 BOOST_CHECK_EQUAL( d->i2, 1 );
244 }
245
246 //
247 // basic test of hierarchy
248 //
test_hierarchy()249 void test_hierarchy()
250 {
251 Base* p = new Derived();
252
253 std::string fn = std::tmpnam( 0 );
254
255 {
256 std::ofstream ofs( fn.c_str() );
257 boost::archive::text_oarchive oa(ofs);
258 oa << as_const(p);
259 }
260
261 Base* d = 0;
262
263 {
264 std::ifstream ifs( fn.c_str(), std::ios::binary );
265 boost::archive::text_iarchive ia(ifs);
266 ia >> d;
267 }
268
269 std::remove( fn.c_str() );
270
271 BOOST_CHECK_EQUAL( p->i, d->i );
272 BOOST_CHECK( p != d );
273 BOOST_CHECK( dynamic_cast<Derived*>( d ) );
274 delete p;
275 delete d;
276 }
277
278 //
279 // test initializer
280 //
test_serialization()281 void test_serialization()
282 {
283 test_hierarchy();
284 test_serialization_helper< boost::ptr_deque<Base>,
285 boost::archive::text_oarchive,
286 boost::archive::text_iarchive >();
287 test_serialization_helper< boost::ptr_list<Base>,
288 boost::archive::text_oarchive,
289 boost::archive::text_iarchive>();
290 test_serialization_helper< boost::ptr_vector<Base>,
291 boost::archive::text_oarchive,
292 boost::archive::text_iarchive>();
293 test_serialization_helper< boost::ptr_vector<Base>,
294 boost::archive::xml_oarchive,
295 boost::archive::xml_iarchive>();
296 test_serialization_helper< boost::ptr_circular_buffer<Base>,
297 boost::archive::text_oarchive,
298 boost::archive::text_iarchive>();
299 test_serialization_helper< boost::ptr_circular_buffer<Base>,
300 boost::archive::xml_oarchive,
301 boost::archive::xml_iarchive>();
302 test_serialization_helper< boost::ptr_array<Base,2>,
303 boost::archive::text_oarchive,
304 boost::archive::text_iarchive>();
305 test_serialization_helper< boost::ptr_set<Base>,
306 boost::archive::text_oarchive,
307 boost::archive::text_iarchive>();
308 test_serialization_helper< boost::ptr_multiset<Base>,
309 boost::archive::text_oarchive,
310 boost::archive::text_iarchive>();
311
312 test_serialization_unordered_set_helper< boost::ptr_unordered_set<Base>,
313 boost::archive::text_oarchive,
314 boost::archive::text_iarchive>();
315 test_serialization_unordered_set_helper<boost::ptr_unordered_multiset<Base>,
316 boost::archive::text_oarchive,
317 boost::archive::text_iarchive>();
318
319 test_serialization_map_helper< boost::ptr_map<std::string,Base>,
320 boost::archive::text_oarchive,
321 boost::archive::text_iarchive>();
322 test_serialization_map_helper< boost::ptr_multimap<std::string,Base>,
323 boost::archive::text_oarchive,
324 boost::archive::text_iarchive>();
325
326 test_serialization_map_helper< boost::ptr_map<std::string,Base>,
327 boost::archive::xml_oarchive,
328 boost::archive::xml_iarchive>();
329 test_serialization_map_helper< boost::ptr_multimap<std::string,Base>,
330 boost::archive::xml_oarchive,
331 boost::archive::xml_iarchive>();
332
333 test_serialization_map_helper< boost::ptr_unordered_map<std::string,Base>,
334 boost::archive::text_oarchive,
335 boost::archive::text_iarchive>();
336 test_serialization_map_helper< boost::ptr_unordered_multimap<std::string,Base>,
337 boost::archive::text_oarchive,
338 boost::archive::text_iarchive>();
339
340 test_serialization_map_helper< boost::ptr_unordered_map<std::string,Base>,
341 boost::archive::xml_oarchive,
342 boost::archive::xml_iarchive>();
343 test_serialization_map_helper< boost::ptr_unordered_multimap<std::string,Base>,
344 boost::archive::xml_oarchive,
345 boost::archive::xml_iarchive>();
346
347 }
348
349
350 using boost::unit_test::test_suite;
351
init_unit_test_suite(int argc,char * argv[])352 test_suite* init_unit_test_suite( int argc, char* argv[] )
353 {
354 test_suite* test = BOOST_TEST_SUITE( "Pointer Container Test Suite" );
355
356 test->add( BOOST_TEST_CASE( &test_serialization ) );
357
358 return test;
359 }
360