test_cyclic_ptrs.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  2. // test_cyclic_ptrs.cpp
  3. // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
  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. // should pass compilation and execution
  8. #include <cstddef> // NULL
  9. #include <fstream>
  10. #include <cstdio> // remove
  11. #include <boost/config.hpp>
  12. #if defined(BOOST_NO_STDC_NAMESPACE)
  13. namespace std{
  14. using ::remove;
  15. }
  16. #endif
  17. #include "test_tools.hpp"
  18. #include <boost/core/no_exceptions_support.hpp>
  19. #include <boost/serialization/nvp.hpp>
  20. #include <boost/serialization/version.hpp>
  21. #include <boost/serialization/base_object.hpp>
  22. #include "A.hpp"
  23. #include "A.ipp"
  24. ///////////////////////////////////////////////////////
  25. // class with a member which refers to itself
  26. class J : public A
  27. {
  28. private:
  29. friend class boost::serialization::access;
  30. template<class Archive>
  31. void serialize(Archive &ar, const unsigned int /* file_version */){
  32. ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(A);
  33. ar & BOOST_SERIALIZATION_NVP(j);
  34. }
  35. public:
  36. bool operator==(const J &rhs) const;
  37. J *j;
  38. J(J *_j) : j(_j) {}
  39. J() : j(NULL){}
  40. };
  41. BOOST_CLASS_VERSION(J, 6)
  42. bool J::operator==(const J &rhs) const
  43. {
  44. return static_cast<const A &>(*this) == static_cast<const A &>(rhs);
  45. }
  46. ///////////////////////////////////////////////////////
  47. // class with members that refer to each other
  48. // this is an example of a class that, as written, cannot
  49. // be serialized with this system. The problem is that the
  50. // serialization of the first member - j1 , provokes serialization
  51. // of those objects which it points to either directly or indirectly.
  52. // When those objects are subsequently serialized, it is discovered
  53. // that have already been serialized through pointers. This is
  54. // detected by the system and an exception - pointer_conflict -
  55. // is thrown. Permiting this to go undetected would result in the
  56. // creation of multiple equal objects rather than the original
  57. // structure.
  58. class K
  59. {
  60. J j1;
  61. J j2;
  62. J j3;
  63. friend class boost::serialization::access;
  64. template<class Archive>
  65. void serialize(
  66. Archive &ar,
  67. const unsigned int /* file_version */
  68. ){
  69. ar & BOOST_SERIALIZATION_NVP(j1);
  70. ar & BOOST_SERIALIZATION_NVP(j2);
  71. ar & BOOST_SERIALIZATION_NVP(j3);
  72. }
  73. public:
  74. bool operator==(const K &rhs) const;
  75. K();
  76. };
  77. K::K()
  78. : j1(&j2), j2(&j3), j3(&j1)
  79. {
  80. }
  81. bool K::operator==(const K &rhs) const
  82. {
  83. return
  84. j1.j == & j2
  85. && j2.j == & j3
  86. && j3.j == & j1
  87. && j1 == rhs.j1
  88. && j2 == rhs.j2
  89. && j3 == rhs.j3
  90. ;
  91. }
  92. int test1(){
  93. const char * testfile = boost::archive::tmpnam(NULL);
  94. BOOST_REQUIRE(NULL != testfile);
  95. J j1, j2;
  96. {
  97. test_ostream os(testfile, TEST_STREAM_FLAGS);
  98. test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
  99. oa << BOOST_SERIALIZATION_NVP(j1);
  100. }
  101. {
  102. // try to read the archive
  103. test_istream is(testfile, TEST_STREAM_FLAGS);
  104. test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
  105. ia >> BOOST_SERIALIZATION_NVP(j2);
  106. }
  107. BOOST_CHECK(j1 == j2);
  108. std::remove(testfile);
  109. return EXIT_SUCCESS;
  110. }
  111. int test2(){
  112. const char * testfile = boost::archive::tmpnam(NULL);
  113. BOOST_REQUIRE(NULL != testfile);
  114. J *j1 = new J;
  115. j1->j = j1;
  116. J *j2 = reinterpret_cast<J *>(0xBAADF00D);
  117. {
  118. test_ostream os(testfile, TEST_STREAM_FLAGS);
  119. test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
  120. oa << BOOST_SERIALIZATION_NVP(j1);
  121. }
  122. {
  123. // try to read the archive
  124. test_istream is(testfile, TEST_STREAM_FLAGS);
  125. test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
  126. ia >> BOOST_SERIALIZATION_NVP(j2);
  127. }
  128. BOOST_CHECK(*j1 == *j2);
  129. delete j1;
  130. BOOST_CHECK(j2 == j2->j);
  131. std::remove(testfile);
  132. return EXIT_SUCCESS;
  133. }
  134. int test3(){
  135. const char * testfile = boost::archive::tmpnam(NULL);
  136. BOOST_REQUIRE(NULL != testfile);
  137. K k;
  138. boost::archive::archive_exception exception(
  139. boost::archive::archive_exception::no_exception
  140. );
  141. {
  142. test_ostream os(testfile, TEST_STREAM_FLAGS);
  143. test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
  144. BOOST_TRY {
  145. oa << BOOST_SERIALIZATION_NVP(k);
  146. }
  147. BOOST_CATCH (boost::archive::archive_exception const& ae){
  148. exception = ae;
  149. }
  150. BOOST_CATCH_END
  151. BOOST_CHECK(
  152. exception.code == boost::archive::archive_exception::pointer_conflict
  153. );
  154. }
  155. // if exception wasn't invoked
  156. if(exception.code == boost::archive::archive_exception::no_exception){
  157. // try to read the archive
  158. test_istream is(testfile, TEST_STREAM_FLAGS);
  159. test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
  160. exception = boost::archive::archive_exception(
  161. boost::archive::archive_exception::no_exception
  162. );
  163. BOOST_TRY {
  164. ia >> BOOST_SERIALIZATION_NVP(k);
  165. }
  166. BOOST_CATCH (boost::archive::archive_exception const& ae){
  167. exception = ae;
  168. }
  169. BOOST_CATCH_END
  170. BOOST_CHECK(
  171. exception.code == boost::archive::archive_exception::pointer_conflict
  172. );
  173. }
  174. std::remove(testfile);
  175. return EXIT_SUCCESS;
  176. }
  177. int test_main( int /* argc */, char* /* argv */[] ){
  178. test1();
  179. test2();
  180. test3();
  181. return EXIT_SUCCESS;
  182. }
  183. // EOF