Skip to content

Commit 9e3bc1c

Browse files
Use testcontainers.
1 parent 941689f commit 9e3bc1c

File tree

1,293 files changed

+206213
-5239
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,293 files changed

+206213
-5239
lines changed

.github/workflows/ci.yml

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,23 @@
1-
21
name: CI
2+
33
on: [pull_request]
4+
45
jobs:
56
build:
7+
68
runs-on: ubuntu-latest
9+
710
steps:
8-
- name: Setup MySQL
9-
run: >-
10-
docker run --rm -d
11-
--name mysql
12-
-p 3306:3306
13-
--health-cmd="mysqladmin ping"
14-
--health-interval=10s
15-
--health-timeout=5s
16-
--health-retries=3
17-
mysql:8.0.39
18-
-e MYSQL_ROOT_PASSWORD=root
19-
-e MYSQL_DATABASE=test
20-
--log-bin=mysql-bin
21-
--binlog-format=row
22-
--gtid-mode=ON
23-
--enforce-gtid-consistency=ON
24-
--transaction-write-set-extraction=XXHASH64
25-
--binlog-transaction-dependency-tracking=WRITESET
2611
- uses: actions/checkout@v4
12+
2713
- name: Set up Go
2814
uses: actions/setup-go@v5
2915
with:
3016
go-version-file: go.mod
17+
3118
- name: Build
3219
run: script/cibuild
20+
3321
- name: Upload gh-ost binary artifact
3422
uses: actions/upload-artifact@v4
3523
with:

go.mod

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,64 @@ require (
88
github.com/go-sql-driver/mysql v1.8.1
99
github.com/google/uuid v1.6.0
1010
github.com/openark/golib v0.0.0-20210531070646-355f37940af8
11-
github.com/stretchr/testify v1.8.0
11+
github.com/stretchr/testify v1.9.0
12+
github.com/testcontainers/testcontainers-go v0.34.0
1213
golang.org/x/net v0.24.0
1314
golang.org/x/term v0.19.0
1415
golang.org/x/text v0.14.0
1516
)
1617

1718
require (
19+
dario.cat/mergo v1.0.0 // indirect
1820
filippo.io/edwards25519 v1.1.0 // indirect
21+
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
22+
github.com/Microsoft/go-winio v0.6.2 // indirect
23+
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
24+
github.com/containerd/containerd v1.7.18 // indirect
25+
github.com/containerd/log v0.1.0 // indirect
26+
github.com/containerd/platforms v0.2.1 // indirect
27+
github.com/cpuguy83/dockercfg v0.3.2 // indirect
1928
github.com/davecgh/go-spew v1.1.1 // indirect
29+
github.com/distribution/reference v0.6.0 // indirect
30+
github.com/docker/docker v27.1.1+incompatible // indirect
31+
github.com/docker/go-connections v0.5.0 // indirect
32+
github.com/docker/go-units v0.5.0 // indirect
33+
github.com/felixge/httpsnoop v1.0.4 // indirect
34+
github.com/go-logr/logr v1.4.1 // indirect
35+
github.com/go-logr/stdr v1.2.2 // indirect
36+
github.com/go-ole/go-ole v1.2.6 // indirect
37+
github.com/gogo/protobuf v1.3.2 // indirect
38+
github.com/klauspost/compress v1.17.4 // indirect
39+
github.com/kr/text v0.2.0 // indirect
40+
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
41+
github.com/magiconair/properties v1.8.7 // indirect
42+
github.com/moby/docker-image-spec v1.3.1 // indirect
43+
github.com/moby/patternmatcher v0.6.0 // indirect
44+
github.com/moby/sys/sequential v0.5.0 // indirect
45+
github.com/moby/sys/user v0.1.0 // indirect
46+
github.com/moby/term v0.5.0 // indirect
47+
github.com/morikuni/aec v1.0.0 // indirect
48+
github.com/opencontainers/go-digest v1.0.0 // indirect
49+
github.com/opencontainers/image-spec v1.1.0 // indirect
2050
github.com/pingcap/errors v0.11.5-0.20210425183316-da1aaba5fb63 // indirect
51+
github.com/pkg/errors v0.9.1 // indirect
2152
github.com/pmezard/go-difflib v1.0.0 // indirect
53+
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
54+
github.com/shirou/gopsutil/v3 v3.23.12 // indirect
55+
github.com/shoenig/go-m1cpu v0.1.6 // indirect
2256
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 // indirect
2357
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 // indirect
2458
github.com/siddontang/go-log v0.0.0-20180807004314-8d05993dda07 // indirect
59+
github.com/sirupsen/logrus v1.9.3 // indirect
60+
github.com/tklauser/go-sysconf v0.3.12 // indirect
61+
github.com/tklauser/numcpus v0.6.1 // indirect
62+
github.com/yusufpapurcu/wmi v1.2.3 // indirect
63+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
64+
go.opentelemetry.io/otel v1.24.0 // indirect
65+
go.opentelemetry.io/otel/metric v1.24.0 // indirect
66+
go.opentelemetry.io/otel/trace v1.24.0 // indirect
2567
go.uber.org/atomic v1.7.0 // indirect
26-
golang.org/x/sys v0.19.0 // indirect
68+
golang.org/x/crypto v0.22.0 // indirect
69+
golang.org/x/sys v0.21.0 // indirect
2770
gopkg.in/yaml.v3 v3.0.1 // indirect
2871
)

go.sum

Lines changed: 150 additions & 6 deletions
Large diffs are not rendered by default.

go/binlog/gomysql_reader_test.go

Lines changed: 90 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package binlog
22

33
import (
4+
"context"
45
"database/sql"
56
"testing"
67

78
"github.com/github/gh-ost/go/base"
89
"github.com/github/gh-ost/go/mysql"
910
"github.com/stretchr/testify/require"
10-
"golang.org/x/net/context"
11+
"github.com/stretchr/testify/suite"
12+
"github.com/testcontainers/testcontainers-go"
13+
"github.com/testcontainers/testcontainers-go/wait"
1114
)
1215

1316
func getCurrentBinlogCoordinates(t *testing.T, db *sql.DB) mysql.BinlogCoordinates {
@@ -24,11 +27,11 @@ func getCurrentBinlogCoordinates(t *testing.T, db *sql.DB) mysql.BinlogCoordinat
2427
return mysql.BinlogCoordinates{LogFile: file, LogPos: position}
2528
}
2629

27-
func getMigrationContext() *base.MigrationContext {
30+
func getMigrationContext(host string) *base.MigrationContext {
2831
migrationContext := base.NewMigrationContext()
2932
migrationContext.InspectorConnectionConfig = &mysql.ConnectionConfig{
3033
Key: mysql.InstanceKey{
31-
Hostname: "localhost",
34+
Hostname: host,
3235
Port: 3306,
3336
},
3437
User: "root",
@@ -40,29 +43,73 @@ func getMigrationContext() *base.MigrationContext {
4043
}
4144

4245
func prepareDatabase(t *testing.T, db *sql.DB) {
43-
_, err := db.Exec("DROP DATABASE test")
46+
_, err := db.Exec("CREATE TABLE test.gh_ost_test (id int NOT NULL AUTO_INCREMENT, name varchar(255), PRIMARY KEY (id)) ENGINE=InnoDB")
4447
require.NoError(t, err)
4548

46-
_, err = db.Exec("CREATE DATABASE test")
49+
_, err = db.Exec("CREATE TABLE test.gh_ost_test2 (id int NOT NULL AUTO_INCREMENT, name varchar(255), PRIMARY KEY (id)) ENGINE=InnoDB")
4750
require.NoError(t, err)
51+
}
4852

49-
_, err = db.Exec("CREATE TABLE test.gh_ost_test (id int NOT NULL AUTO_INCREMENT, name varchar(255), PRIMARY KEY (id)) ENGINE=InnoDB")
50-
require.NoError(t, err)
53+
type GoMySQLReaderTestSuite struct {
54+
suite.Suite
5155

52-
_, err = db.Exec("CREATE TABLE test.gh_ost_test2 (id int NOT NULL AUTO_INCREMENT, name varchar(255), PRIMARY KEY (id)) ENGINE=InnoDB")
53-
require.NoError(t, err)
56+
mysqlContainer testcontainers.Container
57+
}
58+
59+
func (suite *GoMySQLReaderTestSuite) SetupSuite() {
60+
ctx := context.Background()
61+
62+
req := testcontainers.ContainerRequest{
63+
Image: "mysql:8.0",
64+
Env: map[string]string{"MYSQL_ROOT_PASSWORD": "root"},
65+
WaitingFor: wait.ForLog("port: 3306 MySQL Community Server - GPL"),
66+
}
67+
68+
mysqlContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
69+
ContainerRequest: req,
70+
Started: true,
71+
})
72+
suite.Require().NoError(err)
73+
suite.mysqlContainer = mysqlContainer
74+
}
75+
76+
func (suite *GoMySQLReaderTestSuite) TearDownSuite() {
77+
ctx := context.Background()
78+
suite.Require().NoError(suite.mysqlContainer.Terminate(ctx))
79+
}
80+
81+
func (suite *GoMySQLReaderTestSuite) SetupTest() {
82+
ctx := context.Background()
83+
84+
rc, _, err := suite.mysqlContainer.Exec(ctx, []string{"mysql", "-proot", "-e", "CREATE DATABASE test"})
85+
suite.Require().NoError(err)
86+
suite.Require().Equal(0, rc, "expected exit code 0")
87+
}
88+
89+
func (suite *GoMySQLReaderTestSuite) TearDownTest() {
90+
ctx := context.Background()
91+
92+
rc, _, err := suite.mysqlContainer.Exec(ctx, []string{"mysql", "-proot", "-e", "DROP DATABASE test"})
93+
suite.Require().NoError(err)
94+
suite.Require().Equal(0, rc, "expected exit code 0")
5495
}
5596

56-
func TestStreamTransactionSingleAutoCommitChange(t *testing.T) {
57-
db, err := sql.Open("mysql", "root:root@/")
97+
func (suite *GoMySQLReaderTestSuite) TestStreamTransactionSingleAutoCommitChange() {
98+
t := suite.T()
99+
100+
ctx := context.Background()
101+
host, err := suite.mysqlContainer.ContainerIP(ctx)
102+
require.NoError(t, err)
103+
104+
db, err := sql.Open("mysql", "root:root@tcp("+host+")/")
58105
require.NoError(t, err)
59106
defer db.Close()
60107

61108
prepareDatabase(t, db)
62109

63110
binlogCoordinates := getCurrentBinlogCoordinates(t, db)
64111

65-
migrationContext := getMigrationContext()
112+
migrationContext := getMigrationContext(host)
66113
migrationContext.DatabaseName = "test"
67114
migrationContext.OriginalTableName = "gh_ost_test"
68115
migrationContext.AlterStatement = "ALTER TABLE gh_ost_test ENGINE=InnoDB"
@@ -96,16 +143,22 @@ func TestStreamTransactionSingleAutoCommitChange(t *testing.T) {
96143
require.Len(t, transactionsChan, 0)
97144
}
98145

99-
func TestStreamTransactionSingleChangeInTransaction(t *testing.T) {
100-
db, err := sql.Open("mysql", "root:root@/")
146+
func (suite *GoMySQLReaderTestSuite) TestStreamTransactionSingleChangeInTransaction() {
147+
t := suite.T()
148+
149+
ctx := context.Background()
150+
host, err := suite.mysqlContainer.ContainerIP(ctx)
151+
require.NoError(t, err)
152+
153+
db, err := sql.Open("mysql", "root:root@tcp("+host+")/")
101154
require.NoError(t, err)
102155
defer db.Close()
103156

104157
prepareDatabase(t, db)
105158

106159
binlogCoordinates := getCurrentBinlogCoordinates(t, db)
107160

108-
migrationContext := getMigrationContext()
161+
migrationContext := getMigrationContext(host)
109162
migrationContext.DatabaseName = "test"
110163
migrationContext.OriginalTableName = "gh_ost_test"
111164
migrationContext.AlterStatement = "ALTER TABLE gh_ost_test ENGINE=InnoDB"
@@ -145,16 +198,22 @@ func TestStreamTransactionSingleChangeInTransaction(t *testing.T) {
145198
require.Len(t, transactionsChan, 0)
146199
}
147200

148-
func TestStreamTransactionMultipleChangesInTransaction(t *testing.T) {
149-
db, err := sql.Open("mysql", "root:root@/")
201+
func (suite *GoMySQLReaderTestSuite) TestStreamTransactionMultipleChangesInTransaction() {
202+
t := suite.T()
203+
204+
ctx := context.Background()
205+
host, err := suite.mysqlContainer.ContainerIP(ctx)
206+
require.NoError(t, err)
207+
208+
db, err := sql.Open("mysql", "root:root@tcp("+host+")/")
150209
require.NoError(t, err)
151210
defer db.Close()
152211

153212
prepareDatabase(t, db)
154213

155214
binlogCoordinates := getCurrentBinlogCoordinates(t, db)
156215

157-
migrationContext := getMigrationContext()
216+
migrationContext := getMigrationContext(host)
158217
migrationContext.DatabaseName = "test"
159218
migrationContext.OriginalTableName = "gh_ost_test"
160219
migrationContext.AlterStatement = "ALTER TABLE gh_ost_test ENGINE=InnoDB"
@@ -200,16 +259,22 @@ func TestStreamTransactionMultipleChangesInTransaction(t *testing.T) {
200259
require.Len(t, transactionsChan, 0)
201260
}
202261

203-
func TestStreamTransactionWithDDL(t *testing.T) {
204-
db, err := sql.Open("mysql", "root:root@/")
262+
func (suite *GoMySQLReaderTestSuite) TestStreamTransactionWithDDL() {
263+
t := suite.T()
264+
265+
ctx := context.Background()
266+
host, err := suite.mysqlContainer.ContainerIP(ctx)
267+
require.NoError(t, err)
268+
269+
db, err := sql.Open("mysql", "root:root@tcp("+host+")/")
205270
require.NoError(t, err)
206271
defer db.Close()
207272

208273
prepareDatabase(t, db)
209274

210275
binlogCoordinates := getCurrentBinlogCoordinates(t, db)
211276

212-
migrationContext := getMigrationContext()
277+
migrationContext := getMigrationContext(host)
213278
migrationContext.DatabaseName = "test"
214279
migrationContext.OriginalTableName = "gh_ost_test"
215280
migrationContext.AlterStatement = "ALTER TABLE gh_ost_test ENGINE=InnoDB"
@@ -242,3 +307,7 @@ func TestStreamTransactionWithDDL(t *testing.T) {
242307
close(transactionsChan)
243308
require.Len(t, transactionsChan, 0)
244309
}
310+
311+
func TestGoMySQLReader(t *testing.T) {
312+
suite.Run(t, new(GoMySQLReaderTestSuite))
313+
}

go/logic/coordinator_test.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,32 @@ import (
1313
"github.com/github/gh-ost/go/mysql"
1414
"github.com/github/gh-ost/go/sql"
1515
"github.com/stretchr/testify/require"
16+
"github.com/testcontainers/testcontainers-go"
17+
"github.com/testcontainers/testcontainers-go/wait"
1618
)
1719

1820
func TestCoordinator(t *testing.T) {
19-
db, err := gosql.Open("mysql", "root:root@/")
21+
ctx := context.Background()
22+
req := testcontainers.ContainerRequest{
23+
Image: "mysql:8.0",
24+
Env: map[string]string{"MYSQL_ROOT_PASSWORD": "root"},
25+
WaitingFor: wait.ForLog("port: 3306 MySQL Community Server - GPL"),
26+
}
27+
28+
mysqlContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
29+
ContainerRequest: req,
30+
Started: true,
31+
})
32+
require.NoError(t, err)
33+
t.Cleanup(func() {
34+
ctx := context.Background()
35+
require.NoError(t, mysqlContainer.Terminate(ctx))
36+
})
37+
38+
host, err := mysqlContainer.ContainerIP(ctx)
39+
require.NoError(t, err)
40+
41+
db, err := gosql.Open("mysql", "root:root@tcp("+host+")/")
2042
require.NoError(t, err)
2143

2244
t.Cleanup(func() {
@@ -31,7 +53,6 @@ func TestCoordinator(t *testing.T) {
3153
require.NoError(t, err)
3254

3355
migrationContext := base.NewMigrationContext()
34-
migrationContext.Hostname = "localhost"
3556
migrationContext.DatabaseName = "test"
3657
migrationContext.OriginalTableName = "gh_ost_test"
3758
migrationContext.AlterStatement = "ALTER TABLE gh_ost_test ENGINE=InnoDB"
@@ -44,7 +65,7 @@ func TestCoordinator(t *testing.T) {
4465

4566
migrationContext.ApplierConnectionConfig = &mysql.ConnectionConfig{
4667
Key: mysql.InstanceKey{
47-
Hostname: "localhost",
68+
Hostname: host,
4869
Port: 3306,
4970
},
5071
User: "root",
@@ -53,7 +74,7 @@ func TestCoordinator(t *testing.T) {
5374

5475
migrationContext.InspectorConnectionConfig = &mysql.ConnectionConfig{
5576
Key: mysql.InstanceKey{
56-
Hostname: "localhost",
77+
Hostname: host,
5778
Port: 3306,
5879
},
5980
User: "root",

0 commit comments

Comments
 (0)