[#278] client: Support wrapped errors in error checkers
Client errors are quite often wrapped in context. When checking a specific error, it is required not to lose the ability to determine it, regardless of the attached context. In previous implementation `IsErr*` functions didn't support wrapped errors. Make `IsErr*` functions to preliminarily unwrap `error` argument before type assertion. Use `errors.Unwrap` for this instead of `errors.As` since the latter has the overhead of filling in an error. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
40942affe9
commit
09ed6077f9
2 changed files with 22 additions and 7 deletions
|
@ -1,11 +1,24 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// unwraps err using errors.Unwrap and returns the result.
|
||||||
|
func unwrapErr(err error) error {
|
||||||
|
for e := errors.Unwrap(err); e != nil; e = errors.Unwrap(err) {
|
||||||
|
err = e
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// IsErrContainerNotFound checks if err corresponds to NeoFS status
|
// IsErrContainerNotFound checks if err corresponds to NeoFS status
|
||||||
// return corresponding to missing container.
|
// return corresponding to missing container. Supports wrapped errors.
|
||||||
func IsErrContainerNotFound(err error) bool {
|
func IsErrContainerNotFound(err error) bool {
|
||||||
switch err.(type) {
|
switch unwrapErr(err).(type) {
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
case
|
case
|
||||||
|
@ -16,9 +29,9 @@ func IsErrContainerNotFound(err error) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrObjectNotFound checks if err corresponds to NeoFS status
|
// IsErrObjectNotFound checks if err corresponds to NeoFS status
|
||||||
// return corresponding to missing object.
|
// return corresponding to missing object. Supports wrapped errors.
|
||||||
func IsErrObjectNotFound(err error) bool {
|
func IsErrObjectNotFound(err error) bool {
|
||||||
switch err.(type) {
|
switch unwrapErr(err).(type) {
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
case
|
case
|
||||||
|
@ -29,9 +42,9 @@ func IsErrObjectNotFound(err error) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrObjectAlreadyRemoved checks if err corresponds to NeoFS status
|
// IsErrObjectAlreadyRemoved checks if err corresponds to NeoFS status
|
||||||
// return corresponding to already removed object.
|
// return corresponding to already removed object. Supports wrapped errors.
|
||||||
func IsErrObjectAlreadyRemoved(err error) bool {
|
func IsErrObjectAlreadyRemoved(err error) bool {
|
||||||
switch err.(type) {
|
switch unwrapErr(err).(type) {
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
case
|
case
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package client_test
|
package client_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/client"
|
"github.com/nspcc-dev/neofs-sdk-go/client"
|
||||||
|
@ -39,6 +40,7 @@ func TestErrors(t *testing.T) {
|
||||||
|
|
||||||
for i := range tc.errs {
|
for i := range tc.errs {
|
||||||
require.True(t, tc.check(tc.errs[i]), tc.errs[i])
|
require.True(t, tc.check(tc.errs[i]), tc.errs[i])
|
||||||
|
require.True(t, tc.check(fmt.Errorf("some context: %w", tc.errs[i])), tc.errs[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue