Skip to content

Commit 86b9554

Browse files
committed
chore: use testcontainers for crdb
1 parent fbe233e commit 86b9554

7 files changed

Lines changed: 167 additions & 327 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
max_connections = 3000
2+
track_commit_timestamp = 1
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
max_connections = 3000

internal/testserver/datastore/crdb.go

Lines changed: 8 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,14 @@ package datastore
22

33
import (
44
"context"
5-
"fmt"
65
"testing"
76

8-
"github.com/google/uuid"
97
"github.com/stretchr/testify/require"
10-
"github.com/testcontainers/testcontainers-go"
118
"github.com/testcontainers/testcontainers-go/modules/cockroachdb"
129

1310
crdbmigrations "github.com/authzed/spicedb/internal/datastore/crdb/migrations"
1411
"github.com/authzed/spicedb/pkg/datastore"
1512
"github.com/authzed/spicedb/pkg/migrate"
16-
"github.com/authzed/spicedb/pkg/secrets"
1713
)
1814

1915
// crdbTester is safe for concurrent use by tests.
@@ -24,73 +20,28 @@ type crdbTester struct {
2420
var _ RunningEngineForTest = (*crdbTester)(nil)
2521

2622
// RunCRDBForTesting returns a RunningEngineForTest for CRDB
27-
func RunCRDBForTesting(t testing.TB, bridgeNetworkName string, crdbVersion string) *crdbTester {
28-
ctx := context.Background()
29-
name := "crds-" + uuid.New().String()
23+
func RunCRDBForTesting(t testing.TB, crdbVersion string) *crdbTester {
24+
ctx := t.Context()
3025

31-
containerReq := testcontainers.ContainerRequest{
32-
Name: name,
33-
Cmd: []string{"--insecure", "--max-offset=50ms"},
34-
}
35-
36-
if bridgeNetworkName != "" {
37-
containerReq.Networks = []string{bridgeNetworkName}
38-
}
39-
40-
opts := []testcontainers.ContainerCustomizer{
26+
container, err := cockroachdb.Run(ctx, "mirror.gcr.io/cockroachdb/cockroach:v"+crdbVersion,
4127
cockroachdb.WithInsecure(),
42-
testcontainers.CustomizeRequest(testcontainers.GenericContainerRequest{
43-
ContainerRequest: containerReq,
44-
}),
45-
}
46-
47-
container, err := cockroachdb.Run(ctx, "mirror.gcr.io/cockroachdb/cockroach:v"+crdbVersion, opts...)
28+
)
4829
require.NoError(t, err)
4930

50-
t.Cleanup(func() {
51-
require.NoError(t, container.Terminate(ctx))
52-
})
53-
5431
// enable changefeeds
55-
code, _, _ := container.Exec(ctx, []string{
32+
code, _, err := container.Exec(ctx, []string{
5633
"cockroach", "sql",
5734
"--insecure",
5835
"-e", "SET CLUSTER SETTING kv.rangefeed.enabled = true;",
5936
})
60-
require.Equal(t, 0, code)
61-
62-
// create DB
63-
dbNameUniquePortion, err := secrets.TokenHex(4)
6437
require.NoError(t, err)
65-
66-
newDBName := "db" + dbNameUniquePortion
67-
code, _, _ = container.Exec(ctx, []string{
68-
"cockroach", "sql",
69-
"--insecure",
70-
"-e", "CREATE DATABASE " + newDBName + ";",
71-
})
7238
require.Equal(t, 0, code)
7339

74-
hostname := "localhost"
75-
creds := "root:fake"
76-
port := "26257"
77-
78-
if bridgeNetworkName != "" {
79-
hostname = name
80-
} else {
81-
mappedPort, err := container.MappedPort(ctx, "26257")
82-
require.NoError(t, err)
83-
port = mappedPort.Port()
84-
}
40+
connUri, err := container.ConnectionString(ctx)
41+
require.NoError(t, err)
8542

8643
return &crdbTester{
87-
databaseConnectStr: fmt.Sprintf(
88-
"postgres://%s@%s:%s/%s?sslmode=disable",
89-
creds,
90-
hostname,
91-
port,
92-
newDBName,
93-
),
44+
databaseConnectStr: connUri,
9445
}
9546
}
9647

@@ -101,8 +52,6 @@ func (r *crdbTester) NewDatabase(t testing.TB) string {
10152

10253
// NewDatastore creates a database and runs migrations on it.
10354
func (r *crdbTester) NewDatastore(t testing.TB, initFunc InitFunc) datastore.Datastore {
104-
t.Log("MAINE")
105-
t.Log(r.databaseConnectStr)
10655
connectStr := r.databaseConnectStr
10756

10857
migrationDriver, err := crdbmigrations.NewCRDBDriver(connectStr)

internal/testserver/datastore/datastore.go

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,33 +48,25 @@ type RunningEngineForTestWithEnvVars interface {
4848
// respectively. Note also that the backing database or service will be shutdown automatically via
4949
// the Cleanup of the testing object.
5050
func RunDatastoreEngine(t testing.TB, engine string) RunningEngineForTest {
51-
return RunDatastoreEngineWithBridge(t, engine, "")
52-
}
53-
54-
// RunDatastoreEngineWithBridge runs a datastore engine on a specific bridge. If a bridge is
55-
// specified, then the hostnames returned by the engines are those to be called from another
56-
// container on the bridge.
57-
func RunDatastoreEngineWithBridge(t testing.TB, engine string, bridgeNetworkName string) RunningEngineForTest {
5851
switch engine {
5952
case "memory":
60-
require.Empty(t, bridgeNetworkName, "memory datastore does not support bridge networking")
6153
return RunMemoryForTesting(t)
6254
case "cockroachdb":
6355
ver := os.Getenv("CRDB_TEST_VERSION")
6456
if ver == "" {
6557
ver = crdbversion.LatestTestedCockroachDBVersion
6658
}
67-
return RunCRDBForTesting(t, bridgeNetworkName, ver)
59+
return RunCRDBForTesting(t, ver)
6860
case "postgres":
6961
ver := os.Getenv("POSTGRES_TEST_VERSION")
7062
if ver == "" {
7163
ver = pgversion.LatestTestedPostgresVersion
7264
}
73-
return RunPostgresForTesting(t, bridgeNetworkName, migrate.Head, ver, false)
65+
return RunPostgresForTesting(t, migrate.Head, ver, false)
7466
case "mysql":
75-
return RunMySQLForTesting(t, bridgeNetworkName)
67+
return RunMySQLForTesting(t)
7668
case "spanner":
77-
return RunSpannerForTesting(t, bridgeNetworkName, migrate.Head)
69+
return RunSpannerForTesting(t, migrate.Head)
7870
default:
7971
t.Fatalf("found missing engine for RunDatastoreEngine: %s", engine)
8072
return nil

internal/testserver/datastore/mysql.go

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,20 @@ type MySQLTesterOptions struct {
4343

4444
// RunMySQLForTesting returns a RunningEngineForTest for the mysql driver
4545
// backed by a MySQL instance with RunningEngineForTest options - no prefix is added, and datastore migration is run.
46-
func RunMySQLForTesting(t testing.TB, bridgeNetworkName string) RunningEngineForTest {
47-
return RunMySQLForTestingWithOptions(t, MySQLTesterOptions{Prefix: "", MigrateForNewDatastore: true}, bridgeNetworkName)
46+
func RunMySQLForTesting(t testing.TB) RunningEngineForTest {
47+
return RunMySQLForTestingWithOptions(t, MySQLTesterOptions{Prefix: "", MigrateForNewDatastore: true})
4848
}
4949

5050
// RunMySQLForTestingWithOptions returns a RunningEngineForTest for the mysql driver
5151
// backed by a MySQL instance, while allowing options to be forwarded
52-
func RunMySQLForTestingWithOptions(t testing.TB, options MySQLTesterOptions, bridgeNetworkName string) RunningEngineForTest {
53-
ctx := context.Background()
52+
func RunMySQLForTestingWithOptions(t testing.TB, options MySQLTesterOptions) RunningEngineForTest {
53+
ctx := t.Context()
5454
containerImageTag := version.MinimumSupportedMySQLVersion
5555

56-
name := "mysql-" + uuid.New().String()
56+
// TODO: add wait behavior
57+
// TODO: simplify
5758

5859
req := testcontainers.ContainerRequest{
59-
Name: name,
6060
Image: "mirror.gcr.io/library/mysql:" + containerImageTag,
6161
ExposedPorts: []string{fmt.Sprintf("%d/tcp", mysqlPort)},
6262
Env: map[string]string{
@@ -68,10 +68,6 @@ func RunMySQLForTestingWithOptions(t testing.TB, options MySQLTesterOptions, bri
6868
WithStartupTimeout(dockerBootTimeout),
6969
}
7070

71-
if bridgeNetworkName != "" {
72-
req.Networks = []string{bridgeNetworkName}
73-
}
74-
7571
container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
7672
ContainerRequest: req,
7773
Started: true,
@@ -86,34 +82,12 @@ func RunMySQLForTestingWithOptions(t testing.TB, options MySQLTesterOptions, bri
8682
mappedPort, err := container.MappedPort(ctx, "3306")
8783
require.NoError(t, err)
8884

89-
if bridgeNetworkName != "" {
90-
builder.hostname = name
91-
builder.port = strconv.Itoa(mysqlPort)
92-
} else {
93-
builder.port = mappedPort.Port()
94-
}
85+
builder.port = mappedPort.Port()
9586

9687
dsn := fmt.Sprintf("%s@(localhost:%s)/mysql?parseTime=true", builder.creds, port)
9788
builder.db, err = sql.Open("mysql", dsn)
9889
require.NoError(t, err)
9990

100-
// TODO: use require.Eventually here
101-
require.NoError(t, pool.Retry(func() error {
102-
var err error
103-
ctx, cancelPing := context.WithTimeout(context.Background(), dockerBootTimeout)
104-
defer cancelPing()
105-
err = builder.db.PingContext(ctx)
106-
if err != nil {
107-
return err
108-
}
109-
time.Sleep(500 * time.Millisecond)
110-
}))
111-
112-
t.Cleanup(func() {
113-
require.NoError(t, builder.db.Close())
114-
require.NoError(t, container.Terminate(ctx))
115-
})
116-
11791
return builder
11892
}
11993

0 commit comments

Comments
 (0)