Skip to content
This repository was archived by the owner on Jun 27, 2023. It is now read-only.

Commit 31092bf

Browse files
committed
More info when Do func has wrong signature
Catch panic and show a terser call stack and the file and line number of the function that has the wrong arguments Before: ``` ... Test Panicked reflect: Call using *[]*models.ImageDefinition as type int /usr/local/Cellar/go/1.10/libexec/src/runtime/panic.go:505 Full Stack Trace /usr/local/Cellar/go/1.10/libexec/src/runtime/panic.go:505 +0x229 reflect.Value.call(0x4889200, 0x49e60c0, 0x13, 0x49b4159, 0x4, 0xc4203c1c20, 0x3, 0x3, 0x49af000, 0x485f4c0, ...) /usr/local/Cellar/go/1.10/libexec/src/reflect/value.go:377 +0x1202 reflect.Value.Call(0x4889200, 0x49e60c0, 0x13, 0xc4203c1c20, 0x3, 0x3, 0x94, 0x0, 0x0) /usr/local/Cellar/go/1.10/libexec/src/reflect/value.go:308 +0xa4 git.corp.adobe.com/adobe-platform/flight-director/vendor/github.com/golang/mock/gomock.(*Call).Do.func1(0xc4202126c0, 0x3, 0x4, 0xc4201b7e40, 0x2, 0x2) /Users/abramowi/go/src/git.corp.adobe.com/adobe-platform/flight-director/vendor/github.com/golang/mock/gomock/call.go:154 +0x23f git.corp.adobe.com/adobe-platform/flight-director/vendor/github.com/golang/mock/gomock.(*Controller).Call(0xc420177230, 0x4913f80, 0xc42007f7a0, 0x49b5a9c, 0x6, 0xc4202126c0, 0x3, 0x4, 0x0, 0x0, ...) /Users/abramowi/go/src/git.corp.adobe.com/adobe-platform/flight-director/vendor/github.com/golang/mock/gomock/controller.go:170 +0x167 git.corp.adobe.com/adobe-platform/flight-director/mocks/shared/db.(*MockWrapper).Select(0xc42007f7a0, 0x4829a00, 0xc420212620, 0xc4201de180, 0x34, 0xc420478520, 0x1, 0x1, 0x40133b8, 0x120, ...) /Users/abramowi/go/src/git.corp.adobe.com/adobe-platform/flight-director/mocks/shared/db/wrapper.go:82 +0x218 git.corp.adobe.com/adobe-platform/flight-director/shared/db.(*QueryFilter).SelectIntoEntities(0xc420334988, 0x4a70c00, 0xc42007f7a0, 0x4829a00, 0xc420212620, 0x1, 0x0) /Users/abramowi/go/src/git.corp.adobe.com/adobe-platform/flight-director/shared/db/query_filter.go:74 +0x202 ... ``` After: ``` ... reflect: Call using *[]*models.ImageDefinition as type int (incorrect func args at /Users/abramowi/go/src/git.corp.adobe.com/adobe-platform/flight-director/server/routes/deploys/handlers_test.go:71?) git.corp.adobe.com/adobe-platform/flight-director/shared/db.(*QueryFilter).SelectIntoEntities /Users/abramowi/go/src/git.corp.adobe.com/adobe-platform/flight-director/shared/db/query_filter.go:74 ... ```
1 parent dd8d2a2 commit 31092bf

File tree

2 files changed

+85
-1
lines changed

2 files changed

+85
-1
lines changed

gomock/call.go

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package gomock
1717
import (
1818
"fmt"
1919
"reflect"
20+
"runtime"
2021
"strconv"
2122
"strings"
2223
)
@@ -149,6 +150,27 @@ func (c *Call) Do(f interface{}) *Call {
149150
vargs[i] = reflect.Zero(ft.In(i))
150151
}
151152
}
153+
defer func() {
154+
if r := recover(); r != nil {
155+
errMsg, ok := r.(string)
156+
157+
// We only handle a very specific panic
158+
// If it's not that one, then we "rethrow" the panic
159+
// This allows users to use functions that panic in their tests
160+
if !ok {
161+
panic(r)
162+
}
163+
if !strings.Contains(errMsg, "reflect: Call using") &&
164+
!strings.Contains(errMsg, "reflect.Set: value of") {
165+
panic(r)
166+
}
167+
skipFrames := 8
168+
stackTraceStr := "\n\n" + currentStackTrace(skipFrames)
169+
funcPC := v.Pointer()
170+
file, line := runtime.FuncForPC(funcPC).FileLine(funcPC)
171+
c.t.Fatalf("%s (incorrect func args at %s:%d?)%+v", errMsg, file, line, stackTraceStr)
172+
}
173+
}()
152174
v.Call(vargs)
153175
return nil
154176
})
@@ -239,6 +261,25 @@ func (c *Call) SetArg(n int, value interface{}) *Call {
239261
case reflect.Slice:
240262
setSlice(args[n], v)
241263
default:
264+
defer func() {
265+
if r := recover(); r != nil {
266+
errMsg, ok := r.(string)
267+
268+
// We only handle a very specific panic
269+
// If it's not that one, then we "rethrow" the panic
270+
// This allows users to use functions that panic in their tests
271+
if !ok {
272+
panic(r)
273+
}
274+
if !strings.Contains(errMsg, "reflect: Call using") &&
275+
!strings.Contains(errMsg, "reflect.Set: value of") {
276+
panic(r)
277+
}
278+
skipFrames := 8
279+
stackTraceStr := "\n\n" + currentStackTrace(skipFrames)
280+
c.t.Fatalf("%s%+v", errMsg, stackTraceStr)
281+
}
282+
}()
242283
reflect.ValueOf(args[n]).Elem().Set(v)
243284
}
244285
return nil
@@ -382,7 +423,7 @@ func (c *Call) matches(args []interface{}) error {
382423

383424
// Check that the call is not exhausted.
384425
if c.exhausted() {
385-
return fmt.Errorf("Expected call at %s has already been called the max number of times.", c.origin)
426+
return fmt.Errorf("Expected call at %s has already been called the max number of times (%d).", c.origin, c.maxCalls)
386427
}
387428

388429
return nil

gomock/stack.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package gomock
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"strings"
7+
8+
"github.com/pkg/errors"
9+
)
10+
11+
const skipFrames = 2
12+
13+
type stackTracer interface {
14+
StackTrace() errors.StackTrace
15+
}
16+
17+
func stackTraceStringFromError(err error, skipFrames int) string {
18+
if err, ok := err.(stackTracer); ok {
19+
return stackTraceString(err.StackTrace(), skipFrames)
20+
}
21+
return ""
22+
}
23+
24+
func currentStackTrace(skipFrames int) string {
25+
err := errors.New("fake error just to get stack")
26+
if err, ok := err.(stackTracer); ok {
27+
return stackTraceString(err.StackTrace(), skipFrames)
28+
}
29+
return ""
30+
}
31+
32+
func stackTraceString(stackTrace errors.StackTrace, skipFrames int) string {
33+
buffer := bytes.NewBufferString("")
34+
for i := skipFrames + 1; i < len(stackTrace); i++ {
35+
frame := stackTrace[i]
36+
buffer.WriteString(fmt.Sprintf("%+v\n", frame))
37+
filename := fmt.Sprintf("%s", frame)
38+
if strings.Contains(filename, "_test.go") {
39+
break
40+
}
41+
}
42+
return buffer.String()
43+
}

0 commit comments

Comments
 (0)