de6474c3c7
(cherry picked from commit 93a844dd13904c0ba1b7fd4a0a233002194a504b) (cherry picked from commit 6d6d1a121ce3fc5cf7cd92ad1a38be3bdcbf7088) (cherry picked from commit 34646f9886bb6b06dc1bd06b44c49c28ddb29aad) (cherry picked from commit 83801a64cff076618fe14134c90f38b36a60675c) (cherry picked from commit c9a1e55a80495effb8bd2b45b833943ba19f31d3) (cherry picked from commit 6c7292419c2cda5cfaef5dde8bdef024dd9841ab) (cherry picked from commit 5439218f1a3543fe6941a4dfbbe59784940d092c)
146 lines
4 KiB
Go
146 lines
4 KiB
Go
// Copyright 2021 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
//nolint:forbidigo
|
|
package unittest
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"code.gitea.io/gitea/models/db"
|
|
"code.gitea.io/gitea/modules/auth/password/hash"
|
|
"code.gitea.io/gitea/modules/setting"
|
|
|
|
"github.com/go-testfixtures/testfixtures/v3"
|
|
"xorm.io/xorm"
|
|
"xorm.io/xorm/schemas"
|
|
)
|
|
|
|
var fixturesLoader *testfixtures.Loader
|
|
|
|
// GetXORMEngine gets the XORM engine
|
|
func GetXORMEngine(engine ...*xorm.Engine) (x *xorm.Engine) {
|
|
if len(engine) == 1 {
|
|
return engine[0]
|
|
}
|
|
return db.DefaultContext.(*db.Context).Engine().(*xorm.Engine)
|
|
}
|
|
|
|
func OverrideFixtures(opts FixturesOptions, engine ...*xorm.Engine) func() {
|
|
old := fixturesLoader
|
|
if err := InitFixtures(opts, engine...); err != nil {
|
|
panic(err)
|
|
}
|
|
return func() {
|
|
fixturesLoader = old
|
|
}
|
|
}
|
|
|
|
// InitFixtures initialize test fixtures for a test database
|
|
func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
|
|
e := GetXORMEngine(engine...)
|
|
var fixtureOptionFiles func(*testfixtures.Loader) error
|
|
if opts.Dir != "" {
|
|
fixtureOptionFiles = testfixtures.Directory(opts.Dir)
|
|
} else {
|
|
fixtureOptionFiles = testfixtures.Files(opts.Files...)
|
|
}
|
|
var fixtureOptionDirs []func(*testfixtures.Loader) error
|
|
if opts.Dirs != nil {
|
|
for _, dir := range opts.Dirs {
|
|
fixtureOptionDirs = append(fixtureOptionDirs, testfixtures.Directory(filepath.Join(opts.Base, dir)))
|
|
}
|
|
}
|
|
dialect := "unknown"
|
|
switch e.Dialect().URI().DBType {
|
|
case schemas.POSTGRES:
|
|
dialect = "postgres"
|
|
case schemas.MYSQL:
|
|
dialect = "mysql"
|
|
case schemas.MSSQL:
|
|
dialect = "mssql"
|
|
case schemas.SQLITE:
|
|
dialect = "sqlite3"
|
|
default:
|
|
fmt.Println("Unsupported RDBMS for integration tests")
|
|
os.Exit(1)
|
|
}
|
|
loaderOptions := []func(loader *testfixtures.Loader) error{
|
|
testfixtures.Database(e.DB().DB),
|
|
testfixtures.Dialect(dialect),
|
|
testfixtures.DangerousSkipTestDatabaseCheck(),
|
|
fixtureOptionFiles,
|
|
}
|
|
loaderOptions = append(loaderOptions, fixtureOptionDirs...)
|
|
|
|
if e.Dialect().URI().DBType == schemas.POSTGRES {
|
|
loaderOptions = append(loaderOptions, testfixtures.SkipResetSequences())
|
|
}
|
|
|
|
fixturesLoader, err = testfixtures.New(loaderOptions...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// register the dummy hash algorithm function used in the test fixtures
|
|
_ = hash.Register("dummy", hash.NewDummyHasher)
|
|
|
|
setting.PasswordHashAlgo, _ = hash.SetDefaultPasswordHashAlgorithm("dummy")
|
|
|
|
return err
|
|
}
|
|
|
|
// LoadFixtures load fixtures for a test database
|
|
func LoadFixtures(engine ...*xorm.Engine) error {
|
|
e := GetXORMEngine(engine...)
|
|
var err error
|
|
// (doubt) database transaction conflicts could occur and result in ROLLBACK? just try for a few times.
|
|
for i := 0; i < 5; i++ {
|
|
if err = fixturesLoader.Load(); err == nil {
|
|
break
|
|
}
|
|
time.Sleep(200 * time.Millisecond)
|
|
}
|
|
if err != nil {
|
|
fmt.Printf("LoadFixtures failed after retries: %v\n", err)
|
|
}
|
|
// Now if we're running postgres we need to tell it to update the sequences
|
|
if e.Dialect().URI().DBType == schemas.POSTGRES {
|
|
results, err := e.QueryString(`SELECT 'SELECT SETVAL(' ||
|
|
quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||
|
|
', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1) ) FROM ' ||
|
|
quote_ident(PGT.schemaname)|| '.'||quote_ident(T.relname)|| ';'
|
|
FROM pg_class AS S,
|
|
pg_depend AS D,
|
|
pg_class AS T,
|
|
pg_attribute AS C,
|
|
pg_tables AS PGT
|
|
WHERE S.relkind = 'S'
|
|
AND S.oid = D.objid
|
|
AND D.refobjid = T.oid
|
|
AND D.refobjid = C.attrelid
|
|
AND D.refobjsubid = C.attnum
|
|
AND T.relname = PGT.tablename
|
|
ORDER BY S.relname;`)
|
|
if err != nil {
|
|
fmt.Printf("Failed to generate sequence update: %v\n", err)
|
|
return err
|
|
}
|
|
for _, r := range results {
|
|
for _, value := range r {
|
|
_, err = e.Exec(value)
|
|
if err != nil {
|
|
fmt.Printf("Failed to update sequence: %s Error: %v\n", value, err)
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_ = hash.Register("dummy", hash.NewDummyHasher)
|
|
setting.PasswordHashAlgo, _ = hash.SetDefaultPasswordHashAlgorithm("dummy")
|
|
|
|
return err
|
|
}
|