4d360d1082
[SVN r58151]
413 lines
8.6 KiB
C++
413 lines
8.6 KiB
C++
/////////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 <sstream>
|
|
#include <cassert>
|
|
#include <cstdlib> // for rand()
|
|
#include <cstddef> // size_t
|
|
|
|
#include <boost/config.hpp>
|
|
#if defined(BOOST_NO_STDC_NAMESPACE)
|
|
namespace std{
|
|
using ::rand;
|
|
using ::size_t;
|
|
}
|
|
#endif
|
|
|
|
#include "test_tools.hpp"
|
|
|
|
#include <boost/archive/text_oarchive.hpp>
|
|
#include <boost/archive/text_iarchive.hpp>
|
|
#include <boost/archive/polymorphic_text_oarchive.hpp>
|
|
#include <boost/archive/polymorphic_text_iarchive.hpp>
|
|
|
|
#include <boost/serialization/list.hpp>
|
|
#include <boost/serialization/access.hpp>
|
|
|
|
// 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<class Archive>
|
|
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<class Archive>
|
|
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<class Archive>
|
|
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<class Archive>
|
|
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<class Archive>
|
|
void save(Archive &ar, const unsigned int /*file_version*/) const {
|
|
ar << m_a1;
|
|
ar << m_a2;
|
|
ar << m_pa2;
|
|
}
|
|
template<class Archive>
|
|
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<class Archive>
|
|
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<class Archive>
|
|
void save(Archive& ar,const unsigned int)const
|
|
{
|
|
for(int i=0;i<2;++i){
|
|
ar<<f[i].x;
|
|
ar<<f[i];
|
|
}
|
|
for(int j=0;j<2;++j){
|
|
ar<<pf[j];
|
|
}
|
|
}
|
|
|
|
template<class Archive>
|
|
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<<const_cast<const bar&>(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<const B *> l;
|
|
l.push_back(b_ptr);
|
|
boost::archive::text_oarchive oa(ss);
|
|
oa << const_cast<const std::list<const B *> &>(l);
|
|
}
|
|
B b1;
|
|
{
|
|
std::list<B *> 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<const B *> l;
|
|
l.push_back(b_ptr);
|
|
boost::archive::polymorphic_text_oarchive oa(ss);
|
|
boost::archive::polymorphic_oarchive & poa = oa;
|
|
poa << const_cast<const std::list<const B *> &>(l);
|
|
}
|
|
B b1;
|
|
{
|
|
std::list<B *> 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;
|
|
}
|