Skip to content
This repository has been archived by the owner on Dec 1, 2021. It is now read-only.

feat ExistStack: Add a public method to determine if the error has been appended to the stack. #239

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,24 @@ func New(message string) error {
}
}

// ExistStack return an error already with stack
// ExistStack will check all parent error
func ExistStack(err error) bool {
type stackTracer interface {
StackTrace() StackTrace
}
if _, ok := err.(stackTracer); ok {
return true
}
type causer interface {
Cause() error
}
Comment on lines +118 to +120

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checking Cause() error ignores the possibility of an Unwrap() error which is kind of the preferred way of unwrapping errors now. So, this would only work with errors from this package, and those designed specifically for pre-unwrap compatibility with this package, which is no longer a strong argument since go1.13.

if value, ok := err.(causer); ok {
return ExistStack(err.Cause())
} else {
return false

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every code path in the preceding if … { … } block returns from the function, therefore there is no reason to use an else block.

Considering using:

cause, ok := err.(causer)
if !ok {
  return false
}
return ExistStack(cause.Cause())

Please check the implementation of Cause(err error) below, and try and mirror that as much as possible.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for your help

}
}
// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
// Errorf also records the stack trace at the point it was called.
Expand Down
17 changes: 17 additions & 0 deletions errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,23 @@ func TestNew(t *testing.T) {
}
}

func TestExistStack(t *testing.T) {
tests := []struct {
err error
want bool
}{
{io.EOF, false},
{Wrap(io.EOF, "read error"), true},

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing test cases: WithStack, WithMessage, and errors.New.

}

for _, tt := range tests {
got := ExistStack(tt.err)
if got != tt.want {
t.Errorf("ExistStack(%v): got: %v, want %v", tt.err, got, tt.want)
}
}
}

func TestWrapNil(t *testing.T) {
got := Wrap(nil, "no error")
if got != nil {
Expand Down