mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
reflect: return user-visible method name in panic string
This was accidentally broken in CL 166462, which introduce another function in the panicking path without adjusting the argument to runtime.Caller. Change-Id: Ib6f9ed8673fefd458c7a4e3a918c45c5b31ca552 Reviewed-on: https://go-review.googlesource.com/c/go/+/229082 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
7f8fda3c0b
commit
f6b30e53bb
2 changed files with 119 additions and 89 deletions
|
|
@ -2021,7 +2021,7 @@ func TestMakeFuncValidReturnAssignments(t *testing.T) {
|
|||
|
||||
func TestMakeFuncInvalidReturnAssignments(t *testing.T) {
|
||||
// Type doesn't implement the required interface.
|
||||
shouldPanic(func() {
|
||||
shouldPanic("", func() {
|
||||
var f func() error
|
||||
f = MakeFunc(TypeOf(f), func([]Value) []Value {
|
||||
return []Value{ValueOf(int(7))}
|
||||
|
|
@ -2029,7 +2029,7 @@ func TestMakeFuncInvalidReturnAssignments(t *testing.T) {
|
|||
f()
|
||||
})
|
||||
// Assigning to an interface with additional methods.
|
||||
shouldPanic(func() {
|
||||
shouldPanic("", func() {
|
||||
var f func() io.ReadWriteCloser
|
||||
f = MakeFunc(TypeOf(f), func([]Value) []Value {
|
||||
var w io.WriteCloser = &WC{}
|
||||
|
|
@ -2038,7 +2038,7 @@ func TestMakeFuncInvalidReturnAssignments(t *testing.T) {
|
|||
f()
|
||||
})
|
||||
// Directional channels can't be assigned to bidirectional ones.
|
||||
shouldPanic(func() {
|
||||
shouldPanic("", func() {
|
||||
var f func() chan int
|
||||
f = MakeFunc(TypeOf(f), func([]Value) []Value {
|
||||
var c <-chan int = make(chan int)
|
||||
|
|
@ -2047,7 +2047,7 @@ func TestMakeFuncInvalidReturnAssignments(t *testing.T) {
|
|||
f()
|
||||
})
|
||||
// Two named types which are otherwise identical.
|
||||
shouldPanic(func() {
|
||||
shouldPanic("", func() {
|
||||
type T struct{ a, b, c int }
|
||||
type U struct{ a, b, c int }
|
||||
var f func() T
|
||||
|
|
@ -2511,7 +2511,7 @@ func TestMethod5(t *testing.T) {
|
|||
|
||||
var tnil Tinter
|
||||
vnil := ValueOf(&tnil).Elem()
|
||||
shouldPanic(func() { vnil.Method(0) })
|
||||
shouldPanic("Method", func() { vnil.Method(0) })
|
||||
}
|
||||
|
||||
func TestInterfaceSet(t *testing.T) {
|
||||
|
|
@ -3216,9 +3216,9 @@ func TestSlice3(t *testing.T) {
|
|||
t.Errorf("xs.Slice3(3, 5, 7)[0:4] = %v", v[0:4])
|
||||
}
|
||||
rv := ValueOf(&xs).Elem()
|
||||
shouldPanic(func() { rv.Slice3(1, 2, 1) })
|
||||
shouldPanic(func() { rv.Slice3(1, 1, 11) })
|
||||
shouldPanic(func() { rv.Slice3(2, 2, 1) })
|
||||
shouldPanic("Slice3", func() { rv.Slice3(1, 2, 1) })
|
||||
shouldPanic("Slice3", func() { rv.Slice3(1, 1, 11) })
|
||||
shouldPanic("Slice3", func() { rv.Slice3(2, 2, 1) })
|
||||
|
||||
xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
|
||||
v = ValueOf(&xa).Elem().Slice3(2, 5, 6).Interface().([]int)
|
||||
|
|
@ -3232,13 +3232,13 @@ func TestSlice3(t *testing.T) {
|
|||
t.Errorf("xs.Slice(2, 5, 6)[0:4] = %v", v[0:4])
|
||||
}
|
||||
rv = ValueOf(&xa).Elem()
|
||||
shouldPanic(func() { rv.Slice3(1, 2, 1) })
|
||||
shouldPanic(func() { rv.Slice3(1, 1, 11) })
|
||||
shouldPanic(func() { rv.Slice3(2, 2, 1) })
|
||||
shouldPanic("Slice3", func() { rv.Slice3(1, 2, 1) })
|
||||
shouldPanic("Slice3", func() { rv.Slice3(1, 1, 11) })
|
||||
shouldPanic("Slice3", func() { rv.Slice3(2, 2, 1) })
|
||||
|
||||
s := "hello world"
|
||||
rv = ValueOf(&s).Elem()
|
||||
shouldPanic(func() { rv.Slice3(1, 2, 3) })
|
||||
shouldPanic("Slice3", func() { rv.Slice3(1, 2, 3) })
|
||||
|
||||
rv = ValueOf(&xs).Elem()
|
||||
rv = rv.Slice3(3, 5, 7)
|
||||
|
|
@ -3255,11 +3255,11 @@ func TestSetLenCap(t *testing.T) {
|
|||
xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
|
||||
|
||||
vs := ValueOf(&xs).Elem()
|
||||
shouldPanic(func() { vs.SetLen(10) })
|
||||
shouldPanic(func() { vs.SetCap(10) })
|
||||
shouldPanic(func() { vs.SetLen(-1) })
|
||||
shouldPanic(func() { vs.SetCap(-1) })
|
||||
shouldPanic(func() { vs.SetCap(6) }) // smaller than len
|
||||
shouldPanic("SetLen", func() { vs.SetLen(10) })
|
||||
shouldPanic("SetCap", func() { vs.SetCap(10) })
|
||||
shouldPanic("SetLen", func() { vs.SetLen(-1) })
|
||||
shouldPanic("SetCap", func() { vs.SetCap(-1) })
|
||||
shouldPanic("SetCap", func() { vs.SetCap(6) }) // smaller than len
|
||||
vs.SetLen(5)
|
||||
if len(xs) != 5 || cap(xs) != 8 {
|
||||
t.Errorf("after SetLen(5), len, cap = %d, %d, want 5, 8", len(xs), cap(xs))
|
||||
|
|
@ -3272,12 +3272,12 @@ func TestSetLenCap(t *testing.T) {
|
|||
if len(xs) != 5 || cap(xs) != 5 {
|
||||
t.Errorf("after SetCap(5), len, cap = %d, %d, want 5, 5", len(xs), cap(xs))
|
||||
}
|
||||
shouldPanic(func() { vs.SetCap(4) }) // smaller than len
|
||||
shouldPanic(func() { vs.SetLen(6) }) // bigger than cap
|
||||
shouldPanic("SetCap", func() { vs.SetCap(4) }) // smaller than len
|
||||
shouldPanic("SetLen", func() { vs.SetLen(6) }) // bigger than cap
|
||||
|
||||
va := ValueOf(&xa).Elem()
|
||||
shouldPanic(func() { va.SetLen(8) })
|
||||
shouldPanic(func() { va.SetCap(8) })
|
||||
shouldPanic("SetLen", func() { va.SetLen(8) })
|
||||
shouldPanic("SetCap", func() { va.SetCap(8) })
|
||||
}
|
||||
|
||||
func TestVariadic(t *testing.T) {
|
||||
|
|
@ -3435,16 +3435,16 @@ func TestUnexported(t *testing.T) {
|
|||
isValid(v.Elem().Field(1))
|
||||
isValid(v.Elem().FieldByName("x"))
|
||||
isValid(v.Elem().FieldByName("y"))
|
||||
shouldPanic(func() { v.Elem().Field(0).Interface() })
|
||||
shouldPanic(func() { v.Elem().Field(1).Interface() })
|
||||
shouldPanic(func() { v.Elem().FieldByName("x").Interface() })
|
||||
shouldPanic(func() { v.Elem().FieldByName("y").Interface() })
|
||||
shouldPanic(func() { v.Type().Method(0) })
|
||||
shouldPanic("Interface", func() { v.Elem().Field(0).Interface() })
|
||||
shouldPanic("Interface", func() { v.Elem().Field(1).Interface() })
|
||||
shouldPanic("Interface", func() { v.Elem().FieldByName("x").Interface() })
|
||||
shouldPanic("Interface", func() { v.Elem().FieldByName("y").Interface() })
|
||||
shouldPanic("Method", func() { v.Type().Method(0) })
|
||||
}
|
||||
|
||||
func TestSetPanic(t *testing.T) {
|
||||
ok := func(f func()) { f() }
|
||||
bad := shouldPanic
|
||||
bad := func(f func()) { shouldPanic("Set", f) }
|
||||
clear := func(v Value) { v.Set(Zero(v.Type())) }
|
||||
|
||||
type t0 struct {
|
||||
|
|
@ -3561,56 +3561,75 @@ func TestCallPanic(t *testing.T) {
|
|||
namedT2 T2 // 7
|
||||
}
|
||||
ok := func(f func()) { f() }
|
||||
bad := shouldPanic
|
||||
badCall := func(f func()) { shouldPanic("Call", f) }
|
||||
badMethod := func(f func()) { shouldPanic("Method", f) }
|
||||
call := func(v Value) { v.Call(nil) }
|
||||
|
||||
i := timp(0)
|
||||
v := ValueOf(T{i, i, i, i, T2{i, i}, i, i, T2{i, i}})
|
||||
ok(func() { call(v.Field(0).Method(0)) }) // .t0.W
|
||||
bad(func() { call(v.Field(0).Elem().Method(0)) }) // .t0.W
|
||||
bad(func() { call(v.Field(0).Method(1)) }) // .t0.w
|
||||
bad(func() { call(v.Field(0).Elem().Method(2)) }) // .t0.w
|
||||
ok(func() { call(v.Field(1).Method(0)) }) // .T1.Y
|
||||
ok(func() { call(v.Field(1).Elem().Method(0)) }) // .T1.Y
|
||||
bad(func() { call(v.Field(1).Method(1)) }) // .T1.y
|
||||
bad(func() { call(v.Field(1).Elem().Method(2)) }) // .T1.y
|
||||
ok(func() { call(v.Field(0).Method(0)) }) // .t0.W
|
||||
badCall(func() { call(v.Field(0).Elem().Method(0)) }) // .t0.W
|
||||
badCall(func() { call(v.Field(0).Method(1)) }) // .t0.w
|
||||
badMethod(func() { call(v.Field(0).Elem().Method(2)) }) // .t0.w
|
||||
ok(func() { call(v.Field(1).Method(0)) }) // .T1.Y
|
||||
ok(func() { call(v.Field(1).Elem().Method(0)) }) // .T1.Y
|
||||
badCall(func() { call(v.Field(1).Method(1)) }) // .T1.y
|
||||
badMethod(func() { call(v.Field(1).Elem().Method(2)) }) // .T1.y
|
||||
|
||||
ok(func() { call(v.Field(2).Method(0)) }) // .NamedT0.W
|
||||
ok(func() { call(v.Field(2).Elem().Method(0)) }) // .NamedT0.W
|
||||
bad(func() { call(v.Field(2).Method(1)) }) // .NamedT0.w
|
||||
bad(func() { call(v.Field(2).Elem().Method(2)) }) // .NamedT0.w
|
||||
ok(func() { call(v.Field(2).Method(0)) }) // .NamedT0.W
|
||||
ok(func() { call(v.Field(2).Elem().Method(0)) }) // .NamedT0.W
|
||||
badCall(func() { call(v.Field(2).Method(1)) }) // .NamedT0.w
|
||||
badMethod(func() { call(v.Field(2).Elem().Method(2)) }) // .NamedT0.w
|
||||
|
||||
ok(func() { call(v.Field(3).Method(0)) }) // .NamedT1.Y
|
||||
ok(func() { call(v.Field(3).Elem().Method(0)) }) // .NamedT1.Y
|
||||
bad(func() { call(v.Field(3).Method(1)) }) // .NamedT1.y
|
||||
bad(func() { call(v.Field(3).Elem().Method(3)) }) // .NamedT1.y
|
||||
ok(func() { call(v.Field(3).Method(0)) }) // .NamedT1.Y
|
||||
ok(func() { call(v.Field(3).Elem().Method(0)) }) // .NamedT1.Y
|
||||
badCall(func() { call(v.Field(3).Method(1)) }) // .NamedT1.y
|
||||
badMethod(func() { call(v.Field(3).Elem().Method(3)) }) // .NamedT1.y
|
||||
|
||||
ok(func() { call(v.Field(4).Field(0).Method(0)) }) // .NamedT2.T1.Y
|
||||
ok(func() { call(v.Field(4).Field(0).Elem().Method(0)) }) // .NamedT2.T1.W
|
||||
ok(func() { call(v.Field(4).Field(1).Method(0)) }) // .NamedT2.t0.W
|
||||
bad(func() { call(v.Field(4).Field(1).Elem().Method(0)) }) // .NamedT2.t0.W
|
||||
ok(func() { call(v.Field(4).Field(0).Method(0)) }) // .NamedT2.T1.Y
|
||||
ok(func() { call(v.Field(4).Field(0).Elem().Method(0)) }) // .NamedT2.T1.W
|
||||
ok(func() { call(v.Field(4).Field(1).Method(0)) }) // .NamedT2.t0.W
|
||||
badCall(func() { call(v.Field(4).Field(1).Elem().Method(0)) }) // .NamedT2.t0.W
|
||||
|
||||
bad(func() { call(v.Field(5).Method(0)) }) // .namedT0.W
|
||||
bad(func() { call(v.Field(5).Elem().Method(0)) }) // .namedT0.W
|
||||
bad(func() { call(v.Field(5).Method(1)) }) // .namedT0.w
|
||||
bad(func() { call(v.Field(5).Elem().Method(2)) }) // .namedT0.w
|
||||
badCall(func() { call(v.Field(5).Method(0)) }) // .namedT0.W
|
||||
badCall(func() { call(v.Field(5).Elem().Method(0)) }) // .namedT0.W
|
||||
badCall(func() { call(v.Field(5).Method(1)) }) // .namedT0.w
|
||||
badMethod(func() { call(v.Field(5).Elem().Method(2)) }) // .namedT0.w
|
||||
|
||||
bad(func() { call(v.Field(6).Method(0)) }) // .namedT1.Y
|
||||
bad(func() { call(v.Field(6).Elem().Method(0)) }) // .namedT1.Y
|
||||
bad(func() { call(v.Field(6).Method(0)) }) // .namedT1.y
|
||||
bad(func() { call(v.Field(6).Elem().Method(0)) }) // .namedT1.y
|
||||
badCall(func() { call(v.Field(6).Method(0)) }) // .namedT1.Y
|
||||
badCall(func() { call(v.Field(6).Elem().Method(0)) }) // .namedT1.Y
|
||||
badCall(func() { call(v.Field(6).Method(0)) }) // .namedT1.y
|
||||
badCall(func() { call(v.Field(6).Elem().Method(0)) }) // .namedT1.y
|
||||
|
||||
bad(func() { call(v.Field(7).Field(0).Method(0)) }) // .namedT2.T1.Y
|
||||
bad(func() { call(v.Field(7).Field(0).Elem().Method(0)) }) // .namedT2.T1.W
|
||||
bad(func() { call(v.Field(7).Field(1).Method(0)) }) // .namedT2.t0.W
|
||||
bad(func() { call(v.Field(7).Field(1).Elem().Method(0)) }) // .namedT2.t0.W
|
||||
badCall(func() { call(v.Field(7).Field(0).Method(0)) }) // .namedT2.T1.Y
|
||||
badCall(func() { call(v.Field(7).Field(0).Elem().Method(0)) }) // .namedT2.T1.W
|
||||
badCall(func() { call(v.Field(7).Field(1).Method(0)) }) // .namedT2.t0.W
|
||||
badCall(func() { call(v.Field(7).Field(1).Elem().Method(0)) }) // .namedT2.t0.W
|
||||
}
|
||||
|
||||
func shouldPanic(f func()) {
|
||||
func shouldPanic(expect string, f func()) {
|
||||
defer func() {
|
||||
if recover() == nil {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
panic("did not panic")
|
||||
}
|
||||
if expect != "" {
|
||||
var s string
|
||||
switch r := r.(type) {
|
||||
case string:
|
||||
s = r
|
||||
case *ValueError:
|
||||
s = r.Error()
|
||||
default:
|
||||
panic(fmt.Sprintf("panicked with unexpected type %T", r))
|
||||
}
|
||||
if !strings.HasPrefix(s, "reflect") {
|
||||
panic(`panic string does not start with "reflect": ` + s)
|
||||
}
|
||||
if !strings.Contains(s, expect) {
|
||||
panic(`panic string does not contain "` + expect + `": ` + s)
|
||||
}
|
||||
}
|
||||
}()
|
||||
f()
|
||||
}
|
||||
|
|
@ -4445,7 +4464,7 @@ func TestArrayOfAlg(t *testing.T) {
|
|||
|
||||
at = ArrayOf(6, TypeOf([]int(nil)))
|
||||
v1 = New(at).Elem()
|
||||
shouldPanic(func() { _ = v1.Interface() == v1.Interface() })
|
||||
shouldPanic("", func() { _ = v1.Interface() == v1.Interface() })
|
||||
}
|
||||
|
||||
func TestArrayOfGenericAlg(t *testing.T) {
|
||||
|
|
@ -4589,23 +4608,23 @@ func TestSliceOfGC(t *testing.T) {
|
|||
|
||||
func TestStructOfFieldName(t *testing.T) {
|
||||
// invalid field name "1nvalid"
|
||||
shouldPanic(func() {
|
||||
shouldPanic("has invalid name", func() {
|
||||
StructOf([]StructField{
|
||||
{Name: "valid", Type: TypeOf("")},
|
||||
{Name: "Valid", Type: TypeOf("")},
|
||||
{Name: "1nvalid", Type: TypeOf("")},
|
||||
})
|
||||
})
|
||||
|
||||
// invalid field name "+"
|
||||
shouldPanic(func() {
|
||||
shouldPanic("has invalid name", func() {
|
||||
StructOf([]StructField{
|
||||
{Name: "val1d", Type: TypeOf("")},
|
||||
{Name: "Val1d", Type: TypeOf("")},
|
||||
{Name: "+", Type: TypeOf("")},
|
||||
})
|
||||
})
|
||||
|
||||
// no field name
|
||||
shouldPanic(func() {
|
||||
shouldPanic("has no name", func() {
|
||||
StructOf([]StructField{
|
||||
{Name: "", Type: TypeOf("")},
|
||||
})
|
||||
|
|
@ -4732,19 +4751,19 @@ func TestStructOf(t *testing.T) {
|
|||
}
|
||||
|
||||
// check duplicate names
|
||||
shouldPanic(func() {
|
||||
shouldPanic("duplicate field", func() {
|
||||
StructOf([]StructField{
|
||||
{Name: "string", Type: TypeOf("")},
|
||||
{Name: "string", Type: TypeOf("")},
|
||||
{Name: "string", PkgPath: "p", Type: TypeOf("")},
|
||||
{Name: "string", PkgPath: "p", Type: TypeOf("")},
|
||||
})
|
||||
})
|
||||
shouldPanic(func() {
|
||||
shouldPanic("has no name", func() {
|
||||
StructOf([]StructField{
|
||||
{Type: TypeOf("")},
|
||||
{Name: "string", Type: TypeOf("")},
|
||||
{Name: "string", PkgPath: "p", Type: TypeOf("")},
|
||||
})
|
||||
})
|
||||
shouldPanic(func() {
|
||||
shouldPanic("has no name", func() {
|
||||
StructOf([]StructField{
|
||||
{Type: TypeOf("")},
|
||||
{Type: TypeOf("")},
|
||||
|
|
@ -4967,7 +4986,7 @@ func TestStructOfAlg(t *testing.T) {
|
|||
|
||||
st = StructOf([]StructField{{Name: "X", Tag: "x", Type: TypeOf([]int(nil))}})
|
||||
v1 = New(st).Elem()
|
||||
shouldPanic(func() { _ = v1.Interface() == v1.Interface() })
|
||||
shouldPanic("", func() { _ = v1.Interface() == v1.Interface() })
|
||||
}
|
||||
|
||||
func TestStructOfGenericAlg(t *testing.T) {
|
||||
|
|
@ -5298,7 +5317,7 @@ func TestStructOfWithInterface(t *testing.T) {
|
|||
rt := StructOf(fields)
|
||||
rv := New(rt).Elem()
|
||||
// This should panic since the pointer is nil.
|
||||
shouldPanic(func() {
|
||||
shouldPanic("", func() {
|
||||
rv.Interface().(IfaceSet).Set(want)
|
||||
})
|
||||
|
||||
|
|
@ -5312,7 +5331,7 @@ func TestStructOfWithInterface(t *testing.T) {
|
|||
rt = StructOf(fields)
|
||||
rv = New(rt).Elem()
|
||||
// This should panic since the pointer is nil.
|
||||
shouldPanic(func() {
|
||||
shouldPanic("", func() {
|
||||
rv.Interface().(IfaceSet).Set(want)
|
||||
})
|
||||
|
||||
|
|
@ -5334,7 +5353,7 @@ func TestStructOfWithInterface(t *testing.T) {
|
|||
// With the current implementation this is expected to panic.
|
||||
// Ideally it should work and we should be able to see a panic
|
||||
// if we call the Set method.
|
||||
shouldPanic(func() {
|
||||
shouldPanic("", func() {
|
||||
StructOf(fields)
|
||||
})
|
||||
|
||||
|
|
@ -5355,7 +5374,7 @@ func TestStructOfWithInterface(t *testing.T) {
|
|||
// With the current implementation this is expected to panic.
|
||||
// Ideally it should work and we should be able to call the
|
||||
// Set and Get methods.
|
||||
shouldPanic(func() {
|
||||
shouldPanic("", func() {
|
||||
StructOf(fields)
|
||||
})
|
||||
}
|
||||
|
|
@ -5384,7 +5403,7 @@ func TestStructOfDifferentPkgPath(t *testing.T) {
|
|||
Type: TypeOf(int(0)),
|
||||
},
|
||||
}
|
||||
shouldPanic(func() {
|
||||
shouldPanic("different PkgPath", func() {
|
||||
StructOf(fields)
|
||||
})
|
||||
}
|
||||
|
|
@ -5501,7 +5520,7 @@ func TestMapOf(t *testing.T) {
|
|||
checkSameType(t, MapOf(TypeOf(V(0)), TypeOf(K(""))), map[V]K(nil))
|
||||
|
||||
// check that invalid key type panics
|
||||
shouldPanic(func() { MapOf(TypeOf((func())(nil)), TypeOf(false)) })
|
||||
shouldPanic("invalid key type", func() { MapOf(TypeOf((func())(nil)), TypeOf(false)) })
|
||||
}
|
||||
|
||||
func TestMapOfGCKeys(t *testing.T) {
|
||||
|
|
@ -5633,8 +5652,8 @@ func TestFuncOf(t *testing.T) {
|
|||
|
||||
// check that variadic requires last element be a slice.
|
||||
FuncOf([]Type{TypeOf(1), TypeOf(""), SliceOf(TypeOf(false))}, nil, true)
|
||||
shouldPanic(func() { FuncOf([]Type{TypeOf(0), TypeOf(""), TypeOf(false)}, nil, true) })
|
||||
shouldPanic(func() { FuncOf(nil, nil, true) })
|
||||
shouldPanic("must be slice", func() { FuncOf([]Type{TypeOf(0), TypeOf(""), TypeOf(false)}, nil, true) })
|
||||
shouldPanic("must be slice", func() { FuncOf(nil, nil, true) })
|
||||
}
|
||||
|
||||
type B1 struct {
|
||||
|
|
@ -6866,7 +6885,7 @@ func TestUnaddressableField(t *testing.T) {
|
|||
}
|
||||
lv := ValueOf(&localBuffer).Elem()
|
||||
rv := ValueOf(b)
|
||||
shouldPanic(func() {
|
||||
shouldPanic("Set", func() {
|
||||
lv.Set(rv)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue