summaryrefslogtreecommitdiff
path: root/vendor/github.com/go-stack/stack
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/go-stack/stack')
-rw-r--r--vendor/github.com/go-stack/stack/LICENSE.md21
-rw-r--r--vendor/github.com/go-stack/stack/README.md38
-rw-r--r--vendor/github.com/go-stack/stack/format_test.go21
-rw-r--r--vendor/github.com/go-stack/stack/go.mod1
-rw-r--r--vendor/github.com/go-stack/stack/stack-go19_test.go67
-rw-r--r--vendor/github.com/go-stack/stack/stack.go400
-rw-r--r--vendor/github.com/go-stack/stack/stack_test.go582
7 files changed, 0 insertions, 1130 deletions
diff --git a/vendor/github.com/go-stack/stack/LICENSE.md b/vendor/github.com/go-stack/stack/LICENSE.md
deleted file mode 100644
index 2abf98e..0000000
--- a/vendor/github.com/go-stack/stack/LICENSE.md
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 Chris Hines
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/vendor/github.com/go-stack/stack/README.md b/vendor/github.com/go-stack/stack/README.md
deleted file mode 100644
index f11cccc..0000000
--- a/vendor/github.com/go-stack/stack/README.md
+++ /dev/null
@@ -1,38 +0,0 @@
-[![GoDoc](https://godoc.org/github.com/go-stack/stack?status.svg)](https://godoc.org/github.com/go-stack/stack)
-[![Go Report Card](https://goreportcard.com/badge/go-stack/stack)](https://goreportcard.com/report/go-stack/stack)
-[![TravisCI](https://travis-ci.org/go-stack/stack.svg?branch=master)](https://travis-ci.org/go-stack/stack)
-[![Coverage Status](https://coveralls.io/repos/github/go-stack/stack/badge.svg?branch=master)](https://coveralls.io/github/go-stack/stack?branch=master)
-
-# stack
-
-Package stack implements utilities to capture, manipulate, and format call
-stacks. It provides a simpler API than package runtime.
-
-The implementation takes care of the minutia and special cases of interpreting
-the program counter (pc) values returned by runtime.Callers.
-
-## Versioning
-
-Package stack publishes releases via [semver](http://semver.org/) compatible Git
-tags prefixed with a single 'v'. The master branch always contains the latest
-release. The develop branch contains unreleased commits.
-
-## Formatting
-
-Package stack's types implement fmt.Formatter, which provides a simple and
-flexible way to declaratively configure formatting when used with logging or
-error tracking packages.
-
-```go
-func DoTheThing() {
- c := stack.Caller(0)
- log.Print(c) // "source.go:10"
- log.Printf("%+v", c) // "pkg/path/source.go:10"
- log.Printf("%n", c) // "DoTheThing"
-
- s := stack.Trace().TrimRuntime()
- log.Print(s) // "[source.go:15 caller.go:42 main.go:14]"
-}
-```
-
-See the docs for all of the supported formatting options.
diff --git a/vendor/github.com/go-stack/stack/format_test.go b/vendor/github.com/go-stack/stack/format_test.go
deleted file mode 100644
index 013ad67..0000000
--- a/vendor/github.com/go-stack/stack/format_test.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// +build go1.2
-
-package stack_test
-
-import (
- "fmt"
-
- "github.com/go-stack/stack"
-)
-
-func Example_callFormat() {
- logCaller("%+s")
- logCaller("%v %[1]n()")
- // Output:
- // github.com/go-stack/stack/format_test.go
- // format_test.go:13 Example_callFormat()
-}
-
-func logCaller(format string) {
- fmt.Printf(format+"\n", stack.Caller(1))
-}
diff --git a/vendor/github.com/go-stack/stack/go.mod b/vendor/github.com/go-stack/stack/go.mod
deleted file mode 100644
index 96a53a1..0000000
--- a/vendor/github.com/go-stack/stack/go.mod
+++ /dev/null
@@ -1 +0,0 @@
-module github.com/go-stack/stack
diff --git a/vendor/github.com/go-stack/stack/stack-go19_test.go b/vendor/github.com/go-stack/stack/stack-go19_test.go
deleted file mode 100644
index d7aeea2..0000000
--- a/vendor/github.com/go-stack/stack/stack-go19_test.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// +build go1.9
-
-package stack_test
-
-import (
- "runtime"
- "testing"
-
- "github.com/go-stack/stack"
-)
-
-func TestCallerInlinedPanic(t *testing.T) {
- t.Parallel()
-
- var line int
-
- defer func() {
- if recover() != nil {
- var pcs [32]uintptr
- n := runtime.Callers(1, pcs[:])
- frames := runtime.CallersFrames(pcs[:n])
- // count frames to runtime.sigpanic
- panicIdx := 0
- for {
- f, more := frames.Next()
- if f.Function == "runtime.sigpanic" {
- break
- }
- panicIdx++
- if !more {
- t.Fatal("no runtime.sigpanic entry on the stack")
- }
- }
-
- c := stack.Caller(panicIdx)
- if got, want := c.Frame().Function, "runtime.sigpanic"; got != want {
- t.Errorf("sigpanic frame: got name == %v, want name == %v", got, want)
- }
-
- c1 := stack.Caller(panicIdx + 1)
- if got, want := c1.Frame().Function, "github.com/go-stack/stack_test.inlinablePanic"; got != want {
- t.Errorf("TestCallerInlinedPanic frame: got name == %v, want name == %v", got, want)
- }
- if got, want := c1.Frame().Line, line; got != want {
- t.Errorf("TestCallerInlinedPanic frame: got line == %v, want line == %v", got, want)
- }
- }
- }()
-
- doPanic(t, &line)
- t.Fatal("failed to panic")
-}
-
-func doPanic(t *testing.T, panicLine *int) {
- _, _, line, ok := runtime.Caller(0)
- *panicLine = line + 11 // adjust to match line of panic below
- if !ok {
- t.Fatal("runtime.Caller(0) failed")
- }
- inlinablePanic()
-}
-
-func inlinablePanic() {
- // Initiate a sigpanic.
- var x *uintptr
- _ = *x
-}
diff --git a/vendor/github.com/go-stack/stack/stack.go b/vendor/github.com/go-stack/stack/stack.go
deleted file mode 100644
index ac3b93b..0000000
--- a/vendor/github.com/go-stack/stack/stack.go
+++ /dev/null
@@ -1,400 +0,0 @@
-// +build go1.7
-
-// Package stack implements utilities to capture, manipulate, and format call
-// stacks. It provides a simpler API than package runtime.
-//
-// The implementation takes care of the minutia and special cases of
-// interpreting the program counter (pc) values returned by runtime.Callers.
-//
-// Package stack's types implement fmt.Formatter, which provides a simple and
-// flexible way to declaratively configure formatting when used with logging
-// or error tracking packages.
-package stack
-
-import (
- "bytes"
- "errors"
- "fmt"
- "io"
- "runtime"
- "strconv"
- "strings"
-)
-
-// Call records a single function invocation from a goroutine stack.
-type Call struct {
- frame runtime.Frame
-}
-
-// Caller returns a Call from the stack of the current goroutine. The argument
-// skip is the number of stack frames to ascend, with 0 identifying the
-// calling function.
-func Caller(skip int) Call {
- // As of Go 1.9 we need room for up to three PC entries.
- //
- // 0. An entry for the stack frame prior to the target to check for
- // special handling needed if that prior entry is runtime.sigpanic.
- // 1. A possible second entry to hold metadata about skipped inlined
- // functions. If inline functions were not skipped the target frame
- // PC will be here.
- // 2. A third entry for the target frame PC when the second entry
- // is used for skipped inline functions.
- var pcs [3]uintptr
- n := runtime.Callers(skip+1, pcs[:])
- frames := runtime.CallersFrames(pcs[:n])
- frame, _ := frames.Next()
- frame, _ = frames.Next()
-
- return Call{
- frame: frame,
- }
-}
-
-// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", c).
-func (c Call) String() string {
- return fmt.Sprint(c)
-}
-
-// MarshalText implements encoding.TextMarshaler. It formats the Call the same
-// as fmt.Sprintf("%v", c).
-func (c Call) MarshalText() ([]byte, error) {
- if c.frame == (runtime.Frame{}) {
- return nil, ErrNoFunc
- }
-
- buf := bytes.Buffer{}
- fmt.Fprint(&buf, c)
- return buf.Bytes(), nil
-}
-
-// ErrNoFunc means that the Call has a nil *runtime.Func. The most likely
-// cause is a Call with the zero value.
-var ErrNoFunc = errors.New("no call stack information")
-
-// Format implements fmt.Formatter with support for the following verbs.
-//
-// %s source file
-// %d line number
-// %n function name
-// %k last segment of the package path
-// %v equivalent to %s:%d
-//
-// It accepts the '+' and '#' flags for most of the verbs as follows.
-//
-// %+s path of source file relative to the compile time GOPATH,
-// or the module path joined to the path of source file relative
-// to module root
-// %#s full path of source file
-// %+n import path qualified function name
-// %+k full package path
-// %+v equivalent to %+s:%d
-// %#v equivalent to %#s:%d
-func (c Call) Format(s fmt.State, verb rune) {
- if c.frame == (runtime.Frame{}) {
- fmt.Fprintf(s, "%%!%c(NOFUNC)", verb)
- return
- }
-
- switch verb {
- case 's', 'v':
- file := c.frame.File
- switch {
- case s.Flag('#'):
- // done
- case s.Flag('+'):
- file = pkgFilePath(&c.frame)
- default:
- const sep = "/"
- if i := strings.LastIndex(file, sep); i != -1 {
- file = file[i+len(sep):]
- }
- }
- io.WriteString(s, file)
- if verb == 'v' {
- buf := [7]byte{':'}
- s.Write(strconv.AppendInt(buf[:1], int64(c.frame.Line), 10))
- }
-
- case 'd':
- buf := [6]byte{}
- s.Write(strconv.AppendInt(buf[:0], int64(c.frame.Line), 10))
-
- case 'k':
- name := c.frame.Function
- const pathSep = "/"
- start, end := 0, len(name)
- if i := strings.LastIndex(name, pathSep); i != -1 {
- start = i + len(pathSep)
- }
- const pkgSep = "."
- if i := strings.Index(name[start:], pkgSep); i != -1 {
- end = start + i
- }
- if s.Flag('+') {
- start = 0
- }
- io.WriteString(s, name[start:end])
-
- case 'n':
- name := c.frame.Function
- if !s.Flag('+') {
- const pathSep = "/"
- if i := strings.LastIndex(name, pathSep); i != -1 {
- name = name[i+len(pathSep):]
- }
- const pkgSep = "."
- if i := strings.Index(name, pkgSep); i != -1 {
- name = name[i+len(pkgSep):]
- }
- }
- io.WriteString(s, name)
- }
-}
-
-// Frame returns the call frame infomation for the Call.
-func (c Call) Frame() runtime.Frame {
- return c.frame
-}
-
-// PC returns the program counter for this call frame; multiple frames may
-// have the same PC value.
-//
-// Deprecated: Use Call.Frame instead.
-func (c Call) PC() uintptr {
- return c.frame.PC
-}
-
-// CallStack records a sequence of function invocations from a goroutine
-// stack.
-type CallStack []Call
-
-// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", cs).
-func (cs CallStack) String() string {
- return fmt.Sprint(cs)
-}
-
-var (
- openBracketBytes = []byte("[")
- closeBracketBytes = []byte("]")
- spaceBytes = []byte(" ")
-)
-
-// MarshalText implements encoding.TextMarshaler. It formats the CallStack the
-// same as fmt.Sprintf("%v", cs).
-func (cs CallStack) MarshalText() ([]byte, error) {
- buf := bytes.Buffer{}
- buf.Write(openBracketBytes)
- for i, pc := range cs {
- if i > 0 {
- buf.Write(spaceBytes)
- }
- fmt.Fprint(&buf, pc)
- }
- buf.Write(closeBracketBytes)
- return buf.Bytes(), nil
-}
-
-// Format implements fmt.Formatter by printing the CallStack as square brackets
-// ([, ]) surrounding a space separated list of Calls each formatted with the
-// supplied verb and options.
-func (cs CallStack) Format(s fmt.State, verb rune) {
- s.Write(openBracketBytes)
- for i, pc := range cs {
- if i > 0 {
- s.Write(spaceBytes)
- }
- pc.Format(s, verb)
- }
- s.Write(closeBracketBytes)
-}
-
-// Trace returns a CallStack for the current goroutine with element 0
-// identifying the calling function.
-func Trace() CallStack {
- var pcs [512]uintptr
- n := runtime.Callers(1, pcs[:])
-
- frames := runtime.CallersFrames(pcs[:n])
- cs := make(CallStack, 0, n)
-
- // Skip extra frame retrieved just to make sure the runtime.sigpanic
- // special case is handled.
- frame, more := frames.Next()
-
- for more {
- frame, more = frames.Next()
- cs = append(cs, Call{frame: frame})
- }
-
- return cs
-}
-
-// TrimBelow returns a slice of the CallStack with all entries below c
-// removed.
-func (cs CallStack) TrimBelow(c Call) CallStack {
- for len(cs) > 0 && cs[0] != c {
- cs = cs[1:]
- }
- return cs
-}
-
-// TrimAbove returns a slice of the CallStack with all entries above c
-// removed.
-func (cs CallStack) TrimAbove(c Call) CallStack {
- for len(cs) > 0 && cs[len(cs)-1] != c {
- cs = cs[:len(cs)-1]
- }
- return cs
-}
-
-// pkgIndex returns the index that results in file[index:] being the path of
-// file relative to the compile time GOPATH, and file[:index] being the
-// $GOPATH/src/ portion of file. funcName must be the name of a function in
-// file as returned by runtime.Func.Name.
-func pkgIndex(file, funcName string) int {
- // As of Go 1.6.2 there is no direct way to know the compile time GOPATH
- // at runtime, but we can infer the number of path segments in the GOPATH.
- // We note that runtime.Func.Name() returns the function name qualified by
- // the import path, which does not include the GOPATH. Thus we can trim
- // segments from the beginning of the file path until the number of path
- // separators remaining is one more than the number of path separators in
- // the function name. For example, given:
- //
- // GOPATH /home/user
- // file /home/user/src/pkg/sub/file.go
- // fn.Name() pkg/sub.Type.Method
- //
- // We want to produce:
- //
- // file[:idx] == /home/user/src/
- // file[idx:] == pkg/sub/file.go
- //
- // From this we can easily see that fn.Name() has one less path separator
- // than our desired result for file[idx:]. We count separators from the
- // end of the file path until it finds two more than in the function name
- // and then move one character forward to preserve the initial path
- // segment without a leading separator.
- const sep = "/"
- i := len(file)
- for n := strings.Count(funcName, sep) + 2; n > 0; n-- {
- i = strings.LastIndex(file[:i], sep)
- if i == -1 {
- i = -len(sep)
- break
- }
- }
- // get back to 0 or trim the leading separator
- return i + len(sep)
-}
-
-// pkgFilePath returns the frame's filepath relative to the compile-time GOPATH,
-// or its module path joined to its path relative to the module root.
-//
-// As of Go 1.11 there is no direct way to know the compile time GOPATH or
-// module paths at runtime, but we can piece together the desired information
-// from available information. We note that runtime.Frame.Function contains the
-// function name qualified by the package path, which includes the module path
-// but not the GOPATH. We can extract the package path from that and append the
-// last segments of the file path to arrive at the desired package qualified
-// file path. For example, given:
-//
-// GOPATH /home/user
-// import path pkg/sub
-// frame.File /home/user/src/pkg/sub/file.go
-// frame.Function pkg/sub.Type.Method
-// Desired return pkg/sub/file.go
-//
-// It appears that we simply need to trim ".Type.Method" from frame.Function and
-// append "/" + path.Base(file).
-//
-// But there are other wrinkles. Although it is idiomatic to do so, the internal
-// name of a package is not required to match the last segment of its import
-// path. In addition, the introduction of modules in Go 1.11 allows working
-// without a GOPATH. So we also must make these work right:
-//
-// GOPATH /home/user
-// import path pkg/go-sub
-// package name sub
-// frame.File /home/user/src/pkg/go-sub/file.go
-// frame.Function pkg/sub.Type.Method
-// Desired return pkg/go-sub/file.go
-//
-// Module path pkg/v2
-// import path pkg/v2/go-sub
-// package name sub
-// frame.File /home/user/cloned-pkg/go-sub/file.go
-// frame.Function pkg/v2/sub.Type.Method
-// Desired return pkg/v2/go-sub/file.go
-//
-// We can handle all of these situations by using the package path extracted
-// from frame.Function up to, but not including, the last segment as the prefix
-// and the last two segments of frame.File as the suffix of the returned path.
-// This preserves the existing behavior when working in a GOPATH without modules
-// and a semantically equivalent behavior when used in module aware project.
-func pkgFilePath(frame *runtime.Frame) string {
- pre := pkgPrefix(frame.Function)
- post := pathSuffix(frame.File)
- if pre == "" {
- return post
- }
- return pre + "/" + post
-}
-
-// pkgPrefix returns the import path of the function's package with the final
-// segment removed.
-func pkgPrefix(funcName string) string {
- const pathSep = "/"
- end := strings.LastIndex(funcName, pathSep)
- if end == -1 {
- return ""
- }
- return funcName[:end]
-}
-
-// pathSuffix returns the last two segments of path.
-func pathSuffix(path string) string {
- const pathSep = "/"
- lastSep := strings.LastIndex(path, pathSep)
- if lastSep == -1 {
- return path
- }
- return path[strings.LastIndex(path[:lastSep], pathSep)+1:]
-}
-
-var runtimePath string
-
-func init() {
- var pcs [3]uintptr
- runtime.Callers(0, pcs[:])
- frames := runtime.CallersFrames(pcs[:])
- frame, _ := frames.Next()
- file := frame.File
-
- idx := pkgIndex(frame.File, frame.Function)
-
- runtimePath = file[:idx]
- if runtime.GOOS == "windows" {
- runtimePath = strings.ToLower(runtimePath)
- }
-}
-
-func inGoroot(c Call) bool {
- file := c.frame.File
- if len(file) == 0 || file[0] == '?' {
- return true
- }
- if runtime.GOOS == "windows" {
- file = strings.ToLower(file)
- }
- return strings.HasPrefix(file, runtimePath) || strings.HasSuffix(file, "/_testmain.go")
-}
-
-// TrimRuntime returns a slice of the CallStack with the topmost entries from
-// the go runtime removed. It considers any calls originating from unknown
-// files, files under GOROOT, or _testmain.go as part of the runtime.
-func (cs CallStack) TrimRuntime() CallStack {
- for len(cs) > 0 && inGoroot(cs[len(cs)-1]) {
- cs = cs[:len(cs)-1]
- }
- return cs
-}
diff --git a/vendor/github.com/go-stack/stack/stack_test.go b/vendor/github.com/go-stack/stack/stack_test.go
deleted file mode 100644
index 44f3a7d..0000000
--- a/vendor/github.com/go-stack/stack/stack_test.go
+++ /dev/null
@@ -1,582 +0,0 @@
-package stack_test
-
-import (
- "fmt"
- "io/ioutil"
- "path"
- "path/filepath"
- "reflect"
- "runtime"
- "strings"
- "testing"
-
- "github.com/go-stack/stack"
-)
-
-func TestCaller(t *testing.T) {
- t.Parallel()
-
- c := stack.Caller(0)
- _, file, line, ok := runtime.Caller(0)
- line--
- if !ok {
- t.Fatal("runtime.Caller(0) failed")
- }
-
- if got, want := c.Frame().File, file; got != want {
- t.Errorf("got file == %v, want file == %v", got, want)
- }
-
- if got, want := c.Frame().Line, line; got != want {
- t.Errorf("got line == %v, want line == %v", got, want)
- }
-}
-
-func f3(f1 func() stack.Call) stack.Call {
- return f2(f1)
-}
-
-func f2(f1 func() stack.Call) stack.Call {
- return f1()
-}
-
-func TestCallerMidstackInlined(t *testing.T) {
- t.Parallel()
-
- _, _, line, ok := runtime.Caller(0)
- line -= 10 // adjust to return f1() line inside f2()
- if !ok {
- t.Fatal("runtime.Caller(0) failed")
- }
-
- c := f3(func() stack.Call {
- return stack.Caller(2)
- })
-
- if got, want := c.Frame().Line, line; got != want {
- t.Errorf("got line == %v, want line == %v", got, want)
- }
- if got, want := c.Frame().Function, "github.com/go-stack/stack_test.f3"; got != want {
- t.Errorf("got func name == %v, want func name == %v", got, want)
- }
-}
-
-func TestCallerPanic(t *testing.T) {
- t.Parallel()
-
- var (
- line int
- ok bool
- )
-
- defer func() {
- if recover() != nil {
- var pcs [32]uintptr
- n := runtime.Callers(1, pcs[:])
- frames := runtime.CallersFrames(pcs[:n])
- // count frames to runtime.sigpanic
- panicIdx := 0
- for {
- f, more := frames.Next()
- if f.Function == "runtime.sigpanic" {
- break
- }
- panicIdx++
- if !more {
- t.Fatal("no runtime.sigpanic entry on the stack")
- }
- }
- c := stack.Caller(panicIdx)
- if got, want := c.Frame().Function, "runtime.sigpanic"; got != want {
- t.Errorf("sigpanic frame: got name == %v, want name == %v", got, want)
- }
- c1 := stack.Caller(panicIdx + 1)
- if got, want := c1.Frame().Function, "github.com/go-stack/stack_test.TestCallerPanic"; got != want {
- t.Errorf("TestCallerPanic frame: got name == %v, want name == %v", got, want)
- }
- if got, want := c1.Frame().Line, line; got != want {
- t.Errorf("TestCallerPanic frame: got line == %v, want line == %v", got, want)
- }
- }
- }()
-
- _, _, line, ok = runtime.Caller(0)
- line += 7 // adjust to match line of panic below
- if !ok {
- t.Fatal("runtime.Caller(0) failed")
- }
- // Initiate a sigpanic.
- var x *uintptr
- _ = *x
-}
-
-type tholder struct {
- trace func() stack.CallStack
-}
-
-func (th *tholder) traceLabyrinth() stack.CallStack {
- for {
- return th.trace()
- }
-}
-
-func TestTrace(t *testing.T) {
- t.Parallel()
-
- _, _, line, ok := runtime.Caller(0)
- if !ok {
- t.Fatal("runtime.Caller(0) failed")
- }
-
- fh := tholder{
- trace: func() stack.CallStack {
- cs := stack.Trace()
- return cs
- },
- }
-
- cs := fh.traceLabyrinth()
-
- lines := []int{line + 7, line - 7, line + 12}
-
- for i, line := range lines {
- if got, want := cs[i].Frame().Line, line; got != want {
- t.Errorf("got line[%d] == %v, want line[%d] == %v", i, got, i, want)
- }
- }
-}
-
-// Test stack handling originating from a sigpanic.
-func TestTracePanic(t *testing.T) {
- t.Parallel()
-
- var (
- line int
- ok bool
- )
-
- defer func() {
- if recover() != nil {
- trace := stack.Trace()
-
- // find runtime.sigpanic
- panicIdx := -1
- for i, c := range trace {
- if c.Frame().Function == "runtime.sigpanic" {
- panicIdx = i
- break
- }
- }
- if panicIdx == -1 {
- t.Fatal("no runtime.sigpanic entry on the stack")
- }
- if got, want := trace[panicIdx].Frame().Function, "runtime.sigpanic"; got != want {
- t.Errorf("sigpanic frame: got name == %v, want name == %v", got, want)
- }
- if got, want := trace[panicIdx+1].Frame().Function, "github.com/go-stack/stack_test.TestTracePanic"; got != want {
- t.Errorf("TestTracePanic frame: got name == %v, want name == %v", got, want)
- }
- if got, want := trace[panicIdx+1].Frame().Line, line; got != want {
- t.Errorf("TestTracePanic frame: got line == %v, want line == %v", got, want)
- }
- }
- }()
-
- _, _, line, ok = runtime.Caller(0)
- line += 7 // adjust to match line of panic below
- if !ok {
- t.Fatal("runtime.Caller(0) failed")
- }
- // Initiate a sigpanic.
- var x *uintptr
- _ = *x
-}
-
-const importPath = "github.com/go-stack/stack"
-
-type testType struct{}
-
-func (tt testType) testMethod() (c stack.Call, file string, line int, ok bool) {
- c = stack.Caller(0)
- _, file, line, ok = runtime.Caller(0)
- line--
- return
-}
-
-func TestCallFormat(t *testing.T) {
- t.Parallel()
-
- c := stack.Caller(0)
- _, file, line, ok := runtime.Caller(0)
- line--
- if !ok {
- t.Fatal("runtime.Caller(0) failed")
- }
- relFile := path.Join(importPath, filepath.Base(file))
-
- c2, file2, line2, ok2 := testType{}.testMethod()
- if !ok2 {
- t.Fatal("runtime.Caller(0) failed")
- }
- relFile2 := path.Join(importPath, filepath.Base(file2))
-
- data := []struct {
- c stack.Call
- desc string
- fmt string
- out string
- }{
- {stack.Call{}, "error", "%s", "%!s(NOFUNC)"},
-
- {c, "func", "%s", path.Base(file)},
- {c, "func", "%+s", relFile},
- {c, "func", "%#s", file},
- {c, "func", "%d", fmt.Sprint(line)},
- {c, "func", "%n", "TestCallFormat"},
- {c, "func", "%+n", "github.com/go-stack/stack_test.TestCallFormat"},
- {c, "func", "%k", "stack_test"},
- {c, "func", "%+k", "github.com/go-stack/stack_test"},
- {c, "func", "%v", fmt.Sprint(path.Base(file), ":", line)},
- {c, "func", "%+v", fmt.Sprint(relFile, ":", line)},
- {c, "func", "%#v", fmt.Sprint(file, ":", line)},
-
- {c2, "meth", "%s", path.Base(file2)},
- {c2, "meth", "%+s", relFile2},
- {c2, "meth", "%#s", file2},
- {c2, "meth", "%d", fmt.Sprint(line2)},
- {c2, "meth", "%n", "testType.testMethod"},
- {c2, "meth", "%+n", "github.com/go-stack/stack_test.testType.testMethod"},
- {c2, "meth", "%k", "stack_test"},
- {c2, "meth", "%+k", "github.com/go-stack/stack_test"},
- {c2, "meth", "%v", fmt.Sprint(path.Base(file2), ":", line2)},
- {c2, "meth", "%+v", fmt.Sprint(relFile2, ":", line2)},
- {c2, "meth", "%#v", fmt.Sprint(file2, ":", line2)},
- }
-
- for _, d := range data {
- got := fmt.Sprintf(d.fmt, d.c)
- if got != d.out {
- t.Errorf("fmt.Sprintf(%q, Call(%s)) = %s, want %s", d.fmt, d.desc, got, d.out)
- }
- }
-}
-
-func TestCallString(t *testing.T) {
- t.Parallel()
-
- c := stack.Caller(0)
- _, file, line, ok := runtime.Caller(0)
- line--
- if !ok {
- t.Fatal("runtime.Caller(0) failed")
- }
-
- c2, file2, line2, ok2 := testType{}.testMethod()
- if !ok2 {
- t.Fatal("runtime.Caller(0) failed")
- }
-
- data := []struct {
- c stack.Call
- desc string
- out string
- }{
- {stack.Call{}, "error", "%!v(NOFUNC)"},
- {c, "func", fmt.Sprint(path.Base(file), ":", line)},
- {c2, "meth", fmt.Sprint(path.Base(file2), ":", line2)},
- }
-
- for _, d := range data {
- got := d.c.String()
- if got != d.out {
- t.Errorf("got %s, want %s", got, d.out)
- }
- }
-}
-
-func TestCallMarshalText(t *testing.T) {
- t.Parallel()
-
- c := stack.Caller(0)
- _, file, line, ok := runtime.Caller(0)
- line--
- if !ok {
- t.Fatal("runtime.Caller(0) failed")
- }
-
- c2, file2, line2, ok2 := testType{}.testMethod()
- if !ok2 {
- t.Fatal("runtime.Caller(0) failed")
- }
-
- data := []struct {
- c stack.Call
- desc string
- out []byte
- err error
- }{
- {stack.Call{}, "error", nil, stack.ErrNoFunc},
- {c, "func", []byte(fmt.Sprint(path.Base(file), ":", line)), nil},
- {c2, "meth", []byte(fmt.Sprint(path.Base(file2), ":", line2)), nil},
- }
-
- for _, d := range data {
- text, err := d.c.MarshalText()
- if got, want := err, d.err; got != want {
- t.Errorf("%s: got err %v, want err %v", d.desc, got, want)
- }
- if got, want := text, d.out; !reflect.DeepEqual(got, want) {
- t.Errorf("%s: got %s, want %s", d.desc, got, want)
- }
- }
-}
-
-func TestCallStackString(t *testing.T) {
- cs, line0 := getTrace(t)
- _, file, line1, ok := runtime.Caller(0)
- line1--
- if !ok {
- t.Fatal("runtime.Caller(0) failed")
- }
- file = path.Base(file)
- if got, want := cs.String(), fmt.Sprintf("[%s:%d %s:%d]", file, line0, file, line1); got != want {
- t.Errorf("\n got %v\nwant %v", got, want)
- }
-}
-
-func TestCallStackMarshalText(t *testing.T) {
- cs, line0 := getTrace(t)
- _, file, line1, ok := runtime.Caller(0)
- line1--
- if !ok {
- t.Fatal("runtime.Caller(0) failed")
- }
- file = path.Base(file)
- text, _ := cs.MarshalText()
- if got, want := text, []byte(fmt.Sprintf("[%s:%d %s:%d]", file, line0, file, line1)); !reflect.DeepEqual(got, want) {
- t.Errorf("\n got %v\nwant %v", got, want)
- }
-}
-
-func getTrace(t *testing.T) (stack.CallStack, int) {
- cs := stack.Trace().TrimRuntime()
- _, _, line, ok := runtime.Caller(0)
- line--
- if !ok {
- t.Fatal("runtime.Caller(0) failed")
- }
- return cs, line
-}
-
-func TestTrimAbove(t *testing.T) {
- trace := trimAbove()
- if got, want := len(trace), 2; got != want {
- t.Fatalf("got len(trace) == %v, want %v, trace: %n", got, want, trace)
- }
- if got, want := fmt.Sprintf("%n", trace[1]), "TestTrimAbove"; got != want {
- t.Errorf("got %q, want %q", got, want)
- }
-}
-
-func trimAbove() stack.CallStack {
- call := stack.Caller(1)
- trace := stack.Trace()
- return trace.TrimAbove(call)
-}
-
-func TestTrimBelow(t *testing.T) {
- trace := trimBelow()
- if got, want := fmt.Sprintf("%n", trace[0]), "TestTrimBelow"; got != want {
- t.Errorf("got %q, want %q", got, want)
- }
-}
-
-func trimBelow() stack.CallStack {
- call := stack.Caller(1)
- trace := stack.Trace()
- return trace.TrimBelow(call)
-}
-
-func TestTrimRuntime(t *testing.T) {
- trace := stack.Trace().TrimRuntime()
- if got, want := len(trace), 1; got != want {
- t.Errorf("got len(trace) == %v, want %v, goroot: %q, trace: %#v", got, want, runtime.GOROOT(), trace)
- }
-}
-
-func BenchmarkCallVFmt(b *testing.B) {
- c := stack.Caller(0)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- fmt.Fprint(ioutil.Discard, c)
- }
-}
-
-func BenchmarkCallPlusVFmt(b *testing.B) {
- c := stack.Caller(0)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- fmt.Fprintf(ioutil.Discard, "%+v", c)
- }
-}
-
-func BenchmarkCallSharpVFmt(b *testing.B) {
- c := stack.Caller(0)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- fmt.Fprintf(ioutil.Discard, "%#v", c)
- }
-}
-
-func BenchmarkCallSFmt(b *testing.B) {
- c := stack.Caller(0)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- fmt.Fprintf(ioutil.Discard, "%s", c)
- }
-}
-
-func BenchmarkCallPlusSFmt(b *testing.B) {
- c := stack.Caller(0)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- fmt.Fprintf(ioutil.Discard, "%+s", c)
- }
-}
-
-func BenchmarkCallSharpSFmt(b *testing.B) {
- c := stack.Caller(0)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- fmt.Fprintf(ioutil.Discard, "%#s", c)
- }
-}
-
-func BenchmarkCallDFmt(b *testing.B) {
- c := stack.Caller(0)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- fmt.Fprintf(ioutil.Discard, "%d", c)
- }
-}
-
-func BenchmarkCallNFmt(b *testing.B) {
- c := stack.Caller(0)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- fmt.Fprintf(ioutil.Discard, "%n", c)
- }
-}
-
-func BenchmarkCallPlusNFmt(b *testing.B) {
- c := stack.Caller(0)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- fmt.Fprintf(ioutil.Discard, "%+n", c)
- }
-}
-
-func BenchmarkCaller(b *testing.B) {
- for i := 0; i < b.N; i++ {
- stack.Caller(0)
- }
-}
-
-func BenchmarkTrace(b *testing.B) {
- for i := 0; i < b.N; i++ {
- stack.Trace()
- }
-}
-
-func deepStack(depth int, b *testing.B) stack.CallStack {
- if depth > 0 {
- return deepStack(depth-1, b)
- }
- b.StartTimer()
- s := stack.Trace()
- return s
-}
-
-func BenchmarkTrace10(b *testing.B) {
- for i := 0; i < b.N; i++ {
- b.StopTimer()
- deepStack(10, b)
- }
-}
-
-func BenchmarkTrace50(b *testing.B) {
- b.StopTimer()
- for i := 0; i < b.N; i++ {
- deepStack(50, b)
- }
-}
-
-func BenchmarkTrace100(b *testing.B) {
- b.StopTimer()
- for i := 0; i < b.N; i++ {
- deepStack(100, b)
- }
-}
-
-////////////////
-// Benchmark functions followed by formatting
-////////////////
-
-func BenchmarkCallerAndVFmt(b *testing.B) {
- for i := 0; i < b.N; i++ {
- fmt.Fprint(ioutil.Discard, stack.Caller(0))
- }
-}
-
-func BenchmarkTraceAndVFmt(b *testing.B) {
- for i := 0; i < b.N; i++ {
- fmt.Fprint(ioutil.Discard, stack.Trace())
- }
-}
-
-func BenchmarkTrace10AndVFmt(b *testing.B) {
- for i := 0; i < b.N; i++ {
- b.StopTimer()
- fmt.Fprint(ioutil.Discard, deepStack(10, b))
- }
-}
-
-////////////////
-// Baseline against package runtime.
-////////////////
-
-func BenchmarkRuntimeCaller(b *testing.B) {
- for i := 0; i < b.N; i++ {
- runtime.Caller(0)
- }
-}
-
-func BenchmarkRuntimeCallerAndFmt(b *testing.B) {
- for i := 0; i < b.N; i++ {
- _, file, line, _ := runtime.Caller(0)
- const sep = "/"
- if i := strings.LastIndex(file, sep); i != -1 {
- file = file[i+len(sep):]
- }
- fmt.Fprint(ioutil.Discard, file, ":", line)
- }
-}
-
-func BenchmarkFuncForPC(b *testing.B) {
- pc, _, _, _ := runtime.Caller(0)
- pc--
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- runtime.FuncForPC(pc)
- }
-}
-
-func BenchmarkFuncFileLine(b *testing.B) {
- pc, _, _, _ := runtime.Caller(0)
- pc--
- fn := runtime.FuncForPC(pc)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- fn.FileLine(pc)
- }
-}