diff options
Diffstat (limited to 'src/pkg/encoding/gob/gobencdec_test.go')
-rw-r--r-- | src/pkg/encoding/gob/gobencdec_test.go | 797 |
1 files changed, 0 insertions, 797 deletions
diff --git a/src/pkg/encoding/gob/gobencdec_test.go b/src/pkg/encoding/gob/gobencdec_test.go deleted file mode 100644 index 157b7723a..000000000 --- a/src/pkg/encoding/gob/gobencdec_test.go +++ /dev/null @@ -1,797 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file contains tests of the GobEncoder/GobDecoder support. - -package gob - -import ( - "bytes" - "errors" - "fmt" - "io" - "net" - "strings" - "testing" - "time" -) - -// Types that implement the GobEncoder/Decoder interfaces. - -type ByteStruct struct { - a byte // not an exported field -} - -type StringStruct struct { - s string // not an exported field -} - -type ArrayStruct struct { - a [8192]byte // not an exported field -} - -type Gobber int - -type ValueGobber string // encodes with a value, decodes with a pointer. - -type BinaryGobber int - -type BinaryValueGobber string - -type TextGobber int - -type TextValueGobber string - -// The relevant methods - -func (g *ByteStruct) GobEncode() ([]byte, error) { - b := make([]byte, 3) - b[0] = g.a - b[1] = g.a + 1 - b[2] = g.a + 2 - return b, nil -} - -func (g *ByteStruct) GobDecode(data []byte) error { - if g == nil { - return errors.New("NIL RECEIVER") - } - // Expect N sequential-valued bytes. - if len(data) == 0 { - return io.EOF - } - g.a = data[0] - for i, c := range data { - if c != g.a+byte(i) { - return errors.New("invalid data sequence") - } - } - return nil -} - -func (g *StringStruct) GobEncode() ([]byte, error) { - return []byte(g.s), nil -} - -func (g *StringStruct) GobDecode(data []byte) error { - // Expect N sequential-valued bytes. - if len(data) == 0 { - return io.EOF - } - a := data[0] - for i, c := range data { - if c != a+byte(i) { - return errors.New("invalid data sequence") - } - } - g.s = string(data) - return nil -} - -func (a *ArrayStruct) GobEncode() ([]byte, error) { - return a.a[:], nil -} - -func (a *ArrayStruct) GobDecode(data []byte) error { - if len(data) != len(a.a) { - return errors.New("wrong length in array decode") - } - copy(a.a[:], data) - return nil -} - -func (g *Gobber) GobEncode() ([]byte, error) { - return []byte(fmt.Sprintf("VALUE=%d", *g)), nil -} - -func (g *Gobber) GobDecode(data []byte) error { - _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g)) - return err -} - -func (g *BinaryGobber) MarshalBinary() ([]byte, error) { - return []byte(fmt.Sprintf("VALUE=%d", *g)), nil -} - -func (g *BinaryGobber) UnmarshalBinary(data []byte) error { - _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g)) - return err -} - -func (g *TextGobber) MarshalText() ([]byte, error) { - return []byte(fmt.Sprintf("VALUE=%d", *g)), nil -} - -func (g *TextGobber) UnmarshalText(data []byte) error { - _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g)) - return err -} - -func (v ValueGobber) GobEncode() ([]byte, error) { - return []byte(fmt.Sprintf("VALUE=%s", v)), nil -} - -func (v *ValueGobber) GobDecode(data []byte) error { - _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v)) - return err -} - -func (v BinaryValueGobber) MarshalBinary() ([]byte, error) { - return []byte(fmt.Sprintf("VALUE=%s", v)), nil -} - -func (v *BinaryValueGobber) UnmarshalBinary(data []byte) error { - _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v)) - return err -} - -func (v TextValueGobber) MarshalText() ([]byte, error) { - return []byte(fmt.Sprintf("VALUE=%s", v)), nil -} - -func (v *TextValueGobber) UnmarshalText(data []byte) error { - _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v)) - return err -} - -// Structs that include GobEncodable fields. - -type GobTest0 struct { - X int // guarantee we have something in common with GobTest* - G *ByteStruct -} - -type GobTest1 struct { - X int // guarantee we have something in common with GobTest* - G *StringStruct -} - -type GobTest2 struct { - X int // guarantee we have something in common with GobTest* - G string // not a GobEncoder - should give us errors -} - -type GobTest3 struct { - X int // guarantee we have something in common with GobTest* - G *Gobber - B *BinaryGobber - T *TextGobber -} - -type GobTest4 struct { - X int // guarantee we have something in common with GobTest* - V ValueGobber - BV BinaryValueGobber - TV TextValueGobber -} - -type GobTest5 struct { - X int // guarantee we have something in common with GobTest* - V *ValueGobber - BV *BinaryValueGobber - TV *TextValueGobber -} - -type GobTest6 struct { - X int // guarantee we have something in common with GobTest* - V ValueGobber - W *ValueGobber - BV BinaryValueGobber - BW *BinaryValueGobber - TV TextValueGobber - TW *TextValueGobber -} - -type GobTest7 struct { - X int // guarantee we have something in common with GobTest* - V *ValueGobber - W ValueGobber - BV *BinaryValueGobber - BW BinaryValueGobber - TV *TextValueGobber - TW TextValueGobber -} - -type GobTestIgnoreEncoder struct { - X int // guarantee we have something in common with GobTest* -} - -type GobTestValueEncDec struct { - X int // guarantee we have something in common with GobTest* - G StringStruct // not a pointer. -} - -type GobTestIndirectEncDec struct { - X int // guarantee we have something in common with GobTest* - G ***StringStruct // indirections to the receiver. -} - -type GobTestArrayEncDec struct { - X int // guarantee we have something in common with GobTest* - A ArrayStruct // not a pointer. -} - -type GobTestIndirectArrayEncDec struct { - X int // guarantee we have something in common with GobTest* - A ***ArrayStruct // indirections to a large receiver. -} - -func TestGobEncoderField(t *testing.T) { - b := new(bytes.Buffer) - // First a field that's a structure. - enc := NewEncoder(b) - err := enc.Encode(GobTest0{17, &ByteStruct{'A'}}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTest0) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if x.G.a != 'A' { - t.Errorf("expected 'A' got %c", x.G.a) - } - // Now a field that's not a structure. - b.Reset() - gobber := Gobber(23) - bgobber := BinaryGobber(24) - tgobber := TextGobber(25) - err = enc.Encode(GobTest3{17, &gobber, &bgobber, &tgobber}) - if err != nil { - t.Fatal("encode error:", err) - } - y := new(GobTest3) - err = dec.Decode(y) - if err != nil { - t.Fatal("decode error:", err) - } - if *y.G != 23 || *y.B != 24 || *y.T != 25 { - t.Errorf("expected '23 got %d", *y.G) - } -} - -// Even though the field is a value, we can still take its address -// and should be able to call the methods. -func TestGobEncoderValueField(t *testing.T) { - b := new(bytes.Buffer) - // First a field that's a structure. - enc := NewEncoder(b) - err := enc.Encode(GobTestValueEncDec{17, StringStruct{"HIJKL"}}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTestValueEncDec) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if x.G.s != "HIJKL" { - t.Errorf("expected `HIJKL` got %s", x.G.s) - } -} - -// GobEncode/Decode should work even if the value is -// more indirect than the receiver. -func TestGobEncoderIndirectField(t *testing.T) { - b := new(bytes.Buffer) - // First a field that's a structure. - enc := NewEncoder(b) - s := &StringStruct{"HIJKL"} - sp := &s - err := enc.Encode(GobTestIndirectEncDec{17, &sp}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTestIndirectEncDec) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if (***x.G).s != "HIJKL" { - t.Errorf("expected `HIJKL` got %s", (***x.G).s) - } -} - -// Test with a large field with methods. -func TestGobEncoderArrayField(t *testing.T) { - b := new(bytes.Buffer) - enc := NewEncoder(b) - var a GobTestArrayEncDec - a.X = 17 - for i := range a.A.a { - a.A.a[i] = byte(i) - } - err := enc.Encode(a) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTestArrayEncDec) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - for i, v := range x.A.a { - if v != byte(i) { - t.Errorf("expected %x got %x", byte(i), v) - break - } - } -} - -// Test an indirection to a large field with methods. -func TestGobEncoderIndirectArrayField(t *testing.T) { - b := new(bytes.Buffer) - enc := NewEncoder(b) - var a GobTestIndirectArrayEncDec - a.X = 17 - var array ArrayStruct - ap := &array - app := &ap - a.A = &app - for i := range array.a { - array.a[i] = byte(i) - } - err := enc.Encode(a) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTestIndirectArrayEncDec) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - for i, v := range (***x.A).a { - if v != byte(i) { - t.Errorf("expected %x got %x", byte(i), v) - break - } - } -} - -// As long as the fields have the same name and implement the -// interface, we can cross-connect them. Not sure it's useful -// and may even be bad but it works and it's hard to prevent -// without exposing the contents of the object, which would -// defeat the purpose. -func TestGobEncoderFieldsOfDifferentType(t *testing.T) { - // first, string in field to byte in field - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTest0) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if x.G.a != 'A' { - t.Errorf("expected 'A' got %c", x.G.a) - } - // now the other direction, byte in field to string in field - b.Reset() - err = enc.Encode(GobTest0{17, &ByteStruct{'X'}}) - if err != nil { - t.Fatal("encode error:", err) - } - y := new(GobTest1) - err = dec.Decode(y) - if err != nil { - t.Fatal("decode error:", err) - } - if y.G.s != "XYZ" { - t.Fatalf("expected `XYZ` got %q", y.G.s) - } -} - -// Test that we can encode a value and decode into a pointer. -func TestGobEncoderValueEncoder(t *testing.T) { - // first, string in field to byte in field - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(GobTest4{17, ValueGobber("hello"), BinaryValueGobber("Καλημέρα"), TextValueGobber("こんにちは")}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTest5) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if *x.V != "hello" || *x.BV != "Καλημέρα" || *x.TV != "こんにちは" { - t.Errorf("expected `hello` got %s", *x.V) - } -} - -// Test that we can use a value then a pointer type of a GobEncoder -// in the same encoded value. Bug 4647. -func TestGobEncoderValueThenPointer(t *testing.T) { - v := ValueGobber("forty-two") - w := ValueGobber("six-by-nine") - bv := BinaryValueGobber("1nanocentury") - bw := BinaryValueGobber("πseconds") - tv := TextValueGobber("gravitationalacceleration") - tw := TextValueGobber("π²ft/s²") - - // this was a bug: encoding a GobEncoder by value before a GobEncoder - // pointer would cause duplicate type definitions to be sent. - - b := new(bytes.Buffer) - enc := NewEncoder(b) - if err := enc.Encode(GobTest6{42, v, &w, bv, &bw, tv, &tw}); err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTest6) - if err := dec.Decode(x); err != nil { - t.Fatal("decode error:", err) - } - - if got, want := x.V, v; got != want { - t.Errorf("v = %q, want %q", got, want) - } - if got, want := x.W, w; got == nil { - t.Errorf("w = nil, want %q", want) - } else if *got != want { - t.Errorf("w = %q, want %q", *got, want) - } - - if got, want := x.BV, bv; got != want { - t.Errorf("bv = %q, want %q", got, want) - } - if got, want := x.BW, bw; got == nil { - t.Errorf("bw = nil, want %q", want) - } else if *got != want { - t.Errorf("bw = %q, want %q", *got, want) - } - - if got, want := x.TV, tv; got != want { - t.Errorf("tv = %q, want %q", got, want) - } - if got, want := x.TW, tw; got == nil { - t.Errorf("tw = nil, want %q", want) - } else if *got != want { - t.Errorf("tw = %q, want %q", *got, want) - } -} - -// Test that we can use a pointer then a value type of a GobEncoder -// in the same encoded value. -func TestGobEncoderPointerThenValue(t *testing.T) { - v := ValueGobber("forty-two") - w := ValueGobber("six-by-nine") - bv := BinaryValueGobber("1nanocentury") - bw := BinaryValueGobber("πseconds") - tv := TextValueGobber("gravitationalacceleration") - tw := TextValueGobber("π²ft/s²") - - b := new(bytes.Buffer) - enc := NewEncoder(b) - if err := enc.Encode(GobTest7{42, &v, w, &bv, bw, &tv, tw}); err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTest7) - if err := dec.Decode(x); err != nil { - t.Fatal("decode error:", err) - } - - if got, want := x.V, v; got == nil { - t.Errorf("v = nil, want %q", want) - } else if *got != want { - t.Errorf("v = %q, want %q", *got, want) - } - if got, want := x.W, w; got != want { - t.Errorf("w = %q, want %q", got, want) - } - - if got, want := x.BV, bv; got == nil { - t.Errorf("bv = nil, want %q", want) - } else if *got != want { - t.Errorf("bv = %q, want %q", *got, want) - } - if got, want := x.BW, bw; got != want { - t.Errorf("bw = %q, want %q", got, want) - } - - if got, want := x.TV, tv; got == nil { - t.Errorf("tv = nil, want %q", want) - } else if *got != want { - t.Errorf("tv = %q, want %q", *got, want) - } - if got, want := x.TW, tw; got != want { - t.Errorf("tw = %q, want %q", got, want) - } -} - -func TestGobEncoderFieldTypeError(t *testing.T) { - // GobEncoder to non-decoder: error - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := &GobTest2{} - err = dec.Decode(x) - if err == nil { - t.Fatal("expected decode error for mismatched fields (encoder to non-decoder)") - } - if strings.Index(err.Error(), "type") < 0 { - t.Fatal("expected type error; got", err) - } - // Non-encoder to GobDecoder: error - b.Reset() - err = enc.Encode(GobTest2{17, "ABC"}) - if err != nil { - t.Fatal("encode error:", err) - } - y := &GobTest1{} - err = dec.Decode(y) - if err == nil { - t.Fatal("expected decode error for mismatched fields (non-encoder to decoder)") - } - if strings.Index(err.Error(), "type") < 0 { - t.Fatal("expected type error; got", err) - } -} - -// Even though ByteStruct is a struct, it's treated as a singleton at the top level. -func TestGobEncoderStructSingleton(t *testing.T) { - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(&ByteStruct{'A'}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(ByteStruct) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if x.a != 'A' { - t.Errorf("expected 'A' got %c", x.a) - } -} - -func TestGobEncoderNonStructSingleton(t *testing.T) { - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(Gobber(1234)) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - var x Gobber - err = dec.Decode(&x) - if err != nil { - t.Fatal("decode error:", err) - } - if x != 1234 { - t.Errorf("expected 1234 got %d", x) - } -} - -func TestGobEncoderIgnoreStructField(t *testing.T) { - b := new(bytes.Buffer) - // First a field that's a structure. - enc := NewEncoder(b) - err := enc.Encode(GobTest0{17, &ByteStruct{'A'}}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTestIgnoreEncoder) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if x.X != 17 { - t.Errorf("expected 17 got %c", x.X) - } -} - -func TestGobEncoderIgnoreNonStructField(t *testing.T) { - b := new(bytes.Buffer) - // First a field that's a structure. - enc := NewEncoder(b) - gobber := Gobber(23) - bgobber := BinaryGobber(24) - tgobber := TextGobber(25) - err := enc.Encode(GobTest3{17, &gobber, &bgobber, &tgobber}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTestIgnoreEncoder) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if x.X != 17 { - t.Errorf("expected 17 got %c", x.X) - } -} - -func TestGobEncoderIgnoreNilEncoder(t *testing.T) { - b := new(bytes.Buffer) - // First a field that's a structure. - enc := NewEncoder(b) - err := enc.Encode(GobTest0{X: 18}) // G is nil - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTest0) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if x.X != 18 { - t.Errorf("expected x.X = 18, got %v", x.X) - } - if x.G != nil { - t.Errorf("expected x.G = nil, got %v", x.G) - } -} - -type gobDecoderBug0 struct { - foo, bar string -} - -func (br *gobDecoderBug0) String() string { - return br.foo + "-" + br.bar -} - -func (br *gobDecoderBug0) GobEncode() ([]byte, error) { - return []byte(br.String()), nil -} - -func (br *gobDecoderBug0) GobDecode(b []byte) error { - br.foo = "foo" - br.bar = "bar" - return nil -} - -// This was a bug: the receiver has a different indirection level -// than the variable. -func TestGobEncoderExtraIndirect(t *testing.T) { - gdb := &gobDecoderBug0{"foo", "bar"} - buf := new(bytes.Buffer) - e := NewEncoder(buf) - if err := e.Encode(gdb); err != nil { - t.Fatalf("encode: %v", err) - } - d := NewDecoder(buf) - var got *gobDecoderBug0 - if err := d.Decode(&got); err != nil { - t.Fatalf("decode: %v", err) - } - if got.foo != gdb.foo || got.bar != gdb.bar { - t.Errorf("got = %q, want %q", got, gdb) - } -} - -// Another bug: this caused a crash with the new Go1 Time type. -// We throw in a gob-encoding array, to test another case of isZero, -// and a struct containing an nil interface, to test a third. -type isZeroBug struct { - T time.Time - S string - I int - A isZeroBugArray - F isZeroBugInterface -} - -type isZeroBugArray [2]uint8 - -// Receiver is value, not pointer, to test isZero of array. -func (a isZeroBugArray) GobEncode() (b []byte, e error) { - b = append(b, a[:]...) - return b, nil -} - -func (a *isZeroBugArray) GobDecode(data []byte) error { - if len(data) != len(a) { - return io.EOF - } - a[0] = data[0] - a[1] = data[1] - return nil -} - -type isZeroBugInterface struct { - I interface{} -} - -func (i isZeroBugInterface) GobEncode() (b []byte, e error) { - return []byte{}, nil -} - -func (i *isZeroBugInterface) GobDecode(data []byte) error { - return nil -} - -func TestGobEncodeIsZero(t *testing.T) { - x := isZeroBug{time.Now(), "hello", -55, isZeroBugArray{1, 2}, isZeroBugInterface{}} - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(x) - if err != nil { - t.Fatal("encode:", err) - } - var y isZeroBug - dec := NewDecoder(b) - err = dec.Decode(&y) - if err != nil { - t.Fatal("decode:", err) - } - if x != y { - t.Fatalf("%v != %v", x, y) - } -} - -func TestGobEncodePtrError(t *testing.T) { - var err error - b := new(bytes.Buffer) - enc := NewEncoder(b) - err = enc.Encode(&err) - if err != nil { - t.Fatal("encode:", err) - } - dec := NewDecoder(b) - err2 := fmt.Errorf("foo") - err = dec.Decode(&err2) - if err != nil { - t.Fatal("decode:", err) - } - if err2 != nil { - t.Fatalf("expected nil, got %v", err2) - } -} - -func TestNetIP(t *testing.T) { - // Encoding of net.IP{1,2,3,4} in Go 1.1. - enc := []byte{0x07, 0x0a, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04} - - var ip net.IP - err := NewDecoder(bytes.NewReader(enc)).Decode(&ip) - if err != nil { - t.Fatalf("decode: %v", err) - } - if ip.String() != "1.2.3.4" { - t.Errorf("decoded to %v, want 1.2.3.4", ip.String()) - } -} |