package engine import ( "context" "path/filepath" "sort" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" ) func sortAddresses(addrWithType []object.AddressWithType) []object.AddressWithType { sort.Slice(addrWithType, func(i, j int) bool { return addrWithType[i].Address.EncodeToString() < addrWithType[j].Address.EncodeToString() }) return addrWithType } func TestListWithCursor(t *testing.T) { t.Parallel() tests := []struct { name string shardNum int objectNum int batchSize uint32 }{ { name: "one shard, few objects, small batch size", shardNum: 1, objectNum: 2, batchSize: 1, }, { name: "one shard, many objects, big batch size", shardNum: 1, objectNum: 53, batchSize: 100, }, { name: "many shards, many objects, small batch size", shardNum: 6, objectNum: 66, batchSize: 1, }, { name: "many shards, many objects, big batch size", shardNum: 6, objectNum: 99, batchSize: 100, }, } for i := range tests { tt := tests[i] t.Run(tt.name, func(t *testing.T) { t.Parallel() e := testNewEngine(t).setShardsNumOpts(t, tt.shardNum, func(id int) []shard.Option { return []shard.Option{ shard.WithLogger(test.NewLogger(t, true)), shard.WithBlobStorOptions( blobstor.WithStorages( newStorages(t.TempDir(), 1<<20))), shard.WithPiloramaOptions(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama"))), shard.WithMetaBaseOptions( meta.WithPath(filepath.Join(t.TempDir(), "metabase")), meta.WithPermissions(0o700), meta.WithEpochState(epochState{}), ), } }).engine require.NoError(t, e.Open(context.Background())) require.NoError(t, e.Init(context.Background())) t.Cleanup(func() { e.Close(context.Background()) }) expected := make([]object.AddressWithType, 0, tt.objectNum) got := make([]object.AddressWithType, 0, tt.objectNum) for i := 0; i < tt.objectNum; i++ { containerID := cidtest.ID() obj := testutil.GenerateObjectWithCIDWithPayload(containerID, []byte{'a'}) var prm PutPrm prm.WithObject(obj) err := e.Put(context.Background(), prm) require.NoError(t, err) expected = append(expected, object.AddressWithType{Type: objectSDK.TypeRegular, Address: object.AddressOf(obj)}) } expected = sortAddresses(expected) var prm ListWithCursorPrm prm.count = tt.batchSize for { res, err := e.ListWithCursor(context.Background(), prm) if err == ErrEndOfListing { require.Empty(t, res.AddressList()) break } require.NotEmpty(t, res.AddressList()) got = append(got, res.AddressList()...) prm.cursor = res.Cursor() } got = sortAddresses(got) require.Equal(t, expected, got) }) } }