From a700a1bdab2f188f1eb331cd534d488a83f76366 Mon Sep 17 00:00:00 2001 From: Egon Elbre Date: Fri, 22 Jan 2021 19:34:08 +0200 Subject: [PATCH] satellite/metainfo/metabase: add benchmark Change-Id: I4289aac252f9c951548444aa5a82e007e9f47806 --- Jenkinsfile.public | 2 +- go.mod | 1 + go.sum | 2 + satellite/metainfo/metabase/bench_test.go | 314 ++++++++++++++++++++++ satellite/metainfo/metabase/db_test.go | 48 +++- satellite/metainfo/metabase/test_test.go | 58 ++-- 6 files changed, 388 insertions(+), 37 deletions(-) create mode 100644 satellite/metainfo/metabase/bench_test.go diff --git a/Jenkinsfile.public b/Jenkinsfile.public index 1ce0093a2..7c51f2b27 100644 --- a/Jenkinsfile.public +++ b/Jenkinsfile.public @@ -114,10 +114,10 @@ pipeline { environment { STORJ_TEST_COCKROACH = 'cockroach://root@localhost:26256/benchcockroach?sslmode=disable' STORJ_TEST_POSTGRES = 'postgres://postgres@localhost/benchstorj?sslmode=disable' + STORJ_TEST_DATABASES = 'crdb|pgx|cockroach://root@localhost:26256/benchcockroach?sslmode=disable;pg|pgx|postgres://postgres@localhost/benchstorj?sslmode=disable' } steps { sh 'cockroach sql --insecure --host=localhost:26256 -e \'create database benchcockroach;\'' - sh 'psql -U postgres -c \'create database benchstorj;\'' sh 'go test -parallel 1 -p 1 -vet=off -timeout 20m -short -run XYZXYZXYZXYZ -bench . -benchtime 1x ./...' } diff --git a/go.mod b/go.mod index 402ba7e5e..07187a7be 100644 --- a/go.mod +++ b/go.mod @@ -24,6 +24,7 @@ require ( github.com/jackc/pgx/v4 v4.9.0 github.com/jinzhu/now v1.1.1 github.com/jtolds/monkit-hw/v2 v2.0.0-20191108235325-141a0da276b3 + github.com/loov/hrtime v1.0.3 github.com/mattn/go-sqlite3 v2.0.3+incompatible github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 diff --git a/go.sum b/go.sum index cabb6a23f..59da70376 100644 --- a/go.sum +++ b/go.sum @@ -346,6 +346,8 @@ github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU= github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/loov/hrtime v1.0.3 h1:LiWKU3B9skJwRPUf0Urs9+0+OE3TxdMuiRPOTwR0gcU= +github.com/loov/hrtime v1.0.3/go.mod h1:yDY3Pwv2izeY4sq7YcPX/dtLwzg5NU1AxWuWxKwd0p0= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= diff --git a/satellite/metainfo/metabase/bench_test.go b/satellite/metainfo/metabase/bench_test.go new file mode 100644 index 000000000..332bba305 --- /dev/null +++ b/satellite/metainfo/metabase/bench_test.go @@ -0,0 +1,314 @@ +// Copyright (C) 2021 Storj Labs, Inc. +// See LICENSE for copying information. + +package metabase_test + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/loov/hrtime" + "github.com/stretchr/testify/require" + + "storj.io/common/memory" + "storj.io/common/storj" + "storj.io/common/testcontext" + "storj.io/common/testrand" + "storj.io/common/uuid" + "storj.io/storj/satellite/metainfo/metabase" +) + +func Benchmark(b *testing.B) { + if testing.Short() { + scenario{projects: 1, objects: 1, parts: 1, segments: 2}.Run(b) + return + } + scenario{projects: 2, objects: 50, parts: 2, segments: 5}.Run(b) +} + +type scenario struct { + projects int + objects int + parts int + segments int + + // info filled in during execution. + redundancy storj.RedundancyScheme + projectID []uuid.UUID + objectStream []metabase.ObjectStream +} + +// Run runs the scenario as a subtest. +func (s scenario) Run(b *testing.B) { + b.Run(s.name(), func(b *testing.B) { Bench(b, s.run) }) +} + +// name returns the scenario arguments as a string. +func (s *scenario) name() string { + return fmt.Sprintf("projects=%d,objects=%d,parts=%d,segments=%d", s.projects, s.objects, s.parts, s.segments) +} + +// run runs the specified scenario. +// +// nolint: scopelint // This heavily uses loop variables without goroutines, avoiding these would add lots of boilerplate. +func (s *scenario) run(ctx *testcontext.Context, b *testing.B, db *metabase.DB) { + if s.redundancy.IsZero() { + s.redundancy = storj.RedundancyScheme{ + Algorithm: storj.ReedSolomon, + RequiredShares: 29, + RepairShares: 50, + OptimalShares: 85, + TotalShares: 90, + ShareSize: 256, + } + } + for i := 0; i < s.projects; i++ { + s.projectID = append(s.projectID, testrand.UUID()) + } + + b.Run("Upload", func(b *testing.B) { + totalUpload := make(Metrics, 0, b.N*s.projects*s.objects) + beginObject := make(Metrics, 0, b.N*s.projects*s.objects) + beginSegment := make(Metrics, 0, b.N*s.projects*s.objects) + commitRemoteSegment := make(Metrics, 0, b.N*s.projects*s.objects*s.parts*(s.segments-1)) + commitInlineSegment := make(Metrics, 0, b.N*s.projects*s.objects*s.parts*1) + commitObject := make(Metrics, 0, b.N*s.projects*s.objects) + + defer totalUpload.Report(b, "ns/upl") + defer beginObject.Report(b, "ns/bobj") + defer beginSegment.Report(b, "ns/bseg") + defer commitRemoteSegment.Report(b, "ns/crem") + defer commitInlineSegment.Report(b, "ns/cinl") + defer commitObject.Report(b, "ns/cobj") + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + // wipe data so we can do the exact same test + b.StopTimer() + DeleteAll{}.Check(ctx, b, db) + b.StartTimer() + + s.objectStream = nil + for _, projectID := range s.projectID { + for objectIndex := 0; objectIndex < s.objects; objectIndex++ { + objectStream := metabase.ObjectStream{ + ProjectID: projectID, + BucketName: "bucket", + ObjectKey: metabase.ObjectKey(testrand.Path() + "/" + testrand.UUID().String()), + Version: 1, + StreamID: testrand.UUID(), + } + s.objectStream = append(s.objectStream, objectStream) + + totalUpload.Record(func() { + beginObject.Record(func() { + _, err := db.BeginObjectExactVersion(ctx, metabase.BeginObjectExactVersion{ + ObjectStream: objectStream, + Encryption: storj.EncryptionParameters{ + CipherSuite: storj.EncAESGCM, + BlockSize: 256, + }, + }) + require.NoError(b, err) + }) + + for part := 0; part < s.parts; part++ { + for segment := 0; segment < s.segments-1; segment++ { + rootPieceID := testrand.PieceID() + pieces := randPieces(int(s.redundancy.OptimalShares)) + + beginSegment.Record(func() { + err := db.BeginSegment(ctx, metabase.BeginSegment{ + ObjectStream: objectStream, + Position: metabase.SegmentPosition{ + Part: uint32(part), + Index: uint32(segment), + }, + RootPieceID: rootPieceID, + Pieces: pieces, + }) + require.NoError(b, err) + }) + + segmentSize := testrand.Intn(64*memory.MiB.Int()) + 1 + encryptedKey := testrand.BytesInt(storj.KeySize) + encryptedKeyNonce := testrand.BytesInt(storj.NonceSize) + + commitRemoteSegment.Record(func() { + err := db.CommitSegment(ctx, metabase.CommitSegment{ + ObjectStream: objectStream, + Position: metabase.SegmentPosition{ + Part: uint32(part), + Index: uint32(segment), + }, + EncryptedKey: encryptedKey, + EncryptedKeyNonce: encryptedKeyNonce, + PlainSize: int32(segmentSize), + EncryptedSize: int32(segmentSize), + RootPieceID: rootPieceID, + Pieces: pieces, + Redundancy: s.redundancy, + }) + require.NoError(b, err) + }) + } + + segmentSize := testrand.Intn(4*memory.KiB.Int()) + 1 + inlineData := testrand.BytesInt(segmentSize) + encryptedKey := testrand.BytesInt(storj.KeySize) + encryptedKeyNonce := testrand.BytesInt(storj.NonceSize) + + commitInlineSegment.Record(func() { + err := db.CommitInlineSegment(ctx, metabase.CommitInlineSegment{ + ObjectStream: objectStream, + Position: metabase.SegmentPosition{ + Part: uint32(part), + Index: uint32(s.segments - 1), + }, + InlineData: inlineData, + EncryptedKey: encryptedKey, + EncryptedKeyNonce: encryptedKeyNonce, + PlainSize: int32(segmentSize), + }) + require.NoError(b, err) + }) + } + + commitObject.Record(func() { + _, err := db.CommitObject(ctx, metabase.CommitObject{ + ObjectStream: objectStream, + }) + require.NoError(b, err) + }) + }) + } + } + } + }) + + if len(s.objectStream) == 0 { + b.Fatal("no objects uploaded") + } + + b.Run("Iterate", func(b *testing.B) { + m := make(Metrics, 0, b.N*s.projects) + defer m.Report(b, "ns/proj") + + for i := 0; i < b.N; i++ { + for _, projectID := range s.projectID { + m.Record(func() { + err := db.IterateObjectsAllVersions(ctx, metabase.IterateObjects{ + ProjectID: projectID, + BucketName: "bucket", + }, func(ctx context.Context, it metabase.ObjectsIterator) error { + var entry metabase.ObjectEntry + for it.Next(ctx, &entry) { + } + return nil + }) + require.NoError(b, err) + }) + } + } + }) + + b.Run("ListSegments", func(b *testing.B) { + m := make(Metrics, 0, b.N*len(s.objectStream)) + defer m.Report(b, "ns/obj") + + for i := 0; i < b.N; i++ { + for _, object := range s.objectStream { + m.Record(func() { + var cursor metabase.SegmentPosition + for { + result, err := db.ListSegments(ctx, metabase.ListSegments{ + StreamID: object.StreamID, + Cursor: cursor, + }) + require.NoError(b, err) + if !result.More { + break + } + cursor = result.Segments[len(result.Segments)-1].Position + } + }) + } + } + }) + + b.Run("GetObjectLatestVersion", func(b *testing.B) { + m := make(Metrics, 0, b.N*len(s.objectStream)) + defer m.Report(b, "ns/obj") + + for i := 0; i < b.N; i++ { + for _, object := range s.objectStream { + m.Record(func() { + _, err := db.GetObjectLatestVersion(ctx, metabase.GetObjectLatestVersion{ + ObjectLocation: object.Location(), + }) + require.NoError(b, err) + }) + } + } + }) + + b.Run("GetSegmentByPosition", func(b *testing.B) { + m := make(Metrics, 0, b.N*len(s.objectStream)*s.parts*s.segments) + defer m.Report(b, "ns/seg") + + for i := 0; i < b.N; i++ { + for _, object := range s.objectStream { + for part := 0; part < s.parts; part++ { + for segment := 0; segment < s.segments; segment++ { + m.Record(func() { + _, err := db.GetSegmentByPosition(ctx, metabase.GetSegmentByPosition{ + StreamID: object.StreamID, + Position: metabase.SegmentPosition{ + Part: uint32(part), + Index: uint32(segment), + }, + }) + require.NoError(b, err) + }) + } + } + } + } + }) +} + +// Metrics records a set of time.Durations. +type Metrics []time.Duration + +// Record records a single value to the slice. +func (m *Metrics) Record(fn func()) { + start := hrtime.Now() + fn() + *m = append(*m, hrtime.Since(start)) +} + +// Report reports the metric with the specified name. +func (m *Metrics) Report(b *testing.B, name string) { + hist := hrtime.NewDurationHistogram(*m, &hrtime.HistogramOptions{ + BinCount: 1, + NiceRange: true, + ClampMaximum: 0, + ClampPercentile: 0.999, + }) + b.ReportMetric(hist.P50, name) +} + +// randPieces returns randomized pieces. +func randPieces(count int) metabase.Pieces { + pieces := make(metabase.Pieces, count) + for i := range pieces { + pieces[i] = metabase.Piece{ + Number: uint16(i), + StorageNode: testrand.NodeID(), + } + } + return pieces +} diff --git a/satellite/metainfo/metabase/db_test.go b/satellite/metainfo/metabase/db_test.go index 85409f449..d1222a8c4 100644 --- a/satellite/metainfo/metabase/db_test.go +++ b/satellite/metainfo/metabase/db_test.go @@ -20,13 +20,13 @@ import ( var databases = flag.String("databases", os.Getenv("STORJ_TEST_DATABASES"), "databases to use for testing") -func All(t *testing.T, fn func(ctx *testcontext.Context, t *testing.T, db *metabase.DB)) { - type dbinfo struct { - name string - driver string - connstr string - } +type dbinfo struct { + name string + driver string + connstr string +} +func databaseInfos() []dbinfo { infos := []dbinfo{ {"pg", "pgx", "postgres://storj:storj-pass@localhost/metabase?sslmode=disable"}, {"crdb", "pgx", "cockroach://root@localhost:26257/metabase?sslmode=disable"}, @@ -38,8 +38,11 @@ func All(t *testing.T, fn func(ctx *testcontext.Context, t *testing.T, db *metab infos = append(infos, dbinfo{toks[0], toks[1], toks[2]}) } } + return infos +} - for _, info := range infos { +func All(t *testing.T, fn func(ctx *testcontext.Context, t *testing.T, db *metabase.DB)) { + for _, info := range databaseInfos() { info := info t.Run(info.name, func(t *testing.T) { t.Parallel() @@ -70,6 +73,37 @@ func All(t *testing.T, fn func(ctx *testcontext.Context, t *testing.T, db *metab } } +func Bench(b *testing.B, fn func(ctx *testcontext.Context, b *testing.B, db *metabase.DB)) { + for _, info := range databaseInfos() { + info := info + b.Run(info.name, func(b *testing.B) { + ctx := testcontext.New(b) + defer ctx.Cleanup() + + db, err := satellitedbtest.CreateMetabaseDB(ctx, zaptest.NewLogger(b), b.Name(), "M", 0, satellitedbtest.Database{ + Name: info.name, + URL: info.connstr, + Message: "", + }) + if err != nil { + b.Fatal(err) + } + defer func() { + if err := db.Close(); err != nil { + b.Error(err) + } + }() + + if err := db.MigrateToLatest(ctx); err != nil { + b.Fatal(err) + } + + b.ResetTimer() + fn(ctx, b, db.InternalImplementation().(*metabase.DB)) + }) + } +} + func TestSetup(t *testing.T) { All(t, func(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { err := db.Ping(ctx) diff --git a/satellite/metainfo/metabase/test_test.go b/satellite/metainfo/metabase/test_test.go index bde8f6cc5..10f07034e 100644 --- a/satellite/metainfo/metabase/test_test.go +++ b/satellite/metainfo/metabase/test_test.go @@ -28,7 +28,7 @@ type BeginObjectNextVersion struct { ErrText string } -func (step BeginObjectNextVersion) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step BeginObjectNextVersion) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { got, err := db.BeginObjectNextVersion(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) require.Equal(t, step.Version, got) @@ -41,7 +41,7 @@ type BeginObjectExactVersion struct { ErrText string } -func (step BeginObjectExactVersion) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step BeginObjectExactVersion) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { got, err := db.BeginObjectExactVersion(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) if step.ErrClass == nil { @@ -60,7 +60,7 @@ type CommitObject struct { ErrText string } -func (step CommitObject) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) metabase.Object { +func (step CommitObject) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) metabase.Object { object, err := db.CommitObject(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) if err == nil { @@ -76,7 +76,7 @@ type CommitObjectWithSegments struct { ErrText string } -func (step CommitObjectWithSegments) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) metabase.Object { +func (step CommitObjectWithSegments) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) metabase.Object { object, deleted, err := db.CommitObjectWithSegments(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) if err == nil { @@ -92,7 +92,7 @@ type BeginSegment struct { ErrText string } -func (step BeginSegment) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step BeginSegment) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { err := db.BeginSegment(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) } @@ -103,7 +103,7 @@ type CommitSegment struct { ErrText string } -func (step CommitSegment) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step CommitSegment) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { err := db.CommitSegment(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) } @@ -114,7 +114,7 @@ type CommitInlineSegment struct { ErrText string } -func (step CommitInlineSegment) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step CommitInlineSegment) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { err := db.CommitInlineSegment(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) } @@ -126,7 +126,7 @@ type DeleteBucketObjects struct { ErrText string } -func (step DeleteBucketObjects) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step DeleteBucketObjects) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { deleted, err := db.DeleteBucketObjects(ctx, step.Opts) require.Equal(t, step.Deleted, deleted) checkError(t, err, step.ErrClass, step.ErrText) @@ -138,7 +138,7 @@ type UpdateObjectMetadata struct { ErrText string } -func (step UpdateObjectMetadata) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step UpdateObjectMetadata) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { err := db.UpdateObjectMetadata(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) } @@ -149,7 +149,7 @@ type UpdateSegmentPieces struct { ErrText string } -func (step UpdateSegmentPieces) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step UpdateSegmentPieces) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { err := db.UpdateSegmentPieces(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) } @@ -161,7 +161,7 @@ type GetObjectExactVersion struct { ErrText string } -func (step GetObjectExactVersion) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step GetObjectExactVersion) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { result, err := db.GetObjectExactVersion(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) @@ -176,7 +176,7 @@ type GetObjectLatestVersion struct { ErrText string } -func (step GetObjectLatestVersion) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step GetObjectLatestVersion) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { result, err := db.GetObjectLatestVersion(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) @@ -191,7 +191,7 @@ type GetSegmentByPosition struct { ErrText string } -func (step GetSegmentByPosition) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step GetSegmentByPosition) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { result, err := db.GetSegmentByPosition(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) @@ -206,7 +206,7 @@ type GetLatestObjectLastSegment struct { ErrText string } -func (step GetLatestObjectLastSegment) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step GetLatestObjectLastSegment) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { result, err := db.GetLatestObjectLastSegment(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) @@ -221,7 +221,7 @@ type GetSegmentByOffset struct { ErrText string } -func (step GetSegmentByOffset) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step GetSegmentByOffset) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { result, err := db.GetSegmentByOffset(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) @@ -236,7 +236,7 @@ type BucketEmpty struct { ErrText string } -func (step BucketEmpty) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step BucketEmpty) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { result, err := db.BucketEmpty(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) @@ -250,7 +250,7 @@ type ListSegments struct { ErrText string } -func (step ListSegments) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step ListSegments) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { result, err := db.ListSegments(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) @@ -265,7 +265,7 @@ type DeleteObjectExactVersion struct { ErrText string } -func (step DeleteObjectExactVersion) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step DeleteObjectExactVersion) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { result, err := db.DeleteObjectExactVersion(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) @@ -280,7 +280,7 @@ type DeletePendingObject struct { ErrText string } -func (step DeletePendingObject) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step DeletePendingObject) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { result, err := db.DeletePendingObject(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) @@ -295,7 +295,7 @@ type DeleteObjectLatestVersion struct { ErrText string } -func (step DeleteObjectLatestVersion) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step DeleteObjectLatestVersion) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { result, err := db.DeleteObjectLatestVersion(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) @@ -310,7 +310,7 @@ type DeleteObjectAnyStatusAllVersions struct { ErrText string } -func (step DeleteObjectAnyStatusAllVersions) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step DeleteObjectAnyStatusAllVersions) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { result, err := db.DeleteObjectAnyStatusAllVersions(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) @@ -325,7 +325,7 @@ type DeleteObjectsAllVersions struct { ErrText string } -func (step DeleteObjectsAllVersions) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step DeleteObjectsAllVersions) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { result, err := db.DeleteObjectsAllVersions(ctx, step.Opts) checkError(t, err, step.ErrClass, step.ErrText) @@ -341,7 +341,7 @@ type DeleteExpiredObjects struct { ErrText string } -func (step DeleteExpiredObjects) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step DeleteExpiredObjects) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { err := db.DeleteExpiredObjects(ctx, time.Now()) checkError(t, err, step.ErrClass, step.ErrText) } @@ -365,7 +365,7 @@ type IterateObjects struct { ErrText string } -func (step IterateObjects) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step IterateObjects) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { var collector IterateCollector err := db.IterateObjectsAllVersions(ctx, step.Opts, collector.Add) @@ -387,7 +387,7 @@ type IterateObjectsWithStatus struct { ErrText string } -func (step IterateObjectsWithStatus) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step IterateObjectsWithStatus) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { var result IterateCollector err := db.IterateObjectsAllVersionsWithStatus(ctx, step.Opts, result.Add) @@ -397,7 +397,7 @@ func (step IterateObjectsWithStatus) Check(ctx *testcontext.Context, t *testing. require.Zero(t, diff) } -func checkError(t *testing.T, err error, errClass *errs.Class, errText string) { +func checkError(t testing.TB, err error, errClass *errs.Class, errText string) { if errClass != nil { require.True(t, errClass.Has(err), "expected an error %v got %v", *errClass, err) } @@ -429,14 +429,14 @@ func sortRawSegments(segments []metabase.RawSegment) { type DeleteAll struct{} -func (step DeleteAll) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step DeleteAll) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { err := db.TestingDeleteAll(ctx) require.NoError(t, err) } type Verify metabase.RawState -func (step Verify) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) { +func (step Verify) Check(ctx *testcontext.Context, t testing.TB, db *metabase.DB) { state, err := db.TestingGetState(ctx) require.NoError(t, err) @@ -456,7 +456,7 @@ type CreateTestObject struct { // TODO add BeginSegment, CommitSegment } -func (co CreateTestObject) Run(ctx *testcontext.Context, t *testing.T, db *metabase.DB, obj metabase.ObjectStream, numberOfSegments byte) metabase.Object { +func (co CreateTestObject) Run(ctx *testcontext.Context, t testing.TB, db *metabase.DB, obj metabase.ObjectStream, numberOfSegments byte) metabase.Object { boeOpts := metabase.BeginObjectExactVersion{ ObjectStream: obj, Encryption: defaultTestEncryption,