test_shared_ptr.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  2. // test_shared_ptr.cpp
  3. // (C) Copyright 2002 Robert Ramey- http://www.rrsd.com - David Tonge .
  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. // This is a simple class. It contains a counter of the number
  24. // of objects of this class which have been instantiated.
  25. class A
  26. {
  27. private:
  28. friend class boost::serialization::access;
  29. int x;
  30. template<class Archive>
  31. void serialize(Archive & ar, const unsigned int /* file_version */){
  32. ar & BOOST_SERIALIZATION_NVP(x);
  33. }
  34. A(A const & rhs);
  35. A& operator=(A const & rhs);
  36. public:
  37. static int count;
  38. bool operator==(const A & rhs) const {
  39. return x == rhs.x;
  40. }
  41. A(){++count;} // default constructor
  42. virtual ~A(){--count;} // default destructor
  43. };
  44. BOOST_SERIALIZATION_SHARED_PTR(A)
  45. int A::count = 0;
  46. // B is a subclass of A
  47. class B : public A
  48. {
  49. private:
  50. friend class boost::serialization::access;
  51. template<class Archive>
  52. void serialize(Archive & ar, const unsigned int /* file_version */){
  53. ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(A);
  54. }
  55. public:
  56. static int count;
  57. B() : A() {};
  58. virtual ~B() {};
  59. };
  60. // B needs to be exported because its serialized via a base class pointer
  61. BOOST_CLASS_EXPORT(B)
  62. BOOST_SERIALIZATION_SHARED_PTR(B)
  63. // test a non-polymorphic class
  64. class C
  65. {
  66. private:
  67. friend class boost::serialization::access;
  68. int z;
  69. template<class Archive>
  70. void serialize(Archive & ar, const unsigned int /* file_version */){
  71. ar & BOOST_SERIALIZATION_NVP(z);
  72. }
  73. public:
  74. static int count;
  75. bool operator==(const C & rhs) const {
  76. return z == rhs.z;
  77. }
  78. C() :
  79. z(++count) // default constructor
  80. {}
  81. virtual ~C(){--count;} // default destructor
  82. };
  83. int C::count = 0;
  84. template<class SP>
  85. void save(const char * testfile, const SP & spa)
  86. {
  87. test_ostream os(testfile, TEST_STREAM_FLAGS);
  88. test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
  89. oa << BOOST_SERIALIZATION_NVP(spa);
  90. }
  91. template<class SP>
  92. void load(const char * testfile, SP & spa)
  93. {
  94. test_istream is(testfile, TEST_STREAM_FLAGS);
  95. test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
  96. ia >> BOOST_SERIALIZATION_NVP(spa);
  97. }
  98. // trivial test
  99. template<class SP>
  100. void save_and_load(SP & spa)
  101. {
  102. const char * testfile = boost::archive::tmpnam(NULL);
  103. BOOST_REQUIRE(NULL != testfile);
  104. save(testfile, spa);
  105. SP spa1;
  106. load(testfile, spa1);
  107. BOOST_CHECK(
  108. (spa.get() == NULL && spa1.get() == NULL)
  109. || * spa == * spa1
  110. );
  111. std::remove(testfile);
  112. }
  113. template<class SP>
  114. void save2(
  115. const char * testfile,
  116. const SP & first,
  117. const SP & second
  118. ){
  119. test_ostream os(testfile, TEST_STREAM_FLAGS);
  120. test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
  121. oa << BOOST_SERIALIZATION_NVP(first);
  122. oa << BOOST_SERIALIZATION_NVP(second);
  123. }
  124. template<class SP>
  125. void load2(
  126. const char * testfile,
  127. SP & first,
  128. SP & second)
  129. {
  130. test_istream is(testfile, TEST_STREAM_FLAGS);
  131. test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
  132. ia >> BOOST_SERIALIZATION_NVP(first);
  133. ia >> BOOST_SERIALIZATION_NVP(second);
  134. }
  135. // Run tests by serializing two shared_ptrs into an archive,
  136. // clearing them (deleting the objects) and then reloading the
  137. // objects back from an archive.
  138. template<class SP>
  139. void save_and_load2(SP & first, SP & second)
  140. {
  141. const char * testfile = boost::archive::tmpnam(NULL);
  142. BOOST_REQUIRE(NULL != testfile);
  143. save2(testfile, first, second);
  144. // Clear the pointers, thereby destroying the objects they contain
  145. first.reset();
  146. second.reset();
  147. load2(testfile, first, second);
  148. BOOST_CHECK(first == second);
  149. std::remove(testfile);
  150. }
  151. template<class SP, class WP>
  152. void save3(
  153. const char * testfile,
  154. SP & first,
  155. SP & second,
  156. WP & third
  157. ){
  158. test_ostream os(testfile, TEST_STREAM_FLAGS);
  159. test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
  160. oa << BOOST_SERIALIZATION_NVP(third);
  161. oa << BOOST_SERIALIZATION_NVP(first);
  162. oa << BOOST_SERIALIZATION_NVP(second);
  163. }
  164. template<class SP, class WP>
  165. void load3(
  166. const char * testfile,
  167. SP & first,
  168. SP & second,
  169. WP & third
  170. ){
  171. test_istream is(testfile, TEST_STREAM_FLAGS);
  172. test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
  173. // note that we serialize the weak pointer first
  174. ia >> BOOST_SERIALIZATION_NVP(third);
  175. // inorder to test that a temporarily solitary weak pointer
  176. // correctly restored.
  177. ia >> BOOST_SERIALIZATION_NVP(first);
  178. ia >> BOOST_SERIALIZATION_NVP(second);
  179. }
  180. template<class SP, class WP>
  181. void save_and_load3(
  182. SP & first,
  183. SP & second,
  184. WP & third
  185. ){
  186. const char * testfile = boost::archive::tmpnam(NULL);
  187. BOOST_REQUIRE(NULL != testfile);
  188. save3(testfile, first, second, third);
  189. // Clear the pointers, thereby destroying the objects they contain
  190. first.reset();
  191. second.reset();
  192. third.reset();
  193. load3(testfile, first, second, third);
  194. BOOST_CHECK(first == second);
  195. BOOST_CHECK(first == third.lock());
  196. std::remove(testfile);
  197. }
  198. template<class SP>
  199. void save4(const char * testfile, const SP & spc)
  200. {
  201. test_ostream os(testfile, TEST_STREAM_FLAGS);
  202. test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
  203. oa << BOOST_SERIALIZATION_NVP(spc);
  204. }
  205. template<class SP>
  206. void load4(const char * testfile, SP & spc)
  207. {
  208. test_istream is(testfile, TEST_STREAM_FLAGS);
  209. test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
  210. ia >> BOOST_SERIALIZATION_NVP(spc);
  211. }
  212. // trivial test
  213. template<class SP>
  214. void save_and_load4(SP & spc)
  215. {
  216. const char * testfile = boost::archive::tmpnam(NULL);
  217. BOOST_REQUIRE(NULL != testfile);
  218. save4(testfile, spc);
  219. SP spc1;
  220. load4(testfile, spc1);
  221. BOOST_CHECK(
  222. (spc.get() == NULL && spc1.get() == NULL)
  223. || * spc == * spc1
  224. );
  225. std::remove(testfile);
  226. }
  227. // This does the tests
  228. template<template<class T> class SPT , template<class T> class WPT >
  229. bool test(){
  230. {
  231. SPT<A> spa;
  232. // These are our shared_ptrs
  233. spa = SPT<A>(new A);
  234. SPT<A> spa1 = spa;
  235. spa1 = spa;
  236. }
  237. {
  238. // These are our shared_ptrs
  239. SPT<A> spa;
  240. // trivial test 1
  241. save_and_load(spa);
  242. //trivival test 2
  243. spa = SPT<A>(new A);
  244. save_and_load(spa);
  245. // Try to save and load pointers to As
  246. spa = SPT<A>(new A);
  247. SPT<A> spa1 = spa;
  248. save_and_load2(spa, spa1);
  249. // Try to save and load pointers to Bs
  250. spa = SPT<A>(new B);
  251. spa1 = spa;
  252. save_and_load2(spa, spa1);
  253. // test a weak pointer
  254. spa = SPT<A>(new A);
  255. spa1 = spa;
  256. WPT<A> wp = spa;
  257. save_and_load3(spa, spa1, wp);
  258. // obj of type B gets destroyed
  259. // as smart_ptr goes out of scope
  260. }
  261. BOOST_CHECK(A::count == 0);
  262. {
  263. // Try to save and load pointers to Cs
  264. SPT<C> spc;
  265. spc = SPT<C>(new C);
  266. save_and_load4(spc);
  267. }
  268. BOOST_CHECK(C::count == 0);
  269. return true;
  270. }
  271. // This does the tests
  272. int test_main(int /* argc */, char * /* argv */[])
  273. {
  274. bool result = true;
  275. result &= test<boost::shared_ptr, boost::weak_ptr>();
  276. #ifndef BOOST_NO_CXX11_SMART_PTR
  277. result &= test<std::shared_ptr, std::weak_ptr>();
  278. #endif
  279. return result ? EXIT_SUCCESS : EXIT_FAILURE;
  280. }