Skip to content

Commit 0af15e4

Browse files
authored
Add tests for std::span adaptor
2 parents 18ec42c + 2b78d50 commit 0af15e4

File tree

8 files changed

+191
-12
lines changed

8 files changed

+191
-12
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ LIST (APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
2020
SET (GNUCXX_STD_SUPPORT_VERSION "4.3")
2121

2222
OPTION (MSGPACK_CXX11 "Using c++11 compiler" OFF)
23+
OPTION (MSGPACK_CXX17 "Using c++17 compiler" OFF)
24+
OPTION (MSGPACK_CXX20 "Using c++20 compiler (experimental)" OFF)
2325
OPTION (MSGPACK_32BIT "32bit compile" OFF)
2426

2527
IF (MSGPACK_USE_X3_PARSE)

include/msgpack/v1/adaptor/ext.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class ext {
3737
m_data.resize(static_cast<std::size_t>(s) + 1);
3838
m_data[0] = static_cast<char>(t);
3939
}
40-
ext(ext_ref const&);
40+
explicit ext(ext_ref const&);
4141
int8_t type() const {
4242
return static_cast<int8_t>(m_data[0]);
4343
}
@@ -167,6 +167,7 @@ class ext_ref {
167167
if (m_size < x.m_size) return false;
168168
return std::memcmp(m_ptr, x.m_ptr, m_size) > 0;
169169
}
170+
170171
private:
171172
const char* m_ptr;
172173
uint32_t m_size;

test/CMakeLists.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ IF (MSGPACK_USE_X3_PARSE)
4646
)
4747
ENDIF ()
4848

49-
IF (MSGPACK_CXX11 OR MSGPACK_CXX17)
49+
IF (MSGPACK_CXX11 OR MSGPACK_CXX17 OR MSGPACK_CXX20)
5050
LIST (APPEND check_PROGRAMS
5151
iterator_cpp11.cpp
5252
msgpack_cpp11.cpp
@@ -60,12 +60,18 @@ IF (MSGPACK_CXX11 OR MSGPACK_CXX17)
6060
)
6161
ENDIF ()
6262

63-
IF (MSGPACK_CXX17)
63+
IF (MSGPACK_CXX17 OR MSGPACK_CXX20)
6464
LIST (APPEND check_PROGRAMS
6565
msgpack_cpp17.cpp
6666
)
6767
ENDIF ()
6868

