test(mymigrate): use single-schema test fixture for hosted MariaDB

Hosted MariaDB users (e.g. todo_test_*) typically have access to a single
database/schema and cannot CREATE/DROP DATABASE. Drop the per-test database
isolation pattern in favour of dropping _migrations directly on entry and
exit, matching msmigrate's approach. Tests must not run concurrently
against the same DSN.
This commit is contained in:
AJ ONeal 2026-04-10 00:25:29 -06:00
parent 3402b60bc6
commit 28af8f49b8
No known key found for this signature in database

View File

@ -11,8 +11,12 @@ import (
)
// connect opens a *sql.Conn from MYSQL_TEST_DSN, skips the test if the
// env var is unset, and isolates the test in its own database with
// automatic cleanup.
// env var is unset, and ensures _migrations does not exist on entry,
// with cleanup on exit.
//
// Note: tests run against the database in the DSN (no per-test database)
// because hosted MariaDB users typically have access to a single schema
// only. Tests must not be run concurrently against the same DSN.
func connect(t *testing.T) *sql.Conn {
t.Helper()
dsn := os.Getenv("MYSQL_TEST_DSN")
@ -27,46 +31,22 @@ func connect(t *testing.T) *sql.Conn {
}
t.Cleanup(func() { _ = db.Close() })
// Use a per-test database so concurrent tests don't collide and
// _migrations is guaranteed not to exist on entry.
dbName := "mymigrate_test_" + sanitize(t.Name())
if _, err := db.ExecContext(ctx, "DROP DATABASE IF EXISTS "+dbName); err != nil {
t.Fatalf("drop database: %v", err)
}
if _, err := db.ExecContext(ctx, "CREATE DATABASE "+dbName); err != nil {
t.Fatalf("create database: %v", err)
}
t.Cleanup(func() {
_, _ = db.ExecContext(ctx, "DROP DATABASE IF EXISTS "+dbName)
})
conn, err := db.Conn(ctx)
if err != nil {
t.Fatalf("conn: %v", err)
}
t.Cleanup(func() { _ = conn.Close() })
if _, err := conn.ExecContext(ctx, "USE "+dbName); err != nil {
t.Fatalf("use database: %v", err)
if _, err := conn.ExecContext(ctx, "DROP TABLE IF EXISTS _migrations"); err != nil {
t.Fatalf("pre-cleanup _migrations: %v", err)
}
t.Cleanup(func() {
_, _ = conn.ExecContext(ctx, "DROP TABLE IF EXISTS _migrations")
})
return conn
}
// sanitize converts a test name to a valid MySQL identifier suffix.
func sanitize(s string) string {
out := make([]byte, 0, len(s))
for _, c := range []byte(s) {
switch {
case c >= 'a' && c <= 'z', c >= 'A' && c <= 'Z', c >= '0' && c <= '9':
out = append(out, c)
default:
out = append(out, '_')
}
}
return string(out)
}
// TestAppliedNoMigrationsTable verifies Applied returns (nil, nil) when
// the _migrations table does not exist (MySQL error 1146). Defensive
// regression test against drivers that may surface the error lazily.