Support InvalidArgument common failure status #277

Merged
fyrchik merged 4 commits from a-savchuk/frostfs-sdk-go:invalid-argument-status into master 2024-11-02 14:21:46 +00:00
7 changed files with 144 additions and 16 deletions

View file

@ -238,3 +238,61 @@ func (x *NodeUnderMaintenance) SetMessage(v string) {
func (x NodeUnderMaintenance) Message() string {
return x.v2.Message()
}
// InvalidArgument describes failure status related to invalid argument.
// Instances provide Status and StatusV2 interfaces.
type InvalidArgument struct {
v2 status.Status
}
const defaultInvalidArgumentMsg = "argument is invalid"
// Error implements the error interface.
func (x *InvalidArgument) Error() string {
msg := x.v2.Message()
if msg == "" {
msg = defaultInvalidArgumentMsg
}
return errMessageStatusV2(
globalizeCodeV2(status.InvalidArgument, status.GlobalizeCommonFail),
msg,
)
}
// implements local interface defined in FromStatusV2 func.
func (x *InvalidArgument) fromStatusV2(st *status.Status) {
x.v2 = *st
}
// ToStatusV2 implements StatusV2 interface method.
// If the value was returned by FromStatusV2, returns the source message.
// Otherwise, returns message with
// - code: INVALID_ARGUMENT;
// - string message: written message via SetMessage or
// "argument is invalid" as a default message;
// - details: empty.
func (x InvalidArgument) ToStatusV2() *status.Status {
x.v2.SetCode(globalizeCodeV2(status.InvalidArgument, status.GlobalizeCommonFail))
if x.v2.Message() == "" {
x.v2.SetMessage(defaultInvalidArgumentMsg)
}
return &x.v2
}
// SetMessage writes invalid argument failure message.
// Message should be used for debug purposes only.
//
// See also Message.
func (x *InvalidArgument) SetMessage(v string) {
x.v2.SetMessage(v)
}
// Message returns status message. Zero status returns empty message.
// Message should be used for debug purposes only.
//
// See also SetMessage.
func (x InvalidArgument) Message() string {
return x.v2.Message()
}

View file

@ -114,7 +114,7 @@ func TestNodeUnderMaintenance(t *testing.T) {
stV2 := st.ToStatusV2()
require.Empty(t, "", stV2.Message())
require.Equal(t, "node is under maintenance", stV2.Message())
fyrchik marked this conversation as resolved Outdated

How did it pass earlier?

How did it pass earlier?

require.Empty checks that "" is empty and it's empty indeed, so the test has succeeded. st2.Message() was mistakenly passed as an info message to display if the test had failed.

`require.Empty` checks that `""` is empty and it's empty indeed, so the test has succeeded. `st2.Message()` was mistakenly passed as an info message to display if the test had failed.

Indeed, I have written this code, seems to be copy-paste error.

Indeed, I have written this code, seems to be copy-paste error.
})
t.Run("non-empty to V2", func(t *testing.T) {
@ -128,3 +128,42 @@ func TestNodeUnderMaintenance(t *testing.T) {
require.Equal(t, msg, stV2.Message())
})
}
func TestInvalidArgument(t *testing.T) {
t.Run("default", func(t *testing.T) {
var st apistatus.InvalidArgument
require.Empty(t, st.Message())
})
t.Run("custom message", func(t *testing.T) {
var st apistatus.InvalidArgument
msg := "some message"
st.SetMessage(msg)
stV2 := st.ToStatusV2()
require.Equal(t, msg, st.Message())
require.Equal(t, msg, stV2.Message())
})
t.Run("empty to V2", func(t *testing.T) {
var st apistatus.InvalidArgument
stV2 := st.ToStatusV2()
require.Equal(t, "argument is invalid", stV2.Message())
})
t.Run("non-empty to V2", func(t *testing.T) {
var st apistatus.InvalidArgument
msg := "some other msg"
st.SetMessage(msg)
stV2 := st.ToStatusV2()
require.Equal(t, msg, stV2.Message())
})
}

View file

