package web import ( "sync" "sync/atomic" "testing" "time" ) func TestDashboardSnapshotCacheSharesConcurrentBuildAndInvalidates(t *testing.T) { cache := newDashboardSnapshotCache(time.Minute) var builds atomic.Int32 build := func() (map[string]any, error) { builds.Add(1) time.Sleep(15 * time.Millisecond) return map[string]any{"ok": true}, nil } var wait sync.WaitGroup for range 12 { wait.Add(1) go func() { defer wait.Done() value, _, err := cache.Get("24h", build) if err != nil || value["ok"] != true { t.Errorf("Get returned value=%#v err=%v", value, err) } }() } wait.Wait() if got := builds.Load(); got != 1 { t.Fatalf("concurrent cache builds = %d, want 1", got) } cache.Invalidate() if _, hit, err := cache.Get("24h", build); err != nil || hit { t.Fatalf("invalidated cache returned hit=%v err=%v", hit, err) } if got := builds.Load(); got != 2 { t.Fatalf("builds after invalidation = %d, want 2", got) } }