Skip to content

Commit

Permalink
encoding/json: expand and modernize TestInterfaceSet
Browse files Browse the repository at this point in the history
Add more test cases to cover a wider range of edge cases.
Use a generic addr function to take the address of a value.
Even though redudant, explicitly include a cast to the
top-level Go type so that it is more readable what the
expected input and ouput types are.

Change-Id: I3ef68df6f1beb903ae237cd49f3dcb91e5270fe7
Reviewed-on: https://go-review.googlesource.com/c/go/+/638256
Reviewed-by: Daniel Martí <[email protected]>
Reviewed-by: Damien Neil <[email protected]>
Reviewed-by: Ian Lance Taylor <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
  • Loading branch information
dsnet committed Dec 28, 2024
1 parent e3cd55e commit 2b794ed
Showing 1 changed file with 46 additions and 19 deletions.
65 changes: 46 additions & 19 deletions src/encoding/json/decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1797,19 +1797,12 @@ func TestNullString(t *testing.T) {
}
}

func intp(x int) *int {
p := new(int)
*p = x
return p
}

func intpp(x *int) **int {
pp := new(*int)
*pp = x
return pp
func addr[T any](v T) *T {
return &v
}

func TestInterfaceSet(t *testing.T) {
errUnmarshal := &UnmarshalTypeError{Value: "object", Offset: 6, Type: reflect.TypeFor[int](), Field: "X"}
tests := []struct {
CaseName
pre any
Expand All @@ -1820,21 +1813,55 @@ func TestInterfaceSet(t *testing.T) {
{Name(""), "foo", `2`, 2.0},
{Name(""), "foo", `true`, true},
{Name(""), "foo", `null`, nil},

{Name(""), nil, `null`, nil},
{Name(""), new(int), `null`, nil},
{Name(""), (*int)(nil), `null`, nil},
{Name(""), new(*int), `null`, new(*int)},
{Name(""), (**int)(nil), `null`, nil},
{Name(""), intp(1), `null`, nil},
{Name(""), intpp(nil), `null`, intpp(nil)},
{Name(""), intpp(intp(1)), `null`, intpp(nil)},
{Name(""), map[string]any{}, `true`, true},
{Name(""), []string{}, `true`, true},

{Name(""), any(nil), `null`, any(nil)},
{Name(""), (*int)(nil), `null`, any(nil)},
{Name(""), (*int)(addr(0)), `null`, any(nil)},
{Name(""), (*int)(addr(1)), `null`, any(nil)},
{Name(""), (**int)(nil), `null`, any(nil)},
{Name(""), (**int)(addr[*int](nil)), `null`, (**int)(addr[*int](nil))},
{Name(""), (**int)(addr(addr(1))), `null`, (**int)(addr[*int](nil))},
{Name(""), (***int)(nil), `null`, any(nil)},
{Name(""), (***int)(addr[**int](nil)), `null`, (***int)(addr[**int](nil))},
{Name(""), (***int)(addr(addr[*int](nil))), `null`, (***int)(addr[**int](nil))},
{Name(""), (***int)(addr(addr(addr(1)))), `null`, (***int)(addr[**int](nil))},

{Name(""), any(nil), `2`, float64(2)},
{Name(""), (int)(1), `2`, float64(2)},
{Name(""), (*int)(nil), `2`, float64(2)},
{Name(""), (*int)(addr(0)), `2`, (*int)(addr(2))},
{Name(""), (*int)(addr(1)), `2`, (*int)(addr(2))},
{Name(""), (**int)(nil), `2`, float64(2)},
{Name(""), (**int)(addr[*int](nil)), `2`, (**int)(addr(addr(2)))},
{Name(""), (**int)(addr(addr(1))), `2`, (**int)(addr(addr(2)))},
{Name(""), (***int)(nil), `2`, float64(2)},
{Name(""), (***int)(addr[**int](nil)), `2`, (***int)(addr(addr(addr(2))))},
{Name(""), (***int)(addr(addr[*int](nil))), `2`, (***int)(addr(addr(addr(2))))},
{Name(""), (***int)(addr(addr(addr(1)))), `2`, (***int)(addr(addr(addr(2))))},

{Name(""), any(nil), `{}`, map[string]any{}},
{Name(""), (int)(1), `{}`, map[string]any{}},
{Name(""), (*int)(nil), `{}`, map[string]any{}},
{Name(""), (*int)(addr(0)), `{}`, errUnmarshal},
{Name(""), (*int)(addr(1)), `{}`, errUnmarshal},
{Name(""), (**int)(nil), `{}`, map[string]any{}},
{Name(""), (**int)(addr[*int](nil)), `{}`, errUnmarshal},
{Name(""), (**int)(addr(addr(1))), `{}`, errUnmarshal},
{Name(""), (***int)(nil), `{}`, map[string]any{}},
{Name(""), (***int)(addr[**int](nil)), `{}`, errUnmarshal},
{Name(""), (***int)(addr(addr[*int](nil))), `{}`, errUnmarshal},
{Name(""), (***int)(addr(addr(addr(1)))), `{}`, errUnmarshal},
}
for _, tt := range tests {
t.Run(tt.Name, func(t *testing.T) {
b := struct{ X any }{tt.pre}
blob := `{"X":` + tt.json + `}`
if err := Unmarshal([]byte(blob), &b); err != nil {
if wantErr, _ := tt.post.(error); equalError(err, wantErr) {
return
}
t.Fatalf("%s: Unmarshal(%#q) error: %v", tt.Where, blob, err)
}
if !reflect.DeepEqual(b.X, tt.post) {
Expand Down

0 comments on commit 2b794ed

Please sign in to comment.