| | |
| | |
| | |
| |
|
| | |
| |
|
| | package gob |
| |
|
| | import ( |
| | "bytes" |
| | "errors" |
| | "fmt" |
| | "io" |
| | "net" |
| | "reflect" |
| | "strings" |
| | "testing" |
| | "time" |
| | ) |
| |
|
| | |
| |
|
| | type ByteStruct struct { |
| | a byte |
| | } |
| |
|
| | type StringStruct struct { |
| | s string |
| | } |
| |
|
| | type ArrayStruct struct { |
| | a [8192]byte |
| | } |
| |
|
| | type Gobber int |
| |
|
| | type ValueGobber string |
| |
|
| | type BinaryGobber int |
| |
|
| | type BinaryValueGobber string |
| |
|
| | type TextGobber int |
| |
|
| | type TextValueGobber string |
| |
|
| | |
| |
|
| | 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") |
| | } |
| | |
| | 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 { |
| | |
| | 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 |
| | } |
| |
|
| | |
| |
|
| | type GobTest0 struct { |
| | X int |
| | G *ByteStruct |
| | } |
| |
|
| | type GobTest1 struct { |
| | X int |
| | G *StringStruct |
| | } |
| |
|
| | type GobTest2 struct { |
| | X int |
| | G string |
| | } |
| |
|
| | type GobTest3 struct { |
| | X int |
| | G *Gobber |
| | B *BinaryGobber |
| | T *TextGobber |
| | } |
| |
|
| | type GobTest4 struct { |
| | X int |
| | V ValueGobber |
| | BV BinaryValueGobber |
| | TV TextValueGobber |
| | } |
| |
|
| | type GobTest5 struct { |
| | X int |
| | V *ValueGobber |
| | BV *BinaryValueGobber |
| | TV *TextValueGobber |
| | } |
| |
|
| | type GobTest6 struct { |
| | X int |
| | V ValueGobber |
| | W *ValueGobber |
| | BV BinaryValueGobber |
| | BW *BinaryValueGobber |
| | TV TextValueGobber |
| | TW *TextValueGobber |
| | } |
| |
|
| | type GobTest7 struct { |
| | X int |
| | V *ValueGobber |
| | W ValueGobber |
| | BV *BinaryValueGobber |
| | BW BinaryValueGobber |
| | TV *TextValueGobber |
| | TW TextValueGobber |
| | } |
| |
|
| | type GobTestIgnoreEncoder struct { |
| | X int |
| | } |
| |
|
| | type GobTestValueEncDec struct { |
| | X int |
| | G StringStruct |
| | } |
| |
|
| | type GobTestIndirectEncDec struct { |
| | X int |
| | G ***StringStruct |
| | } |
| |
|
| | type GobTestArrayEncDec struct { |
| | X int |
| | A ArrayStruct |
| | } |
| |
|
| | type GobTestIndirectArrayEncDec struct { |
| | X int |
| | A ***ArrayStruct |
| | } |
| |
|
| | func TestGobEncoderField(t *testing.T) { |
| | b := new(bytes.Buffer) |
| | |
| | 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) |
| | } |
| | |
| | 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) |
| | } |
| | } |
| |
|
| | |
| | |
| | func TestGobEncoderValueField(t *testing.T) { |
| | b := new(bytes.Buffer) |
| | |
| | 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) |
| | } |
| | } |
| |
|
| | |
| | |
| | func TestGobEncoderIndirectField(t *testing.T) { |
| | b := new(bytes.Buffer) |
| | |
| | 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) |
| | } |
| | } |
| |
|
| | |
| | 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 |
| | } |
| | } |
| | } |
| |
|
| | |
| | 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 |
| | } |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | func TestGobEncoderFieldsOfDifferentType(t *testing.T) { |
| | |
| | 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) |
| | } |
| | |
| | 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) |
| | } |
| | } |
| |
|
| | |
| | func TestGobEncoderValueEncoder(t *testing.T) { |
| | |
| | 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) |
| | } |
| | } |
| |
|
| | |
| | |
| | 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²") |
| |
|
| | |
| | |
| |
|
| | 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) |
| | } |
| | } |
| |
|
| | |
| | |
| | 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) { |
| | |
| | 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) |
| | } |
| | |
| | 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) |
| | } |
| | } |
| |
|
| | |
| | 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) |
| | |
| | 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) |
| | |
| | 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) |
| | |
| | enc := NewEncoder(b) |
| | err := enc.Encode(GobTest0{X: 18}) |
| | 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 |
| | } |
| |
|
| | |
| | |
| | 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) |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | type isZeroBug struct { |
| | T time.Time |
| | S string |
| | I int |
| | A isZeroBugArray |
| | F isZeroBugInterface |
| | } |
| |
|
| | type isZeroBugArray [2]uint8 |
| |
|
| | |
| | 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 any |
| | } |
| |
|
| | 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.Unix(1e9, 0), "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) { |
| | |
| | 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()) |
| | } |
| | } |
| |
|
| | func TestIgnoreDepthLimit(t *testing.T) { |
| | |
| | |
| | oldNestingDepth := maxIgnoreNestingDepth |
| | maxIgnoreNestingDepth = 100 |
| | defer func() { maxIgnoreNestingDepth = oldNestingDepth }() |
| | b := new(bytes.Buffer) |
| | enc := NewEncoder(b) |
| |
|
| | |
| | typ := reflect.TypeFor[int]() |
| | nested := reflect.ArrayOf(1, typ) |
| | for i := 0; i < 100; i++ { |
| | nested = reflect.ArrayOf(1, nested) |
| | } |
| | badStruct := reflect.New(reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}})) |
| | enc.Encode(badStruct.Interface()) |
| | dec := NewDecoder(b) |
| | var output struct{ Hello int } |
| | expectedErr := "invalid nesting depth" |
| | if err := dec.Decode(&output); err == nil || err.Error() != expectedErr { |
| | t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err) |
| | } |
| |
|
| | |
| | nested = reflect.StructOf([]reflect.StructField{{Name: "F", Type: typ}}) |
| | for i := 0; i < 100; i++ { |
| | nested = reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}}) |
| | } |
| | badStruct = reflect.New(reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}})) |
| | enc.Encode(badStruct.Interface()) |
| | dec = NewDecoder(b) |
| | if err := dec.Decode(&output); err == nil || err.Error() != expectedErr { |
| | t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err) |
| | } |
| | } |
| |
|