Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make tidb adaptor in errors. #2

Merged
merged 21 commits into from
Sep 7, 2018
Merged
Show file tree
Hide file tree
Changes from 2 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
69 changes: 51 additions & 18 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@ func Errorf(format string, args ...interface{}) error {
}
}

type withStackAware interface {
Copy link
Member

Choose a reason for hiding this comment

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

Why not hasStackAware?

hasStack() bool
Copy link
Member

Choose a reason for hiding this comment

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

should it be upper-case to HasStack?

}

func hasStack(err error) bool {
Copy link
Member

Choose a reason for hiding this comment

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

rename to errHasStack to avoid name conflict?

errWithStack, hasStack := err.(withStackAware)
if !hasStack {
return false
}
return errWithStack.hasStack()
}

// fundamental is an error that has a message and a stack, but no caller.
type fundamental struct {
msg string
Expand All @@ -139,6 +151,10 @@ func (f *fundamental) Format(s fmt.State, verb rune) {
}
}

func (f *fundamental) hasStack() bool {
return true
}

// WithStack annotates err with a stack trace at the point WithStack was called.
// If err is nil, WithStack returns nil.
func WithStack(err error) error {
Expand Down Expand Up @@ -174,33 +190,47 @@ func (w *withStack) Format(s fmt.State, verb rune) {
}
}

// Wrap returns an error annotating err with a stack trace
// at the point Wrap is called, and the supplied message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error {
func (w *withStack) hasStack() bool {
return true
}

// Annotate returns an error annotating err with a stack trace
// at the point Annotate is called, and the supplied message.
// If err is nil, Annotate returns nil.
func Annotate(err error, message string) error {
if err == nil {
return nil
}
hasStack := hasStack(err)
err = &withMessage{
cause: err,
msg: message,
cause: err,
msg: message,
causeHasStack: hasStack,
}
if hasStack {
return err
}
return &withStack{
err,
callers(),
}
}

// Wrapf returns an error annotating err with a stack trace
// at the point Wrapf is call, and the format specifier.
// If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error {
// Annotatef returns an error annotating err with a stack trace
// at the point Annotatef is call, and the format specifier.
// If err is nil, Annotatef returns nil.
func Annotatef(err error, format string, args ...interface{}) error {
if err == nil {
return nil
}
hasStack := hasStack(err)
err = &withMessage{
cause: err,
msg: fmt.Sprintf(format, args...),
cause: err,
msg: fmt.Sprintf(format, args...),
causeHasStack: hasStack,
}
if hasStack {
return err
}
return &withStack{
err,
Expand All @@ -215,18 +245,21 @@ func WithMessage(err error, message string) error {
return nil
}
return &withMessage{
cause: err,
msg: message,
cause: err,
msg: message,
causeHasStack: hasStack(err),
}
}

type withMessage struct {
cause error
msg string
cause error
msg string
causeHasStack bool
}

func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
func (w *withMessage) Cause() error { return w.cause }
func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
func (w *withMessage) Cause() error { return w.cause }
func (w *withMessage) hasStack() bool { return w.causeHasStack }

func (w *withMessage) Format(s fmt.State, verb rune) {
switch verb {
Expand Down
20 changes: 10 additions & 10 deletions errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestNew(t *testing.T) {
}

func TestWrapNil(t *testing.T) {
got := Wrap(nil, "no error")
got := Annotate(nil, "no error")
if got != nil {
t.Errorf("Wrap(nil, \"no error\"): got %#v, expected nil", got)
}
Expand All @@ -41,11 +41,11 @@ func TestWrap(t *testing.T) {
want string
}{
{io.EOF, "read error", "read error: EOF"},
{Wrap(io.EOF, "read error"), "client error", "client error: read error: EOF"},
{Annotate(io.EOF, "read error"), "client error", "client error: read error: EOF"},
}

for _, tt := range tests {
got := Wrap(tt.err, tt.message).Error()
got := Annotate(tt.err, tt.message).Error()
if got != tt.want {
t.Errorf("Wrap(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want)
}
Expand Down Expand Up @@ -79,7 +79,7 @@ func TestCause(t *testing.T) {
want: io.EOF,
}, {
// caused error returns cause
err: Wrap(io.EOF, "ignored"),
err: Annotate(io.EOF, "ignored"),
want: io.EOF,
}, {
err: x, // return from errors.New
Expand Down Expand Up @@ -107,7 +107,7 @@ func TestCause(t *testing.T) {
}

func TestWrapfNil(t *testing.T) {
got := Wrapf(nil, "no error")
got := Annotate(nil, "no error")
if got != nil {
t.Errorf("Wrapf(nil, \"no error\"): got %#v, expected nil", got)
}
Expand All @@ -120,12 +120,12 @@ func TestWrapf(t *testing.T) {
want string
}{
{io.EOF, "read error", "read error: EOF"},
{Wrapf(io.EOF, "read error without format specifiers"), "client error", "client error: read error without format specifiers: EOF"},
{Wrapf(io.EOF, "read error with %d format specifier", 1), "client error", "client error: read error with 1 format specifier: EOF"},
{Annotatef(io.EOF, "read error without format specifiers"), "client error", "client error: read error without format specifiers: EOF"},
{Annotatef(io.EOF, "read error with %d format specifier", 1), "client error", "client error: read error with 1 format specifier: EOF"},
}

for _, tt := range tests {
got := Wrapf(tt.err, tt.message).Error()
got := Annotatef(tt.err, tt.message).Error()
if got != tt.want {
t.Errorf("Wrapf(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want)
}
Expand Down Expand Up @@ -209,8 +209,8 @@ func TestErrorEquality(t *testing.T) {
errors.New("EOF"),
New("EOF"),
Errorf("EOF"),
Wrap(io.EOF, "EOF"),
Wrapf(io.EOF, "EOF%d", 2),
Annotate(io.EOF, "EOF"),
Annotatef(io.EOF, "EOF%d", 2),
WithMessage(nil, "whoops"),
WithMessage(io.EOF, "whoops"),
WithStack(io.EOF),
Expand Down
Loading