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

Print stack for unexpected call #171

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion ci/check_go_fmt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

set -euo pipefail

GOFMT_DIFF=$(IFS=$'\n'; gofmt -d $( find . -type f -name '*.go' ) )
GOFMT_DIFF=$(IFS=$'\n'; gofmt -d $( find . -path ./vendor -prune -o -type f -name '*.go' -print ) )
if [[ -n "${GOFMT_DIFF}" ]]; then
echo "${GOFMT_DIFF}"
echo
Expand Down
10 changes: 10 additions & 0 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package: github.com/golang/mock
ignore:
- a
import:
- package: github.com/pkg/errors
version: ^0.8.0
- package: golang.org/x/net
subpackages:
- context
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
module github.com/golang/mock

require golang.org/x/tools v0.0.0-20190425150028-36563e24a262
require (
github.com/pkg/errors v0.8.1
golang.org/x/tools v0.0.0-20190425150028-36563e24a262
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand Down
40 changes: 26 additions & 14 deletions gomock/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,13 @@ func (c *Call) Do(f interface{}) *Call {
// Return declares the values to be returned by the mocked function call.
func (c *Call) Return(rets ...interface{}) *Call {
c.t.Helper()
skipFrames := 1

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)
stackTraceStr := "\n\n" + currentStackTrace(skipFrames)
c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d [%s]%+v",
c.receiver, c.method, len(rets), mt.NumOut(), c.origin, stackTraceStr)
}
for i, ret := range rets {
if got, want := reflect.TypeOf(ret), mt.Out(i); got == want {
Expand All @@ -173,8 +175,9 @@ 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)
stackTraceStr := "\n\n" + currentStackTrace(skipFrames)
c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable [%s]%+v",
i, c.receiver, c.method, want, c.origin, stackTraceStr)
}
} else if got.AssignableTo(want) {
// Assignable type relation. Make the assignment now so that the generated code
Expand All @@ -183,8 +186,10 @@ 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)
skipFrames := 1
stackTraceStr := "\n\n" + currentStackTrace(skipFrames)
c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v [%s]%+v",
i, c.receiver, c.method, got, want, c.origin, stackTraceStr)
}
}

Expand All @@ -206,13 +211,15 @@ func (c *Call) Times(n int) *Call {
// will copy value's elements into the nth argument.
func (c *Call) SetArg(n int, value interface{}) *Call {
c.t.Helper()
skipFrames := 1

mt := c.methodType
// 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)
stackTraceStr := "\n\n" + currentStackTrace(skipFrames)
c.t.Fatalf("SetArg(%d, ...) called for a method with %d args [%s]%+v",
n, mt.NumIn(), c.origin, stackTraceStr)
}
// Permit setting argument through an interface.
// In the interface case, we don't (nay, can't) check the type here.
Expand All @@ -221,16 +228,18 @@ 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)
stackTraceStr := "\n\n" + currentStackTrace(skipFrames)
c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v [%s]%+v",
n, vt, dt, c.origin, stackTraceStr)
}
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 [%s]",
n, at, c.origin)
stackTraceStr := "\n\n" + currentStackTrace(skipFrames)
c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface non-slice type %v [%s]%+v",
n, at, c.origin, stackTraceStr)
}

c.addAction(func(args []interface{}) []interface{} {
Expand Down Expand Up @@ -259,12 +268,15 @@ 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 {
c.t.Helper()
skipFrames := 1

if c == preReq {
c.t.Fatalf("A call isn't allowed to be its own prerequisite")
stackTraceStr := "\n\n" + currentStackTrace(skipFrames)
c.t.Fatalf("A call isn't allowed to be its own prerequisite%+v", stackTraceStr)
}
if preReq.isPreReq(c) {
c.t.Fatalf("Loop in call order: %v is a prerequisite to %v (possibly indirectly).", c, preReq)
stackTraceStr := "\n\n" + currentStackTrace(skipFrames)
c.t.Fatalf("Loop in call order: %v is a prerequisite to %v (possibly indirectly).%+v", c, preReq, stackTraceStr)
}

c.preReqs = append(c.preReqs, preReq)
Expand Down
4 changes: 3 additions & 1 deletion gomock/callset.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ package gomock
import (
"bytes"
"fmt"

"github.com/pkg/errors"
)

// callSet represents a set of expected calls, indexed by receiver and method
Expand Down Expand Up @@ -91,7 +93,7 @@ func (cs callSet) FindMatch(receiver interface{}, method string, args []interfac
fmt.Fprintf(&callsErrors, "there are no expected calls of the method %q for that receiver", method)
}

return nil, fmt.Errorf(callsErrors.String())
return nil, errors.Errorf(callsErrors.String())
}

// Failures returns the calls that are not satisfied.
Expand Down
10 changes: 7 additions & 3 deletions gomock/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ type cancelReporter struct {
func (r *cancelReporter) Errorf(format string, args ...interface{}) {
r.TestHelper.Errorf(format, args...)
}

func (r *cancelReporter) Fatalf(format string, args ...interface{}) {
defer r.cancel()
r.TestHelper.Fatalf(format, args...)
Expand Down Expand Up @@ -197,8 +198,9 @@ 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)
origin := callerInfo(skipFrames)
stackTraceStr := "\n\n" + stackTraceStringFromError(err, skipFrames)
ctrl.T.Fatalf("Unexpected call to %T.%v(%v) at %s because: %s%+v", receiver, method, args, origin, err, stackTraceStr)
}

// Two things happen here:
Expand Down Expand Up @@ -236,7 +238,9 @@ func (ctrl *Controller) Finish() {
defer ctrl.mu.Unlock()

if ctrl.finished {
ctrl.T.Fatalf("Controller.Finish was called more than once. It has to be called exactly once.")
skipFrames := 1
stackTraceStr := "\n\n" + currentStackTrace(skipFrames)
ctrl.T.Fatalf("Controller.Finish was called more than once. It has to be called exactly once.%+v", stackTraceStr)
}
ctrl.finished = true

Expand Down
43 changes: 43 additions & 0 deletions gomock/stack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package gomock

import (
"bytes"
"fmt"
"strings"

"github.com/pkg/errors"
)

const skipFrames = 2

type stackTracer interface {
StackTrace() errors.StackTrace
}

func stackTraceStringFromError(err error, skipFrames int) string {
if err, ok := err.(stackTracer); ok {
return stackTraceString(err.StackTrace(), skipFrames)
}
return ""
}

func currentStackTrace(skipFrames int) string {
err := errors.New("fake error just to get stack")
if err, ok := err.(stackTracer); ok {
return stackTraceString(err.StackTrace(), skipFrames)
}
return ""
}

func stackTraceString(stackTrace errors.StackTrace, skipFrames int) string {
buffer := bytes.NewBufferString("")
for i := skipFrames + 1; i < len(stackTrace); i++ {
frame := stackTrace[i]
buffer.WriteString(fmt.Sprintf("%+v\n", frame))
filename := fmt.Sprintf("%s", frame)
if strings.Contains(filename, "_test.go") {
break
}
}
return buffer.String()
}
24 changes: 24 additions & 0 deletions vendor/github.com/pkg/errors/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions vendor/github.com/pkg/errors/.travis.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions vendor/github.com/pkg/errors/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 52 additions & 0 deletions vendor/github.com/pkg/errors/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions vendor/github.com/pkg/errors/appveyor.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading