1package msgpack_test
2
3import (
4	"bufio"
5	"bytes"
6	"reflect"
7	"testing"
8	"time"
9
10	. "gopkg.in/check.v1"
11
12	"github.com/vmihailenco/msgpack/v4"
13)
14
15type nameStruct struct {
16	Name string
17}
18
19func TestGocheck(t *testing.T) { TestingT(t) }
20
21type MsgpackTest struct {
22	buf *bytes.Buffer
23	enc *msgpack.Encoder
24	dec *msgpack.Decoder
25}
26
27var _ = Suite(&MsgpackTest{})
28
29func (t *MsgpackTest) SetUpTest(c *C) {
30	t.buf = &bytes.Buffer{}
31	t.enc = msgpack.NewEncoder(t.buf)
32	t.dec = msgpack.NewDecoder(bufio.NewReader(t.buf))
33}
34
35func (t *MsgpackTest) TestDecodeNil(c *C) {
36	c.Assert(t.dec.Decode(nil), NotNil)
37}
38
39func (t *MsgpackTest) TestTime(c *C) {
40	in := time.Now()
41	var out time.Time
42	c.Assert(t.enc.Encode(in), IsNil)
43	c.Assert(t.dec.Decode(&out), IsNil)
44	c.Assert(out.Equal(in), Equals, true)
45
46	var zero time.Time
47	c.Assert(t.enc.Encode(zero), IsNil)
48	c.Assert(t.dec.Decode(&out), IsNil)
49	c.Assert(out.Equal(zero), Equals, true)
50	c.Assert(out.IsZero(), Equals, true)
51}
52
53func (t *MsgpackTest) TestLargeBytes(c *C) {
54	N := int(1e6)
55
56	src := bytes.Repeat([]byte{'1'}, N)
57	c.Assert(t.enc.Encode(src), IsNil)
58	var dst []byte
59	c.Assert(t.dec.Decode(&dst), IsNil)
60	c.Assert(dst, DeepEquals, src)
61}
62
63func (t *MsgpackTest) TestLargeString(c *C) {
64	N := int(1e6)
65
66	src := string(bytes.Repeat([]byte{'1'}, N))
67	c.Assert(t.enc.Encode(src), IsNil)
68	var dst string
69	c.Assert(t.dec.Decode(&dst), IsNil)
70	c.Assert(dst, Equals, src)
71}
72
73func (t *MsgpackTest) TestSliceOfStructs(c *C) {
74	in := []*nameStruct{&nameStruct{"hello"}}
75	var out []*nameStruct
76	c.Assert(t.enc.Encode(in), IsNil)
77	c.Assert(t.dec.Decode(&out), IsNil)
78	c.Assert(out, DeepEquals, in)
79}
80
81func (t *MsgpackTest) TestMap(c *C) {
82	for _, i := range []struct {
83		m map[string]string
84		b []byte
85	}{
86		{map[string]string{}, []byte{0x80}},
87		{map[string]string{"hello": "world"}, []byte{0x81, 0xa5, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0xa5, 0x77, 0x6f, 0x72, 0x6c, 0x64}},
88	} {
89		c.Assert(t.enc.Encode(i.m), IsNil)
90		c.Assert(t.buf.Bytes(), DeepEquals, i.b, Commentf("err encoding %v", i.m))
91		var m map[string]string
92		c.Assert(t.dec.Decode(&m), IsNil)
93		c.Assert(m, DeepEquals, i.m)
94	}
95}
96
97func (t *MsgpackTest) TestStructNil(c *C) {
98	var dst *nameStruct
99
100	c.Assert(t.enc.Encode(nameStruct{Name: "foo"}), IsNil)
101	c.Assert(t.dec.Decode(&dst), IsNil)
102	c.Assert(dst, Not(IsNil))
103	c.Assert(dst.Name, Equals, "foo")
104}
105
106func (t *MsgpackTest) TestStructUnknownField(c *C) {
107	in := struct {
108		Field1 string
109		Field2 string
110		Field3 string
111	}{
112		Field1: "value1",
113		Field2: "value2",
114		Field3: "value3",
115	}
116	c.Assert(t.enc.Encode(in), IsNil)
117
118	out := struct {
119		Field2 string
120	}{}
121	c.Assert(t.dec.Decode(&out), IsNil)
122	c.Assert(out.Field2, Equals, "value2")
123}
124
125//------------------------------------------------------------------------------
126
127type coderStruct struct {
128	name string
129}
130
131type wrapperStruct struct {
132	coderStruct
133}
134
135var (
136	_ msgpack.CustomEncoder = (*coderStruct)(nil)
137	_ msgpack.CustomDecoder = (*coderStruct)(nil)
138)
139
140func (s *coderStruct) Name() string {
141	return s.name
142}
143
144func (s *coderStruct) EncodeMsgpack(enc *msgpack.Encoder) error {
145	return enc.Encode(s.name)
146}
147
148func (s *coderStruct) DecodeMsgpack(dec *msgpack.Decoder) error {
149	return dec.Decode(&s.name)
150}
151
152func (t *MsgpackTest) TestCoder(c *C) {
153	in := &coderStruct{name: "hello"}
154	var out coderStruct
155	c.Assert(t.enc.Encode(in), IsNil)
156	c.Assert(t.dec.Decode(&out), IsNil)
157	c.Assert(out.Name(), Equals, "hello")
158}
159
160func (t *MsgpackTest) TestNilCoder(c *C) {
161	in := &coderStruct{name: "hello"}
162	var out *coderStruct
163	c.Assert(t.enc.Encode(in), IsNil)
164	c.Assert(t.dec.Decode(&out), IsNil)
165	c.Assert(out.Name(), Equals, "hello")
166}
167
168func (t *MsgpackTest) TestNilCoderValue(c *C) {
169	in := &coderStruct{name: "hello"}
170	var out *coderStruct
171	c.Assert(t.enc.Encode(in), IsNil)
172	c.Assert(t.dec.DecodeValue(reflect.ValueOf(&out)), IsNil)
173	c.Assert(out.Name(), Equals, "hello")
174}
175
176func (t *MsgpackTest) TestPtrToCoder(c *C) {
177	in := &coderStruct{name: "hello"}
178	var out coderStruct
179	out2 := &out
180	c.Assert(t.enc.Encode(in), IsNil)
181	c.Assert(t.dec.Decode(&out2), IsNil)
182	c.Assert(out.Name(), Equals, "hello")
183}
184
185func (t *MsgpackTest) TestWrappedCoder(c *C) {
186	in := &wrapperStruct{coderStruct: coderStruct{name: "hello"}}
187	var out wrapperStruct
188	c.Assert(t.enc.Encode(in), IsNil)
189	c.Assert(t.dec.Decode(&out), IsNil)
190	c.Assert(out.Name(), Equals, "hello")
191}
192
193//------------------------------------------------------------------------------
194
195type struct2 struct {
196	Name string
197}
198
199type struct1 struct {
200	Name    string
201	Struct2 struct2
202}
203
204func (t *MsgpackTest) TestNestedStructs(c *C) {
205	in := &struct1{Name: "hello", Struct2: struct2{Name: "world"}}
206	var out struct1
207	c.Assert(t.enc.Encode(in), IsNil)
208	c.Assert(t.dec.Decode(&out), IsNil)
209	c.Assert(out.Name, Equals, in.Name)
210	c.Assert(out.Struct2.Name, Equals, in.Struct2.Name)
211}
212
213type Struct4 struct {
214	Name2 string
215}
216
217type Struct3 struct {
218	Struct4
219	Name1 string
220}
221
222func TestEmbedding(t *testing.T) {
223	in := &Struct3{
224		Name1: "hello",
225		Struct4: Struct4{
226			Name2: "world",
227		},
228	}
229	var out Struct3
230
231	b, err := msgpack.Marshal(in)
232	if err != nil {
233		t.Fatal(err)
234	}
235
236	err = msgpack.Unmarshal(b, &out)
237	if err != nil {
238		t.Fatal(err)
239	}
240	if out.Name1 != in.Name1 {
241		t.Fatalf("")
242	}
243	if out.Name2 != in.Name2 {
244		t.Fatalf("")
245	}
246}
247
248func (t *MsgpackTest) TestSliceNil(c *C) {
249	in := [][]*int{nil}
250	var out [][]*int
251
252	c.Assert(t.enc.Encode(in), IsNil)
253	c.Assert(t.dec.Decode(&out), IsNil)
254	c.Assert(out, DeepEquals, in)
255}
256
257//------------------------------------------------------------------------------
258
259func (t *MsgpackTest) TestMapStringInterface(c *C) {
260	in := map[string]interface{}{
261		"foo": "bar",
262		"hello": map[string]interface{}{
263			"foo": "bar",
264		},
265	}
266	var out map[string]interface{}
267
268	c.Assert(t.enc.Encode(in), IsNil)
269	c.Assert(t.dec.Decode(&out), IsNil)
270
271	c.Assert(out["foo"], Equals, "bar")
272	mm := out["hello"].(map[string]interface{})
273	c.Assert(mm["foo"], Equals, "bar")
274}
275