diff --git a/assert/assertions.go b/assert/assertions.go index 104a0c936..461182210 100644 --- a/assert/assertions.go +++ b/assert/assertions.go @@ -24,6 +24,8 @@ import ( "github.com/stretchr/testify/assert/yaml" ) +const stackFrameBufferSize = 10 + //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" // TestingT is an interface wrapper around *testing.T @@ -212,19 +214,26 @@ the problem actually occurred in calling code.*/ func CallerInfo() []string { var pc uintptr - var ok bool var file string var line int var name string callers := []string{} - for i := 0; ; i++ { - pc, file, line, ok = runtime.Caller(i) - if !ok { - // The breaks below failed to terminate the loop, and we ran off the - // end of the call stack. - break - } + pcs := make([]uintptr, stackFrameBufferSize) + offset := 1 + n := runtime.Callers(offset, pcs) + maybeMore := n == stackFrameBufferSize + + if n == 0 { + return []string{} + } + frames := runtime.CallersFrames(pcs[:n]) + + for { + frame, more := frames.Next() + pc = frame.PC + file = frame.File + line = frame.Line // This is a huge edge case, but it will panic if this is the case, see #180 if file == "" { @@ -263,6 +272,23 @@ func CallerInfo() []string { isTest(name, "Example") { break } + + if !more { + // We know we already have less than a buffer's worth of frames + if !maybeMore { + break + } + offset += stackFrameBufferSize + n = runtime.Callers(offset, pcs) + if n == 0 { + break + } + + maybeMore = n == stackFrameBufferSize + + frames = runtime.CallersFrames(pcs[:n]) + } + } return callers