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 "net" 15 "reflect" 16 "strings" 17 "testing" 18 "time" 19) 20 21// Types that implement the GobEncoder/Decoder interfaces. 22 23type ByteStruct struct { 24 a byte // not an exported field 25} 26 27type StringStruct struct { 28 s string // not an exported field 29} 30 31type ArrayStruct struct { 32 a [8192]byte // not an exported field 33} 34 35type Gobber int 36 37type ValueGobber string // encodes with a value, decodes with a pointer. 38 39type BinaryGobber int 40 41type BinaryValueGobber string 42 43type TextGobber int 44 45type TextValueGobber string 46 47// The relevant methods 48 49func (g *ByteStruct) GobEncode() ([]byte, error) { 50 b := make([]byte, 3) 51 b[0] = g.a 52 b[1] = g.a + 1 53 b[2] = g.a + 2 54 return b, nil 55} 56 57func (g *ByteStruct) GobDecode(data []byte) error { 58 if g == nil { 59 return errors.New("NIL RECEIVER") 60 } 61 // Expect N sequential-valued bytes. 62 if len(data) == 0 { 63 return io.EOF 64 } 65 g.a = data[0] 66 for i, c := range data { 67 if c != g.a+byte(i) { 68 return errors.New("invalid data sequence") 69 } 70 } 71 return nil 72} 73 74func (g *StringStruct) GobEncode() ([]byte, error) { 75 return []byte(g.s), nil 76} 77 78func (g *StringStruct) GobDecode(data []byte) error { 79 // Expect N sequential-valued bytes. 80 if len(data) == 0 { 81 return io.EOF 82 } 83 a := data[0] 84 for i, c := range data { 85 if c != a+byte(i) { 86 return errors.New("invalid data sequence") 87 } 88 } 89 g.s = string(data) 90 return nil 91} 92 93func (a *ArrayStruct) GobEncode() ([]byte, error) { 94 return a.a[:], nil 95} 96 97func (a *ArrayStruct) GobDecode(data []byte) error { 98 if len(data) != len(a.a) { 99 return errors.New("wrong length in array decode") 100 } 101 copy(a.a[:], data) 102 return nil 103} 104 105func (g *Gobber) GobEncode() ([]byte, error) { 106 return []byte(fmt.Sprintf("VALUE=%d", *g)), nil 107} 108 109func (g *Gobber) GobDecode(data []byte) error { 110 _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g)) 111 return err 112} 113 114func (g *BinaryGobber) MarshalBinary() ([]byte, error) { 115 return []byte(fmt.Sprintf("VALUE=%d", *g)), nil 116} 117 118func (g *BinaryGobber) UnmarshalBinary(data []byte) error { 119 _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g)) 120 return err 121} 122 123func (g *TextGobber) MarshalText() ([]byte, error) { 124 return []byte(fmt.Sprintf("VALUE=%d", *g)), nil 125} 126 127func (g *TextGobber) UnmarshalText(data []byte) error { 128 _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g)) 129 return err 130} 131 132func (v ValueGobber) GobEncode() ([]byte, error) { 133 return []byte(fmt.Sprintf("VALUE=%s", v)), nil 134} 135 136func (v *ValueGobber) GobDecode(data []byte) error { 137 _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v)) 138 return err 139} 140 141func (v BinaryValueGobber) MarshalBinary() ([]byte, error) { 142 return []byte(fmt.Sprintf("VALUE=%s", v)), nil 143} 144 145func (v *BinaryValueGobber) UnmarshalBinary(data []byte) error { 146 _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v)) 147 return err 148} 149 150func (v TextValueGobber) MarshalText() ([]byte, error) { 151 return []byte(fmt.Sprintf("VALUE=%s", v)), nil 152} 153 154func (v *TextValueGobber) UnmarshalText(data []byte) error { 155 _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v)) 156 return err 157} 158 159// Structs that include GobEncodable fields. 160 161type GobTest0 struct { 162 X int // guarantee we have something in common with GobTest* 163 G *ByteStruct 164} 165 166type GobTest1 struct { 167 X int // guarantee we have something in common with GobTest* 168 G *StringStruct 169} 170 171type GobTest2 struct { 172 X int // guarantee we have something in common with GobTest* 173 G string // not a GobEncoder - should give us errors 174} 175 176type GobTest3 struct { 177 X int // guarantee we have something in common with GobTest* 178 G *Gobber 179 B *BinaryGobber 180 T *TextGobber 181} 182 183type GobTest4 struct { 184 X int // guarantee we have something in common with GobTest* 185 V ValueGobber 186 BV BinaryValueGobber 187 TV TextValueGobber 188} 189 190type GobTest5 struct { 191 X int // guarantee we have something in common with GobTest* 192 V *ValueGobber 193 BV *BinaryValueGobber 194 TV *TextValueGobber 195} 196 197type GobTest6 struct { 198 X int // guarantee we have something in common with GobTest* 199 V ValueGobber 200 W *ValueGobber 201 BV BinaryValueGobber 202 BW *BinaryValueGobber 203 TV TextValueGobber 204 TW *TextValueGobber 205} 206 207type GobTest7 struct { 208 X int // guarantee we have something in common with GobTest* 209 V *ValueGobber 210 W ValueGobber 211 BV *BinaryValueGobber 212 BW BinaryValueGobber 213 TV *TextValueGobber 214 TW TextValueGobber 215} 216 217type GobTestIgnoreEncoder struct { 218 X int // guarantee we have something in common with GobTest* 219} 220 221type GobTestValueEncDec struct { 222 X int // guarantee we have something in common with GobTest* 223 G StringStruct // not a pointer. 224} 225 226type GobTestIndirectEncDec struct { 227 X int // guarantee we have something in common with GobTest* 228 G ***StringStruct // indirections to the receiver. 229} 230 231type GobTestArrayEncDec struct { 232 X int // guarantee we have something in common with GobTest* 233 A ArrayStruct // not a pointer. 234} 235 236type GobTestIndirectArrayEncDec struct { 237 X int // guarantee we have something in common with GobTest* 238 A ***ArrayStruct // indirections to a large receiver. 239} 240 241func TestGobEncoderField(t *testing.T) { 242 b := new(bytes.Buffer) 243 // First a field that's a structure. 244 enc := NewEncoder(b) 245 err := enc.Encode(GobTest0{17, &ByteStruct{'A'}}) 246 if err != nil { 247 t.Fatal("encode error:", err) 248 } 249 dec := NewDecoder(b) 250 x := new(GobTest0) 251 err = dec.Decode(x) 252 if err != nil { 253 t.Fatal("decode error:", err) 254 } 255 if x.G.a != 'A' { 256 t.Errorf("expected 'A' got %c", x.G.a) 257 } 258 // Now a field that's not a structure. 259 b.Reset() 260 gobber := Gobber(23) 261 bgobber := BinaryGobber(24) 262 tgobber := TextGobber(25) 263 err = enc.Encode(GobTest3{17, &gobber, &bgobber, &tgobber}) 264 if err != nil { 265 t.Fatal("encode error:", err) 266 } 267 y := new(GobTest3) 268 err = dec.Decode(y) 269 if err != nil { 270 t.Fatal("decode error:", err) 271 } 272 if *y.G != 23 || *y.B != 24 || *y.T != 25 { 273 t.Errorf("expected '23 got %d", *y.G) 274 } 275} 276 277// Even though the field is a value, we can still take its address 278// and should be able to call the methods. 279func TestGobEncoderValueField(t *testing.T) { 280 b := new(bytes.Buffer) 281 // First a field that's a structure. 282 enc := NewEncoder(b) 283 err := enc.Encode(&GobTestValueEncDec{17, StringStruct{"HIJKL"}}) 284 if err != nil { 285 t.Fatal("encode error:", err) 286 } 287 dec := NewDecoder(b) 288 x := new(GobTestValueEncDec) 289 err = dec.Decode(x) 290 if err != nil { 291 t.Fatal("decode error:", err) 292 } 293 if x.G.s != "HIJKL" { 294 t.Errorf("expected `HIJKL` got %s", x.G.s) 295 } 296} 297 298// GobEncode/Decode should work even if the value is 299// more indirect than the receiver. 300func TestGobEncoderIndirectField(t *testing.T) { 301 b := new(bytes.Buffer) 302 // First a field that's a structure. 303 enc := NewEncoder(b) 304 s := &StringStruct{"HIJKL"} 305 sp := &s 306 err := enc.Encode(GobTestIndirectEncDec{17, &sp}) 307 if err != nil { 308 t.Fatal("encode error:", err) 309 } 310 dec := NewDecoder(b) 311 x := new(GobTestIndirectEncDec) 312 err = dec.Decode(x) 313 if err != nil { 314 t.Fatal("decode error:", err) 315 } 316 if (***x.G).s != "HIJKL" { 317 t.Errorf("expected `HIJKL` got %s", (***x.G).s) 318 } 319} 320 321// Test with a large field with methods. 322func TestGobEncoderArrayField(t *testing.T) { 323 b := new(bytes.Buffer) 324 enc := NewEncoder(b) 325 var a GobTestArrayEncDec 326 a.X = 17 327 for i := range a.A.a { 328 a.A.a[i] = byte(i) 329 } 330 err := enc.Encode(&a) 331 if err != nil { 332 t.Fatal("encode error:", err) 333 } 334 dec := NewDecoder(b) 335 x := new(GobTestArrayEncDec) 336 err = dec.Decode(x) 337 if err != nil { 338 t.Fatal("decode error:", err) 339 } 340 for i, v := range x.A.a { 341 if v != byte(i) { 342 t.Errorf("expected %x got %x", byte(i), v) 343 break 344 } 345 } 346} 347 348// Test an indirection to a large field with methods. 349func TestGobEncoderIndirectArrayField(t *testing.T) { 350 b := new(bytes.Buffer) 351 enc := NewEncoder(b) 352 var a GobTestIndirectArrayEncDec 353 a.X = 17 354 var array ArrayStruct 355 ap := &array 356 app := &ap 357 a.A = &app 358 for i := range array.a { 359 array.a[i] = byte(i) 360 } 361 err := enc.Encode(a) 362 if err != nil { 363 t.Fatal("encode error:", err) 364 } 365 dec := NewDecoder(b) 366 x := new(GobTestIndirectArrayEncDec) 367 err = dec.Decode(x) 368 if err != nil { 369 t.Fatal("decode error:", err) 370 } 371 for i, v := range (***x.A).a { 372 if v != byte(i) { 373 t.Errorf("expected %x got %x", byte(i), v) 374 break 375 } 376 } 377} 378 379// As long as the fields have the same name and implement the 380// interface, we can cross-connect them. Not sure it's useful 381// and may even be bad but it works and it's hard to prevent 382// without exposing the contents of the object, which would 383// defeat the purpose. 384func TestGobEncoderFieldsOfDifferentType(t *testing.T) { 385 // first, string in field to byte in field 386 b := new(bytes.Buffer) 387 enc := NewEncoder(b) 388 err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}}) 389 if err != nil { 390 t.Fatal("encode error:", err) 391 } 392 dec := NewDecoder(b) 393 x := new(GobTest0) 394 err = dec.Decode(x) 395 if err != nil { 396 t.Fatal("decode error:", err) 397 } 398 if x.G.a != 'A' { 399 t.Errorf("expected 'A' got %c", x.G.a) 400 } 401 // now the other direction, byte in field to string in field 402 b.Reset() 403 err = enc.Encode(GobTest0{17, &ByteStruct{'X'}}) 404 if err != nil { 405 t.Fatal("encode error:", err) 406 } 407 y := new(GobTest1) 408 err = dec.Decode(y) 409 if err != nil { 410 t.Fatal("decode error:", err) 411 } 412 if y.G.s != "XYZ" { 413 t.Fatalf("expected `XYZ` got %q", y.G.s) 414 } 415} 416 417// Test that we can encode a value and decode into a pointer. 418func TestGobEncoderValueEncoder(t *testing.T) { 419 // first, string in field to byte in field 420 b := new(bytes.Buffer) 421 enc := NewEncoder(b) 422 err := enc.Encode(GobTest4{17, ValueGobber("hello"), BinaryValueGobber("Καλημέρα"), TextValueGobber("こんにちは")}) 423 if err != nil { 424 t.Fatal("encode error:", err) 425 } 426 dec := NewDecoder(b) 427 x := new(GobTest5) 428 err = dec.Decode(x) 429 if err != nil { 430 t.Fatal("decode error:", err) 431 } 432 if *x.V != "hello" || *x.BV != "Καλημέρα" || *x.TV != "こんにちは" { 433 t.Errorf("expected `hello` got %s", *x.V) 434 } 435} 436 437// Test that we can use a value then a pointer type of a GobEncoder 438// in the same encoded value. Bug 4647. 439func TestGobEncoderValueThenPointer(t *testing.T) { 440 v := ValueGobber("forty-two") 441 w := ValueGobber("six-by-nine") 442 bv := BinaryValueGobber("1nanocentury") 443 bw := BinaryValueGobber("πseconds") 444 tv := TextValueGobber("gravitationalacceleration") 445 tw := TextValueGobber("π²ft/s²") 446 447 // this was a bug: encoding a GobEncoder by value before a GobEncoder 448 // pointer would cause duplicate type definitions to be sent. 449 450 b := new(bytes.Buffer) 451 enc := NewEncoder(b) 452 if err := enc.Encode(GobTest6{42, v, &w, bv, &bw, tv, &tw}); err != nil { 453 t.Fatal("encode error:", err) 454 } 455 dec := NewDecoder(b) 456 x := new(GobTest6) 457 if err := dec.Decode(x); err != nil { 458 t.Fatal("decode error:", err) 459 } 460 461 if got, want := x.V, v; got != want { 462 t.Errorf("v = %q, want %q", got, want) 463 } 464 if got, want := x.W, w; got == nil { 465 t.Errorf("w = nil, want %q", want) 466 } else if *got != want { 467 t.Errorf("w = %q, want %q", *got, want) 468 } 469 470 if got, want := x.BV, bv; got != want { 471 t.Errorf("bv = %q, want %q", got, want) 472 } 473 if got, want := x.BW, bw; got == nil { 474 t.Errorf("bw = nil, want %q", want) 475 } else if *got != want { 476 t.Errorf("bw = %q, want %q", *got, want) 477 } 478 479 if got, want := x.TV, tv; got != want { 480 t.Errorf("tv = %q, want %q", got, want) 481 } 482 if got, want := x.TW, tw; got == nil { 483 t.Errorf("tw = nil, want %q", want) 484 } else if *got != want { 485 t.Errorf("tw = %q, want %q", *got, want) 486 } 487} 488 489// Test that we can use a pointer then a value type of a GobEncoder 490// in the same encoded value. 491func TestGobEncoderPointerThenValue(t *testing.T) { 492 v := ValueGobber("forty-two") 493 w := ValueGobber("six-by-nine") 494 bv := BinaryValueGobber("1nanocentury") 495 bw := BinaryValueGobber("πseconds") 496 tv := TextValueGobber("gravitationalacceleration") 497 tw := TextValueGobber("π²ft/s²") 498 499 b := new(bytes.Buffer) 500 enc := NewEncoder(b) 501 if err := enc.Encode(GobTest7{42, &v, w, &bv, bw, &tv, tw}); err != nil { 502 t.Fatal("encode error:", err) 503 } 504 dec := NewDecoder(b) 505 x := new(GobTest7) 506 if err := dec.Decode(x); err != nil { 507 t.Fatal("decode error:", err) 508 } 509 510 if got, want := x.V, v; got == nil { 511 t.Errorf("v = nil, want %q", want) 512 } else if *got != want { 513 t.Errorf("v = %q, want %q", *got, want) 514 } 515 if got, want := x.W, w; got != want { 516 t.Errorf("w = %q, want %q", got, want) 517 } 518 519 if got, want := x.BV, bv; got == nil { 520 t.Errorf("bv = nil, want %q", want) 521 } else if *got != want { 522 t.Errorf("bv = %q, want %q", *got, want) 523 } 524 if got, want := x.BW, bw; got != want { 525 t.Errorf("bw = %q, want %q", got, want) 526 } 527 528 if got, want := x.TV, tv; got == nil { 529 t.Errorf("tv = nil, want %q", want) 530 } else if *got != want { 531 t.Errorf("tv = %q, want %q", *got, want) 532 } 533 if got, want := x.TW, tw; got != want { 534 t.Errorf("tw = %q, want %q", got, want) 535 } 536} 537 538func TestGobEncoderFieldTypeError(t *testing.T) { 539 // GobEncoder to non-decoder: error 540 b := new(bytes.Buffer) 541 enc := NewEncoder(b) 542 err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}}) 543 if err != nil { 544 t.Fatal("encode error:", err) 545 } 546 dec := NewDecoder(b) 547 x := &GobTest2{} 548 err = dec.Decode(x) 549 if err == nil { 550 t.Fatal("expected decode error for mismatched fields (encoder to non-decoder)") 551 } 552 if !strings.Contains(err.Error(), "type") { 553 t.Fatal("expected type error; got", err) 554 } 555 // Non-encoder to GobDecoder: error 556 b.Reset() 557 err = enc.Encode(GobTest2{17, "ABC"}) 558 if err != nil { 559 t.Fatal("encode error:", err) 560 } 561 y := &GobTest1{} 562 err = dec.Decode(y) 563 if err == nil { 564 t.Fatal("expected decode error for mismatched fields (non-encoder to decoder)") 565 } 566 if !strings.Contains(err.Error(), "type") { 567 t.Fatal("expected type error; got", err) 568 } 569} 570 571// Even though ByteStruct is a struct, it's treated as a singleton at the top level. 572func TestGobEncoderStructSingleton(t *testing.T) { 573 b := new(bytes.Buffer) 574 enc := NewEncoder(b) 575 err := enc.Encode(&ByteStruct{'A'}) 576 if err != nil { 577 t.Fatal("encode error:", err) 578 } 579 dec := NewDecoder(b) 580 x := new(ByteStruct) 581 err = dec.Decode(x) 582 if err != nil { 583 t.Fatal("decode error:", err) 584 } 585 if x.a != 'A' { 586 t.Errorf("expected 'A' got %c", x.a) 587 } 588} 589 590func TestGobEncoderNonStructSingleton(t *testing.T) { 591 b := new(bytes.Buffer) 592 enc := NewEncoder(b) 593 var g Gobber = 1234 594 err := enc.Encode(&g) 595 if err != nil { 596 t.Fatal("encode error:", err) 597 } 598 dec := NewDecoder(b) 599 var x Gobber 600 err = dec.Decode(&x) 601 if err != nil { 602 t.Fatal("decode error:", err) 603 } 604 if x != 1234 { 605 t.Errorf("expected 1234 got %d", x) 606 } 607} 608 609func TestGobEncoderIgnoreStructField(t *testing.T) { 610 b := new(bytes.Buffer) 611 // First a field that's a structure. 612 enc := NewEncoder(b) 613 err := enc.Encode(GobTest0{17, &ByteStruct{'A'}}) 614 if err != nil { 615 t.Fatal("encode error:", err) 616 } 617 dec := NewDecoder(b) 618 x := new(GobTestIgnoreEncoder) 619 err = dec.Decode(x) 620 if err != nil { 621 t.Fatal("decode error:", err) 622 } 623 if x.X != 17 { 624 t.Errorf("expected 17 got %c", x.X) 625 } 626} 627 628func TestGobEncoderIgnoreNonStructField(t *testing.T) { 629 b := new(bytes.Buffer) 630 // First a field that's a structure. 631 enc := NewEncoder(b) 632 gobber := Gobber(23) 633 bgobber := BinaryGobber(24) 634 tgobber := TextGobber(25) 635 err := enc.Encode(GobTest3{17, &gobber, &bgobber, &tgobber}) 636 if err != nil { 637 t.Fatal("encode error:", err) 638 } 639 dec := NewDecoder(b) 640 x := new(GobTestIgnoreEncoder) 641 err = dec.Decode(x) 642 if err != nil { 643 t.Fatal("decode error:", err) 644 } 645 if x.X != 17 { 646 t.Errorf("expected 17 got %c", x.X) 647 } 648} 649 650func TestGobEncoderIgnoreNilEncoder(t *testing.T) { 651 b := new(bytes.Buffer) 652 // First a field that's a structure. 653 enc := NewEncoder(b) 654 err := enc.Encode(GobTest0{X: 18}) // G is nil 655 if err != nil { 656 t.Fatal("encode error:", err) 657 } 658 dec := NewDecoder(b) 659 x := new(GobTest0) 660 err = dec.Decode(x) 661 if err != nil { 662 t.Fatal("decode error:", err) 663 } 664 if x.X != 18 { 665 t.Errorf("expected x.X = 18, got %v", x.X) 666 } 667 if x.G != nil { 668 t.Errorf("expected x.G = nil, got %v", x.G) 669 } 670} 671 672type gobDecoderBug0 struct { 673 foo, bar string 674} 675 676func (br *gobDecoderBug0) String() string { 677 return br.foo + "-" + br.bar 678} 679 680func (br *gobDecoderBug0) GobEncode() ([]byte, error) { 681 return []byte(br.String()), nil 682} 683 684func (br *gobDecoderBug0) GobDecode(b []byte) error { 685 br.foo = "foo" 686 br.bar = "bar" 687 return nil 688} 689 690// This was a bug: the receiver has a different indirection level 691// than the variable. 692func TestGobEncoderExtraIndirect(t *testing.T) { 693 gdb := &gobDecoderBug0{"foo", "bar"} 694 buf := new(bytes.Buffer) 695 e := NewEncoder(buf) 696 if err := e.Encode(gdb); err != nil { 697 t.Fatalf("encode: %v", err) 698 } 699 d := NewDecoder(buf) 700 var got *gobDecoderBug0 701 if err := d.Decode(&got); err != nil { 702 t.Fatalf("decode: %v", err) 703 } 704 if got.foo != gdb.foo || got.bar != gdb.bar { 705 t.Errorf("got = %q, want %q", got, gdb) 706 } 707} 708 709// Another bug: this caused a crash with the new Go1 Time type. 710// We throw in a gob-encoding array, to test another case of isZero, 711// and a struct containing a nil interface, to test a third. 712type isZeroBug struct { 713 T time.Time 714 S string 715 I int 716 A isZeroBugArray 717 F isZeroBugInterface 718} 719 720type isZeroBugArray [2]uint8 721 722// Receiver is value, not pointer, to test isZero of array. 723func (a isZeroBugArray) GobEncode() (b []byte, e error) { 724 b = append(b, a[:]...) 725 return b, nil 726} 727 728func (a *isZeroBugArray) GobDecode(data []byte) error { 729 if len(data) != len(a) { 730 return io.EOF 731 } 732 a[0] = data[0] 733 a[1] = data[1] 734 return nil 735} 736 737type isZeroBugInterface struct { 738 I any 739} 740 741func (i isZeroBugInterface) GobEncode() (b []byte, e error) { 742 return []byte{}, nil 743} 744 745func (i *isZeroBugInterface) GobDecode(data []byte) error { 746 return nil 747} 748 749func TestGobEncodeIsZero(t *testing.T) { 750 x := isZeroBug{time.Unix(1e9, 0), "hello", -55, isZeroBugArray{1, 2}, isZeroBugInterface{}} 751 b := new(bytes.Buffer) 752 enc := NewEncoder(b) 753 err := enc.Encode(x) 754 if err != nil { 755 t.Fatal("encode:", err) 756 } 757 var y isZeroBug 758 dec := NewDecoder(b) 759 err = dec.Decode(&y) 760 if err != nil { 761 t.Fatal("decode:", err) 762 } 763 if x != y { 764 t.Fatalf("%v != %v", x, y) 765 } 766} 767 768func TestGobEncodePtrError(t *testing.T) { 769 var err error 770 b := new(bytes.Buffer) 771 enc := NewEncoder(b) 772 err = enc.Encode(&err) 773 if err != nil { 774 t.Fatal("encode:", err) 775 } 776 dec := NewDecoder(b) 777 err2 := fmt.Errorf("foo") 778 err = dec.Decode(&err2) 779 if err != nil { 780 t.Fatal("decode:", err) 781 } 782 if err2 != nil { 783 t.Fatalf("expected nil, got %v", err2) 784 } 785} 786 787func TestNetIP(t *testing.T) { 788 // Encoding of net.IP{1,2,3,4} in Go 1.1. 789 enc := []byte{0x07, 0x0a, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04} 790 791 var ip net.IP 792 err := NewDecoder(bytes.NewReader(enc)).Decode(&ip) 793 if err != nil { 794 t.Fatalf("decode: %v", err) 795 } 796 if ip.String() != "1.2.3.4" { 797 t.Errorf("decoded to %v, want 1.2.3.4", ip.String()) 798 } 799} 800 801func TestIgnoreDepthLimit(t *testing.T) { 802 // We don't test the actual depth limit because it requires building an 803 // extremely large message, which takes quite a while. 804 oldNestingDepth := maxIgnoreNestingDepth 805 maxIgnoreNestingDepth = 100 806 defer func() { maxIgnoreNestingDepth = oldNestingDepth }() 807 b := new(bytes.Buffer) 808 enc := NewEncoder(b) 809 810 // Nested slice 811 typ := reflect.TypeFor[int]() 812 nested := reflect.ArrayOf(1, typ) 813 for i := 0; i < 100; i++ { 814 nested = reflect.ArrayOf(1, nested) 815 } 816 badStruct := reflect.New(reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}})) 817 enc.Encode(badStruct.Interface()) 818 dec := NewDecoder(b) 819 var output struct{ Hello int } 820 expectedErr := "invalid nesting depth" 821 if err := dec.Decode(&output); err == nil || err.Error() != expectedErr { 822 t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err) 823 } 824 825 // Nested struct 826 nested = reflect.StructOf([]reflect.StructField{{Name: "F", Type: typ}}) 827 for i := 0; i < 100; i++ { 828 nested = reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}}) 829 } 830 badStruct = reflect.New(reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}})) 831 enc.Encode(badStruct.Interface()) 832 dec = NewDecoder(b) 833 if err := dec.Decode(&output); err == nil || err.Error() != expectedErr { 834 t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err) 835 } 836} 837