2019-01-24 20:15:10 +00:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
2018-11-15 15:31:33 +00:00
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
2019-02-04 16:56:10 +00:00
|
|
|
package kvmetainfo_test
|
2018-11-15 15:31:33 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2018-11-26 07:39:05 +00:00
|
|
|
"io"
|
2018-11-15 15:31:33 +00:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
2019-03-18 10:55:06 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2018-11-21 14:35:53 +00:00
|
|
|
"storj.io/storj/internal/memory"
|
2019-02-05 21:12:27 +00:00
|
|
|
"storj.io/storj/internal/testplanet"
|
2019-06-26 11:38:51 +01:00
|
|
|
"storj.io/storj/internal/testrand"
|
2018-11-15 15:31:33 +00:00
|
|
|
"storj.io/storj/pkg/storj"
|
2019-07-28 06:55:36 +01:00
|
|
|
"storj.io/storj/uplink/metainfo/kvmetainfo"
|
|
|
|
"storj.io/storj/uplink/storage/streams"
|
|
|
|
"storj.io/storj/uplink/stream"
|
2018-11-15 15:31:33 +00:00
|
|
|
)
|
|
|
|
|
2018-11-30 13:50:52 +00:00
|
|
|
const TestFile = "test-file"
|
|
|
|
|
|
|
|
func TestCreateObject(t *testing.T) {
|
|
|
|
customRS := storj.RedundancyScheme{
|
|
|
|
Algorithm: storj.ReedSolomon,
|
|
|
|
RequiredShares: 29,
|
|
|
|
RepairShares: 35,
|
|
|
|
OptimalShares: 80,
|
|
|
|
TotalShares: 95,
|
2019-03-18 10:55:06 +00:00
|
|
|
ShareSize: 2 * memory.KiB.Int32(),
|
2018-11-30 13:50:52 +00:00
|
|
|
}
|
|
|
|
|
2019-06-11 18:14:05 +01:00
|
|
|
const stripesPerBlock = 2
|
2019-07-03 19:07:44 +01:00
|
|
|
customEP := storj.EncryptionParameters{
|
|
|
|
CipherSuite: storj.EncNull,
|
|
|
|
BlockSize: stripesPerBlock * customRS.StripeSize(),
|
2018-11-30 13:50:52 +00:00
|
|
|
}
|
|
|
|
|
2019-06-24 20:23:07 +01:00
|
|
|
runTest(t, func(t *testing.T, ctx context.Context, planet *testplanet.Planet, db *kvmetainfo.DB, streams streams.Store) {
|
2018-11-15 15:31:33 +00:00
|
|
|
bucket, err := db.CreateBucket(ctx, TestBucket, nil)
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2018-11-30 13:50:52 +00:00
|
|
|
for i, tt := range []struct {
|
|
|
|
create *storj.CreateObject
|
|
|
|
expectedRS storj.RedundancyScheme
|
2019-07-03 19:07:44 +01:00
|
|
|
expectedEP storj.EncryptionParameters
|
2018-11-30 13:50:52 +00:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
create: nil,
|
2019-02-04 16:56:10 +00:00
|
|
|
expectedRS: kvmetainfo.DefaultRS,
|
2019-07-03 19:07:44 +01:00
|
|
|
expectedEP: kvmetainfo.DefaultES,
|
2019-06-06 19:55:10 +01:00
|
|
|
},
|
|
|
|
{
|
2019-07-03 19:07:44 +01:00
|
|
|
create: &storj.CreateObject{RedundancyScheme: customRS, EncryptionParameters: customEP},
|
2018-11-30 13:50:52 +00:00
|
|
|
expectedRS: customRS,
|
2019-07-03 19:07:44 +01:00
|
|
|
expectedEP: customEP,
|
2019-06-06 19:55:10 +01:00
|
|
|
},
|
|
|
|
{
|
2018-11-30 13:50:52 +00:00
|
|
|
create: &storj.CreateObject{RedundancyScheme: customRS},
|
|
|
|
expectedRS: customRS,
|
2019-07-03 19:07:44 +01:00
|
|
|
expectedEP: storj.EncryptionParameters{CipherSuite: kvmetainfo.DefaultES.CipherSuite, BlockSize: kvmetainfo.DefaultES.BlockSize},
|
2019-06-06 19:55:10 +01:00
|
|
|
},
|
|
|
|
{
|
2019-07-03 19:07:44 +01:00
|
|
|
create: &storj.CreateObject{EncryptionParameters: customEP},
|
2019-02-04 16:56:10 +00:00
|
|
|
expectedRS: kvmetainfo.DefaultRS,
|
2019-07-03 19:07:44 +01:00
|
|
|
expectedEP: storj.EncryptionParameters{CipherSuite: customEP.CipherSuite, BlockSize: kvmetainfo.DefaultES.BlockSize},
|
2018-11-30 13:50:52 +00:00
|
|
|
},
|
|
|
|
} {
|
|
|
|
errTag := fmt.Sprintf("%d. %+v", i, tt)
|
|
|
|
|
|
|
|
obj, err := db.CreateObject(ctx, bucket.Name, TestFile, tt.create)
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2018-11-30 13:50:52 +00:00
|
|
|
|
|
|
|
info := obj.Info()
|
|
|
|
|
2018-12-03 14:38:03 +00:00
|
|
|
assert.Equal(t, TestBucket, info.Bucket.Name, errTag)
|
2019-07-03 19:07:44 +01:00
|
|
|
assert.Equal(t, storj.EncAESGCM, info.Bucket.PathCipher, errTag)
|
2018-11-30 13:50:52 +00:00
|
|
|
assert.Equal(t, TestFile, info.Path, errTag)
|
|
|
|
assert.EqualValues(t, 0, info.Size, errTag)
|
|
|
|
assert.Equal(t, tt.expectedRS, info.RedundancyScheme, errTag)
|
2019-07-03 19:07:44 +01:00
|
|
|
assert.Equal(t, tt.expectedEP, info.EncryptionParameters, errTag)
|
2018-11-15 15:31:33 +00:00
|
|
|
}
|
2018-11-30 13:50:52 +00:00
|
|
|
})
|
|
|
|
}
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2018-11-30 13:50:52 +00:00
|
|
|
func TestGetObject(t *testing.T) {
|
2019-06-24 20:23:07 +01:00
|
|
|
runTest(t, func(t *testing.T, ctx context.Context, planet *testplanet.Planet, db *kvmetainfo.DB, streams streams.Store) {
|
2018-11-30 13:50:52 +00:00
|
|
|
bucket, err := db.CreateBucket(ctx, TestBucket, nil)
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2019-02-04 16:56:10 +00:00
|
|
|
upload(ctx, t, db, streams, bucket, TestFile, nil)
|
2018-11-30 13:50:52 +00:00
|
|
|
|
2018-11-15 15:31:33 +00:00
|
|
|
_, err = db.GetObject(ctx, "", "")
|
|
|
|
assert.True(t, storj.ErrNoBucket.Has(err))
|
|
|
|
|
|
|
|
_, err = db.GetObject(ctx, bucket.Name, "")
|
2018-11-30 13:50:52 +00:00
|
|
|
assert.True(t, storj.ErrNoPath.Has(err))
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2018-11-30 13:50:52 +00:00
|
|
|
_, err = db.GetObject(ctx, "non-existing-bucket", TestFile)
|
2018-11-21 11:17:28 +00:00
|
|
|
assert.True(t, storj.ErrBucketNotFound.Has(err))
|
2018-11-15 15:31:33 +00:00
|
|
|
|
|
|
|
_, err = db.GetObject(ctx, bucket.Name, "non-existing-file")
|
2018-11-21 11:17:28 +00:00
|
|
|
assert.True(t, storj.ErrObjectNotFound.Has(err))
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2018-11-30 13:50:52 +00:00
|
|
|
object, err := db.GetObject(ctx, bucket.Name, TestFile)
|
2018-11-15 15:31:33 +00:00
|
|
|
if assert.NoError(t, err) {
|
2018-11-30 13:50:52 +00:00
|
|
|
assert.Equal(t, TestFile, object.Path)
|
2018-12-03 14:38:03 +00:00
|
|
|
assert.Equal(t, TestBucket, object.Bucket.Name)
|
2019-07-03 19:07:44 +01:00
|
|
|
assert.Equal(t, storj.EncAESGCM, object.Bucket.PathCipher)
|
2018-11-15 15:31:33 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetObjectStream(t *testing.T) {
|
2019-06-24 20:23:07 +01:00
|
|
|
runTest(t, func(t *testing.T, ctx context.Context, planet *testplanet.Planet, db *kvmetainfo.DB, streams streams.Store) {
|
2019-06-26 11:38:51 +01:00
|
|
|
data := testrand.Bytes(32 * memory.KiB)
|
2018-11-21 14:35:53 +00:00
|
|
|
|
2018-11-30 13:50:52 +00:00
|
|
|
bucket, err := db.CreateBucket(ctx, TestBucket, nil)
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2019-02-04 16:56:10 +00:00
|
|
|
upload(ctx, t, db, streams, bucket, "empty-file", nil)
|
|
|
|
upload(ctx, t, db, streams, bucket, "small-file", []byte("test"))
|
|
|
|
upload(ctx, t, db, streams, bucket, "large-file", data)
|
2018-11-30 13:50:52 +00:00
|
|
|
|
2018-11-15 15:31:33 +00:00
|
|
|
_, err = db.GetObjectStream(ctx, "", "")
|
|
|
|
assert.True(t, storj.ErrNoBucket.Has(err))
|
|
|
|
|
|
|
|
_, err = db.GetObjectStream(ctx, bucket.Name, "")
|
2018-11-30 13:50:52 +00:00
|
|
|
assert.True(t, storj.ErrNoPath.Has(err))
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2018-11-21 14:35:53 +00:00
|
|
|
_, err = db.GetObjectStream(ctx, "non-existing-bucket", "small-file")
|
2018-11-21 11:17:28 +00:00
|
|
|
assert.True(t, storj.ErrBucketNotFound.Has(err))
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2018-12-03 14:38:03 +00:00
|
|
|
_, err = db.GetObjectStream(ctx, bucket.Name, "non-existing-file")
|
2018-11-21 11:17:28 +00:00
|
|
|
assert.True(t, storj.ErrObjectNotFound.Has(err))
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2019-07-22 20:10:04 +01:00
|
|
|
assertStream(ctx, t, db, streams, bucket, "empty-file", []byte{})
|
|
|
|
assertStream(ctx, t, db, streams, bucket, "small-file", []byte("test"))
|
|
|
|
assertStream(ctx, t, db, streams, bucket, "large-file", data)
|
2019-02-05 21:12:27 +00:00
|
|
|
|
2019-02-08 20:35:59 +00:00
|
|
|
/* TODO: Disable stopping due to flakiness.
|
2019-08-06 17:35:59 +01:00
|
|
|
// Stop randomly half of the storage nodes and remove them from satellite's overlay
|
2019-02-05 21:12:27 +00:00
|
|
|
perm := mathrand.Perm(len(planet.StorageNodes))
|
2019-02-08 13:20:12 +00:00
|
|
|
for _, i := range perm[:(len(perm) / 2)] {
|
2019-02-05 21:12:27 +00:00
|
|
|
assert.NoError(t, planet.StopPeer(planet.StorageNodes[i]))
|
2019-04-04 17:34:36 +01:00
|
|
|
_, err := planet.Satellites[0].Overlay.Service.UpdateUptime(ctx, planet.StorageNodes[i].ID(), false)
|
|
|
|
assert.NoError(t, err)
|
2019-02-05 21:12:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// try downloading the large file again
|
2019-03-18 10:55:06 +00:00
|
|
|
assertStream(ctx, t, db, streams, bucket, "large-file", 32*memory.KiB.Int64(), data)
|
2019-02-08 20:35:59 +00:00
|
|
|
*/
|
2018-11-15 15:31:33 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-02-04 16:56:10 +00:00
|
|
|
func upload(ctx context.Context, t *testing.T, db *kvmetainfo.DB, streams streams.Store, bucket storj.Bucket, path storj.Path, data []byte) {
|
2018-11-30 13:50:52 +00:00
|
|
|
obj, err := db.CreateObject(ctx, bucket.Name, path, nil)
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2018-11-30 13:50:52 +00:00
|
|
|
|
|
|
|
str, err := obj.CreateStream(ctx)
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2018-11-30 13:50:52 +00:00
|
|
|
|
2019-02-04 16:56:10 +00:00
|
|
|
upload := stream.NewUpload(ctx, str, streams)
|
2018-11-30 13:50:52 +00:00
|
|
|
|
|
|
|
_, err = upload.Write(data)
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2018-11-30 13:50:52 +00:00
|
|
|
|
|
|
|
err = upload.Close()
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2018-11-30 13:50:52 +00:00
|
|
|
|
|
|
|
err = obj.Commit(ctx)
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2018-11-30 13:50:52 +00:00
|
|
|
}
|
|
|
|
|
2019-07-22 20:10:04 +01:00
|
|
|
func assertStream(ctx context.Context, t *testing.T, db *kvmetainfo.DB, streams streams.Store, bucket storj.Bucket, path storj.Path, content []byte) {
|
2018-12-04 16:46:02 +00:00
|
|
|
readOnly, err := db.GetObjectStream(ctx, bucket.Name, path)
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2018-12-04 16:46:02 +00:00
|
|
|
|
2018-11-26 07:39:05 +00:00
|
|
|
assert.Equal(t, path, readOnly.Info().Path)
|
2018-12-03 14:38:03 +00:00
|
|
|
assert.Equal(t, TestBucket, readOnly.Info().Bucket.Name)
|
2019-07-03 19:07:44 +01:00
|
|
|
assert.Equal(t, storj.EncAESGCM, readOnly.Info().Bucket.PathCipher)
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2018-11-26 07:39:05 +00:00
|
|
|
segments, more, err := readOnly.Segments(ctx, 0, 0)
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2018-11-15 15:31:33 +00:00
|
|
|
|
|
|
|
assert.False(t, more)
|
|
|
|
if !assert.Equal(t, 1, len(segments)) {
|
2018-11-21 14:35:53 +00:00
|
|
|
return
|
2018-11-15 15:31:33 +00:00
|
|
|
}
|
2018-11-21 14:35:53 +00:00
|
|
|
|
2018-11-15 15:31:33 +00:00
|
|
|
assert.EqualValues(t, 0, segments[0].Index)
|
|
|
|
assert.EqualValues(t, len(content), segments[0].Size)
|
2019-03-18 10:55:06 +00:00
|
|
|
if segments[0].Size > 4*memory.KiB.Int64() {
|
2018-11-21 14:35:53 +00:00
|
|
|
assertRemoteSegment(t, segments[0])
|
|
|
|
} else {
|
|
|
|
assertInlineSegment(t, segments[0], content)
|
|
|
|
}
|
2018-11-26 07:39:05 +00:00
|
|
|
|
2019-02-04 16:56:10 +00:00
|
|
|
download := stream.NewDownload(ctx, readOnly, streams)
|
2018-11-26 07:39:05 +00:00
|
|
|
defer func() {
|
|
|
|
err = download.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}()
|
|
|
|
|
|
|
|
data := make([]byte, len(content))
|
|
|
|
n, err := io.ReadFull(download, data)
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2018-11-26 07:39:05 +00:00
|
|
|
|
|
|
|
assert.Equal(t, len(content), n)
|
|
|
|
assert.Equal(t, content, data)
|
2018-11-21 14:35:53 +00:00
|
|
|
}
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2018-11-21 14:35:53 +00:00
|
|
|
func assertInlineSegment(t *testing.T, segment storj.Segment, content []byte) {
|
|
|
|
assert.Equal(t, content, segment.Inline)
|
2019-03-18 10:55:06 +00:00
|
|
|
assert.True(t, segment.PieceID.IsZero())
|
2018-11-21 14:35:53 +00:00
|
|
|
assert.Equal(t, 0, len(segment.Pieces))
|
|
|
|
}
|
|
|
|
|
|
|
|
func assertRemoteSegment(t *testing.T, segment storj.Segment) {
|
|
|
|
assert.Nil(t, segment.Inline)
|
|
|
|
assert.NotNil(t, segment.PieceID)
|
|
|
|
assert.NotEqual(t, 0, len(segment.Pieces))
|
|
|
|
|
|
|
|
// check that piece numbers and nodes are unique
|
|
|
|
nums := make(map[byte]struct{})
|
|
|
|
nodes := make(map[string]struct{})
|
|
|
|
for _, piece := range segment.Pieces {
|
|
|
|
if _, ok := nums[piece.Number]; ok {
|
|
|
|
t.Fatalf("piece number %d is not unique", piece.Number)
|
|
|
|
}
|
|
|
|
nums[piece.Number] = struct{}{}
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2018-11-29 18:39:27 +00:00
|
|
|
id := piece.Location.String()
|
2018-11-21 14:35:53 +00:00
|
|
|
if _, ok := nodes[id]; ok {
|
|
|
|
t.Fatalf("node id %s is not unique", id)
|
|
|
|
}
|
|
|
|
nodes[id] = struct{}{}
|
|
|
|
}
|
2018-11-15 15:31:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDeleteObject(t *testing.T) {
|
2019-06-24 20:23:07 +01:00
|
|
|
runTest(t, func(t *testing.T, ctx context.Context, planet *testplanet.Planet, db *kvmetainfo.DB, streams streams.Store) {
|
2018-11-15 15:31:33 +00:00
|
|
|
bucket, err := db.CreateBucket(ctx, TestBucket, nil)
|
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-02-04 16:56:10 +00:00
|
|
|
upload(ctx, t, db, streams, bucket, TestFile, nil)
|
2018-11-15 15:31:33 +00:00
|
|
|
|
|
|
|
err = db.DeleteObject(ctx, "", "")
|
|
|
|
assert.True(t, storj.ErrNoBucket.Has(err))
|
|
|
|
|
|
|
|
err = db.DeleteObject(ctx, bucket.Name, "")
|
2018-11-21 11:17:28 +00:00
|
|
|
assert.True(t, storj.ErrNoPath.Has(err))
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2018-11-30 13:50:52 +00:00
|
|
|
err = db.DeleteObject(ctx, "non-existing-bucket", TestFile)
|
2018-11-21 11:17:28 +00:00
|
|
|
assert.True(t, storj.ErrBucketNotFound.Has(err))
|
2018-11-15 15:31:33 +00:00
|
|
|
|
|
|
|
err = db.DeleteObject(ctx, bucket.Name, "non-existing-file")
|
2018-11-21 11:17:28 +00:00
|
|
|
assert.True(t, storj.ErrObjectNotFound.Has(err))
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2018-11-30 13:50:52 +00:00
|
|
|
err = db.DeleteObject(ctx, bucket.Name, TestFile)
|
2018-11-15 15:31:33 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestListObjectsEmpty(t *testing.T) {
|
2019-06-24 20:23:07 +01:00
|
|
|
runTest(t, func(t *testing.T, ctx context.Context, planet *testplanet.Planet, db *kvmetainfo.DB, streams streams.Store) {
|
2018-11-15 15:31:33 +00:00
|
|
|
bucket, err := db.CreateBucket(ctx, TestBucket, nil)
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2018-11-15 15:31:33 +00:00
|
|
|
|
|
|
|
_, err = db.ListObjects(ctx, "", storj.ListOptions{})
|
|
|
|
assert.True(t, storj.ErrNoBucket.Has(err))
|
|
|
|
|
|
|
|
_, err = db.ListObjects(ctx, bucket.Name, storj.ListOptions{})
|
|
|
|
assert.EqualError(t, err, "kvmetainfo: invalid direction 0")
|
|
|
|
|
2019-09-10 16:39:47 +01:00
|
|
|
// TODO for now we are supporting only storj.After
|
2018-11-15 15:31:33 +00:00
|
|
|
for _, direction := range []storj.ListDirection{
|
2019-09-10 16:39:47 +01:00
|
|
|
// storj.Before,
|
|
|
|
// storj.Backward,
|
|
|
|
// storj.Forward,
|
2018-11-15 15:31:33 +00:00
|
|
|
storj.After,
|
|
|
|
} {
|
|
|
|
list, err := db.ListObjects(ctx, bucket.Name, storj.ListOptions{Direction: direction})
|
|
|
|
if assert.NoError(t, err) {
|
|
|
|
assert.False(t, list.More)
|
|
|
|
assert.Equal(t, 0, len(list.Items))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestListObjects(t *testing.T) {
|
2019-06-24 20:23:07 +01:00
|
|
|
runTest(t, func(t *testing.T, ctx context.Context, planet *testplanet.Planet, db *kvmetainfo.DB, streams streams.Store) {
|
2019-07-03 19:07:44 +01:00
|
|
|
bucket, err := db.CreateBucket(ctx, TestBucket, &storj.Bucket{PathCipher: storj.EncNull})
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2018-11-15 15:31:33 +00:00
|
|
|
|
|
|
|
filePaths := []string{
|
|
|
|
"a", "aa", "b", "bb", "c",
|
|
|
|
"a/xa", "a/xaa", "a/xb", "a/xbb", "a/xc",
|
|
|
|
"b/ya", "b/yaa", "b/yb", "b/ybb", "b/yc",
|
|
|
|
}
|
2018-11-30 13:50:52 +00:00
|
|
|
|
2018-11-15 15:31:33 +00:00
|
|
|
for _, path := range filePaths {
|
2019-02-04 16:56:10 +00:00
|
|
|
upload(ctx, t, db, streams, bucket, path, nil)
|
2018-11-15 15:31:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
otherBucket, err := db.CreateBucket(ctx, "otherbucket", nil)
|
2019-03-18 10:55:06 +00:00
|
|
|
require.NoError(t, err)
|
2018-11-15 15:31:33 +00:00
|
|
|
|
2019-02-04 16:56:10 +00:00
|
|
|
upload(ctx, t, db, streams, otherBucket, "file-in-other-bucket", nil)
|
2018-11-15 15:31:33 +00:00
|
|
|
|
|
|
|
for i, tt := range []struct {
|
|
|
|
options storj.ListOptions
|
|
|
|
more bool
|
|
|
|
result []string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
options: options("", "", storj.After, 0),
|
|
|
|
result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
|
|
|
|
}, {
|
|
|
|
options: options("", "`", storj.After, 0),
|
|
|
|
result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
|
|
|
|
}, {
|
|
|
|
options: options("", "b", storj.After, 0),
|
|
|
|
result: []string{"b/", "bb", "c"},
|
|
|
|
}, {
|
|
|
|
options: options("", "c", storj.After, 0),
|
|
|
|
result: []string{},
|
|
|
|
}, {
|
|
|
|
options: options("", "ca", storj.After, 0),
|
|
|
|
result: []string{},
|
|
|
|
}, {
|
|
|
|
options: options("", "", storj.After, 1),
|
|
|
|
more: true,
|
|
|
|
result: []string{"a"},
|
|
|
|
}, {
|
|
|
|
options: options("", "`", storj.After, 1),
|
|
|
|
more: true,
|
|
|
|
result: []string{"a"},
|
|
|
|
}, {
|
|
|
|
options: options("", "aa", storj.After, 1),
|
|
|
|
more: true,
|
|
|
|
result: []string{"b"},
|
|
|
|
}, {
|
|
|
|
options: options("", "c", storj.After, 1),
|
|
|
|
result: []string{},
|
|
|
|
}, {
|
|
|
|
options: options("", "ca", storj.After, 1),
|
|
|
|
result: []string{},
|
|
|
|
}, {
|
|
|
|
options: options("", "", storj.After, 2),
|
|
|
|
more: true,
|
|
|
|
result: []string{"a", "a/"},
|
|
|
|
}, {
|
2018-12-07 18:31:29 +00:00
|
|
|
options: options("", "`", storj.After, 2),
|
2018-11-15 15:31:33 +00:00
|
|
|
more: true,
|
|
|
|
result: []string{"a", "a/"},
|
|
|
|
}, {
|
|
|
|
options: options("", "aa", storj.After, 2),
|
|
|
|
more: true,
|
|
|
|
result: []string{"b", "b/"},
|
|
|
|
}, {
|
|
|
|
options: options("", "bb", storj.After, 2),
|
|
|
|
result: []string{"c"},
|
|
|
|
}, {
|
|
|
|
options: options("", "c", storj.After, 2),
|
|
|
|
result: []string{},
|
|
|
|
}, {
|
|
|
|
options: options("", "ca", storj.After, 2),
|
|
|
|
result: []string{},
|
|
|
|
}, {
|
|
|
|
options: optionsRecursive("", "", storj.After, 0),
|
|
|
|
result: []string{"a", "a/xa", "a/xaa", "a/xb", "a/xbb", "a/xc", "aa", "b", "b/ya", "b/yaa", "b/yb", "b/ybb", "b/yc", "bb", "c"},
|
|
|
|
}, {
|
|
|
|
options: options("a", "", storj.After, 0),
|
|
|
|
result: []string{"xa", "xaa", "xb", "xbb", "xc"},
|
|
|
|
}, {
|
|
|
|
options: options("a/", "", storj.After, 0),
|
|
|
|
result: []string{"xa", "xaa", "xb", "xbb", "xc"},
|
|
|
|
}, {
|
|
|
|
options: options("a/", "xb", storj.After, 0),
|
|
|
|
result: []string{"xbb", "xc"},
|
|
|
|
}, {
|
|
|
|
options: optionsRecursive("", "a/xbb", storj.After, 5),
|
|
|
|
more: true,
|
|
|
|
result: []string{"a/xc", "aa", "b", "b/ya", "b/yaa"},
|
|
|
|
}, {
|
|
|
|
options: options("a/", "xaa", storj.After, 2),
|
|
|
|
more: true,
|
|
|
|
result: []string{"xb", "xbb"},
|
|
|
|
},
|
2019-09-10 16:39:47 +01:00
|
|
|
// TODO commented until we will decide if we will support direction for object listing
|
|
|
|
//
|
|
|
|
// {
|
|
|
|
// options: options("", "", storj.Forward, 0),
|
|
|
|
// result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "`", storj.Forward, 0),
|
|
|
|
// result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "b", storj.Forward, 0),
|
|
|
|
// result: []string{"b", "b/", "bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "c", storj.Forward, 0),
|
|
|
|
// result: []string{"c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "ca", storj.Forward, 0),
|
|
|
|
// result: []string{},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "", storj.Forward, 1),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"a"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "`", storj.Forward, 1),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"a"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "aa", storj.Forward, 1),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"aa"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "c", storj.Forward, 1),
|
|
|
|
// result: []string{"c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "ca", storj.Forward, 1),
|
|
|
|
// result: []string{},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "", storj.Forward, 2),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"a", "a/"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "`", storj.Forward, 2),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"a", "a/"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "aa", storj.Forward, 2),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"aa", "b"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "bb", storj.Forward, 2),
|
|
|
|
// result: []string{"bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "c", storj.Forward, 2),
|
|
|
|
// result: []string{"c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "ca", storj.Forward, 2),
|
|
|
|
// result: []string{},
|
|
|
|
// }, {
|
|
|
|
// options: optionsRecursive("", "", storj.Forward, 0),
|
|
|
|
// result: []string{"a", "a/xa", "a/xaa", "a/xb", "a/xbb", "a/xc", "aa", "b", "b/ya", "b/yaa", "b/yb", "b/ybb", "b/yc", "bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("a", "", storj.Forward, 0),
|
|
|
|
// result: []string{"xa", "xaa", "xb", "xbb", "xc"},
|
|
|
|
// }, {
|
|
|
|
// options: options("a/", "", storj.Forward, 0),
|
|
|
|
// result: []string{"xa", "xaa", "xb", "xbb", "xc"},
|
|
|
|
// }, {
|
|
|
|
// options: options("a/", "xb", storj.Forward, 0),
|
|
|
|
// result: []string{"xb", "xbb", "xc"},
|
|
|
|
// }, {
|
|
|
|
// options: optionsRecursive("", "a/xbb", storj.Forward, 5),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"a/xbb", "a/xc", "aa", "b", "b/ya"},
|
|
|
|
// }, {
|
|
|
|
// options: options("a/", "xaa", storj.Forward, 2),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"xaa", "xb"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "", storj.Backward, 0),
|
|
|
|
// result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "`", storj.Backward, 0),
|
|
|
|
// result: []string{},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "b", storj.Backward, 0),
|
|
|
|
// result: []string{"a", "a/", "aa", "b"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "c", storj.Backward, 0),
|
|
|
|
// result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "ca", storj.Backward, 0),
|
|
|
|
// result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "", storj.Backward, 1),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "`", storj.Backward, 1),
|
|
|
|
// result: []string{},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "aa", storj.Backward, 1),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"aa"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "c", storj.Backward, 1),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "ca", storj.Backward, 1),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "", storj.Backward, 2),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "`", storj.Backward, 2),
|
|
|
|
// result: []string{},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "a/", storj.Backward, 2),
|
|
|
|
// result: []string{"a"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "bb", storj.Backward, 2),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"b/", "bb"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "c", storj.Backward, 2),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "ca", storj.Backward, 2),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: optionsRecursive("", "", storj.Backward, 0),
|
|
|
|
// result: []string{"a", "a/xa", "a/xaa", "a/xb", "a/xbb", "a/xc", "aa", "b", "b/ya", "b/yaa", "b/yb", "b/ybb", "b/yc", "bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("a", "", storj.Backward, 0),
|
|
|
|
// result: []string{"xa", "xaa", "xb", "xbb", "xc"},
|
|
|
|
// }, {
|
|
|
|
// options: options("a/", "", storj.Backward, 0),
|
|
|
|
// result: []string{"xa", "xaa", "xb", "xbb", "xc"},
|
|
|
|
// }, {
|
|
|
|
// options: options("a/", "xb", storj.Backward, 0),
|
|
|
|
// result: []string{"xa", "xaa", "xb"},
|
|
|
|
// }, {
|
|
|
|
// options: optionsRecursive("", "b/yaa", storj.Backward, 5),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"a/xc", "aa", "b", "b/ya", "b/yaa"},
|
|
|
|
// }, {
|
|
|
|
// options: options("a/", "xbb", storj.Backward, 2),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"xb", "xbb"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "", storj.Before, 0),
|
|
|
|
// result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "`", storj.Before, 0),
|
|
|
|
// result: []string{},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "a", storj.Before, 0),
|
|
|
|
// result: []string{},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "b", storj.Before, 0),
|
|
|
|
// result: []string{"a", "a/", "aa"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "c", storj.Before, 0),
|
|
|
|
// result: []string{"a", "a/", "aa", "b", "b/", "bb"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "ca", storj.Before, 0),
|
|
|
|
// result: []string{"a", "a/", "aa", "b", "b/", "bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "", storj.Before, 1),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "`", storj.Before, 1),
|
|
|
|
// result: []string{},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "a/", storj.Before, 1),
|
|
|
|
// result: []string{"a"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "c", storj.Before, 1),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"bb"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "ca", storj.Before, 1),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "", storj.Before, 2),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "`", storj.Before, 2),
|
|
|
|
// result: []string{},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "a/", storj.Before, 2),
|
|
|
|
// result: []string{"a"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "bb", storj.Before, 2),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"b", "b/"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "c", storj.Before, 2),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"b/", "bb"},
|
|
|
|
// }, {
|
|
|
|
// options: options("", "ca", storj.Before, 2),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: optionsRecursive("", "", storj.Before, 0),
|
|
|
|
// result: []string{"a", "a/xa", "a/xaa", "a/xb", "a/xbb", "a/xc", "aa", "b", "b/ya", "b/yaa", "b/yb", "b/ybb", "b/yc", "bb", "c"},
|
|
|
|
// }, {
|
|
|
|
// options: options("a", "", storj.Before, 0),
|
|
|
|
// result: []string{"xa", "xaa", "xb", "xbb", "xc"},
|
|
|
|
// }, {
|
|
|
|
// options: options("a/", "", storj.Before, 0),
|
|
|
|
// result: []string{"xa", "xaa", "xb", "xbb", "xc"},
|
|
|
|
// }, {
|
|
|
|
// options: options("a/", "xb", storj.Before, 0),
|
|
|
|
// result: []string{"xa", "xaa"},
|
|
|
|
// }, {
|
|
|
|
// options: optionsRecursive("", "b/yaa", storj.Before, 5),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"a/xbb", "a/xc", "aa", "b", "b/ya"},
|
|
|
|
// }, {
|
|
|
|
// options: options("a/", "xbb", storj.Before, 2),
|
|
|
|
// more: true,
|
|
|
|
// result: []string{"xaa", "xb"},
|
|
|
|
// },
|
2018-11-15 15:31:33 +00:00
|
|
|
} {
|
|
|
|
errTag := fmt.Sprintf("%d. %+v", i, tt)
|
|
|
|
|
|
|
|
list, err := db.ListObjects(ctx, bucket.Name, tt.options)
|
|
|
|
|
|
|
|
if assert.NoError(t, err, errTag) {
|
|
|
|
assert.Equal(t, tt.more, list.More, errTag)
|
2018-12-03 14:38:03 +00:00
|
|
|
for i, item := range list.Items {
|
|
|
|
assert.Equal(t, tt.result[i], item.Path, errTag)
|
|
|
|
assert.Equal(t, TestBucket, item.Bucket.Name, errTag)
|
2019-07-03 19:07:44 +01:00
|
|
|
assert.Equal(t, storj.EncNull, item.Bucket.PathCipher, errTag)
|
2018-12-03 14:38:03 +00:00
|
|
|
}
|
2018-11-15 15:31:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
func options(prefix, cursor string, direction storj.ListDirection, limit int) storj.ListOptions {
|
|
|
|
return storj.ListOptions{
|
|
|
|
Prefix: prefix,
|
|
|
|
Cursor: cursor,
|
|
|
|
Direction: direction,
|
|
|
|
Limit: limit,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func optionsRecursive(prefix, cursor string, direction storj.ListDirection, limit int) storj.ListOptions {
|
|
|
|
return storj.ListOptions{
|
|
|
|
Prefix: prefix,
|
|
|
|
Cursor: cursor,
|
|
|
|
Direction: direction,
|
|
|
|
Limit: limit,
|
|
|
|
Recursive: true,
|
|
|
|
}
|
|
|
|
}
|