URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [encoding/] [gob/] [gobencdec_test.go] - Rev 747
Compare with Previous | Blame | View Log
// Copyright 20011 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 gobimport ("bytes""errors""fmt""io""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 inttype ValueGobber string // encodes with a value, decodes with a pointer.// The relevant methodsfunc (g *ByteStruct) GobEncode() ([]byte, error) {b := make([]byte, 3)b[0] = g.ab[1] = g.a + 1b[2] = g.a + 2return 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 (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}// 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}type GobTest4 struct {X int // guarantee we have something in common with GobTest*V ValueGobber}type GobTest5 struct {X int // guarantee we have something in common with GobTest*V *ValueGobber}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)err = enc.Encode(GobTest3{17, &gobber})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 {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 := &serr := 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 GobTestArrayEncDeca.X = 17for 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 GobTestIndirectArrayEncDeca.X = 17var array ArrayStructap := &arrayapp := &apa.A = &appfor 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 fieldb := 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 fieldb.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 %c", 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 fieldb := new(bytes.Buffer)enc := NewEncoder(b)err := enc.Encode(GobTest4{17, ValueGobber("hello")})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" {t.Errorf("expected `hello` got %s", x.V)}}func TestGobEncoderFieldTypeError(t *testing.T) {// GobEncoder to non-decoder: errorb := 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: errorb.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 Gobbererr = 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)err := enc.Encode(GobTest3{17, &gobber})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 nilif 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 *gobDecoderBug0if 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 isZerotype isZeroBug struct {T time.TimeS stringI intA isZeroBugArray}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}func TestGobEncodeIsZero(t *testing.T) {x := isZeroBug{time.Now(), "hello", -55, isZeroBugArray{1, 2}}b := new(bytes.Buffer)enc := NewEncoder(b)err := enc.Encode(x)if err != nil {t.Fatal("encode:", err)}var y isZeroBugdec := NewDecoder(b)err = dec.Decode(&y)if err != nil {t.Fatal("decode:", err)}if x != y {t.Fatalf("%v != %v", x, y)}}
