mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			799 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			799 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Go
		
	
	
	
// 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.Contains(err.Error(), "type") {
 | 
						|
		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.Contains(err.Error(), "type") {
 | 
						|
		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)
 | 
						|
	var g Gobber = 1234
 | 
						|
	err := enc.Encode(&g)
 | 
						|
	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())
 | 
						|
	}
 | 
						|
}
 |