]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/json: more tests to cover decoding edge cases
authorDaniel Martí <mvdan@mvdan.cc>
Tue, 11 Sep 2018 20:09:00 +0000 (22:09 +0200)
committerDaniel Martí <mvdan@mvdan.cc>
Wed, 12 Sep 2018 06:48:09 +0000 (06:48 +0000)
The overall coverage of the json package goes up from 90.8% to 91.3%.

While at it, apply two minor code simplifications found while inspecting
the HTML coverage report.

Change-Id: I0fba968afeedc813b1385e4bde72d93b878854d7
Reviewed-on: https://go-review.googlesource.com/134735
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/vet/all/whitelist/all.txt
src/encoding/json/decode.go
src/encoding/json/decode_test.go

index b974d21c6ae236d684aa1d9b6f76599d6a9f00ed..5425f84fc6e36247011f6d68499cff0f06e1c025 100644 (file)
@@ -24,6 +24,7 @@ runtime/asm_ARCHSUFF.s: [GOARCH] gcWriteBarrier: function gcWriteBarrier missing
 // in bad situations that vet can also detect statically.
 encoding/json/decode_test.go: struct field m has json tag but is not exported
 encoding/json/decode_test.go: struct field m2 has json tag but is not exported
+encoding/json/decode_test.go: struct field s has json tag but is not exported
 encoding/json/tagkey_test.go: struct field tag `:"BadFormat"` not compatible with reflect.StructTag.Get: bad syntax for struct tag key
 runtime/testdata/testprog/deadlock.go: unreachable code
 runtime/testdata/testprog/deadlock.go: unreachable code
index 82dc78083a7ca9f62f33efb78889401828c27b98..dbff2d063137a2848ef6fa077cd6f781a172a7c8 100644 (file)
@@ -533,8 +533,7 @@ func (d *decodeState) array(v reflect.Value) error {
                d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
                d.skip()
                return nil
-       case reflect.Array:
-       case reflect.Slice:
+       case reflect.Array, reflect.Slice:
                break
        }
 
@@ -871,18 +870,16 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
                if item[0] != '"' {
                        if fromQuoted {
                                d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
-                       } else {
-                               var val string
-                               switch item[0] {
-                               case 'n':
-                                       val = "null"
-                               case 't', 'f':
-                                       val = "bool"
-                               default:
-                                       val = "number"
-                               }
-                               d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())})
+                               return nil
+                       }
+                       val := "number"
+                       switch item[0] {
+                       case 'n':
+                               val = "null"
+                       case 't', 'f':
+                               val = "bool"
                        }
+                       d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())})
                        return nil
                }
                s, ok := unquoteBytes(item)
index defa97e40fdd080ebbb00f52e076317c64dcd170..5fbe67a7063b3233fb30aaaf16ed309fec1a0720 100644 (file)
@@ -445,6 +445,7 @@ var unmarshalTests = []unmarshalTest{
        {in: `{"X": "foo", "Y"}`, err: &SyntaxError{"invalid character '}' after object key", 17}},
        {in: `[1, 2, 3+]`, err: &SyntaxError{"invalid character '+' after array element", 9}},
        {in: `{"X":12x}`, err: &SyntaxError{"invalid character 'x' after object key:value pair", 8}, useNumber: true},
+       {in: `[2, 3`, err: &SyntaxError{msg: "unexpected end of JSON input", Offset: 5}},
 
        // raw value errors
        {in: "\x01 42", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
@@ -460,6 +461,7 @@ var unmarshalTests = []unmarshalTest{
        {in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}},
        {in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}},
        {in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}},
+       {in: `[1, 2, 3]`, ptr: new(MustNotUnmarshalJSON), err: errors.New("MustNotUnmarshalJSON was used")},
 
        // empty array to interface test
        {in: `[]`, ptr: new([]interface{}), out: []interface{}{}},
@@ -826,6 +828,7 @@ var unmarshalTests = []unmarshalTest{
        {in: `{"B": "False"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "False" into bool`)},
        {in: `{"B": "null"}`, ptr: new(B), out: B{false}},
        {in: `{"B": "nul"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "nul" into bool`)},
+       {in: `{"B": [2, 3]}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal unquoted value into bool`)},
 
        // additional tests for disallowUnknownFields
        {
@@ -894,6 +897,18 @@ var unmarshalTests = []unmarshalTest{
                ptr: new(mapStringToStringData),
                err: &UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 21, Struct: "mapStringToStringData", Field: "data"},
        },
+
+       // trying to decode JSON arrays or objects via TextUnmarshaler
+       {
+               in:  `[1, 2, 3]`,
+               ptr: new(MustNotUnmarshalText),
+               err: &UnmarshalTypeError{Value: "array", Type: reflect.TypeOf(&MustNotUnmarshalText{}), Offset: 1},
+       },
+       {
+               in:  `{"foo": "bar"}`,
+               ptr: new(MustNotUnmarshalText),
+               err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(&MustNotUnmarshalText{}), Offset: 1},
+       },
 }
 
 func TestMarshal(t *testing.T) {
@@ -1955,10 +1970,12 @@ type unexportedFields struct {
        Name string
        m    map[string]interface{} `json:"-"`
        m2   map[string]interface{} `json:"abcd"`
+
+       s []int `json:"-"`
 }
 
 func TestUnmarshalUnexported(t *testing.T) {
-       input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}}`
+       input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}, "s": [2, 3]}`
        want := &unexportedFields{Name: "Bob"}
 
        out := &unexportedFields{}