package web import ( "io" "log" "sync" "sync/atomic" "testing" "time" ) // R-695 (v0.275.0) — the file-browser sync is single-flight: callers that queued behind a running sync // are covered by ONE sync that read the state after they asked, not by one restart each; a caller whose // request came after a sync began reading is never dropped. // // COMPANION RED-PROOF (REPORT.md): remove the `fbDoneGen >= mine` early return — five queued callers // then run five syncs. func TestR695_QueuedSyncsCoalesceIntoOne(t *testing.T) { s := &Server{logger: log.New(io.Discard, "", 0)} var runs int32 release := make(chan struct{}) first := true var fmu sync.Mutex s.syncFileBrowserHook = func() { atomic.AddInt32(&runs, 1) fmu.Lock() f := first first = false fmu.Unlock() if f { <-release // the first sync is slow: everything below queues behind it } } var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done(); s.SyncFileBrowserMounts() }() time.Sleep(50 * time.Millisecond) // the first sync holds the lock for i := 0; i < 5; i++ { wg.Add(1) go func() { defer wg.Done(); s.SyncFileBrowserMounts() }() } time.Sleep(50 * time.Millisecond) // all five are queued close(release) wg.Wait() if got := atomic.LoadInt32(&runs); got != 2 { t.Fatalf("%d syncs ran for 6 requests (1 running + 5 queued) — want 2: the running one and ONE that re-reads for the queue", got) } // A request after everything finished is never dropped. s.SyncFileBrowserMounts() if got := atomic.LoadInt32(&runs); got != 3 { t.Fatalf("a new request after the queue drained ran %d syncs in total, want 3", got) } }