OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / go-stack / stack / stack_test.go
1 package stack_test
2
3 import (
4         "fmt"
5         "io/ioutil"
6         "path"
7         "path/filepath"
8         "reflect"
9         "runtime"
10         "strings"
11         "testing"
12
13         "github.com/go-stack/stack"
14 )
15
16 const importPath = "github.com/go-stack/stack"
17
18 type testType struct{}
19
20 func (tt testType) testMethod() (c stack.Call, pc uintptr, file string, line int, ok bool) {
21         c = stack.Caller(0)
22         pc, file, line, ok = runtime.Caller(0)
23         line--
24         return
25 }
26
27 func TestCallFormat(t *testing.T) {
28         t.Parallel()
29
30         c := stack.Caller(0)
31         pc, file, line, ok := runtime.Caller(0)
32         line--
33         if !ok {
34                 t.Fatal("runtime.Caller(0) failed")
35         }
36         relFile := path.Join(importPath, filepath.Base(file))
37
38         c2, pc2, file2, line2, ok2 := testType{}.testMethod()
39         if !ok2 {
40                 t.Fatal("runtime.Caller(0) failed")
41         }
42         relFile2 := path.Join(importPath, filepath.Base(file2))
43
44         data := []struct {
45                 c    stack.Call
46                 desc string
47                 fmt  string
48                 out  string
49         }{
50                 {stack.Call{}, "error", "%s", "%!s(NOFUNC)"},
51
52                 {c, "func", "%s", path.Base(file)},
53                 {c, "func", "%+s", relFile},
54                 {c, "func", "%#s", file},
55                 {c, "func", "%d", fmt.Sprint(line)},
56                 {c, "func", "%n", "TestCallFormat"},
57                 {c, "func", "%+n", runtime.FuncForPC(pc - 1).Name()},
58                 {c, "func", "%k", "stack_test"},
59                 {c, "func", "%+k", "github.com/go-stack/stack_test"},
60                 {c, "func", "%v", fmt.Sprint(path.Base(file), ":", line)},
61                 {c, "func", "%+v", fmt.Sprint(relFile, ":", line)},
62                 {c, "func", "%#v", fmt.Sprint(file, ":", line)},
63
64                 {c2, "meth", "%s", path.Base(file2)},
65                 {c2, "meth", "%+s", relFile2},
66                 {c2, "meth", "%#s", file2},
67                 {c2, "meth", "%d", fmt.Sprint(line2)},
68                 {c2, "meth", "%n", "testType.testMethod"},
69                 {c2, "meth", "%+n", runtime.FuncForPC(pc2).Name()},
70                 {c2, "meth", "%k", "stack_test"},
71                 {c2, "meth", "%+k", "github.com/go-stack/stack_test"},
72                 {c2, "meth", "%v", fmt.Sprint(path.Base(file2), ":", line2)},
73                 {c2, "meth", "%+v", fmt.Sprint(relFile2, ":", line2)},
74                 {c2, "meth", "%#v", fmt.Sprint(file2, ":", line2)},
75         }
76
77         for _, d := range data {
78                 got := fmt.Sprintf(d.fmt, d.c)
79                 if got != d.out {
80                         t.Errorf("fmt.Sprintf(%q, Call(%s)) = %s, want %s", d.fmt, d.desc, got, d.out)
81                 }
82         }
83 }
84
85 func TestCallString(t *testing.T) {
86         t.Parallel()
87
88         c := stack.Caller(0)
89         _, file, line, ok := runtime.Caller(0)
90         line--
91         if !ok {
92                 t.Fatal("runtime.Caller(0) failed")
93         }
94
95         c2, _, file2, line2, ok2 := testType{}.testMethod()
96         if !ok2 {
97                 t.Fatal("runtime.Caller(0) failed")
98         }
99
100         data := []struct {
101                 c    stack.Call
102                 desc string
103                 out  string
104         }{
105                 {stack.Call{}, "error", "%!v(NOFUNC)"},
106                 {c, "func", fmt.Sprint(path.Base(file), ":", line)},
107                 {c2, "meth", fmt.Sprint(path.Base(file2), ":", line2)},
108         }
109
110         for _, d := range data {
111                 got := d.c.String()
112                 if got != d.out {
113                         t.Errorf("got %s, want %s", got, d.out)
114                 }
115         }
116 }
117
118 func TestCallMarshalText(t *testing.T) {
119         t.Parallel()
120
121         c := stack.Caller(0)
122         _, file, line, ok := runtime.Caller(0)
123         line--
124         if !ok {
125                 t.Fatal("runtime.Caller(0) failed")
126         }
127
128         c2, _, file2, line2, ok2 := testType{}.testMethod()
129         if !ok2 {
130                 t.Fatal("runtime.Caller(0) failed")
131         }
132
133         data := []struct {
134                 c    stack.Call
135                 desc string
136                 out  []byte
137                 err  error
138         }{
139                 {stack.Call{}, "error", nil, stack.ErrNoFunc},
140                 {c, "func", []byte(fmt.Sprint(path.Base(file), ":", line)), nil},
141                 {c2, "meth", []byte(fmt.Sprint(path.Base(file2), ":", line2)), nil},
142         }
143
144         for _, d := range data {
145                 text, err := d.c.MarshalText()
146                 if got, want := err, d.err; got != want {
147                         t.Errorf("%s: got err %v, want err %v", d.desc, got, want)
148                 }
149                 if got, want := text, d.out; !reflect.DeepEqual(got, want) {
150                         t.Errorf("%s: got %s, want %s", d.desc, got, want)
151                 }
152         }
153 }
154
155 func TestCallStackString(t *testing.T) {
156         cs, line0 := getTrace(t)
157         _, file, line1, ok := runtime.Caller(0)
158         line1--
159         if !ok {
160                 t.Fatal("runtime.Caller(0) failed")
161         }
162         file = path.Base(file)
163         if got, want := cs.String(), fmt.Sprintf("[%s:%d %s:%d]", file, line0, file, line1); got != want {
164                 t.Errorf("\n got %v\nwant %v", got, want)
165         }
166 }
167
168 func TestCallStackMarshalText(t *testing.T) {
169         cs, line0 := getTrace(t)
170         _, file, line1, ok := runtime.Caller(0)
171         line1--
172         if !ok {
173                 t.Fatal("runtime.Caller(0) failed")
174         }
175         file = path.Base(file)
176         text, _ := cs.MarshalText()
177         if got, want := text, []byte(fmt.Sprintf("[%s:%d %s:%d]", file, line0, file, line1)); !reflect.DeepEqual(got, want) {
178                 t.Errorf("\n got %v\nwant %v", got, want)
179         }
180 }
181 func getTrace(t *testing.T) (stack.CallStack, int) {
182         cs := stack.Trace().TrimRuntime()
183         _, _, line, ok := runtime.Caller(0)
184         line--
185         if !ok {
186                 t.Fatal("runtime.Caller(0) failed")
187         }
188         return cs, line
189 }
190
191 func TestTrimAbove(t *testing.T) {
192         trace := trimAbove()
193         if got, want := len(trace), 2; got != want {
194                 t.Errorf("got len(trace) == %v, want %v, trace: %n", got, want, trace)
195         }
196         if got, want := fmt.Sprintf("%n", trace[1]), "TestTrimAbove"; got != want {
197                 t.Errorf("got %q, want %q", got, want)
198         }
199 }
200
201 func trimAbove() stack.CallStack {
202         call := stack.Caller(1)
203         trace := stack.Trace()
204         return trace.TrimAbove(call)
205 }
206
207 func TestTrimBelow(t *testing.T) {
208         trace := trimBelow()
209         if got, want := fmt.Sprintf("%n", trace[0]), "TestTrimBelow"; got != want {
210                 t.Errorf("got %q, want %q", got, want)
211         }
212 }
213
214 func trimBelow() stack.CallStack {
215         call := stack.Caller(1)
216         trace := stack.Trace()
217         return trace.TrimBelow(call)
218 }
219
220 func TestTrimRuntime(t *testing.T) {
221         trace := stack.Trace().TrimRuntime()
222         if got, want := len(trace), 1; got != want {
223                 t.Errorf("got len(trace) == %v, want %v, goroot: %q, trace: %#v", got, want, runtime.GOROOT(), trace)
224         }
225 }
226
227 func BenchmarkCallVFmt(b *testing.B) {
228         c := stack.Caller(0)
229         b.ResetTimer()
230         for i := 0; i < b.N; i++ {
231                 fmt.Fprint(ioutil.Discard, c)
232         }
233 }
234
235 func BenchmarkCallPlusVFmt(b *testing.B) {
236         c := stack.Caller(0)
237         b.ResetTimer()
238         for i := 0; i < b.N; i++ {
239                 fmt.Fprintf(ioutil.Discard, "%+v", c)
240         }
241 }
242
243 func BenchmarkCallSharpVFmt(b *testing.B) {
244         c := stack.Caller(0)
245         b.ResetTimer()
246         for i := 0; i < b.N; i++ {
247                 fmt.Fprintf(ioutil.Discard, "%#v", c)
248         }
249 }
250
251 func BenchmarkCallSFmt(b *testing.B) {
252         c := stack.Caller(0)
253         b.ResetTimer()
254         for i := 0; i < b.N; i++ {
255                 fmt.Fprintf(ioutil.Discard, "%s", c)
256         }
257 }
258
259 func BenchmarkCallPlusSFmt(b *testing.B) {
260         c := stack.Caller(0)
261         b.ResetTimer()
262         for i := 0; i < b.N; i++ {
263                 fmt.Fprintf(ioutil.Discard, "%+s", c)
264         }
265 }
266
267 func BenchmarkCallSharpSFmt(b *testing.B) {
268         c := stack.Caller(0)
269         b.ResetTimer()
270         for i := 0; i < b.N; i++ {
271                 fmt.Fprintf(ioutil.Discard, "%#s", c)
272         }
273 }
274
275 func BenchmarkCallDFmt(b *testing.B) {
276         c := stack.Caller(0)
277         b.ResetTimer()
278         for i := 0; i < b.N; i++ {
279                 fmt.Fprintf(ioutil.Discard, "%d", c)
280         }
281 }
282
283 func BenchmarkCallNFmt(b *testing.B) {
284         c := stack.Caller(0)
285         b.ResetTimer()
286         for i := 0; i < b.N; i++ {
287                 fmt.Fprintf(ioutil.Discard, "%n", c)
288         }
289 }
290
291 func BenchmarkCallPlusNFmt(b *testing.B) {
292         c := stack.Caller(0)
293         b.ResetTimer()
294         for i := 0; i < b.N; i++ {
295                 fmt.Fprintf(ioutil.Discard, "%+n", c)
296         }
297 }
298
299 func BenchmarkCaller(b *testing.B) {
300         for i := 0; i < b.N; i++ {
301                 stack.Caller(0)
302         }
303 }
304
305 func BenchmarkTrace(b *testing.B) {
306         for i := 0; i < b.N; i++ {
307                 stack.Trace()
308         }
309 }
310
311 func deepStack(depth int, b *testing.B) stack.CallStack {
312         if depth > 0 {
313                 return deepStack(depth-1, b)
314         }
315         b.StartTimer()
316         s := stack.Trace()
317         return s
318 }
319
320 func BenchmarkTrace10(b *testing.B) {
321         for i := 0; i < b.N; i++ {
322                 b.StopTimer()
323                 deepStack(10, b)
324         }
325 }
326
327 func BenchmarkTrace50(b *testing.B) {
328         b.StopTimer()
329         for i := 0; i < b.N; i++ {
330                 deepStack(50, b)
331         }
332 }
333
334 func BenchmarkTrace100(b *testing.B) {
335         b.StopTimer()
336         for i := 0; i < b.N; i++ {
337                 deepStack(100, b)
338         }
339 }
340
341 ////////////////
342 // Benchmark functions followed by formatting
343 ////////////////
344
345 func BenchmarkCallerAndVFmt(b *testing.B) {
346         for i := 0; i < b.N; i++ {
347                 fmt.Fprint(ioutil.Discard, stack.Caller(0))
348         }
349 }
350
351 func BenchmarkTraceAndVFmt(b *testing.B) {
352         for i := 0; i < b.N; i++ {
353                 fmt.Fprint(ioutil.Discard, stack.Trace())
354         }
355 }
356
357 func BenchmarkTrace10AndVFmt(b *testing.B) {
358         for i := 0; i < b.N; i++ {
359                 b.StopTimer()
360                 fmt.Fprint(ioutil.Discard, deepStack(10, b))
361         }
362 }
363
364 ////////////////
365 // Baseline against package runtime.
366 ////////////////
367
368 func BenchmarkRuntimeCaller(b *testing.B) {
369         for i := 0; i < b.N; i++ {
370                 runtime.Caller(0)
371         }
372 }
373
374 func BenchmarkRuntimeCallerAndFmt(b *testing.B) {
375         for i := 0; i < b.N; i++ {
376                 _, file, line, _ := runtime.Caller(0)
377                 const sep = "/"
378                 if i := strings.LastIndex(file, sep); i != -1 {
379                         file = file[i+len(sep):]
380                 }
381                 fmt.Fprint(ioutil.Discard, file, ":", line)
382         }
383 }
384
385 func BenchmarkFuncForPC(b *testing.B) {
386         pc, _, _, _ := runtime.Caller(0)
387         pc--
388         b.ResetTimer()
389         for i := 0; i < b.N; i++ {
390                 runtime.FuncForPC(pc)
391         }
392 }
393
394 func BenchmarkFuncFileLine(b *testing.B) {
395         pc, _, _, _ := runtime.Caller(0)
396         pc--
397         fn := runtime.FuncForPC(pc)
398         b.ResetTimer()
399         for i := 0; i < b.N; i++ {
400                 fn.FileLine(pc)
401         }
402 }