2021-08-13 14:13:14 +00:00
|
|
|
package layer
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
2023-07-06 13:37:53 +00:00
|
|
|
"io"
|
2021-08-13 14:13:14 +00:00
|
|
|
"testing"
|
|
|
|
|
2023-03-07 14:38:08 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
2023-07-05 14:05:45 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
2023-03-07 14:38:08 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
|
|
|
bearertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer/test"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
|
|
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
2021-08-13 14:13:14 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
|
|
"github.com/stretchr/testify/require"
|
2022-03-22 10:22:00 +00:00
|
|
|
"go.uber.org/zap"
|
2021-08-13 14:13:14 +00:00
|
|
|
)
|
|
|
|
|
2021-09-10 06:56:56 +00:00
|
|
|
func (tc *testContext) putObject(content []byte) *data.ObjectInfo {
|
2022-10-14 14:36:43 +00:00
|
|
|
extObjInfo, err := tc.layer.PutObject(tc.ctx, &PutObjectParams{
|
2022-03-18 13:04:09 +00:00
|
|
|
BktInfo: tc.bktInfo,
|
|
|
|
Object: tc.obj,
|
2023-06-01 13:45:28 +00:00
|
|
|
Size: uint64(len(content)),
|
2022-03-18 13:04:09 +00:00
|
|
|
Reader: bytes.NewReader(content),
|
|
|
|
Header: make(map[string]string),
|
2021-08-13 14:13:14 +00:00
|
|
|
})
|
|
|
|
require.NoError(tc.t, err)
|
|
|
|
|
2022-10-14 14:36:43 +00:00
|
|
|
return extObjInfo.ObjectInfo
|
2021-08-13 14:13:14 +00:00
|
|
|
}
|
|
|
|
|
2021-09-10 06:56:56 +00:00
|
|
|
func (tc *testContext) getObject(objectName, versionID string, needError bool) (*data.ObjectInfo, []byte) {
|
2023-07-06 13:37:53 +00:00
|
|
|
headPrm := &HeadObjectParams{
|
2022-03-18 13:04:09 +00:00
|
|
|
BktInfo: tc.bktInfo,
|
2021-08-13 14:13:14 +00:00
|
|
|
Object: objectName,
|
|
|
|
VersionID: versionID,
|
2023-07-06 13:37:53 +00:00
|
|
|
}
|
|
|
|
objInfo, err := tc.layer.GetObjectInfo(tc.ctx, headPrm)
|
2021-08-13 14:13:14 +00:00
|
|
|
if needError {
|
|
|
|
require.Error(tc.t, err)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
require.NoError(tc.t, err)
|
|
|
|
|
2023-07-06 13:37:53 +00:00
|
|
|
objPayload, err := tc.layer.GetObject(tc.ctx, &GetObjectParams{
|
2022-08-05 00:54:21 +00:00
|
|
|
ObjectInfo: objInfo,
|
2023-07-06 13:37:53 +00:00
|
|
|
Versioned: headPrm.Versioned(),
|
2022-06-02 17:01:00 +00:00
|
|
|
BucketInfo: tc.bktInfo,
|
2021-08-13 14:13:14 +00:00
|
|
|
})
|
|
|
|
require.NoError(tc.t, err)
|
|
|
|
|
2023-07-06 13:37:53 +00:00
|
|
|
payload, err := io.ReadAll(objPayload)
|
|
|
|
require.NoError(tc.t, err)
|
|
|
|
|
|
|
|
return objInfo, payload
|
2021-08-13 14:13:14 +00:00
|
|
|
}
|
|
|
|
|
2022-06-24 12:39:30 +00:00
|
|
|
func (tc *testContext) deleteObject(objectName, versionID string, settings *data.BucketSettings) {
|
2022-03-31 06:24:29 +00:00
|
|
|
p := &DeleteObjectParams{
|
2022-06-24 12:39:30 +00:00
|
|
|
BktInfo: tc.bktInfo,
|
|
|
|
Settings: settings,
|
2022-03-31 06:24:29 +00:00
|
|
|
Objects: []*VersionedObject{
|
|
|
|
{Name: objectName, VersionID: versionID},
|
|
|
|
},
|
|
|
|
}
|
2022-06-24 12:39:30 +00:00
|
|
|
deletedObjects := tc.layer.DeleteObjects(tc.ctx, p)
|
2021-09-07 06:17:12 +00:00
|
|
|
for _, obj := range deletedObjects {
|
|
|
|
require.NoError(tc.t, obj.Error)
|
2021-08-13 14:13:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-10 06:56:56 +00:00
|
|
|
func (tc *testContext) listObjectsV1() []*data.ObjectInfo {
|
2021-08-13 14:13:14 +00:00
|
|
|
res, err := tc.layer.ListObjectsV1(tc.ctx, &ListObjectsParamsV1{
|
|
|
|
ListObjectsParamsCommon: ListObjectsParamsCommon{
|
2022-03-18 13:04:09 +00:00
|
|
|
BktInfo: tc.bktInfo,
|
2021-08-13 14:13:14 +00:00
|
|
|
MaxKeys: 1000,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
require.NoError(tc.t, err)
|
|
|
|
return res.Objects
|
|
|
|
}
|
|
|
|
|
2021-09-10 06:56:56 +00:00
|
|
|
func (tc *testContext) listObjectsV2() []*data.ObjectInfo {
|
2021-08-13 14:13:14 +00:00
|
|
|
res, err := tc.layer.ListObjectsV2(tc.ctx, &ListObjectsParamsV2{
|
|
|
|
ListObjectsParamsCommon: ListObjectsParamsCommon{
|
2022-03-18 13:04:09 +00:00
|
|
|
BktInfo: tc.bktInfo,
|
2021-08-13 14:13:14 +00:00
|
|
|
MaxKeys: 1000,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
require.NoError(tc.t, err)
|
|
|
|
return res.Objects
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tc *testContext) listVersions() *ListObjectVersionsInfo {
|
|
|
|
res, err := tc.layer.ListObjectVersions(tc.ctx, &ListObjectVersionsParams{
|
2022-03-18 13:04:09 +00:00
|
|
|
BktInfo: tc.bktInfo,
|
2021-08-13 14:13:14 +00:00
|
|
|
MaxKeys: 1000,
|
|
|
|
})
|
|
|
|
require.NoError(tc.t, err)
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
2022-05-25 17:25:43 +00:00
|
|
|
func (tc *testContext) checkListObjects(ids ...oid.ID) {
|
2021-08-13 14:13:14 +00:00
|
|
|
objs := tc.listObjectsV1()
|
|
|
|
require.Equal(tc.t, len(ids), len(objs))
|
|
|
|
for _, id := range ids {
|
|
|
|
require.Contains(tc.t, ids, id)
|
|
|
|
}
|
|
|
|
|
|
|
|
objs = tc.listObjectsV2()
|
|
|
|
require.Equal(tc.t, len(ids), len(objs))
|
|
|
|
for _, id := range ids {
|
|
|
|
require.Contains(tc.t, ids, id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-26 13:11:14 +00:00
|
|
|
func (tc *testContext) getObjectByID(objID oid.ID) *object.Object {
|
2022-12-20 08:38:58 +00:00
|
|
|
for _, obj := range tc.testFrostFS.Objects() {
|
2022-05-26 13:11:14 +00:00
|
|
|
id, _ := obj.ID()
|
|
|
|
if id.Equals(objID) {
|
|
|
|
return obj
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-08-13 14:13:14 +00:00
|
|
|
type testContext struct {
|
2022-12-20 08:38:58 +00:00
|
|
|
t *testing.T
|
|
|
|
ctx context.Context
|
|
|
|
layer Client
|
|
|
|
bktInfo *data.BucketInfo
|
|
|
|
obj string
|
|
|
|
testFrostFS *TestFrostFS
|
2021-08-13 14:13:14 +00:00
|
|
|
}
|
|
|
|
|
2021-09-21 13:08:06 +00:00
|
|
|
func prepareContext(t *testing.T, cachesConfig ...*CachesConfig) *testContext {
|
2022-06-06 08:01:12 +00:00
|
|
|
logger := zap.NewExample()
|
|
|
|
|
2021-08-13 14:13:14 +00:00
|
|
|
key, err := keys.NewPrivateKey()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-04-25 09:57:58 +00:00
|
|
|
bearerToken := bearertest.Token()
|
|
|
|
require.NoError(t, bearerToken.Sign(key.PrivateKey))
|
2022-03-01 19:02:24 +00:00
|
|
|
|
2023-08-14 15:34:41 +00:00
|
|
|
ctx := middleware.SetBoxData(context.Background(), &accessbox.Box{
|
2021-08-13 14:13:14 +00:00
|
|
|
Gate: &accessbox.GateData{
|
2022-04-25 09:57:58 +00:00
|
|
|
BearerToken: &bearerToken,
|
2021-08-13 14:13:14 +00:00
|
|
|
GateKey: key.PublicKey(),
|
|
|
|
},
|
|
|
|
})
|
2023-08-03 12:08:22 +00:00
|
|
|
tp := NewTestFrostFS(key)
|
2021-08-13 14:13:14 +00:00
|
|
|
|
|
|
|
bktName := "testbucket1"
|
2022-06-06 11:09:09 +00:00
|
|
|
bktID, err := tp.CreateContainer(ctx, PrmContainerCreate{
|
2022-03-01 19:02:24 +00:00
|
|
|
Name: bktName,
|
|
|
|
})
|
2021-08-13 14:13:14 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-06-06 08:01:12 +00:00
|
|
|
config := DefaultCachesConfigs(logger)
|
2021-09-21 13:08:06 +00:00
|
|
|
if len(cachesConfig) != 0 {
|
|
|
|
config = cachesConfig[0]
|
|
|
|
}
|
|
|
|
|
2022-10-04 08:31:09 +00:00
|
|
|
var owner user.ID
|
|
|
|
user.IDFromKey(&owner, key.PrivateKey.PublicKey)
|
|
|
|
|
2021-11-22 09:16:05 +00:00
|
|
|
layerCfg := &Config{
|
2022-05-20 15:02:00 +00:00
|
|
|
Caches: config,
|
|
|
|
AnonKey: AnonymousKey{Key: key},
|
2022-05-31 08:12:53 +00:00
|
|
|
TreeService: NewTreeService(),
|
2021-11-22 09:16:05 +00:00
|
|
|
}
|
|
|
|
|
2021-08-13 14:13:14 +00:00
|
|
|
return &testContext{
|
2022-02-28 08:02:05 +00:00
|
|
|
ctx: ctx,
|
2022-06-06 08:01:12 +00:00
|
|
|
layer: NewLayer(logger, tp, layerCfg),
|
2022-02-28 08:02:05 +00:00
|
|
|
bktInfo: &data.BucketInfo{
|
2022-03-04 13:07:27 +00:00
|
|
|
Name: bktName,
|
2022-10-04 08:31:09 +00:00
|
|
|
Owner: owner,
|
2022-06-27 09:08:26 +00:00
|
|
|
CID: bktID,
|
2022-02-28 08:02:05 +00:00
|
|
|
},
|
2022-12-20 08:38:58 +00:00
|
|
|
obj: "obj1",
|
|
|
|
t: t,
|
|
|
|
testFrostFS: tp,
|
2021-08-13 14:13:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSimpleVersioning(t *testing.T) {
|
|
|
|
tc := prepareContext(t)
|
2022-02-28 08:02:05 +00:00
|
|
|
err := tc.layer.PutBucketSettings(tc.ctx, &PutSettingsParams{
|
|
|
|
BktInfo: tc.bktInfo,
|
2022-07-20 10:30:19 +00:00
|
|
|
Settings: &data.BucketSettings{Versioning: data.VersioningEnabled},
|
2021-08-13 14:13:14 +00:00
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
obj1Content1 := []byte("content obj1 v1")
|
|
|
|
obj1v1 := tc.putObject(obj1Content1)
|
|
|
|
|
|
|
|
obj1Content2 := []byte("content obj1 v2")
|
|
|
|
obj1v2 := tc.putObject(obj1Content2)
|
|
|
|
|
2022-05-20 15:02:00 +00:00
|
|
|
_, buffer2 := tc.getObject(tc.obj, "", false)
|
2021-08-13 14:13:14 +00:00
|
|
|
require.Equal(t, obj1Content2, buffer2)
|
|
|
|
|
2022-05-25 17:25:43 +00:00
|
|
|
_, buffer1 := tc.getObject(tc.obj, obj1v1.ID.EncodeToString(), false)
|
2021-08-13 14:13:14 +00:00
|
|
|
require.Equal(t, obj1Content1, buffer1)
|
|
|
|
|
2021-08-27 21:33:50 +00:00
|
|
|
tc.checkListObjects(obj1v2.ID)
|
2021-08-13 14:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSimpleNoVersioning(t *testing.T) {
|
|
|
|
tc := prepareContext(t)
|
|
|
|
|
|
|
|
obj1Content1 := []byte("content obj1 v1")
|
|
|
|
obj1v1 := tc.putObject(obj1Content1)
|
|
|
|
|
|
|
|
obj1Content2 := []byte("content obj1 v2")
|
|
|
|
obj1v2 := tc.putObject(obj1Content2)
|
|
|
|
|
2022-05-20 15:02:00 +00:00
|
|
|
_, buffer2 := tc.getObject(tc.obj, "", false)
|
2021-08-13 14:13:14 +00:00
|
|
|
require.Equal(t, obj1Content2, buffer2)
|
|
|
|
|
2022-05-25 17:25:43 +00:00
|
|
|
tc.getObject(tc.obj, obj1v1.ID.EncodeToString(), true)
|
2021-08-27 21:33:50 +00:00
|
|
|
tc.checkListObjects(obj1v2.ID)
|
2021-08-13 14:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestVersioningDeleteObject(t *testing.T) {
|
|
|
|
tc := prepareContext(t)
|
2022-07-20 10:30:19 +00:00
|
|
|
settings := &data.BucketSettings{Versioning: data.VersioningEnabled}
|
2022-02-28 08:02:05 +00:00
|
|
|
err := tc.layer.PutBucketSettings(tc.ctx, &PutSettingsParams{
|
|
|
|
BktInfo: tc.bktInfo,
|
2022-03-31 06:24:29 +00:00
|
|
|
Settings: settings,
|
2021-08-13 14:13:14 +00:00
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
tc.putObject([]byte("content obj1 v1"))
|
|
|
|
tc.putObject([]byte("content obj1 v2"))
|
|
|
|
|
2022-06-24 12:39:30 +00:00
|
|
|
tc.deleteObject(tc.obj, "", settings)
|
2021-08-13 14:13:14 +00:00
|
|
|
tc.getObject(tc.obj, "", true)
|
|
|
|
|
|
|
|
tc.checkListObjects()
|
|
|
|
}
|
|
|
|
|
2022-05-31 08:12:53 +00:00
|
|
|
func TestGetUnversioned(t *testing.T) {
|
|
|
|
tc := prepareContext(t)
|
|
|
|
|
|
|
|
objContent := []byte("content obj1 v1")
|
|
|
|
objInfo := tc.putObject(objContent)
|
|
|
|
|
2022-07-20 10:30:19 +00:00
|
|
|
settings := &data.BucketSettings{Versioning: data.VersioningUnversioned}
|
2022-05-31 08:12:53 +00:00
|
|
|
err := tc.layer.PutBucketSettings(tc.ctx, &PutSettingsParams{
|
|
|
|
BktInfo: tc.bktInfo,
|
|
|
|
Settings: settings,
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-08-05 01:41:33 +00:00
|
|
|
resInfo, buffer := tc.getObject(tc.obj, data.UnversionedObjectVersionID, false)
|
2022-05-31 08:12:53 +00:00
|
|
|
require.Equal(t, objContent, buffer)
|
2022-08-04 17:31:33 +00:00
|
|
|
require.Equal(t, objInfo.VersionID(), resInfo.VersionID())
|
2022-05-31 08:12:53 +00:00
|
|
|
}
|
|
|
|
|
2021-08-13 14:13:14 +00:00
|
|
|
func TestVersioningDeleteSpecificObjectVersion(t *testing.T) {
|
|
|
|
tc := prepareContext(t)
|
2022-07-20 10:30:19 +00:00
|
|
|
settings := &data.BucketSettings{Versioning: data.VersioningEnabled}
|
2022-02-28 08:02:05 +00:00
|
|
|
err := tc.layer.PutBucketSettings(tc.ctx, &PutSettingsParams{
|
|
|
|
BktInfo: tc.bktInfo,
|
2022-03-31 06:24:29 +00:00
|
|
|
Settings: settings,
|
2021-08-13 14:13:14 +00:00
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
tc.putObject([]byte("content obj1 v1"))
|
|
|
|
objV2Info := tc.putObject([]byte("content obj1 v2"))
|
|
|
|
objV3Content := []byte("content obj1 v3")
|
|
|
|
objV3Info := tc.putObject(objV3Content)
|
|
|
|
|
2022-08-04 17:31:33 +00:00
|
|
|
tc.deleteObject(tc.obj, objV2Info.VersionID(), settings)
|
|
|
|
tc.getObject(tc.obj, objV2Info.VersionID(), true)
|
2021-08-13 14:13:14 +00:00
|
|
|
|
|
|
|
_, buffer3 := tc.getObject(tc.obj, "", false)
|
|
|
|
require.Equal(t, objV3Content, buffer3)
|
|
|
|
|
2022-06-24 12:39:30 +00:00
|
|
|
tc.deleteObject(tc.obj, "", settings)
|
2021-08-13 14:13:14 +00:00
|
|
|
tc.getObject(tc.obj, "", true)
|
|
|
|
|
2022-05-31 15:03:58 +00:00
|
|
|
versions := tc.listVersions()
|
|
|
|
for _, ver := range versions.DeleteMarker {
|
2021-08-13 14:13:14 +00:00
|
|
|
if ver.IsLatest {
|
2022-08-05 01:41:33 +00:00
|
|
|
tc.deleteObject(tc.obj, ver.ObjectInfo.VersionID(), settings)
|
2021-08-13 14:13:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
resInfo, buffer := tc.getObject(tc.obj, "", false)
|
|
|
|
require.Equal(t, objV3Content, buffer)
|
2022-08-04 17:31:33 +00:00
|
|
|
require.Equal(t, objV3Info.VersionID(), resInfo.VersionID())
|
2021-08-13 14:13:14 +00:00
|
|
|
}
|
|
|
|
|
2022-02-08 16:54:04 +00:00
|
|
|
func TestNoVersioningDeleteObject(t *testing.T) {
|
|
|
|
tc := prepareContext(t)
|
|
|
|
|
|
|
|
tc.putObject([]byte("content obj1 v1"))
|
|
|
|
tc.putObject([]byte("content obj1 v2"))
|
|
|
|
|
2022-06-24 12:39:30 +00:00
|
|
|
settings, err := tc.layer.GetBucketSettings(tc.ctx, tc.bktInfo)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
tc.deleteObject(tc.obj, "", settings)
|
2022-02-08 16:54:04 +00:00
|
|
|
tc.getObject(tc.obj, "", true)
|
|
|
|
tc.checkListObjects()
|
|
|
|
}
|