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