3146ad7f2e
Previously we were exposing the testing facilities via interface casting the necessary parts, however, when things are not part of the main satellite.DB interface they need to be manually propagated. Rather than relying on using hidden methods lets expose things as long as they don't create a direct dependency to the database driver. Change-Id: I2eb7d8b60f4b64de1320c2d32581f7be267c0f57
184 lines
5.2 KiB
Go
184 lines
5.2 KiB
Go
// Copyright (C) 2019 Storj Labs, Inc.
|
|
// See LICENSE for copying information
|
|
|
|
package testplanet
|
|
|
|
import (
|
|
"context"
|
|
"runtime/pprof"
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"go.uber.org/zap"
|
|
|
|
"storj.io/common/context2"
|
|
"storj.io/common/grant"
|
|
"storj.io/common/storj"
|
|
"storj.io/common/testcontext"
|
|
"storj.io/private/dbutil"
|
|
"storj.io/private/dbutil/pgtest"
|
|
"storj.io/private/dbutil/pgutil"
|
|
"storj.io/private/tagsql"
|
|
"storj.io/storj/private/testmonkit"
|
|
"storj.io/storj/satellite/satellitedb/satellitedbtest"
|
|
"storj.io/uplink"
|
|
)
|
|
|
|
// Run runs testplanet in multiple configurations.
|
|
func Run(t *testing.T, config Config, test func(t *testing.T, ctx *testcontext.Context, planet *Planet)) {
|
|
databases := satellitedbtest.Databases()
|
|
if len(databases) == 0 {
|
|
t.Fatal("Databases flag missing, set at least one:\n" +
|
|
"-postgres-test-db=" + pgtest.DefaultPostgres + "\n" +
|
|
"-cockroach-test-db=" + pgtest.DefaultCockroach)
|
|
}
|
|
|
|
for _, satelliteDB := range databases {
|
|
satelliteDB := satelliteDB
|
|
t.Run(satelliteDB.Name, func(t *testing.T) {
|
|
parallel := !config.NonParallel
|
|
if parallel {
|
|
t.Parallel()
|
|
}
|
|
|
|
if satelliteDB.MasterDB.URL == "" {
|
|
t.Skipf("Database %s connection string not provided. %s", satelliteDB.MasterDB.Name, satelliteDB.MasterDB.Message)
|
|
}
|
|
planetConfig := config
|
|
if planetConfig.Name == "" {
|
|
planetConfig.Name = t.Name()
|
|
}
|
|
|
|
log := NewLogger(t)
|
|
|
|
testmonkit.Run(context.Background(), t, func(parent context.Context) {
|
|
defer pprof.SetGoroutineLabels(parent)
|
|
parent = pprof.WithLabels(parent, pprof.Labels("test", t.Name()))
|
|
|
|
timeout := config.Timeout
|
|
if timeout == 0 {
|
|
timeout = testcontext.DefaultTimeout
|
|
}
|
|
ctx := testcontext.NewWithContextAndTimeout(parent, t, timeout)
|
|
defer ctx.Cleanup()
|
|
|
|
planetConfig.applicationName = "testplanet" + pgutil.CreateRandomTestingSchemaName(6)
|
|
planet, err := NewCustom(ctx, log, planetConfig, satelliteDB)
|
|
if err != nil {
|
|
t.Fatalf("%+v", err)
|
|
}
|
|
defer ctx.Check(planet.Shutdown)
|
|
|
|
planet.Start(ctx)
|
|
provisionUplinks(ctx, t, planet)
|
|
|
|
var rawDB tagsql.DB
|
|
var queriesBefore []string
|
|
if len(planet.Satellites) > 0 && satelliteDB.Name == "Cockroach" {
|
|
rawDB = planet.Satellites[0].DB.Testing().RawDB()
|
|
|
|
var err error
|
|
queriesBefore, err = satellitedbtest.FullTableScanQueries(ctx, rawDB, dbutil.Cockroach, planetConfig.applicationName)
|
|
if err != nil {
|
|
t.Fatalf("%+v", err)
|
|
}
|
|
}
|
|
|
|
test(t, ctx, planet)
|
|
|
|
if rawDB != nil {
|
|
queriesAfter, err := satellitedbtest.FullTableScanQueries(context2.WithoutCancellation(ctx), rawDB, dbutil.Cockroach, planetConfig.applicationName)
|
|
if err != nil {
|
|
t.Fatalf("%+v", err)
|
|
}
|
|
|
|
diff := cmp.Diff(queriesBefore, queriesAfter)
|
|
if diff != "" {
|
|
log.Sugar().Warnf("FULL TABLE SCAN DETECTED\n%s", diff)
|
|
}
|
|
}
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
// Bench makes benchmark with testplanet as easy as running unit tests with Run method.
|
|
func Bench(b *testing.B, config Config, bench func(b *testing.B, ctx *testcontext.Context, planet *Planet)) {
|
|
databases := satellitedbtest.Databases()
|
|
if len(databases) == 0 {
|
|
b.Fatal("Databases flag missing, set at least one:\n" +
|
|
"-postgres-test-db=" + pgtest.DefaultPostgres + "\n" +
|
|
"-cockroach-test-db=" + pgtest.DefaultCockroach)
|
|
}
|
|
|
|
for _, satelliteDB := range databases {
|
|
satelliteDB := satelliteDB
|
|
b.Run(satelliteDB.Name, func(b *testing.B) {
|
|
if satelliteDB.MasterDB.URL == "" {
|
|
b.Skipf("Database %s connection string not provided. %s", satelliteDB.MasterDB.Name, satelliteDB.MasterDB.Message)
|
|
}
|
|
|
|
log := zap.NewNop()
|
|
|
|
planetConfig := config
|
|
if planetConfig.Name == "" {
|
|
planetConfig.Name = b.Name()
|
|
}
|
|
|
|
testmonkit.Run(context.Background(), b, func(parent context.Context) {
|
|
defer pprof.SetGoroutineLabels(parent)
|
|
parent = pprof.WithLabels(parent, pprof.Labels("test", b.Name()))
|
|
|
|
timeout := config.Timeout
|
|
if timeout == 0 {
|
|
timeout = testcontext.DefaultTimeout
|
|
}
|
|
ctx := testcontext.NewWithContextAndTimeout(parent, b, timeout)
|
|
defer ctx.Cleanup()
|
|
|
|
planetConfig.applicationName = "testplanet-bench"
|
|
planet, err := NewCustom(ctx, log, planetConfig, satelliteDB)
|
|
if err != nil {
|
|
b.Fatalf("%+v", err)
|
|
}
|
|
defer ctx.Check(planet.Shutdown)
|
|
|
|
planet.Start(ctx)
|
|
provisionUplinks(ctx, b, planet)
|
|
|
|
bench(b, ctx, planet)
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
func provisionUplinks(ctx context.Context, t testing.TB, planet *Planet) {
|
|
for _, planetUplink := range planet.Uplinks {
|
|
for _, satellite := range planet.Satellites {
|
|
apiKey := planetUplink.APIKey[satellite.ID()]
|
|
|
|
// create access grant manually to avoid dialing satellite for
|
|
// project id and deriving key with argon2.IDKey method
|
|
encAccess := grant.NewEncryptionAccessWithDefaultKey(&storj.Key{})
|
|
encAccess.SetDefaultPathCipher(storj.EncAESGCM)
|
|
|
|
grantAccess := grant.Access{
|
|
SatelliteAddress: satellite.URL(),
|
|
APIKey: apiKey,
|
|
EncAccess: encAccess,
|
|
}
|
|
|
|
serializedAccess, err := grantAccess.Serialize()
|
|
if err != nil {
|
|
t.Fatalf("%+v", err)
|
|
}
|
|
access, err := uplink.ParseAccess(serializedAccess)
|
|
if err != nil {
|
|
t.Fatalf("%+v", err)
|
|
}
|
|
|
|
planetUplink.Access[satellite.ID()] = access
|
|
}
|
|
}
|
|
}
|