Adding upstream version 0.0~git20250501.cd50c6a.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
947813c282
commit
d8f2a7c92a
16 changed files with 3363 additions and 0 deletions
263
stack_test.go
Normal file
263
stack_test.go
Normal file
|
@ -0,0 +1,263 @@
|
|||
package errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var initpc = caller()
|
||||
|
||||
func testFormatRegexp(t *testing.T, n int, arg interface{}, format, want string) {
|
||||
t.Helper()
|
||||
got := fmt.Sprintf(format, arg)
|
||||
gotLines := strings.SplitN(got, "\n", -1)
|
||||
wantLines := strings.SplitN(want, "\n", -1)
|
||||
|
||||
if len(wantLines) > len(gotLines) {
|
||||
t.Errorf("test %d: wantLines(%d) > gotLines(%d):\n got: %q\nwant: %q", n+1, len(wantLines), len(gotLines), got, want)
|
||||
return
|
||||
}
|
||||
|
||||
for i, w := range wantLines {
|
||||
match, err := regexp.MatchString(w, gotLines[i])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !match {
|
||||
t.Errorf("test %d: line %d: fmt.Sprintf(%q, err):\n got: %q\nwant: %q", n+1, i+1, format, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type X struct{}
|
||||
|
||||
// val returns a Frame pointing to itself.
|
||||
func (x X) val() Frame {
|
||||
return caller()
|
||||
}
|
||||
|
||||
// ptr returns a Frame pointing to itself.
|
||||
func (x *X) ptr() Frame {
|
||||
return caller()
|
||||
}
|
||||
|
||||
func TestFrameFormat(t *testing.T) {
|
||||
var tests = []struct {
|
||||
Frame
|
||||
format string
|
||||
want string
|
||||
}{{
|
||||
initpc,
|
||||
"%s",
|
||||
"stack_test.go",
|
||||
}, {
|
||||
initpc,
|
||||
"%+s",
|
||||
"github.com/go-ap/errors.init\n" +
|
||||
"\t.+/errors/stack_test.go",
|
||||
}, {
|
||||
0,
|
||||
"%s",
|
||||
"unknown",
|
||||
}, {
|
||||
0,
|
||||
"%+s",
|
||||
"unknown",
|
||||
}, {
|
||||
initpc,
|
||||
"%d",
|
||||
"11",
|
||||
}, {
|
||||
0,
|
||||
"%d",
|
||||
"0",
|
||||
}, {
|
||||
initpc,
|
||||
"%n",
|
||||
"init",
|
||||
}, {
|
||||
func() Frame {
|
||||
var x X
|
||||
return x.ptr()
|
||||
}(),
|
||||
"%n",
|
||||
`\(\*X\).ptr`,
|
||||
}, {
|
||||
func() Frame {
|
||||
var x X
|
||||
return x.val()
|
||||
}(),
|
||||
"%n",
|
||||
"X.val",
|
||||
}, {
|
||||
0,
|
||||
"%n",
|
||||
"",
|
||||
}, {
|
||||
initpc,
|
||||
"%v",
|
||||
"stack_test.go:11",
|
||||
}, {
|
||||
initpc,
|
||||
"%+v",
|
||||
"github.com/go-ap/errors.init\n" +
|
||||
"\t.+/errors/stack_test.go:11",
|
||||
}, {
|
||||
0,
|
||||
"%v",
|
||||
"unknown:0",
|
||||
}}
|
||||
|
||||
for i, tt := range tests {
|
||||
testFormatRegexp(t, i, tt.Frame, tt.format, tt.want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuncname(t *testing.T) {
|
||||
tests := []struct {
|
||||
name, want string
|
||||
}{
|
||||
{"", ""},
|
||||
{"runtime.main", "main"},
|
||||
{"github.com/go-ap/errors.funcname", "funcname"},
|
||||
{"funcname", "funcname"},
|
||||
{"io.copyBuffer", "copyBuffer"},
|
||||
{"main.(*R).Write", "(*R).Write"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := funcname(tt.name)
|
||||
want := tt.want
|
||||
if got != want {
|
||||
t.Errorf("funcname(%q): want: %q, got %q", tt.name, want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStackTrace(t *testing.T) {
|
||||
tests := []struct {
|
||||
err error
|
||||
want []string
|
||||
}{{
|
||||
Newf("ooh"), []string{
|
||||
"github.com/go-ap/errors.TestStackTrace\n" +
|
||||
"\t.+/errors/stack_test.go:145",
|
||||
},
|
||||
}, {
|
||||
wrap(Newf("ooh"), "ahh"), []string{
|
||||
"github.com/go-ap/errors.TestStackTrace\n" +
|
||||
"\t.+/errors/stack_test.go:150", // this is the stack of Wrap, not New
|
||||
},
|
||||
}, {
|
||||
func() error { return Newf("ooh") }(), []string{
|
||||
`github.com/go-ap/errors.TestStackTrace.func1` +
|
||||
"\n\t.+/errors/stack_test.go:155", // this is the stack of New
|
||||
"github.com/go-ap/errors.TestStackTrace\n" +
|
||||
"\t.+/errors/stack_test.go:155", // this is the stack of New's caller
|
||||
},
|
||||
}}
|
||||
t.Skipf(`TODO(marius): This needs some more work
|
||||
As going one level up the stack in stack.callers() removes meaningful information from the tests`)
|
||||
for i, tt := range tests {
|
||||
x, ok := tt.err.(interface {
|
||||
StackTrace() StackTrace
|
||||
})
|
||||
if !ok {
|
||||
t.Errorf("expected %#v to implement StackTrace() StackTrace", tt.err)
|
||||
continue
|
||||
}
|
||||
st := x.StackTrace()
|
||||
if len(st) == 0 {
|
||||
continue
|
||||
}
|
||||
for j, want := range tt.want {
|
||||
testFormatRegexp(t, i, st[j], "%+v", want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func stackTrace() StackTrace {
|
||||
const depth = 8
|
||||
var pcs [depth]uintptr
|
||||
n := runtime.Callers(1, pcs[:])
|
||||
var st stack = pcs[0:n]
|
||||
return st.StackTrace()
|
||||
}
|
||||
|
||||
func TestStackTraceFormat(t *testing.T) {
|
||||
tests := []struct {
|
||||
StackTrace
|
||||
format string
|
||||
want string
|
||||
}{{
|
||||
nil,
|
||||
"%s",
|
||||
`\[\]`,
|
||||
}, {
|
||||
nil,
|
||||
"%v",
|
||||
`\[\]`,
|
||||
}, {
|
||||
nil,
|
||||
"%+v",
|
||||
"",
|
||||
}, {
|
||||
nil,
|
||||
"%#v",
|
||||
`\[\]errors.Frame\(nil\)`,
|
||||
}, {
|
||||
make(StackTrace, 0),
|
||||
"%s",
|
||||
`\[\]`,
|
||||
}, {
|
||||
make(StackTrace, 0),
|
||||
"%v",
|
||||
`\[\]`,
|
||||
}, {
|
||||
make(StackTrace, 0),
|
||||
"%+v",
|
||||
"",
|
||||
}, {
|
||||
make(StackTrace, 0),
|
||||
"%#v",
|
||||
`\[\]errors.Frame{}`,
|
||||
}, {
|
||||
stackTrace()[:2],
|
||||
"%s",
|
||||
`\[stack_test.go stack_test.go\]`,
|
||||
}, {
|
||||
stackTrace()[:2],
|
||||
"%v",
|
||||
`\[stack_test.go:183 stack_test.go:230\]`,
|
||||
}, {
|
||||
stackTrace()[:2],
|
||||
"%+v",
|
||||
"\n" +
|
||||
"github.com/go-ap/errors.stackTrace\n" +
|
||||
"\t.+/errors/stack_test.go:183\n" +
|
||||
"github.com/go-ap/errors.TestStackTraceFormat\n" +
|
||||
"\t.+/errors/stack_test.go:234",
|
||||
}, {
|
||||
stackTrace()[:2],
|
||||
"%#v",
|
||||
`\[\]errors.Frame{stack_test.go:183, stack_test.go:242}`,
|
||||
}}
|
||||
|
||||
t.Skipf(`TODO(marius): This needs some more work
|
||||
As going one level up the stack in stack.callers() removes meaningful information from the tests`)
|
||||
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)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue