1#include <msgpack.hpp>
2#include <gtest/gtest.h>
3
4
5enum enum_test {
6    elem
7};
8
9MSGPACK_ADD_ENUM(enum_test);
10
11struct outer_enum {
12    enum enum_test {
13        elem
14    };
15};
16
17MSGPACK_ADD_ENUM(outer_enum::enum_test);
18
19#if !defined(MSGPACK_USE_CPP03)
20
21enum class enum_class_test {
22    elem
23};
24
25MSGPACK_ADD_ENUM(enum_class_test);
26
27struct outer_enum_class {
28    enum class enum_class_test {
29        elem
30    };
31};
32
33MSGPACK_ADD_ENUM(outer_enum_class::enum_class_test);
34
35#endif // !defined(MSGPACK_USE_CPP03)
36
37struct myclass {
38    myclass() : num(0), str("default") { }
39
40    myclass(int num, const std::string& str) :
41        num(num), str(str) { }
42
43    ~myclass() { }
44
45    int num;
46    std::string str;
47    std::vector<double> vec;
48    std::map<std::string, std::vector<char> > map;
49
50    MSGPACK_DEFINE(num, str, vec, map);
51
52    bool operator==(const myclass& o) const
53    {
54        return num == o.num && str == o.str && vec == o.vec && map == o.map;
55    }
56};
57
58std::ostream& operator<<(std::ostream& o, const myclass& m)
59{
60    return o << "myclass("<<m.num<<",\""<<m.str<<"\")";
61}
62
63
64TEST(object, convert)
65{
66    myclass m1(1, "custom");
67
68    msgpack::sbuffer sbuf;
69    msgpack::pack(sbuf, m1);
70
71    msgpack::unpacked ret;
72    msgpack::unpack(ret, sbuf.data(), sbuf.size());
73
74    myclass m2;
75    ret.get().convert(m2);
76
77    EXPECT_EQ(m1, m2);
78}
79
80
81TEST(object, as)
82{
83    myclass m1(1, "custom");
84
85    msgpack::sbuffer sbuf;
86    msgpack::pack(sbuf, m1);
87
88    msgpack::unpacked ret;
89    msgpack::unpack(ret, sbuf.data(), sbuf.size());
90
91    EXPECT_EQ(m1, ret.get().as<myclass>());
92}
93
94TEST(object, cross_zone_copy)
95{
96    myclass m1(1, "custom");
97    m1.vec.push_back(1.0);
98    m1.vec.push_back(0.1);
99    std::vector<char> vc;
100    vc.push_back('t');
101    vc.push_back('w');
102    vc.push_back('o');
103    m1.map["one"] = vc;
104
105    msgpack::zone z1;
106    msgpack::object::with_zone obj1(z1);
107
108    {
109        msgpack::zone z2;
110        msgpack::object::with_zone obj2(z2);
111        obj2 << m1;
112
113        obj1 << obj2;
114
115        EXPECT_EQ(obj1.via.array.ptr[2].via.array.ptr[0].via.f64, 1.0);
116#if defined(MSGPACK_USE_LEGACY_NAME_AS_FLOAT)
117        EXPECT_EQ(obj1.via.array.ptr[2].via.array.ptr[0].via.dec, 1.0);
118#endif // MSGPACK_USE_LEGACY_NAME_AS_FLOAT
119        EXPECT_EQ(obj1.via.array.ptr[3].via.map.ptr[0].key.via.str.ptr[0], 'o');
120        EXPECT_EQ(obj1.via.array.ptr[3].via.map.ptr[0].val.via.bin.ptr[0], 't');
121        EXPECT_NE(
122            obj1.via.array.ptr[2].via.array.ptr,
123            obj2.via.array.ptr[2].via.array.ptr);
124        EXPECT_NE(
125            obj1.via.array.ptr[3].via.map.ptr,
126            obj2.via.array.ptr[3].via.map.ptr);
127        EXPECT_NE(
128            obj1.via.array.ptr[3].via.map.ptr[0].key.via.str.ptr,
129            obj2.via.array.ptr[3].via.map.ptr[0].key.via.str.ptr);
130        EXPECT_NE(
131            obj1.via.array.ptr[3].via.map.ptr[0].val.via.bin.ptr,
132            obj2.via.array.ptr[3].via.map.ptr[0].val.via.bin.ptr);
133    }
134
135    EXPECT_EQ(m1, obj1.as<myclass>());
136}
137
138TEST(object, cross_zone_copy_construct)
139{
140    myclass m1(1, "custom");
141    m1.vec.push_back(1.0);
142    m1.vec.push_back(0.1);
143    std::vector<char> vc;
144    vc.push_back('t');
145    vc.push_back('w');
146    vc.push_back('o');
147    m1.map["one"] = vc;
148
149    msgpack::zone z1;
150    msgpack::zone z2;
151    msgpack::object::with_zone obj2(z2);
152    obj2 << m1;
153
154    msgpack::object obj1(obj2, z1);
155
156    EXPECT_EQ(obj1.via.array.ptr[2].via.array.ptr[0].via.f64, 1.0);
157#if defined(MSGPACK_USE_LEGACY_NAME_AS_FLOAT)
158    EXPECT_EQ(obj1.via.array.ptr[2].via.array.ptr[0].via.dec, 1.0);
159#endif // MSGPACK_USE_LEGACY_NAME_AS_FLOAT
160    EXPECT_EQ(obj1.via.array.ptr[3].via.map.ptr[0].key.via.str.ptr[0], 'o');
161    EXPECT_EQ(obj1.via.array.ptr[3].via.map.ptr[0].val.via.bin.ptr[0], 't');
162    EXPECT_NE(
163        obj1.via.array.ptr[2].via.array.ptr,
164        obj2.via.array.ptr[2].via.array.ptr);
165    EXPECT_NE(
166        obj1.via.array.ptr[3].via.map.ptr,
167        obj2.via.array.ptr[3].via.map.ptr);
168    EXPECT_NE(
169        obj1.via.array.ptr[3].via.map.ptr[0].key.via.str.ptr,
170        obj2.via.array.ptr[3].via.map.ptr[0].key.via.str.ptr);
171    EXPECT_NE(
172        obj1.via.array.ptr[3].via.map.ptr[0].val.via.bin.ptr,
173        obj2.via.array.ptr[3].via.map.ptr[0].val.via.bin.ptr);
174    EXPECT_EQ(m1, obj1.as<myclass>());
175}
176
177TEST(object, cross_zone_copy_ext)
178{
179    msgpack::zone z1;
180    msgpack::zone z2;
181    msgpack::object::with_zone obj1(z1);
182
183    obj1.type = msgpack::type::EXT;
184    char* ptr = static_cast<char*>(obj1.zone.allocate_align(2));
185    ptr[0] = 1;
186    ptr[1] = 2;
187    obj1.via.ext.ptr = ptr;
188    obj1.via.ext.size = 1;
189
190    msgpack::object::with_zone obj2(z2);
191    obj2 << obj1;
192    EXPECT_EQ(obj2.via.ext.size, 1u);
193    EXPECT_EQ(obj2.via.ext.ptr[0], 1);
194    EXPECT_EQ(obj2.via.ext.ptr[1], 2);
195    EXPECT_NE(
196        obj1.via.ext.ptr,
197        obj2.via.ext.ptr);
198}
199
200TEST(object, cross_zone_copy_construct_ext)
201{
202    msgpack::zone z1;
203    msgpack::zone z2;
204    msgpack::object::with_zone obj1(z1);
205
206    obj1.type = msgpack::type::EXT;
207    char* ptr = static_cast<char*>(obj1.zone.allocate_align(2));
208    ptr[0] = 1;
209    ptr[1] = 2;
210    obj1.via.ext.ptr = ptr;
211    obj1.via.ext.size = 1;
212
213    msgpack::object obj2(obj1, z2);
214    EXPECT_EQ(obj2.via.ext.size, 1u);
215    EXPECT_EQ(obj2.via.ext.ptr[0], 1);
216    EXPECT_EQ(obj2.via.ext.ptr[1], 2);
217    EXPECT_NE(
218        obj1.via.ext.ptr,
219        obj2.via.ext.ptr);
220}
221
222TEST(object, print)
223{
224    msgpack::object obj;
225    std::cout << obj << std::endl;
226}
227
228
229TEST(object, is_nil)
230{
231    msgpack::object obj;
232    EXPECT_TRUE(obj.is_nil());
233}
234
235
236TEST(object, type_error)
237{
238    msgpack::object obj(1);
239    EXPECT_THROW(obj.as<std::string>(), msgpack::type_error);
240    EXPECT_THROW(obj.as<std::vector<int> >(), msgpack::type_error);
241    EXPECT_EQ(1, obj.as<int>());
242    EXPECT_EQ(1, obj.as<short>());
243    EXPECT_EQ(1u, obj.as<unsigned int>());
244    EXPECT_EQ(1u, obj.as<unsigned long>());
245}
246
247
248TEST(object, equal_primitive)
249{
250    msgpack::object obj_nil;
251    EXPECT_EQ(obj_nil, msgpack::object());
252
253    msgpack::object obj_int(1);
254    EXPECT_EQ(obj_int, msgpack::object(1));
255    EXPECT_EQ(obj_int, 1);
256
257    msgpack::object obj_float(1.2);
258    EXPECT_EQ(obj_float, msgpack::object(1.2));
259    EXPECT_EQ(obj_float, 1.2);
260
261    msgpack::object obj_bool(true);
262    EXPECT_EQ(obj_bool, msgpack::object(true));
263    EXPECT_EQ(obj_bool, true);
264}
265
266
267TEST(object, construct_primitive)
268{
269    msgpack::object obj_nil;
270    EXPECT_EQ(msgpack::type::NIL, obj_nil.type);
271
272    msgpack::object obj_uint(1);
273    EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj_uint.type);
274    EXPECT_EQ(1u, obj_uint.via.u64);
275
276    msgpack::object obj_int(-1);
277    EXPECT_EQ(msgpack::type::NEGATIVE_INTEGER, obj_int.type);
278    EXPECT_EQ(-1, obj_int.via.i64);
279
280    msgpack::object obj_float(1.2);
281    EXPECT_EQ(msgpack::type::FLOAT, obj_float.type);
282    EXPECT_EQ(1.2, obj_float.via.f64);
283#if defined(MSGPACK_USE_LEGACY_NAME_AS_FLOAT)
284    EXPECT_EQ(msgpack::type::DOUBLE, obj_float.type);
285    EXPECT_EQ(1.2, obj_float.via.dec);
286#endif // MSGPACK_USE_LEGACY_NAME_AS_FLOAT
287
288    msgpack::object obj_bool(true);
289    EXPECT_EQ(msgpack::type::BOOLEAN, obj_bool.type);
290    EXPECT_EQ(true, obj_bool.via.boolean);
291}
292
293TEST(object, construct_enum)
294{
295    msgpack::object obj(elem);
296    EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
297    EXPECT_EQ(static_cast<uint64_t>(elem), obj.via.u64);
298}
299
300#if !defined(MSGPACK_USE_CPP03)
301
302TEST(object, construct_enum_newstyle)
303{
304    msgpack::object obj(enum_test::elem);
305    EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
306    EXPECT_EQ(elem, obj.via.u64);
307}
308
309#endif // !defined(MSGPACK_USE_CPP03)
310
311TEST(object, construct_enum_outer)
312{
313    msgpack::object obj(outer_enum::elem);
314    EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
315    EXPECT_EQ(static_cast<uint64_t>(elem), obj.via.u64);
316}
317
318#if !defined(MSGPACK_USE_CPP03)
319
320TEST(object, construct_enum_outer_newstyle)
321{
322    msgpack::object obj(outer_enum::enum_test::elem);
323    EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
324    EXPECT_EQ(elem, obj.via.u64);
325}
326
327TEST(object, construct_class_enum)
328{
329    msgpack::object obj(enum_class_test::elem);
330    EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
331    EXPECT_EQ(elem, obj.via.u64);
332}
333
334
335TEST(object, construct_class_enum_outer)
336{
337    msgpack::object obj(outer_enum_class::enum_class_test::elem);
338    EXPECT_EQ(msgpack::type::POSITIVE_INTEGER, obj.type);
339    EXPECT_EQ(elem, obj.via.u64);
340}
341
342#endif // !defined(MSGPACK_USE_CPP03)
343
344TEST(object, clone_int)
345{
346    int v = 0;
347    msgpack::object obj(v);
348    std::size_t sz1 = msgpack::aligned_zone_size(obj);
349    msgpack::object_handle h = msgpack::clone(obj);
350    EXPECT_EQ(h.get(), obj);
351    EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
352    h = msgpack::clone(obj);
353    EXPECT_EQ(h.get(), obj);
354    EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
355}
356
357TEST(object, clone_str)
358{
359    msgpack::zone z;
360    std::string v = "123456789";
361    msgpack::object obj(v, z);
362    std::size_t sz1 = msgpack::aligned_zone_size(obj);
363    msgpack::object_handle h = msgpack::clone(obj);
364    EXPECT_EQ(h.get(), obj);
365    EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
366    h = msgpack::clone(obj);
367    EXPECT_EQ(h.get(), obj);
368    EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
369}
370
371TEST(object, clone_bin)
372{
373    msgpack::zone z;
374    std::vector<char> v;
375    v.push_back('A');
376    v.push_back('B');
377    v.push_back('C');
378    msgpack::object obj(v, z);
379    std::size_t sz1 = msgpack::aligned_zone_size(obj);
380    msgpack::object_handle h = msgpack::clone(obj);
381    EXPECT_EQ(h.get(), obj);
382    EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
383    h = msgpack::clone(obj);
384    EXPECT_EQ(h.get(), obj);
385    EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
386}
387
388TEST(object, clone_array)
389{
390    msgpack::zone z;
391    std::vector<int> v;
392    v.push_back(1);
393    v.push_back(2);
394    v.push_back(3);
395    msgpack::object obj(v, z);
396    std::size_t sz1 = msgpack::aligned_zone_size(obj);
397    msgpack::object_handle h = msgpack::clone(obj);
398    EXPECT_EQ(h.get(), obj);
399    EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
400    h = msgpack::clone(obj);
401    EXPECT_EQ(h.get(), obj);
402    EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
403}
404
405TEST(object, clone_map)
406{
407    msgpack::zone z;
408    std::map<int, std::string> v;
409    v.insert(std::map<int, std::string>::value_type(1, "ABC"));
410    v.insert(std::map<int, std::string>::value_type(2, "DEF"));
411    v.insert(std::map<int, std::string>::value_type(3, "GHI"));
412    msgpack::object obj(v, z);
413    std::size_t sz1 = msgpack::aligned_zone_size(obj);
414    msgpack::object_handle h = msgpack::clone(obj);
415    EXPECT_EQ(h.get(), obj);
416    EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
417    h = msgpack::clone(obj);
418    EXPECT_EQ(h.get(), obj);
419    EXPECT_EQ(sz1, msgpack::aligned_zone_size(h.get()));
420}
421