From 4b429787d0fa9b7eff2c248e8f71a117dbe82bc5 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Thu, 15 Oct 2026 22:39:18 +0200 Subject: [PATCH] test(19.3-06): wait for the queued site-cache purge before asserting (WR-01) - every read of the purge receiver first drains the app's purger through cooler.SiteCachePurger.Wait, since cooler now queues purges after commit --- site_cache_admin_test.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/site_cache_admin_test.go b/site_cache_admin_test.go index f2546bd..11a54a7 100644 --- a/site_cache_admin_test.go +++ b/site_cache_admin_test.go @@ -1,6 +1,7 @@ package menu_test import ( + "context" "encoding/json" "fmt" "io" @@ -11,8 +12,10 @@ import ( "sync" "sync/atomic" "testing" + "time" "git.golem15.com/golem15/sm-menu-plugin/models" + "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/cooler" ) @@ -39,6 +42,9 @@ type purgeReceiver struct { got []purgeRequest status int probe func() string + // drain waits for the queued purges of the app under test; see + // drainFrom. + drain func() } func newPurgeReceiver(t *testing.T) *purgeReceiver { @@ -69,6 +75,12 @@ func newPurgeReceiver(t *testing.T) *purgeReceiver { } func (r *purgeReceiver) take() []purgeRequest { + r.mu.Lock() + drain := r.drain + r.mu.Unlock() + if drain != nil { + drain() + } r.mu.Lock() defer r.mu.Unlock() got := r.got @@ -76,6 +88,21 @@ func (r *purgeReceiver) take() []purgeRequest { return got } +// drainFrom makes every read of r first wait for the purges queued on app's +// site-cache purger: cooler queues them after commit and sends them in the +// background, so a save's purge is asserted only once it was sent. +func (r *purgeReceiver) drainFrom(t *testing.T, app *backpack.App) { + r.mu.Lock() + defer r.mu.Unlock() + r.drain = func() { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + if err := cooler.SiteCacheFromApp(app).Wait(ctx); err != nil { + t.Errorf("waiting for the queued site-cache purge: %v", err) + } + } +} + func (r *purgeReceiver) setStatus(status int) { r.mu.Lock() r.status = status @@ -124,6 +151,7 @@ func (r *purgeReceiver) expectNone(t *testing.T, stage string) { func TestMenuAdminPurgesSiteCache(t *testing.T) { recv := newPurgeReceiver(t) e := bootMenu(t) + recv.drainFrom(t, e.app) // SiteCacheFromApp reads the keys on the first save, so they can be set // after boot. if err := e.app.Config.Set(cooler.SiteCachePurgeURLKey, recv.srv.URL+purgeTestPath); err != nil {