serialization.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  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. #include <boost/config.hpp>
  12. #ifdef BOOST_MSVC
  13. #pragma warning( disable: 4996 )
  14. #endif
  15. #include <boost/test/unit_test.hpp>
  16. #include <boost/archive/text_oarchive.hpp>
  17. #include <boost/archive/text_iarchive.hpp>
  18. #include <boost/archive/xml_iarchive.hpp>
  19. #include <boost/archive/xml_oarchive.hpp>
  20. #include <boost/functional/hash.hpp>
  21. #include <boost/ptr_container/ptr_container.hpp>
  22. #include <boost/ptr_container/serialize_ptr_container.hpp>
  23. #include <boost/serialization/export.hpp>
  24. #include <boost/serialization/base_object.hpp>
  25. #include <boost/serialization/utility.hpp>
  26. #include <boost/serialization/string.hpp>
  27. #include <fstream>
  28. #include <string>
  29. #include <cstdio>
  30. //
  31. // serialization helper: we can't save a non-const object
  32. //
  33. template< class T >
  34. inline T const& as_const( T const& r )
  35. {
  36. return r;
  37. }
  38. //
  39. // used to customize tests for circular_buffer
  40. //
  41. template< class Cont >
  42. struct set_capacity
  43. {
  44. void operator()( Cont& ) const
  45. { }
  46. };
  47. template<class T>
  48. struct set_capacity< boost::ptr_circular_buffer<T> >
  49. {
  50. void operator()( boost::ptr_circular_buffer<T>& c ) const
  51. {
  52. c.set_capacity( 100u );
  53. }
  54. };
  55. //
  56. // class hierarchy
  57. //
  58. struct Base
  59. {
  60. friend class boost::serialization::access;
  61. int i;
  62. template< class Archive >
  63. void serialize( Archive& ar, const unsigned int /*version*/ )
  64. {
  65. ar & boost::serialization::make_nvp( "i", i );
  66. }
  67. Base() : i(42)
  68. { }
  69. Base( int i ) : i(i)
  70. { }
  71. virtual ~Base()
  72. { }
  73. };
  74. inline bool operator<( const Base& l, const Base& r )
  75. {
  76. return l.i < r.i;
  77. }
  78. inline bool operator==( const Base& l, const Base& r )
  79. {
  80. return l.i == r.i;
  81. }
  82. inline std::size_t hash_value( const Base& b )
  83. {
  84. return boost::hash_value( b.i );
  85. }
  86. struct Derived : Base
  87. {
  88. int i2;
  89. template< class Archive >
  90. void serialize( Archive& ar, const unsigned int /*version*/ )
  91. {
  92. ar & boost::serialization::make_nvp( "Base",
  93. boost::serialization::base_object<Base>( *this ) );
  94. ar & boost::serialization::make_nvp( "i2", i2 );
  95. }
  96. Derived() : Base(42), i2(42)
  97. { }
  98. explicit Derived( int i2 ) : Base(0), i2(i2)
  99. { }
  100. };
  101. BOOST_CLASS_EXPORT_GUID( Derived, "Derived" )
  102. //
  103. // test of containers
  104. //
  105. //
  106. template< class C, class T >
  107. void add( C& c, T* r, unsigned /*n*/ )
  108. {
  109. c.insert( c.end(), r );
  110. }
  111. template< class U, class T >
  112. void add( boost::ptr_array<U,2>& c, T* r, unsigned n )
  113. {
  114. c.replace( n, r );
  115. }
  116. template< class Cont, class OArchive, class IArchive >
  117. void test_serialization_helper()
  118. {
  119. Cont vec;
  120. set_capacity<Cont>()( vec );
  121. add( vec, new Base( -1 ), 0u );
  122. add( vec, new Derived( 1 ), 1u );
  123. BOOST_CHECK_EQUAL( vec.size(), 2u );
  124. std::string fn = std::tmpnam( 0 );
  125. {
  126. std::ofstream ofs( fn.c_str() );
  127. OArchive oa(ofs);
  128. oa << boost::serialization::make_nvp( "container", as_const(vec) );
  129. }
  130. Cont vec2;
  131. {
  132. std::ifstream ifs( fn.c_str(), std::ios::binary );
  133. IArchive ia(ifs);
  134. ia >> boost::serialization::make_nvp( "container", vec2 );
  135. }
  136. std::remove( fn.c_str() );
  137. BOOST_CHECK_EQUAL( vec.size(), vec2.size() );
  138. BOOST_CHECK_EQUAL( (*vec2.begin()).i, -1 );
  139. BOOST_CHECK_EQUAL( (*++vec2.begin()).i, 0 );
  140. typename Cont::iterator i = vec2.begin();
  141. ++i;
  142. Derived* d = dynamic_cast<Derived*>( &*i );
  143. BOOST_CHECK_EQUAL( d->i2, 1 );
  144. }
  145. template< class Cont, class OArchive, class IArchive >
  146. void test_serialization_unordered_set_helper()
  147. {
  148. Cont vec;
  149. set_capacity<Cont>()( vec );
  150. add( vec, new Base( -1 ), 0u );
  151. add( vec, new Derived( 1 ), 1u );
  152. BOOST_CHECK_EQUAL( vec.size(), 2u );
  153. std::string fn = std::tmpnam( 0 );
  154. {
  155. std::ofstream ofs( fn.c_str() );
  156. OArchive oa(ofs);
  157. oa << boost::serialization::make_nvp( "container", as_const(vec) );
  158. }
  159. Cont vec2;
  160. {
  161. std::ifstream ifs( fn.c_str(), std::ios::binary );
  162. IArchive ia(ifs);
  163. ia >> boost::serialization::make_nvp( "container", vec2 );
  164. }
  165. std::remove( fn.c_str() );
  166. BOOST_CHECK_EQUAL( vec.size(), vec2.size() );
  167. BOOST_CHECK_EQUAL( (*vec2.begin()).i, -1 );
  168. BOOST_CHECK_EQUAL( (*++vec2.begin()).i, 0 );
  169. }
  170. template< class Map, class OArchive, class IArchive >
  171. void test_serialization_map_helper()
  172. {
  173. Map m;
  174. std::string key1("key1"), key2("key2");
  175. m.insert( key1, new Base( -1 ) );
  176. m.insert( key2, new Derived( 1 ) );
  177. BOOST_CHECK_EQUAL( m.size(), 2u );
  178. std::string fn = std::tmpnam( 0 );
  179. {
  180. std::ofstream ofs( fn.c_str() );
  181. OArchive oa(ofs);
  182. oa << boost::serialization::make_nvp( "container", as_const(m) );
  183. }
  184. Map m2;
  185. {
  186. std::ifstream ifs( fn.c_str(), std::ios::binary );
  187. IArchive ia(ifs);
  188. ia >> boost::serialization::make_nvp( "container", m2 );
  189. }
  190. std::remove( fn.c_str() );
  191. BOOST_CHECK_EQUAL( m.size(), m2.size() );
  192. BOOST_CHECK_EQUAL( m2.find(key1)->second->i, -1 );
  193. BOOST_CHECK_EQUAL( m2.find(key2)->second->i, 0 );
  194. typename Map::iterator i = m2.find(key2);
  195. Derived* d = dynamic_cast<Derived*>( i->second );
  196. BOOST_CHECK_EQUAL( d->i2, 1 );
  197. }
  198. //
  199. // basic test of hierarchy
  200. //
  201. void test_hierarchy()
  202. {
  203. Base* p = new Derived();
  204. std::string fn = std::tmpnam( 0 );
  205. {
  206. std::ofstream ofs( fn.c_str() );
  207. boost::archive::text_oarchive oa(ofs);
  208. oa << as_const(p);
  209. }
  210. Base* d = 0;
  211. {
  212. std::ifstream ifs( fn.c_str(), std::ios::binary );
  213. boost::archive::text_iarchive ia(ifs);
  214. ia >> d;
  215. }
  216. std::remove( fn.c_str() );
  217. BOOST_CHECK_EQUAL( p->i, d->i );
  218. BOOST_CHECK( p != d );
  219. BOOST_CHECK( dynamic_cast<Derived*>( d ) );
  220. delete p;
  221. delete d;
  222. }
  223. //
  224. // test initializer
  225. //
  226. void test_serialization()
  227. {
  228. test_hierarchy();
  229. test_serialization_helper< boost::ptr_deque<Base>,
  230. boost::archive::text_oarchive,
  231. boost::archive::text_iarchive >();
  232. test_serialization_helper< boost::ptr_list<Base>,
  233. boost::archive::text_oarchive,
  234. boost::archive::text_iarchive>();
  235. test_serialization_helper< boost::ptr_vector<Base>,
  236. boost::archive::text_oarchive,
  237. boost::archive::text_iarchive>();
  238. test_serialization_helper< boost::ptr_vector<Base>,
  239. boost::archive::xml_oarchive,
  240. boost::archive::xml_iarchive>();
  241. test_serialization_helper< boost::ptr_circular_buffer<Base>,
  242. boost::archive::text_oarchive,
  243. boost::archive::text_iarchive>();
  244. test_serialization_helper< boost::ptr_circular_buffer<Base>,
  245. boost::archive::xml_oarchive,
  246. boost::archive::xml_iarchive>();
  247. test_serialization_helper< boost::ptr_array<Base,2>,
  248. boost::archive::text_oarchive,
  249. boost::archive::text_iarchive>();
  250. test_serialization_helper< boost::ptr_set<Base>,
  251. boost::archive::text_oarchive,
  252. boost::archive::text_iarchive>();
  253. test_serialization_helper< boost::ptr_multiset<Base>,
  254. boost::archive::text_oarchive,
  255. boost::archive::text_iarchive>();
  256. test_serialization_unordered_set_helper< boost::ptr_unordered_set<Base>,
  257. boost::archive::text_oarchive,
  258. boost::archive::text_iarchive>();
  259. test_serialization_unordered_set_helper<boost::ptr_unordered_multiset<Base>,
  260. boost::archive::text_oarchive,
  261. boost::archive::text_iarchive>();
  262. test_serialization_map_helper< boost::ptr_map<std::string,Base>,
  263. boost::archive::text_oarchive,
  264. boost::archive::text_iarchive>();
  265. test_serialization_map_helper< boost::ptr_multimap<std::string,Base>,
  266. boost::archive::text_oarchive,
  267. boost::archive::text_iarchive>();
  268. test_serialization_map_helper< boost::ptr_map<std::string,Base>,
  269. boost::archive::xml_oarchive,
  270. boost::archive::xml_iarchive>();
  271. test_serialization_map_helper< boost::ptr_multimap<std::string,Base>,
  272. boost::archive::xml_oarchive,
  273. boost::archive::xml_iarchive>();
  274. test_serialization_map_helper< boost::ptr_unordered_map<std::string,Base>,
  275. boost::archive::text_oarchive,
  276. boost::archive::text_iarchive>();
  277. test_serialization_map_helper< boost::ptr_unordered_multimap<std::string,Base>,
  278. boost::archive::text_oarchive,
  279. boost::archive::text_iarchive>();
  280. test_serialization_map_helper< boost::ptr_unordered_map<std::string,Base>,
  281. boost::archive::xml_oarchive,
  282. boost::archive::xml_iarchive>();
  283. test_serialization_map_helper< boost::ptr_unordered_multimap<std::string,Base>,
  284. boost::archive::xml_oarchive,
  285. boost::archive::xml_iarchive>();
  286. }
  287. using boost::unit_test::test_suite;
  288. test_suite* init_unit_test_suite( int argc, char* argv[] )
  289. {
  290. test_suite* test = BOOST_TEST_SUITE( "Pointer Container Test Suite" );
  291. test->add( BOOST_TEST_CASE( &test_serialization ) );
  292. return test;
  293. }