From e8c21980b626a566acd580f91bc8f68921796ec5 Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Tue, 24 May 2016 12:36:43 +1000 Subject: [PATCH] Make errors.stack comparable (#30) Fixed #29 errors.New, etc values are not expected to be compared by value but the change in errors#27 made them incomparable. Assert that various kinds of errors have a functional equality operator, even if the result of that equality is always false. --- errors.go | 19 ++++++++++--------- errors_test.go | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/errors.go b/errors.go index 9b057f6..4f128df 100644 --- a/errors.go +++ b/errors.go @@ -64,17 +64,17 @@ import ( // stack represents a stack of programm counters. type stack []uintptr -func (s stack) Stack() []uintptr { return s } +func (s *stack) Stack() []uintptr { return *s } -func (s stack) Location() (string, int) { - return location(s[0] - 1) +func (s *stack) Location() (string, int) { + return location((*s)[0] - 1) } // New returns an error that formats as the given text. func New(text string) error { return struct { error - stack + *stack }{ errors.New(text), callers(), @@ -95,7 +95,7 @@ func (c cause) Message() string { return c.message } func Errorf(format string, args ...interface{}) error { return struct { error - stack + *stack }{ fmt.Errorf(format, args...), callers(), @@ -120,10 +120,10 @@ func Wrapf(cause error, format string, args ...interface{}) error { return wrap(cause, fmt.Sprintf(format, args...), callers()) } -func wrap(err error, msg string, st stack) error { +func wrap(err error, msg string, st *stack) error { return struct { cause - stack + *stack }{ cause{ cause: err, @@ -198,11 +198,12 @@ func Fprint(w io.Writer, err error) { } } -func callers() stack { +func callers() *stack { const depth = 32 var pcs [depth]uintptr n := runtime.Callers(3, pcs[:]) - return pcs[0:n] + var st stack = pcs[0:n] + return &st } // location returns the source file and line matching pc. diff --git a/errors_test.go b/errors_test.go index 7ffd7db..2795bb2 100644 --- a/errors_test.go +++ b/errors_test.go @@ -241,3 +241,24 @@ func TestStack(t *testing.T) { } } } + +// errors.New, etc values are not expected to be compared by value +// but the change in errors#27 made them incomparable. Assert that +// various kinds of errors have a functional equality operator, even +// if the result of that equality is always false. +func TestErrorEquality(t *testing.T) { + tests := []struct { + err1, err2 error + }{ + {io.EOF, io.EOF}, + {io.EOF, nil}, + {io.EOF, errors.New("EOF")}, + {io.EOF, New("EOF")}, + {New("EOF"), New("EOF")}, + {New("EOF"), Errorf("EOF")}, + {New("EOF"), Wrap(io.EOF, "EOF")}, + } + for _, tt := range tests { + _ = tt.err1 == tt.err2 // mustn't panic + } +}