From a2a2035b770d69d406661bcddabf2abd5b63ba27 Mon Sep 17 00:00:00 2001 From: Evgenii Baidakov Date: Thu, 22 Feb 2024 13:58:44 +0400 Subject: [PATCH] layer: Actualize multipart tests Signed-off-by: Evgenii Baidakov --- api/handler/handlers_test.go | 8 +- api/layer/neofs_mock.go | 176 +++++++++++++++++++++++++++++++---- api/layer/versioning_test.go | 2 +- 3 files changed, 165 insertions(+), 21 deletions(-) diff --git a/api/handler/handlers_test.go b/api/handler/handlers_test.go index 3cfa13d37..285e18a62 100644 --- a/api/handler/handlers_test.go +++ b/api/handler/handlers_test.go @@ -78,14 +78,14 @@ func prepareHandlerContext(t *testing.T) *handlerContext { require.NoError(t, err) anonSigner := user.NewAutoIDSignerRFC6979(anonKey.PrivateKey) + signer := user.NewAutoIDSignerRFC6979(key.PrivateKey) + owner := signer.UserID() + l := zap.NewExample() - tp := layer.NewTestNeoFS() + tp := layer.NewTestNeoFS(signer) testResolver := &contResolver{layer: tp} - signer := user.NewAutoIDSignerRFC6979(key.PrivateKey) - owner := signer.UserID() - layerCfg := &layer.Config{ Caches: layer.DefaultCachesConfigs(zap.NewExample()), GateKey: key, diff --git a/api/layer/neofs_mock.go b/api/layer/neofs_mock.go index b90ac3354..147a1d297 100644 --- a/api/layer/neofs_mock.go +++ b/api/layer/neofs_mock.go @@ -17,11 +17,13 @@ import ( "github.com/nspcc-dev/neofs-sdk-go/checksum" "github.com/nspcc-dev/neofs-sdk-go/container" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" "github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/nspcc-dev/neofs-sdk-go/object" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" "github.com/nspcc-dev/neofs-sdk-go/session" "github.com/nspcc-dev/neofs-sdk-go/user" + "github.com/nspcc-dev/tzhash/tz" ) type TestNeoFS struct { @@ -31,13 +33,15 @@ type TestNeoFS struct { containers map[string]*container.Container eaclTables map[string]*eacl.Table currentEpoch uint64 + signer neofscrypto.Signer } -func NewTestNeoFS() *TestNeoFS { +func NewTestNeoFS(signer neofscrypto.Signer) *TestNeoFS { return &TestNeoFS{ objects: make(map[string]*object.Object), containers: make(map[string]*container.Container), eaclTables: make(map[string]*eacl.Table), + signer: signer, } } @@ -138,32 +142,105 @@ func (t *TestNeoFS) UserContainers(_ context.Context, _ user.ID) ([]cid.ID, erro } func (t *TestNeoFS) ReadObject(ctx context.Context, prm PrmObjectRead) (*ObjectPart, error) { - var addr oid.Address + var ( + addr oid.Address + ) addr.SetContainer(prm.Container) addr.SetObject(prm.Object) sAddr := addr.EncodeToString() - if obj, ok := t.objects[sAddr]; ok { - owner := getOwner(ctx) - if !obj.OwnerID().Equals(owner) { - return nil, ErrAccessDenied + obj, ok := t.objects[sAddr] + if !ok { + // trying to find linking object. + for _, o := range t.objects { + parentID, isSet := o.ParentID() + if !isSet { + continue + } + + if !parentID.Equals(prm.Object) { + continue + } + + if len(o.Children()) == 0 { + continue + } + + // linking object is found. + objPart, err := t.constructMupltipartObject(ctx, prm.Container, o) + if err != nil { + return nil, err + } + + obj = objPart.Head + + pl, err := io.ReadAll(objPart.Payload) + if err != nil { + return nil, err + } + + obj.SetPayload(pl) + ok = true + break } + } + + if !ok { + return nil, fmt.Errorf("object not found %s", addr) + } + + owner := getOwner(ctx) + if !obj.OwnerID().Equals(owner) { + return nil, ErrAccessDenied + } + + payload := obj.Payload() + + if prm.PayloadRange[0]+prm.PayloadRange[1] > 0 { + off := prm.PayloadRange[0] + payload = payload[off : off+prm.PayloadRange[1]] + } + + return &ObjectPart{ + Head: obj, + Payload: io.NopCloser(bytes.NewReader(payload)), + }, nil +} + +func (t *TestNeoFS) constructMupltipartObject(ctx context.Context, containerID cid.ID, linkingObject *object.Object) (*ObjectPart, error) { + if _, isSet := linkingObject.ParentID(); !isSet { + return nil, fmt.Errorf("linking object is invalid") + } + + var ( + addr oid.Address + headObject = linkingObject.Parent() + payloadReaders = make([]io.Reader, 0, len(linkingObject.Children())) + childList = linkingObject.Children() + ) - payload := obj.Payload() + addr.SetContainer(containerID) - if prm.PayloadRange[0]+prm.PayloadRange[1] > 0 { - off := prm.PayloadRange[0] - payload = payload[off : off+prm.PayloadRange[1]] + for _, c := range childList { + addr.SetObject(c) + + objPart, err := t.ReadObject(ctx, PrmObjectRead{ + Container: containerID, + Object: c, + }) + + if err != nil { + return nil, fmt.Errorf("child read: %w", err) } - return &ObjectPart{ - Head: obj, - Payload: io.NopCloser(bytes.NewReader(payload)), - }, nil + payloadReaders = append(payloadReaders, objPart.Payload) } - return nil, fmt.Errorf("object not found %s", addr) + return &ObjectPart{ + Head: headObject, + Payload: io.NopCloser(io.MultiReader(payloadReaders...)), + }, nil } func (t *TestNeoFS) CreateObject(_ context.Context, prm PrmObjectCreate) (oid.ID, error) { @@ -195,6 +272,32 @@ func (t *TestNeoFS) CreateObject(_ context.Context, prm PrmObjectCreate) (oid.ID obj.SetOwnerID(&prm.Creator) t.currentEpoch++ + if prm.SplitID != "" { + var split object.SplitID + if err := split.Parse(prm.SplitID); err != nil { + return oid.ID{}, fmt.Errorf("split parse: %w", err) + } + obj.SetSplitID(&split) + + if prm.SplitPreviousID != nil { + obj.SetPreviousID(*prm.SplitPreviousID) + } + + if len(prm.Children) > 0 { + obj.SetChildren(prm.Children...) + } + + if prm.HeaderObject != nil { + id, isSet := prm.HeaderObject.ID() + if !isSet { + return oid.ID{}, errors.New("HeaderObject id is not set") + } + + obj.SetParentID(id) + obj.SetParent(prm.HeaderObject) + } + } + if len(prm.Locks) > 0 { var lock object.Lock lock.WriteMembers(prm.Locks) @@ -221,7 +324,48 @@ func (t *TestNeoFS) CreateObject(_ context.Context, prm PrmObjectCreate) (oid.ID return objID, nil } -func (t *TestNeoFS) PrepareMulptipartHeader(_ context.Context, header object.Object, _ hash.Hash, _ hash.Hash, _ uint64) (*object.Object, error) { +func (t *TestNeoFS) PrepareMulptipartHeader(_ context.Context, header object.Object, metaChecksum hash.Hash, homomorphicChecksum hash.Hash, payloadLength uint64) (*object.Object, error) { + header.SetCreationEpoch(t.currentEpoch) + + var cs checksum.Checksum + + var csBytes [sha256.Size]byte + copy(csBytes[:], metaChecksum.Sum(nil)) + + cs.SetSHA256(csBytes) + header.SetPayloadChecksum(cs) + + if homomorphicChecksum != nil { + var csHomoBytes [tz.Size]byte + copy(csHomoBytes[:], homomorphicChecksum.Sum(nil)) + + cs.SetTillichZemor(csHomoBytes) + header.SetPayloadHomomorphicHash(cs) + } + + header.SetPayloadSize(payloadLength) + + id, err := header.CalculateID() + if err != nil { + return nil, fmt.Errorf("calculate ID: %w", err) + } + + header.SetID(id) + + bID, err := id.Marshal() + if err != nil { + return nil, fmt.Errorf("marshal object ID: %w", err) + } + + var sig neofscrypto.Signature + + err = sig.Calculate(t.signer, bID) + if err != nil { + return nil, fmt.Errorf("sign object ID: %w", err) + } + + header.SetSignature(&sig) + return &header, nil } diff --git a/api/layer/versioning_test.go b/api/layer/versioning_test.go index fc79ccb38..147a94e2c 100644 --- a/api/layer/versioning_test.go +++ b/api/layer/versioning_test.go @@ -152,7 +152,7 @@ func prepareContext(t *testing.T, cachesConfig ...*CachesConfig) *testContext { GateKey: key.PublicKey(), }, }) - tp := NewTestNeoFS() + tp := NewTestNeoFS(signer) bktName := "testbucket1" bktID, err := tp.CreateContainer(ctx, PrmContainerCreate{