diff options
Diffstat (limited to 'libgo/go/encoding/json/decode_test.go')
-rw-r--r-- | libgo/go/encoding/json/decode_test.go | 167 |
1 files changed, 146 insertions, 21 deletions
diff --git a/libgo/go/encoding/json/decode_test.go b/libgo/go/encoding/json/decode_test.go index f845f69ab7f..22c5f89f798 100644 --- a/libgo/go/encoding/json/decode_test.go +++ b/libgo/go/encoding/json/decode_test.go @@ -6,6 +6,7 @@ package json import ( "bytes" + "encoding" "fmt" "image" "reflect" @@ -50,8 +51,6 @@ type tx struct { x int } -var txType = reflect.TypeOf((*tx)(nil)).Elem() - // A type that can unmarshal itself. type unmarshaler struct { @@ -59,7 +58,7 @@ type unmarshaler struct { } func (u *unmarshaler) UnmarshalJSON(b []byte) error { - *u = unmarshaler{true} // All we need to see that UnmarshalJson is called. + *u = unmarshaler{true} // All we need to see that UnmarshalJSON is called. return nil } @@ -67,6 +66,26 @@ type ustruct struct { M unmarshaler } +type unmarshalerText struct { + T bool +} + +// needed for re-marshaling tests +func (u *unmarshalerText) MarshalText() ([]byte, error) { + return []byte(""), nil +} + +func (u *unmarshalerText) UnmarshalText(b []byte) error { + *u = unmarshalerText{true} // All we need to see that UnmarshalText is called. + return nil +} + +var _ encoding.TextUnmarshaler = (*unmarshalerText)(nil) + +type ustructText struct { + M unmarshalerText +} + var ( um0, um1 unmarshaler // target2 of unmarshaling ump = &um1 @@ -74,6 +93,13 @@ var ( umslice = []unmarshaler{{true}} umslicep = new([]unmarshaler) umstruct = ustruct{unmarshaler{true}} + + um0T, um1T unmarshalerText // target2 of unmarshaling + umpT = &um1T + umtrueT = unmarshalerText{true} + umsliceT = []unmarshalerText{{true}} + umslicepT = new([]unmarshalerText) + umstructT = ustructText{unmarshalerText{true}} ) // Test data structures for anonymous fields. @@ -184,6 +210,12 @@ type Ambig struct { Second int `json:"Hello"` } +type XYZ struct { + X interface{} + Y interface{} + Z interface{} +} + var unmarshalTests = []unmarshalTest{ // basic types {in: `true`, ptr: new(bool), out: true}, @@ -263,6 +295,13 @@ var unmarshalTests = []unmarshalTest{ {in: `[{"T":false}]`, ptr: &umslicep, out: &umslice}, {in: `{"M":{"T":false}}`, ptr: &umstruct, out: umstruct}, + // UnmarshalText interface test + {in: `"X"`, ptr: &um0T, out: umtrueT}, // use "false" so test will fail if custom unmarshaler is not called + {in: `"X"`, ptr: &umpT, out: &umtrueT}, + {in: `["X"]`, ptr: &umsliceT, out: umsliceT}, + {in: `["X"]`, ptr: &umslicepT, out: &umsliceT}, + {in: `{"M":"X"}`, ptr: &umstructT, out: umstructT}, + { in: `{ "Level0": 1, @@ -391,17 +430,23 @@ func TestMarshal(t *testing.T) { } } +var badUTF8 = []struct { + in, out string +}{ + {"hello\xffworld", `"hello\ufffdworld"`}, + {"", `""`}, + {"\xff", `"\ufffd"`}, + {"\xff\xff", `"\ufffd\ufffd"`}, + {"a\xffb", `"a\ufffdb"`}, + {"\xe6\x97\xa5\xe6\x9c\xac\xff\xaa\x9e", `"日本\ufffd\ufffd\ufffd"`}, +} + func TestMarshalBadUTF8(t *testing.T) { - s := "hello\xffworld" - b, err := Marshal(s) - if err == nil { - t.Fatal("Marshal bad UTF8: no error") - } - if len(b) != 0 { - t.Fatal("Marshal returned data") - } - if _, ok := err.(*InvalidUTF8Error); !ok { - t.Fatalf("Marshal did not return InvalidUTF8Error: %T %v", err, err) + for _, tt := range badUTF8 { + b, err := Marshal(tt.in) + if string(b) != tt.out || err != nil { + t.Errorf("Marshal(%q) = %#q, %v, want %#q, nil", tt.in, b, err, tt.out) + } } } @@ -417,6 +462,45 @@ func TestMarshalNumberZeroVal(t *testing.T) { } } +func TestMarshalEmbeds(t *testing.T) { + top := &Top{ + Level0: 1, + Embed0: Embed0{ + Level1b: 2, + Level1c: 3, + }, + Embed0a: &Embed0a{ + Level1a: 5, + Level1b: 6, + }, + Embed0b: &Embed0b{ + Level1a: 8, + Level1b: 9, + Level1c: 10, + Level1d: 11, + Level1e: 12, + }, + Loop: Loop{ + Loop1: 13, + Loop2: 14, + }, + Embed0p: Embed0p{ + Point: image.Point{X: 15, Y: 16}, + }, + Embed0q: Embed0q{ + Point: Point{Z: 17}, + }, + } + b, err := Marshal(top) + if err != nil { + t.Fatal(err) + } + want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17}" + if string(b) != want { + t.Errorf("Wrong marshal result.\n got: %q\nwant: %q", b, want) + } +} + func TestUnmarshal(t *testing.T) { for i, tt := range unmarshalTests { var scan scanner @@ -432,7 +516,7 @@ func TestUnmarshal(t *testing.T) { } // v = new(right-type) v := reflect.New(reflect.TypeOf(tt.ptr).Elem()) - dec := NewDecoder(bytes.NewBuffer(in)) + dec := NewDecoder(bytes.NewReader(in)) if tt.useNumber { dec.UseNumber() } @@ -457,16 +541,18 @@ func TestUnmarshal(t *testing.T) { continue } vv := reflect.New(reflect.TypeOf(tt.ptr).Elem()) - dec = NewDecoder(bytes.NewBuffer(enc)) + dec = NewDecoder(bytes.NewReader(enc)) if tt.useNumber { dec.UseNumber() } if err := dec.Decode(vv.Interface()); err != nil { - t.Errorf("#%d: error re-unmarshaling: %v", i, err) + t.Errorf("#%d: error re-unmarshaling %#q: %v", i, enc, err) continue } if !reflect.DeepEqual(v.Elem().Interface(), vv.Elem().Interface()) { t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), vv.Elem().Interface()) + t.Errorf(" In: %q", strings.Map(noSpace, string(in))) + t.Errorf("Marshal: %q", strings.Map(noSpace, string(enc))) continue } } @@ -568,14 +654,14 @@ func TestUnmarshalPtrPtr(t *testing.T) { } func TestEscape(t *testing.T) { - const input = `"foobar"<html>` - const expected = `"\"foobar\"\u003chtml\u003e"` + const input = `"foobar"<html>` + " [\u2028 \u2029]" + const expected = `"\"foobar\"\u003chtml\u003e [\u2028 \u2029]"` b, err := Marshal(input) if err != nil { t.Fatalf("Marshal error: %v", err) } if s := string(b); s != expected { - t.Errorf("Encoding of [%s] was [%s], want [%s]", input, s, expected) + t.Errorf("Encoding of [%s]:\n got [%s]\nwant [%s]", input, s, expected) } } @@ -934,15 +1020,20 @@ func TestRefUnmarshal(t *testing.T) { // Ref is defined in encode_test.go. R0 Ref R1 *Ref + R2 RefText + R3 *RefText } want := S{ R0: 12, R1: new(Ref), + R2: 13, + R3: new(RefText), } *want.R1 = 12 + *want.R3 = 13 var got S - if err := Unmarshal([]byte(`{"R0":"ref","R1":"ref"}`), &got); err != nil { + if err := Unmarshal([]byte(`{"R0":"ref","R1":"ref","R2":"ref","R3":"ref"}`), &got); err != nil { t.Fatalf("Unmarshal: %v", err) } if !reflect.DeepEqual(got, want) { @@ -1064,7 +1155,6 @@ func TestUnmarshalNulls(t *testing.T) { func TestStringKind(t *testing.T) { type stringKind string - type aMap map[stringKind]int var m1, m2 map[stringKind]int m1 = map[stringKind]int{ @@ -1191,3 +1281,38 @@ func TestSkipArrayObjects(t *testing.T) { t.Errorf("got error %q, want nil", err) } } + +// Test semantics of pre-filled struct fields and pre-filled map fields. +// Issue 4900. +func TestPrefilled(t *testing.T) { + ptrToMap := func(m map[string]interface{}) *map[string]interface{} { return &m } + + // Values here change, cannot reuse table across runs. + var prefillTests = []struct { + in string + ptr interface{} + out interface{} + }{ + { + in: `{"X": 1, "Y": 2}`, + ptr: &XYZ{X: float32(3), Y: int16(4), Z: 1.5}, + out: &XYZ{X: float64(1), Y: float64(2), Z: 1.5}, + }, + { + in: `{"X": 1, "Y": 2}`, + ptr: ptrToMap(map[string]interface{}{"X": float32(3), "Y": int16(4), "Z": 1.5}), + out: ptrToMap(map[string]interface{}{"X": float64(1), "Y": float64(2), "Z": 1.5}), + }, + } + + for _, tt := range prefillTests { + ptrstr := fmt.Sprintf("%v", tt.ptr) + err := Unmarshal([]byte(tt.in), tt.ptr) // tt.ptr edited here + if err != nil { + t.Errorf("Unmarshal: %v", err) + } + if !reflect.DeepEqual(tt.ptr, tt.out) { + t.Errorf("Unmarshal(%#q, %s): have %v, want %v", tt.in, ptrstr, tt.ptr, tt.out) + } + } +} |