forked from TrueCloudLab/frostfs-s3-gw
[#452] Fix versions tests
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
parent
5529fb914e
commit
9fb3fb1274
5 changed files with 92 additions and 120 deletions
|
@ -17,7 +17,6 @@ import (
|
|||
"github.com/nspcc-dev/neofs-s3-gw/api/data"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/api/resolver"
|
||||
treetest "github.com/nspcc-dev/neofs-s3-gw/internal/neofstest/tree"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/user"
|
||||
|
@ -59,7 +58,7 @@ func prepareHandlerContext(t *testing.T) *handlerContext {
|
|||
Caches: layer.DefaultCachesConfigs(zap.NewExample()),
|
||||
AnonKey: layer.AnonymousKey{Key: key},
|
||||
Resolver: testResolver,
|
||||
TreeService: treetest.NewTreeService(),
|
||||
TreeService: layer.NewTreeService(),
|
||||
}
|
||||
|
||||
h := &handler{
|
||||
|
|
|
@ -499,6 +499,8 @@ func (n *layer) deleteObject(ctx context.Context, bkt *data.BucketInfo, settings
|
|||
if obj.Error = n.treeService.AddVersion(ctx, &bkt.CID, obj.Name, newVersion); obj.Error != nil {
|
||||
return obj
|
||||
}
|
||||
|
||||
n.namesCache.Delete(bkt.Name + "/" + obj.Name)
|
||||
} else {
|
||||
versions, err := n.treeService.GetVersions(ctx, &bkt.CID, obj.Name)
|
||||
if err != nil {
|
||||
|
@ -530,16 +532,7 @@ func (n *layer) removeVersionIfFound(ctx context.Context, bkt *data.BucketInfo,
|
|||
if err := n.objectDelete(ctx, bkt, version.OID); err != nil {
|
||||
return deleteMarkVersion, err
|
||||
}
|
||||
if err := n.treeService.RemoveVersion(ctx, &bkt.CID, version.ID); err != nil {
|
||||
return deleteMarkVersion, err
|
||||
}
|
||||
|
||||
p := &ObjectVersion{
|
||||
BktInfo: bkt,
|
||||
ObjectName: obj.Name,
|
||||
VersionID: version.OID.EncodeToString(),
|
||||
}
|
||||
return deleteMarkVersion, n.DeleteObjectTagging(ctx, p)
|
||||
return deleteMarkVersion, n.treeService.RemoveVersion(ctx, &bkt.CID, version.ID)
|
||||
}
|
||||
|
||||
return "", errors.GetAPIError(errors.ErrNoSuchVersion)
|
||||
|
|
|
@ -342,35 +342,32 @@ func (n *layer) headVersions(ctx context.Context, bkt *data.BucketInfo, objectNa
|
|||
}
|
||||
|
||||
func (n *layer) headVersion(ctx context.Context, bkt *data.BucketInfo, p *HeadObjectParams) (*data.ObjectInfo, error) {
|
||||
var err error
|
||||
var foundVersion *data.NodeVersion
|
||||
if p.VersionID == unversionedObjectVersionID {
|
||||
versions, err := n.headVersions(ctx, bkt, p.Object)
|
||||
foundVersion, err = n.treeService.GetUnversioned(ctx, &bkt.CID, p.Object)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
objInfo := versions.getLast(FromUnversioned())
|
||||
if objInfo == nil {
|
||||
if errors.Is(err, ErrNodeNotFound) {
|
||||
return nil, apiErrors.GetAPIError(apiErrors.ErrNoSuchVersion)
|
||||
}
|
||||
return objInfo, nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
} else {
|
||||
versions, err := n.treeService.GetVersions(ctx, &bkt.CID, p.Object)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't get versions: %w", err)
|
||||
}
|
||||
|
||||
var foundVersion *data.NodeVersion
|
||||
for _, version := range versions {
|
||||
if version.OID.EncodeToString() == p.VersionID {
|
||||
foundVersion = version
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if foundVersion == nil {
|
||||
return nil, apiErrors.GetAPIError(apiErrors.ErrNoSuchVersion)
|
||||
}
|
||||
}
|
||||
|
||||
if headInfo := n.objCache.Get(newAddress(bkt.CID, foundVersion.OID)); headInfo != nil {
|
||||
return objInfoFromMeta(bkt, headInfo), nil
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package tree
|
||||
package layer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
|
@ -48,8 +47,6 @@ func (t *TreeServiceMock) DeleteBucketTagging(ctx context.Context, cnrID *cid.ID
|
|||
panic("implement me")
|
||||
}
|
||||
|
||||
var ErrNodeNotFound = errors.New("not found")
|
||||
|
||||
func NewTreeService() *TreeServiceMock {
|
||||
return &TreeServiceMock{
|
||||
settings: make(map[string]*data.BucketSettings),
|
||||
|
@ -107,7 +104,7 @@ func (t *TreeServiceMock) GetVersions(_ context.Context, cnrID *cid.ID, objectNa
|
|||
return versions, nil
|
||||
}
|
||||
|
||||
func (t *TreeServiceMock) GetLatestVersion(ctx context.Context, cnrID *cid.ID, objectName string) (*data.NodeVersion, error) {
|
||||
func (t *TreeServiceMock) GetLatestVersion(_ context.Context, cnrID *cid.ID, objectName string) (*data.NodeVersion, error) {
|
||||
cnrVersionsMap, ok := t.versions[cnrID.EncodeToString()]
|
||||
if !ok {
|
||||
return nil, ErrNodeNotFound
|
||||
|
@ -154,8 +151,24 @@ func (t *TreeServiceMock) GetLatestVersionsByPrefix(_ context.Context, cnrID *ci
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (t *TreeServiceMock) GetUnversioned(ctx context.Context, cnrID *cid.ID, objectName string) (*data.NodeVersion, error) {
|
||||
panic("implement me")
|
||||
func (t *TreeServiceMock) GetUnversioned(_ context.Context, cnrID *cid.ID, objectName string) (*data.NodeVersion, error) {
|
||||
cnrVersionsMap, ok := t.versions[cnrID.EncodeToString()]
|
||||
if !ok {
|
||||
return nil, ErrNodeNotFound
|
||||
}
|
||||
|
||||
versions, ok := cnrVersionsMap[objectName]
|
||||
if !ok {
|
||||
return nil, ErrNodeNotFound
|
||||
}
|
||||
|
||||
for _, version := range versions {
|
||||
if version.IsUnversioned {
|
||||
return version, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, ErrNodeNotFound
|
||||
}
|
||||
|
||||
func (t *TreeServiceMock) AddVersion(_ context.Context, cnrID *cid.ID, objectName string, newVersion *data.NodeVersion) error {
|
||||
|
@ -179,6 +192,7 @@ func (t *TreeServiceMock) AddVersion(_ context.Context, cnrID *cid.ID, objectNam
|
|||
|
||||
if len(versions) != 0 {
|
||||
newVersion.ID = versions[len(versions)-1].ID + 1
|
||||
newVersion.Timestamp = versions[len(versions)-1].Timestamp + 1
|
||||
}
|
||||
|
||||
result := versions
|
||||
|
@ -197,12 +211,38 @@ func (t *TreeServiceMock) AddVersion(_ context.Context, cnrID *cid.ID, objectNam
|
|||
return nil
|
||||
}
|
||||
|
||||
func (t *TreeServiceMock) RemoveVersion(ctx context.Context, cnrID *cid.ID, nodeID uint64) error {
|
||||
panic("implement me")
|
||||
func (t *TreeServiceMock) RemoveVersion(_ context.Context, cnrID *cid.ID, nodeID uint64) error {
|
||||
cnrVersionsMap, ok := t.versions[cnrID.EncodeToString()]
|
||||
if !ok {
|
||||
return ErrNodeNotFound
|
||||
}
|
||||
|
||||
func (t *TreeServiceMock) GetAllVersionsByPrefix(ctx context.Context, cnrID *cid.ID, prefix string) ([]*data.NodeVersion, error) {
|
||||
panic("implement me")
|
||||
for key, versions := range cnrVersionsMap {
|
||||
for i, node := range versions {
|
||||
if node.ID == nodeID {
|
||||
cnrVersionsMap[key] = append(versions[:i], versions[i+1:]...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ErrNodeNotFound
|
||||
}
|
||||
|
||||
func (t *TreeServiceMock) GetAllVersionsByPrefix(_ context.Context, cnrID *cid.ID, prefix string) ([]*data.NodeVersion, error) {
|
||||
cnrVersionsMap, ok := t.versions[cnrID.EncodeToString()]
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var result []*data.NodeVersion
|
||||
for objName, versions := range cnrVersionsMap {
|
||||
if strings.HasPrefix(objName, prefix) {
|
||||
result = append(result, versions...)
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (t *TreeServiceMock) CreateMultipartUpload(ctx context.Context, cnrID *cid.ID, info *data.MultipartInfo) error {
|
|
@ -11,7 +11,6 @@ import (
|
|||
"github.com/nspcc-dev/neofs-s3-gw/api"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/api/data"
|
||||
"github.com/nspcc-dev/neofs-s3-gw/creds/accessbox"
|
||||
treetest "github.com/nspcc-dev/neofs-s3-gw/internal/neofstest/tree"
|
||||
bearertest "github.com/nspcc-dev/neofs-sdk-go/bearer/test"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||
|
@ -177,7 +176,7 @@ func prepareContext(t *testing.T, cachesConfig ...*CachesConfig) *testContext {
|
|||
layerCfg := &Config{
|
||||
Caches: config,
|
||||
AnonKey: AnonymousKey{Key: key},
|
||||
TreeService: treetest.NewTreeService(),
|
||||
TreeService: NewTreeService(),
|
||||
}
|
||||
|
||||
return &testContext{
|
||||
|
@ -251,6 +250,24 @@ func TestVersioningDeleteObject(t *testing.T) {
|
|||
tc.checkListObjects()
|
||||
}
|
||||
|
||||
func TestGetUnversioned(t *testing.T) {
|
||||
tc := prepareContext(t)
|
||||
|
||||
objContent := []byte("content obj1 v1")
|
||||
objInfo := tc.putObject(objContent)
|
||||
|
||||
settings := &data.BucketSettings{VersioningEnabled: false}
|
||||
err := tc.layer.PutBucketSettings(tc.ctx, &PutSettingsParams{
|
||||
BktInfo: tc.bktInfo,
|
||||
Settings: settings,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
resInfo, buffer := tc.getObject(tc.obj, unversionedObjectVersionID, false)
|
||||
require.Equal(t, objContent, buffer)
|
||||
require.Equal(t, objInfo.Version(), resInfo.Version())
|
||||
}
|
||||
|
||||
func TestVersioningDeleteSpecificObjectVersion(t *testing.T) {
|
||||
tc := prepareContext(t)
|
||||
settings := &data.BucketSettings{VersioningEnabled: true}
|
||||
|
@ -521,77 +538,3 @@ func getTestObjectInfoEpoch(epoch uint64, id byte, addAttr, delAttr, delMarkAttr
|
|||
obj.CreationEpoch = epoch
|
||||
return obj
|
||||
}
|
||||
|
||||
func TestSystemObjectsVersioning(t *testing.T) {
|
||||
cacheConfig := DefaultCachesConfigs(zap.NewExample())
|
||||
cacheConfig.System.Lifetime = 0
|
||||
|
||||
tc := prepareContext(t, cacheConfig)
|
||||
err := tc.layer.PutBucketSettings(tc.ctx, &PutSettingsParams{
|
||||
BktInfo: tc.bktInfo,
|
||||
Settings: &data.BucketSettings{VersioningEnabled: false},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
objMeta := tc.getSystemObject(tc.bktInfo.SettingsObjectName())
|
||||
require.NotNil(t, objMeta)
|
||||
|
||||
err = tc.layer.PutBucketSettings(tc.ctx, &PutSettingsParams{
|
||||
BktInfo: tc.bktInfo,
|
||||
Settings: &data.BucketSettings{VersioningEnabled: true},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
cnrID, _ := objMeta.ContainerID()
|
||||
objID, _ := objMeta.ID()
|
||||
|
||||
var addr oid.Address
|
||||
addr.SetContainer(cnrID)
|
||||
addr.SetObject(objID)
|
||||
|
||||
// simulate failed deletion
|
||||
tc.testNeoFS.AddObject(addr.EncodeToString(), objMeta)
|
||||
|
||||
versioning, err := tc.layer.GetBucketSettings(tc.ctx, tc.bktInfo)
|
||||
require.NoError(t, err)
|
||||
require.True(t, versioning.VersioningEnabled)
|
||||
}
|
||||
|
||||
func TestDeleteSystemObjectsVersioning(t *testing.T) {
|
||||
cacheConfig := DefaultCachesConfigs(zap.NewExample())
|
||||
cacheConfig.System.Lifetime = 0
|
||||
|
||||
tc := prepareContext(t, cacheConfig)
|
||||
|
||||
tagSet := map[string]string{
|
||||
"tag1": "val1",
|
||||
}
|
||||
|
||||
err := tc.layer.PutBucketTagging(tc.ctx, &tc.bktInfo.CID, tagSet)
|
||||
require.NoError(t, err)
|
||||
|
||||
objMeta := tc.getSystemObject(formBucketTagObjectName(tc.bktInfo.CID.EncodeToString()))
|
||||
|
||||
tagSet["tag2"] = "val2"
|
||||
err = tc.layer.PutBucketTagging(tc.ctx, &tc.bktInfo.CID, tagSet)
|
||||
require.NoError(t, err)
|
||||
|
||||
// simulate failed deletion
|
||||
cnrID, _ := objMeta.ContainerID()
|
||||
objID, _ := objMeta.ID()
|
||||
tc.testNeoFS.AddObject(newAddress(cnrID, objID).EncodeToString(), objMeta)
|
||||
|
||||
tagging, err := tc.layer.GetBucketTagging(tc.ctx, &tc.bktInfo.CID)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedTagSet := map[string]string{
|
||||
"tag1": "val1",
|
||||
"tag2": "val2",
|
||||
}
|
||||
require.Equal(t, expectedTagSet, tagging)
|
||||
|
||||
err = tc.layer.DeleteBucketTagging(tc.ctx, &tc.bktInfo.CID)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Nil(t, tc.getSystemObject(formBucketTagObjectName(tc.bktInfo.Name)))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue