Skip to content

Commit

Permalink
Merge pull request #171 from SimonRichardson/errors-is-checker
Browse files Browse the repository at this point in the history
error.Is testing checker
  • Loading branch information
SimonRichardson authored Aug 16, 2023
2 parents 9af10d6 + 448af9c commit d0b20a6
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 0 deletions.
52 changes: 52 additions & 0 deletions checkers/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2023 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.

package checkers

import (
"errors"
"fmt"
"reflect"

gc "gopkg.in/check.v1"
)

type errorIsChecker struct {
*gc.CheckerInfo
}

// ErrorIs checks whether a value is an error that matches the other
// argument.
var ErrorIs gc.Checker = &errorIsChecker{
CheckerInfo: &gc.CheckerInfo{
Name: "ErrorIs",
Params: []string{"obtained", "error"},
},
}

var (
errType = reflect.TypeOf((*error)(nil)).Elem()
)

func (checker *errorIsChecker) Check(params []interface{}, names []string) (result bool, err string) {
if params[1] == nil || params[0] == nil {
return params[1] == params[0], ""
}

f := reflect.ValueOf(params[1])
ft := f.Type()
if !ft.Implements(errType) {
return false, fmt.Sprintf("wrong error target type, got: %s", ft)
}

v := reflect.ValueOf(params[0])
vt := v.Type()
if !v.IsValid() {
return false, fmt.Sprintf("wrong argument type %s for %s", vt, ft)
}
if !vt.Implements(errType) {
return false, fmt.Sprintf("wrong argument type %s for %s", vt, ft)
}

return errors.Is(v.Interface().(error), f.Interface().(error)), ""
}
69 changes: 69 additions & 0 deletions checkers/error_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package checkers_test

import (
"fmt"

"github.com/juju/errors"
jc "github.com/juju/testing/checkers"
gc "gopkg.in/check.v1"
)

type ErrorSuite struct{}

var _ = gc.Suite(&ErrorSuite{})

var errorIsTests = []struct {
arg interface{}
target interface{}
result bool
msg string
}{{
arg: fmt.Errorf("bar"),
target: nil,
result: false,
}, {
arg: nil,
target: fmt.Errorf("bar"),
result: false,
}, {
arg: nil,
target: nil,
result: true,
}, {
arg: fmt.Errorf("bar"),
target: fmt.Errorf("foo"),
result: false,
}, {
arg: errors.ConstError("bar"),
target: errors.ConstError("foo"),
result: false,
}, {
arg: errors.ConstError("foo"),
target: errors.ConstError("foo"),
result: true,
}, {
arg: errors.Trace(errors.ConstError("foo")),
target: errors.ConstError("foo"),
result: true,
}, {
arg: errors.ConstError("foo"),
target: "blah",
msg: "wrong error target type, got: string",
}, {
arg: "blah",
target: errors.ConstError("foo"),
msg: "wrong argument type string for errors.ConstError",
}, {
arg: (*error)(nil),
target: errors.ConstError("foo"),
msg: "wrong argument type *error for errors.ConstError",
}}

func (s *ErrorSuite) TestErrorIs(c *gc.C) {
for i, test := range errorIsTests {
c.Logf("test %d. %T %T", i, test.arg, test.target)
result, msg := jc.ErrorIs.Check([]interface{}{test.arg, test.target}, nil)
c.Check(result, gc.Equals, test.result)
c.Check(msg, gc.Equals, test.msg)
}
}

0 comments on commit d0b20a6

Please sign in to comment.