From 4ae2a9cd07f77baff2d8007186d334313e5fc01b Mon Sep 17 00:00:00 2001
From: Elliott Sales de Andrade <quantum.analyst@gmail.com>
Date: Mon, 18 Feb 2019 01:17:44 -0500
Subject: [PATCH] Fix build against Go 1.12.
Backport #183 and #193, effectively.
Signed-off-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
---
stack.go | 26 +++++++------
stack_test.go | 104 ++++++++++++++++++++------------------------------
2 files changed, 57 insertions(+), 73 deletions(-)
diff --git a/stack.go b/stack.go
index 2874a04..4db50c7 100644
--- a/stack.go
+++ b/stack.go
@@ -5,6 +5,7 @@ import (
"io"
"path"
"runtime"
+ "strconv"
"strings"
)
@@ -37,6 +38,15 @@ func (f Frame) line() int {
return line
}
+// name returns the name of this function, if known.
+func (f Frame) name() string {
+ fn := runtime.FuncForPC(f.pc())
+ if fn == nil {
+ return "unknown"
+ }
+ return fn.Name()
+}
+
// Format formats the frame according to the fmt.Formatter interface.
//
// %s source file
@@ -54,22 +64,16 @@ func (f Frame) Format(s fmt.State, verb rune) {
case 's':
switch {
case s.Flag('+'):
- pc := f.pc()
- fn := runtime.FuncForPC(pc)
- if fn == nil {
- io.WriteString(s, "unknown")
- } else {
- file, _ := fn.FileLine(pc)
- fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file)
- }
+ io.WriteString(s, f.name())
+ io.WriteString(s, "\n\t")
+ io.WriteString(s, f.file())
default:
io.WriteString(s, path.Base(f.file()))
}
case 'd':
- fmt.Fprintf(s, "%d", f.line())
+ io.WriteString(s, strconv.Itoa(f.line()))
case 'n':
- name := runtime.FuncForPC(f.pc()).Name()
- io.WriteString(s, funcname(name))
+ io.WriteString(s, funcname(f.name()))
case 'v':
f.Format(s, 's')
io.WriteString(s, ":")
diff --git a/stack_test.go b/stack_test.go
index 85fc419..bc1b3fb 100644
--- a/stack_test.go
+++ b/stack_test.go
@@ -6,51 +6,18 @@ import (
"testing"
)
-var initpc, _, _, _ = runtime.Caller(0)
-
-func TestFrameLine(t *testing.T) {
- var tests = []struct {
- Frame
- want int
- }{{
- Frame(initpc),
- 9,
- }, {
- func() Frame {
- var pc, _, _, _ = runtime.Caller(0)
- return Frame(pc)
- }(),
- 20,
- }, {
- func() Frame {
- var pc, _, _, _ = runtime.Caller(1)
- return Frame(pc)
- }(),
- 28,
- }, {
- Frame(0), // invalid PC
- 0,
- }}
-
- for _, tt := range tests {
- got := tt.Frame.line()
- want := tt.want
- if want != got {
- t.Errorf("Frame(%v): want: %v, got: %v", uintptr(tt.Frame), want, got)
- }
- }
-}
+var initpc = caller()
type X struct{}
+// val returns a Frame pointing to itself.
func (x X) val() Frame {
- var pc, _, _, _ = runtime.Caller(0)
- return Frame(pc)
+ return caller()
}
+// ptr returns a Frame pointing to itself.
func (x *X) ptr() Frame {
- var pc, _, _, _ = runtime.Caller(0)
- return Frame(pc)
+ return caller()
}
func TestFrameFormat(t *testing.T) {
@@ -59,32 +26,32 @@ func TestFrameFormat(t *testing.T) {
format string
want string
}{{
- Frame(initpc),
+ initpc,
"%s",
"stack_test.go",
}, {
- Frame(initpc),
+ initpc,
"%+s",
"github.com/pkg/errors.init\n" +
"\t.+/github.com/pkg/errors/stack_test.go",
}, {
- Frame(0),
+ 0,
"%s",
"unknown",
}, {
- Frame(0),
+ 0,
"%+s",
"unknown",
}, {
- Frame(initpc),
+ initpc,
"%d",
"9",
}, {
- Frame(0),
+ 0,
"%d",
"0",
}, {
- Frame(initpc),
+ initpc,
"%n",
"init",
}, {
@@ -102,20 +69,20 @@ func TestFrameFormat(t *testing.T) {
"%n",
"X.val",
}, {
- Frame(0),
+ 0,
"%n",
"",
}, {
- Frame(initpc),
+ initpc,
"%v",
"stack_test.go:9",
}, {
- Frame(initpc),
+ initpc,
"%+v",
"github.com/pkg/errors.init\n" +
"\t.+/github.com/pkg/errors/stack_test.go:9",
}, {
- Frame(0),
+ 0,
"%v",
"unknown:0",
}}
@@ -153,24 +120,24 @@ func TestStackTrace(t *testing.T) {
}{{
New("ooh"), []string{
"github.com/pkg/errors.TestStackTrace\n" +
- "\t.+/github.com/pkg/errors/stack_test.go:154",
+ "\t.+/github.com/pkg/errors/stack_test.go:121",
},
}, {
Wrap(New("ooh"), "ahh"), []string{
"github.com/pkg/errors.TestStackTrace\n" +
- "\t.+/github.com/pkg/errors/stack_test.go:159", // this is the stack of Wrap, not New
+ "\t.+/github.com/pkg/errors/stack_test.go:126", // this is the stack of Wrap, not New
},
}, {
Cause(Wrap(New("ooh"), "ahh")), []string{
"github.com/pkg/errors.TestStackTrace\n" +
- "\t.+/github.com/pkg/errors/stack_test.go:164", // this is the stack of New
+ "\t.+/github.com/pkg/errors/stack_test.go:131", // this is the stack of New
},
}, {
- func() error { return New("ooh") }(), []string{
+ func() error { noinline(); return New("ooh") }(), []string{
`github.com/pkg/errors.(func·009|TestStackTrace.func1)` +
- "\n\t.+/github.com/pkg/errors/stack_test.go:169", // this is the stack of New
+ "\n\t.+/github.com/pkg/errors/stack_test.go:136", // this is the stack of New
"github.com/pkg/errors.TestStackTrace\n" +
- "\t.+/github.com/pkg/errors/stack_test.go:169", // this is the stack of New's caller
+ "\t.+/github.com/pkg/errors/stack_test.go:136", // this is the stack of New's caller
},
}, {
Cause(func() error {
@@ -179,11 +146,11 @@ func TestStackTrace(t *testing.T) {
}()
}()), []string{
`github.com/pkg/errors.(func·010|TestStackTrace.func2.1)` +
- "\n\t.+/github.com/pkg/errors/stack_test.go:178", // this is the stack of Errorf
+ "\n\t.+/github.com/pkg/errors/stack_test.go:145", // this is the stack of Errorf
`github.com/pkg/errors.(func·011|TestStackTrace.func2)` +
- "\n\t.+/github.com/pkg/errors/stack_test.go:179", // this is the stack of Errorf's caller
+ "\n\t.+/github.com/pkg/errors/stack_test.go:146", // this is the stack of Errorf's caller
"github.com/pkg/errors.TestStackTrace\n" +
- "\t.+/github.com/pkg/errors/stack_test.go:180", // this is the stack of Errorf's caller's caller
+ "\t.+/github.com/pkg/errors/stack_test.go:147", // this is the stack of Errorf's caller's caller
},
}}
for i, tt := range tests {
@@ -253,22 +220,35 @@ func TestStackTraceFormat(t *testing.T) {
}, {
stackTrace()[:2],
"%v",
- `\[stack_test.go:207 stack_test.go:254\]`,
+ `\[stack_test.go:174 stack_test.go:221\]`,
}, {
stackTrace()[:2],
"%+v",
"\n" +
"github.com/pkg/errors.stackTrace\n" +
- "\t.+/github.com/pkg/errors/stack_test.go:207\n" +
+ "\t.+/github.com/pkg/errors/stack_test.go:174\n" +
"github.com/pkg/errors.TestStackTraceFormat\n" +
- "\t.+/github.com/pkg/errors/stack_test.go:258",
+ "\t.+/github.com/pkg/errors/stack_test.go:225",
}, {
stackTrace()[:2],
"%#v",
- `\[\]errors.Frame{stack_test.go:207, stack_test.go:266}`,
+ `\[\]errors.Frame{stack_test.go:174, stack_test.go:233}`,
}}
for i, tt := range tests {
testFormatRegexp(t, i, tt.StackTrace, tt.format, tt.want)
}
}
+
+// a version of runtime.Caller that returns a Frame, not a uintptr.
+func caller() Frame {
+ var pcs [3]uintptr
+ n := runtime.Callers(2, pcs[:])
+ frames := runtime.CallersFrames(pcs[:n])
+ frame, _ := frames.Next()
+ return Frame(frame.PC)
+}
+
+//go:noinline
+// noinline prevents the caller being inlined
+func noinline() {}
--
2.20.1