frostfs-api-go/v2/container/marshal_test.go
Leonard Lyubich 93e1580684 [#253] container: Implement marshalers on UsedSpaceAnnouncement structure
Implement Unmarshal method on UsedSpaceAnnouncement v2 message. Implement
Marshal/Unmarshal methods on cross-version UsedSpaceAnnouncement type.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2021-02-11 15:04:13 +03:00

492 lines
13 KiB
Go

package container_test
import (
"crypto/sha256"
"fmt"
"math/rand"
"testing"
"github.com/nspcc-dev/neofs-api-go/v2/acl"
"github.com/nspcc-dev/neofs-api-go/v2/container"
grpc "github.com/nspcc-dev/neofs-api-go/v2/container/grpc"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
"github.com/stretchr/testify/require"
goproto "google.golang.org/protobuf/proto"
)
func TestAttribute_StableMarshal(t *testing.T) {
attributeFrom := generateAttribute("key", "value")
t.Run("non empty", func(t *testing.T) {
wire, err := attributeFrom.StableMarshal(nil)
require.NoError(t, err)
attributeTo := new(container.Attribute)
require.NoError(t, attributeTo.Unmarshal(wire))
require.Equal(t, attributeFrom, attributeTo)
})
}
func TestContainer_StableMarshal(t *testing.T) {
cnrFrom := generateContainer("nonce")
t.Run("non empty", func(t *testing.T) {
wire, err := cnrFrom.StableMarshal(nil)
require.NoError(t, err)
cnrTo := new(container.Container)
require.NoError(t, cnrTo.Unmarshal(wire))
require.Equal(t, cnrFrom, cnrTo)
})
}
func TestPutRequestBody_StableMarshal(t *testing.T) {
requestFrom := generatePutRequestBody("nonce")
transport := new(grpc.PutRequest_Body)
t.Run("non empty", func(t *testing.T) {
wire, err := requestFrom.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
requestTo := container.PutRequestBodyFromGRPCMessage(transport)
require.Equal(t, requestFrom, requestTo)
})
}
func TestPutResponseBody_StableMarshal(t *testing.T) {
responseFrom := generatePutResponseBody("Container ID")
transport := new(grpc.PutResponse_Body)
t.Run("non empty", func(t *testing.T) {
wire, err := responseFrom.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
responseTo := container.PutResponseBodyFromGRPCMessage(transport)
require.Equal(t, responseFrom, responseTo)
})
}
func TestDeleteRequestBody_StableMarshal(t *testing.T) {
requestFrom := generateDeleteRequestBody("Container ID")
transport := new(grpc.DeleteRequest_Body)
t.Run("non empty", func(t *testing.T) {
wire, err := requestFrom.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
requestTo := container.DeleteRequestBodyFromGRPCMessage(transport)
require.Equal(t, requestFrom, requestTo)
})
}
func TestDeleteResponseBody_StableMarshal(t *testing.T) {
responseFrom := generateDeleteResponseBody()
transport := new(grpc.DeleteResponse_Body)
t.Run("non empty", func(t *testing.T) {
wire, err := responseFrom.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
responseTo := container.DeleteResponseBodyFromGRPCMessage(transport)
require.Equal(t, responseFrom, responseTo)
})
}
func TestGetRequestBody_StableMarshal(t *testing.T) {
requestFrom := generateGetRequestBody("Container ID")
transport := new(grpc.GetRequest_Body)
t.Run("non empty", func(t *testing.T) {
wire, err := requestFrom.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
requestTo := container.GetRequestBodyFromGRPCMessage(transport)
require.Equal(t, requestFrom, requestTo)
})
}
func TestGetResponseBody_StableMarshal(t *testing.T) {
responseFrom := generateGetResponseBody("nonce")
transport := new(grpc.GetResponse_Body)
t.Run("non empty", func(t *testing.T) {
wire, err := responseFrom.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
responseTo := container.GetResponseBodyFromGRPCMessage(transport)
require.Equal(t, responseFrom, responseTo)
})
}
func TestListRequestBody_StableMarshal(t *testing.T) {
requestFrom := generateListRequestBody("Owner ID")
transport := new(grpc.ListRequest_Body)
t.Run("non empty", func(t *testing.T) {
wire, err := requestFrom.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
requestTo := container.ListRequestBodyFromGRPCMessage(transport)
require.Equal(t, requestFrom, requestTo)
})
}
func TestListResponseBody_StableMarshal(t *testing.T) {
responseFrom := generateListResponseBody(3)
transport := new(grpc.ListResponse_Body)
t.Run("non empty", func(t *testing.T) {
wire, err := responseFrom.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
responseTo := container.ListResponseBodyFromGRPCMessage(transport)
require.Equal(t, responseFrom, responseTo)
})
}
func TestSetEACLRequestBody_StableMarshal(t *testing.T) {
requestFrom := generateSetEACLRequestBody(4, "Filter Key", "Filter Value")
transport := new(grpc.SetExtendedACLRequest_Body)
t.Run("non empty", func(t *testing.T) {
wire, err := requestFrom.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
requestTo := container.SetExtendedACLRequestBodyFromGRPCMessage(transport)
require.Equal(t, requestFrom, requestTo)
})
}
func TestSetEACLResponseBody_StableMarshal(t *testing.T) {
responseFrom := generateSetEACLResponseBody()
transport := new(grpc.SetExtendedACLResponse_Body)
t.Run("non empty", func(t *testing.T) {
wire, err := responseFrom.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
responseTo := container.SetExtendedACLResponseBodyFromGRPCMessage(transport)
require.Equal(t, responseFrom, responseTo)
})
}
func TestGetEACLRequestBody_StableMarshal(t *testing.T) {
requestFrom := generateGetEACLRequestBody("Container ID")
transport := new(grpc.GetExtendedACLRequest_Body)
t.Run("non empty", func(t *testing.T) {
wire, err := requestFrom.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
requestTo := container.GetExtendedACLRequestBodyFromGRPCMessage(transport)
require.Equal(t, requestFrom, requestTo)
})
}
func TestGetEACLResponseBody_StableMarshal(t *testing.T) {
responseFrom := generateGetEACLResponseBody(3, "Filter Key", "Filter Value")
transport := new(grpc.GetExtendedACLResponse_Body)
t.Run("non empty", func(t *testing.T) {
wire, err := responseFrom.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
responseTo := container.GetExtendedACLResponseBodyFromGRPCMessage(transport)
require.Equal(t, responseFrom, responseTo)
})
}
func TestUsedSpaceAnnouncement_StableMarshal(t *testing.T) {
from := generateAnnouncement()
transport := new(grpc.AnnounceUsedSpaceRequest_Body_Announcement)
t.Run("non empty", func(t *testing.T) {
wire, err := from.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
to := container.UsedSpaceAnnouncementFromGRPCMessage(transport)
require.Equal(t, from, to)
})
}
func TestAnnounceUsedSpaceRequestBody_StableMarshal(t *testing.T) {
requestFrom := generateAnnounceRequestBody(10)
transport := new(grpc.AnnounceUsedSpaceRequest_Body)
t.Run("non empty", func(t *testing.T) {
wire, err := requestFrom.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
requestTo := container.AnnounceUsedSpaceRequestBodyFromGRPCMessage(transport)
require.Equal(t, requestFrom, requestTo)
})
}
func TestAnnounceUsedSpaceResponseBody_StableMarshal(t *testing.T) {
responseFrom := generateAnnounceResponseBody()
transport := new(grpc.AnnounceUsedSpaceResponse_Body)
t.Run("non empty", func(t *testing.T) {
wire, err := responseFrom.StableMarshal(nil)
require.NoError(t, err)
err = goproto.Unmarshal(wire, transport)
require.NoError(t, err)
responseTo := container.AnnounceUsedSpaceResponseBodyFromGRPCMessage(transport)
require.Equal(t, responseFrom, responseTo)
})
}
func generateAttribute(k, v string) *container.Attribute {
attr := new(container.Attribute)
attr.SetKey(k)
attr.SetValue(v)
return attr
}
func generateContainer(n string) *container.Container {
owner := new(refs.OwnerID)
owner.SetValue([]byte("Owner ID"))
version := new(refs.Version)
version.SetMajor(2)
version.SetMinor(0)
// todo: add placement rule
cnr := new(container.Container)
cnr.SetOwnerID(owner)
cnr.SetVersion(version)
cnr.SetAttributes([]*container.Attribute{
generateAttribute("one", "two"),
generateAttribute("three", "four"),
})
cnr.SetBasicACL(100)
cnr.SetNonce([]byte(n))
return cnr
}
func generateSignature(k, v string) *refs.Signature {
sig := new(refs.Signature)
sig.SetKey([]byte(k))
sig.SetSign([]byte(v))
return sig
}
func generatePutRequestBody(n string) *container.PutRequestBody {
req := new(container.PutRequestBody)
req.SetContainer(generateContainer(n))
req.SetSignature(generateSignature("public key", "signature"))
return req
}
func generatePutResponseBody(id string) *container.PutResponseBody {
cid := new(refs.ContainerID)
cid.SetValue([]byte(id))
resp := new(container.PutResponseBody)
resp.SetContainerID(cid)
return resp
}
func generateDeleteRequestBody(id string) *container.DeleteRequestBody {
cid := new(refs.ContainerID)
cid.SetValue([]byte(id))
req := new(container.DeleteRequestBody)
req.SetContainerID(cid)
req.SetSignature(generateSignature("public key", "signature"))
return req
}
func generateDeleteResponseBody() *container.DeleteResponseBody {
return new(container.DeleteResponseBody)
}
func generateGetRequestBody(id string) *container.GetRequestBody {
cid := new(refs.ContainerID)
cid.SetValue([]byte(id))
req := new(container.GetRequestBody)
req.SetContainerID(cid)
return req
}
func generateGetResponseBody(n string) *container.GetResponseBody {
resp := new(container.GetResponseBody)
resp.SetContainer(generateContainer(n))
return resp
}
func generateListRequestBody(id string) *container.ListRequestBody {
owner := new(refs.OwnerID)
owner.SetValue([]byte(id))
req := new(container.ListRequestBody)
req.SetOwnerID(owner)
return req
}
func generateListResponseBody(n int) *container.ListResponseBody {
resp := new(container.ListResponseBody)
ids := make([]*refs.ContainerID, n)
for i := 0; i < n; i++ {
cid := new(refs.ContainerID)
cid.SetValue([]byte(fmt.Sprintf("Container ID %d", n+1)))
ids[i] = cid
}
resp.SetContainerIDs(ids)
return resp
}
func generateEACL(n int, k, v string) *acl.Table {
target := new(acl.Target)
target.SetRole(acl.RoleUser)
keys := make([][]byte, n)
for i := 0; i < n; i++ {
s := fmt.Sprintf("Public Key %d", i+1)
keys[i] = []byte(s)
}
filter := new(acl.HeaderFilter)
filter.SetHeaderType(acl.HeaderTypeObject)
filter.SetMatchType(acl.MatchTypeStringEqual)
filter.SetKey(k)
filter.SetValue(v)
record := new(acl.Record)
record.SetOperation(acl.OperationHead)
record.SetAction(acl.ActionDeny)
record.SetTargets([]*acl.Target{target})
record.SetFilters([]*acl.HeaderFilter{filter})
table := new(acl.Table)
cid := new(refs.ContainerID)
cid.SetValue([]byte("Container ID"))
table.SetContainerID(cid)
table.SetRecords([]*acl.Record{record})
return table
}
func generateSetEACLRequestBody(n int, k, v string) *container.SetExtendedACLRequestBody {
req := new(container.SetExtendedACLRequestBody)
req.SetEACL(generateEACL(n, k, v))
req.SetSignature(generateSignature("public key", "signature"))
return req
}
func generateSetEACLResponseBody() *container.SetExtendedACLResponseBody {
return new(container.SetExtendedACLResponseBody)
}
func generateGetEACLRequestBody(id string) *container.GetExtendedACLRequestBody {
cid := new(refs.ContainerID)
cid.SetValue([]byte(id))
req := new(container.GetExtendedACLRequestBody)
req.SetContainerID(cid)
return req
}
func generateGetEACLResponseBody(n int, k, v string) *container.GetExtendedACLResponseBody {
resp := new(container.GetExtendedACLResponseBody)
resp.SetEACL(generateEACL(n, k, v))
resp.SetSignature(generateSignature("public key", "signature"))
return resp
}
func generateAnnouncement() *container.UsedSpaceAnnouncement {
buf := make([]byte, sha256.Size)
rand.Read(buf)
cid := new(refs.ContainerID)
cid.SetValue(buf)
a := new(container.UsedSpaceAnnouncement)
a.SetEpoch(rand.Uint64())
a.SetContainerID(cid)
a.SetUsedSpace(rand.Uint64())
return a
}
func generateAnnounceRequestBody(n int) *container.AnnounceUsedSpaceRequestBody {
resp := new(container.AnnounceUsedSpaceRequestBody)
announcements := make([]*container.UsedSpaceAnnouncement, 0, n)
for i := 0; i < n; i++ {
announcements = append(announcements, generateAnnouncement())
}
resp.SetAnnouncements(announcements)
return resp
}
func generateAnnounceResponseBody() *container.AnnounceUsedSpaceResponseBody {
return new(container.AnnounceUsedSpaceResponseBody)
}