func TestCallersMulti(t *testing.T) { m := stack.CallersMulti(0) const expected = "stack_test.go:35 TestCallersMulti" first := m.Stacks()[0][0].String() if !strings.HasSuffix(first, expected) { t.Fatalf(`expected suffix "%s" got "%s"`, expected, first) } }
func stackFromErrValue(errValue interface{}) *stack.Multi { if stackErr, ok := errValue.(stackErr); ok { return stackErr.MultiStack() } else { // skip 2 stack frames such that top frame is the service handler return stack.CallersMulti(2) } }
func TestCallersMulti(t *testing.T) { m := stack.CallersMulti(0) const expected = "github.com/facebookgo/stack/stack_test.go:35 TestCallersMulti" first := m.Stacks()[0][0].String() if first != expected { t.Fatalf(`expected "%s" got "%s"`, expected, first) } }
func TestCallersMultiWithTwo(t *testing.T) { m := stack.CallersMulti(0) m.AddCallers(0) matches := []string{ "stack_test.go:44 +TestCallersMultiWithTwo$", "", "", `\(Stack 2\)$`, "stack_test.go:46 +TestCallersMultiWithTwo$", } match(t, m.String(), matches) }
func TestCallersMultiWithTwo(t *testing.T) { m := stack.CallersMulti(0) m.AddCallers(0) matches := []string{ "^github.com/facebookgo/stack/stack_test.go:44 +TestCallersMultiWithTwo$", "", "", `^\(Stack 2\)$`, "^github.com/facebookgo/stack/stack_test.go:46 +TestCallersMultiWithTwo$", } match(t, m.String(), matches) }
// WrapSkip the error and add the current Stack. The argument skip is the // number of stack frames to ascend, with 0 identifying the caller of Wrap. If // the error to be wrapped has a MultiStack, the current stack will be added to // it. If the error to be wrapped is nil, a nil error is returned. func WrapSkip(err error, skip int) error { // nil errors are returned back as nil. if err == nil { return nil } // we're adding another Stack to an already wrapped error. if se, ok := err.(hasMultiStack); ok { se.MultiStack().AddCallers(skip + 1) return err } // we're create a freshly wrapped error. return &Error{ multiStack: stack.CallersMulti(skip + 1), underlying: err, } }
// WrapSkip may wrap the error and return an augmented error depending on the // configuration in the context. The defaults result in the error being // returned as is. It also handles nils correctly, returning a nil in that // case. If the given error is already wrapped, it returns it as-is. func WrapSkip(ctx context.Context, err error, skip int) error { switch err := err.(type) { case nil: return nil case *singleFrameError: return err case *singleStackError: return err case *multiStackError: err.multiStack.AddCallers(skip + 1) return err } config := ContextConfig(ctx) switch config.StackMode { case StackModeSingleFrame: return &singleFrameError{ config: config, underlying: err, frame: stack.Caller(skip + 1), } case StackModeSingleStack: return &singleStackError{ config: config, underlying: err, stack: stack.Callers(skip + 1), } case StackModeMultiStack: return &multiStackError{ config: config, underlying: err, multiStack: stack.CallersMulti(skip + 1), } } return err }
func BenchmarkCallersMulti(b *testing.B) { for i := 0; i < b.N; i++ { stack.CallersMulti(0) } }
// Chk checks if the error var is nil // If not it prints the error and stops execution func Chk(err error) { if nil != err { fmt.Println(stack.CallersMulti(0)) log.Fatal(err) } }