From d508b4a708a820ef456cc021592a631eb286ef80 Mon Sep 17 00:00:00 2001 From: Rob Percival Date: Fri, 10 Mar 2017 12:18:32 +0000 Subject: [PATCH 1/2] Include stacktrace when no matching expected call This helps with tracking down the offending call. --- gomock/controller.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gomock/controller.go b/gomock/controller.go index d06dfbbe..1054890d 100644 --- a/gomock/controller.go +++ b/gomock/controller.go @@ -59,6 +59,7 @@ import ( "fmt" "reflect" "runtime" + "runtime/debug" "sync" ) @@ -128,8 +129,7 @@ func (ctrl *Controller) Call(receiver interface{}, method string, args ...interf expected, err := ctrl.expectedCalls.FindMatch(receiver, method, args) if err != nil { - origin := callerInfo(2) - ctrl.t.Fatalf("Unexpected call to %T.%v(%v) at %s because: %s", receiver, method, args, origin, err) + ctrl.t.Fatalf("Unexpected call to %T.%v(%v) because: %s\n%s", receiver, method, args, err, debug.Stack()) } // Two things happen here: From 7f9c436df904080ae5bf7841f720251001904364 Mon Sep 17 00:00:00 2001 From: Rob Percival Date: Fri, 28 Apr 2017 12:28:55 +0100 Subject: [PATCH 2/2] Include stacktrace when call expectation is invalid This helps with tracking down the offending expectation. --- gomock/call.go | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/gomock/call.go b/gomock/call.go index dc2a479d..5a0500e9 100644 --- a/gomock/call.go +++ b/gomock/call.go @@ -17,6 +17,7 @@ package gomock import ( "fmt" "reflect" + "runtime/debug" "strconv" "strings" ) @@ -81,8 +82,8 @@ func (c *Call) Do(f interface{}) *Call { func (c *Call) Return(rets ...interface{}) *Call { mt := c.methodType if len(rets) != mt.NumOut() { - c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d [%s]", - c.receiver, c.method, len(rets), mt.NumOut(), c.origin) + c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d\n%s", + c.receiver, c.method, len(rets), mt.NumOut(), debug.Stack()) } for i, ret := range rets { if got, want := reflect.TypeOf(ret), mt.Out(i); got == want { @@ -93,8 +94,8 @@ func (c *Call) Return(rets ...interface{}) *Call { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: // ok default: - c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable [%s]", - i, c.receiver, c.method, want, c.origin) + c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable\n%s", + i, c.receiver, c.method, want, debug.Stack()) } } else if got.AssignableTo(want) { // Assignable type relation. Make the assignment now so that the generated code @@ -103,8 +104,8 @@ func (c *Call) Return(rets ...interface{}) *Call { v.Set(reflect.ValueOf(ret)) rets[i] = v.Interface() } else { - c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v [%s]", - i, c.receiver, c.method, got, want, c.origin) + c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v\n%s", + i, c.receiver, c.method, got, want, debug.Stack()) } } @@ -128,8 +129,7 @@ func (c *Call) SetArg(n int, value interface{}) *Call { // TODO: This will break on variadic methods. // We will need to check those at invocation time. if n < 0 || n >= mt.NumIn() { - c.t.Fatalf("SetArg(%d, ...) called for a method with %d args [%s]", - n, mt.NumIn(), c.origin) + c.t.Fatalf("SetArg(%d, ...) called for a method with %d args\n%s", n, mt.NumIn(), debug.Stack()) } // Permit setting argument through an interface. // In the interface case, we don't (nay, can't) check the type here. @@ -138,16 +138,14 @@ func (c *Call) SetArg(n int, value interface{}) *Call { case reflect.Ptr: dt := at.Elem() if vt := reflect.TypeOf(value); !vt.AssignableTo(dt) { - c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v [%s]", - n, vt, dt, c.origin) + c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v\n%s", n, vt, dt, debug.Stack()) } case reflect.Interface: // nothing to do case reflect.Slice: // nothing to do default: - c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface non-slice type %v", - n, at, c.origin) + c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface type %v\n%s", n, at, debug.Stack()) } c.setArgs[n] = reflect.ValueOf(value) return c @@ -166,7 +164,7 @@ func (c *Call) isPreReq(other *Call) bool { // After declares that the call may only match after preReq has been exhausted. func (c *Call) After(preReq *Call) *Call { if c == preReq { - c.t.Fatalf("A call isn't allowed to be its own prerequisite") + c.t.Fatalf("A call isn't allowed to be its own prerequisite\n%s", debug.Stack()) } if preReq.isPreReq(c) { c.t.Fatalf("Loop in call order: %v is a prerequisite to %v (possibly indirectly).", c, preReq)