1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// test_variant.cpp
// test of non-intrusive serialization of variant types
//
// copyright (c) 2005
// troy d. straszheim <troy@resophonic.com>
// http://www.resophonic.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)
//
// See http://www.boost.org for updates, documentation, and revision history.
//
// thanks to Robert Ramey and Peter Dimov.
//
#include <fstream>
#include <cstdio> // remove
#include <cmath> // for fabs()
#include <boost/config.hpp>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
using ::remove;
}
#endif
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/throw_exception.hpp>
#if defined(_MSC_VER) && (_MSC_VER <= 1020)
# pragma warning (disable : 4786) // too long name, harmless warning
#endif
#include "test_tools.hpp"
#include <boost/preprocessor/stringize.hpp>
#include BOOST_PP_STRINGIZE(BOOST_ARCHIVE_TEST)
#include <boost/archive/archive_exception.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/variant.hpp>
#include "A.hpp"
class are_equal
: public boost::static_visitor<bool>
{
public:
// note extra rigamorole for compilers which don't support
// partial function template ordering - specfically msvc 6.x
struct same {
template<class T, class U>
static bool invoke(const T & t, const U & u){
return t == u;
}
};
struct not_same {
template<class T, class U>
static bool invoke(const T &, const U &){
return false;
}
};
template <class T, class U>
bool operator()( const T & t, const U & u) const
{
typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if<boost::is_same<T, U>,
boost::mpl::identity<same>,
boost::mpl::identity<not_same>
>::type type;
return type::invoke(t, u);
}
bool operator()( const float & lhs, const float & rhs ) const
{
return std::fabs(lhs- rhs) < std::numeric_limits<float>::round_error();
}
bool operator()( const double & lhs, const double & rhs ) const
{
return std::fabs(lhs - rhs) < std::numeric_limits<float>::round_error();
}
};
template <class T>
void test_type(const T& gets_written){
const char * testfile = boost::archive::tmpnam(NULL);
BOOST_REQUIRE(testfile != NULL);
{
test_ostream os(testfile, TEST_STREAM_FLAGS);
test_oarchive oa(os);
oa << boost::serialization::make_nvp("written", gets_written);
}
T got_read;
{
test_istream is(testfile, TEST_STREAM_FLAGS);
test_iarchive ia(is);
ia >> boost::serialization::make_nvp("written", got_read);
}
BOOST_CHECK(boost::apply_visitor(are_equal(), gets_written, got_read));
std::remove(testfile);
}
// this verifies that if you try to read in a variant from a file
// whose "which" is illegal for the one in memory (that is, you're
// reading in to a different variant than you wrote out to) the load()
// operation will throw. One could concievably add checking for
// sequence length as well, but this would add size to the archive for
// dubious benefit.
//
void do_bad_read()
{
// Compiling this test invokes and ICE on msvc 6
// So, we'll just to skip it for this compiler
#if defined(_MSC_VER) && (_MSC_VER <= 1020)
boost::variant<bool, float, int, std::string> big_variant;
big_variant = std::string("adrenochrome");
const char * testfile = boost::archive::tmpnam(NULL);
BOOST_REQUIRE(testfile != NULL);
{
test_ostream os(testfile, TEST_STREAM_FLAGS);
test_oarchive oa(os);
oa << BOOST_SERIALIZATION_NVP(big_variant);
}
boost::variant<bool, float, int> little_variant;
{
test_istream is(testfile, TEST_STREAM_FLAGS);
test_iarchive ia(is);
bool exception_invoked = false;
BOOST_TRY {
ia >> BOOST_SERIALIZATION_NVP(little_variant);
} BOOST_CATCH (boost::archive::archive_exception e) {
BOOST_CHECK(boost::archive::archive_exception::unsupported_version == e.code);
exception_invoked = true;
}
BOOST_CATCH_END
BOOST_CHECK(exception_invoked);
}
#endif
}
int test_main( int /* argc */, char* /* argv */[] )
{
{
boost::variant<bool, int, float, double, A, std::string> v;
v = false;
test_type(v);
v = 1;
test_type(v);
v = (float) 2.3;
test_type(v);
v = (double) 6.4;
test_type(v);
v = std::string("we can't stop here, this is Bat Country");
test_type(v);
v = A();
test_type(v);
}
do_bad_read();
return EXIT_SUCCESS;
}
// EOF
|