Refactor database connection (#37496)
Clean up legacy copied&pasted code, introduce the unique "database connection" function. Move migration testing helper function PrepareTestEnv to a separate package. By the way, remove "shadow connection secrets" tricks: showing connection string on UI is useless --------- Co-authored-by: Nicolas <bircni@icloud.com>
This commit is contained in:
+102
-4
@@ -5,6 +5,8 @@ package unittest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -102,6 +104,101 @@ func mainTest(m *testing.M, testOptsArg ...*TestOptions) int {
|
||||
return exitStatus
|
||||
}
|
||||
|
||||
func ResetTestDatabase() (cleanup func(), err error) {
|
||||
defer func() {
|
||||
if cleanup == nil {
|
||||
cleanup = func() {}
|
||||
}
|
||||
}()
|
||||
|
||||
connOpts := db.GlobalConnOptions()
|
||||
driverDefault, connStrDefault, err := db.ConnStrDefaultDatabase(connOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
driverDatabase, connStrDatabase, err := db.ConnStr(connOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if connOpts.Type.IsSQLite3() {
|
||||
if !strings.HasSuffix(connOpts.SQLitePath, "-test.db") {
|
||||
return nil, errors.New(`testing database file for sqlite3 must end in "-test.db"`)
|
||||
}
|
||||
_ = os.Remove(connOpts.SQLitePath)
|
||||
err = os.MkdirAll(filepath.Dir(connOpts.SQLitePath), os.ModePerm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cleanup = func() {
|
||||
_ = os.Remove(connOpts.SQLitePath)
|
||||
_ = os.Remove(filepath.Dir(connOpts.SQLitePath))
|
||||
}
|
||||
return cleanup, nil
|
||||
}
|
||||
|
||||
if !strings.Contains(connOpts.Database, "test") {
|
||||
return nil, fmt.Errorf(`testing database name for %s must contain "test"`, connOpts.Database)
|
||||
}
|
||||
|
||||
quotedDbName := connOpts.Database
|
||||
if connOpts.Type.IsMSSQL() {
|
||||
quotedDbName = `[` + connOpts.Database + `]`
|
||||
}
|
||||
|
||||
sqlExec := func(sqlDB *sql.DB, sql string) error {
|
||||
_, err := sqlDB.Exec(sql)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute SQL %q: %w", sql, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
createDatabase := func() error {
|
||||
sqlDB, err := sql.Open(driverDefault, connStrDefault)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer sqlDB.Close()
|
||||
if err = sqlExec(sqlDB, "DROP DATABASE IF EXISTS "+quotedDbName); err != nil {
|
||||
return err
|
||||
}
|
||||
return sqlExec(sqlDB, "CREATE DATABASE "+quotedDbName)
|
||||
}
|
||||
if err = createDatabase(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cleanup = func() {
|
||||
sqlDB, err := sql.Open(driverDefault, connStrDefault)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer sqlDB.Close()
|
||||
_, _ = sqlDB.Exec("DROP DATABASE IF EXISTS " + quotedDbName)
|
||||
}
|
||||
|
||||
createDatabaseSchema := func() error {
|
||||
if !connOpts.Type.IsPostgreSQL() {
|
||||
return nil
|
||||
}
|
||||
if connOpts.Schema == "" {
|
||||
return nil
|
||||
}
|
||||
sqlDB, err := sql.Open(driverDatabase, connStrDatabase)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer sqlDB.Close()
|
||||
if err = sqlExec(sqlDB, "DROP SCHEMA IF EXISTS "+connOpts.Schema); err != nil {
|
||||
return err
|
||||
}
|
||||
return sqlExec(sqlDB, "CREATE SCHEMA "+connOpts.Schema)
|
||||
}
|
||||
|
||||
return cleanup, createDatabaseSchema()
|
||||
}
|
||||
|
||||
// FixturesOptions fixtures needs to be loaded options
|
||||
type FixturesOptions struct {
|
||||
Dir string
|
||||
@@ -110,11 +207,12 @@ type FixturesOptions struct {
|
||||
|
||||
// CreateTestEngine creates a memory database and loads the fixture data from fixturesDir
|
||||
func CreateTestEngine(opts FixturesOptions) error {
|
||||
x, err := xorm.NewEngine("sqlite3", "file::memory:?cache=shared&_txlock=immediate")
|
||||
driver, connStr, err := db.ConnStr(db.ConnOptions{Type: "sqlite3", SQLitePath: ":memory:"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
x, err := xorm.NewEngine(driver, connStr)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "unknown driver") {
|
||||
return fmt.Errorf("sqlite3 requires: -tags sqlite,sqlite_unlock_notify\n%w", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
x.SetMapper(names.GonicMapper{})
|
||||
|
||||
Reference in New Issue
Block a user