diff --git a/juju_adaptor.go b/juju_adaptor.go index 97a4b2b..ece86cd 100644 --- a/juju_adaptor.go +++ b/juju_adaptor.go @@ -66,18 +66,37 @@ func NewNoStackError(msg string) error { } } -// SuspendStack suspends stack for a exists error. -// it can be used to suspend follow up Trace do not add stack. +// SuspendStack suspends stack generate for error. func SuspendStack(err error) error { if err == nil { return err } - return withStack{ + cleared := clearStack(err) + if cleared { + return err + } + return &withStack{ err, &emptyStack, } } +func clearStack(err error) (cleared bool) { + switch typedErr := err.(type) { + case *withMessage: + return clearStack(typedErr.Cause()) + case *fundamental: + typedErr.stack = &emptyStack + return true + case *withStack: + typedErr.stack = &emptyStack + clearStack(typedErr.Cause()) + return true + default: + return false + } +} + // ErrorStack will format a stack trace if it is available, otherwise it will be Error() // If the error is nil, the empty string is returned // Note that this just calls fmt.Sprintf("%+v", err) diff --git a/stack_test.go b/stack_test.go index 16e3912..7ef28fe 100644 --- a/stack_test.go +++ b/stack_test.go @@ -299,7 +299,7 @@ func TestNewNoStackError(t *testing.T) { } } -func TestSuspendStackError(t *testing.T) { +func TestSuspendError(t *testing.T) { err := io.EOF err = SuspendStack(err) err = Trace(err) @@ -307,4 +307,19 @@ func TestSuspendStackError(t *testing.T) { if result != "EOF" { t.Errorf("NewNoStackError(): want %s, got %v", "EOF", result) } + if io.EOF != Cause(err) { + t.Errorf("SuspendStackError can not got back origion error.") + } +} + +func TestSuspendTracedWithMessageError(t *testing.T) { + tracedErr := Trace(io.EOF) + tracedErr = WithStack(tracedErr) + tracedErr = WithMessage(tracedErr, "1") + tracedErr = SuspendStack(tracedErr) + tracedErr = Trace(tracedErr) + result := fmt.Sprintf("%+v", tracedErr) + if result != "EOF\n1" { + t.Errorf("NewNoStackError(): want %s, got %v", "EOF\n1", result) + } }