OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / github.com / pkg / errors / stack_test.go
1 package errors
2
3 import (
4         "fmt"
5         "runtime"
6         "testing"
7 )
8
9 var initpc, _, _, _ = runtime.Caller(0)
10
11 func TestFrameLine(t *testing.T) {
12         var tests = []struct {
13                 Frame
14                 want int
15         }{{
16                 Frame(initpc),
17                 9,
18         }, {
19                 func() Frame {
20                         var pc, _, _, _ = runtime.Caller(0)
21                         return Frame(pc)
22                 }(),
23                 20,
24         }, {
25                 func() Frame {
26                         var pc, _, _, _ = runtime.Caller(1)
27                         return Frame(pc)
28                 }(),
29                 28,
30         }, {
31                 Frame(0), // invalid PC
32                 0,
33         }}
34
35         for _, tt := range tests {
36                 got := tt.Frame.line()
37                 want := tt.want
38                 if want != got {
39                         t.Errorf("Frame(%v): want: %v, got: %v", uintptr(tt.Frame), want, got)
40                 }
41         }
42 }
43
44 type X struct{}
45
46 func (x X) val() Frame {
47         var pc, _, _, _ = runtime.Caller(0)
48         return Frame(pc)
49 }
50
51 func (x *X) ptr() Frame {
52         var pc, _, _, _ = runtime.Caller(0)
53         return Frame(pc)
54 }
55
56 func TestFrameFormat(t *testing.T) {
57         var tests = []struct {
58                 Frame
59                 format string
60                 want   string
61         }{{
62                 Frame(initpc),
63                 "%s",
64                 "stack_test.go",
65         }, {
66                 Frame(initpc),
67                 "%+s",
68                 "github.com/pkg/errors.init\n" +
69                         "\t.+/github.com/pkg/errors/stack_test.go",
70         }, {
71                 Frame(0),
72                 "%s",
73                 "unknown",
74         }, {
75                 Frame(0),
76                 "%+s",
77                 "unknown",
78         }, {
79                 Frame(initpc),
80                 "%d",
81                 "9",
82         }, {
83                 Frame(0),
84                 "%d",
85                 "0",
86         }, {
87                 Frame(initpc),
88                 "%n",
89                 "init",
90         }, {
91                 func() Frame {
92                         var x X
93                         return x.ptr()
94                 }(),
95                 "%n",
96                 `\(\*X\).ptr`,
97         }, {
98                 func() Frame {
99                         var x X
100                         return x.val()
101                 }(),
102                 "%n",
103                 "X.val",
104         }, {
105                 Frame(0),
106                 "%n",
107                 "",
108         }, {
109                 Frame(initpc),
110                 "%v",
111                 "stack_test.go:9",
112         }, {
113                 Frame(initpc),
114                 "%+v",
115                 "github.com/pkg/errors.init\n" +
116                         "\t.+/github.com/pkg/errors/stack_test.go:9",
117         }, {
118                 Frame(0),
119                 "%v",
120                 "unknown:0",
121         }}
122
123         for i, tt := range tests {
124                 testFormatRegexp(t, i, tt.Frame, tt.format, tt.want)
125         }
126 }
127
128 func TestFuncname(t *testing.T) {
129         tests := []struct {
130                 name, want string
131         }{
132                 {"", ""},
133                 {"runtime.main", "main"},
134                 {"github.com/pkg/errors.funcname", "funcname"},
135                 {"funcname", "funcname"},
136                 {"io.copyBuffer", "copyBuffer"},
137                 {"main.(*R).Write", "(*R).Write"},
138         }
139
140         for _, tt := range tests {
141                 got := funcname(tt.name)
142                 want := tt.want
143                 if got != want {
144                         t.Errorf("funcname(%q): want: %q, got %q", tt.name, want, got)
145                 }
146         }
147 }
148
149 func TestTrimGOPATH(t *testing.T) {
150         var tests = []struct {
151                 Frame
152                 want string
153         }{{
154                 Frame(initpc),
155                 "github.com/pkg/errors/stack_test.go",
156         }}
157
158         for i, tt := range tests {
159                 pc := tt.Frame.pc()
160                 fn := runtime.FuncForPC(pc)
161                 file, _ := fn.FileLine(pc)
162                 got := trimGOPATH(fn.Name(), file)
163                 testFormatRegexp(t, i, got, "%s", tt.want)
164         }
165 }
166
167 func TestStackTrace(t *testing.T) {
168         tests := []struct {
169                 err  error
170                 want []string
171         }{{
172                 New("ooh"), []string{
173                         "github.com/pkg/errors.TestStackTrace\n" +
174                                 "\t.+/github.com/pkg/errors/stack_test.go:172",
175                 },
176         }, {
177                 Wrap(New("ooh"), "ahh"), []string{
178                         "github.com/pkg/errors.TestStackTrace\n" +
179                                 "\t.+/github.com/pkg/errors/stack_test.go:177", // this is the stack of Wrap, not New
180                 },
181         }, {
182                 Cause(Wrap(New("ooh"), "ahh")), []string{
183                         "github.com/pkg/errors.TestStackTrace\n" +
184                                 "\t.+/github.com/pkg/errors/stack_test.go:182", // this is the stack of New
185                 },
186         }, {
187                 func() error { return New("ooh") }(), []string{
188                         `github.com/pkg/errors.(func·009|TestStackTrace.func1)` +
189                                 "\n\t.+/github.com/pkg/errors/stack_test.go:187", // this is the stack of New
190                         "github.com/pkg/errors.TestStackTrace\n" +
191                                 "\t.+/github.com/pkg/errors/stack_test.go:187", // this is the stack of New's caller
192                 },
193         }, {
194                 Cause(func() error {
195                         return func() error {
196                                 return Errorf("hello %s", fmt.Sprintf("world"))
197                         }()
198                 }()), []string{
199                         `github.com/pkg/errors.(func·010|TestStackTrace.func2.1)` +
200                                 "\n\t.+/github.com/pkg/errors/stack_test.go:196", // this is the stack of Errorf
201                         `github.com/pkg/errors.(func·011|TestStackTrace.func2)` +
202                                 "\n\t.+/github.com/pkg/errors/stack_test.go:197", // this is the stack of Errorf's caller
203                         "github.com/pkg/errors.TestStackTrace\n" +
204                                 "\t.+/github.com/pkg/errors/stack_test.go:198", // this is the stack of Errorf's caller's caller
205                 },
206         }}
207         for i, tt := range tests {
208                 x, ok := tt.err.(interface {
209                         StackTrace() StackTrace
210                 })
211                 if !ok {
212                         t.Errorf("expected %#v to implement StackTrace() StackTrace", tt.err)
213                         continue
214                 }
215                 st := x.StackTrace()
216                 for j, want := range tt.want {
217                         testFormatRegexp(t, i, st[j], "%+v", want)
218                 }
219         }
220 }
221
222 func stackTrace() StackTrace {
223         const depth = 8
224         var pcs [depth]uintptr
225         n := runtime.Callers(1, pcs[:])
226         var st stack = pcs[0:n]
227         return st.StackTrace()
228 }
229
230 func TestStackTraceFormat(t *testing.T) {
231         tests := []struct {
232                 StackTrace
233                 format string
234                 want   string
235         }{{
236                 nil,
237                 "%s",
238                 `\[\]`,
239         }, {
240                 nil,
241                 "%v",
242                 `\[\]`,
243         }, {
244                 nil,
245                 "%+v",
246                 "",
247         }, {
248                 nil,
249                 "%#v",
250                 `\[\]errors.Frame\(nil\)`,
251         }, {
252                 make(StackTrace, 0),
253                 "%s",
254                 `\[\]`,
255         }, {
256                 make(StackTrace, 0),
257                 "%v",
258                 `\[\]`,
259         }, {
260                 make(StackTrace, 0),
261                 "%+v",
262                 "",
263         }, {
264                 make(StackTrace, 0),
265                 "%#v",
266                 `\[\]errors.Frame{}`,
267         }, {
268                 stackTrace()[:2],
269                 "%s",
270                 `\[stack_test.go stack_test.go\]`,
271         }, {
272                 stackTrace()[:2],
273                 "%v",
274                 `\[stack_test.go:225 stack_test.go:272\]`,
275         }, {
276                 stackTrace()[:2],
277                 "%+v",
278                 "\n" +
279                         "github.com/pkg/errors.stackTrace\n" +
280                         "\t.+/github.com/pkg/errors/stack_test.go:225\n" +
281                         "github.com/pkg/errors.TestStackTraceFormat\n" +
282                         "\t.+/github.com/pkg/errors/stack_test.go:276",
283         }, {
284                 stackTrace()[:2],
285                 "%#v",
286                 `\[\]errors.Frame{stack_test.go:225, stack_test.go:284}`,
287         }}
288
289         for i, tt := range tests {
290                 testFormatRegexp(t, i, tt.StackTrace, tt.format, tt.want)
291         }
292 }