diff --git a/.github/workflows/bats-tests.yml b/.github/workflows/bats-tests.yml new file mode 100644 index 00000000..53a8b3e2 --- /dev/null +++ b/.github/workflows/bats-tests.yml @@ -0,0 +1,52 @@ +name: BATS Tests + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + bats-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.23' + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - name: Install system packages + uses: awalsh128/cache-apt-pkgs-action@latest + with: + packages: bats mysql-client + version: 1.0 + + - name: Install dependencies + run: | + go get . + + pip3 install "sqlglot[rs]" + + curl -LJO https://github.com/duckdb/duckdb/releases/download/v1.1.3/duckdb_cli-linux-amd64.zip + unzip duckdb_cli-linux-amd64.zip + chmod +x duckdb + sudo mv duckdb /usr/local/bin + + - name: Build + run: go build -v + + - name: Start MyDuck Server + run: | + ./myduckserver & + sleep 5 + + - name: Run BATS Tests + run: | + find test/bats -name "*.bats" -type f -exec bats {} + \ No newline at end of file diff --git a/.github/workflows/clients-compatibility.yml b/.github/workflows/clients-compatibility.yml index ec9ade0d..8605e090 100644 --- a/.github/workflows/clients-compatibility.yml +++ b/.github/workflows/clients-compatibility.yml @@ -28,7 +28,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.13' - name: Install system packages uses: awalsh128/cache-apt-pkgs-action@latest diff --git a/binlogreplication/binlog_replication_reconnect_test.go b/binlogreplication/binlog_replication_reconnect_test.go index 1215a052..0489dc79 100644 --- a/binlogreplication/binlog_replication_reconnect_test.go +++ b/binlogreplication/binlog_replication_reconnect_test.go @@ -23,7 +23,7 @@ import ( "github.com/Shopify/toxiproxy/v2" toxiproxyclient "github.com/Shopify/toxiproxy/v2/client" - "github.com/apecloud/myduckserver/test" + "github.com/apecloud/myduckserver/testutil" "github.com/prometheus/client_golang/prometheus" "github.com/rs/zerolog" "github.com/stretchr/testify/require" @@ -153,7 +153,7 @@ func showReplicaStatus(t *testing.T) map[string]interface{} { } func configureToxiProxy(t *testing.T) { - toxiproxyPort := test.FindFreePort() + toxiproxyPort := testutil.FindFreePort() metrics := toxiproxy.NewMetricsContainer(prometheus.NewRegistry()) toxiproxyServer := toxiproxy.NewServer(metrics, zerolog.Nop()) @@ -165,7 +165,7 @@ func configureToxiProxy(t *testing.T) { toxiClient = toxiproxyclient.NewClient(fmt.Sprintf("localhost:%d", toxiproxyPort)) - proxyPort = test.FindFreePort() + proxyPort = testutil.FindFreePort() var err error mysqlProxy, err = toxiClient.CreateProxy("mysql", fmt.Sprintf("localhost:%d", proxyPort), // downstream diff --git a/binlogreplication/binlog_replication_restart_test.go b/binlogreplication/binlog_replication_restart_test.go index 70d6d247..9bd79c97 100644 --- a/binlogreplication/binlog_replication_restart_test.go +++ b/binlogreplication/binlog_replication_restart_test.go @@ -19,7 +19,7 @@ import ( "testing" "time" - "github.com/apecloud/myduckserver/test" + "github.com/apecloud/myduckserver/testutil" "github.com/stretchr/testify/require" ) @@ -46,13 +46,13 @@ func TestBinlogReplicationServerRestart(t *testing.T) { // Let the replica process a few transactions, then stop the server and pause a second waitForReplicaToReachGtid(t, 3) - test.StopDuckSqlServer(t, duckProcess) + testutil.StopDuckSqlServer(t, duckProcess) time.Sleep(1000 * time.Millisecond) var err error - testEnv := test.NewTestEnv() + testEnv := testutil.NewTestEnv() setupTestEnv(testEnv) - err = test.StartDuckSqlServer(t, testDir, nil, testEnv) + err = testutil.StartDuckSqlServer(t, testDir, nil, testEnv) require.NoError(t, err) loadEnvFromTestEnv(testEnv) diff --git a/binlogreplication/binlog_replication_test.go b/binlogreplication/binlog_replication_test.go index 56839b89..66595daf 100644 --- a/binlogreplication/binlog_replication_test.go +++ b/binlogreplication/binlog_replication_test.go @@ -30,7 +30,7 @@ import ( "testing" "time" - "github.com/apecloud/myduckserver/test" + "github.com/apecloud/myduckserver/testutil" _ "github.com/go-sql-driver/mysql" "github.com/jmoiron/sqlx" "github.com/stretchr/testify/require" @@ -70,7 +70,7 @@ func teardown(t *testing.T) { stopMySqlServer(t) } if duckProcess != nil { - test.StopDuckSqlServer(t, duckProcess) + testutil.StopDuckSqlServer(t, duckProcess) } if mysqlLogFile != nil { mysqlLogFile.Close() @@ -101,7 +101,7 @@ func teardown(t *testing.T) { } } -func setupTestEnv(testEnv *test.TestEnv) { +func setupTestEnv(testEnv *testutil.TestEnv) { testEnv.MySqlContainer = mySqlContainer testEnv.MySqlPort = mySqlPort testEnv.DuckPort = duckPort @@ -116,7 +116,7 @@ func setupTestEnv(testEnv *test.TestEnv) { testEnv.OriginalWorkingDir = originalWorkingDir } -func loadEnvFromTestEnv(testEnv *test.TestEnv) { +func loadEnvFromTestEnv(testEnv *testutil.TestEnv) { mySqlContainer = testEnv.MySqlContainer mySqlPort = testEnv.MySqlPort duckPort = testEnv.DuckPort @@ -185,11 +185,11 @@ func TestAutoRestartReplica(t *testing.T) { require.True(t, fileExists(filepath.Join(testDir, duckSubdir, ".replica", "replica-running"))) // Restart the Dolt replica - test.StopDuckSqlServer(t, duckProcess) + testutil.StopDuckSqlServer(t, duckProcess) var err error - testEnv := test.NewTestEnv() + testEnv := testutil.NewTestEnv() setupTestEnv(testEnv) - err = test.StartDuckSqlServer(t, testDir, nil, testEnv) + err = testutil.StartDuckSqlServer(t, testDir, nil, testEnv) require.NoError(t, err) loadEnvFromTestEnv(testEnv) @@ -214,9 +214,9 @@ func TestAutoRestartReplica(t *testing.T) { require.False(t, fileExists(filepath.Join(testDir, duckSubdir, ".replica", "replica-running"))) // Restart the Dolt replica - test.StopDuckSqlServer(t, duckProcess) + testutil.StopDuckSqlServer(t, duckProcess) setupTestEnv(testEnv) - err = test.StartDuckSqlServer(t, testDir, nil, testEnv) + err = testutil.StartDuckSqlServer(t, testDir, nil, testEnv) require.NoError(t, err) loadEnvFromTestEnv(testEnv) @@ -688,15 +688,15 @@ func startSqlServersWithSystemVars(t *testing.T, persistentSystemVars map[string t.Skip("Skipping binlog replication integ tests in CI environment on Mac OS") } - testDir = test.CreateTestDir(t) + testDir = testutil.CreateTestDir(t) var err error // Start up primary and replica databases mySqlPort, mySqlContainer, err = startMySqlServer(testDir) require.NoError(t, err) - testEnv := test.NewTestEnv() + testEnv := testutil.NewTestEnv() setupTestEnv(testEnv) - err = test.StartDuckSqlServer(t, testDir, persistentSystemVars, testEnv) + err = testutil.StartDuckSqlServer(t, testDir, persistentSystemVars, testEnv) require.NoError(t, err) loadEnvFromTestEnv(testEnv) } @@ -825,7 +825,7 @@ func getGtidEnabled() bool { // startMySqlServer configures a starts a fresh MySQL server instance in a Docker container // and returns the port it is running on. If unable to start up the MySQL server, an error is returned. func startMySqlServer(dir string) (int, string, error) { - mySqlPort = test.FindFreePort() + mySqlPort = testutil.FindFreePort() // Use a random name for the container to avoid conflicts mySqlContainer = "mysql-test-" + strconv.Itoa(rand.Int()) @@ -863,7 +863,7 @@ func startMySqlServer(dir string) (int, string, error) { dsn := fmt.Sprintf("root:password@tcp(127.0.0.1:%v)/", mySqlPort) primaryDatabase = sqlx.MustOpen("mysql", dsn) - err = test.WaitForSqlServerToStart(primaryDatabase) + err = testutil.WaitForSqlServerToStart(primaryDatabase) if err != nil { return -1, "", err } diff --git a/pgserver/sess_params_test.go b/pgserver/sess_params_test.go index e9e48835..442a1293 100644 --- a/pgserver/sess_params_test.go +++ b/pgserver/sess_params_test.go @@ -6,7 +6,7 @@ import ( "strconv" "testing" - "github.com/apecloud/myduckserver/test" + "github.com/apecloud/myduckserver/testutil" "github.com/jackc/pgx/v5" "github.com/stretchr/testify/require" ) @@ -420,11 +420,11 @@ func TestSessParam(t *testing.T) { } // Setup MyDuck Server - testDir := test.CreateTestDir(t) - testEnv := test.NewTestEnv() - err := test.StartDuckSqlServer(t, testDir, nil, testEnv) + testDir := testutil.CreateTestDir(t) + testEnv := testutil.NewTestEnv() + err := testutil.StartDuckSqlServer(t, testDir, nil, testEnv) require.NoError(t, err) - defer test.StopDuckSqlServer(t, testEnv.DuckProcess) + defer testutil.StopDuckSqlServer(t, testEnv.DuckProcess) dsn := "postgresql://postgres@localhost:" + strconv.Itoa(testEnv.DuckPgPort) + "/postgres" // https://pkg.go.dev/github.com/jackc/pgx/v5#ParseConfig diff --git a/test/bats/mysql/cli.bats b/test/bats/mysql/cli.bats new file mode 100644 index 00000000..1ee88245 --- /dev/null +++ b/test/bats/mysql/cli.bats @@ -0,0 +1,5 @@ +##!/usr/bin/env bats + +@test "cli_show_databases" { + mysql -h 127.0.0.1 -P 3306 -u root -e "SHOW DATABASES;" | grep -q 'mysql' +} \ No newline at end of file diff --git a/test/test_utils.go b/testutil/testutil.go similarity index 99% rename from test/test_utils.go rename to testutil/testutil.go index bc10c422..0001bb9f 100644 --- a/test/test_utils.go +++ b/testutil/testutil.go @@ -1,4 +1,4 @@ -package test +package testutil import ( "fmt"