diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 18fce3e7..5224e1b3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -48,6 +48,24 @@ jobs: - 3306 options: --health-cmd "mysql -proot -e \"show databases;\"" --health-interval 10s --health-timeout 5s --health-retries 5 + mysql8: + image: mysql:8.0 + env: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: dex + ports: + - 3306 + options: --health-cmd "mysql -proot -e \"show databases;\"" --health-interval 10s --health-timeout 5s --health-retries 5 + + mysql8-ent: + image: mysql:8.0 + env: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: dex + ports: + - 3306 + options: --health-cmd "mysql -proot -e \"show databases;\"" --health-interval 10s --health-timeout 5s --health-retries 5 + etcd: image: gcr.io/etcd-development/etcd:v3.5.0 ports: @@ -124,6 +142,18 @@ jobs: DEX_MYSQL_ENT_HOST: 127.0.0.1 DEX_MYSQL_ENT_PORT: ${{ job.services.mysql-ent.ports[3306] }} + DEX_MYSQL8_DATABASE: dex + DEX_MYSQL8_USER: root + DEX_MYSQL8_PASSWORD: root + DEX_MYSQL8_HOST: 127.0.0.1 + DEX_MYSQL8_PORT: ${{ job.services.mysql8.ports[3306] }} + + DEX_MYSQL8_ENT_DATABASE: dex + DEX_MYSQL8_ENT_USER: root + DEX_MYSQL8_ENT_PASSWORD: root + DEX_MYSQL8_ENT_HOST: 127.0.0.1 + DEX_MYSQL8_ENT_PORT: ${{ job.services.mysql8-ent.ports[3306] }} + DEX_POSTGRES_DATABASE: postgres DEX_POSTGRES_USER: postgres DEX_POSTGRES_PASSWORD: postgres diff --git a/docker-compose.override.yaml.dist b/docker-compose.override.yaml.dist index b9eefac5..30591add 100644 --- a/docker-compose.override.yaml.dist +++ b/docker-compose.override.yaml.dist @@ -5,6 +5,10 @@ services: ports: - "127.0.0.1:3306:3306" + mysql8: + ports: + - "127.0.0.1:3307:3306" + postgres: ports: - "127.0.0.1:5432:5432" diff --git a/docker-compose.yaml b/docker-compose.yaml index cfaf739c..6c5a052a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -17,6 +17,15 @@ services: MYSQL_PASSWORD: mysql MYSQL_ROOT_PASSWORD: root + mysql8: + image: mysql:8.0 + command: --default-authentication-plugin=mysql_native_password + environment: + MYSQL_DATABASE: dex + MYSQL_USER: mysql + MYSQL_PASSWORD: mysql + MYSQL_ROOT_PASSWORD: root + postgres: image: postgres:10.15 environment: diff --git a/storage/ent/mysql_test.go b/storage/ent/mysql_test.go index a1baffb3..b602e4a5 100644 --- a/storage/ent/mysql_test.go +++ b/storage/ent/mysql_test.go @@ -18,6 +18,12 @@ const ( MySQLEntDatabaseEnv = "DEX_MYSQL_ENT_DATABASE" MySQLEntUserEnv = "DEX_MYSQL_ENT_USER" MySQLEntPasswordEnv = "DEX_MYSQL_ENT_PASSWORD" + + MySQL8EntHostEnv = "DEX_MYSQL8_ENT_HOST" + MySQL8EntPortEnv = "DEX_MYSQL8_ENT_PORT" + MySQL8EntDatabaseEnv = "DEX_MYSQL8_ENT_DATABASE" + MySQL8EntUserEnv = "DEX_MYSQL8_ENT_USER" + MySQL8EntPasswordEnv = "DEX_MYSQL8_ENT_PASSWORD" ) func mysqlTestConfig(host string, port uint64) *MySQL { @@ -40,6 +46,35 @@ func mysqlTestConfig(host string, port uint64) *MySQL { } } +func mysql8TestConfig(host string, port uint64) *MySQL { + return &MySQL{ + NetworkDB: NetworkDB{ + Database: getenv(MySQL8EntDatabaseEnv, "mysql"), + User: getenv(MySQL8EntUserEnv, "mysql"), + Password: getenv(MySQL8EntPasswordEnv, "mysql"), + Host: host, + Port: uint16(port), + }, + SSL: SSL{ + Mode: mysqlSSLFalse, + }, + params: map[string]string{ + "innodb_lock_wait_timeout": "1", + }, + } +} + +func newMySQL8Storage(t *testing.T, host string, port uint64) storage.Storage { + logger := slog.New(slog.NewTextHandler(t.Output(), &slog.HandlerOptions{Level: slog.LevelDebug})) + + cfg := mysql8TestConfig(host, port) + s, err := cfg.Open(logger) + if err != nil { + panic(err) + } + return s +} + func newMySQLStorage(t *testing.T, host string, port uint64) storage.Storage { logger := slog.New(slog.NewTextHandler(t.Output(), &slog.HandlerOptions{Level: slog.LevelDebug})) @@ -72,6 +107,27 @@ func TestMySQL(t *testing.T) { conformance.RunTransactionTests(t, newStorage) } +func TestMySQL8(t *testing.T) { + host := os.Getenv(MySQL8EntHostEnv) + if host == "" { + t.Skipf("test environment variable %s not set, skipping", MySQL8EntHostEnv) + } + + port := uint64(3306) + if rawPort := os.Getenv(MySQL8EntPortEnv); rawPort != "" { + var err error + + port, err = strconv.ParseUint(rawPort, 10, 32) + require.NoError(t, err, "invalid mysql port %q: %s", rawPort, err) + } + + newStorage := func(t *testing.T) storage.Storage { + return newMySQL8Storage(t, host, port) + } + conformance.RunTests(t, newStorage) + conformance.RunTransactionTests(t, newStorage) +} + func TestMySQLDSN(t *testing.T) { tests := []struct { name string diff --git a/storage/sql/config_test.go b/storage/sql/config_test.go index 93a593ea..606c95a8 100644 --- a/storage/sql/config_test.go +++ b/storage/sql/config_test.go @@ -275,3 +275,40 @@ func TestMySQL(t *testing.T) { } testDB(t, s, true) } + +const testMySQL8Env = "DEX_MYSQL8_HOST" + +func TestMySQL8(t *testing.T) { + host := os.Getenv(testMySQL8Env) + if host == "" { + t.Skipf("test environment variable %q not set, skipping", testMySQL8Env) + } + + port := uint64(3306) + if rawPort := os.Getenv("DEX_MYSQL8_PORT"); rawPort != "" { + var err error + + port, err = strconv.ParseUint(rawPort, 10, 32) + if err != nil { + t.Fatalf("invalid mysql port %q: %s", rawPort, err) + } + } + + s := &MySQL{ + NetworkDB: NetworkDB{ + Database: getenv("DEX_MYSQL8_DATABASE", "mysql"), + User: getenv("DEX_MYSQL8_USER", "mysql"), + Password: getenv("DEX_MYSQL8_PASSWORD", "mysql"), + Host: host, + Port: uint16(port), + ConnectionTimeout: 5, + }, + SSL: SSL{ + Mode: mysqlSSLFalse, + }, + params: map[string]string{ + "innodb_lock_wait_timeout": "3", + }, + } + testDB(t, s, true) +}