Make tests that wait for concurrent work wait on the event or a condition with a long deadline (issue 1814)
A test that slept a fixed time and then asserted what a goroutine, process or watcher did failed under the checker's load. Each now waits for its positive evidence (a started baseline, a call counted, a state reached) within 30 s, and the concurrency-limit tests meet at a barrier instead of overlapping by sleep. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
@@ -310,7 +310,8 @@ func TestTheWatcherReloadsOnceAfterAChangeAndNeverIntoErrors(t *testing.T) {
|
||||
stop := make(chan struct{})
|
||||
defer close(stop)
|
||||
go w.Run(stop)
|
||||
time.Sleep(60 * time.Millisecond)
|
||||
// the baseline is taken once Since is set; a change written before that would be part of it
|
||||
waitFor(t, func() bool { return w.Status().Since != "" })
|
||||
os.MkdirAll(filepath.Join(dir, "config.d"), 0o755)
|
||||
os.WriteFile(filepath.Join(dir, "config.d", "50-x.conf"), []byte("b"), 0o644)
|
||||
os.WriteFile(filepath.Join(dir, "config"), []byte("aa"), 0o644)
|
||||
@@ -342,15 +343,21 @@ func TestAtItsStartTheWatcherReloadsWhatTheRunningI3HasNotLoaded(t *testing.T) {
|
||||
{map[string]string{cfg: "new", filepath.Join(dir, "config.d", "gone.conf"): "x"}, 1},
|
||||
} {
|
||||
var mu sync.Mutex
|
||||
reloads := 0
|
||||
reloads, asked := 0, 0
|
||||
w := &Watcher{Dir: dir, Every: 10 * time.Millisecond,
|
||||
Check: func() ([]ConfigError, error) { return nil, nil },
|
||||
Reload: func() error { mu.Lock(); reloads++; mu.Unlock(); return nil },
|
||||
Loaded: func() (map[string]string, error) { return c.loaded, nil },
|
||||
Loaded: func() (map[string]string, error) { mu.Lock(); asked++; mu.Unlock(); return c.loaded, nil },
|
||||
}
|
||||
stop := make(chan struct{})
|
||||
go w.Run(stop)
|
||||
time.Sleep(80 * time.Millisecond)
|
||||
// positive evidence first: the watcher asked i3 what it has loaded, then reloads
|
||||
// (want 1) or has had many rounds to do so (want 0)
|
||||
waitFor(t, func() bool { mu.Lock(); defer mu.Unlock(); return asked > 0 })
|
||||
if c.want > 0 {
|
||||
waitFor(t, func() bool { mu.Lock(); defer mu.Unlock(); return reloads >= c.want })
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
close(stop)
|
||||
mu.Lock()
|
||||
if reloads != c.want {
|
||||
@@ -361,11 +368,12 @@ func TestAtItsStartTheWatcherReloadsWhatTheRunningI3HasNotLoaded(t *testing.T) {
|
||||
}
|
||||
|
||||
func waitFor(t *testing.T, ok func() bool) {
|
||||
for i := 0; i < 200; i++ {
|
||||
t.Helper()
|
||||
for i := 0; i < 3000; i++ {
|
||||
if ok() {
|
||||
return
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
t.Fatal("timed out")
|
||||
t.Fatal("timed out after 30 s")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user