...

Source file src/encoding/gob/gobencdec_test.go

Documentation: encoding/gob

     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  
     7  package gob
     8  
     9  import (
    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  
    23  type ByteStruct struct {
    24  	a byte // not an exported field
    25  }
    26  
    27  type StringStruct struct {
    28  	s string // not an exported field
    29  }
    30  
    31  type ArrayStruct struct {
    32  	a [8192]byte // not an exported field
    33  }
    34  
    35  type Gobber int
    36  
    37  type ValueGobber string // encodes with a value, decodes with a pointer.
    38  
    39  type BinaryGobber int
    40  
    41  type BinaryValueGobber string
    42  
    43  type TextGobber int
    44  
    45  type TextValueGobber string
    46  
    47  // The relevant methods
    48  
    49  func (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  
    57  func (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  
    74  func (g *StringStruct) GobEncode() ([]byte, error) {
    75  	return []byte(g.s), nil
    76  }
    77  
    78  func (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  
    93  func (a *ArrayStruct) GobEncode() ([]byte, error) {
    94  	return a.a[:], nil
    95  }
    96  
    97  func (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  
   105  func (g *Gobber) GobEncode() ([]byte, error) {
   106  	return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
   107  }
   108  
   109  func (g *Gobber) GobDecode(data []byte) error {
   110  	_, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
   111  	return err
   112  }
   113  
   114  func (g *BinaryGobber) MarshalBinary() ([]byte, error) {
   115  	return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
   116  }
   117  
   118  func (g *BinaryGobber) UnmarshalBinary(data []byte) error {
   119  	_, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
   120  	return err
   121  }
   122  
   123  func (g *TextGobber) MarshalText() ([]byte, error) {
   124  	return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
   125  }
   126  
   127  func (g *TextGobber) UnmarshalText(data []byte) error {
   128  	_, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
   129  	return err
   130  }
   131  
   132  func (v ValueGobber) GobEncode() ([]byte, error) {
   133  	return []byte(fmt.Sprintf("VALUE=%s", v)), nil
   134  }
   135  
   136  func (v *ValueGobber) GobDecode(data []byte) error {
   137  	_, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
   138  	return err
   139  }
   140  
   141  func (v BinaryValueGobber) MarshalBinary() ([]byte, error) {
   142  	return []byte(fmt.Sprintf("VALUE=%s", v)), nil
   143  }
   144  
   145  func (v *BinaryValueGobber) UnmarshalBinary(data []byte) error {
   146  	_, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
   147  	return err
   148  }
   149  
   150  func (v TextValueGobber) MarshalText() ([]byte, error) {
   151  	return []byte(fmt.Sprintf("VALUE=%s", v)), nil
   152  }
   153  
   154  func (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  
   161  type GobTest0 struct {
   162  	X int // guarantee we have  something in common with GobTest*
   163  	G *ByteStruct
   164  }
   165  
   166  type GobTest1 struct {
   167  	X int // guarantee we have  something in common with GobTest*
   168  	G *StringStruct
   169  }
   170  
   171  type 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  
   176  type GobTest3 struct {
   177  	X int // guarantee we have  something in common with GobTest*
   178  	G *Gobber
   179  	B *BinaryGobber
   180  	T *TextGobber
   181  }
   182  
   183  type GobTest4 struct {
   184  	X  int // guarantee we have  something in common with GobTest*
   185  	V  ValueGobber
   186  	BV BinaryValueGobber
   187  	TV TextValueGobber
   188  }
   189  
   190  type GobTest5 struct {
   191  	X  int // guarantee we have  something in common with GobTest*
   192  	V  *ValueGobber
   193  	BV *BinaryValueGobber
   194  	TV *TextValueGobber
   195  }
   196  
   197  type 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  
   207  type 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  
   217  type GobTestIgnoreEncoder struct {
   218  	X int // guarantee we have  something in common with GobTest*
   219  }
   220  
   221  type GobTestValueEncDec struct {
   222  	X int          // guarantee we have  something in common with GobTest*
   223  	G StringStruct // not a pointer.
   224  }
   225  
   226  type GobTestIndirectEncDec struct {
   227  	X int             // guarantee we have  something in common with GobTest*
   228  	G ***StringStruct // indirections to the receiver.
   229  }
   230  
   231  type GobTestArrayEncDec struct {
   232  	X int         // guarantee we have  something in common with GobTest*
   233  	A ArrayStruct // not a pointer.
   234  }
   235  
   236  type GobTestIndirectArrayEncDec struct {
   237  	X int            // guarantee we have  something in common with GobTest*
   238  	A ***ArrayStruct // indirections to a large receiver.
   239  }
   240  
   241  func 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.
   279  func 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.
   300  func 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.
   322  func 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.
   349  func 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.
   384  func 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.
   418  func 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.
   439  func 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.
   491  func 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  
   538  func 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.
   572  func 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  
   590  func 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  
   609  func 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  
   628  func 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  
   650  func 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  
   672  type gobDecoderBug0 struct {
   673  	foo, bar string
   674  }
   675  
   676  func (br *gobDecoderBug0) String() string {
   677  	return br.foo + "-" + br.bar
   678  }
   679  
   680  func (br *gobDecoderBug0) GobEncode() ([]byte, error) {
   681  	return []byte(br.String()), nil
   682  }
   683  
   684  func (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.
   692  func 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.
   712  type isZeroBug struct {
   713  	T time.Time
   714  	S string
   715  	I int
   716  	A isZeroBugArray
   717  	F isZeroBugInterface
   718  }
   719  
   720  type isZeroBugArray [2]uint8
   721  
   722  // Receiver is value, not pointer, to test isZero of array.
   723  func (a isZeroBugArray) GobEncode() (b []byte, e error) {
   724  	b = append(b, a[:]...)
   725  	return b, nil
   726  }
   727  
   728  func (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  
   737  type isZeroBugInterface struct {
   738  	I any
   739  }
   740  
   741  func (i isZeroBugInterface) GobEncode() (b []byte, e error) {
   742  	return []byte{}, nil
   743  }
   744  
   745  func (i *isZeroBugInterface) GobDecode(data []byte) error {
   746  	return nil
   747  }
   748  
   749  func 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  
   768  func 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  
   787  func 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  
   801  func 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  

View as plain text