1
0
mirror of https://github.com/golang/go synced 2024-09-29 09:34:28 -06:00

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/+/181299
Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
Jonathan Amsterdam 2019-06-08 07:32:13 -04:00
parent 5f94d44722
commit 34a43d7c1d

View File

@ -8,6 +8,7 @@ import (
"errors"
"fmt"
"os"
"reflect"
"testing"
)
@ -60,6 +61,8 @@ type poser struct {
f func(error) bool
}
var poserPathErr = &os.PathError{Op: "poser"}
func (p *poser) Error() string { return p.msg }
func (p *poser) Is(err error) bool { return p.f(err) }
func (p *poser) As(err interface{}) bool {
@ -67,9 +70,9 @@ func (p *poser) As(err interface{}) bool {
case **poser:
*x = p
case *errorT:
*x = errorT{}
*x = errorT{"poser"}
case **os.PathError:
*x = &os.PathError{}
*x = poserPathErr
default:
return false
}
@ -82,58 +85,74 @@ func TestAs(t *testing.T) {
var timeout interface{ Timeout() bool }
var p *poser
_, errF := os.Open("non-existing")
poserErr := &poser{"oh no", nil}
testCases := []struct {
err error
target interface{}
match bool
want interface{} // value of target on match
}{{
nil,
&errP,
false,
nil,
}, {
wrapped{"pittied the fool", errorT{}},
wrapped{"pitied the fool", errorT{"T"}},
&errT,
true,
errorT{"T"},
}, {
errF,
&errP,
true,
errF,
}, {
errorT{},
&errP,
false,
nil,
}, {
wrapped{"wrapped", nil},
&errT,
false,
nil,
}, {
&poser{"error", nil},
&errT,
true,
errorT{"poser"},
}, {
&poser{"path", nil},
&errP,
true,
poserPathErr,
}, {
&poser{"oh no", nil},
poserErr,
&p,
true,
poserErr,
}, {
errors.New("err"),
&timeout,
false,
nil,
}, {
errF,
&timeout,
true,
errF,
}, {
wrapped{"path error", errF},
&timeout,
true,
errF,
}}
for i, tc := range testCases {
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) {
match := errors.As(tc.err, tc.target)
if match != tc.match {
@ -142,8 +161,8 @@ func TestAs(t *testing.T) {
if !match {
return
}
if tc.target == nil {
t.Fatalf("non-nil result after match")
if got := rtarget.Elem().Interface(); got != tc.want {
t.Fatalf("got %#v, want %#v", got, tc.want)
}
})
}
@ -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 {
msg string