@ -33,12 +33,29 @@ type StatusV2 interface {
//
// Common failures:
// - status.Internal: *ServerInternal;
// - status.SignatureVerificationFail: *SignatureVerification.
// - status.WrongMagicNumber: *WrongMagicNumber;
// - status.SignatureVerificationFail: *SignatureVerification;
// - status.NodeUnderMaintenance: *NodeUnderMaintenance;
// - status.InvalidArgument: *InvalidArgument.
//
// Object failures:
// - object.StatusLocked: *ObjectLocked;
// - object.StatusLockNonRegularObject: *LockNonRegularObject.
// - object.StatusAccessDenied: *ObjectAccessDenied.
// - object.StatusLockNonRegularObject: *LockNonRegularObject;
// - object.StatusAccessDenied: *ObjectAccessDenied;
// - object.StatusNotFound: *ObjectNotFound;
// - object.StatusAlreadyRemoved: *ObjectAlreadyRemoved;
// - object.StatusOutOfRange: *ObjectOutOfRange.
//
// Container failures:
// - container.StatusNotFound: *ContainerNotFound;
// - container.StatusEACLNotFound: *EACLNotFound.
//
// Session failures:
// - session.StatusTokenNotFound: *SessionTokenNotFound;
// - session.StatusTokenExpired: *SessionTokenExpired.
//
// APE Manager failures
// - apemanager.StatusAPEManagerAccessDenied: *APEManagerAccessDenied.
func FromStatusV2(st *status.Status) Status {
var decoder interface {
fromStatusV2(*status.Status)
@ -61,6 +78,8 @@ func FromStatusV2(st *status.Status) Status {
decoder = new(SignatureVerification)
case status.NodeUnderMaintenance:
decoder = new(NodeUnderMaintenance)
case status.InvalidArgument:
decoder = new(InvalidArgument)
}
case object.LocalizeFailStatus(&code):
switch code {

View file

@ -61,6 +61,24 @@ func TestToStatusV2(t *testing.T) {
}),
codeV2: 1025,
},
{
status: (statusConstructor)(func() apistatus.Status {
return new(apistatus.SignatureVerification)
}),
codeV2: 1026,
},
{
status: (statusConstructor)(func() apistatus.Status {
return new(apistatus.NodeUnderMaintenance)
}),
codeV2: 1027,
},
{
status: (statusConstructor)(func() apistatus.Status {
return new(apistatus.InvalidArgument)
}),
codeV2: 1028,
},
{
status: (statusConstructor)(func() apistatus.Status {
return new(apistatus.ObjectLocked)
@ -131,12 +149,6 @@ func TestToStatusV2(t *testing.T) {
}),
codeV2: 5120,
},
{
status: (statusConstructor)(func() apistatus.Status {
return new(apistatus.NodeUnderMaintenance)
}),
codeV2: 1027,
},
} {
var st apistatus.Status

2
go.mod
View file

@ -3,7 +3,7 @@ module git.frostfs.info/TrueCloudLab/frostfs-sdk-go
go 1.22
require (
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240916093537-13fa0da3741e
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241002064811-3e705a3cbe84
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e
git.frostfs.info/TrueCloudLab/hrw v1.2.1
git.frostfs.info/TrueCloudLab/tzhash v1.8.0

4
go.sum
View file

@ -1,5 +1,5 @@
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240916093537-13fa0da3741e h1:740ABnOBYx4o6jxULHdSSnVW2fYIO35ohg+Uz59sxd0=
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240916093537-13fa0da3741e/go.mod h1:F5GS7hRb62PUy5sTYDC4ajVdeffoAfjHSSHTKUJEaYU=
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241002064811-3e705a3cbe84 h1:enycv8Uaji5Ic1+hk+F4BpYOQKV5U5t8A9CV8AmU2+M=
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241002064811-3e705a3cbe84/go.mod h1:F5GS7hRb62PUy5sTYDC4ajVdeffoAfjHSSHTKUJEaYU=
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4=
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc=
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk=

View file

@ -649,17 +649,17 @@ func TestHandleError(t *testing.T) {
},
{
ctx: ctx,
status: new(apistatus.SignatureVerification),
fyrchik marked this conversation as resolved Outdated

Why do you change unrelated tests instead of adding new ones?

Why do you change unrelated tests instead of adding new ones?

There were two duplicate test cases:

Lines 643 to 656 in 1b67ab9
{
ctx: ctx,
status: new(apistatus.SignatureVerification),
err: nil,
expectedError: true,
countError: true,
},
{
ctx: ctx,
status: new(apistatus.SignatureVerification),
err: nil,
expectedError: true,
countError: true,
},

I've deleted one of them and added a new one for the new status, but Git shows it as if I changed the existing test. Should I keep the duplicate test case?

There were two duplicate test cases: https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/1b67ab9608482f2f862fb582cd2570949ef83528/pool/pool_test.go#L643-L656 I've deleted one of them and added a new one for the new status, but Git shows it as if I changed the existing test. Should I keep the duplicate test case?
status: new(apistatus.NodeUnderMaintenance),
err: nil,
expectedError: true,
countError: true,
},
{
ctx: ctx,
status: new(apistatus.NodeUnderMaintenance),
status: new(apistatus.InvalidArgument),
err: nil,
expectedError: true,
countError: true,
countError: false,
},
{
ctx: canceledCtx,