69+
IF (MSGPACK_CXX20)
70+
LIST (APPEND check_PROGRAMS
71+
msgpack_cpp20.cpp
72+
)
73+
ENDIF ()
74+
6975
FOREACH (source_file ${check_PROGRAMS})
7076
GET_FILENAME_COMPONENT (source_file_we ${source_file} NAME_WE)
7177
ADD_EXECUTABLE (

test/boost_variant.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ TEST(MSGPACK_BOOST, object_with_zone_variant_ext_ref)
488488
msgpack::type::variant val2 = obj.as<msgpack::type::variant>();
489489
// Converted as msgpack::type::ext.
490490
EXPECT_TRUE(val2.is_ext());
491-
EXPECT_EQ(val2.as_ext(), e);
491+
EXPECT_EQ(val2.as_ext(), msgpack::type::ext(e));
492492
EXPECT_NO_THROW(boost::get<msgpack::type::ext>(val2));
493493
// msgpack::type::ext_ref and msgpack::type::ext are different.
494494
EXPECT_FALSE(val1 == val2);

test/msgpack_cpp11.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,11 +262,19 @@ struct set_allocator : std::allocator<Key> {
262262
using std::allocator<Key>::allocator;
263263
};
264264

265-
template <class Key, class T>
266-
struct map_allocator : std::allocator<std::pair<const Key, T>> {
267-
using std::allocator<std::pair<const Key, T>>::allocator;
265+
// C++ named requirement Allocator implies that the first template type
266+
// parameter matches the value type of the allocator. There might be additional
267+
// parameters, but the first one must match the type.
268+
// That's why this helper with exactly one template parameter representing
269+
// a whole key-value pair is required
270+
template <typename KeyValuePair>
271+
struct map_allocator_impl : std::allocator<KeyValuePair> {
272+
using std::allocator<KeyValuePair>::allocator;
268273
};
269274

275+
template <class Key, class T>
276+
using map_allocator = map_allocator_impl<std::pair<const Key, T>>;
277+
270278
template <class T>
271279
struct allocator : std::allocator<T> {
272280
using std::allocator<T>::allocator;

test/msgpack_cpp20.cpp

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#include <msgpack.hpp>
2+
3+
#if defined(__GNUC__)
4+
#pragma GCC diagnostic push
5+
#pragma GCC diagnostic ignored "-Wconversion"
6+
#endif //defined(__GNUC__)
7+
8+
#include <gtest/gtest.h>
9+
10+
#if defined(__GNUC__)
11+
#pragma GCC diagnostic pop
12+
#endif //defined(__GNUC__)
13+
14+
#ifdef HAVE_CONFIG_H
15+
#include "config.h"
16+
#endif
17+
18+
// To avoid link error
19+
TEST(MSGPACK_CPP20, dummy)
20+
{
21+
}
22+
23+
#if !defined(MSGPACK_USE_CPP03) && __cplusplus > 201703
24+
25+
#if MSGPACK_HAS_INCLUDE(<span>)
26+
27+
template <typename Byte>
28+
bool operator==(const std::span<const Byte>& lhs, const std::span<const Byte>& rhs)
29+
{
30+
if (lhs.size() != rhs.size())
31+
return false;
32+
for (std::size_t i = 0; i < lhs.size(); ++i)
33+
if (lhs[i] != rhs[i])
34+
return false;
35+
return true;
36+
}
37+
38+
template <typename Byte>
39+
bool operator==(const std::span<const Byte>& lhs, const std::vector<Byte>& rhs)
40+
{
41+
return lhs == std::span<const Byte>{rhs.data(), rhs.size()};
42+
}
43+
44+
template <typename Byte>
45+
bool operator==(const std::vector<Byte>& lhs, const std::span<const Byte>& rhs)
46+
{
47+
return std::span<const Byte>{lhs.data(), lhs.size()} == rhs;
48+
}
49+
50+
#define MSGPACK_TEST_SPAN_BYTE_PACK_CONVERT(byte_t, display_name) \
51+
TEST(MSGPACK_CPP20, span_##display_name##_pack_convert) \
52+
{ \
53+
std::stringstream ss; \
54+
byte_t raw_data[] = { \
55+
(byte_t)(0x01), (byte_t)(0x02), (byte_t)(0x7f), (byte_t)(0x80), (byte_t)(0xff) \
56+
}; \
57+
std::span<const byte_t> val1{raw_data, sizeof(raw_data)}; \
58+
\
59+
msgpack::pack(ss, val1); \
60+
std::string const& str = ss.str(); \
61+
\
62+
char packed[] = { char(0xc4), char(0x05), char(0x01), char(0x02), char(0x7f), char(0x80), char(0xff) }; \
63+
EXPECT_EQ(str.size(), sizeof(packed)); \
64+
for (size_t i = 0; i != sizeof(packed); ++i) { \
65+
EXPECT_EQ(str[i], packed[i]); \
66+
} \
67+
\
68+
msgpack::object_handle oh; \
69+
msgpack::unpack(oh, str.data(), str.size()); \
70+
{ \
71+
auto val2 = oh.get().as<std::vector<byte_t>>(); \
72+
EXPECT_TRUE(val1 == val2); \
73+
} \
74+
{ \
75+
auto val2 = oh.get().as<std::span<const byte_t>>(); \
76+
EXPECT_TRUE(val1 == val2); \
77+
} \
78+
} \
79+
80+
#define MSGPACK_TEST_SPAN_BYTE_OBJECT(byte_t, display_name) \
81+
TEST(MSGPACK_CPP20, span_##display_name##_object) \
82+
{ \
83+
byte_t raw_data[] = { \
84+
(byte_t)(0x01), (byte_t)(0x02), (byte_t)(0x7f), (byte_t)(0x80), (byte_t)(0xff) \
85+
}; \
86+
std::span<const byte_t> val1{raw_data, sizeof(raw_data)}; \
87+
\
88+
/* Caller needs to manage val1's lifetime. The Data is not copied. */ \
89+
msgpack::object obj(val1); \
90+
\
91+
{ \
92+
auto val2 = obj.as<std::vector<byte_t>>(); \
93+
EXPECT_TRUE(val1 == val2); \
94+
} \
95+
{ \
96+
auto val2 = obj.as<std::span<const byte_t>>(); \
97+
EXPECT_TRUE(val1 == val2); \
98+
} \
99+
} \
100+
101+
#define MSGPACK_TEST_SPAN_BYTE_OBJECT_WITH_ZONE(byte_t, display_name) \
102+
TEST(MSGPACK_CPP20, span_##display_name##_object_with_zone) \
103+
{ \
104+
msgpack::zone z; \
105+
byte_t raw_data[] = { \
106+
(byte_t)(0x01), (byte_t)(0x02), (byte_t)(0x7f), (byte_t)(0x80), (byte_t)(0xff) \
107+
}; \
108+
std::span<const byte_t> val1(raw_data, sizeof(raw_data)); \
109+
\
110+
msgpack::object obj(val1, z); \
111+
\
112+
{ \
113+
auto val2 = obj.as<std::vector<byte_t>>(); \
114+
EXPECT_TRUE(val1 == val2); \
115+
} \
116+
{ \
117+
auto val2 = obj.as<std::span<const byte_t>>(); \
118+
EXPECT_TRUE(val1 == val2); \
119+
} \
120+
} \
121+
122+
#define MSGPACK_TEST_SPAN_BYTE(byte_t, display_name) \
123+
MSGPACK_TEST_SPAN_BYTE_PACK_CONVERT(byte_t, display_name) \
124+
MSGPACK_TEST_SPAN_BYTE_OBJECT(byte_t, display_name) \
125+
MSGPACK_TEST_SPAN_BYTE_OBJECT_WITH_ZONE(byte_t, display_name) \
126+
127+
MSGPACK_TEST_SPAN_BYTE(std::byte, byte)
128+
MSGPACK_TEST_SPAN_BYTE(char, char)
129+
MSGPACK_TEST_SPAN_BYTE(unsigned char, unsigned_char)
130+
131+
#undef MSGPACK_TEST_SPAN_BYTE
132+
#undef MSGPACK_TEST_SPAN_BYTE_OBJECT_WITH_ZONE
133+
#undef MSGPACK_TEST_SPAN_BYTE_OBJECT
134+
#undef MSGPACK_TEST_SPAN_BYTE_PACK_CONVERT
135+
136+
#endif // MSGPACK_HAS_INCLUDE(<span>)
137+
138+
#endif // !defined(MSGPACK_USE_CPP03) && __cplusplus > 201703

test/object_with_zone.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,7 @@ TEST(object_with_zone, ext_ref_empty)
11021102
msgpack::type::ext_ref v;
11031103
msgpack::zone z;
11041104
msgpack::object obj(v, z);
1105-
EXPECT_TRUE(obj.as<msgpack::type::ext>() == v);
1105+
EXPECT_TRUE(obj.as<msgpack::type::ext>() == msgpack::type::ext(v));
11061106
EXPECT_TRUE(obj.as<msgpack::type::ext_ref>() == v);
11071107
}
11081108

@@ -1112,6 +1112,6 @@ TEST(object_with_zone, ext_ref_from_buf)
11121112
msgpack::type::ext_ref v(buf, sizeof(buf));
11131113
msgpack::zone z;
11141114
msgpack::object obj(v, z);
1115-
EXPECT_TRUE(obj.as<msgpack::type::ext>() == v);
1115+
EXPECT_TRUE(obj.as<msgpack::type::ext>() == msgpack::type::ext(v));
11161116
EXPECT_TRUE(obj.as<msgpack::type::ext_ref>() == v);
11171117
}

test/test_allocator.hpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,20 @@ namespace test {
1818
template <typename T>
1919
struct allocator {
2020
typedef typename std::allocator<T>::value_type value_type;
21+
typedef typename std::allocator<T>::size_type size_type;
22+
typedef typename std::allocator<T>::difference_type difference_type;
23+
template <class U> struct rebind { typedef allocator<U> other; };
24+
#if __cplusplus <= 201703
2125
typedef typename std::allocator<T>::pointer pointer;
2226
typedef typename std::allocator<T>::reference reference;
2327
typedef typename std::allocator<T>::const_pointer const_pointer;
2428
typedef typename std::allocator<T>::const_reference const_reference;
25-
typedef typename std::allocator<T>::size_type size_type;
26-
typedef typename std::allocator<T>::difference_type difference_type;
27-
template <class U> struct rebind { typedef allocator<U> other; };
29+
#else // __cplusplus <= 201703
30+
typedef value_type* pointer;
31+
typedef value_type& reference;
32+
typedef const value_type* const_pointer;
33+
typedef const value_type& const_reference;
34+
#endif // __cplusplus <= 201703
2835
#if defined(MSGPACK_USE_CPP03)
2936
allocator() throw() {}
3037
allocator (const allocator& alloc) throw()
@@ -45,21 +52,38 @@ struct allocator {
4552
template <class U>
4653
allocator (const allocator<U>& alloc) noexcept
4754
:alloc_(alloc.alloc_) {}
55+
#if __cplusplus <= 201703
4856
template <class U, class... Args>
4957
void construct (U* p, Args&&... args) {
5058
return alloc_.construct(p, std::forward<Args>(args)...);
5159
}
5260
size_type max_size() const noexcept { return alloc_.max_size(); }
61+
#else // __cplusplus <= 201703
62+
template <class U, class... Args>
63+
void construct (U* p, Args&&... args) {
64+
return std::allocator_traits<decltype(alloc_)>::construct(alloc_, p, std::forward<Args>(args)...);
65+
}
66+
size_type max_size() const noexcept {
67+
return std::allocator_traits<decltype(alloc_)>::max_size(alloc_);
68+
}
69+
#endif // __cplusplus <= 201703
5370
#endif // defined(MSGPACK_USE_CPP03)
5471
pointer allocate (size_type n) {
5572
return alloc_.allocate(n);
5673
}
5774
void deallocate (pointer p, size_type n) {
5875
return alloc_.deallocate(p, n);
5976
}
77+
78+
#if __cplusplus <= 201703
6079
void destroy (pointer p) {
6180
alloc_.destroy(p);
6281
}
82+
#else // __cplusplus <= 201703
83+
void destroy (pointer p) {
84+
std::allocator_traits<decltype(alloc_)>::destroy(alloc_, p);
85+
}
86+
#endif // __cplusplus <= 201703
6387

6488
std::allocator<T> alloc_;
6589
};

0 commit comments

Comments
 (0)