]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/serialization/test/test_variant.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / serialization / test / test_variant.cpp
1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2 // test_variant.cpp
3 // test of non-intrusive serialization of variant types
4 //
5 // copyright (c) 2005
6 // troy d. straszheim <troy@resophonic.com>
7 // http://www.resophonic.com
8 //
9 // Use, modification and distribution is subject to the Boost Software
10 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
12 //
13 // See http://www.boost.org for updates, documentation, and revision history.
14 //
15 // thanks to Robert Ramey and Peter Dimov.
16 //
17
18 #include <cstddef> // NULL
19 #include <cstdio> // remove
20 #include <fstream>
21 #include <boost/config.hpp>
22 #include <boost/math/special_functions/next.hpp> // float_distance
23 #if defined(BOOST_NO_STDC_NAMESPACE)
24 namespace std{
25 using ::remove;
26 }
27 #endif
28
29 #include <boost/type_traits/is_same.hpp>
30 #include <boost/mpl/eval_if.hpp>
31 #include <boost/mpl/identity.hpp>
32 #include <boost/serialization/throw_exception.hpp>
33
34 #if defined(_MSC_VER) && (_MSC_VER <= 1020)
35 # pragma warning (disable : 4786) // too long name, harmless warning
36 #endif
37
38 #include "test_tools.hpp"
39
40 #include <boost/archive/archive_exception.hpp>
41
42 #include <boost/serialization/nvp.hpp>
43 #include <boost/serialization/variant.hpp>
44
45 #include "A.hpp"
46 #include "A.ipp"
47
48 class are_equal
49 : public boost::static_visitor<bool>
50 {
51 public:
52 // note extra rigamorole for compilers which don't support
53 // partial function template ordering - specfically msvc 6.x
54 struct same {
55 template<class T, class U>
56 static bool invoke(const T & t, const U & u){
57 return t == u;
58 }
59 };
60
61 struct not_same {
62 template<class T, class U>
63 static bool invoke(const T &, const U &){
64 return false;
65 }
66 };
67
68 template <class T, class U>
69 bool operator()( const T & t, const U & u) const
70 {
71 typedef typename boost::mpl::eval_if<boost::is_same<T, U>,
72 boost::mpl::identity<same>,
73 boost::mpl::identity<not_same>
74 >::type type;
75 return type::invoke(t, u);
76 }
77
78 bool operator()( const float & lhs, const float & rhs ) const
79 {
80 return std::abs( boost::math::float_distance(lhs, rhs)) < 2;
81 }
82 bool operator()( const double & lhs, const double & rhs ) const
83 {
84 return std::abs( boost::math::float_distance(lhs, rhs)) < 2;
85 }
86 };
87
88 template <class T>
89 void test_type(const T& gets_written){
90 const char * testfile = boost::archive::tmpnam(NULL);
91 BOOST_REQUIRE(testfile != NULL);
92 {
93 test_ostream os(testfile, TEST_STREAM_FLAGS);
94 test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
95 oa << boost::serialization::make_nvp("written", gets_written);
96 }
97
98 T got_read;
99 {
100 test_istream is(testfile, TEST_STREAM_FLAGS);
101 test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
102 ia >> boost::serialization::make_nvp("written", got_read);
103 }
104 BOOST_CHECK(boost::apply_visitor(are_equal(), gets_written, got_read));
105
106 std::remove(testfile);
107 }
108
109 // this verifies that if you try to read in a variant from a file
110 // whose "which" is illegal for the one in memory (that is, you're
111 // reading in to a different variant than you wrote out to) the load()
112 // operation will throw. One could concievably add checking for
113 // sequence length as well, but this would add size to the archive for
114 // dubious benefit.
115 //
116 void do_bad_read()
117 {
118 // Compiling this test invokes and ICE on msvc 6
119 // So, we'll just to skip it for this compiler
120 #if defined(_MSC_VER) && (_MSC_VER <= 1020)
121 boost::variant<bool, float, int, std::string> big_variant;
122 big_variant = std::string("adrenochrome");
123
124 const char * testfile = boost::archive::tmpnam(NULL);
125 BOOST_REQUIRE(testfile != NULL);
126 {
127 test_ostream os(testfile, TEST_STREAM_FLAGS);
128 test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
129 oa << BOOST_SERIALIZATION_NVP(big_variant);
130 }
131 boost::variant<bool, float, int> little_variant;
132 {
133 test_istream is(testfile, TEST_STREAM_FLAGS);
134 test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
135 bool exception_invoked = false;
136 BOOST_TRY {
137 ia >> BOOST_SERIALIZATION_NVP(little_variant);
138 } BOOST_CATCH (boost::archive::archive_exception const& e) {
139 BOOST_CHECK(boost::archive::archive_exception::unsupported_version == e.code);
140 exception_invoked = true;
141 }
142 BOOST_CATCH_END
143 BOOST_CHECK(exception_invoked);
144 }
145 #endif
146 }
147
148 struct H {
149 int i;
150 };
151
152 namespace boost {
153 namespace serialization {
154
155 template<class Archive>
156 void serialize(Archive &ar, H & h, const unsigned int /*file_version*/){
157 ar & boost::serialization::make_nvp("h", h.i);
158 }
159
160 } // namespace serialization
161 } // namespace boost
162
163 inline bool operator==(H const & lhs, H const & rhs) {
164 return lhs.i == rhs.i;
165 }
166
167 inline bool operator!=(H const & lhs, H const & rhs) {
168 return !(lhs == rhs);
169 }
170
171 inline bool operator<(H const & lhs, H const & rhs) {
172 return lhs.i < rhs.i;
173 }
174
175 inline std::size_t hash_value(H const & val) {
176 return val.i;
177 }
178
179 void test_pointer(){
180 const char * testfile = boost::archive::tmpnam(NULL);
181 BOOST_REQUIRE(testfile != NULL);
182 typedef boost::variant<H, int> variant_t;
183 H const h = {5};
184 variant_t v(h);
185 {
186 test_ostream os(testfile, TEST_STREAM_FLAGS);
187 test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
188 oa << boost::serialization::make_nvp("written", v);
189 const H * h_ptr = & boost::strict_get<H const &>(v);
190 oa << boost::serialization::make_nvp("written", h_ptr);
191 }
192 variant_t v2;
193 {
194 test_istream is(testfile, TEST_STREAM_FLAGS);
195 test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
196 ia >> boost::serialization::make_nvp("written", v2);
197 H * h2_ptr;
198 ia >> boost::serialization::make_nvp("written", h2_ptr);
199 BOOST_CHECK_EQUAL(h, boost::strict_get<H const>(v2));
200 BOOST_CHECK_EQUAL(h2_ptr, & boost::strict_get<H const &>(v2));
201 }
202 BOOST_CHECK_EQUAL(v, v2);
203 }
204
205 #include <boost/serialization/map.hpp>
206 #include <boost/serialization/set.hpp>
207
208 // test a pointer to an object contained into a variant that is an
209 // element of a set
210 void test_variant_set()
211 {
212 const char * testfile = boost::archive::tmpnam(NULL);
213 BOOST_REQUIRE(testfile != NULL);
214 typedef boost::variant<H, int> variant_t;
215 typedef std::set<variant_t> uset_t;
216 uset_t set;
217 {
218 test_ostream os(testfile, TEST_STREAM_FLAGS);
219 test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
220 H const h = {5};
221 variant_t v(h);
222 set.insert(v);
223 oa << boost::serialization::make_nvp("written", set);
224 H const * const h_ptr = boost::strict_get<H const>(&(*set.begin()));
225 oa << boost::serialization::make_nvp("written", h_ptr);
226 }
227 uset_t set2;
228 {
229 test_istream is(testfile, TEST_STREAM_FLAGS);
230 test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
231 ia >> boost::serialization::make_nvp("written", set2);
232 H * h_ptr;
233 ia >> boost::serialization::make_nvp("written", h_ptr);
234 const H * h_ptr2 = & boost::strict_get<H const>(*set2.begin());
235 BOOST_CHECK_EQUAL(h_ptr, h_ptr2);
236 }
237 BOOST_CHECK_EQUAL(set, set2);
238 }
239
240 // test a pointer to an object contained into a variant that is an
241 // element of a map
242 void test_variant_map()
243 {
244 const char * testfile = boost::archive::tmpnam(NULL);
245 BOOST_REQUIRE(testfile != NULL);
246 typedef boost::variant<H, int> variant_t;
247 typedef std::map<int, variant_t> map_t;
248 map_t map;
249 {
250 test_ostream os(testfile, TEST_STREAM_FLAGS);
251 test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
252 H const h = {5};
253 variant_t v(h);
254 map[0] = v;
255 BOOST_ASSERT(1 == map.size());
256 oa << boost::serialization::make_nvp("written", map);
257 H const * const h_ptr = boost::strict_get<H const>(&map[0]);
258 BOOST_CHECK_EQUAL(h_ptr, boost::strict_get<H const>(&map[0]));
259 oa << boost::serialization::make_nvp("written", h_ptr);
260 }
261 map_t map2;
262 {
263 test_istream is(testfile, TEST_STREAM_FLAGS);
264 test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
265 ia >> boost::serialization::make_nvp("written", map2);
266 BOOST_ASSERT(1 == map2.size());
267 H * h_ptr;
268 ia >> boost::serialization::make_nvp("written", h_ptr);
269 H const * const h_ptr2 = boost::strict_get<H const>(&map2[0]);
270 BOOST_CHECK_EQUAL(h_ptr, h_ptr2);
271 }
272 BOOST_CHECK_EQUAL(map, map2);
273 }
274
275 int test_main( int /* argc */, char* /* argv */[] )
276 {
277 {
278 boost::variant<bool, int, float, double, A, std::string> v;
279 v = false;
280 test_type(v);
281 v = 1;
282 test_type(v);
283 v = (float) 2.3;
284 test_type(v);
285 v = (double) 6.4;
286 test_type(v);
287 v = std::string("we can't stop here, this is Bat Country");
288 test_type(v);
289 v = A();
290 test_type(v);
291 }
292 test_pointer();
293 test_variant_set();
294 test_variant_map();
295 do_bad_read();
296 return EXIT_SUCCESS;
297 }
298
299 // EOF