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
32 //
33 // serialization helper: we can't save a non-const object
34 //
35 template< class T >
as_const(T const & r)36 inline T const& as_const( T const& r )
37 {
38 return r;
39 }
40
41 //
42 // used to customize tests for circular_buffer
43 //
44 template< class Cont >
45 struct set_capacity
46 {
operator ()set_capacity47 void operator()( Cont& ) const
48 { }
49 };
50
51 template<class T>
52 struct set_capacity< boost::ptr_circular_buffer<T> >
53 {
operator ()set_capacity54 void operator()( boost::ptr_circular_buffer<T>& c ) const
55 {
56 c.set_capacity( 100u );
57 }
58 };
59
60 //
61 // class hierarchy
62 //
63 struct Base
64 {
65 friend class boost::serialization::access;
66
67 int i;
68
69
70 template< class Archive >
serializeBase71 void serialize( Archive& ar, const unsigned int /*version*/ )
72 {
73 ar & boost::serialization::make_nvp( "i", i );
74 }
75
BaseBase76 Base() : i(42)
77 { }
78
BaseBase79 Base( int i ) : i(i)
80 { }
81
~BaseBase82 virtual ~Base()
83 { }
84 };
85
operator <(const Base & l,const Base & r)86 inline bool operator<( const Base& l, const Base& r )
87 {
88 return l.i < r.i;
89 }
90
operator ==(const Base & l,const Base & r)91 inline bool operator==( const Base& l, const Base& r )
92 {
93 return l.i == r.i;
94 }
95
hash_value(const Base & b)96 inline std::size_t hash_value( const Base& b )
97 {
98 return boost::hash_value( b.i );
99 }
100
101 struct Derived : Base
102 {
103 int i2;
104
105 template< class Archive >
serializeDerived106 void serialize( Archive& ar, const unsigned int /*version*/ )
107 {
108 ar & boost::serialization::make_nvp( "Base",
109 boost::serialization::base_object<Base>( *this ) );
110 ar & boost::serialization::make_nvp( "i2", i2 );
111 }
112
DerivedDerived113 Derived() : Base(42), i2(42)
114 { }
115
DerivedDerived116 explicit Derived( int i2 ) : Base(0), i2(i2)
117 { }
118 };
119
120 BOOST_CLASS_EXPORT_GUID( Derived, "Derived" )
121
122 //
123 // test of containers
124 //
125 //
126
127 template< class C, class T >
add(C & c,T * r,unsigned)128 void add( C& c, T* r, unsigned /*n*/ )
129 {
130 c.insert( c.end(), r );
131 }
132
133 template< class U, class T >
add(boost::ptr_array<U,2> & c,T * r,unsigned n)134 void add( boost::ptr_array<U,2>& c, T* r, unsigned n )
135 {
136 c.replace( n, r );
137 }
138
139 template< class Cont, class OArchive, class IArchive >
test_serialization_helper()140 void test_serialization_helper()
141 {
142 Cont vec;
143 set_capacity<Cont>()( vec );
144 add( vec, new Base( -1 ), 0u );
145 add( vec, new Derived( 1 ), 1u );
146 BOOST_CHECK_EQUAL( vec.size(), 2u );
147
148 std::ofstream ofs("filename");
149 OArchive oa(ofs);
150 oa << boost::serialization::make_nvp( "container", as_const(vec) );
151 ofs.close();
152
153
154 std::ifstream ifs("filename", std::ios::binary);
155 IArchive ia(ifs);
156 Cont vec2;
157 ia >> boost::serialization::make_nvp( "container", vec2 );
158 ifs.close();
159
160 BOOST_CHECK_EQUAL( vec.size(), vec2.size() );
161 BOOST_CHECK_EQUAL( (*vec2.begin()).i, -1 );
162 BOOST_CHECK_EQUAL( (*++vec2.begin()).i, 0 );
163
164 typename Cont::iterator i = vec2.begin();
165 ++i;
166 Derived* d = dynamic_cast<Derived*>( &*i );
167 BOOST_CHECK_EQUAL( d->i2, 1 );
168
169 }
170
171 template< class Cont, class OArchive, class IArchive >
test_serialization_unordered_set_helper()172 void test_serialization_unordered_set_helper()
173 {
174 Cont vec;
175 set_capacity<Cont>()( vec );
176 add( vec, new Base( -1 ), 0u );
177 add( vec, new Derived( 1 ), 1u );
178 BOOST_CHECK_EQUAL( vec.size(), 2u );
179
180 std::ofstream ofs("filename");
181 OArchive oa(ofs);
182 oa << boost::serialization::make_nvp( "container", as_const(vec) );
183 ofs.close();
184
185
186 std::ifstream ifs("filename", std::ios::binary);
187 IArchive ia(ifs);
188 Cont vec2;
189 ia >> boost::serialization::make_nvp( "container", vec2 );
190 ifs.close();
191
192 BOOST_CHECK_EQUAL( vec.size(), vec2.size() );
193 BOOST_CHECK_EQUAL( (*vec2.begin()).i, -1 );
194 BOOST_CHECK_EQUAL( (*++vec2.begin()).i, 0 );
195 }
196
197 template< class Map, class OArchive, class IArchive >
test_serialization_map_helper()198 void test_serialization_map_helper()
199 {
200 Map m;
201 std::string key1("key1"), key2("key2");
202 m.insert( key1, new Base( -1 ) );
203 m.insert( key2, new Derived( 1 ) );
204 BOOST_CHECK_EQUAL( m.size(), 2u );
205
206 std::ofstream ofs("filename");
207 OArchive oa(ofs);
208 oa << boost::serialization::make_nvp( "container", as_const(m) );
209 ofs.close();
210
211
212 std::ifstream ifs("filename", std::ios::binary);
213 IArchive ia(ifs);
214 Map m2;
215 ia >> boost::serialization::make_nvp( "container", m2 );
216 ifs.close();
217
218 BOOST_CHECK_EQUAL( m.size(), m2.size() );
219 BOOST_CHECK_EQUAL( m2.find(key1)->second->i, -1 );
220 BOOST_CHECK_EQUAL( m2.find(key2)->second->i, 0 );
221
222 typename Map::iterator i = m2.find(key2);
223 Derived* d = dynamic_cast<Derived*>( i->second );
224 BOOST_CHECK_EQUAL( d->i2, 1 );
225 }
226
227 //
228 // basic test of hierarchy
229 //
test_hierarchy()230 void test_hierarchy()
231 {
232 Base* p = new Derived();
233 std::ofstream ofs("filename");
234 boost::archive::text_oarchive oa(ofs);
235 oa << as_const(p);
236 ofs.close();
237
238
239 Base* d = 0;
240 std::ifstream ifs("filename", std::ios::binary);
241 boost::archive::text_iarchive ia(ifs);
242 ia >> d;
243 ifs.close();
244
245 BOOST_CHECK_EQUAL( p->i, d->i );
246 BOOST_CHECK( p != d );
247 BOOST_CHECK( dynamic_cast<Derived*>( d ) );
248 delete p;
249 delete d;
250 }
251
252 //
253 // test initializer
254 //
test_serialization()255 void test_serialization()
256 {
257 test_hierarchy();
258 test_serialization_helper< boost::ptr_deque<Base>,
259 boost::archive::text_oarchive,
260 boost::archive::text_iarchive >();
261 test_serialization_helper< boost::ptr_list<Base>,
262 boost::archive::text_oarchive,
263 boost::archive::text_iarchive>();
264 test_serialization_helper< boost::ptr_vector<Base>,
265 boost::archive::text_oarchive,
266 boost::archive::text_iarchive>();
267 test_serialization_helper< boost::ptr_vector<Base>,
268 boost::archive::xml_oarchive,
269 boost::archive::xml_iarchive>();
270 test_serialization_helper< boost::ptr_circular_buffer<Base>,
271 boost::archive::text_oarchive,
272 boost::archive::text_iarchive>();
273 test_serialization_helper< boost::ptr_circular_buffer<Base>,
274 boost::archive::xml_oarchive,
275 boost::archive::xml_iarchive>();
276 test_serialization_helper< boost::ptr_array<Base,2>,
277 boost::archive::text_oarchive,
278 boost::archive::text_iarchive>();
279 test_serialization_helper< boost::ptr_set<Base>,
280 boost::archive::text_oarchive,
281 boost::archive::text_iarchive>();
282 test_serialization_helper< boost::ptr_multiset<Base>,
283 boost::archive::text_oarchive,
284 boost::archive::text_iarchive>();
285
286 test_serialization_unordered_set_helper< boost::ptr_unordered_set<Base>,
287 boost::archive::text_oarchive,
288 boost::archive::text_iarchive>();
289 test_serialization_unordered_set_helper<boost::ptr_unordered_multiset<Base>,
290 boost::archive::text_oarchive,
291 boost::archive::text_iarchive>();
292
293 test_serialization_map_helper< boost::ptr_map<std::string,Base>,
294 boost::archive::text_oarchive,
295 boost::archive::text_iarchive>();
296 test_serialization_map_helper< boost::ptr_multimap<std::string,Base>,
297 boost::archive::text_oarchive,
298 boost::archive::text_iarchive>();
299
300 test_serialization_map_helper< boost::ptr_map<std::string,Base>,
301 boost::archive::xml_oarchive,
302 boost::archive::xml_iarchive>();
303 test_serialization_map_helper< boost::ptr_multimap<std::string,Base>,
304 boost::archive::xml_oarchive,
305 boost::archive::xml_iarchive>();
306
307 test_serialization_map_helper< boost::ptr_unordered_map<std::string,Base>,
308 boost::archive::text_oarchive,
309 boost::archive::text_iarchive>();
310 test_serialization_map_helper< boost::ptr_unordered_multimap<std::string,Base>,
311 boost::archive::text_oarchive,
312 boost::archive::text_iarchive>();
313
314 test_serialization_map_helper< boost::ptr_unordered_map<std::string,Base>,
315 boost::archive::xml_oarchive,
316 boost::archive::xml_iarchive>();
317 test_serialization_map_helper< boost::ptr_unordered_multimap<std::string,Base>,
318 boost::archive::xml_oarchive,
319 boost::archive::xml_iarchive>();
320
321 }
322
323
324 using boost::unit_test::test_suite;
325
init_unit_test_suite(int argc,char * argv[])326 test_suite* init_unit_test_suite( int argc, char* argv[] )
327 {
328 test_suite* test = BOOST_TEST_SUITE( "Pointer Container Test Suite" );
329
330 test->add( BOOST_TEST_CASE( &test_serialization ) );
331
332 return test;
333 }
334
335
336