forked from TrueCloudLab/frostfs-sdk-go
client: Use error in FromStatusV2, ToStatusV2 functions
Signed-off-by: Evgenii Baidakov <evgenii@nspcc.io>
This commit is contained in:
parent
22ff96ad44
commit
26c1b26eec
4 changed files with 47 additions and 104 deletions
|
@ -197,12 +197,8 @@ func (x *contextCall) processResponse() bool {
|
|||
}
|
||||
|
||||
// get result status
|
||||
st := apistatus.FromStatusV2(x.resp.GetMetaHeader().GetStatus())
|
||||
|
||||
var errorExists bool
|
||||
x.err, errorExists = st.(error)
|
||||
|
||||
return !errorExists
|
||||
x.err = apistatus.FromStatusV2(x.resp.GetMetaHeader().GetStatus())
|
||||
return x.err == nil
|
||||
}
|
||||
|
||||
// processResponse verifies response signature.
|
||||
|
@ -211,12 +207,7 @@ func (c *Client) processResponse(resp responseV2) error {
|
|||
return fmt.Errorf("invalid response signature: %w", err)
|
||||
}
|
||||
|
||||
st := apistatus.FromStatusV2(resp.GetMetaHeader().GetStatus())
|
||||
if err, ok := st.(error); ok {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return apistatus.FromStatusV2(resp.GetMetaHeader().GetStatus())
|
||||
}
|
||||
|
||||
// reads response (if rResp is set) and processes it. Result means success.
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
package apistatus
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/status"
|
||||
)
|
||||
|
||||
// SuccessDefaultV2 represents instance of default success. Implements [StatusV2].
|
||||
type SuccessDefaultV2 struct {
|
||||
isNil bool
|
||||
|
||||
v2 *status.Status
|
||||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *SuccessDefaultV2) fromStatusV2(st *status.Status) {
|
||||
x.isNil = st == nil
|
||||
x.v2 = st
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
// If the value was returned by FromStatusV2, returns the source message.
|
||||
// Otherwise, returns message with
|
||||
// - code: OK;
|
||||
// - string message: empty;
|
||||
// - details: empty.
|
||||
func (x SuccessDefaultV2) ToStatusV2() *status.Status {
|
||||
if x.isNil || x.v2 != nil {
|
||||
return x.v2
|
||||
}
|
||||
|
||||
return newStatusV2WithLocalCode(status.OK, status.GlobalizeSuccess)
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package apistatus
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/container"
|
||||
|
@ -17,7 +18,7 @@ type StatusV2 interface {
|
|||
ToStatusV2() *status.Status
|
||||
}
|
||||
|
||||
// FromStatusV2 converts [status.Status] message structure to status instance. Inverse to [ToStatusV2] operation.
|
||||
// FromStatusV2 converts [status.Status] message structure to error. Inverse to [ToStatusV2] operation.
|
||||
//
|
||||
// If result is not nil, it implements [StatusV2]. This fact should be taken into account only when passing
|
||||
// the result to the inverse function [ToStatusV2], casts are not compatibility-safe.
|
||||
|
@ -26,7 +27,7 @@ type StatusV2 interface {
|
|||
// Note: notice if the return type is a pointer.
|
||||
//
|
||||
// Successes:
|
||||
// - [status.OK]: *[SuccessDefaultV2] (this also includes nil argument).
|
||||
// - [status.OK]: nil (this also includes nil argument).
|
||||
//
|
||||
// Common failures:
|
||||
// - [status.Internal]: *[ServerInternal];
|
||||
|
@ -49,9 +50,10 @@ type StatusV2 interface {
|
|||
// Session failures:
|
||||
// - [session.StatusTokenNotFound]: *[SessionTokenNotFound];
|
||||
// - [session.StatusTokenExpired]: *[SessionTokenExpired];
|
||||
func FromStatusV2(st *status.Status) any {
|
||||
func FromStatusV2(st *status.Status) error {
|
||||
var decoder interface {
|
||||
fromStatusV2(*status.Status)
|
||||
Error() string
|
||||
}
|
||||
|
||||
switch code := st.Code(); {
|
||||
|
@ -59,7 +61,7 @@ func FromStatusV2(st *status.Status) any {
|
|||
//nolint:exhaustive
|
||||
switch status.LocalizeSuccess(&code); code {
|
||||
case status.OK:
|
||||
decoder = new(SuccessDefaultV2)
|
||||
return nil
|
||||
}
|
||||
case status.IsCommonFail(code):
|
||||
switch status.LocalizeCommonFail(&code); code {
|
||||
|
@ -114,19 +116,19 @@ func FromStatusV2(st *status.Status) any {
|
|||
return decoder
|
||||
}
|
||||
|
||||
// ToStatusV2 converts instance to status.Status message structure. Inverse to [FromStatusV2] operation.
|
||||
// ToStatusV2 converts error to status.Status message structure. Inverse to [FromStatusV2] operation.
|
||||
//
|
||||
// If argument is the [StatusV2] instance, it is converted directly.
|
||||
// Otherwise, successes are converted with [status.OK] code w/o details and message,
|
||||
// failures - with [status.Internal] and error text message w/o details.
|
||||
func ToStatusV2(st any) *status.Status {
|
||||
if v, ok := st.(StatusV2); ok {
|
||||
return v.ToStatusV2()
|
||||
func ToStatusV2(err error) *status.Status {
|
||||
if err == nil {
|
||||
return newStatusV2WithLocalCode(status.OK, status.GlobalizeSuccess)
|
||||
}
|
||||
|
||||
err, isErrorExists := st.(error)
|
||||
if !isErrorExists {
|
||||
return newStatusV2WithLocalCode(status.OK, status.GlobalizeSuccess)
|
||||
var instance StatusV2
|
||||
if errors.As(err, &instance) {
|
||||
return instance.ToStatusV2()
|
||||
}
|
||||
|
||||
internalErrorStatus := newStatusV2WithLocalCode(status.Internal, status.GlobalizeCommonFail)
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
func TestFromStatusV2(t *testing.T) {
|
||||
type statusConstructor func() any
|
||||
type statusConstructor func() error
|
||||
|
||||
for _, testItem := range [...]struct {
|
||||
status any // Status or statusConstructor
|
||||
|
@ -19,32 +19,20 @@ func TestFromStatusV2(t *testing.T) {
|
|||
checkAsErr func(error) bool
|
||||
}{
|
||||
{
|
||||
status: errors.New("some error"),
|
||||
status: (statusConstructor)(func() error {
|
||||
return errors.New("some error")
|
||||
}),
|
||||
codeV2: 1024,
|
||||
messageV2: "some error",
|
||||
},
|
||||
{
|
||||
status: 1,
|
||||
status: (statusConstructor)(func() error {
|
||||
return nil
|
||||
}),
|
||||
codeV2: 0,
|
||||
},
|
||||
{
|
||||
status: "text",
|
||||
codeV2: 0,
|
||||
},
|
||||
{
|
||||
status: false,
|
||||
codeV2: 0,
|
||||
},
|
||||
{
|
||||
status: true,
|
||||
codeV2: 0,
|
||||
},
|
||||
{
|
||||
status: nil,
|
||||
codeV2: 0,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() any {
|
||||
status: (statusConstructor)(func() error {
|
||||
st := new(apistatus.ServerInternal)
|
||||
st.SetMessage("internal error message")
|
||||
|
||||
|
@ -58,7 +46,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() any {
|
||||
status: (statusConstructor)(func() error {
|
||||
st := new(apistatus.WrongMagicNumber)
|
||||
st.WriteCorrectMagic(322)
|
||||
|
||||
|
@ -72,7 +60,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() any {
|
||||
status: (statusConstructor)(func() error {
|
||||
return new(apistatus.ObjectLocked)
|
||||
}),
|
||||
codeV2: 2050,
|
||||
|
@ -83,7 +71,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() any {
|
||||
status: (statusConstructor)(func() error {
|
||||
return new(apistatus.LockNonRegularObject)
|
||||
}),
|
||||
codeV2: 2051,
|
||||
|
@ -94,7 +82,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() any {
|
||||
status: (statusConstructor)(func() error {
|
||||
st := new(apistatus.ObjectAccessDenied)
|
||||
st.WriteReason("any reason")
|
||||
|
||||
|
@ -108,7 +96,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() any {
|
||||
status: (statusConstructor)(func() error {
|
||||
return new(apistatus.ObjectNotFound)
|
||||
}),
|
||||
codeV2: 2049,
|
||||
|
@ -119,7 +107,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() any {
|
||||
status: (statusConstructor)(func() error {
|
||||
return new(apistatus.ObjectAlreadyRemoved)
|
||||
}),
|
||||
codeV2: 2052,
|
||||
|
@ -130,7 +118,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
status: statusConstructor(func() any {
|
||||
status: statusConstructor(func() error {
|
||||
return new(apistatus.ObjectOutOfRange)
|
||||
}),
|
||||
codeV2: 2053,
|
||||
|
@ -141,7 +129,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() any {
|
||||
status: (statusConstructor)(func() error {
|
||||
return new(apistatus.ContainerNotFound)
|
||||
}),
|
||||
codeV2: 3072,
|
||||
|
@ -152,7 +140,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() any {
|
||||
status: (statusConstructor)(func() error {
|
||||
return new(apistatus.EACLNotFound)
|
||||
}),
|
||||
codeV2: 3073,
|
||||
|
@ -163,7 +151,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() any {
|
||||
status: (statusConstructor)(func() error {
|
||||
return new(apistatus.SessionTokenNotFound)
|
||||
}),
|
||||
codeV2: 4096,
|
||||
|
@ -174,7 +162,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() any {
|
||||
status: (statusConstructor)(func() error {
|
||||
return new(apistatus.SessionTokenExpired)
|
||||
}),
|
||||
codeV2: 4097,
|
||||
|
@ -185,7 +173,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() any {
|
||||
status: (statusConstructor)(func() error {
|
||||
return new(apistatus.NodeUnderMaintenance)
|
||||
}),
|
||||
codeV2: 1027,
|
||||
|
@ -196,13 +184,11 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
},
|
||||
} {
|
||||
var st any
|
||||
var st error
|
||||
cons, ok := testItem.status.(statusConstructor)
|
||||
require.True(t, ok)
|
||||
|
||||
if cons, ok := testItem.status.(statusConstructor); ok {
|
||||
st = cons()
|
||||
} else {
|
||||
st = testItem.status
|
||||
}
|
||||
st = cons()
|
||||
|
||||
stv2 := apistatus.ToStatusV2(st)
|
||||
|
||||
|
@ -212,7 +198,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
require.Equal(t, testItem.messageV2, stv2.Message())
|
||||
}
|
||||
|
||||
_, ok := st.(apistatus.StatusV2)
|
||||
_, ok = st.(apistatus.StatusV2)
|
||||
if ok {
|
||||
// restore and convert again
|
||||
restored := apistatus.FromStatusV2(stv2)
|
||||
|
@ -224,17 +210,13 @@ func TestFromStatusV2(t *testing.T) {
|
|||
}
|
||||
|
||||
randomError := errors.New("garbage")
|
||||
// some `st` in test-cases is int, bool, string
|
||||
errFromStatus, ok := st.(error)
|
||||
if ok {
|
||||
for _, err := range testItem.compatibleErrs {
|
||||
require.ErrorIs(t, errFromStatus, err)
|
||||
require.NotErrorIs(t, randomError, err)
|
||||
}
|
||||
for _, err := range testItem.compatibleErrs {
|
||||
require.ErrorIs(t, st, err)
|
||||
require.NotErrorIs(t, randomError, err)
|
||||
}
|
||||
|
||||
if testItem.checkAsErr != nil {
|
||||
require.True(t, testItem.checkAsErr(errFromStatus))
|
||||
}
|
||||
if testItem.checkAsErr != nil {
|
||||
require.True(t, testItem.checkAsErr(st))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue