diff options
Diffstat (limited to 'vendor/github.com/go-stack')
-rw-r--r-- | vendor/github.com/go-stack/stack/LICENSE.md | 21 | ||||
-rw-r--r-- | vendor/github.com/go-stack/stack/README.md | 38 | ||||
-rw-r--r-- | vendor/github.com/go-stack/stack/format_test.go | 21 | ||||
-rw-r--r-- | vendor/github.com/go-stack/stack/go.mod | 1 | ||||
-rw-r--r-- | vendor/github.com/go-stack/stack/stack-go19_test.go | 67 | ||||
-rw-r--r-- | vendor/github.com/go-stack/stack/stack.go | 400 | ||||
-rw-r--r-- | vendor/github.com/go-stack/stack/stack_test.go | 582 |
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) - } -} |