From 1b87018a0aee2c0f3f85e9dce53e1ec4575fe36f Mon Sep 17 00:00:00 2001 From: Takatoshi Kondo Date: Mon, 20 Jun 2016 15:25:27 +0900 Subject: [PATCH] Fixed #390. Added size_equal_only class template to check converted container size strictly. Relaxed std::array size checking by default. Fixed std::tuple and msgpack::type::tuple size checking problem. --- Files.cmake | 5 + include/msgpack/adaptor/size_equal_only.hpp | 17 ++ .../msgpack/adaptor/size_equal_only_decl.hpp | 16 ++ include/msgpack/type.hpp | 1 + include/msgpack/v1/adaptor/cpp11/array.hpp | 4 +- .../msgpack/v1/adaptor/cpp11/array_char.hpp | 4 +- .../v1/adaptor/cpp11/array_unsigned_char.hpp | 4 +- include/msgpack/v1/adaptor/cpp11/tuple.hpp | 7 +- .../v1/adaptor/detail/cpp11_msgpack_tuple.hpp | 7 +- .../msgpack/v1/adaptor/size_equal_only.hpp | 123 ++++++++++ .../v1/adaptor/size_equal_only_decl.hpp | 55 +++++ .../v2/adaptor/size_equal_only_decl.hpp | 35 +++ test/CMakeLists.txt | 1 + test/msgpack_cpp11.cpp | 32 +++ test/size_equal_only.cpp | 217 ++++++++++++++++++ 15 files changed, 516 insertions(+), 12 deletions(-) create mode 100644 include/msgpack/adaptor/size_equal_only.hpp create mode 100644 include/msgpack/adaptor/size_equal_only_decl.hpp create mode 100644 include/msgpack/v1/adaptor/size_equal_only.hpp create mode 100644 include/msgpack/v1/adaptor/size_equal_only_decl.hpp create mode 100644 include/msgpack/v2/adaptor/size_equal_only_decl.hpp create mode 100644 test/size_equal_only.cpp diff --git a/Files.cmake b/Files.cmake index 3a30e1dd..635872c6 100644 --- a/Files.cmake +++ b/Files.cmake @@ -200,6 +200,8 @@ IF (MSGPACK_ENABLE_CXX) include/msgpack/adaptor/raw.hpp include/msgpack/adaptor/raw_decl.hpp include/msgpack/adaptor/set.hpp + include/msgpack/adaptor/size_equal_only.hpp + include/msgpack/adaptor/size_equal_only_decl.hpp include/msgpack/adaptor/string.hpp include/msgpack/adaptor/tr1/unordered_map.hpp include/msgpack/adaptor/tr1/unordered_set.hpp @@ -555,6 +557,8 @@ IF (MSGPACK_ENABLE_CXX) include/msgpack/v1/adaptor/raw.hpp include/msgpack/v1/adaptor/raw_decl.hpp include/msgpack/v1/adaptor/set.hpp + include/msgpack/v1/adaptor/size_equal_only.hpp + include/msgpack/v1/adaptor/size_equal_only_decl.hpp include/msgpack/v1/adaptor/string.hpp include/msgpack/v1/adaptor/tr1/unordered_map.hpp include/msgpack/v1/adaptor/tr1/unordered_set.hpp @@ -614,6 +618,7 @@ IF (MSGPACK_ENABLE_CXX) include/msgpack/v2/adaptor/msgpack_tuple_decl.hpp include/msgpack/v2/adaptor/nil_decl.hpp include/msgpack/v2/adaptor/raw_decl.hpp + include/msgpack/v2/adaptor/size_equal_only_decl.hpp include/msgpack/v2/adaptor/v4raw_decl.hpp include/msgpack/v2/cpp_config_decl.hpp include/msgpack/v2/detail/cpp03_zone_decl.hpp diff --git a/include/msgpack/adaptor/size_equal_only.hpp b/include/msgpack/adaptor/size_equal_only.hpp new file mode 100644 index 00000000..de9d2473 --- /dev/null +++ b/include/msgpack/adaptor/size_equal_only.hpp @@ -0,0 +1,17 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2016 KONDO Takatoshi +// +// Distributed under 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) +// +#ifndef MSGPACK_TYPE_SIZE_EQUAL_ONLY_HPP +#define MSGPACK_TYPE_SIZE_EQUAL_ONLY_HPP + +#include "msgpack/adaptor/size_equal_only_decl.hpp" + +#include "msgpack/v1/adaptor/size_equal_only.hpp" + +#endif // MSGPACK_TYPE_SIZE_EQUAL_ONLYL_HPP diff --git a/include/msgpack/adaptor/size_equal_only_decl.hpp b/include/msgpack/adaptor/size_equal_only_decl.hpp new file mode 100644 index 00000000..3735d16d --- /dev/null +++ b/include/msgpack/adaptor/size_equal_only_decl.hpp @@ -0,0 +1,16 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2016 KONDO Takatoshi +// +// Distributed under 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) +// +#ifndef MSGPACK_TYPE_SIZE_EQUAL_ONLY_DECL_HPP +#define MSGPACK_TYPE_SIZE_EQUAL_ONLY_DECL_HPP + +#include "msgpack/v1/adaptor/size_equal_only_decl.hpp" +#include "msgpack/v2/adaptor/size_equal_only_decl.hpp" + +#endif // MSGPACK_TYPE_SIZE_EQUAL_ONLY_DECL_HPP diff --git a/include/msgpack/type.hpp b/include/msgpack/type.hpp index e5084a6f..bca42266 100644 --- a/include/msgpack/type.hpp +++ b/include/msgpack/type.hpp @@ -15,6 +15,7 @@ #include "adaptor/raw.hpp" #include "adaptor/v4raw.hpp" #include "adaptor/set.hpp" +#include "adaptor/size_equal_only.hpp" #include "adaptor/string.hpp" #include "adaptor/vector.hpp" #include "adaptor/vector_bool.hpp" diff --git a/include/msgpack/v1/adaptor/cpp11/array.hpp b/include/msgpack/v1/adaptor/cpp11/array.hpp index 387401b9..1c01e3e0 100644 --- a/include/msgpack/v1/adaptor/cpp11/array.hpp +++ b/include/msgpack/v1/adaptor/cpp11/array.hpp @@ -75,7 +75,7 @@ template struct as, typename std::enable_if::value>::type> { std::array operator()(msgpack::object const& o) const { if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } - if(o.via.array.size != N) { throw msgpack::type_error(); } + if(o.via.array.size > N) { throw msgpack::type_error(); } return detail::array::as_impl::as(o); } }; @@ -84,7 +84,7 @@ template struct convert> { msgpack::object const& operator()(msgpack::object const& o, std::array& v) const { if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } - if(o.via.array.size != N) { throw msgpack::type_error(); } + if(o.via.array.size > N) { throw msgpack::type_error(); } if(o.via.array.size > 0) { msgpack::object* p = o.via.array.ptr; msgpack::object* const pend = o.via.array.ptr + o.via.array.size; diff --git a/include/msgpack/v1/adaptor/cpp11/array_char.hpp b/include/msgpack/v1/adaptor/cpp11/array_char.hpp index b47f7998..5472282f 100644 --- a/include/msgpack/v1/adaptor/cpp11/array_char.hpp +++ b/include/msgpack/v1/adaptor/cpp11/array_char.hpp @@ -30,11 +30,11 @@ struct convert> { msgpack::object const& operator()(msgpack::object const& o, std::array& v) const { switch (o.type) { case msgpack::type::BIN: - if(o.via.bin.size != N) { throw msgpack::type_error(); } + if(o.via.bin.size > N) { throw msgpack::type_error(); } std::memcpy(v.data(), o.via.bin.ptr, o.via.bin.size); break; case msgpack::type::STR: - if(o.via.str.size != N) { throw msgpack::type_error(); } + if(o.via.str.size > N) { throw msgpack::type_error(); } std::memcpy(v.data(), o.via.str.ptr, N); break; default: diff --git a/include/msgpack/v1/adaptor/cpp11/array_unsigned_char.hpp b/include/msgpack/v1/adaptor/cpp11/array_unsigned_char.hpp index 627a8c7f..815ee629 100644 --- a/include/msgpack/v1/adaptor/cpp11/array_unsigned_char.hpp +++ b/include/msgpack/v1/adaptor/cpp11/array_unsigned_char.hpp @@ -30,11 +30,11 @@ struct convert> { msgpack::object const& operator()(msgpack::object const& o, std::array& v) const { switch (o.type) { case msgpack::type::BIN: - if(o.via.bin.size != N) { throw msgpack::type_error(); } + if(o.via.bin.size > N) { throw msgpack::type_error(); } std::memcpy(v.data(), o.via.bin.ptr, o.via.bin.size); break; case msgpack::type::STR: - if(o.via.str.size != N) { throw msgpack::type_error(); } + if(o.via.str.size > N) { throw msgpack::type_error(); } std::memcpy(v.data(), o.via.str.ptr, N); break; default: diff --git a/include/msgpack/v1/adaptor/cpp11/tuple.hpp b/include/msgpack/v1/adaptor/cpp11/tuple.hpp index 6d2cfdf1..d274404f 100644 --- a/include/msgpack/v1/adaptor/cpp11/tuple.hpp +++ b/include/msgpack/v1/adaptor/cpp11/tuple.hpp @@ -93,7 +93,8 @@ struct StdTupleConverter { msgpack::object const& o, Tuple& v) { StdTupleConverter::convert(o, v); - o.via.array.ptr[N-1].convert(v))>::type>(std::get(v)); + if (o.via.array.size >= N) + o.via.array.ptr[N-1].convert(v))>::type>(std::get(v)); } }; @@ -112,7 +113,7 @@ struct as, typename std::enable_if operator()( msgpack::object const& o) const { if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } - if (o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); } + if(o.via.array.size > sizeof...(Args)) { throw msgpack::type_error(); } return StdTupleAs::as(o); } }; @@ -123,7 +124,7 @@ struct convert> { msgpack::object const& o, std::tuple& v) const { if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } - if(o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); } + if(o.via.array.size > sizeof...(Args)) { throw msgpack::type_error(); } StdTupleConverter::convert(o, v); return o; } diff --git a/include/msgpack/v1/adaptor/detail/cpp11_msgpack_tuple.hpp b/include/msgpack/v1/adaptor/detail/cpp11_msgpack_tuple.hpp index ca3f9dd6..91780366 100644 --- a/include/msgpack/v1/adaptor/detail/cpp11_msgpack_tuple.hpp +++ b/include/msgpack/v1/adaptor/detail/cpp11_msgpack_tuple.hpp @@ -121,7 +121,8 @@ struct MsgpackTupleConverter { msgpack::object const& o, Tuple& v) { MsgpackTupleConverter::convert(o, v); - o.via.array.ptr[N-1].convert(v))>::type>(type::get(v)); + if (o.via.array.size >= N) + o.via.array.ptr[N-1].convert(v))>::type>(type::get(v)); } }; @@ -149,7 +150,7 @@ struct as, typename std::enable_if operator()( msgpack::object const& o) const { if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } - if (o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); } + if (o.via.array.size > sizeof...(Args)) { throw msgpack::type_error(); } return MsgpackTupleAs::as(o); } }; @@ -160,7 +161,7 @@ struct convert> { msgpack::object const& o, msgpack::type::tuple& v) const { if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } - if(o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); } + if(o.via.array.size > sizeof...(Args)) { throw msgpack::type_error(); } MsgpackTupleConverter::convert(o, v); return o; } diff --git a/include/msgpack/v1/adaptor/size_equal_only.hpp b/include/msgpack/v1/adaptor/size_equal_only.hpp new file mode 100644 index 00000000..768939be --- /dev/null +++ b/include/msgpack/v1/adaptor/size_equal_only.hpp @@ -0,0 +1,123 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2016 KONDO Takatoshi +// +// Distributed under 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) +// +#ifndef MSGPACK_V1_TYPE_SIZE_EQUAL_ONLY_HPP +#define MSGPACK_V1_TYPE_SIZE_EQUAL_ONLY_HPP + +#include "msgpack/v1/adaptor/size_equal_only_decl.hpp" + +namespace msgpack { + +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v1) { +/// @endcond + +namespace type { + +template +inline std::size_t size(T const& t) { + return t.size(); +} + +template +inline std::size_t size(const T(&)[N]) { + return N; +} + + +#if !defined(MSGPACK_USE_CPP03) + +template +inline std::size_t size(std::tuple const&) { + return sizeof...(T); +} + +template +inline std::size_t size(msgpack::type::tuple const&) { + return sizeof...(T); +} + +#endif // !defined(MSGPACK_USE_CPP03) + + +template +struct size_equal_only { + size_equal_only(T& t):m_t(t) {} + T& m_t; +}; + +template +inline size_equal_only make_size_equal_only(T& t) { + return size_equal_only(t); +} + +template +inline bool operator<(size_equal_only const& lhs, size_equal_only const& rhs) { + return lhs.m_t < rhs.m_t; +} + +template +inline bool operator==(size_equal_only const& lhs, size_equal_only const& rhs) { + return lhs.m_t == &rhs.m_t; +} + +} // namespace type + +namespace adaptor { + +template +struct convert > { + msgpack::object const& operator()(msgpack::object const& o, type::size_equal_only& v) const { + switch(o.type) { + case msgpack::type::ARRAY: + if (o.via.array.size != msgpack::type::size(v.m_t)) throw msgpack::type_error(); + break; + case msgpack::type::MAP: + if (o.via.map.size != msgpack::type::size(v.m_t)) throw msgpack::type_error(); + break; + default: + throw msgpack::type_error(); + } + o >> v.m_t; + return o; + } +}; + +template +struct pack > { + template + msgpack::packer& operator()(msgpack::packer& o, const type::size_equal_only& v) const { + o << v.m_t; + return o; + } +}; + +template +struct object > { + void operator()(msgpack::object& o, type::size_equal_only const& v) const { + o << v.m_t; + } +}; + +template +struct object_with_zone > { + void operator()(msgpack::object::with_zone& o, type::size_equal_only v) const { + o << v.m_t; + } +}; + +} // namespace adaptor + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v1) +/// @endcond + +} // namespace msgpack + +#endif // MSGPACK_V1_TYPE_SIZE_EQUAL_ONLY_HPP diff --git a/include/msgpack/v1/adaptor/size_equal_only_decl.hpp b/include/msgpack/v1/adaptor/size_equal_only_decl.hpp new file mode 100644 index 00000000..8f6e6b5d --- /dev/null +++ b/include/msgpack/v1/adaptor/size_equal_only_decl.hpp @@ -0,0 +1,55 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2016 KONDO Takatoshi +// +// Distributed under 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) +// +#ifndef MSGPACK_V1_TYPE_SIZE_EQUAL_ONLY_DECL_HPP +#define MSGPACK_V1_TYPE_SIZE_EQUAL_ONLY_DECL_HPP + +#include "msgpack/versioning.hpp" +#include "msgpack/adaptor/adaptor_base.hpp" +#include "msgpack/adaptor/msgpack_tuple.hpp" + +namespace msgpack { + +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v1) { +/// @endcond + +namespace type { + +template +struct size_equal_only; + +template +size_equal_only make_size_equal_only(T& t); + +template +std::size_t size(T const& t); + +template +std::size_t size(const T(&)[N]); + +#if !defined(MSGPACK_USE_CPP03) + +template +std::size_t size(std::tuple const&); + +template +std::size_t size(msgpack::type::tuple const&); + +#endif // !defined(MSGPACK_USE_CPP03) + +} // namespace type + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v1) +/// @endcond + +} // namespace msgpack + +#endif // MSGPACK_V1_TYPE_SIZE_EQUAL_ONLY_DECL_HPP diff --git a/include/msgpack/v2/adaptor/size_equal_only_decl.hpp b/include/msgpack/v2/adaptor/size_equal_only_decl.hpp new file mode 100644 index 00000000..a6f21fa1 --- /dev/null +++ b/include/msgpack/v2/adaptor/size_equal_only_decl.hpp @@ -0,0 +1,35 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2016 KONDO Takatoshi +// +// Distributed under 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) +// +#ifndef MSGPACK_V2_TYPE_SIZE_EQUAL_ONLY_DECL_HPP +#define MSGPACK_V2_TYPE_SIZE_EQUAL_ONLY_DECL_HPP + +#include "msgpack/v1/adaptor/size_equal_only_decl.hpp" + +namespace msgpack { + +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v2) { +/// @endcond + +namespace type { + +using v1::type::size_equal_only; +using v1::type::make_size_equal_only; +using v1::type::size; + +} // namespace type + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v2) +/// @endcond + +} // namespace msgpack + +#endif // MSGPACK_V2_TYPE_SIZE_EQUAL_ONLY_DECL_HPP diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ebb5c11c..c0d4592b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -30,6 +30,7 @@ LIST (APPEND check_PROGRAMS pack_unpack_c.cpp raw.cpp reference.cpp + size_equal_only.cpp streaming.cpp streaming_c.cpp user_class.cpp diff --git a/test/msgpack_cpp11.cpp b/test/msgpack_cpp11.cpp index 9a6d5b1b..155a8e94 100644 --- a/test/msgpack_cpp11.cpp +++ b/test/msgpack_cpp11.cpp @@ -89,6 +89,38 @@ TEST(MSGPACK_CPP11, simple_array_empty) EXPECT_TRUE(equal(val1.begin(), val1.end(), val2.begin())); } +TEST(MSGPACK_CPP11, simple_array_size_less_than) +{ + array val1 { 1 , 2 }; + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, val1); + msgpack::object_handle oh = + msgpack::unpack(sbuf.data(), sbuf.size()); + EXPECT_EQ(oh.get().type, msgpack::type::ARRAY); + array val2; + try { + oh.get().convert(val2); + EXPECT_TRUE(false); + } + catch (msgpack::type_error const&) { + EXPECT_TRUE(true); + } +} + +TEST(MSGPACK_CPP11, simple_array_size_greater_than) +{ + array val1 { 1 , 2 }; + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, val1); + msgpack::object_handle oh = + msgpack::unpack(sbuf.data(), sbuf.size()); + EXPECT_EQ(oh.get().type, msgpack::type::ARRAY); + array val2; + oh.get().convert(val2); + EXPECT_EQ(val1[0], val2[0]); + EXPECT_EQ(val1[1], val2[1]); +} + TEST(MSGPACK_CPP11, simple_buffer_array_char) { for (unsigned int k = 0; k < kLoop; k++) { diff --git a/test/size_equal_only.cpp b/test/size_equal_only.cpp new file mode 100644 index 00000000..4bab736c --- /dev/null +++ b/test/size_equal_only.cpp @@ -0,0 +1,217 @@ +#include +#include +#include + +TEST(size_equal_only, array) +{ + std::stringstream ss; + int buf[3] = { 1, 2, 3 }; + msgpack::type::size_equal_only seo(buf); + + msgpack::pack(ss, seo); + msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size()); + + int ret_buf1[3]; + oh.get().convert(ret_buf1); + EXPECT_EQ(buf[0], ret_buf1[0]); + EXPECT_EQ(buf[1], ret_buf1[1]); + EXPECT_EQ(buf[2], ret_buf1[2]); + + int ret_buf2[4]; + oh.get().convert(ret_buf2); + EXPECT_EQ(buf[0], ret_buf2[0]); + EXPECT_EQ(buf[1], ret_buf2[1]); + EXPECT_EQ(buf[2], ret_buf2[2]); + + int ret_buf3[3]; + msgpack::type::size_equal_only ret_seo3(ret_buf3); + oh.get().convert(ret_seo3); + EXPECT_EQ(buf[0], ret_buf3[0]); + EXPECT_EQ(buf[1], ret_buf3[1]); + EXPECT_EQ(buf[2], ret_buf3[2]); + + int ret_buf4[4]; + msgpack::type::size_equal_only ret_seo4(ret_buf4); + try { + oh.get().convert(ret_seo4); + EXPECT_TRUE(false); + } + catch (msgpack::type_error const&) { + EXPECT_TRUE(true); + } +} + +TEST(size_equal_only, vector) +{ + std::stringstream ss; + std::vector buf; + buf.push_back(1); + buf.push_back(2); + buf.push_back(3); + + msgpack::type::size_equal_only > seo(buf); + + msgpack::pack(ss, seo); + msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size()); + + std::vector ret_buf1; + oh.get().convert(ret_buf1); + EXPECT_EQ(buf, ret_buf1); + + + std::vector ret_buf2; + ret_buf2.resize(3); + msgpack::type::size_equal_only > ret_seo2(ret_buf2); + oh.get().convert(ret_seo2); + EXPECT_EQ(buf, ret_buf2); + + std::vector ret_buf3; + ret_buf2.resize(4); + msgpack::type::size_equal_only > ret_seo3(ret_buf3); + try { + oh.get().convert(ret_seo3); + EXPECT_TRUE(false); + } + catch (msgpack::type_error const&) { + EXPECT_TRUE(true); + } +} + +#if !defined(MSGPACK_USE_CPP03) + +TEST(size_equal_only, tuple) +{ + std::stringstream ss; + std::tuple buf(1, false, "ABC"); + + auto seo = msgpack::type::make_size_equal_only(buf); + + msgpack::pack(ss, seo); + msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size()); + + std::tuple ret_buf1; + oh.get().convert(ret_buf1); + EXPECT_EQ(buf, ret_buf1); + + std::tuple ret_buf2; + auto ret_seo2 = msgpack::type::make_size_equal_only(ret_buf2); + oh.get().convert(ret_seo2); + EXPECT_EQ(buf, ret_buf2); + + std::tuple ret_buf3; + oh.get().convert(ret_buf3); + EXPECT_EQ(std::get<0>(buf), std::get<0>(ret_buf3)); + EXPECT_EQ(std::get<1>(buf), std::get<1>(ret_buf3)); + EXPECT_EQ(std::get<2>(buf), std::get<2>(ret_buf3)); + + std::tuple ret_buf4; + auto ret_seo4 = msgpack::type::make_size_equal_only(ret_buf4); + try { + oh.get().convert(ret_seo4); + EXPECT_TRUE(false); + } + catch (msgpack::type_error const&) { + EXPECT_TRUE(true); + } + + std::tuple ret_buf5; + oh.get().convert(ret_buf5); + EXPECT_EQ(std::get<0>(buf), std::get<0>(ret_buf5)); + EXPECT_EQ(std::get<1>(buf), std::get<1>(ret_buf5)); + + std::tuple ret_buf6; + auto ret_seo6 = msgpack::type::make_size_equal_only(ret_buf6); + try { + oh.get().convert(ret_seo6); + EXPECT_TRUE(false); + } + catch (msgpack::type_error const&) { + EXPECT_TRUE(true); + } +} + +TEST(size_equal_only, msgpack_tuple) +{ + std::stringstream ss; + msgpack::type::tuple buf(1, false, "ABC"); + + auto seo = msgpack::type::make_size_equal_only(buf); + + msgpack::pack(ss, seo); + msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size()); + + msgpack::type::tuple ret_buf1; + oh.get().convert(ret_buf1); + EXPECT_EQ(buf, ret_buf1); + + msgpack::type::tuple ret_buf2; + auto ret_seo2 = msgpack::type::make_size_equal_only(ret_buf2); + oh.get().convert(ret_seo2); + EXPECT_EQ(buf, ret_buf2); + + msgpack::type::tuple ret_buf3; + oh.get().convert(ret_buf3); + EXPECT_EQ(std::get<0>(buf), std::get<0>(ret_buf3)); + EXPECT_EQ(std::get<1>(buf), std::get<1>(ret_buf3)); + EXPECT_EQ(std::get<2>(buf), std::get<2>(ret_buf3)); + + msgpack::type::tuple ret_buf4; + auto ret_seo4 = msgpack::type::make_size_equal_only(ret_buf4); + try { + oh.get().convert(ret_seo4); + EXPECT_TRUE(false); + } + catch (msgpack::type_error const&) { + EXPECT_TRUE(true); + } + + msgpack::type::tuple ret_buf5; + oh.get().convert(ret_buf5); + EXPECT_EQ(std::get<0>(buf), std::get<0>(ret_buf5)); + EXPECT_EQ(std::get<1>(buf), std::get<1>(ret_buf5)); + + msgpack::type::tuple ret_buf6; + auto ret_seo6 = msgpack::type::make_size_equal_only(ret_buf6); + try { + oh.get().convert(ret_seo6); + EXPECT_TRUE(false); + } + catch (msgpack::type_error const&) { + EXPECT_TRUE(true); + } +} + +struct foo1 { + foo1() = default; + foo1(int i, bool b):t(i, b), seo(t) {} + std::tuple t; + msgpack::type::size_equal_only > seo; + MSGPACK_DEFINE(seo); +}; + +struct foo2 { + foo2() = default; + foo2(int i, bool b, std::string const& s):t(i, b, s), seo(t) {} + std::tuple t; + msgpack::type::size_equal_only > seo; + MSGPACK_DEFINE(seo); +}; + +TEST(size_equal_only, custom_class) +{ + std::stringstream ss; + foo1 f1(42, true); + msgpack::pack(ss, f1); + msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size()); + + foo2 f2(123, false, "ABC"); + try { + oh.get().convert(f2); + EXPECT_TRUE(false); + } + catch (msgpack::type_error const&) { + EXPECT_TRUE(true); + } +} + +#endif // !defined(MSGPACK_USE_CPP03)