From 4fca268dc6ffa4f601b346b9e8d4f7d8807ff945 Mon Sep 17 00:00:00 2001 From: Dmitry Verkhoturov Date: Sat, 22 Aug 2026 04:06:58 +0100 Subject: [PATCH] Pin staging ages in TestFsStore_Cleanup instead of sleeping (#2191) The test slept 200ms, ran Cleanup with a 300ms TTL and then asserted the second and third staged images survived. Cleanup collects anything older than the TTL plus a 100ms commit grace, and the second image was already 300ms old by then, so a runner that stalled ~100ms anywhere in the setup aged it past the line and the assertion failed with "file on staging". Age comes from the file's modification time, so the test now sets it with os.Chtimes on both sides of the boundary immediately before each Cleanup call: the image meant to be collected is backdated an hour, the ones meant to survive are stamped at now. That leaves no window for a stall to age a file into the wrong bucket, and drops 600ms of sleeping. Verified by injecting a stall into the setup: 250ms reproduces the failure on the current code, while the version here survives 2s. --- backend/app/store/image/fs_store_test.go | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/backend/app/store/image/fs_store_test.go b/backend/app/store/image/fs_store_test.go index a68db322..5478ca50 100644 --- a/backend/app/store/image/fs_store_test.go +++ b/backend/app/store/image/fs_store_test.go @@ -215,15 +215,24 @@ func TestFsStore_Cleanup(t *testing.T) { return img } + // age is read from the file's modification time, so every file gets its mtime stamped right + // before each call: far past the ttl for the ones meant to go, at now for the ones meant to + // survive, leaving no window for a stalled runner to age a survivor into the wrong bucket + const ttl = 300 * time.Millisecond + age := func(file string, d time.Duration) { + mtime := time.Now().Add(-d) + require.NoError(t, os.Chtimes(file, mtime, mtime)) + } + // save 3 images to staging img1 := save("blah_ff1.png", "user1") - time.Sleep(100 * time.Millisecond) img2 := save("blah_ff2.png", "user1") - time.Sleep(100 * time.Millisecond) img3 := save("blah_ff3.png", "user2") - time.Sleep(200 * time.Millisecond) // make first image expired - err := svc.Cleanup(context.Background(), time.Millisecond*300) + age(img1, time.Hour) // past the ttl, collected + age(img2, 0) // fresh, survives + age(img3, 0) + err := svc.Cleanup(context.Background(), ttl) assert.NoError(t, err) _, err = os.Stat(img1) @@ -242,10 +251,11 @@ func TestFsStore_Cleanup(t *testing.T) { _, err = os.Stat(img3) assert.NoError(t, err, "file on staging") - time.Sleep(200 * time.Millisecond) // make all images expired + age(img2, time.Hour) + age(img3, time.Hour) err = svc.ResetCleanupTimer("user2/blah_ff3.png") // reset the time to cleanup for third image assert.NoError(t, err) - err = svc.Cleanup(context.Background(), time.Millisecond*300) + err = svc.Cleanup(context.Background(), ttl) assert.NoError(t, err) _, err = os.Stat(img2)