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.
5 // This file contains tests of the GobEncoder/GobDecoder support.
20 // Types that implement the GobEncoder/Decoder interfaces.
22 type ByteStruct
struct {
23 a
byte // not an exported field
26 type StringStruct
struct {
27 s
string // not an exported field
30 type ArrayStruct
struct {
31 a
[8192]byte // not an exported field
36 type ValueGobber
string // encodes with a value, decodes with a pointer.
40 type BinaryValueGobber
string
44 type TextValueGobber
string
46 // The relevant methods
48 func (g
*ByteStruct
) GobEncode() ([]byte, error
) {
56 func (g
*ByteStruct
) GobDecode(data
[]byte) error
{
58 return errors
.New("NIL RECEIVER")
60 // Expect N sequential-valued bytes.
65 for i
, c
:= range data
{
67 return errors
.New("invalid data sequence")
73 func (g
*StringStruct
) GobEncode() ([]byte, error
) {
74 return []byte(g
.s
), nil
77 func (g
*StringStruct
) GobDecode(data
[]byte) error
{
78 // Expect N sequential-valued bytes.
83 for i
, c
:= range data
{
85 return errors
.New("invalid data sequence")
92 func (a
*ArrayStruct
) GobEncode() ([]byte, error
) {
96 func (a
*ArrayStruct
) GobDecode(data
[]byte) error
{
97 if len(data
) != len(a
.a
) {
98 return errors
.New("wrong length in array decode")
104 func (g
*Gobber
) GobEncode() ([]byte, error
) {
105 return []byte(fmt
.Sprintf("VALUE=%d", *g
)), nil
108 func (g
*Gobber
) GobDecode(data
[]byte) error
{
109 _
, err
:= fmt
.Sscanf(string(data
), "VALUE=%d", (*int)(g
))
113 func (g
*BinaryGobber
) MarshalBinary() ([]byte, error
) {
114 return []byte(fmt
.Sprintf("VALUE=%d", *g
)), nil
117 func (g
*BinaryGobber
) UnmarshalBinary(data
[]byte) error
{
118 _
, err
:= fmt
.Sscanf(string(data
), "VALUE=%d", (*int)(g
))
122 func (g
*TextGobber
) MarshalText() ([]byte, error
) {
123 return []byte(fmt
.Sprintf("VALUE=%d", *g
)), nil
126 func (g
*TextGobber
) UnmarshalText(data
[]byte) error
{
127 _
, err
:= fmt
.Sscanf(string(data
), "VALUE=%d", (*int)(g
))
131 func (v ValueGobber
) GobEncode() ([]byte, error
) {
132 return []byte(fmt
.Sprintf("VALUE=%s", v
)), nil
135 func (v
*ValueGobber
) GobDecode(data
[]byte) error
{
136 _
, err
:= fmt
.Sscanf(string(data
), "VALUE=%s", (*string)(v
))
140 func (v BinaryValueGobber
) MarshalBinary() ([]byte, error
) {
141 return []byte(fmt
.Sprintf("VALUE=%s", v
)), nil
144 func (v
*BinaryValueGobber
) UnmarshalBinary(data
[]byte) error
{
145 _
, err
:= fmt
.Sscanf(string(data
), "VALUE=%s", (*string)(v
))
149 func (v TextValueGobber
) MarshalText() ([]byte, error
) {
150 return []byte(fmt
.Sprintf("VALUE=%s", v
)), nil
153 func (v
*TextValueGobber
) UnmarshalText(data
[]byte) error
{
154 _
, err
:= fmt
.Sscanf(string(data
), "VALUE=%s", (*string)(v
))
158 // Structs that include GobEncodable fields.
160 type GobTest0
struct {
161 X
int // guarantee we have something in common with GobTest*
165 type GobTest1
struct {
166 X
int // guarantee we have something in common with GobTest*
170 type GobTest2
struct {
171 X
int // guarantee we have something in common with GobTest*
172 G
string // not a GobEncoder - should give us errors
175 type GobTest3
struct {
176 X
int // guarantee we have something in common with GobTest*
182 type GobTest4
struct {
183 X
int // guarantee we have something in common with GobTest*
189 type GobTest5
struct {
190 X
int // guarantee we have something in common with GobTest*
192 BV
*BinaryValueGobber
196 type GobTest6
struct {
197 X
int // guarantee we have something in common with GobTest*
201 BW
*BinaryValueGobber
206 type GobTest7
struct {
207 X
int // guarantee we have something in common with GobTest*
210 BV
*BinaryValueGobber
216 type GobTestIgnoreEncoder
struct {
217 X
int // guarantee we have something in common with GobTest*
220 type GobTestValueEncDec
struct {
221 X
int // guarantee we have something in common with GobTest*
222 G StringStruct
// not a pointer.
225 type GobTestIndirectEncDec
struct {
226 X
int // guarantee we have something in common with GobTest*
227 G
***StringStruct
// indirections to the receiver.
230 type GobTestArrayEncDec
struct {
231 X
int // guarantee we have something in common with GobTest*
232 A ArrayStruct
// not a pointer.
235 type GobTestIndirectArrayEncDec
struct {
236 X
int // guarantee we have something in common with GobTest*
237 A
***ArrayStruct
// indirections to a large receiver.
240 func TestGobEncoderField(t
*testing
.T
) {
241 b
:= new(bytes
.Buffer
)
242 // First a field that's a structure.
244 err
:= enc
.Encode(GobTest0
{17, &ByteStruct
{'A'}})
246 t
.Fatal("encode error:", err
)
252 t
.Fatal("decode error:", err
)
255 t
.Errorf("expected 'A' got %c", x
.G
.a
)
257 // Now a field that's not a structure.
260 bgobber
:= BinaryGobber(24)
261 tgobber
:= TextGobber(25)
262 err
= enc
.Encode(GobTest3
{17, &gobber
, &bgobber
, &tgobber
})
264 t
.Fatal("encode error:", err
)
269 t
.Fatal("decode error:", err
)
271 if *y
.G
!= 23 ||
*y
.B
!= 24 ||
*y
.T
!= 25 {
272 t
.Errorf("expected '23 got %d", *y
.G
)
276 // Even though the field is a value, we can still take its address
277 // and should be able to call the methods.
278 func TestGobEncoderValueField(t
*testing
.T
) {
279 b
:= new(bytes
.Buffer
)
280 // First a field that's a structure.
282 err
:= enc
.Encode(&GobTestValueEncDec
{17, StringStruct
{"HIJKL"}})
284 t
.Fatal("encode error:", err
)
287 x
:= new(GobTestValueEncDec
)
290 t
.Fatal("decode error:", err
)
292 if x
.G
.s
!= "HIJKL" {
293 t
.Errorf("expected `HIJKL` got %s", x
.G
.s
)
297 // GobEncode/Decode should work even if the value is
298 // more indirect than the receiver.
299 func TestGobEncoderIndirectField(t
*testing
.T
) {
300 b
:= new(bytes
.Buffer
)
301 // First a field that's a structure.
303 s
:= &StringStruct
{"HIJKL"}
305 err
:= enc
.Encode(GobTestIndirectEncDec
{17, &sp
})
307 t
.Fatal("encode error:", err
)
310 x
:= new(GobTestIndirectEncDec
)
313 t
.Fatal("decode error:", err
)
315 if (***x
.G
).s
!= "HIJKL" {
316 t
.Errorf("expected `HIJKL` got %s", (***x
.G
).s
)
320 // Test with a large field with methods.
321 func TestGobEncoderArrayField(t
*testing
.T
) {
322 b
:= new(bytes
.Buffer
)
324 var a GobTestArrayEncDec
326 for i
:= range a
.A
.a
{
329 err
:= enc
.Encode(&a
)
331 t
.Fatal("encode error:", err
)
334 x
:= new(GobTestArrayEncDec
)
337 t
.Fatal("decode error:", err
)
339 for i
, v
:= range x
.A
.a
{
341 t
.Errorf("expected %x got %x", byte(i
), v
)
347 // Test an indirection to a large field with methods.
348 func TestGobEncoderIndirectArrayField(t
*testing
.T
) {
349 b
:= new(bytes
.Buffer
)
351 var a GobTestIndirectArrayEncDec
353 var array ArrayStruct
357 for i
:= range array
.a
{
362 t
.Fatal("encode error:", err
)
365 x
:= new(GobTestIndirectArrayEncDec
)
368 t
.Fatal("decode error:", err
)
370 for i
, v
:= range (***x
.A
).a
{
372 t
.Errorf("expected %x got %x", byte(i
), v
)
378 // As long as the fields have the same name and implement the
379 // interface, we can cross-connect them. Not sure it's useful
380 // and may even be bad but it works and it's hard to prevent
381 // without exposing the contents of the object, which would
382 // defeat the purpose.
383 func TestGobEncoderFieldsOfDifferentType(t
*testing
.T
) {
384 // first, string in field to byte in field
385 b
:= new(bytes
.Buffer
)
387 err
:= enc
.Encode(GobTest1
{17, &StringStruct
{"ABC"}})
389 t
.Fatal("encode error:", err
)
395 t
.Fatal("decode error:", err
)
398 t
.Errorf("expected 'A' got %c", x
.G
.a
)
400 // now the other direction, byte in field to string in field
402 err
= enc
.Encode(GobTest0
{17, &ByteStruct
{'X'}})
404 t
.Fatal("encode error:", err
)
409 t
.Fatal("decode error:", err
)
412 t
.Fatalf("expected `XYZ` got %q", y
.G
.s
)
416 // Test that we can encode a value and decode into a pointer.
417 func TestGobEncoderValueEncoder(t
*testing
.T
) {
418 // first, string in field to byte in field
419 b
:= new(bytes
.Buffer
)
421 err
:= enc
.Encode(GobTest4
{17, ValueGobber("hello"), BinaryValueGobber("Καλημέρα"), TextValueGobber("こんにちは")})
423 t
.Fatal("encode error:", err
)
429 t
.Fatal("decode error:", err
)
431 if *x
.V
!= "hello" ||
*x
.BV
!= "Καλημέρα" ||
*x
.TV
!= "こんにちは" {
432 t
.Errorf("expected `hello` got %s", *x
.V
)
436 // Test that we can use a value then a pointer type of a GobEncoder
437 // in the same encoded value. Bug 4647.
438 func TestGobEncoderValueThenPointer(t
*testing
.T
) {
439 v
:= ValueGobber("forty-two")
440 w
:= ValueGobber("six-by-nine")
441 bv
:= BinaryValueGobber("1nanocentury")
442 bw
:= BinaryValueGobber("πseconds")
443 tv
:= TextValueGobber("gravitationalacceleration")
444 tw
:= TextValueGobber("π²ft/s²")
446 // this was a bug: encoding a GobEncoder by value before a GobEncoder
447 // pointer would cause duplicate type definitions to be sent.
449 b
:= new(bytes
.Buffer
)
451 if err
:= enc
.Encode(GobTest6
{42, v
, &w
, bv
, &bw
, tv
, &tw
}); err
!= nil {
452 t
.Fatal("encode error:", err
)
456 if err
:= dec
.Decode(x
); err
!= nil {
457 t
.Fatal("decode error:", err
)
460 if got
, want
:= x
.V
, v
; got
!= want
{
461 t
.Errorf("v = %q, want %q", got
, want
)
463 if got
, want
:= x
.W
, w
; got
== nil {
464 t
.Errorf("w = nil, want %q", want
)
465 } else if *got
!= want
{
466 t
.Errorf("w = %q, want %q", *got
, want
)
469 if got
, want
:= x
.BV
, bv
; got
!= want
{
470 t
.Errorf("bv = %q, want %q", got
, want
)
472 if got
, want
:= x
.BW
, bw
; got
== nil {
473 t
.Errorf("bw = nil, want %q", want
)
474 } else if *got
!= want
{
475 t
.Errorf("bw = %q, want %q", *got
, want
)
478 if got
, want
:= x
.TV
, tv
; got
!= want
{
479 t
.Errorf("tv = %q, want %q", got
, want
)
481 if got
, want
:= x
.TW
, tw
; got
== nil {
482 t
.Errorf("tw = nil, want %q", want
)
483 } else if *got
!= want
{
484 t
.Errorf("tw = %q, want %q", *got
, want
)
488 // Test that we can use a pointer then a value type of a GobEncoder
489 // in the same encoded value.
490 func TestGobEncoderPointerThenValue(t
*testing
.T
) {
491 v
:= ValueGobber("forty-two")
492 w
:= ValueGobber("six-by-nine")
493 bv
:= BinaryValueGobber("1nanocentury")
494 bw
:= BinaryValueGobber("πseconds")
495 tv
:= TextValueGobber("gravitationalacceleration")
496 tw
:= TextValueGobber("π²ft/s²")
498 b
:= new(bytes
.Buffer
)
500 if err
:= enc
.Encode(GobTest7
{42, &v
, w
, &bv
, bw
, &tv
, tw
}); err
!= nil {
501 t
.Fatal("encode error:", err
)
505 if err
:= dec
.Decode(x
); err
!= nil {
506 t
.Fatal("decode error:", err
)
509 if got
, want
:= x
.V
, v
; got
== nil {
510 t
.Errorf("v = nil, want %q", want
)
511 } else if *got
!= want
{
512 t
.Errorf("v = %q, want %q", *got
, want
)
514 if got
, want
:= x
.W
, w
; got
!= want
{
515 t
.Errorf("w = %q, want %q", got
, want
)
518 if got
, want
:= x
.BV
, bv
; got
== nil {
519 t
.Errorf("bv = nil, want %q", want
)
520 } else if *got
!= want
{
521 t
.Errorf("bv = %q, want %q", *got
, want
)
523 if got
, want
:= x
.BW
, bw
; got
!= want
{
524 t
.Errorf("bw = %q, want %q", got
, want
)
527 if got
, want
:= x
.TV
, tv
; got
== nil {
528 t
.Errorf("tv = nil, want %q", want
)
529 } else if *got
!= want
{
530 t
.Errorf("tv = %q, want %q", *got
, want
)
532 if got
, want
:= x
.TW
, tw
; got
!= want
{
533 t
.Errorf("tw = %q, want %q", got
, want
)
537 func TestGobEncoderFieldTypeError(t
*testing
.T
) {
538 // GobEncoder to non-decoder: error
539 b
:= new(bytes
.Buffer
)
541 err
:= enc
.Encode(GobTest1
{17, &StringStruct
{"ABC"}})
543 t
.Fatal("encode error:", err
)
549 t
.Fatal("expected decode error for mismatched fields (encoder to non-decoder)")
551 if !strings
.Contains(err
.Error(), "type") {
552 t
.Fatal("expected type error; got", err
)
554 // Non-encoder to GobDecoder: error
556 err
= enc
.Encode(GobTest2
{17, "ABC"})
558 t
.Fatal("encode error:", err
)
563 t
.Fatal("expected decode error for mismatched fields (non-encoder to decoder)")
565 if !strings
.Contains(err
.Error(), "type") {
566 t
.Fatal("expected type error; got", err
)
570 // Even though ByteStruct is a struct, it's treated as a singleton at the top level.
571 func TestGobEncoderStructSingleton(t
*testing
.T
) {
572 b
:= new(bytes
.Buffer
)
574 err
:= enc
.Encode(&ByteStruct
{'A'})
576 t
.Fatal("encode error:", err
)
582 t
.Fatal("decode error:", err
)
585 t
.Errorf("expected 'A' got %c", x
.a
)
589 func TestGobEncoderNonStructSingleton(t
*testing
.T
) {
590 b
:= new(bytes
.Buffer
)
593 err
:= enc
.Encode(&g
)
595 t
.Fatal("encode error:", err
)
601 t
.Fatal("decode error:", err
)
604 t
.Errorf("expected 1234 got %d", x
)
608 func TestGobEncoderIgnoreStructField(t
*testing
.T
) {
609 b
:= new(bytes
.Buffer
)
610 // First a field that's a structure.
612 err
:= enc
.Encode(GobTest0
{17, &ByteStruct
{'A'}})
614 t
.Fatal("encode error:", err
)
617 x
:= new(GobTestIgnoreEncoder
)
620 t
.Fatal("decode error:", err
)
623 t
.Errorf("expected 17 got %c", x
.X
)
627 func TestGobEncoderIgnoreNonStructField(t
*testing
.T
) {
628 b
:= new(bytes
.Buffer
)
629 // First a field that's a structure.
632 bgobber
:= BinaryGobber(24)
633 tgobber
:= TextGobber(25)
634 err
:= enc
.Encode(GobTest3
{17, &gobber
, &bgobber
, &tgobber
})
636 t
.Fatal("encode error:", err
)
639 x
:= new(GobTestIgnoreEncoder
)
642 t
.Fatal("decode error:", err
)
645 t
.Errorf("expected 17 got %c", x
.X
)
649 func TestGobEncoderIgnoreNilEncoder(t
*testing
.T
) {
650 b
:= new(bytes
.Buffer
)
651 // First a field that's a structure.
653 err
:= enc
.Encode(GobTest0
{X
: 18}) // G is nil
655 t
.Fatal("encode error:", err
)
661 t
.Fatal("decode error:", err
)
664 t
.Errorf("expected x.X = 18, got %v", x
.X
)
667 t
.Errorf("expected x.G = nil, got %v", x
.G
)
671 type gobDecoderBug0
struct {
675 func (br
*gobDecoderBug0
) String() string {
676 return br
.foo
+ "-" + br
.bar
679 func (br
*gobDecoderBug0
) GobEncode() ([]byte, error
) {
680 return []byte(br
.String()), nil
683 func (br
*gobDecoderBug0
) GobDecode(b
[]byte) error
{
689 // This was a bug: the receiver has a different indirection level
690 // than the variable.
691 func TestGobEncoderExtraIndirect(t
*testing
.T
) {
692 gdb
:= &gobDecoderBug0
{"foo", "bar"}
693 buf
:= new(bytes
.Buffer
)
695 if err
:= e
.Encode(gdb
); err
!= nil {
696 t
.Fatalf("encode: %v", err
)
699 var got
*gobDecoderBug0
700 if err
:= d
.Decode(&got
); err
!= nil {
701 t
.Fatalf("decode: %v", err
)
703 if got
.foo
!= gdb
.foo || got
.bar
!= gdb
.bar
{
704 t
.Errorf("got = %q, want %q", got
, gdb
)
708 // Another bug: this caused a crash with the new Go1 Time type.
709 // We throw in a gob-encoding array, to test another case of isZero,
710 // and a struct containing an nil interface, to test a third.
711 type isZeroBug
struct {
719 type isZeroBugArray
[2]uint8
721 // Receiver is value, not pointer, to test isZero of array.
722 func (a isZeroBugArray
) GobEncode() (b
[]byte, e error
) {
723 b
= append(b
, a
[:]...)
727 func (a
*isZeroBugArray
) GobDecode(data
[]byte) error
{
728 if len(data
) != len(a
) {
736 type isZeroBugInterface
struct {
740 func (i isZeroBugInterface
) GobEncode() (b
[]byte, e error
) {
744 func (i
*isZeroBugInterface
) GobDecode(data
[]byte) error
{
748 func TestGobEncodeIsZero(t
*testing
.T
) {
749 x
:= isZeroBug
{time
.Unix(1e9
, 0), "hello", -55, isZeroBugArray
{1, 2}, isZeroBugInterface
{}}
750 b
:= new(bytes
.Buffer
)
754 t
.Fatal("encode:", err
)
760 t
.Fatal("decode:", err
)
763 t
.Fatalf("%v != %v", x
, y
)
767 func TestGobEncodePtrError(t
*testing
.T
) {
769 b
:= new(bytes
.Buffer
)
771 err
= enc
.Encode(&err
)
773 t
.Fatal("encode:", err
)
776 err2
:= fmt
.Errorf("foo")
777 err
= dec
.Decode(&err2
)
779 t
.Fatal("decode:", err
)
782 t
.Fatalf("expected nil, got %v", err2
)
786 func TestNetIP(t
*testing
.T
) {
787 // Encoding of net.IP{1,2,3,4} in Go 1.1.
788 enc
:= []byte{0x07, 0x0a, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04}
791 err
:= NewDecoder(bytes
.NewReader(enc
)).Decode(&ip
)
793 t
.Fatalf("decode: %v", err
)
795 if ip
.String() != "1.2.3.4" {
796 t
.Errorf("decoded to %v, want 1.2.3.4", ip
.String())