serialization/test/test_cyclic_ptrs.cpp
Nikita Kniazev c5120dfd11 Fixed catch by value warnings in tests
warning: catching polymorphic type 'class boost::archive::archive_exception' by value [-Wcatch-value=]
2018-10-02 17:08:10 +03:00

205 lines
5.4 KiB
C++

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// test_cyclic_ptrs.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)
// should pass compilation and execution
#include <cstddef> // NULL
#include <fstream>
#include <cstdio> // remove
#include <boost/config.hpp>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
using ::remove;
}
#endif
#include "test_tools.hpp"
#include <boost/core/no_exceptions_support.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/version.hpp>
#include <boost/serialization/base_object.hpp>
#include "A.hpp"
#include "A.ipp"
///////////////////////////////////////////////////////
// class with a member which refers to itself
class J : public A
{
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int /* file_version */){
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(A);
ar & BOOST_SERIALIZATION_NVP(j);
}
public:
bool operator==(const J &rhs) const;
J *j;
J(J *_j) : j(_j) {}
J() : j(NULL){}
};
BOOST_CLASS_VERSION(J, 6)
bool J::operator==(const J &rhs) const
{
return static_cast<const A &>(*this) == static_cast<const A &>(rhs);
}
///////////////////////////////////////////////////////
// class with members that refer to each other
// this is an example of a class that, as written, cannot
// be serialized with this system. The problem is that the
// serialization of the first member - j1 , provokes serialization
// of those objects which it points to either directly or indirectly.
// When those objects are subsequently serialized, it is discovered
// that have already been serialized through pointers. This is
// detected by the system and an exception - pointer_conflict -
// is thrown. Permiting this to go undetected would result in the
// creation of multiple equal objects rather than the original
// structure.
class K
{
J j1;
J j2;
J j3;
friend class boost::serialization::access;
template<class Archive>
void serialize(
Archive &ar,
const unsigned int /* file_version */
){
ar & BOOST_SERIALIZATION_NVP(j1);
ar & BOOST_SERIALIZATION_NVP(j2);
ar & BOOST_SERIALIZATION_NVP(j3);
}
public:
bool operator==(const K &rhs) const;
K();
};
K::K()
: j1(&j2), j2(&j3), j3(&j1)
{
}
bool K::operator==(const K &rhs) const
{
return
j1.j == & j2
&& j2.j == & j3
&& j3.j == & j1
&& j1 == rhs.j1
&& j2 == rhs.j2
&& j3 == rhs.j3
;
}
int test1(){
const char * testfile = boost::archive::tmpnam(NULL);
BOOST_REQUIRE(NULL != testfile);
J j1, j2;
{
test_ostream os(testfile, TEST_STREAM_FLAGS);
test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
oa << BOOST_SERIALIZATION_NVP(j1);
}
{
// try to read the archive
test_istream is(testfile, TEST_STREAM_FLAGS);
test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
ia >> BOOST_SERIALIZATION_NVP(j2);
}
BOOST_CHECK(j1 == j2);
std::remove(testfile);
return EXIT_SUCCESS;
}
int test2(){
const char * testfile = boost::archive::tmpnam(NULL);
BOOST_REQUIRE(NULL != testfile);
J *j1 = new J;
j1->j = j1;
J *j2 = reinterpret_cast<J *>(0xBAADF00D);
{
test_ostream os(testfile, TEST_STREAM_FLAGS);
test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
oa << BOOST_SERIALIZATION_NVP(j1);
}
{
// try to read the archive
test_istream is(testfile, TEST_STREAM_FLAGS);
test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
ia >> BOOST_SERIALIZATION_NVP(j2);
}
BOOST_CHECK(*j1 == *j2);
delete j1;
BOOST_CHECK(j2 == j2->j);
std::remove(testfile);
return EXIT_SUCCESS;
}
int test3(){
const char * testfile = boost::archive::tmpnam(NULL);
BOOST_REQUIRE(NULL != testfile);
K k;
boost::archive::archive_exception exception(
boost::archive::archive_exception::no_exception
);
{
test_ostream os(testfile, TEST_STREAM_FLAGS);
test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
BOOST_TRY {
oa << BOOST_SERIALIZATION_NVP(k);
}
BOOST_CATCH (boost::archive::archive_exception const& ae){
exception = ae;
}
BOOST_CATCH_END
BOOST_CHECK(
exception.code == boost::archive::archive_exception::pointer_conflict
);
}
// if exception wasn't invoked
if(exception.code == boost::archive::archive_exception::no_exception){
// try to read the archive
test_istream is(testfile, TEST_STREAM_FLAGS);
test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
exception = boost::archive::archive_exception(
boost::archive::archive_exception::no_exception
);
BOOST_TRY {
ia >> BOOST_SERIALIZATION_NVP(k);
}
BOOST_CATCH (boost::archive::archive_exception const& ae){
exception = ae;
}
BOOST_CATCH_END
BOOST_CHECK(
exception.code == boost::archive::archive_exception::pointer_conflict
);
}
std::remove(testfile);
return EXIT_SUCCESS;
}
int test_main( int /* argc */, char* /* argv */[] ){
test1();
test2();
test3();
return EXIT_SUCCESS;
}
// EOF