diff options
author | Daniel Baumann <daniel@debian.org> | 2024-10-18 20:33:49 +0200 |
---|---|---|
committer | Daniel Baumann <daniel@debian.org> | 2024-12-12 23:57:56 +0100 |
commit | e68b9d00a6e05b3a941f63ffb696f91e554ac5ec (patch) | |
tree | 97775d6c13b0f416af55314eb6a89ef792474615 /models/unittest/fixtures.go | |
parent | Initial commit. (diff) | |
download | forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.tar.xz forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.zip |
Adding upstream version 9.0.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to '')
-rw-r--r-- | models/unittest/fixtures.go | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/models/unittest/fixtures.go b/models/unittest/fixtures.go new file mode 100644 index 0000000..63b26a0 --- /dev/null +++ b/models/unittest/fixtures.go @@ -0,0 +1,144 @@ +// 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.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 +} |