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