1 // Copyright 20011 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.
19 // Types that implement the GobEncoder/Decoder interfaces.
21 type ByteStruct struct {
22 a byte // not an exported field
25 type StringStruct struct {
26 s string // not an exported field
29 type ArrayStruct struct {
30 a [8192]byte // not an exported field
35 type ValueGobber string // encodes with a value, decodes with a pointer.
37 // The relevant methods
39 func (g *ByteStruct) GobEncode() ([]byte, error) {
47 func (g *ByteStruct) GobDecode(data []byte) error {
49 return errors.New("NIL RECEIVER")
51 // Expect N sequential-valued bytes.
56 for i, c := range data {
58 return errors.New("invalid data sequence")
64 func (g *StringStruct) GobEncode() ([]byte, error) {
65 return []byte(g.s), nil
68 func (g *StringStruct) GobDecode(data []byte) error {
69 // Expect N sequential-valued bytes.
74 for i, c := range data {
76 return errors.New("invalid data sequence")
83 func (a *ArrayStruct) GobEncode() ([]byte, error) {
87 func (a *ArrayStruct) GobDecode(data []byte) error {
88 if len(data) != len(a.a) {
89 return errors.New("wrong length in array decode")
95 func (g *Gobber) GobEncode() ([]byte, error) {
96 return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
99 func (g *Gobber) GobDecode(data []byte) error {
100 _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
104 func (v ValueGobber) GobEncode() ([]byte, error) {
105 return []byte(fmt.Sprintf("VALUE=%s", v)), nil
108 func (v *ValueGobber) GobDecode(data []byte) error {
109 _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
113 // Structs that include GobEncodable fields.
115 type GobTest0 struct {
116 X int // guarantee we have something in common with GobTest*
120 type GobTest1 struct {
121 X int // guarantee we have something in common with GobTest*
125 type GobTest2 struct {
126 X int // guarantee we have something in common with GobTest*
127 G string // not a GobEncoder - should give us errors
130 type GobTest3 struct {
131 X int // guarantee we have something in common with GobTest*
135 type GobTest4 struct {
136 X int // guarantee we have something in common with GobTest*
140 type GobTest5 struct {
141 X int // guarantee we have something in common with GobTest*
145 type GobTestIgnoreEncoder struct {
146 X int // guarantee we have something in common with GobTest*
149 type GobTestValueEncDec struct {
150 X int // guarantee we have something in common with GobTest*
151 G StringStruct // not a pointer.
154 type GobTestIndirectEncDec struct {
155 X int // guarantee we have something in common with GobTest*
156 G ***StringStruct // indirections to the receiver.
159 type GobTestArrayEncDec struct {
160 X int // guarantee we have something in common with GobTest*
161 A ArrayStruct // not a pointer.
164 type GobTestIndirectArrayEncDec struct {
165 X int // guarantee we have something in common with GobTest*
166 A ***ArrayStruct // indirections to a large receiver.
169 func TestGobEncoderField(t *testing.T) {
170 b := new(bytes.Buffer)
171 // First a field that's a structure.
173 err := enc.Encode(GobTest0{17, &ByteStruct{'A'}})
175 t.Fatal("encode error:", err)
181 t.Fatal("decode error:", err)
184 t.Errorf("expected 'A' got %c", x.G.a)
186 // Now a field that's not a structure.
189 err = enc.Encode(GobTest3{17, &gobber})
191 t.Fatal("encode error:", err)
196 t.Fatal("decode error:", err)
199 t.Errorf("expected '23 got %d", *y.G)
203 // Even though the field is a value, we can still take its address
204 // and should be able to call the methods.
205 func TestGobEncoderValueField(t *testing.T) {
206 b := new(bytes.Buffer)
207 // First a field that's a structure.
209 err := enc.Encode(GobTestValueEncDec{17, StringStruct{"HIJKL"}})
211 t.Fatal("encode error:", err)
214 x := new(GobTestValueEncDec)
217 t.Fatal("decode error:", err)
219 if x.G.s != "HIJKL" {
220 t.Errorf("expected `HIJKL` got %s", x.G.s)
224 // GobEncode/Decode should work even if the value is
225 // more indirect than the receiver.
226 func TestGobEncoderIndirectField(t *testing.T) {
227 b := new(bytes.Buffer)
228 // First a field that's a structure.
230 s := &StringStruct{"HIJKL"}
232 err := enc.Encode(GobTestIndirectEncDec{17, &sp})
234 t.Fatal("encode error:", err)
237 x := new(GobTestIndirectEncDec)
240 t.Fatal("decode error:", err)
242 if (***x.G).s != "HIJKL" {
243 t.Errorf("expected `HIJKL` got %s", (***x.G).s)
247 // Test with a large field with methods.
248 func TestGobEncoderArrayField(t *testing.T) {
249 b := new(bytes.Buffer)
251 var a GobTestArrayEncDec
253 for i := range a.A.a {
258 t.Fatal("encode error:", err)
261 x := new(GobTestArrayEncDec)
264 t.Fatal("decode error:", err)
266 for i, v := range x.A.a {
268 t.Errorf("expected %x got %x", byte(i), v)
274 // Test an indirection to a large field with methods.
275 func TestGobEncoderIndirectArrayField(t *testing.T) {
276 b := new(bytes.Buffer)
278 var a GobTestIndirectArrayEncDec
280 var array ArrayStruct
284 for i := range array.a {
289 t.Fatal("encode error:", err)
292 x := new(GobTestIndirectArrayEncDec)
295 t.Fatal("decode error:", err)
297 for i, v := range (***x.A).a {
299 t.Errorf("expected %x got %x", byte(i), v)
305 // As long as the fields have the same name and implement the
306 // interface, we can cross-connect them. Not sure it's useful
307 // and may even be bad but it works and it's hard to prevent
308 // without exposing the contents of the object, which would
309 // defeat the purpose.
310 func TestGobEncoderFieldsOfDifferentType(t *testing.T) {
311 // first, string in field to byte in field
312 b := new(bytes.Buffer)
314 err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}})
316 t.Fatal("encode error:", err)
322 t.Fatal("decode error:", err)
325 t.Errorf("expected 'A' got %c", x.G.a)
327 // now the other direction, byte in field to string in field
329 err = enc.Encode(GobTest0{17, &ByteStruct{'X'}})
331 t.Fatal("encode error:", err)
336 t.Fatal("decode error:", err)
339 t.Fatalf("expected `XYZ` got %c", y.G.s)
343 // Test that we can encode a value and decode into a pointer.
344 func TestGobEncoderValueEncoder(t *testing.T) {
345 // first, string in field to byte in field
346 b := new(bytes.Buffer)
348 err := enc.Encode(GobTest4{17, ValueGobber("hello")})
350 t.Fatal("encode error:", err)
356 t.Fatal("decode error:", err)
359 t.Errorf("expected `hello` got %s", x.V)
363 func TestGobEncoderFieldTypeError(t *testing.T) {
364 // GobEncoder to non-decoder: error
365 b := new(bytes.Buffer)
367 err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}})
369 t.Fatal("encode error:", err)
375 t.Fatal("expected decode error for mismatched fields (encoder to non-decoder)")
377 if strings.Index(err.Error(), "type") < 0 {
378 t.Fatal("expected type error; got", err)
380 // Non-encoder to GobDecoder: error
382 err = enc.Encode(GobTest2{17, "ABC"})
384 t.Fatal("encode error:", err)
389 t.Fatal("expected decode error for mismatched fields (non-encoder to decoder)")
391 if strings.Index(err.Error(), "type") < 0 {
392 t.Fatal("expected type error; got", err)
396 // Even though ByteStruct is a struct, it's treated as a singleton at the top level.
397 func TestGobEncoderStructSingleton(t *testing.T) {
398 b := new(bytes.Buffer)
400 err := enc.Encode(&ByteStruct{'A'})
402 t.Fatal("encode error:", err)
408 t.Fatal("decode error:", err)
411 t.Errorf("expected 'A' got %c", x.a)
415 func TestGobEncoderNonStructSingleton(t *testing.T) {
416 b := new(bytes.Buffer)
418 err := enc.Encode(Gobber(1234))
420 t.Fatal("encode error:", err)
426 t.Fatal("decode error:", err)
429 t.Errorf("expected 1234 got %d", x)
433 func TestGobEncoderIgnoreStructField(t *testing.T) {
434 b := new(bytes.Buffer)
435 // First a field that's a structure.
437 err := enc.Encode(GobTest0{17, &ByteStruct{'A'}})
439 t.Fatal("encode error:", err)
442 x := new(GobTestIgnoreEncoder)
445 t.Fatal("decode error:", err)
448 t.Errorf("expected 17 got %c", x.X)
452 func TestGobEncoderIgnoreNonStructField(t *testing.T) {
453 b := new(bytes.Buffer)
454 // First a field that's a structure.
457 err := enc.Encode(GobTest3{17, &gobber})
459 t.Fatal("encode error:", err)
462 x := new(GobTestIgnoreEncoder)
465 t.Fatal("decode error:", err)
468 t.Errorf("expected 17 got %c", x.X)
472 func TestGobEncoderIgnoreNilEncoder(t *testing.T) {
473 b := new(bytes.Buffer)
474 // First a field that's a structure.
476 err := enc.Encode(GobTest0{X: 18}) // G is nil
478 t.Fatal("encode error:", err)
484 t.Fatal("decode error:", err)
487 t.Errorf("expected x.X = 18, got %v", x.X)
490 t.Errorf("expected x.G = nil, got %v", x.G)
494 type gobDecoderBug0 struct {
498 func (br *gobDecoderBug0) String() string {
499 return br.foo + "-" + br.bar
502 func (br *gobDecoderBug0) GobEncode() ([]byte, error) {
503 return []byte(br.String()), nil
506 func (br *gobDecoderBug0) GobDecode(b []byte) error {
512 // This was a bug: the receiver has a different indirection level
513 // than the variable.
514 func TestGobEncoderExtraIndirect(t *testing.T) {
515 gdb := &gobDecoderBug0{"foo", "bar"}
516 buf := new(bytes.Buffer)
518 if err := e.Encode(gdb); err != nil {
519 t.Fatalf("encode: %v", err)
522 var got *gobDecoderBug0
523 if err := d.Decode(&got); err != nil {
524 t.Fatalf("decode: %v", err)
526 if got.foo != gdb.foo || got.bar != gdb.bar {
527 t.Errorf("got = %q, want %q", got, gdb)
531 // Another bug: this caused a crash with the new Go1 Time type.
532 // We throw in a gob-encoding array, to test another case of isZero
534 type isZeroBug struct {
541 type isZeroBugArray [2]uint8
543 // Receiver is value, not pointer, to test isZero of array.
544 func (a isZeroBugArray) GobEncode() (b []byte, e error) {
545 b = append(b, a[:]...)
549 func (a *isZeroBugArray) GobDecode(data []byte) error {
550 if len(data) != len(a) {
558 func TestGobEncodeIsZero(t *testing.T) {
559 x := isZeroBug{time.Now(), "hello", -55, isZeroBugArray{1, 2}}
560 b := new(bytes.Buffer)
564 t.Fatal("encode:", err)
570 t.Fatal("decode:", err)
573 t.Fatalf("%v != %v", x, y)
577 func TestGobEncodePtrError(t *testing.T) {
579 b := new(bytes.Buffer)
581 err = enc.Encode(&err)
583 t.Fatal("encode:", err)
586 err2 := fmt.Errorf("foo")
587 err = dec.Decode(&err2)
589 t.Fatal("decode:", err)
592 t.Fatalf("expected nil, got %v", err2)