test_shared_ptr_multi_base.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  2. // test_shared_ptr_multi_base.cpp
  3. // (C) Copyright 2002 Robert Ramey- http://www.rrsd.com and Takatoshi Kondo.
  4. // Use, modification and distribution is subject to the Boost Software
  5. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // See http://www.boost.org for updates, documentation, and revision history.
  9. #include <cstddef> // NULL
  10. #include <cstdio> // remove
  11. #include <fstream>
  12. #include <boost/config.hpp>
  13. #if defined(BOOST_NO_STDC_NAMESPACE)
  14. namespace std{
  15. using ::remove;
  16. }
  17. #endif
  18. #include <boost/serialization/nvp.hpp>
  19. #include <boost/serialization/export.hpp>
  20. #include <boost/serialization/shared_ptr.hpp>
  21. #include <boost/serialization/weak_ptr.hpp>
  22. #include "test_tools.hpp"
  23. struct Base1 {
  24. Base1() {}
  25. Base1(int x) : m_x(1 + x) {}
  26. virtual ~Base1(){
  27. }
  28. int m_x;
  29. // serialize
  30. friend class boost::serialization::access;
  31. template<class Archive>
  32. void serialize(Archive &ar, const unsigned int /* file_version */)
  33. {
  34. ar & BOOST_SERIALIZATION_NVP(m_x);
  35. }
  36. };
  37. struct Base2 {
  38. Base2() {}
  39. Base2(int x) : m_x(2 + x) {}
  40. int m_x;
  41. virtual ~Base2(){
  42. }
  43. // serialize
  44. friend class boost::serialization::access;
  45. template<class Archive>
  46. void serialize(Archive &ar, const unsigned int /* file_version */)
  47. {
  48. ar & BOOST_SERIALIZATION_NVP(m_x);
  49. }
  50. };
  51. struct Base3 {
  52. Base3() {}
  53. Base3(int x) : m_x(3 + x) {}
  54. virtual ~Base3(){
  55. }
  56. int m_x;
  57. // serialize
  58. friend class boost::serialization::access;
  59. template<class Archive>
  60. void serialize(Archive &ar, const unsigned int /* file_version */)
  61. {
  62. ar & BOOST_SERIALIZATION_NVP(m_x);
  63. }
  64. };
  65. // Sub is a subclass of Base1, Base1 and Base3.
  66. struct Sub:public Base1, public Base2, public Base3 {
  67. static int count;
  68. Sub() {
  69. ++count;
  70. }
  71. Sub(int x) :
  72. Base1(x),
  73. Base2(x),
  74. m_x(x)
  75. {
  76. ++count;
  77. }
  78. Sub(const Sub & rhs) :
  79. m_x(rhs.m_x)
  80. {
  81. ++count;
  82. }
  83. virtual ~Sub() {
  84. assert(0 < count);
  85. --count;
  86. }
  87. int m_x;
  88. // serialize
  89. friend class boost::serialization::access;
  90. template<class Archive>
  91. void serialize(Archive &ar, const unsigned int /* file_version */)
  92. {
  93. ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base1);
  94. ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base2);
  95. ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base3);
  96. ar & BOOST_SERIALIZATION_NVP(m_x);
  97. }
  98. };
  99. // Sub needs to be exported because its serialized via a base class pointer
  100. BOOST_CLASS_EXPORT(Sub)
  101. BOOST_SERIALIZATION_SHARED_PTR(Sub)
  102. int Sub::count = 0;
  103. template <class FIRST, class SECOND>
  104. void save2(
  105. const char * testfile,
  106. const FIRST& first,
  107. const SECOND& second
  108. ){
  109. test_ostream os(testfile, TEST_STREAM_FLAGS);
  110. test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
  111. oa << BOOST_SERIALIZATION_NVP(first);
  112. oa << BOOST_SERIALIZATION_NVP(second);
  113. }
  114. template <class FIRST, class SECOND>
  115. void load2(
  116. const char * testfile,
  117. FIRST& first,
  118. SECOND& second)
  119. {
  120. test_istream is(testfile, TEST_STREAM_FLAGS);
  121. test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
  122. ia >> BOOST_SERIALIZATION_NVP(first);
  123. ia >> BOOST_SERIALIZATION_NVP(second);
  124. }
  125. // Run tests by serializing two shared_ptrs into an archive,
  126. // clearing them (deleting the objects) and then reloading the
  127. // objects back from an archive.
  128. template<class T, class U>
  129. boost::shared_ptr<T> dynamic_pointer_cast(boost::shared_ptr<U> const & u)
  130. BOOST_NOEXCEPT
  131. {
  132. return boost::dynamic_pointer_cast<T>(u);
  133. }
  134. #ifndef BOOST_NO_CXX11_SMART_PTR
  135. template<class T, class U>
  136. std::shared_ptr<T> dynamic_pointer_cast(std::shared_ptr<U> const & u)
  137. BOOST_NOEXCEPT
  138. {
  139. return std::dynamic_pointer_cast<T>(u);
  140. }
  141. #endif
  142. // Serialization sequence
  143. // First, shared_ptr
  144. // Second, weak_ptr
  145. template <class SP, class WP>
  146. void shared_weak(
  147. SP & first,
  148. WP & second
  149. ){
  150. const char * testfile = boost::archive::tmpnam(NULL);
  151. BOOST_REQUIRE(NULL != testfile);
  152. int firstm = first->m_x;
  153. BOOST_REQUIRE(! second.expired());
  154. int secondm = second.lock()->m_x;
  155. save2(testfile, first, second);
  156. // Clear the pointers, thereby destroying the objects they contain
  157. second.reset();
  158. first.reset();
  159. load2(testfile, first, second);
  160. BOOST_CHECK(! second.expired());
  161. // Check data member
  162. BOOST_CHECK(firstm == first->m_x);
  163. BOOST_CHECK(secondm == second.lock()->m_x);
  164. // Check pointer to vtable
  165. BOOST_CHECK(::dynamic_pointer_cast<Sub>(first));
  166. BOOST_CHECK(::dynamic_pointer_cast<Sub>(second.lock()));
  167. std::remove(testfile);
  168. }
  169. // Serialization sequence
  170. // First, weak_ptr
  171. // Second, shared_ptr
  172. template <class WP, class SP>
  173. void weak_shared(
  174. WP & first,
  175. SP & second
  176. ){
  177. const char * testfile = boost::archive::tmpnam(NULL);
  178. BOOST_REQUIRE(NULL != testfile);
  179. BOOST_CHECK(! first.expired());
  180. int firstm = first.lock()->m_x;
  181. int secondm = second->m_x;
  182. save2(testfile, first, second);
  183. // Clear the pointers, thereby destroying the objects they contain
  184. first.reset();
  185. second.reset();
  186. load2(testfile, first, second);
  187. BOOST_CHECK(! first.expired());
  188. // Check data member
  189. BOOST_CHECK(firstm == first.lock()->m_x);
  190. BOOST_CHECK(secondm == second->m_x);
  191. // Check pointer to vtable
  192. BOOST_CHECK(::dynamic_pointer_cast<Sub>(first.lock()));
  193. BOOST_CHECK(::dynamic_pointer_cast<Sub>(second));
  194. std::remove(testfile);
  195. }
  196. // This does the tests
  197. template<template<class T> class SPT, template<class T> class WPT>
  198. bool test(){
  199. // Both Sub
  200. SPT<Sub> tc1_sp(new Sub(10));
  201. WPT<Sub> tc1_wp(tc1_sp);
  202. shared_weak(tc1_sp, tc1_wp);
  203. weak_shared(tc1_wp, tc1_sp);
  204. tc1_sp.reset();
  205. BOOST_CHECK(0 == Sub::count);
  206. // Sub and Base1
  207. SPT<Sub> tc2_sp(new Sub(10));
  208. WPT<Base1> tc2_wp(tc2_sp);
  209. shared_weak(tc2_sp, tc2_wp);
  210. weak_shared(tc2_wp, tc2_sp);
  211. tc2_sp.reset();
  212. BOOST_CHECK(0 == Sub::count);
  213. // Sub and Base2
  214. SPT<Sub> tc3_sp(new Sub(10));
  215. WPT<Base2> tc3_wp(tc3_sp);
  216. shared_weak(tc3_sp, tc3_wp);
  217. weak_shared(tc3_wp, tc3_sp);
  218. tc3_sp.reset();
  219. BOOST_CHECK(0 == Sub::count);
  220. // Sub and Base3
  221. SPT<Sub> tc4_sp(new Sub(10));
  222. WPT<Base3> tc4_wp(tc4_sp);
  223. shared_weak(tc4_sp, tc4_wp);
  224. weak_shared(tc4_wp, tc4_sp);
  225. tc4_sp.reset();
  226. BOOST_CHECK(0 == Sub::count);
  227. // Base1 and Base2
  228. SPT<Sub> tc5_sp_tmp(new Sub(10));
  229. SPT<Base1> tc5_sp(tc5_sp_tmp);
  230. WPT<Base2> tc5_wp(tc5_sp_tmp);
  231. tc5_sp_tmp.reset();
  232. shared_weak(tc5_sp, tc5_wp);
  233. weak_shared(tc5_wp, tc5_sp);
  234. tc5_sp.reset();
  235. BOOST_CHECK(0 == Sub::count);
  236. // Base2 and Base3
  237. SPT<Sub> tc6_sp_tmp(new Sub(10));
  238. SPT<Base2> tc6_sp(tc6_sp_tmp);
  239. WPT<Base3> tc6_wp(tc6_sp_tmp);
  240. tc6_sp_tmp.reset();
  241. shared_weak(tc6_sp, tc6_wp);
  242. weak_shared(tc6_wp, tc6_sp);
  243. tc6_sp.reset();
  244. BOOST_CHECK(0 == Sub::count);
  245. // Base3 and Base1
  246. SPT<Sub> tc7_sp_tmp(new Sub(10));
  247. SPT<Base3> tc7_sp(tc7_sp_tmp);
  248. WPT<Base1> tc7_wp(tc7_sp_tmp);
  249. tc7_sp_tmp.reset();
  250. shared_weak(tc7_sp, tc7_wp);
  251. weak_shared(tc7_wp, tc7_sp);
  252. tc7_sp.reset();
  253. BOOST_CHECK(0 == Sub::count);
  254. return true;
  255. }
  256. // This does the tests
  257. int test_main(int /* argc */, char * /* argv */[])
  258. {
  259. bool result = true;
  260. result &= test<boost::shared_ptr, boost::weak_ptr>();
  261. #ifndef BOOST_NO_CXX11_SMART_PTR
  262. result &= test<std::shared_ptr, std::weak_ptr>();
  263. #endif
  264. return result ? EXIT_SUCCESS : EXIT_FAILURE;
  265. }