package engine import ( "context" "path/filepath" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore" 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" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" ) type epochState struct { currEpoch uint64 } func (s epochState) CurrentEpoch() uint64 { return s.currEpoch } type testEngineWrapper struct { engine *StorageEngine shards []*shard.Shard shardIDs []*shard.ID } func testNewEngine(t testing.TB, opts ...Option) *testEngineWrapper { opts = append(testGetDefaultEngineOptions(t), opts...) return &testEngineWrapper{engine: New(opts...)} } func (te *testEngineWrapper) setShardsNum(t testing.TB, num int) *testEngineWrapper { return te.setShardsNumOpts(t, num, func(_ int) []shard.Option { return testGetDefaultShardOptions(t) }) } func (te *testEngineWrapper) setShardsNumOpts( t testing.TB, num int, shardOpts func(id int) []shard.Option, ) *testEngineWrapper { te.shards = make([]*shard.Shard, num) te.shardIDs = make([]*shard.ID, num) for i := range num { shard, err := te.engine.createShard(context.Background(), shardOpts(i)) require.NoError(t, err) require.NoError(t, te.engine.addShard(shard)) te.shards[i] = shard te.shardIDs[i] = shard.ID() } require.Len(t, te.engine.shards, num) require.Len(t, te.engine.shardPools, num) return te } func (te *testEngineWrapper) setShardsNumAdditionalOpts( t testing.TB, num int, shardOpts func(id int) []shard.Option, ) *testEngineWrapper { return te.setShardsNumOpts(t, num, func(id int) []shard.Option { return append(testGetDefaultShardOptions(t), shardOpts(id)...) }) } // prepare calls Open and Init on the created engine. func (te *testEngineWrapper) prepare(t testing.TB) *testEngineWrapper { require.NoError(t, te.engine.Open(context.Background())) require.NoError(t, te.engine.Init(context.Background())) return te } func testGetDefaultEngineOptions(t testing.TB) []Option { return []Option{ WithLogger(test.NewLogger(t)), } } func testGetDefaultShardOptions(t testing.TB) []shard.Option { return []shard.Option{ shard.WithLogger(test.NewLogger(t)), shard.WithBlobStorOptions( blobstor.WithStorages( newStorages(t, t.TempDir(), 1<<20)), blobstor.WithLogger(test.NewLogger(t)), ), shard.WithPiloramaOptions(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama"))), shard.WithMetaBaseOptions(testGetDefaultMetabaseOptions(t)...), } } func testGetDefaultMetabaseOptions(t testing.TB) []meta.Option { return []meta.Option{ meta.WithPath(filepath.Join(t.TempDir(), "metabase")), meta.WithPermissions(0o700), meta.WithEpochState(epochState{}), meta.WithLogger(test.NewLogger(t)), } } func newStorages(t testing.TB, root string, smallSize uint64) []blobstor.SubStorage { return []blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( context.Background(), blobovniczatree.WithRootPath(filepath.Join(root, "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1), blobovniczatree.WithPermissions(0o700), blobovniczatree.WithLogger(test.NewLogger(t))), Policy: func(_ *objectSDK.Object, data []byte) bool { return uint64(len(data)) < smallSize }, }, { Storage: fstree.New( fstree.WithPath(root), fstree.WithDepth(1), fstree.WithLogger(test.NewLogger(t))), }, } } func newTestStorages(root string, smallSize uint64) ([]blobstor.SubStorage, *teststore.TestStore, *teststore.TestStore) { smallFileStorage := teststore.New( teststore.WithSubstorage(blobovniczatree.NewBlobovniczaTree( context.Background(), blobovniczatree.WithRootPath(filepath.Join(root, "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1), blobovniczatree.WithPermissions(0o700)), )) largeFileStorage := teststore.New( teststore.WithSubstorage(fstree.New( fstree.WithPath(root), fstree.WithDepth(1)), )) return []blobstor.SubStorage{ { Storage: smallFileStorage, Policy: func(_ *objectSDK.Object, data []byte) bool { return uint64(len(data)) < smallSize }, }, { Storage: largeFileStorage, }, }, smallFileStorage, largeFileStorage }