package db import ( "context" "crypto/rand" "database/sql" "log/slog" "testing" ) // NewTestDatabaseURL returns the URL of a new, empty in-memory // database for one test. SQLite deletes an in-memory database when // its last connection closes. A pool closes a connection when a query // on it is cancelled while it runs. So this function holds a // connection of its own open until the test ends. func NewTestDatabaseURL(tb testing.TB) string { tb.Helper() // A random name, so that no other test can share the database. dbURL := "file:" + rand.Text() + "?mode=memory&cache=shared" pool, err := sql.Open("sqlite", dbURL) if err != nil { tb.Fatalf("open test database: %v", err) } tb.Cleanup(func() { _ = pool.Close() }) conn, err := pool.Conn(tb.Context()) if err != nil { tb.Fatalf("connect to test database: %v", err) } tb.Cleanup(func() { _ = conn.Close() }) return dbURL } // NewTestDatabaseFromConn creates a Database wrapping an // existing *sql.DB connection. Intended for integration // tests in other packages. func NewTestDatabaseFromConn(conn *sql.DB) *Database { return &Database{ //nolint:exhaustruct conn: conn, log: slog.Default(), } } // RunMigrations applies all schema migrations. Exposed // for integration tests in other packages. func (database *Database) RunMigrations( ctx context.Context, ) error { return database.runMigrations(ctx) }