| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- package errors
- import (
- "fmt"
- "runtime"
- "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)
- }
- }
- }
- type X struct{}
- func (x X) val() Frame {
- var pc, _, _, _ = runtime.Caller(0)
- return Frame(pc)
- }
- func (x *X) ptr() Frame {
- var pc, _, _, _ = runtime.Caller(0)
- return Frame(pc)
- }
- func TestFrameFormat(t *testing.T) {
- var tests = []struct {
- Frame
- format string
- want string
- }{{
- Frame(initpc),
- "%s",
- "stack_test.go",
- }, {
- Frame(initpc),
- "%+s",
- "github.com/pkg/errors/stack_test.go",
- }, {
- Frame(0),
- "%s",
- "unknown",
- }, {
- Frame(0),
- "%+s",
- "unknown",
- }, {
- Frame(initpc),
- "%d",
- "9",
- }, {
- Frame(0),
- "%d",
- "0",
- }, {
- Frame(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",
- }, {
- Frame(0),
- "%n",
- "",
- }, {
- Frame(initpc),
- "%v",
- "stack_test.go:9",
- }, {
- Frame(initpc),
- "%+v",
- "github.com/pkg/errors/stack_test.go:9",
- }, {
- Frame(0),
- "%v",
- "unknown:0",
- }}
- for _, tt := range tests {
- got := fmt.Sprintf(tt.format, tt.Frame)
- want := tt.want
- if want != got {
- t.Errorf("%v %q: want: %q, got: %q", tt.Frame, tt.format, want, got)
- }
- }
- }
- func TestFuncname(t *testing.T) {
- tests := []struct {
- name, want string
- }{
- {"", ""},
- {"runtime.main", "main"},
- {"github.com/pkg/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 TestTrimGOPATH(t *testing.T) {
- var tests = []struct {
- Frame
- want string
- }{{
- Frame(initpc),
- "github.com/pkg/errors/stack_test.go",
- }}
- for _, tt := range tests {
- pc := tt.Frame.pc()
- fn := runtime.FuncForPC(pc)
- file, _ := fn.FileLine(pc)
- got := trimGOPATH(fn.Name(), file)
- want := tt.want
- if want != got {
- t.Errorf("%v: want %q, got %q", tt.Frame, want, got)
- }
- }
- }
- func TestStacktrace(t *testing.T) {
- tests := []struct {
- err error
- want []string
- }{{
- New("ooh"), []string{
- "github.com/pkg/errors/stack_test.go:177",
- },
- }, {
- Wrap(New("ooh"), "ahh"), []string{
- "github.com/pkg/errors/stack_test.go:181", // this is the stack of Wrap, not New
- },
- }, {
- Cause(Wrap(New("ooh"), "ahh")), []string{
- "github.com/pkg/errors/stack_test.go:185", // this is the stack of New
- },
- }, {
- func() error { return New("ooh") }(), []string{
- "github.com/pkg/errors/stack_test.go:189", // this is the stack of New
- "github.com/pkg/errors/stack_test.go:189", // this is the stack of New's caller
- },
- }, {
- Cause(func() error {
- return func() error {
- return Errorf("hello %s", fmt.Sprintf("world"))
- }()
- }()), []string{
- "github.com/pkg/errors/stack_test.go:196", // this is the stack of Errorf
- "github.com/pkg/errors/stack_test.go:197", // this is the stack of Errorf's caller
- "github.com/pkg/errors/stack_test.go:198", // this is the stack of Errorf's caller's caller
- },
- }}
- 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()
- for j, want := range tt.want {
- frame := st[j]
- got := fmt.Sprintf("%+v", frame)
- if got != want {
- t.Errorf("test %d: frame %d: got %q, want %q", i, j, got, 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:226 stack_test.go:273]",
- }, {
- stacktrace()[:2],
- "%+v",
- "[github.com/pkg/errors/stack_test.go:226 github.com/pkg/errors/stack_test.go:277]",
- }, {
- stacktrace()[:2],
- "%#v",
- "[]errors.Frame{stack_test.go:226, stack_test.go:281}",
- }}
- for i, tt := range tests {
- got := fmt.Sprintf(tt.format, tt.Stacktrace)
- if got != tt.want {
- t.Errorf("test %d: got: %q, want: %q", i+1, got, tt.want)
- }
- }
- }
|