2017-04-25 10:24:51 +03:00
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package models
import (
2018-10-21 17:09:17 +03:00
"fmt"
2020-06-17 22:07:58 +03:00
"os"
2018-10-21 17:09:17 +03:00
"time"
2020-06-17 22:07:58 +03:00
"github.com/go-testfixtures/testfixtures/v3"
2021-03-24 21:27:22 +03:00
"xorm.io/xorm"
2020-03-22 18:12:55 +03:00
"xorm.io/xorm/schemas"
2017-04-25 10:24:51 +03:00
)
2020-06-17 22:07:58 +03:00
var fixtures * testfixtures . Loader
2017-04-25 10:24:51 +03:00
// InitFixtures initialize test fixtures for a test database
2021-03-24 21:27:22 +03:00
func InitFixtures ( dir string , engine ... * xorm . Engine ) ( err error ) {
e := x
if len ( engine ) == 1 {
e = engine [ 0 ]
}
2020-06-17 22:07:58 +03:00
testfiles := testfixtures . Directory ( dir )
dialect := "unknown"
2021-03-24 21:27:22 +03:00
switch e . Dialect ( ) . URI ( ) . DBType {
2020-06-17 22:07:58 +03:00
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 {
2021-03-24 21:27:22 +03:00
testfixtures . Database ( e . DB ( ) . DB ) ,
2020-06-17 22:07:58 +03:00
testfixtures . Dialect ( dialect ) ,
testfixtures . DangerousSkipTestDatabaseCheck ( ) ,
testfiles ,
}
2021-03-24 21:27:22 +03:00
if e . Dialect ( ) . URI ( ) . DBType == schemas . POSTGRES {
2020-06-17 22:07:58 +03:00
loaderOptions = append ( loaderOptions , testfixtures . SkipResetSequences ( ) )
}
fixtures , err = testfixtures . New ( loaderOptions ... )
if err != nil {
return err
}
2017-04-25 10:24:51 +03:00
return err
}
// LoadFixtures load fixtures for a test database
2021-03-24 21:27:22 +03:00
func LoadFixtures ( engine ... * xorm . Engine ) error {
e := x
if len ( engine ) == 1 {
e = engine [ 0 ]
}
2018-10-20 23:48:33 +03:00
var err error
// Database transaction conflicts could occur and result in ROLLBACK
2018-10-21 17:09:17 +03:00
// As a simple workaround, we just retry 20 times.
for i := 0 ; i < 20 ; i ++ {
2018-10-20 23:48:33 +03:00
err = fixtures . Load ( )
if err == nil {
break
}
2018-10-21 17:09:17 +03:00
time . Sleep ( 200 * time . Millisecond )
}
if err != nil {
fmt . Printf ( "LoadFixtures failed after retries: %v\n" , err )
2018-10-20 23:48:33 +03:00
}
2019-12-10 10:49:05 +03:00
// Now if we're running postgres we need to tell it to update the sequences
2021-03-24 21:27:22 +03:00
if e . Dialect ( ) . URI ( ) . DBType == schemas . POSTGRES {
results , err := e . QueryString ( ` SELECT ' SELECT SETVAL ( ' ||
2019-12-10 10:49:05 +03:00
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 {
2021-03-24 21:27:22 +03:00
_ , err = e . Exec ( value )
2019-12-10 10:49:05 +03:00
if err != nil {
fmt . Printf ( "Failed to update sequence: %s Error: %v\n" , value , err )
return err
}
}
}
}
2018-10-20 23:48:33 +03:00
return err
2017-04-25 10:24:51 +03:00
}