1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// This file contains tests of the GobEncoder/GobDecoder support.
6
7package gob
8
9import (
10	"bytes"
11	"errors"
12	"fmt"
13	"io"
14	"strings"
15	"testing"
16	"time"
17)
18
19// Types that implement the GobEncoder/Decoder interfaces.
20
21type ByteStruct struct {
22	a byte // not an exported field
23}
24
25type StringStruct struct {
26	s string // not an exported field
27}
28
29type ArrayStruct struct {
30	a [8192]byte // not an exported field
31}
32
33type Gobber int
34
35type ValueGobber string // encodes with a value, decodes with a pointer.
36
37// The relevant methods
38
39func (g *ByteStruct) GobEncode() ([]byte, error) {
40	b := make([]byte, 3)
41	b[0] = g.a
42	b[1] = g.a + 1
43	b[2] = g.a + 2
44	return b, nil
45}
46
47func (g *ByteStruct) GobDecode(data []byte) error {
48	if g == nil {
49		return errors.New("NIL RECEIVER")
50	}
51	// Expect N sequential-valued bytes.
52	if len(data) == 0 {
53		return io.EOF
54	}
55	g.a = data[0]
56	for i, c := range data {
57		if c != g.a+byte(i) {
58			return errors.New("invalid data sequence")
59		}
60	}
61	return nil
62}
63
64func (g *StringStruct) GobEncode() ([]byte, error) {
65	return []byte(g.s), nil
66}
67
68func (g *StringStruct) GobDecode(data []byte) error {
69	// Expect N sequential-valued bytes.
70	if len(data) == 0 {
71		return io.EOF
72	}
73	a := data[0]
74	for i, c := range data {
75		if c != a+byte(i) {
76			return errors.New("invalid data sequence")
77		}
78	}
79	g.s = string(data)
80	return nil
81}
82
83func (a *ArrayStruct) GobEncode() ([]byte, error) {
84	return a.a[:], nil
85}
86
87func (a *ArrayStruct) GobDecode(data []byte) error {
88	if len(data) != len(a.a) {
89		return errors.New("wrong length in array decode")
90	}
91	copy(a.a[:], data)
92	return nil
93}
94
95func (g *Gobber) GobEncode() ([]byte, error) {
96	return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
97}
98
99func (g *Gobber) GobDecode(data []byte) error {
100	_, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
101	return err
102}
103
104func (v ValueGobber) GobEncode() ([]byte, error) {
105	return []byte(fmt.Sprintf("VALUE=%s", v)), nil
106}
107
108func (v *ValueGobber) GobDecode(data []byte) error {
109	_, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
110	return err
111}
112
113// Structs that include GobEncodable fields.
114
115type GobTest0 struct {
116	X int // guarantee we have  something in common with GobTest*
117	G *ByteStruct
118}
119
120type GobTest1 struct {
121	X int // guarantee we have  something in common with GobTest*
122	G *StringStruct
123}
124
125type GobTest2 struct {
126	X int    // guarantee we have  something in common with GobTest*
127	G string // not a GobEncoder - should give us errors
128}
129
130type GobTest3 struct {
131	X int // guarantee we have  something in common with GobTest*
132	G *Gobber
133}
134
135type GobTest4 struct {
136	X int // guarantee we have  something in common with GobTest*
137	V ValueGobber
138}
139
140type GobTest5 struct {
141	X int // guarantee we have  something in common with GobTest*
142	V *ValueGobber
143}
144
145type GobTest6 struct {
146	X int // guarantee we have  something in common with GobTest*
147	V ValueGobber
148	W *ValueGobber
149}
150
151type GobTest7 struct {
152	X int // guarantee we have  something in common with GobTest*
153	V *ValueGobber
154	W ValueGobber
155}
156
157type GobTestIgnoreEncoder struct {
158	X int // guarantee we have  something in common with GobTest*
159}
160
161type GobTestValueEncDec struct {
162	X int          // guarantee we have  something in common with GobTest*
163	G StringStruct // not a pointer.
164}
165
166type GobTestIndirectEncDec struct {
167	X int             // guarantee we have  something in common with GobTest*
168	G ***StringStruct // indirections to the receiver.
169}
170
171type GobTestArrayEncDec struct {
172	X int         // guarantee we have  something in common with GobTest*
173	A ArrayStruct // not a pointer.
174}
175
176type GobTestIndirectArrayEncDec struct {
177	X int            // guarantee we have  something in common with GobTest*
178	A ***ArrayStruct // indirections to a large receiver.
179}
180
181func TestGobEncoderField(t *testing.T) {
182	b := new(bytes.Buffer)
183	// First a field that's a structure.
184	enc := NewEncoder(b)
185	err := enc.Encode(GobTest0{17, &ByteStruct{'A'}})
186	if err != nil {
187		t.Fatal("encode error:", err)
188	}
189	dec := NewDecoder(b)
190	x := new(GobTest0)
191	err = dec.Decode(x)
192	if err != nil {
193		t.Fatal("decode error:", err)
194	}
195	if x.G.a != 'A' {
196		t.Errorf("expected 'A' got %c", x.G.a)
197	}
198	// Now a field that's not a structure.
199	b.Reset()
200	gobber := Gobber(23)
201	err = enc.Encode(GobTest3{17, &gobber})
202	if err != nil {
203		t.Fatal("encode error:", err)
204	}
205	y := new(GobTest3)
206	err = dec.Decode(y)
207	if err != nil {
208		t.Fatal("decode error:", err)
209	}
210	if *y.G != 23 {
211		t.Errorf("expected '23 got %d", *y.G)
212	}
213}
214
215// Even though the field is a value, we can still take its address
216// and should be able to call the methods.
217func TestGobEncoderValueField(t *testing.T) {
218	b := new(bytes.Buffer)
219	// First a field that's a structure.
220	enc := NewEncoder(b)
221	err := enc.Encode(GobTestValueEncDec{17, StringStruct{"HIJKL"}})
222	if err != nil {
223		t.Fatal("encode error:", err)
224	}
225	dec := NewDecoder(b)
226	x := new(GobTestValueEncDec)
227	err = dec.Decode(x)
228	if err != nil {
229		t.Fatal("decode error:", err)
230	}
231	if x.G.s != "HIJKL" {
232		t.Errorf("expected `HIJKL` got %s", x.G.s)
233	}
234}
235
236// GobEncode/Decode should work even if the value is
237// more indirect than the receiver.
238func TestGobEncoderIndirectField(t *testing.T) {
239	b := new(bytes.Buffer)
240	// First a field that's a structure.
241	enc := NewEncoder(b)
242	s := &StringStruct{"HIJKL"}
243	sp := &s
244	err := enc.Encode(GobTestIndirectEncDec{17, &sp})
245	if err != nil {
246		t.Fatal("encode error:", err)
247	}
248	dec := NewDecoder(b)
249	x := new(GobTestIndirectEncDec)
250	err = dec.Decode(x)
251	if err != nil {
252		t.Fatal("decode error:", err)
253	}
254	if (***x.G).s != "HIJKL" {
255		t.Errorf("expected `HIJKL` got %s", (***x.G).s)
256	}
257}
258
259// Test with a large field with methods.
260func TestGobEncoderArrayField(t *testing.T) {
261	b := new(bytes.Buffer)
262	enc := NewEncoder(b)
263	var a GobTestArrayEncDec
264	a.X = 17
265	for i := range a.A.a {
266		a.A.a[i] = byte(i)
267	}
268	err := enc.Encode(a)
269	if err != nil {
270		t.Fatal("encode error:", err)
271	}
272	dec := NewDecoder(b)
273	x := new(GobTestArrayEncDec)
274	err = dec.Decode(x)
275	if err != nil {
276		t.Fatal("decode error:", err)
277	}
278	for i, v := range x.A.a {
279		if v != byte(i) {
280			t.Errorf("expected %x got %x", byte(i), v)
281			break
282		}
283	}
284}
285
286// Test an indirection to a large field with methods.
287func TestGobEncoderIndirectArrayField(t *testing.T) {
288	b := new(bytes.Buffer)
289	enc := NewEncoder(b)
290	var a GobTestIndirectArrayEncDec
291	a.X = 17
292	var array ArrayStruct
293	ap := &array
294	app := &ap
295	a.A = &app
296	for i := range array.a {
297		array.a[i] = byte(i)
298	}
299	err := enc.Encode(a)
300	if err != nil {
301		t.Fatal("encode error:", err)
302	}
303	dec := NewDecoder(b)
304	x := new(GobTestIndirectArrayEncDec)
305	err = dec.Decode(x)
306	if err != nil {
307		t.Fatal("decode error:", err)
308	}
309	for i, v := range (***x.A).a {
310		if v != byte(i) {
311			t.Errorf("expected %x got %x", byte(i), v)
312			break
313		}
314	}
315}
316
317// As long as the fields have the same name and implement the
318// interface, we can cross-connect them.  Not sure it's useful
319// and may even be bad but it works and it's hard to prevent
320// without exposing the contents of the object, which would
321// defeat the purpose.
322func TestGobEncoderFieldsOfDifferentType(t *testing.T) {
323	// first, string in field to byte in field
324	b := new(bytes.Buffer)
325	enc := NewEncoder(b)
326	err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}})
327	if err != nil {
328		t.Fatal("encode error:", err)
329	}
330	dec := NewDecoder(b)
331	x := new(GobTest0)
332	err = dec.Decode(x)
333	if err != nil {
334		t.Fatal("decode error:", err)
335	}
336	if x.G.a != 'A' {
337		t.Errorf("expected 'A' got %c", x.G.a)
338	}
339	// now the other direction, byte in field to string in field
340	b.Reset()
341	err = enc.Encode(GobTest0{17, &ByteStruct{'X'}})
342	if err != nil {
343		t.Fatal("encode error:", err)
344	}
345	y := new(GobTest1)
346	err = dec.Decode(y)
347	if err != nil {
348		t.Fatal("decode error:", err)
349	}
350	if y.G.s != "XYZ" {
351		t.Fatalf("expected `XYZ` got %q", y.G.s)
352	}
353}
354
355// Test that we can encode a value and decode into a pointer.
356func TestGobEncoderValueEncoder(t *testing.T) {
357	// first, string in field to byte in field
358	b := new(bytes.Buffer)
359	enc := NewEncoder(b)
360	err := enc.Encode(GobTest4{17, ValueGobber("hello")})
361	if err != nil {
362		t.Fatal("encode error:", err)
363	}
364	dec := NewDecoder(b)
365	x := new(GobTest5)
366	err = dec.Decode(x)
367	if err != nil {
368		t.Fatal("decode error:", err)
369	}
370	if *x.V != "hello" {
371		t.Errorf("expected `hello` got %s", x.V)
372	}
373}
374
375// Test that we can use a value then a pointer type of a GobEncoder
376// in the same encoded value.  Bug 4647.
377func TestGobEncoderValueThenPointer(t *testing.T) {
378	v := ValueGobber("forty-two")
379	w := ValueGobber("six-by-nine")
380
381	// this was a bug: encoding a GobEncoder by value before a GobEncoder
382	// pointer would cause duplicate type definitions to be sent.
383
384	b := new(bytes.Buffer)
385	enc := NewEncoder(b)
386	if err := enc.Encode(GobTest6{42, v, &w}); err != nil {
387		t.Fatal("encode error:", err)
388	}
389	dec := NewDecoder(b)
390	x := new(GobTest6)
391	if err := dec.Decode(x); err != nil {
392		t.Fatal("decode error:", err)
393	}
394	if got, want := x.V, v; got != want {
395		t.Errorf("v = %q, want %q", got, want)
396	}
397	if got, want := x.W, w; got == nil {
398		t.Errorf("w = nil, want %q", want)
399	} else if *got != want {
400		t.Errorf("w = %q, want %q", *got, want)
401	}
402}
403
404// Test that we can use a pointer then a value type of a GobEncoder
405// in the same encoded value.
406func TestGobEncoderPointerThenValue(t *testing.T) {
407	v := ValueGobber("forty-two")
408	w := ValueGobber("six-by-nine")
409
410	b := new(bytes.Buffer)
411	enc := NewEncoder(b)
412	if err := enc.Encode(GobTest7{42, &v, w}); err != nil {
413		t.Fatal("encode error:", err)
414	}
415	dec := NewDecoder(b)
416	x := new(GobTest7)
417	if err := dec.Decode(x); err != nil {
418		t.Fatal("decode error:", err)
419	}
420	if got, want := x.V, v; got == nil {
421		t.Errorf("v = nil, want %q", want)
422	} else if *got != want {
423		t.Errorf("v = %q, want %q", got, want)
424	}
425	if got, want := x.W, w; got != want {
426		t.Errorf("w = %q, want %q", got, want)
427	}
428}
429
430func TestGobEncoderFieldTypeError(t *testing.T) {
431	// GobEncoder to non-decoder: error
432	b := new(bytes.Buffer)
433	enc := NewEncoder(b)
434	err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}})
435	if err != nil {
436		t.Fatal("encode error:", err)
437	}
438	dec := NewDecoder(b)
439	x := &GobTest2{}
440	err = dec.Decode(x)
441	if err == nil {
442		t.Fatal("expected decode error for mismatched fields (encoder to non-decoder)")
443	}
444	if strings.Index(err.Error(), "type") < 0 {
445		t.Fatal("expected type error; got", err)
446	}
447	// Non-encoder to GobDecoder: error
448	b.Reset()
449	err = enc.Encode(GobTest2{17, "ABC"})
450	if err != nil {
451		t.Fatal("encode error:", err)
452	}
453	y := &GobTest1{}
454	err = dec.Decode(y)
455	if err == nil {
456		t.Fatal("expected decode error for mismatched fields (non-encoder to decoder)")
457	}
458	if strings.Index(err.Error(), "type") < 0 {
459		t.Fatal("expected type error; got", err)
460	}
461}
462
463// Even though ByteStruct is a struct, it's treated as a singleton at the top level.
464func TestGobEncoderStructSingleton(t *testing.T) {
465	b := new(bytes.Buffer)
466	enc := NewEncoder(b)
467	err := enc.Encode(&ByteStruct{'A'})
468	if err != nil {
469		t.Fatal("encode error:", err)
470	}
471	dec := NewDecoder(b)
472	x := new(ByteStruct)
473	err = dec.Decode(x)
474	if err != nil {
475		t.Fatal("decode error:", err)
476	}
477	if x.a != 'A' {
478		t.Errorf("expected 'A' got %c", x.a)
479	}
480}
481
482func TestGobEncoderNonStructSingleton(t *testing.T) {
483	b := new(bytes.Buffer)
484	enc := NewEncoder(b)
485	err := enc.Encode(Gobber(1234))
486	if err != nil {
487		t.Fatal("encode error:", err)
488	}
489	dec := NewDecoder(b)
490	var x Gobber
491	err = dec.Decode(&x)
492	if err != nil {
493		t.Fatal("decode error:", err)
494	}
495	if x != 1234 {
496		t.Errorf("expected 1234 got %d", x)
497	}
498}
499
500func TestGobEncoderIgnoreStructField(t *testing.T) {
501	b := new(bytes.Buffer)
502	// First a field that's a structure.
503	enc := NewEncoder(b)
504	err := enc.Encode(GobTest0{17, &ByteStruct{'A'}})
505	if err != nil {
506		t.Fatal("encode error:", err)
507	}
508	dec := NewDecoder(b)
509	x := new(GobTestIgnoreEncoder)
510	err = dec.Decode(x)
511	if err != nil {
512		t.Fatal("decode error:", err)
513	}
514	if x.X != 17 {
515		t.Errorf("expected 17 got %c", x.X)
516	}
517}
518
519func TestGobEncoderIgnoreNonStructField(t *testing.T) {
520	b := new(bytes.Buffer)
521	// First a field that's a structure.
522	enc := NewEncoder(b)
523	gobber := Gobber(23)
524	err := enc.Encode(GobTest3{17, &gobber})
525	if err != nil {
526		t.Fatal("encode error:", err)
527	}
528	dec := NewDecoder(b)
529	x := new(GobTestIgnoreEncoder)
530	err = dec.Decode(x)
531	if err != nil {
532		t.Fatal("decode error:", err)
533	}
534	if x.X != 17 {
535		t.Errorf("expected 17 got %c", x.X)
536	}
537}
538
539func TestGobEncoderIgnoreNilEncoder(t *testing.T) {
540	b := new(bytes.Buffer)
541	// First a field that's a structure.
542	enc := NewEncoder(b)
543	err := enc.Encode(GobTest0{X: 18}) // G is nil
544	if err != nil {
545		t.Fatal("encode error:", err)
546	}
547	dec := NewDecoder(b)
548	x := new(GobTest0)
549	err = dec.Decode(x)
550	if err != nil {
551		t.Fatal("decode error:", err)
552	}
553	if x.X != 18 {
554		t.Errorf("expected x.X = 18, got %v", x.X)
555	}
556	if x.G != nil {
557		t.Errorf("expected x.G = nil, got %v", x.G)
558	}
559}
560
561type gobDecoderBug0 struct {
562	foo, bar string
563}
564
565func (br *gobDecoderBug0) String() string {
566	return br.foo + "-" + br.bar
567}
568
569func (br *gobDecoderBug0) GobEncode() ([]byte, error) {
570	return []byte(br.String()), nil
571}
572
573func (br *gobDecoderBug0) GobDecode(b []byte) error {
574	br.foo = "foo"
575	br.bar = "bar"
576	return nil
577}
578
579// This was a bug: the receiver has a different indirection level
580// than the variable.
581func TestGobEncoderExtraIndirect(t *testing.T) {
582	gdb := &gobDecoderBug0{"foo", "bar"}
583	buf := new(bytes.Buffer)
584	e := NewEncoder(buf)
585	if err := e.Encode(gdb); err != nil {
586		t.Fatalf("encode: %v", err)
587	}
588	d := NewDecoder(buf)
589	var got *gobDecoderBug0
590	if err := d.Decode(&got); err != nil {
591		t.Fatalf("decode: %v", err)
592	}
593	if got.foo != gdb.foo || got.bar != gdb.bar {
594		t.Errorf("got = %q, want %q", got, gdb)
595	}
596}
597
598// Another bug: this caused a crash with the new Go1 Time type.
599// We throw in a gob-encoding array, to test another case of isZero
600
601type isZeroBug struct {
602	T time.Time
603	S string
604	I int
605	A isZeroBugArray
606}
607
608type isZeroBugArray [2]uint8
609
610// Receiver is value, not pointer, to test isZero of array.
611func (a isZeroBugArray) GobEncode() (b []byte, e error) {
612	b = append(b, a[:]...)
613	return b, nil
614}
615
616func (a *isZeroBugArray) GobDecode(data []byte) error {
617	if len(data) != len(a) {
618		return io.EOF
619	}
620	a[0] = data[0]
621	a[1] = data[1]
622	return nil
623}
624
625func TestGobEncodeIsZero(t *testing.T) {
626	x := isZeroBug{time.Now(), "hello", -55, isZeroBugArray{1, 2}}
627	b := new(bytes.Buffer)
628	enc := NewEncoder(b)
629	err := enc.Encode(x)
630	if err != nil {
631		t.Fatal("encode:", err)
632	}
633	var y isZeroBug
634	dec := NewDecoder(b)
635	err = dec.Decode(&y)
636	if err != nil {
637		t.Fatal("decode:", err)
638	}
639	if x != y {
640		t.Fatalf("%v != %v", x, y)
641	}
642}
643
644func TestGobEncodePtrError(t *testing.T) {
645	var err error
646	b := new(bytes.Buffer)
647	enc := NewEncoder(b)
648	err = enc.Encode(&err)
649	if err != nil {
650		t.Fatal("encode:", err)
651	}
652	dec := NewDecoder(b)
653	err2 := fmt.Errorf("foo")
654	err = dec.Decode(&err2)
655	if err != nil {
656		t.Fatal("decode:", err)
657	}
658	if err2 != nil {
659		t.Fatalf("expected nil, got %v", err2)
660	}
661}
662