@@ -4,13 +4,16 @@ import (
44 "context"
55 "database/sql"
66 "fmt"
7+ "os"
78 "path/filepath"
89 "runtime"
910 "testing"
11+ "time"
1012
1113 "github.com/sirupsen/logrus"
1214 "github.com/sirupsen/logrus/hooks/test"
1315 "github.com/spiffe/spire/pkg/server/datastore/sqltest"
16+ "github.com/stretchr/testify/assert"
1417 "github.com/stretchr/testify/require"
1518)
1619
@@ -173,9 +176,35 @@ func TestConfigure(t *testing.T) {
173176 }
174177}
175178
179+ // removeDirWithRetry removes dir, retrying a few times on Windows where a
180+ // closed SQLite file handle may not be released immediately. On other
181+ // platforms a single RemoveAll always succeeds.
182+ func removeDirWithRetry (t * testing.T , dir string ) {
183+ const attempts = 20
184+ var err error
185+ for range attempts {
186+ if err = os .RemoveAll (dir ); err == nil {
187+ return
188+ }
189+ if runtime .GOOS != "windows" {
190+ break
191+ }
192+ time .Sleep (50 * time .Millisecond )
193+ }
194+ assert .NoError (t , err , "failed to remove migration temp dir %q" , dir )
195+ }
196+
176197func TestMigration (t * testing.T ) {
177198 ds := newTestPlugin (t )
178- dir := t .TempDir ()
199+
200+ // Use a dedicated directory instead of t.TempDir(): the migration DBs run
201+ // in WAL mode, and on Windows the SQLite file handle (plus its -wal/-shm
202+ // sidecars) is not always released synchronously when Close() returns.
203+ // t.TempDir()'s built-in RemoveAll fails hard on the first "file in use"
204+ // error, causing a flake; removeDirWithRetry retries instead.
205+ dir , err := os .MkdirTemp ("" , "migration" )
206+ require .NoError (t , err )
207+ t .Cleanup (func () { removeDirWithRetry (t , dir ) })
179208
180209 for schemaVersion := range latestSchemaVersion {
181210 t .Run (fmt .Sprintf ("migration_from_schema_version_%d" , schemaVersion ), func (t * testing.T ) {
0 commit comments