/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 // test_reset_object_address.cpp // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . // Use, modification and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include // for rand() #include // size_t #include #if defined(BOOST_NO_STDC_NAMESPACE) namespace std{ using ::rand; using ::size_t; } #endif #include "test_tools.hpp" #include #include #include #include #include #include // Someday, maybe all tests will be converted to the unit test framework. // but for now use the text execution monitor to be consistent with all // the other tests. // simple test of untracked value #include "A.hpp" #include "A.ipp" void test1(){ std::stringstream ss; const A a; { boost::archive::text_oarchive oa(ss); oa << a; } A a1; { boost::archive::text_iarchive ia(ss); // load to temporary A a2; ia >> a2; BOOST_CHECK_EQUAL(a, a2); // move to final destination a1 = a2; ia.reset_object_address(& a1, & a2); } BOOST_CHECK_EQUAL(a, a1); } // simple test of tracked value class B { friend class boost::serialization::access; int m_i; template void serialize(Archive &ar, const unsigned int /*file_version*/){ ar & m_i; } public: bool operator==(const B & rhs) const { return m_i == rhs.m_i; } B() : m_i(std::rand()) {} }; //BOOST_TEST_DONT_PRINT_LOG_VALUE( B ) void test2(){ std::stringstream ss; B const b; B const * const b_ptr = & b; BOOST_CHECK_EQUAL(& b, b_ptr); { boost::archive::text_oarchive oa(ss); oa << b; oa << b_ptr; } B b1; B * b1_ptr; { boost::archive::text_iarchive ia(ss); // load to temporary B b2; ia >> b2; BOOST_CHECK_EQUAL(b, b2); // move to final destination b1 = b2; ia.reset_object_address(& b1, & b2); ia >> b1_ptr; } BOOST_CHECK_EQUAL(b, b1); BOOST_CHECK_EQUAL(& b1, b1_ptr); } // check that nested member values are properly moved class D { friend class boost::serialization::access; template void serialize(Archive &ar, const unsigned int /*file_version*/){ ar & m_b; } public: B m_b; bool operator==(const D & rhs) const { return m_b == rhs.m_b; } D(){} }; //BOOST_TEST_DONT_PRINT_LOG_VALUE( D ) void test3(){ std::stringstream ss; D const d; B const * const b_ptr = & d.m_b; { boost::archive::text_oarchive oa(ss); oa << d; oa << b_ptr; } D d1; B * b1_ptr; { boost::archive::text_iarchive ia(ss); D d2; ia >> d2; d1 = d2; ia.reset_object_address(& d1, & d2); ia >> b1_ptr; } BOOST_CHECK_EQUAL(d, d1); BOOST_CHECK_EQUAL(* b_ptr, * b1_ptr); } // check that data pointed to by pointer members is NOT moved class E { int m_i; friend class boost::serialization::access; template void serialize(Archive &ar, const unsigned int /*file_version*/){ ar & m_i; } public: bool operator==(const E &rhs) const { return m_i == rhs.m_i; } E() : m_i(std::rand()) {} E(const E & rhs) : m_i(rhs.m_i) {} }; //BOOST_TEST_DONT_PRINT_LOG_VALUE( E ) // check that moves don't move stuff pointed to class F { friend class boost::serialization::access; E * m_eptr; template void serialize(Archive &ar, const unsigned int /*file_version*/){ ar & m_eptr; } public: bool operator==(const F &rhs) const { return *m_eptr == *rhs.m_eptr; } F & operator=(const F & rhs) { * m_eptr = * rhs.m_eptr; return *this; } F(){ m_eptr = new E; } F(const F & rhs){ *this = rhs; } ~F(){ delete m_eptr; } }; //BOOST_TEST_DONT_PRINT_LOG_VALUE( F ) void test4(){ std::stringstream ss; const F f; { boost::archive::text_oarchive oa(ss); oa << f; } F f1; { boost::archive::text_iarchive ia(ss); F f2; ia >> f2; f1 = f2; ia.reset_object_address(& f1, & f2); } BOOST_CHECK_EQUAL(f, f1); } // check that multiple moves keep track of the correct target class G { friend class boost::serialization::access; A m_a1; A m_a2; A *m_pa2; template void save(Archive &ar, const unsigned int /*file_version*/) const { ar << m_a1; ar << m_a2; ar << m_pa2; } template void load(Archive &ar, const unsigned int /*file_version*/){ A a; // temporary A ar >> a; m_a1 = a; ar.reset_object_address(& m_a1, & a); ar >> a; m_a2 = a; ar.reset_object_address(& m_a2, & a); ar & m_pa2; } BOOST_SERIALIZATION_SPLIT_MEMBER() public: bool operator==(const G &rhs) const { return m_a1 == rhs.m_a1 && m_a2 == rhs.m_a2 && *m_pa2 == *rhs.m_pa2; } G & operator=(const G & rhs) { m_a1 = rhs.m_a1; m_a2 = rhs.m_a2; m_pa2 = & m_a2; return *this; } G(){ m_pa2 = & m_a2; } G(const G & rhs){ *this = rhs; } ~G(){} }; //BOOST_TEST_DONT_PRINT_LOG_VALUE( G ) void test5(){ std::stringstream ss; const G g; { boost::archive::text_oarchive oa(ss); oa << g; } G g1; { boost::archive::text_iarchive ia(ss); ia >> g1; } BOOST_CHECK_EQUAL(g, g1); } // joaquin's test - this tests the case where rest_object_address // is applied to an item which in fact is not tracked so that // the call is in fact superfluous. struct foo { int x; private: friend class boost::serialization::access; template void serialize(Archive &,const unsigned int) { } }; struct bar { foo f[2]; foo* pf[2]; private: friend class boost::serialization::access; BOOST_SERIALIZATION_SPLIT_MEMBER() template void save(Archive& ar,const unsigned int)const { for(int i=0;i<2;++i){ ar< void load(Archive& ar,const unsigned int) { for(int i=0;i<2;++i){ int x; ar>>x; f[i].x=x; ar.reset_object_address(&f[i].x,&x); ar>>f[i]; } for(int j=0;j<2;++j){ ar>>pf[j]; } } }; int test6() { bar b; b.f[0].x=0; b.f[1].x=1; b.pf[0]=&b.f[0]; b.pf[1]=&b.f[1]; std::ostringstream oss; { boost::archive::text_oarchive oa(oss); oa<(b); } bar b1; b1.pf[0]=0; b1.pf[1]=0; std::istringstream iss(oss.str()); boost::archive::text_iarchive ia(iss); ia>>b1; BOOST_CHECK(b1.pf[0]==&b1.f[0]&&b1.pf[1]==&b1.f[1]); return 0; } // test one of the collections void test7(){ std::stringstream ss; B const b; B const * const b_ptr = & b; BOOST_CHECK_EQUAL(& b, b_ptr); { std::list l; l.push_back(b_ptr); boost::archive::text_oarchive oa(ss); oa << const_cast &>(l); } B b1; { std::list l; boost::archive::text_iarchive ia(ss); ia >> l; delete l.front(); // prevent memory leak } } // test one of the collections with polymorphic archive void test8(){ std::stringstream ss; B const b; B const * const b_ptr = & b; BOOST_CHECK_EQUAL(& b, b_ptr); { std::list l; l.push_back(b_ptr); boost::archive::polymorphic_text_oarchive oa(ss); boost::archive::polymorphic_oarchive & poa = oa; poa << const_cast &>(l); } B b1; { std::list l; boost::archive::polymorphic_text_iarchive ia(ss); boost::archive::polymorphic_iarchive & pia = ia; pia >> l; delete l.front(); // prevent memory leak } } int test_main(int /* argc */, char * /* argv */[]) { test1(); test2(); test3(); test4(); test5(); test6(); test7(); test8(); return EXIT_SUCCESS; }