From dc91753206ce83995cf688c45393603eb1da9b8f Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Tue, 18 Aug 2020 19:46:55 +0300 Subject: [PATCH] Add stable marshal for object service Signed-off-by: Alex Vanin --- v2/object/marshal.go | 768 +++++++++++++++++++++++++++++++++++++- v2/object/marshal_test.go | 457 ++++++++++++++++++++++- 2 files changed, 1202 insertions(+), 23 deletions(-) diff --git a/v2/object/marshal.go b/v2/object/marshal.go index 7693846..3949066 100644 --- a/v2/object/marshal.go +++ b/v2/object/marshal.go @@ -36,6 +36,59 @@ const ( objSignatureField = 2 objHeaderField = 3 objPayloadField = 4 + + getReqBodyAddressField = 1 + getReqBodyRawFlagField = 2 + + getRespInitObjectIDField = 1 + getRespInitSignatureField = 2 + getRespInitHeaderField = 3 + + getRespBodyInitField = 1 + getRespBodyChunkField = 2 + + putReqInitObjectIDField = 1 + putReqInitSignatureField = 2 + putReqInitHeaderField = 3 + putReqInitCopiesNumField = 4 + + putReqBodyInitField = 1 + putReqBodyChunkField = 2 + + putRespBodyObjectIDField = 1 + + deleteReqBodyAddressField = 1 + + headReqBodyAddressField = 1 + headReqBodyMainFlagField = 2 + headReqBodyRawFlagField = 3 + + headRespBodyHeaderField = 1 + headRespBodyShortHeaderField = 2 + + searchFilterMatchField = 1 + searchFilterNameField = 2 + searchFilterValueField = 3 + + searchReqBodyContainerIDField = 1 + searchReqBodyVersionField = 2 + searchReqBodyFiltersField = 3 + + searchRespBodyObjectIDsField = 1 + + rangeOffsetField = 1 + rangeLengthField = 2 + + getRangeReqBodyAddressField = 1 + getRangeReqBodyRangeField = 2 + + getRangeRespChunkField = 1 + + getRangeHashReqBodyAddressField = 1 + getRangeHashReqBodyRangesField = 2 + getRangeHashReqBodySaltField = 3 + + getRangeHashRespBodyHashList = 1 ) func (h *ShortHeader) StableMarshal(buf []byte) ([]byte, error) { @@ -385,66 +438,745 @@ func (o *Object) StableSize() (size int) { return size } -func (r *PutRequestBody) StableMarshal(buf []byte) ([]byte, error) { - panic("not implemented") +func (r *GetRequestBody) StableMarshal(buf []byte) ([]byte, error) { + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var ( + offset, n int + err error + ) + + n, err = proto.NestedStructureMarshal(getReqBodyAddressField, buf[offset:], r.addr) + if err != nil { + return nil, err + } + + offset += n + + _, err = proto.BoolMarshal(getReqBodyRawFlagField, buf[offset:], r.raw) + if err != nil { + return nil, err + } + + return buf, nil } -func (r *PutRequestBody) StableSize() (size int) { - panic("not implemented") +func (r *GetRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(getReqBodyAddressField, r.addr) + size += proto.BoolSize(getReqBodyRawFlagField, r.raw) + + return size +} + +func (r *GetObjectPartInit) StableMarshal(buf []byte) ([]byte, error) { + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var ( + offset, n int + err error + ) + + n, err = proto.NestedStructureMarshal(getRespInitObjectIDField, buf[offset:], r.id) + if err != nil { + return nil, err + } + + offset += n + + n, err = proto.NestedStructureMarshal(getRespInitSignatureField, buf[offset:], r.sig) + if err != nil { + return nil, err + } + + offset += n + + _, err = proto.NestedStructureMarshal(getRespInitHeaderField, buf[offset:], r.hdr) + if err != nil { + return nil, err + } + + return buf, nil +} + +func (r *GetObjectPartInit) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(getRespInitObjectIDField, r.id) + size += proto.NestedStructureSize(getRespInitSignatureField, r.sig) + size += proto.NestedStructureSize(getRespInitHeaderField, r.hdr) + + return size } func (r *GetResponseBody) StableMarshal(buf []byte) ([]byte, error) { - panic("not implemented") + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + if r.objPart != nil { + switch v := r.objPart.(type) { + case *GetObjectPartInit: + _, err := proto.NestedStructureMarshal(getRespBodyInitField, buf, v) + if err != nil { + return nil, err + } + case *GetObjectPartChunk: + if v != nil { + _, err := proto.BytesMarshal(getRespBodyChunkField, buf, v.chunk) + if err != nil { + return nil, err + } + } + default: + panic("unknown one of object get response body type") + } + } + + return buf, nil } func (r *GetResponseBody) StableSize() (size int) { - panic("not implemented") + if r == nil { + return 0 + } + + if r.objPart != nil { + switch v := r.objPart.(type) { + case *GetObjectPartInit: + size += proto.NestedStructureSize(getRespBodyInitField, v) + case *GetObjectPartChunk: + if v != nil { + size += proto.BytesSize(getRespBodyChunkField, v.chunk) + } + default: + panic("unknown one of object get response body type") + } + } + + return size +} + +func (r *PutObjectPartInit) StableMarshal(buf []byte) ([]byte, error) { + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var ( + offset, n int + err error + ) + + n, err = proto.NestedStructureMarshal(putReqInitObjectIDField, buf[offset:], r.id) + if err != nil { + return nil, err + } + + offset += n + + n, err = proto.NestedStructureMarshal(putReqInitSignatureField, buf[offset:], r.sig) + if err != nil { + return nil, err + } + + offset += n + + n, err = proto.NestedStructureMarshal(putReqInitHeaderField, buf[offset:], r.hdr) + if err != nil { + return nil, err + } + + offset += n + + n, err = proto.UInt32Marshal(putReqInitCopiesNumField, buf[offset:], r.copyNum) + if err != nil { + return nil, err + } + + return buf, nil +} + +func (r *PutObjectPartInit) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(putReqInitObjectIDField, r.id) + size += proto.NestedStructureSize(putReqInitSignatureField, r.sig) + size += proto.NestedStructureSize(putReqInitHeaderField, r.hdr) + size += proto.UInt32Size(putReqInitCopiesNumField, r.copyNum) + + return size +} + +func (r *PutRequestBody) StableMarshal(buf []byte) ([]byte, error) { + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + if r.objPart != nil { + switch v := r.objPart.(type) { + case *PutObjectPartInit: + _, err := proto.NestedStructureMarshal(putReqBodyInitField, buf, v) + if err != nil { + return nil, err + } + case *PutObjectPartChunk: + if v != nil { + _, err := proto.BytesMarshal(putReqBodyChunkField, buf, v.chunk) + if err != nil { + return nil, err + } + } + default: + panic("unknown one of object put request body type") + } + } + + return buf, nil +} + +func (r *PutRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + if r.objPart != nil { + switch v := r.objPart.(type) { + case *PutObjectPartInit: + size += proto.NestedStructureSize(putReqBodyInitField, v) + case *PutObjectPartChunk: + if v != nil { + size += proto.BytesSize(putReqBodyChunkField, v.chunk) + } + default: + panic("unknown one of object get response body type") + } + } + + return size } func (r *PutResponseBody) StableMarshal(buf []byte) ([]byte, error) { - panic("not implemented") + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + _, err := proto.NestedStructureMarshal(putRespBodyObjectIDField, buf, r.id) + if err != nil { + return nil, err + } + + return buf, nil } func (r *PutResponseBody) StableSize() (size int) { - panic("not implemented") + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(putRespBodyObjectIDField, r.id) + + return size +} + +func (r *DeleteRequestBody) StableMarshal(buf []byte) ([]byte, error) { + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + _, err := proto.NestedStructureMarshal(deleteReqBodyAddressField, buf, r.addr) + if err != nil { + return nil, err + } + + return buf, nil +} + +func (r *DeleteRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(deleteReqBodyAddressField, r.addr) + + return size } func (r *DeleteResponseBody) StableMarshal(buf []byte) ([]byte, error) { - panic("not implemented") + return nil, nil } func (r *DeleteResponseBody) StableSize() (size int) { - panic("not implemented") + return 0 +} + +func (r *HeadRequestBody) StableMarshal(buf []byte) ([]byte, error) { + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var ( + offset, n int + err error + ) + + n, err = proto.NestedStructureMarshal(headReqBodyAddressField, buf[offset:], r.addr) + if err != nil { + return nil, err + } + + offset += n + + n, err = proto.BoolMarshal(headReqBodyMainFlagField, buf[offset:], r.mainOnly) + if err != nil { + return nil, err + } + + offset += n + + _, err = proto.BoolMarshal(headReqBodyRawFlagField, buf[offset:], r.raw) + if err != nil { + return nil, err + } + + return buf, nil +} + +func (r *HeadRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(headReqBodyAddressField, r.addr) + size += proto.BoolSize(headReqBodyMainFlagField, r.mainOnly) + size += proto.BoolSize(headReqBodyRawFlagField, r.raw) + + return size } func (r *HeadResponseBody) StableMarshal(buf []byte) ([]byte, error) { - panic("not implemented") + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + if r.hdrPart != nil { + switch v := r.hdrPart.(type) { + case *GetHeaderPartFull: + if v != nil { + _, err := proto.NestedStructureMarshal(headRespBodyHeaderField, buf, v.hdr) + if err != nil { + return nil, err + } + } + case *GetHeaderPartShort: + if v != nil { + _, err := proto.NestedStructureMarshal(headRespBodyShortHeaderField, buf, v.hdr) + if err != nil { + return nil, err + } + } + default: + panic("unknown one of object put request body type") + } + } + + return buf, nil } func (r *HeadResponseBody) StableSize() (size int) { - panic("not implemented") + if r == nil { + return 0 + } + + if r.hdrPart != nil { + switch v := r.hdrPart.(type) { + case *GetHeaderPartFull: + if v != nil { + size += proto.NestedStructureSize(headRespBodyHeaderField, v.hdr) + } + case *GetHeaderPartShort: + if v != nil { + size += proto.NestedStructureSize(headRespBodyShortHeaderField, v.hdr) + } + default: + panic("unknown one of object put request body type") + } + } + + return size +} + +func (f *SearchFilter) StableMarshal(buf []byte) ([]byte, error) { + if f == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, f.StableSize()) + } + + var ( + offset, n int + err error + ) + + n, err = proto.EnumMarshal(searchFilterMatchField, buf[offset:], int32(f.matchType)) + if err != nil { + return nil, err + } + + offset += n + + n, err = proto.StringMarshal(searchFilterNameField, buf[offset:], f.name) + if err != nil { + return nil, err + } + + offset += n + + _, err = proto.StringMarshal(searchFilterValueField, buf[offset:], f.val) + if err != nil { + return nil, err + } + + return buf, nil +} + +func (f *SearchFilter) StableSize() (size int) { + if f == nil { + return 0 + } + + size += proto.EnumSize(searchFilterMatchField, int32(f.matchType)) + size += proto.StringSize(searchFilterNameField, f.name) + size += proto.StringSize(searchFilterValueField, f.val) + + return size +} + +func (r *SearchRequestBody) StableMarshal(buf []byte) ([]byte, error) { + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var ( + offset, n int + err error + ) + + n, err = proto.NestedStructureMarshal(searchReqBodyContainerIDField, buf[offset:], r.cid) + if err != nil { + return nil, err + } + + offset += n + + n, err = proto.UInt32Marshal(searchReqBodyVersionField, buf[offset:], r.version) + if err != nil { + return nil, err + } + + offset += n + + for i := range r.filters { + n, err = proto.NestedStructureMarshal(searchReqBodyFiltersField, buf[offset:], r.filters[i]) + if err != nil { + return nil, err + } + + offset += n + } + + return buf, nil +} + +func (r *SearchRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(searchReqBodyContainerIDField, r.cid) + size += proto.UInt32Size(searchReqBodyVersionField, r.version) + + for i := range r.filters { + size += proto.NestedStructureSize(searchReqBodyFiltersField, r.filters[i]) + } + + return size } func (r *SearchResponseBody) StableMarshal(buf []byte) ([]byte, error) { - panic("not implemented") + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var ( + offset, n int + err error + ) + + for i := range r.idList { + n, err = proto.NestedStructureMarshal(searchRespBodyObjectIDsField, buf[offset:], r.idList[i]) + if err != nil { + return nil, err + } + + offset += n + } + + return buf, nil } func (r *SearchResponseBody) StableSize() (size int) { - panic("not implemented") + if r == nil { + return 0 + } + + for i := range r.idList { + size += proto.NestedStructureSize(searchRespBodyObjectIDsField, r.idList[i]) + } + + return size +} + +func (r *Range) StableMarshal(buf []byte) ([]byte, error) { + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var ( + offset, n int + err error + ) + + n, err = proto.UInt64Marshal(rangeOffsetField, buf[offset:], r.off) + if err != nil { + return nil, err + } + + offset += n + + _, err = proto.UInt64Marshal(rangeLengthField, buf[offset:], r.len) + if err != nil { + return nil, err + } + + return buf, nil +} + +func (r *Range) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.UInt64Size(rangeOffsetField, r.off) + size += proto.UInt64Size(rangeLengthField, r.len) + + return size +} + +func (r *GetRangeRequestBody) StableMarshal(buf []byte) ([]byte, error) { + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var ( + offset, n int + err error + ) + + n, err = proto.NestedStructureMarshal(getRangeReqBodyAddressField, buf[offset:], r.addr) + if err != nil { + return nil, err + } + + offset += n + + _, err = proto.NestedStructureMarshal(getRangeReqBodyRangeField, buf[offset:], r.rng) + if err != nil { + return nil, err + } + + return buf, nil +} + +func (r *GetRangeRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(getRangeReqBodyAddressField, r.addr) + size += proto.NestedStructureSize(getRangeReqBodyRangeField, r.rng) + + return size } func (r *GetRangeResponseBody) StableMarshal(buf []byte) ([]byte, error) { - panic("not implemented") + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + _, err := proto.BytesMarshal(getRangeRespChunkField, buf, r.chunk) + if err != nil { + return nil, err + } + + return buf, nil } func (r *GetRangeResponseBody) StableSize() (size int) { - panic("not implemented") + if r == nil { + return 0 + } + + size += proto.BytesSize(getRangeRespChunkField, r.chunk) + + return size +} + +func (r *GetRangeHashRequestBody) StableMarshal(buf []byte) ([]byte, error) { + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + var ( + offset, n int + err error + ) + + n, err = proto.NestedStructureMarshal(getRangeHashReqBodyAddressField, buf[offset:], r.addr) + if err != nil { + return nil, err + } + + offset += n + + for i := range r.rngs { + n, err = proto.NestedStructureMarshal(getRangeHashReqBodyRangesField, buf[offset:], r.rngs[i]) + if err != nil { + return nil, err + } + + offset += n + } + + _, err = proto.BytesMarshal(getRangeHashReqBodySaltField, buf[offset:], r.salt) + if err != nil { + return nil, err + } + + return buf, nil +} + +func (r *GetRangeHashRequestBody) StableSize() (size int) { + if r == nil { + return 0 + } + + size += proto.NestedStructureSize(getRangeHashReqBodyAddressField, r.addr) + + for i := range r.rngs { + size += proto.NestedStructureSize(getRangeHashReqBodyRangesField, r.rngs[i]) + } + + size += proto.BytesSize(getRangeHashReqBodySaltField, r.salt) + + return size } func (r *GetRangeHashResponseBody) StableMarshal(buf []byte) ([]byte, error) { - panic("not implemented") + if r == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, r.StableSize()) + } + + _, err := proto.RepeatedBytesMarshal(getRangeHashRespBodyHashList, buf, r.hashList) + if err != nil { + return nil, err + } + + return buf, nil } func (r *GetRangeHashResponseBody) StableSize() (size int) { - panic("not implemented") + if r == nil { + return 0 + } + + size += proto.RepeatedBytesSize(getRangeHashRespBodyHashList, r.hashList) + + return size } diff --git a/v2/object/marshal_test.go b/v2/object/marshal_test.go index a2a37ac..87dc0c7 100644 --- a/v2/object/marshal_test.go +++ b/v2/object/marshal_test.go @@ -1,6 +1,7 @@ package object_test import ( + "fmt" "testing" "github.com/nspcc-dev/neofs-api-go/v2/object" @@ -99,6 +100,266 @@ func TestObject_StableMarshal(t *testing.T) { }) } +func TestGetRequestBody_StableMarshal(t *testing.T) { + from := generateGetRequestBody("Container ID", "Object ID") + transport := new(grpc.GetRequest_Body) + + t.Run("non empty", func(t *testing.T) { + wire, err := from.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.GetRequestBodyFromGRPCMessage(transport) + require.Equal(t, from, to) + }) +} + +func TestGetResponseBody_StableMarshal(t *testing.T) { + initFrom := generateGetResponseBody(true) + chunkFrom := generateGetResponseBody(false) + transport := new(grpc.GetResponse_Body) + + t.Run("init non empty", func(t *testing.T) { + wire, err := initFrom.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.GetResponseBodyFromGRPCMessage(transport) + require.Equal(t, initFrom, to) + }) + + t.Run("chunk non empty", func(t *testing.T) { + wire, err := chunkFrom.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.GetResponseBodyFromGRPCMessage(transport) + require.Equal(t, chunkFrom, to) + }) +} + +func TestPutRequestBody_StableMarshal(t *testing.T) { + initFrom := generatePutRequestBody(true) + chunkFrom := generatePutRequestBody(false) + transport := new(grpc.PutRequest_Body) + + t.Run("init non empty", func(t *testing.T) { + wire, err := initFrom.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.PutRequestBodyFromGRPCMessage(transport) + require.Equal(t, initFrom, to) + }) + + t.Run("chunk non empty", func(t *testing.T) { + wire, err := chunkFrom.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.PutRequestBodyFromGRPCMessage(transport) + require.Equal(t, chunkFrom, to) + }) +} + +func TestPutRequestBody_StableSize(t *testing.T) { + from := generatePutResponseBody("Object ID") + transport := new(grpc.PutResponse_Body) + + t.Run("non empty", func(t *testing.T) { + wire, err := from.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.PutResponseBodyFromGRPCMessage(transport) + require.Equal(t, from, to) + }) +} + +func TestDeleteRequestBody_StableMarshal(t *testing.T) { + from := generateDeleteRequestBody("Container ID", "Object ID") + transport := new(grpc.DeleteRequest_Body) + + t.Run("non empty", func(t *testing.T) { + wire, err := from.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.DeleteRequestBodyFromGRPCMessage(transport) + require.Equal(t, from, to) + }) +} + +func TestDeleteResponseBody_StableMarshal(t *testing.T) { + from := generateDeleteResponseBody() + transport := new(grpc.DeleteResponse_Body) + + t.Run("non empty", func(t *testing.T) { + wire, err := from.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.DeleteResponseBodyFromGRPCMessage(transport) + require.Equal(t, from, to) + }) +} + +func TestSplitHeaderFromGRPCMessage(t *testing.T) { + from := generateHeadRequestBody("Container ID", "Object ID") + transport := new(grpc.HeadRequest_Body) + + t.Run("non empty", func(t *testing.T) { + wire, err := from.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.HeadRequestBodyFromGRPCMessage(transport) + require.Equal(t, from, to) + }) +} + +func TestHeadResponseBody_StableMarshal(t *testing.T) { + shortFrom := generateHeadResponseBody(true) + fullFrom := generateHeadResponseBody(false) + transport := new(grpc.HeadResponse_Body) + + t.Run("short header non empty", func(t *testing.T) { + wire, err := shortFrom.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.HeadResponseBodyFromGRPCMessage(transport) + require.Equal(t, shortFrom, to) + }) + + t.Run("full header non empty", func(t *testing.T) { + wire, err := fullFrom.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.HeadResponseBodyFromGRPCMessage(transport) + require.Equal(t, fullFrom, to) + }) +} + +func TestSearchRequestBody_StableMarshal(t *testing.T) { + from := generateSearchRequestBody(10, "Container ID") + transport := new(grpc.SearchRequest_Body) + + t.Run("non empty", func(t *testing.T) { + wire, err := from.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.SearchRequestBodyFromGRPCMessage(transport) + require.Equal(t, from, to) + }) +} + +func TestSearchResponseBody_StableMarshal(t *testing.T) { + from := generateSearchResponseBody(10) + transport := new(grpc.SearchResponse_Body) + + t.Run("non empty", func(t *testing.T) { + wire, err := from.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.SearchResponseBodyFromGRPCMessage(transport) + require.Equal(t, from, to) + }) +} + +func TestGetRangeRequestBody_StableMarshal(t *testing.T) { + from := generateRangeRequestBody("Container ID", "Object ID") + transport := new(grpc.GetRangeRequest_Body) + + t.Run("non empty", func(t *testing.T) { + wire, err := from.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.GetRangeRequestBodyFromGRPCMessage(transport) + require.Equal(t, from, to) + }) +} + +func TestGetRangeResponseBody_StableMarshal(t *testing.T) { + from := generateRangeResponseBody("some data") + transport := new(grpc.GetRangeResponse_Body) + + t.Run("non empty", func(t *testing.T) { + wire, err := from.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.GetRangeResponseBodyFromGRPCMessage(transport) + require.Equal(t, from, to) + }) +} + +func TestGetRangeHashRequestBody_StableMarshal(t *testing.T) { + from := generateRangeHashRequestBody("Container ID", "Object ID", 5) + transport := new(grpc.GetRangeHashRequest_Body) + + t.Run("non empty", func(t *testing.T) { + wire, err := from.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.GetRangeHashRequestBodyFromGRPCMessage(transport) + require.Equal(t, from, to) + }) +} + +func TestGetRangeHashResponseBody_StableMarshal(t *testing.T) { + from := generateRangeHashResponseBody(5) + transport := new(grpc.GetRangeHashResponse_Body) + + t.Run("non empty", func(t *testing.T) { + wire, err := from.StableMarshal(nil) + require.NoError(t, err) + + err = transport.Unmarshal(wire) + require.NoError(t, err) + + to := object.GetRangeHashResponseBodyFromGRPCMessage(transport) + require.Equal(t, from, to) + }) +} + func generateOwner(id string) *refs.OwnerID { owner := new(refs.OwnerID) owner.SetValue([]byte(id)) @@ -136,19 +397,23 @@ func generateVersion(maj, min uint32) *service.Version { return version } +func generateAddress(cid, oid string) *refs.Address { + addr := new(refs.Address) + addr.SetObjectID(generateObjectID(oid)) + addr.SetContainerID(generateContainerID(cid)) + + return addr +} + func generateSessionToken(id string) *service.SessionToken { lifetime := new(service.TokenLifetime) lifetime.SetExp(1) lifetime.SetNbf(2) lifetime.SetIat(3) - addr := new(refs.Address) - addr.SetContainerID(generateContainerID("Container ID")) - addr.SetObjectID(generateObjectID("Object ID")) - objectCtx := new(service.ObjectSessionContext) objectCtx.SetVerb(service.ObjectVerbPut) - objectCtx.SetAddress(addr) + objectCtx.SetAddress(generateAddress("Container ID", "Object ID")) tokenBody := new(service.SessionTokenBody) tokenBody.SetID([]byte(id)) @@ -231,3 +496,185 @@ func generateObject(data string) *object.Object { return obj } + +func generateGetRequestBody(cid, oid string) *object.GetRequestBody { + req := new(object.GetRequestBody) + req.SetAddress(generateAddress(cid, oid)) + req.SetRaw(true) + + return req +} + +func generateGetResponseBody(flag bool) *object.GetResponseBody { + resp := new(object.GetResponseBody) + var part object.GetObjectPart + + if flag { + init := new(object.GetObjectPartInit) + init.SetObjectID(generateObjectID("Object ID")) + init.SetSignature(generateSignature("Key", "Signature")) + init.SetHeader(generateHeader(10)) + part = init + } else { + chunk := new(object.GetObjectPartChunk) + chunk.SetChunk([]byte("Some data chunk")) + part = chunk + } + resp.SetObjectPart(part) + + return resp +} + +func generatePutRequestBody(flag bool) *object.PutRequestBody { + req := new(object.PutRequestBody) + var part object.PutObjectPart + + if flag { + init := new(object.PutObjectPartInit) + init.SetObjectID(generateObjectID("Object ID")) + init.SetSignature(generateSignature("Key", "Signature")) + init.SetHeader(generateHeader(10)) + init.SetCopiesNumber(1) + part = init + } else { + chunk := new(object.PutObjectPartChunk) + chunk.SetChunk([]byte("Some data chunk")) + part = chunk + } + req.SetObjectPart(part) + + return req +} + +func generatePutResponseBody(oid string) *object.PutResponseBody { + resp := new(object.PutResponseBody) + resp.SetObjectID(generateObjectID(oid)) + + return resp +} + +func generateDeleteRequestBody(cid, oid string) *object.DeleteRequestBody { + req := new(object.DeleteRequestBody) + req.SetAddress(generateAddress(cid, oid)) + + return req +} + +func generateDeleteResponseBody() *object.DeleteResponseBody { + return new(object.DeleteResponseBody) +} + +func generateHeadRequestBody(cid, oid string) *object.HeadRequestBody { + req := new(object.HeadRequestBody) + req.SetAddress(generateAddress(cid, oid)) + req.SetRaw(true) + req.SetMainOnly(true) + + return req +} + +func generateHeadResponseBody(flag bool) *object.HeadResponseBody { + req := new(object.HeadResponseBody) + var part object.GetHeaderPart + + if flag { + short := new(object.GetHeaderPartShort) + short.SetShortHeader(generateShortHeader("short id")) + part = short + } else { + full := new(object.GetHeaderPartFull) + full.SetHeader(generateHeader(30)) + part = full + } + + req.SetHeaderPart(part) + + return req +} + +func generateFilter(k, v string) *object.SearchFilter { + f := new(object.SearchFilter) + f.SetName(k) + f.SetValue(v) + f.SetMatchType(object.MatchStringEqual) + + return f +} + +func generateSearchRequestBody(n int, id string) *object.SearchRequestBody { + req := new(object.SearchRequestBody) + req.SetContainerID(generateContainerID(id)) + req.SetVersion(1) + + ff := make([]*object.SearchFilter, n) + + for i := 0; i < n; i++ { + ff[i] = generateFilter("Some Key", fmt.Sprintf("Value %d", i+1)) + } + req.SetFilters(ff) + + return req +} + +func generateSearchResponseBody(n int) *object.SearchResponseBody { + resp := new(object.SearchResponseBody) + list := make([]*refs.ObjectID, n) + for i := 0; i < n; i++ { + list[i] = generateObjectID(fmt.Sprintf("Object ID %d", i+1)) + } + + resp.SetIDList(list) + + return resp +} + +func generateRange(off, ln uint64) *object.Range { + r := new(object.Range) + r.SetOffset(off) + r.SetLength(ln) + + return r +} + +func generateRangeRequestBody(cid, oid string) *object.GetRangeRequestBody { + req := new(object.GetRangeRequestBody) + req.SetAddress(generateAddress(cid, oid)) + req.SetRange(generateRange(10, 20)) + + return req +} + +func generateRangeResponseBody(data string) *object.GetRangeResponseBody { + resp := new(object.GetRangeResponseBody) + resp.SetChunk([]byte(data)) + + return resp +} + +func generateRangeHashRequestBody(cid, oid string, n int) *object.GetRangeHashRequestBody { + req := new(object.GetRangeHashRequestBody) + req.SetAddress(generateAddress(cid, oid)) + + rngs := make([]*object.Range, n) + for i := 0; i < n; i++ { + rngs[i] = generateRange(100, 200+uint64(n)) + } + + req.SetRanges(rngs) + req.SetSalt([]byte("xor salt")) + + return req +} + +func generateRangeHashResponseBody(n int) *object.GetRangeHashResponseBody { + resp := new(object.GetRangeHashResponseBody) + + list := make([][]byte, n) + for i := 0; i < n; i++ { + list[i] = []byte("Some homomorphic hash data" + string(n)) + } + + resp.SetHashList(list) + + return resp +}