Commit 34a43d7c authored by Jonathan Amsterdam's avatar Jonathan Amsterdam

errors: improve As tests

Check the value of target after As returns true.

Change-Id: I76a2b25fe825ee1dbb5f39f8f0b211c55bd25a4f
Reviewed-on: https://go-review.googlesource.com/c/go/+/181299Reviewed-by: default avatarBryan C. Mills <bcmills@google.com>
parent 5f94d447
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"reflect"
"testing" "testing"
) )
...@@ -60,6 +61,8 @@ type poser struct { ...@@ -60,6 +61,8 @@ type poser struct {
f func(error) bool f func(error) bool
} }
var poserPathErr = &os.PathError{Op: "poser"}
func (p *poser) Error() string { return p.msg } func (p *poser) Error() string { return p.msg }
func (p *poser) Is(err error) bool { return p.f(err) } func (p *poser) Is(err error) bool { return p.f(err) }
func (p *poser) As(err interface{}) bool { func (p *poser) As(err interface{}) bool {
...@@ -67,9 +70,9 @@ func (p *poser) As(err interface{}) bool { ...@@ -67,9 +70,9 @@ func (p *poser) As(err interface{}) bool {
case **poser: case **poser:
*x = p *x = p
case *errorT: case *errorT:
*x = errorT{} *x = errorT{"poser"}
case **os.PathError: case **os.PathError:
*x = &os.PathError{} *x = poserPathErr
default: default:
return false return false
} }
...@@ -82,58 +85,74 @@ func TestAs(t *testing.T) { ...@@ -82,58 +85,74 @@ func TestAs(t *testing.T) {
var timeout interface{ Timeout() bool } var timeout interface{ Timeout() bool }
var p *poser var p *poser
_, errF := os.Open("non-existing") _, errF := os.Open("non-existing")
poserErr := &poser{"oh no", nil}
testCases := []struct { testCases := []struct {
err error err error
target interface{} target interface{}
match bool match bool
want interface{} // value of target on match
}{{ }{{
nil, nil,
&errP, &errP,
false, false,
nil,
}, { }, {
wrapped{"pittied the fool", errorT{}}, wrapped{"pitied the fool", errorT{"T"}},
&errT, &errT,
true, true,
errorT{"T"},
}, { }, {
errF, errF,
&errP, &errP,
true, true,
errF,
}, { }, {
errorT{}, errorT{},
&errP, &errP,
false, false,
nil,
}, { }, {
wrapped{"wrapped", nil}, wrapped{"wrapped", nil},
&errT, &errT,
false, false,
nil,
}, { }, {
&poser{"error", nil}, &poser{"error", nil},
&errT, &errT,
true, true,
errorT{"poser"},
}, { }, {
&poser{"path", nil}, &poser{"path", nil},
&errP, &errP,
true, true,
poserPathErr,
}, { }, {
&poser{"oh no", nil}, poserErr,
&p, &p,
true, true,
poserErr,
}, { }, {
errors.New("err"), errors.New("err"),
&timeout, &timeout,
false, false,
nil,
}, { }, {
errF, errF,
&timeout, &timeout,
true, true,
errF,
}, { }, {
wrapped{"path error", errF}, wrapped{"path error", errF},
&timeout, &timeout,
true, true,
errF,
}} }}
for i, tc := range testCases { for i, tc := range testCases {
name := fmt.Sprintf("%d:As(Errorf(..., %v), %v)", i, tc.err, tc.target) name := fmt.Sprintf("%d:As(Errorf(..., %v), %v)", i, tc.err, tc.target)
// Clear the target pointer, in case it was set in a previous test.
rtarget := reflect.ValueOf(tc.target)
rtarget.Elem().Set(reflect.Zero(reflect.TypeOf(tc.target).Elem()))
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
match := errors.As(tc.err, tc.target) match := errors.As(tc.err, tc.target)
if match != tc.match { if match != tc.match {
...@@ -142,8 +161,8 @@ func TestAs(t *testing.T) { ...@@ -142,8 +161,8 @@ func TestAs(t *testing.T) {
if !match { if !match {
return return
} }
if tc.target == nil { if got := rtarget.Elem().Interface(); got != tc.want {
t.Fatalf("non-nil result after match") t.Fatalf("got %#v, want %#v", got, tc.want)
} }
}) })
} }
...@@ -193,9 +212,9 @@ func TestUnwrap(t *testing.T) { ...@@ -193,9 +212,9 @@ func TestUnwrap(t *testing.T) {
} }
} }
type errorT struct{} type errorT struct{ s string }
func (errorT) Error() string { return "errorT" } func (e errorT) Error() string { return fmt.Sprintf("errorT(%s)", e.s) }
type wrapped struct { type wrapped struct {
msg string msg string
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment