test: release fixtures loader lock before database work (#39263)

This commit is contained in:
silverwind
2026-09-08 11:10:14 +02:00
committed by GitHub
parent e8254bd5c1
commit df8e7db02f
+13 -16
View File
@@ -34,8 +34,7 @@ type FixtureItem struct {
type fixturesLoaderInternal struct { type fixturesLoaderInternal struct {
xormEngine *xorm.Engine xormEngine *xorm.Engine
tableSyncMu sync.Mutex tableSyncMap sync.Map
tableSynced map[string]bool
db *sql.DB db *sql.DB
dbType schemas.DBType dbType schemas.DBType
fixtures map[string]*FixtureItem fixtures map[string]*FixtureItem
@@ -153,35 +152,33 @@ func (f *fixturesLoaderInternal) Load() error {
ctx := context.WithValue(context.Background(), db.ContextKeyTestFixtures, true) ctx := context.WithValue(context.Background(), db.ContextKeyTestFixtures, true)
f.tableSyncMu.Lock()
defer f.tableSyncMu.Unlock()
for _, fixture := range f.fixtures { for _, fixture := range f.fixtures {
synced, existing := f.tableSynced[fixture.tableName] synced, existing := f.tableSyncMap.Load(fixture.tableName)
if synced || !existing { if synced == true || !existing {
continue continue
} }
if err := f.loadFixtures(tx, fixture); err != nil { if err := f.loadFixtures(tx, fixture); err != nil {
return fmt.Errorf("failed to load fixtures from %s: %w", fixture.fileFullPath, err) return fmt.Errorf("failed to load fixtures from %s: %w", fixture.fileFullPath, err)
} }
f.tableSynced[fixture.tableName] = true f.tableSyncMap.Store(fixture.tableName, true)
} }
if err = tx.Commit(); err != nil { if err = tx.Commit(); err != nil {
return err return err
} }
for tableName, synced := range f.tableSynced { f.tableSyncMap.Range(func(k, v any) bool {
tableName, _ := k.(string)
synced, _ := v.(bool)
if !synced && f.fixtures[tableName] == nil { if !synced && f.fixtures[tableName] == nil {
_, _ = f.xormEngine.Context(ctx).Exec("DELETE FROM `" + tableName + "`") _, _ = f.xormEngine.Context(ctx).Exec("DELETE FROM `" + tableName + "`")
} }
f.tableSynced[tableName] = true f.tableSyncMap.Store(tableName, true)
} return true
})
return nil return nil
} }
func (f *fixturesLoaderInternal) MarkTableChanged(tableName string) { func (f *fixturesLoaderInternal) MarkTableChanged(tableName string) {
f.tableSyncMu.Lock() f.tableSyncMap.Store(tableName, false)
defer f.tableSyncMu.Unlock()
f.tableSynced[tableName] = false
} }
func FixturesFileFullPaths(dir string, files []string) (map[string]*FixtureItem, error) { func FixturesFileFullPaths(dir string, files []string) (map[string]*FixtureItem, error) {
@@ -216,7 +213,7 @@ func NewFixturesLoader(x *xorm.Engine, opts FixturesOptions) (FixturesLoader, er
return nil, fmt.Errorf("failed to get fixtures files: %w", err) return nil, fmt.Errorf("failed to get fixtures files: %w", err)
} }
f := &fixturesLoaderInternal{xormEngine: x, db: x.DB().DB, dbType: x.Dialect().URI().DBType, fixtures: fixtureItems, tableSynced: map[string]bool{}} f := &fixturesLoaderInternal{xormEngine: x, db: x.DB().DB, dbType: x.Dialect().URI().DBType, fixtures: fixtureItems}
switch f.dbType { switch f.dbType {
case schemas.SQLITE: case schemas.SQLITE:
f.quoteObject = func(s string) string { return fmt.Sprintf(`"%s"`, s) } f.quoteObject = func(s string) string { return fmt.Sprintf(`"%s"`, s) }
@@ -237,7 +234,7 @@ func NewFixturesLoader(x *xorm.Engine, opts FixturesOptions) (FixturesLoader, er
xormBeans, _ := db.NamesToBean() xormBeans, _ := db.NamesToBean()
for _, bean := range xormBeans { for _, bean := range xormBeans {
beanTableName := x.TableName(bean) beanTableName := x.TableName(bean)
f.tableSynced[trimTableNameQuotes(beanTableName)] = false f.tableSyncMap.Store(trimTableNameQuotes(beanTableName), false)
} }
return f, nil return f, nil
} }