Codebase list golang-github-go-stack-stack / e140d45
Update upstream source from tag 'upstream/1.8.0' Update to upstream version '1.8.0' with Debian dir cecb5028e296fb2779a2e4edbf51f649ee09a6ef Shengjing Zhu 4 years ago
7 changed file(s) with 436 addition(s) and 191 deletion(s). Raw diff Collapse all Expand all
00 language: go
11 sudo: false
22 go:
3 - 1.2
4 - 1.3
5 - 1.4
6 - 1.5
7 - 1.6
3 - 1.7.x
4 - 1.8.x
5 - 1.9.x
6 - 1.10.x
7 - 1.11.x
88 - tip
99
1010 before_install:
1111 - go get github.com/mattn/goveralls
12 - go get golang.org/x/tools/cmd/cover
1312
1413 script:
1514 - goveralls -service=travis-ci
0 Copyright 2014 Chris Hines
0 The MIT License (MIT)
11
2 Licensed under the Apache License, Version 2.0 (the "License");
3 you may not use this file except in compliance with the License.
4 You may obtain a copy of the License at
2 Copyright (c) 2014 Chris Hines
53
6 http://www.apache.org/licenses/LICENSE-2.0
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
710
8 Unless required by applicable law or agreed to in writing, software
9 distributed under the License is distributed on an "AS IS" BASIS,
10 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 See the License for the specific language governing permissions and
12 limitations under the License.
11 The above copyright notice and this permission notice shall be included in all
12 copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 SOFTWARE.
0 module github.com/go-stack/stack
0 // +build go1.9
1
2 package stack_test
3
4 import (
5 "runtime"
6 "testing"
7
8 "github.com/go-stack/stack"
9 )
10
11 func TestCallerInlinedPanic(t *testing.T) {
12 t.Parallel()
13
14 var line int
15
16 defer func() {
17 if recover() != nil {
18 var pcs [32]uintptr
19 n := runtime.Callers(1, pcs[:])
20 frames := runtime.CallersFrames(pcs[:n])
21 // count frames to runtime.sigpanic
22 panicIdx := 0
23 for {
24 f, more := frames.Next()
25 if f.Function == "runtime.sigpanic" {
26 break
27 }
28 panicIdx++
29 if !more {
30 t.Fatal("no runtime.sigpanic entry on the stack")
31 }
32 }
33
34 c := stack.Caller(panicIdx)
35 if got, want := c.Frame().Function, "runtime.sigpanic"; got != want {
36 t.Errorf("sigpanic frame: got name == %v, want name == %v", got, want)
37 }
38
39 c1 := stack.Caller(panicIdx + 1)
40 if got, want := c1.Frame().Function, "github.com/go-stack/stack_test.inlinablePanic"; got != want {
41 t.Errorf("TestCallerInlinedPanic frame: got name == %v, want name == %v", got, want)
42 }
43 if got, want := c1.Frame().Line, line; got != want {
44 t.Errorf("TestCallerInlinedPanic frame: got line == %v, want line == %v", got, want)
45 }
46 }
47 }()
48
49 doPanic(t, &line)
50 t.Fatal("failed to panic")
51 }
52
53 func doPanic(t *testing.T, panicLine *int) {
54 _, _, line, ok := runtime.Caller(0)
55 *panicLine = line + 11 // adjust to match line of panic below
56 if !ok {
57 t.Fatal("runtime.Caller(0) failed")
58 }
59 inlinablePanic()
60 }
61
62 func inlinablePanic() {
63 // Initiate a sigpanic.
64 var x *uintptr
65 _ = *x
66 }
+152
-101
stack.go less more
0 // +build go1.7
1
02 // Package stack implements utilities to capture, manipulate, and format call
13 // stacks. It provides a simpler API than package runtime.
24 //
2022
2123 // Call records a single function invocation from a goroutine stack.
2224 type Call struct {
23 fn *runtime.Func
24 pc uintptr
25 frame runtime.Frame
2526 }
2627
2728 // Caller returns a Call from the stack of the current goroutine. The argument
2829 // skip is the number of stack frames to ascend, with 0 identifying the
2930 // calling function.
3031 func Caller(skip int) Call {
31 var pcs [2]uintptr
32 // As of Go 1.9 we need room for up to three PC entries.
33 //
34 // 0. An entry for the stack frame prior to the target to check for
35 // special handling needed if that prior entry is runtime.sigpanic.
36 // 1. A possible second entry to hold metadata about skipped inlined
37 // functions. If inline functions were not skipped the target frame
38 // PC will be here.
39 // 2. A third entry for the target frame PC when the second entry
40 // is used for skipped inline functions.
41 var pcs [3]uintptr
3242 n := runtime.Callers(skip+1, pcs[:])
33
34 var c Call
35
36 if n < 2 {
37 return c
38 }
39
40 c.pc = pcs[1]
41 if runtime.FuncForPC(pcs[0]) != sigpanic {
42 c.pc--
43 }
44 c.fn = runtime.FuncForPC(c.pc)
45 return c
43 frames := runtime.CallersFrames(pcs[:n])
44 frame, _ := frames.Next()
45 frame, _ = frames.Next()
46
47 return Call{
48 frame: frame,
49 }
4650 }
4751
4852 // String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", c).
5357 // MarshalText implements encoding.TextMarshaler. It formats the Call the same
5458 // as fmt.Sprintf("%v", c).
5559 func (c Call) MarshalText() ([]byte, error) {
56 if c.fn == nil {
60 if c.frame == (runtime.Frame{}) {
5761 return nil, ErrNoFunc
5862 }
63
5964 buf := bytes.Buffer{}
6065 fmt.Fprint(&buf, c)
6166 return buf.Bytes(), nil
7075 // %s source file
7176 // %d line number
7277 // %n function name
78 // %k last segment of the package path
7379 // %v equivalent to %s:%d
7480 //
7581 // It accepts the '+' and '#' flags for most of the verbs as follows.
7682 //
77 // %+s path of source file relative to the compile time GOPATH
83 // %+s path of source file relative to the compile time GOPATH,
84 // or the module path joined to the path of source file relative
85 // to module root
7886 // %#s full path of source file
7987 // %+n import path qualified function name
88 // %+k full package path
8089 // %+v equivalent to %+s:%d
8190 // %#v equivalent to %#s:%d
8291 func (c Call) Format(s fmt.State, verb rune) {
83 if c.fn == nil {
92 if c.frame == (runtime.Frame{}) {
8493 fmt.Fprintf(s, "%%!%c(NOFUNC)", verb)
8594 return
8695 }
8796
8897 switch verb {
8998 case 's', 'v':
90 file, line := c.fn.FileLine(c.pc)
99 file := c.frame.File
91100 switch {
92101 case s.Flag('#'):
93102 // done
94103 case s.Flag('+'):
95 file = file[pkgIndex(file, c.fn.Name()):]
104 file = pkgFilePath(&c.frame)
96105 default:
97106 const sep = "/"
98107 if i := strings.LastIndex(file, sep); i != -1 {
102111 io.WriteString(s, file)
103112 if verb == 'v' {
104113 buf := [7]byte{':'}
105 s.Write(strconv.AppendInt(buf[:1], int64(line), 10))
114 s.Write(strconv.AppendInt(buf[:1], int64(c.frame.Line), 10))
106115 }
107116
108117 case 'd':
109 _, line := c.fn.FileLine(c.pc)
110118 buf := [6]byte{}
111 s.Write(strconv.AppendInt(buf[:0], int64(line), 10))
119 s.Write(strconv.AppendInt(buf[:0], int64(c.frame.Line), 10))
120
121 case 'k':
122 name := c.frame.Function
123 const pathSep = "/"
124 start, end := 0, len(name)
125 if i := strings.LastIndex(name, pathSep); i != -1 {
126 start = i + len(pathSep)
127 }
128 const pkgSep = "."
129 if i := strings.Index(name[start:], pkgSep); i != -1 {
130 end = start + i
131 }
132 if s.Flag('+') {
133 start = 0
134 }
135 io.WriteString(s, name[start:end])
112136
113137 case 'n':
114 name := c.fn.Name()
138 name := c.frame.Function
115139 if !s.Flag('+') {
116140 const pathSep = "/"
117141 if i := strings.LastIndex(name, pathSep); i != -1 {
126150 }
127151 }
128152
153 // Frame returns the call frame infomation for the Call.
154 func (c Call) Frame() runtime.Frame {
155 return c.frame
156 }
157
129158 // PC returns the program counter for this call frame; multiple frames may
130159 // have the same PC value.
160 //
161 // Deprecated: Use Call.Frame instead.
131162 func (c Call) PC() uintptr {
132 return c.pc
133 }
134
135 // name returns the import path qualified name of the function containing the
136 // call.
137 func (c Call) name() string {
138 if c.fn == nil {
139 return "???"
140 }
141 return c.fn.Name()
142 }
143
144 func (c Call) file() string {
145 if c.fn == nil {
146 return "???"
147 }
148 file, _ := c.fn.FileLine(c.pc)
149 return file
150 }
151
152 func (c Call) line() int {
153 if c.fn == nil {
154 return 0
155 }
156 _, line := c.fn.FileLine(c.pc)
157 return line
163 return c.frame.PC
158164 }
159165
160166 // CallStack records a sequence of function invocations from a goroutine
178184 buf := bytes.Buffer{}
179185 buf.Write(openBracketBytes)
180186 for i, pc := range cs {
181 if pc.fn == nil {
182 return nil, ErrNoFunc
183 }
184187 if i > 0 {
185188 buf.Write(spaceBytes)
186189 }
204207 s.Write(closeBracketBytes)
205208 }
206209
207 // findSigpanic intentionally executes faulting code to generate a stack trace
208 // containing an entry for runtime.sigpanic.
209 func findSigpanic() *runtime.Func {
210 var fn *runtime.Func
211 var p *int
212 func() int {
213 defer func() {
214 if p := recover(); p != nil {
215 var pcs [512]uintptr
216 n := runtime.Callers(2, pcs[:])
217 for _, pc := range pcs[:n] {
218 f := runtime.FuncForPC(pc)
219 if f.Name() == "runtime.sigpanic" {
220 fn = f
221 break
222 }
223 }
224 }
225 }()
226 // intentional nil pointer dereference to trigger sigpanic
227 return *p
228 }()
229 return fn
230 }
231
232 var sigpanic = findSigpanic()
233
234210 // Trace returns a CallStack for the current goroutine with element 0
235211 // identifying the calling function.
236212 func Trace() CallStack {
237213 var pcs [512]uintptr
238 n := runtime.Callers(2, pcs[:])
239 cs := make([]Call, n)
240
241 for i, pc := range pcs[:n] {
242 pcFix := pc
243 if i > 0 && cs[i-1].fn != sigpanic {
244 pcFix--
245 }
246 cs[i] = Call{
247 fn: runtime.FuncForPC(pcFix),
248 pc: pcFix,
249 }
214 n := runtime.Callers(1, pcs[:])
215
216 frames := runtime.CallersFrames(pcs[:n])
217 cs := make(CallStack, 0, n)
218
219 // Skip extra frame retrieved just to make sure the runtime.sigpanic
220 // special case is handled.
221 frame, more := frames.Next()
222
223 for more {
224 frame, more = frames.Next()
225 cs = append(cs, Call{frame: frame})
250226 }
251227
252228 return cs
255231 // TrimBelow returns a slice of the CallStack with all entries below c
256232 // removed.
257233 func (cs CallStack) TrimBelow(c Call) CallStack {
258 for len(cs) > 0 && cs[0].pc != c.pc {
234 for len(cs) > 0 && cs[0] != c {
259235 cs = cs[1:]
260236 }
261237 return cs
264240 // TrimAbove returns a slice of the CallStack with all entries above c
265241 // removed.
266242 func (cs CallStack) TrimAbove(c Call) CallStack {
267 for len(cs) > 0 && cs[len(cs)-1].pc != c.pc {
243 for len(cs) > 0 && cs[len(cs)-1] != c {
268244 cs = cs[:len(cs)-1]
269245 }
270246 return cs
310286 return i + len(sep)
311287 }
312288
289 // pkgFilePath returns the frame's filepath relative to the compile-time GOPATH,
290 // or its module path joined to its path relative to the module root.
291 //
292 // As of Go 1.11 there is no direct way to know the compile time GOPATH or
293 // module paths at runtime, but we can piece together the desired information
294 // from available information. We note that runtime.Frame.Function contains the
295 // function name qualified by the package path, which includes the module path
296 // but not the GOPATH. We can extract the package path from that and append the
297 // last segments of the file path to arrive at the desired package qualified
298 // file path. For example, given:
299 //
300 // GOPATH /home/user
301 // import path pkg/sub
302 // frame.File /home/user/src/pkg/sub/file.go
303 // frame.Function pkg/sub.Type.Method
304 // Desired return pkg/sub/file.go
305 //
306 // It appears that we simply need to trim ".Type.Method" from frame.Function and
307 // append "/" + path.Base(file).
308 //
309 // But there are other wrinkles. Although it is idiomatic to do so, the internal
310 // name of a package is not required to match the last segment of its import
311 // path. In addition, the introduction of modules in Go 1.11 allows working
312 // without a GOPATH. So we also must make these work right:
313 //
314 // GOPATH /home/user
315 // import path pkg/go-sub
316 // package name sub
317 // frame.File /home/user/src/pkg/go-sub/file.go
318 // frame.Function pkg/sub.Type.Method
319 // Desired return pkg/go-sub/file.go
320 //
321 // Module path pkg/v2
322 // import path pkg/v2/go-sub
323 // package name sub
324 // frame.File /home/user/cloned-pkg/go-sub/file.go
325 // frame.Function pkg/v2/sub.Type.Method
326 // Desired return pkg/v2/go-sub/file.go
327 //
328 // We can handle all of these situations by using the package path extracted
329 // from frame.Function up to, but not including, the last segment as the prefix
330 // and the last two segments of frame.File as the suffix of the returned path.
331 // This preserves the existing behavior when working in a GOPATH without modules
332 // and a semantically equivalent behavior when used in module aware project.
333 func pkgFilePath(frame *runtime.Frame) string {
334 pre := pkgPrefix(frame.Function)
335 post := pathSuffix(frame.File)
336 if pre == "" {
337 return post
338 }
339 return pre + "/" + post
340 }
341
342 // pkgPrefix returns the import path of the function's package with the final
343 // segment removed.
344 func pkgPrefix(funcName string) string {
345 const pathSep = "/"
346 end := strings.LastIndex(funcName, pathSep)
347 if end == -1 {
348 return ""
349 }
350 return funcName[:end]
351 }
352
353 // pathSuffix returns the last two segments of path.
354 func pathSuffix(path string) string {
355 const pathSep = "/"
356 lastSep := strings.LastIndex(path, pathSep)
357 if lastSep == -1 {
358 return path
359 }
360 return path[strings.LastIndex(path[:lastSep], pathSep)+1:]
361 }
362
313363 var runtimePath string
314364
315365 func init() {
316 var pcs [1]uintptr
366 var pcs [3]uintptr
317367 runtime.Callers(0, pcs[:])
318 fn := runtime.FuncForPC(pcs[0])
319 file, _ := fn.FileLine(pcs[0])
320
321 idx := pkgIndex(file, fn.Name())
368 frames := runtime.CallersFrames(pcs[:])
369 frame, _ := frames.Next()
370 file := frame.File
371
372 idx := pkgIndex(frame.File, frame.Function)
322373
323374 runtimePath = file[:idx]
324375 if runtime.GOOS == "windows" {
327378 }
328379
329380 func inGoroot(c Call) bool {
330 file := c.file()
381 file := c.frame.File
331382 if len(file) == 0 || file[0] == '?' {
332383 return true
333384 }
1212 "github.com/go-stack/stack"
1313 )
1414
15 func TestCaller(t *testing.T) {
16 t.Parallel()
17
18 c := stack.Caller(0)
19 _, file, line, ok := runtime.Caller(0)
20 line--
21 if !ok {
22 t.Fatal("runtime.Caller(0) failed")
23 }
24
25 if got, want := c.Frame().File, file; got != want {
26 t.Errorf("got file == %v, want file == %v", got, want)
27 }
28
29 if got, want := c.Frame().Line, line; got != want {
30 t.Errorf("got line == %v, want line == %v", got, want)
31 }
32 }
33
34 func f3(f1 func() stack.Call) stack.Call {
35 return f2(f1)
36 }
37
38 func f2(f1 func() stack.Call) stack.Call {
39 return f1()
40 }
41
42 func TestCallerMidstackInlined(t *testing.T) {
43 t.Parallel()
44
45 _, _, line, ok := runtime.Caller(0)
46 line -= 10 // adjust to return f1() line inside f2()
47 if !ok {
48 t.Fatal("runtime.Caller(0) failed")
49 }
50
51 c := f3(func() stack.Call {
52 return stack.Caller(2)
53 })
54
55 if got, want := c.Frame().Line, line; got != want {
56 t.Errorf("got line == %v, want line == %v", got, want)
57 }
58 if got, want := c.Frame().Function, "github.com/go-stack/stack_test.f3"; got != want {
59 t.Errorf("got func name == %v, want func name == %v", got, want)
60 }
61 }
62
63 func TestCallerPanic(t *testing.T) {
64 t.Parallel()
65
66 var (
67 line int
68 ok bool
69 )
70
71 defer func() {
72 if recover() != nil {
73 var pcs [32]uintptr
74 n := runtime.Callers(1, pcs[:])
75 frames := runtime.CallersFrames(pcs[:n])
76 // count frames to runtime.sigpanic
77 panicIdx := 0
78 for {
79 f, more := frames.Next()
80 if f.Function == "runtime.sigpanic" {
81 break
82 }
83 panicIdx++
84 if !more {
85 t.Fatal("no runtime.sigpanic entry on the stack")
86 }
87 }
88 c := stack.Caller(panicIdx)
89 if got, want := c.Frame().Function, "runtime.sigpanic"; got != want {
90 t.Errorf("sigpanic frame: got name == %v, want name == %v", got, want)
91 }
92 c1 := stack.Caller(panicIdx + 1)
93 if got, want := c1.Frame().Function, "github.com/go-stack/stack_test.TestCallerPanic"; got != want {
94 t.Errorf("TestCallerPanic frame: got name == %v, want name == %v", got, want)
95 }
96 if got, want := c1.Frame().Line, line; got != want {
97 t.Errorf("TestCallerPanic frame: got line == %v, want line == %v", got, want)
98 }
99 }
100 }()
101
102 _, _, line, ok = runtime.Caller(0)
103 line += 7 // adjust to match line of panic below
104 if !ok {
105 t.Fatal("runtime.Caller(0) failed")
106 }
107 // Initiate a sigpanic.
108 var x *uintptr
109 _ = *x
110 }
111
112 type tholder struct {
113 trace func() stack.CallStack
114 }
115
116 func (th *tholder) traceLabyrinth() stack.CallStack {
117 for {
118 return th.trace()
119 }
120 }
121
122 func TestTrace(t *testing.T) {
123 t.Parallel()
124
125 _, _, line, ok := runtime.Caller(0)
126 if !ok {
127 t.Fatal("runtime.Caller(0) failed")
128 }
129
130 fh := tholder{
131 trace: func() stack.CallStack {
132 cs := stack.Trace()
133 return cs
134 },
135 }
136
137 cs := fh.traceLabyrinth()
138
139 lines := []int{line + 7, line - 7, line + 12}
140
141 for i, line := range lines {
142 if got, want := cs[i].Frame().Line, line; got != want {
143 t.Errorf("got line[%d] == %v, want line[%d] == %v", i, got, i, want)
144 }
145 }
146 }
147
148 // Test stack handling originating from a sigpanic.
149 func TestTracePanic(t *testing.T) {
150 t.Parallel()
151
152 var (
153 line int
154 ok bool
155 )
156
157 defer func() {
158 if recover() != nil {
159 trace := stack.Trace()
160
161 // find runtime.sigpanic
162 panicIdx := -1
163 for i, c := range trace {
164 if c.Frame().Function == "runtime.sigpanic" {
165 panicIdx = i
166 break
167 }
168 }
169 if panicIdx == -1 {
170 t.Fatal("no runtime.sigpanic entry on the stack")
171 }
172 if got, want := trace[panicIdx].Frame().Function, "runtime.sigpanic"; got != want {
173 t.Errorf("sigpanic frame: got name == %v, want name == %v", got, want)
174 }
175 if got, want := trace[panicIdx+1].Frame().Function, "github.com/go-stack/stack_test.TestTracePanic"; got != want {
176 t.Errorf("TestTracePanic frame: got name == %v, want name == %v", got, want)
177 }
178 if got, want := trace[panicIdx+1].Frame().Line, line; got != want {
179 t.Errorf("TestTracePanic frame: got line == %v, want line == %v", got, want)
180 }
181 }
182 }()
183
184 _, _, line, ok = runtime.Caller(0)
185 line += 7 // adjust to match line of panic below
186 if !ok {
187 t.Fatal("runtime.Caller(0) failed")
188 }
189 // Initiate a sigpanic.
190 var x *uintptr
191 _ = *x
192 }
193
15194 const importPath = "github.com/go-stack/stack"
16195
17196 type testType struct{}
18197
19 func (tt testType) testMethod() (c stack.Call, pc uintptr, file string, line int, ok bool) {
198 func (tt testType) testMethod() (c stack.Call, file string, line int, ok bool) {
20199 c = stack.Caller(0)
21 pc, file, line, ok = runtime.Caller(0)
200 _, file, line, ok = runtime.Caller(0)
22201 line--
23202 return
24203 }
27206 t.Parallel()
28207
29208 c := stack.Caller(0)
30 pc, file, line, ok := runtime.Caller(0)
209 _, file, line, ok := runtime.Caller(0)
31210 line--
32211 if !ok {
33212 t.Fatal("runtime.Caller(0) failed")
34213 }
35214 relFile := path.Join(importPath, filepath.Base(file))
36215
37 c2, pc2, file2, line2, ok2 := testType{}.testMethod()
216 c2, file2, line2, ok2 := testType{}.testMethod()
38217 if !ok2 {
39218 t.Fatal("runtime.Caller(0) failed")
40219 }
53232 {c, "func", "%#s", file},
54233 {c, "func", "%d", fmt.Sprint(line)},
55234 {c, "func", "%n", "TestCallFormat"},
56 {c, "func", "%+n", runtime.FuncForPC(pc - 1).Name()},
235 {c, "func", "%+n", "github.com/go-stack/stack_test.TestCallFormat"},
236 {c, "func", "%k", "stack_test"},
237 {c, "func", "%+k", "github.com/go-stack/stack_test"},
57238 {c, "func", "%v", fmt.Sprint(path.Base(file), ":", line)},
58239 {c, "func", "%+v", fmt.Sprint(relFile, ":", line)},
59240 {c, "func", "%#v", fmt.Sprint(file, ":", line)},
63244 {c2, "meth", "%#s", file2},
64245 {c2, "meth", "%d", fmt.Sprint(line2)},
65246 {c2, "meth", "%n", "testType.testMethod"},
66 {c2, "meth", "%+n", runtime.FuncForPC(pc2).Name()},
247 {c2, "meth", "%+n", "github.com/go-stack/stack_test.testType.testMethod"},
248 {c2, "meth", "%k", "stack_test"},
249 {c2, "meth", "%+k", "github.com/go-stack/stack_test"},
67250 {c2, "meth", "%v", fmt.Sprint(path.Base(file2), ":", line2)},
68251 {c2, "meth", "%+v", fmt.Sprint(relFile2, ":", line2)},
69252 {c2, "meth", "%#v", fmt.Sprint(file2, ":", line2)},
87270 t.Fatal("runtime.Caller(0) failed")
88271 }
89272
90 c2, _, file2, line2, ok2 := testType{}.testMethod()
273 c2, file2, line2, ok2 := testType{}.testMethod()
91274 if !ok2 {
92275 t.Fatal("runtime.Caller(0) failed")
93276 }
120303 t.Fatal("runtime.Caller(0) failed")
121304 }
122305
123 c2, _, file2, line2, ok2 := testType{}.testMethod()
306 c2, file2, line2, ok2 := testType{}.testMethod()
124307 if !ok2 {
125308 t.Fatal("runtime.Caller(0) failed")
126309 }
173356 t.Errorf("\n got %v\nwant %v", got, want)
174357 }
175358 }
359
176360 func getTrace(t *testing.T) (stack.CallStack, int) {
177361 cs := stack.Trace().TrimRuntime()
178362 _, _, line, ok := runtime.Caller(0)
186370 func TestTrimAbove(t *testing.T) {
187371 trace := trimAbove()
188372 if got, want := len(trace), 2; got != want {
189 t.Errorf("got len(trace) == %v, want %v, trace: %n", got, want, trace)
373 t.Fatalf("got len(trace) == %v, want %v, trace: %n", got, want, trace)
190374 }
191375 if got, want := fmt.Sprintf("%n", trace[1]), "TestTrimAbove"; got != want {
192376 t.Errorf("got %q, want %q", got, want)
+0
-65
stackinternal_test.go less more
0 package stack
1
2 import (
3 "runtime"
4 "testing"
5 )
6
7 func TestFindSigpanic(t *testing.T) {
8 t.Parallel()
9 sp := findSigpanic()
10 if got, want := sp.Name(), "runtime.sigpanic"; got != want {
11 t.Errorf("got == %v, want == %v", got, want)
12 }
13 }
14
15 func TestCaller(t *testing.T) {
16 t.Parallel()
17
18 c := Caller(0)
19 _, file, line, ok := runtime.Caller(0)
20 line--
21 if !ok {
22 t.Fatal("runtime.Caller(0) failed")
23 }
24
25 if got, want := c.file(), file; got != want {
26 t.Errorf("got file == %v, want file == %v", got, want)
27 }
28
29 if got, want := c.line(), line; got != want {
30 t.Errorf("got line == %v, want line == %v", got, want)
31 }
32 }
33
34 type fholder struct {
35 f func() CallStack
36 }
37
38 func (fh *fholder) labyrinth() CallStack {
39 for {
40 return fh.f()
41 }
42 panic("this line only needed for go 1.0")
43 }
44
45 func TestTrace(t *testing.T) {
46 t.Parallel()
47
48 fh := fholder{
49 f: func() CallStack {
50 cs := Trace()
51 return cs
52 },
53 }
54
55 cs := fh.labyrinth()
56
57 lines := []int{51, 41, 56}
58
59 for i, line := range lines {
60 if got, want := cs[i].line(), line; got != want {
61 t.Errorf("got line[%d] == %v, want line[%d] == %v", i, got, i, want)
62 }
63 }
64 }