forked from TrueCloudLab/frostfs-s3-gw
217 lines
5.9 KiB
Go
217 lines
5.9 KiB
Go
|
package mock
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"crypto/rand"
|
||
|
"crypto/sha256"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/nspcc-dev/neofs-sdk-go/accounting"
|
||
|
"github.com/nspcc-dev/neofs-sdk-go/client"
|
||
|
"github.com/nspcc-dev/neofs-sdk-go/container"
|
||
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||
|
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
||
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||
|
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
||
|
"github.com/nspcc-dev/neofs-sdk-go/pool"
|
||
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||
|
)
|
||
|
|
||
|
type TestPool struct {
|
||
|
Objects map[string]*object.Object
|
||
|
Containers map[string]*container.Container
|
||
|
CurrentEpoch uint64
|
||
|
}
|
||
|
|
||
|
func NewTestPool() *TestPool {
|
||
|
return &TestPool{
|
||
|
Objects: make(map[string]*object.Object),
|
||
|
Containers: make(map[string]*container.Container),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) PutObject(ctx context.Context, params *client.PutObjectParams, option ...pool.CallOption) (*object.ID, error) {
|
||
|
b := make([]byte, 32)
|
||
|
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
oid := object.NewID()
|
||
|
oid.SetSHA256(sha256.Sum256(b))
|
||
|
|
||
|
raw := object.NewRawFrom(params.Object())
|
||
|
raw.SetID(oid)
|
||
|
raw.SetCreationEpoch(t.CurrentEpoch)
|
||
|
t.CurrentEpoch++
|
||
|
|
||
|
if params.PayloadReader() != nil {
|
||
|
all, err := io.ReadAll(params.PayloadReader())
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
raw.SetPayload(all)
|
||
|
}
|
||
|
raw.SetPayloadSize(uint64(len(raw.Payload())))
|
||
|
|
||
|
addr := newAddress(raw.ContainerID(), raw.ID())
|
||
|
t.Objects[addr.String()] = raw.Object()
|
||
|
return raw.ID(), nil
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) DeleteObject(ctx context.Context, params *client.DeleteObjectParams, option ...pool.CallOption) error {
|
||
|
delete(t.Objects, params.Address().String())
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) GetObject(ctx context.Context, params *client.GetObjectParams, option ...pool.CallOption) (*object.Object, error) {
|
||
|
if obj, ok := t.Objects[params.Address().String()]; ok {
|
||
|
if params.PayloadWriter() != nil {
|
||
|
_, err := params.PayloadWriter().Write(obj.Payload())
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
return obj, nil
|
||
|
}
|
||
|
|
||
|
return nil, fmt.Errorf("object not found " + params.Address().String())
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) GetObjectHeader(ctx context.Context, params *client.ObjectHeaderParams, option ...pool.CallOption) (*object.Object, error) {
|
||
|
p := new(client.GetObjectParams).WithAddress(params.Address())
|
||
|
return t.GetObject(ctx, p)
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) ObjectPayloadRangeData(ctx context.Context, params *client.RangeDataParams, option ...pool.CallOption) ([]byte, error) {
|
||
|
panic("implement me")
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) ObjectPayloadRangeSHA256(ctx context.Context, params *client.RangeChecksumParams, option ...pool.CallOption) ([][32]byte, error) {
|
||
|
panic("implement me")
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) ObjectPayloadRangeTZ(ctx context.Context, params *client.RangeChecksumParams, option ...pool.CallOption) ([][64]byte, error) {
|
||
|
panic("implement me")
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) SearchObject(ctx context.Context, params *client.SearchObjectParams, option ...pool.CallOption) ([]*object.ID, error) {
|
||
|
cidStr := params.ContainerID().String()
|
||
|
|
||
|
var res []*object.ID
|
||
|
|
||
|
if len(params.SearchFilters()) == 1 {
|
||
|
for k, v := range t.Objects {
|
||
|
if strings.Contains(k, cidStr) {
|
||
|
res = append(res, v.ID())
|
||
|
}
|
||
|
}
|
||
|
return res, nil
|
||
|
}
|
||
|
|
||
|
filter := params.SearchFilters()[1]
|
||
|
if len(params.SearchFilters()) != 2 || filter.Operation() != object.MatchStringEqual ||
|
||
|
(filter.Header() != object.AttributeFileName && filter.Header() != "S3-System-name") {
|
||
|
return nil, fmt.Errorf("usupported filters")
|
||
|
}
|
||
|
|
||
|
for k, v := range t.Objects {
|
||
|
if strings.Contains(k, cidStr) && isMatched(v.Attributes(), filter) {
|
||
|
res = append(res, v.ID())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return res, nil
|
||
|
}
|
||
|
|
||
|
func isMatched(attributes []*object.Attribute, filter object.SearchFilter) bool {
|
||
|
for _, attr := range attributes {
|
||
|
if attr.Key() == filter.Header() && attr.Value() == filter.Value() {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) PutContainer(ctx context.Context, container *container.Container, option ...pool.CallOption) (*cid.ID, error) {
|
||
|
b := make([]byte, 32)
|
||
|
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
id := cid.New()
|
||
|
id.SetSHA256(sha256.Sum256(b))
|
||
|
t.Containers[id.String()] = container
|
||
|
|
||
|
return id, nil
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) GetContainer(ctx context.Context, id *cid.ID, option ...pool.CallOption) (*container.Container, error) {
|
||
|
for k, v := range t.Containers {
|
||
|
if k == id.String() {
|
||
|
return v, nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil, fmt.Errorf("container not found " + id.String())
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) ListContainers(ctx context.Context, id *owner.ID, option ...pool.CallOption) ([]*cid.ID, error) {
|
||
|
var res []*cid.ID
|
||
|
for k := range t.Containers {
|
||
|
cID := cid.New()
|
||
|
if err := cID.Parse(k); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
res = append(res, cID)
|
||
|
}
|
||
|
|
||
|
return res, nil
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) DeleteContainer(ctx context.Context, id *cid.ID, option ...pool.CallOption) error {
|
||
|
delete(t.Containers, id.String())
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) GetEACL(ctx context.Context, id *cid.ID, option ...pool.CallOption) (*eacl.Table, error) {
|
||
|
panic("implement me")
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) Balance(ctx context.Context, owner *owner.ID, opts ...pool.CallOption) (*accounting.Decimal, error) {
|
||
|
panic("implement me")
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) SetEACL(ctx context.Context, table *eacl.Table, option ...pool.CallOption) error {
|
||
|
panic("implement me")
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) AnnounceContainerUsedSpace(ctx context.Context, announcements []container.UsedSpaceAnnouncement, option ...pool.CallOption) error {
|
||
|
panic("implement me")
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) Connection() (pool.Client, *session.Token, error) {
|
||
|
panic("implement me")
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) Close() {
|
||
|
panic("implement me")
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) OwnerID() *owner.ID {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (t *TestPool) WaitForContainerPresence(ctx context.Context, id *cid.ID, params *pool.ContainerPollingParams) error {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func newAddress(cid *cid.ID, oid *object.ID) *object.Address {
|
||
|
address := object.NewAddress()
|
||
|
address.SetContainerID(cid)
|
||
|
address.SetObjectID(oid)
|
||
|
return address
|
||
|
}
|