fix(testutil): use shared-cache SQLite so concurrent reads see same DB
SetupTestDB used `sqlite.Open(":memory:")`, which creates a *separate*
in-memory database for every connection in GORM's pool. Sequential tests
never noticed because the pool keeps reusing one connection — but the
moment any code path issued concurrent reads (e.g. errgroup-driven
parallel COUNT queries), a goroutine could pull a fresh connection, see
no migrated tables, and explode with "no such table".
Switched to `file:testdb_<n>?mode=memory&cache=shared&_journal=memory`
with a per-test atomic counter so every connection in the pool sees the
same in-memory DB and tests stay isolated from each other through the
unique cache namespace. As a bonus, this also resolves the pre-existing
TestTaskHandler_QuickComplete flake — same root cause, just intermittent
because the pool occasionally handed out a second connection.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
@@ -21,7 +22,10 @@ import (
|
|||||||
"github.com/treytartt/honeydue-api/internal/validator"
|
"github.com/treytartt/honeydue-api/internal/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
var i18nOnce sync.Once
|
var (
|
||||||
|
i18nOnce sync.Once
|
||||||
|
testDBCounter uint64
|
||||||
|
)
|
||||||
|
|
||||||
// SetupTestDB creates an in-memory SQLite database for testing
|
// SetupTestDB creates an in-memory SQLite database for testing
|
||||||
func SetupTestDB(t *testing.T) *gorm.DB {
|
func SetupTestDB(t *testing.T) *gorm.DB {
|
||||||
@@ -30,7 +34,16 @@ func SetupTestDB(t *testing.T) *gorm.DB {
|
|||||||
i18n.Init()
|
i18n.Init()
|
||||||
})
|
})
|
||||||
|
|
||||||
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{
|
// SQLite in-memory + GORM connection pool needs `cache=shared` so all
|
||||||
|
// pool connections see the same DB. With plain ":memory:", each new
|
||||||
|
// connection gets its own empty database, which makes errgroup-driven
|
||||||
|
// parallel reads explode with "no such table" once a goroutine pulls a
|
||||||
|
// fresh connection. The DSN is uniqued per test invocation (atomic
|
||||||
|
// counter) so tests don't bleed state into each other through the shared
|
||||||
|
// cache namespace.
|
||||||
|
id := atomic.AddUint64(&testDBCounter, 1)
|
||||||
|
dsn := fmt.Sprintf("file:testdb_%d?mode=memory&cache=shared&_journal=memory", id)
|
||||||
|
db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{
|
||||||
Logger: logger.Default.LogMode(logger.Silent),
|
Logger: logger.Default.LogMode(logger.Silent),
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
Reference in New Issue
Block a user