From 3223d919b04818cc3aea24562c12e17de2516be3 Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 26 May 2026 07:06:54 +0200 Subject: [PATCH] test: fix flaky `TestResourceIndex` and reduce its runtime (#37847) The modernc SQLite driver (default since https://github.com/go-gitea/gitea/pull/37562) returns `SQLITE_BUSY` once the busy timeout is reached, unlike mattn which waited indefinitely. `TestResourceIndex` fires many concurrent `NewIssue` writers, but SQLite serializes all writers, so they queue on a single `BEGIN IMMEDIATE` write lock. Under `-race` (modernc is much slower) the goroutines at the back of the queue exceeded the hardcoded 5s test timeout, producing `database is locked (5) (SQLITE_BUSY)`. Changes: - Reduce the concurrent inserts from 25 to 10. Since SQLite serializes writers, the extra goroutines only deepen the busy-lock queue without adding coverage. 10 still exercises concurrent index allocation while cutting the test's `-race` runtime ~3x (2.76s to 0.86s locally). - Share the busy-timeout constant: export `DefaultSQLiteBusyTimeout` (20s, the production default) and reference it from the test engine instead of the hardcoded `5000`. Observed flake: https://github.com/go-gitea/gitea/actions/runs/26394082930/job/77690496092 --- This PR was written with the help of Claude Opus 4.7 --------- Co-authored-by: Claude (Opus 4.7) --- AGENTS.md | 2 +- models/issues/issue_test.go | 2 +- models/unittest/testdb.go | 2 +- modules/setting/database.go | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 2331da486aa..a4cb7db74ce 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,7 +7,7 @@ - Run single playwright e2e test files with `GITEA_TEST_E2E_FLAGS='' make test-e2e` - Add the current year into the copyright header of new `.go` files - Ensure no trailing whitespace in edited files -- Use Conventional Commits format for commit messages and PR titles (for example `type(scope): subject`; place `!` immediately before the colon when the change is breaking) +- Use Conventional Commits for commit messages and PR titles, e.g. `type(scope): subject`; `!` before the colon if breaking. Use `test` type for test-only changes. - Never force-push, amend, or squash unless asked. Use new commits and normal push for pull request updates - Preserve existing code comments, do not remove or rewrite comments that are still relevant - Keep comments short, prefer same-line, explain why, never narrate code diff --git a/models/issues/issue_test.go b/models/issues/issue_test.go index 99a09de0ec5..1202d8216dc 100644 --- a/models/issues/issue_test.go +++ b/models/issues/issue_test.go @@ -299,7 +299,7 @@ func TestIssue_ResolveMentions(t *testing.T) { func TestResourceIndex(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) var wg sync.WaitGroup - for i := range 25 { + for i := range 10 { wg.Go(func() { testInsertIssue(t, fmt.Sprintf("issue %d", i+1), "my issue", 0) }) diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go index 2a87a02fcde..4bcb109924f 100644 --- a/models/unittest/testdb.go +++ b/models/unittest/testdb.go @@ -207,7 +207,7 @@ type FixturesOptions struct { // CreateTestEngine creates a test database and loads the fixture data from fixturesDir func CreateTestEngine(testSQLiteFile string, opts FixturesOptions) error { - driver, connStr, err := db.ConnStr(db.ConnOptions{Type: setting.DatabaseTypeSQLite3, SQLitePath: testSQLiteFile, SQLiteBusyTimeout: 5000}) + driver, connStr, err := db.ConnStr(db.ConnOptions{Type: setting.DatabaseTypeSQLite3, SQLitePath: testSQLiteFile, SQLiteBusyTimeout: setting.DefaultSQLiteBusyTimeout}) if err != nil { return err } diff --git a/modules/setting/database.go b/modules/setting/database.go index edaaf32c14d..639f54f7343 100644 --- a/modules/setting/database.go +++ b/modules/setting/database.go @@ -8,7 +8,7 @@ import ( "time" ) -const defaultSQLiteBusyTimeout = 20 * 1000 +const DefaultSQLiteBusyTimeout = 20 * 1000 var ( // SupportedDatabaseTypes includes all XORM supported databases type, sqlite3 maybe added by the tag-controlled drivers @@ -66,11 +66,11 @@ func loadDBSetting(rootCfg ConfigProvider) { Database.Path = sec.Key("PATH").MustString(filepath.Join(AppDataPath, "gitea.db")) - Database.SQLiteBusyTimeout = sec.Key("SQLITE_TIMEOUT").MustInt(defaultSQLiteBusyTimeout) + Database.SQLiteBusyTimeout = sec.Key("SQLITE_TIMEOUT").MustInt(DefaultSQLiteBusyTimeout) // mattn driver isn't really affected by this timeout, but other drivers are affected // the default value was 500 (0.5s), to avoid breaking existing users, make sure the timeout is long enough (at least, 5 seconds) if Database.SQLiteBusyTimeout < 5000 { - Database.SQLiteBusyTimeout = defaultSQLiteBusyTimeout + Database.SQLiteBusyTimeout = DefaultSQLiteBusyTimeout } Database.SQLiteJournalMode = sec.Key("SQLITE_JOURNAL_MODE").MustString("")