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:
2026-11-01 17:24:19 +01:00
parent 3d1a450406
commit b3fcf408f2
52 changed files with 144 additions and 91 deletions
@@ -215,7 +215,7 @@ func TestTheSeatSweepsAtABuildsEndOnARealBusOnceTheLeaseIsAway(t *testing.T) {
t.Fatal(err)
}
ended()
deadline := time.Now().Add(5 * time.Second)
deadline := time.Now().Add(30 * time.Second)
for {
mu.Lock()
n := len(gone)
@@ -171,7 +171,7 @@ func TestTheSwitcherDoesNotActOnAnotherModel(t *testing.T) {
go func() { sw.Run(context.Background()); close(done) }()
select {
case <-done:
case <-time.After(2 * time.Second):
case <-time.After(30 * time.Second):
t.Fatal("the switcher ran on another model")
}
if r := sw.Report(); r.Running || r.Disabled == "" || len(f.calls) != 0 {
+1 -1
View File
@@ -181,7 +181,7 @@ func standInCapture(release <-chan struct{}, fail error) func(ctx context.Contex
// waitFor polls until the condition holds.
func waitFor(t *testing.T, what string, cond func() bool) {
t.Helper()
for i := 0; i < 400; i++ {
for i := 0; i < 3000; i++ {
if cond() {
return
}
+1 -1
View File
@@ -181,7 +181,7 @@ func TestAFinishedGlassDocumentIsNotFiledAgainByItsExpiry(t *testing.T) {
if _, err := r.call(t, "scanner.scan", docArgs(id, true)); err != nil {
t.Fatal(err)
}
time.Sleep(400 * time.Millisecond)
waitFor(t, "the expired document to be closed and filed", func() bool { e, _ := os.ReadDir(folder); return len(e) >= 1 })
if e, _ := os.ReadDir(folder); len(e) != 1 {
t.Errorf("%d files, want 1", len(e))
}
@@ -311,8 +311,13 @@ func TestASlowUploadAndPrintAnswersStartedNeverATimeout(t *testing.T) {
}
got, _ = r.call(t, "printer.print", map[string]any{"path": "/home/ops/.ssh/id_ed25519", "node": "g14"})
id2, _ := got.(map[string]any)["ask"].(string)
time.Sleep(300 * time.Millisecond)
if _, err := r.call(t, "printer.print", map[string]any{"ask": id2}); err == nil || !strings.Contains(err.Error(), "refused by name") {
t.Errorf("the failed upload's outcome: %v", err)
var outcome error
for end := time.Now().Add(30 * time.Second); time.Now().Before(end); time.Sleep(10 * time.Millisecond) {
if _, outcome = r.call(t, "printer.print", map[string]any{"ask": id2}); outcome != nil {
break
}
}
if outcome == nil || !strings.Contains(outcome.Error(), "refused by name") {
t.Errorf("the failed upload's outcome: %v", outcome)
}
}
@@ -505,7 +505,7 @@ func TestTheHelperReadsOnlyARegularFile(t *testing.T) {
if a.Err == "" || len(a.Data) != 0 {
t.Fatalf("%s was read: %q", path, a.Data)
}
case <-time.After(5 * time.Second):
case <-time.After(30 * time.Second):
t.Fatalf("reading %s held the helper", path)
}
}
@@ -567,7 +567,7 @@ func TestAHelperThatDoesNotAnswerFailsTheRequestInTime(t *testing.T) {
if err == nil || !errors.Is(err, errHelperSlow) {
t.Fatalf("a silent helper answered: %v", err)
}
if time.Since(start) > 2*time.Second {
if time.Since(start) > 30*time.Second {
t.Fatalf("the request waited %s", time.Since(start))
}
}
@@ -133,7 +133,7 @@ func TestAJudgementWaitsItsTurnWithinTheBound(t *testing.T) {
if err == nil || !strings.Contains(err.Error(), "another judgement") {
t.Fatalf("%v", err)
}
if time.Since(start) > 2*time.Second {
if time.Since(start) > 30*time.Second {
t.Fatal("waited past the bound")
}
}
@@ -175,7 +175,7 @@ func TestALongJudgementIsCollectedByItsTicket(t *testing.T) {
j := testJudge(true, true, func(ctx context.Context, _ []string, _ []byte) ([]byte, error) {
deadline, _ = ctx.Deadline()
select {
case <-time.After(400 * time.Millisecond):
case <-time.After(1500 * time.Millisecond): // well past Wait, however loaded the machine
return []byte(`{"structured_output":{"verdict":"none"}}`), nil
case <-ctx.Done():
return nil, ctx.Err()
@@ -191,7 +191,7 @@ func TestALongJudgementIsCollectedByItsTicket(t *testing.T) {
t.Fatalf("not a ticket: %+v", out)
}
var got *Judged
for i := 0; i < 100; i++ {
for i := 0; i < 600; i++ {
got, err = j.Collect(out.Ticket)
if err != nil {
t.Fatal(err)
@@ -223,12 +223,12 @@ func TestALongJudgementIsBoundedAndSaysWhyItFailed(t *testing.T) {
t.Fatalf("a bound past the most taken: %v", err)
}
j.Wait = 20 * time.Millisecond
j.Bound = 30 * time.Millisecond // the test's stand-in for JudgeBound: within is past it, so a ticket
out, err := j.Judge(JudgeAsk{Question: "q", Schema: verdictSchema, Within: 200 * time.Millisecond})
j.Bound = time.Second // the test's stand-in for JudgeBound: within is past it, so a ticket; far past Wait on a loaded machine
out, err := j.Judge(JudgeAsk{Question: "q", Schema: verdictSchema, Within: 2 * time.Second})
if err != nil || !out.Pending {
t.Fatalf("%+v %v", out, err)
}
for i := 0; i < 100; i++ {
for i := 0; i < 3000; i++ {
got, err := j.Collect(out.Ticket)
if err != nil {
if !strings.Contains(err.Error(), "did not answer within") {
@@ -950,11 +950,11 @@ func TestTheWatchHandlerReturnsAtOnceAndDrainAppliesWhatItNoted(t *testing.T) {
if err != nil {
t.Fatal(err)
}
case <-time.After(2 * time.Second):
case <-time.After(30 * time.Second):
t.Fatalf("the watch handler waited for the look or the state (%d of 400 returned)", i)
}
}
if took := time.Since(start); took > time.Second {
if took := time.Since(start); took > 30*time.Second {
t.Fatalf("400 values took %s to hand over", took)
}
shanks.mu.Unlock()
@@ -670,7 +670,7 @@ func TestTheRoutersRefusalIsSaidAndDiscards(t *testing.T) {
r.kinds = nil
refusing := &refusingRouter{router: r, p: p, store: store}
within, every := RouterAnswersWithin, RouterAnswersEvery
RouterAnswersWithin, RouterAnswersEvery = time.Second, 10*time.Millisecond
RouterAnswersWithin, RouterAnswersEvery = 30*time.Second, 10*time.Millisecond
t.Cleanup(func() { RouterAnswersWithin, RouterAnswersEvery = within, every })
_, err := Propose(p, ProposeInput{Scope: ScopeMesh, Name: "x", Text: "Text.\n"}, store, refusing, t0)
if err == nil || !strings.Contains(err.Error(), "no channel can carry any of its answers now") ||
@@ -223,7 +223,7 @@ func TestTheRoutersRefusalIsSaidAndKept(t *testing.T) {
store := newMemQuestions()
refusing := &questionRefusingRouter{router: newRouter(), store: store}
within, every := RouterAnswersWithin, RouterAnswersEvery
RouterAnswersWithin, RouterAnswersEvery = time.Second, 10*time.Millisecond
RouterAnswersWithin, RouterAnswersEvery = 30*time.Second, 10*time.Millisecond
t.Cleanup(func() { RouterAnswersWithin, RouterAnswersEvery = within, every })
_, err := AskQuestion(p, mergeTonight(), store, refusing, t0)
if err == nil || !strings.Contains(err.Error(), "may not leave the mesh") {
@@ -303,7 +303,7 @@ func TestAReadWaitsNoLongerThanItsBound(t *testing.T) {
if err != nil || out["state"] != AnswerWaiting {
t.Fatalf("%v %v", out, err)
}
if took := time.Since(start); took > 2*time.Second {
if took := time.Since(start); took > 30*time.Second {
t.Errorf("a read asked to wait an hour took %s", took)
}
}
@@ -123,25 +123,27 @@ func TestTheLauncherUsesTheManagersDisplayAndWaitsOtherwise(t *testing.T) {
os.MkdirAll(fakeBin, 0o755)
// the manager's environment: empty until the file appears
os.WriteFile(fakeBin+"/systemctl", []byte("#!/bin/sh\n[ -f \""+dir+"/env\" ] && cat \""+dir+"/env\"\nexit 0\n"), 0o755)
run := func(env ...string) (string, bool) {
ctx, cancel := context.WithTimeout(context.Background(), 2500*time.Millisecond)
// wait is how long the launcher may run: a launcher that must answer gets a generous bound (the checker runs
// thousands of tests at once, issue 1814); one that must keep waiting is cut off after a short one
run := func(wait time.Duration, env ...string) (string, bool) {
ctx, cancel := context.WithTimeout(context.Background(), wait)
defer cancel()
cmd := exec.CommandContext(ctx, "sh", file)
cmd.Env = append([]string{"PATH=" + fakeBin + ":" + os.Getenv("PATH"), "HOME=" + dir}, env...)
out, _ := cmd.Output()
return strings.TrimSpace(string(out)), ctx.Err() == nil
}
if out, ok := run("DISPLAY=:7"); !ok || out != "DISPLAY=:7" {
if out, ok := run(30*time.Second, "DISPLAY=:7"); !ok || out != "DISPLAY=:7" {
t.Fatalf("with DISPLAY: %q %v", out, ok)
}
if _, ok := run(); ok {
if _, ok := run(2500 * time.Millisecond); ok {
t.Fatal("it exited with no X server")
}
for _, n := range []string{"X0", "X1"} {
l, _ := net.Listen("unix", dir+"/x11/"+n)
defer l.Close()
}
if _, ok := run(); ok {
if _, ok := run(2500 * time.Millisecond); ok {
t.Fatal("it chose one of two servers")
}
// the session hands the manager its display while the launcher waits
@@ -149,7 +151,7 @@ func TestTheLauncherUsesTheManagersDisplayAndWaitsOtherwise(t *testing.T) {
time.Sleep(1200 * time.Millisecond)
os.WriteFile(dir+"/env", []byte("DISPLAY=:1\nOTHER=x\n"), 0o644)
}()
if out, ok := run(); !ok || out != "DISPLAY=:1" {
if out, ok := run(30 * time.Second); !ok || out != "DISPLAY=:1" {
t.Fatalf("the display that arrived while waiting: %q %v", out, ok)
}
}
+2 -2
View File
@@ -422,11 +422,11 @@ func TestRunWithoutABusSaysItStalledAndReconnects(t *testing.T) {
}, nil)
w.state = filepath.Join(t.TempDir(), "bus")
w.retry = 20 * time.Millisecond
ctx, cancel := context.WithTimeout(context.Background(), 6*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 40*time.Second)
defer cancel()
done := make(chan struct{})
go func() { w.Run(ctx); close(done) }()
deadline := time.Now().Add(6 * time.Second)
deadline := time.Now().Add(30 * time.Second)
for time.Now().Before(deadline) && !w.Snapshot().Connected {
time.Sleep(50 * time.Millisecond)
}
+2 -2
View File
@@ -181,10 +181,10 @@ func readingOf(s *memStore, key string) *health.Reading {
func waitFor(t *testing.T, done func() bool) {
t.Helper()
for end := time.Now().Add(5 * time.Second); time.Now().Before(end); time.Sleep(5 * time.Millisecond) {
for end := time.Now().Add(30 * time.Second); time.Now().Before(end); time.Sleep(5 * time.Millisecond) {
if done() {
return
}
}
t.Fatal("not done within 5 s")
t.Fatal("not done within 30 s")
}
@@ -43,8 +43,12 @@ func TestJobsASlowActIsAnsweredRunningWithItsID(t *testing.T) {
t.Fatalf("%+v", j)
}
close(release)
time.Sleep(50 * time.Millisecond)
got, _ := jobByID(j.ID)
var got Job
for end := time.Now().Add(30 * time.Second); time.Now().Before(end); time.Sleep(5 * time.Millisecond) {
if got, _ = jobByID(j.ID); !got.Running {
break
}
}
if got.Running {
t.Fatalf("finished afterwards: %+v", got)
}
@@ -47,7 +47,7 @@ func TestANotificationsChosenAnswerIsSaidAsAnEvent(t *testing.T) {
if !strings.Contains(string(asked), "[--expire-time=0][--wait][--action=a1b2=Release][--action=c3d4=Stop][--]") {
t.Fatalf("notify-send was asked %s", asked)
}
deadline := time.Now().Add(3 * time.Second)
deadline := time.Now().Add(30 * time.Second)
for {
mu.Lock()
n := len(said)
@@ -43,8 +43,12 @@ func TestJobsASlowActIsAnsweredRunningWithItsID(t *testing.T) {
t.Fatalf("%+v", j)
}
close(release)
time.Sleep(50 * time.Millisecond)
got, _ := jobByID(j.ID)
var got Job
for end := time.Now().Add(30 * time.Second); time.Now().Before(end); time.Sleep(5 * time.Millisecond) {
if got, _ = jobByID(j.ID); !got.Running {
break
}
}
if got.Running {
t.Fatalf("finished afterwards: %+v", got)
}
@@ -569,7 +569,7 @@ func TestKeepRunningStartsTheProviderAgainAfterARefusedWatch(t *testing.T) {
}()
select {
case <-serving:
case <-time.After(5 * time.Second):
case <-time.After(30 * time.Second):
t.Fatal("the provider was not started again after its watch was refused")
}
stop()
+14 -6
View File
@@ -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")
}
@@ -252,7 +252,7 @@ func TestRunRepairsWhenNudged(t *testing.T) {
c, cancel := context.WithCancel(ctx)
defer cancel()
go w.g.Run(c)
deadline := time.Now().Add(5 * time.Second)
deadline := time.Now().Add(30 * time.Second)
for w.g.State() != AdminOK {
if time.Now().After(deadline) {
t.Fatal("no first check")
@@ -108,7 +108,7 @@ func movedWorld(t *testing.T, h *harness.Harness) (f *fakeKeycloak, start func()
Offers: map[string]provider.Offer{ProvisionName: {Credential: provider.PerConsumer, Serves: servedValues(testIssuer)}},
Make: run.Make, Gone: run.Gone, Every: h.Every, Logf: func(string, ...any) {}})
return f, func() {
runCtx, cancel := context.WithTimeout(ctx, 2*time.Second)
runCtx, cancel := context.WithTimeout(ctx, 60*time.Second)
t.Cleanup(cancel)
go func() { _ = run.Run(runCtx, p, bus) }()
}
@@ -69,7 +69,7 @@ func TestTheGrantPathLeavesWhenTheConsumersFileIsFilled(t *testing.T) {
}
select {
case <-done:
case <-time.After(2 * time.Second):
case <-time.After(30 * time.Second):
t.Fatal("did not leave when the file was filled")
}
}
@@ -59,7 +59,7 @@ func TestAPulledAskRunsTheBuildAndItsKeyNamesTheReference(t *testing.T) {
go p.Pull(ctx)
key, _ := delivery.AskStepKey("ace", a.ID)
var step delivery.Step
for deadline := time.Now().Add(3 * time.Second); ; time.Sleep(5 * time.Millisecond) {
for deadline := time.Now().Add(30 * time.Second); ; time.Sleep(5 * time.Millisecond) {
states.mu.Lock()
v := states.steps[key]
states.mu.Unlock()
@@ -246,7 +246,7 @@ func TestTheCallAnswersAStepIdBeforeTheFetchEnds(t *testing.T) {
if key != "ace."+id {
t.Errorf("ended %s", key)
}
case <-time.After(3 * time.Second):
case <-time.After(30 * time.Second):
t.Fatal("the step never ended")
}
states.mu.Lock()
@@ -106,12 +106,23 @@ func TestTheLintOfManyDirectoriesRunsAtOnceUpToTheBound(t *testing.T) {
tree := writeTree(t, files)
var mu sync.Mutex
running, most := 0, 0
release := make(chan struct{}) // closed once two run at once: they overlap however slowly the machine starts them
run := func(ctx context.Context, env []string, name string, args ...string) forgekey.Ran {
mu.Lock()
running++
most = max(most, running)
if running >= 2 {
select {
case <-release:
default:
close(release)
}
}
mu.Unlock()
time.Sleep(30 * time.Millisecond)
select {
case <-release:
case <-time.After(30 * time.Second):
}
mu.Lock()
running--
mu.Unlock()
@@ -65,7 +65,7 @@ func (s *keptStates) waitEnd(t *testing.T) delivery.Step {
defer s.mu.Unlock()
v := s.steps[key]
return v[len(v)-1]
case <-time.After(3 * time.Second):
case <-time.After(30 * time.Second):
t.Fatal("the step never ended on its key")
return delivery.Step{}
}
@@ -86,7 +86,7 @@ func TestStartWritesTheToolchainAndHealthIsHealthy(t *testing.T) {
defer stop()
go m.Start(ctx)
var tc delivery.Toolchain
for deadline := time.Now().Add(3 * time.Second); time.Now().Before(deadline); time.Sleep(5 * time.Millisecond) {
for deadline := time.Now().Add(30 * time.Second); time.Now().Before(deadline); time.Sleep(5 * time.Millisecond) {
if got, ok := states.toolchain("ace.go"); ok {
tc = got
break
@@ -122,7 +122,7 @@ func TestSelectedDirectoriesRunAtOnceAndAnswerInDirectoryOrder(t *testing.T) {
mu.Unlock()
select {
case <-release:
case <-time.After(10 * time.Second):
case <-time.After(30 * time.Second):
}
mu.Lock()
running--
@@ -163,7 +163,7 @@ func TestIntegrationLevelRunsAgainstARealStoreAndBusAndLeavesNothing(t *testing.
if len(entries) != 1 || entries[0].Name() != "tree" {
t.Errorf("the workspace holds %v, want only its tree: the run directory is gone", entries)
}
for deadline := time.Now().Add(5 * time.Second); len(processesNamed(work)) > 0 && time.Now().Before(deadline); time.Sleep(100 * time.Millisecond) {
for deadline := time.Now().Add(30 * time.Second); len(processesNamed(work)) > 0 && time.Now().Before(deadline); time.Sleep(100 * time.Millisecond) {
}
if left := processesNamed(work); len(left) > 0 {
t.Errorf("processes of the run are left: %v", left)
@@ -86,6 +86,7 @@ func TestAFailedVerifyLeavesNoMark(t *testing.T) {
func TestDownloadsRunSideBySideUpToTheBound(t *testing.T) {
var mu sync.Mutex
running, most := 0, 0
release := make(chan struct{}) // closed once two run at once: they overlap however slowly the machine starts them
f := &fakeStep{gomods: "a/go.mod\nb/go.mod\nc/go.mod\nd/go.mod\n", files: map[string]string{
"a/go.mod": "a\n", "b/go.mod": "b\n", "c/go.mod": "c\n", "d/go.mod": "d\n"}}
f.goRule = func(line string) forgekey.Ran {
@@ -95,8 +96,18 @@ func TestDownloadsRunSideBySideUpToTheBound(t *testing.T) {
if running > most {
most = running
}
if running == 2 && most == 2 {
select {
case <-release:
default:
close(release)
}
}
mu.Unlock()
time.Sleep(40 * time.Millisecond)
select {
case <-release:
case <-time.After(30 * time.Second):
}
mu.Lock()
running--
mu.Unlock()
@@ -198,7 +198,7 @@ func TestOnlyATextFileIsRead(t *testing.T) {
if err == nil || !strings.Contains(err.Error(), "fifo") {
t.Errorf("a fifo: %v", err)
}
case <-time.After(5 * time.Second):
case <-time.After(30 * time.Second):
t.Fatal("a read of a fifo waits for a writer")
}
}
@@ -50,7 +50,7 @@ func (s *served) call(t *testing.T, verb, caller string, args map[string]any) (m
var line []byte
select {
case line = <-done:
case <-time.After(5 * time.Second):
case <-time.After(30 * time.Second):
t.Fatalf("%s was not answered", verb)
}
var m struct {
@@ -380,7 +380,7 @@ func TestTheKnowledgeBaseOverTheBus(t *testing.T) {
t.Fatalf("history: %+v", h)
}
// Every change said on the bus, as the module, with who acted.
deadline := time.Now().Add(5 * time.Second)
deadline := time.Now().Add(30 * time.Second)
for time.Now().Before(deadline) && len(w.of(EventProposed)) == 0 {
time.Sleep(50 * time.Millisecond)
}
@@ -46,7 +46,7 @@ func whoCalled(t *testing.T, params map[string]any) string {
select {
case who := <-got:
return who
case <-time.After(3 * time.Second):
case <-time.After(30 * time.Second):
t.Fatal("the call was not answered")
return ""
}
@@ -38,7 +38,7 @@ func TestRunStartsTheWatcherEvenWhenStdinIsAtEOF(t *testing.T) {
select {
case <-started:
case <-time.After(time.Second):
case <-time.After(30 * time.Second):
t.Fatal("the watcher was not started before stdio.Serve returned")
}
@@ -47,7 +47,7 @@ func TestRunStartsTheWatcherEvenWhenStdinIsAtEOF(t *testing.T) {
if err != nil {
t.Fatalf("run over stdin at EOF: %v", err)
}
case <-time.After(time.Second):
case <-time.After(30 * time.Second):
t.Fatal("run did not return once stdin reached EOF, as systemd gives a process nobody talks to")
}
@@ -55,12 +55,12 @@ func TestRunStartsTheWatcherEvenWhenStdinIsAtEOF(t *testing.T) {
// not yet torn down. A watcher that stopped when run returned would never take this ping.
select {
case ping <- struct{}{}:
case <-time.After(time.Second):
case <-time.After(30 * time.Second):
t.Fatal("the watcher is no longer running once run returned: it must not stop just because stdio.Serve did")
}
select {
case <-pong:
case <-time.After(time.Second):
case <-time.After(30 * time.Second):
t.Fatal("the watcher did not answer once run returned")
}
close(ping)
@@ -98,13 +98,13 @@ func TestWatchRetriesASubscribeRefusalWithBackoffAndNeverExits(t *testing.T) {
if err != nil {
t.Fatalf("run over stdin at EOF: %v", err)
}
case <-time.After(time.Second):
case <-time.After(30 * time.Second):
t.Fatal("run did not return once stdin reached EOF: a subscribe refusal must not hold up or kill the process")
}
select {
case <-subscribed:
case <-time.After(time.Second):
case <-time.After(30 * time.Second):
t.Fatal("the watcher never subscribed after its first two refusals")
}
@@ -127,7 +127,7 @@ func TestThirtyWaitingMailsRunAsThreeBatchesAtLeast160sApart(t *testing.T) {
}()
select {
case <-done:
case <-time.After(5 * time.Second):
case <-time.After(30 * time.Second):
t.Fatal("RunBatches did not stop after its own 3rd batch and this test's cancel")
}
@@ -39,7 +39,7 @@ func aToolRunner(t *testing.T, b *aBus) *toolRunner {
func (r *toolRunner) ask(body string) Answered {
r.t.Helper()
var a Answered
deadline := time.Now().Add(10 * time.Second)
deadline := time.Now().Add(30 * time.Second)
for {
msg, err := r.nc.Request(AskSubject(node), []byte(body), 2*time.Second)
if err == nil {
@@ -83,7 +83,7 @@ func (b *aBus) placed(t *testing.T, module string) {
func until(t *testing.T, heard chan string, want string) {
t.Helper()
deadline := time.After(10 * time.Second)
deadline := time.After(30 * time.Second)
for {
select {
case got := <-heard:
@@ -404,10 +404,10 @@ func aClient(t *testing.T, b *aBus, e *engine, state string) (*Client, func()) {
func eventually(t *testing.T, what string, ok func() bool) {
t.Helper()
deadline := time.Now().Add(10 * time.Second)
deadline := time.Now().Add(30 * time.Second)
for !ok() {
if time.Now().After(deadline) {
t.Fatalf("not within 10s: %s", what)
t.Fatalf("not within 30s: %s", what)
}
time.Sleep(20 * time.Millisecond)
}
@@ -502,7 +502,8 @@ func TestNatsAChangeRefillsWritesOnceAndTheProgramTakesIt(t *testing.T) {
// again (ADR 0349 clause 5), which answers unchanged, so the program is not reloaded for it.
b.config(t, "dunst", "font-size", "15")
b.config(t, "dunst", "geometry", `"300x5"`)
time.Sleep(300 * time.Millisecond)
eventually(t, "the node-engine is asked for the file again by each fill", func() bool { _, asked := e.counts(dunstrc); return asked >= 3 })
time.Sleep(300 * time.Millisecond) // any stray extra write would come now
if moved, asked := e.counts(dunstrc); moved != 2 || asked != 3 {
t.Errorf("two values wrote dunstrc %d times (asked %d); want 2 and 3: the program is reloaded once a change, "+
"the file asked again each fill", moved, asked)
@@ -83,7 +83,7 @@ func TestWatchSocketWakesWhenTheSocketIsMadeAndWhenItsDirectoryReturns(t *testin
t.Helper()
select {
case <-up:
case <-time.After(5 * time.Second):
case <-time.After(30 * time.Second):
t.Fatalf("no wake for %s", what)
}
}
@@ -214,7 +214,7 @@ func TestOnlyATextFileIsRead(t *testing.T) {
if err == nil || !strings.Contains(err.Error(), "fifo") {
t.Errorf("a fifo: %v", err)
}
case <-time.After(5 * time.Second):
case <-time.After(30 * time.Second):
t.Fatal("a read of a fifo waits for a writer")
}
}
@@ -175,7 +175,7 @@ authorization {
controller := connectAs(t, url, "controller")
ask = func(name, key string) (Answer, error) {
raw, _ := json.Marshal(map[string]string{"name": name, "public_key": key})
msg, err := controller.Request("mesh.seat.mesh-vault.call.get.controller", raw, 3*time.Second)
msg, err := controller.Request("mesh.seat.mesh-vault.call.get.controller", raw, 30*time.Second)
if err != nil {
return Answer{}, err
}
@@ -170,7 +170,7 @@ func TestOnARealBusANodeEngineStatesOnlyItsOwnKey(t *testing.T) {
call := func(user, subject string, args any) (json.RawMessage, error) {
raw, _ := json.Marshal(args)
msg, err := connectAs(t, s.ClientURL(), user).Request(subject, raw, 3*time.Second)
msg, err := connectAs(t, s.ClientURL(), user).Request(subject, raw, 30*time.Second)
if err != nil {
return nil, err
}
@@ -882,7 +882,7 @@ func TestBreakGlassIsAFileRootMadeAndTheMinuteGoesOn(t *testing.T) {
go func() { h.Tick(); close(done) }()
select {
case <-done:
case <-time.After(5 * time.Second):
case <-time.After(30 * time.Second):
t.Fatal("the router's minute hung on a break-glass file")
}
}
@@ -552,7 +552,7 @@ func TestTheRootFreeWordIsNotAskedWhileTheWorkIsHeld(t *testing.T) {
}()
select {
case <-linked:
case <-time.After(2 * time.Second):
case <-time.After(30 * time.Second):
close(slow)
t.Fatal("a link waited for the controller's root-free word: the work was held while it was asked")
}
+2 -2
View File
@@ -126,12 +126,12 @@ func TestTheActingProcessClearsBetweenItsLooks(t *testing.T) {
go func() { RunApply(ctx, a); close(done) }()
defer func() { cancel(); <-done }()
if !waitFor(t, 2*time.Second, func() bool { return f.called("systemctl enable --now srv-library.automount") }) {
if !waitFor(t, 30*time.Second, func() bool { return f.called("systemctl enable --now srv-library.automount") }) {
t.Fatal("the first look did not arm the pair")
}
// The server is away and someone opened the mount point: the mount failed after the look.
f.setUnit("srv-library.mount", map[string]string{"ActiveState": "failed", "Result": "timeout"})
if !waitFor(t, 2*time.Second, func() bool { return f.called("systemctl reset-failed srv-library.mount") }) {
if !waitFor(t, 30*time.Second, func() bool { return f.called("systemctl reset-failed srv-library.mount") }) {
t.Fatal("a mount that failed between looks, its server away, is cleared before the next look")
}
}
@@ -576,7 +576,7 @@ func TestTheSnapshotUserCannotChangeTheBus(t *testing.T) {
if !strings.Contains(strings.ToLower(e.Error()), "permissions violation") {
t.Errorf("%s: %v", subject, e)
}
case <-time.After(2 * time.Second):
case <-time.After(30 * time.Second):
t.Errorf("the server did not refuse %s", subject)
}
}
@@ -590,7 +590,7 @@ func TestTheSnapshotUserCannotChangeTheBus(t *testing.T) {
if !strings.Contains(strings.ToLower(e.Error()), "permissions violation") {
t.Errorf("subscribing %s: %v", subject, e)
}
case <-time.After(2 * time.Second):
case <-time.After(30 * time.Second):
t.Errorf("the server let the snapshot user subscribe %s", subject)
}
}
@@ -48,7 +48,7 @@ func TestTheGrantPathLeavesWhenTheConsumersFileIsFilled(t *testing.T) {
}
select {
case <-done:
case <-time.After(2 * time.Second):
case <-time.After(30 * time.Second):
t.Fatal("did not leave when the file was filled")
}
}
@@ -140,7 +140,7 @@ func TestARetiredItemIsDeletedOnlyAfterALastRestorePoint(t *testing.T) {
wait := func(path string) Deletion {
t.Helper()
for i := 0; i < 200; i++ {
for i := 0; i < 6000; i++ {
if d, err := b.DeletedOutcome(path); err == nil && d.Done {
return d
}
@@ -229,7 +229,7 @@ func TestANightWaitsForAnotherProcesssNight(t *testing.T) {
release()
select {
case <-done:
case <-time.After(5 * time.Second):
case <-time.After(30 * time.Second):
t.Fatal("the night did not run once the other let go")
}
}
@@ -170,7 +170,12 @@ func TestAnInhibitionTurnsIdleOffAndRestoresWhatWasThereWhenItEndsOrIsStopped(t
if err := cmd.Start(); err != nil {
t.Fatal(err)
}
time.Sleep(300 * time.Millisecond)
// stop it only once it has turned idle off: the trap is set before that, and a slow start must not be signalled early
for end := time.Now().Add(30 * time.Second); time.Now().Before(end); time.Sleep(10 * time.Millisecond) {
if b, _ := os.ReadFile(filepath.Join(dir, "log")); strings.Contains(string(b), "s off -dpms") {
break
}
}
_ = cmd.Process.Signal(os.Interrupt)
_ = cmd.Wait()
got, _ := os.ReadFile(filepath.Join(dir, "log"))
@@ -31,10 +31,10 @@ func TestAStuckReadIsUnhealthyAndDoesNotStopTheOtherDrives(t *testing.T) {
if err != nil {
t.Fatal(err)
}
case <-time.After(5 * time.Second):
case <-time.After(30 * time.Second):
t.Fatal("a look waited on a stuck drive")
}
deadline := time.Now().Add(5 * time.Second)
deadline := time.Now().Add(30 * time.Second)
for {
_ = w.write()
r, _ := m.ReadReadings(DrivesPath)
@@ -267,7 +267,7 @@ func TestSweepDoesNotOpenAPipe(t *testing.T) {
if err != nil {
t.Fatal(err)
}
case <-time.After(2 * time.Second):
case <-time.After(30 * time.Second):
t.Fatal("the sweep blocked on a pipe")
}
}
@@ -185,7 +185,7 @@ func TestTheVerbsOnTheMachine(t *testing.T) {
defer cancel()
sock := filepath.Join(g.Dir, "verbs.sock")
go func() { _ = g.Serve(ctx, sock) }()
for i := 0; i < 100; i++ {
for i := 0; i < 3000; i++ {
if _, err := os.Stat(sock); err == nil {
break
}
@@ -233,7 +233,7 @@ func TestTheVerbsOnTheMachine(t *testing.T) {
select {
case <-g.wake:
g.Tick()
case <-time.After(time.Second):
case <-time.After(30 * time.Second):
t.Fatal("taking the write did not wake the guard")
}
if contentOf(t, g.Path) != meshFile {
+5 -3
View File
@@ -26,11 +26,11 @@ func TestATimedOutCommandIsEndedWithItsChildren(t *testing.T) {
KillGrace = 300 * time.Millisecond
defer func() { KillGrace = old }()
pidFile := filepath.Join(t.TempDir(), "child")
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Millisecond)
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) // long enough for a loaded machine to start the shell and write the pid
defer cancel()
start := time.Now()
r := ExecRunner(ctx, "sh", "-c", "sleep 30 & echo $! > "+pidFile+"; wait")
if took := time.Since(start); took > 5*time.Second {
if took := time.Since(start); took > 30*time.Second {
t.Fatalf("the call waited %s for a child holding its output", took)
}
if !r.TimedOut {
@@ -41,7 +41,9 @@ func TestATimedOutCommandIsEndedWithItsChildren(t *testing.T) {
t.Fatal(err)
}
pid, _ := strconv.Atoi(strings.TrimSpace(string(b)))
time.Sleep(100 * time.Millisecond)
// the kill is sent before the answer; give the system up to 30 s to take the child away
for end := time.Now().Add(30 * time.Second); time.Now().Before(end) && syscall.Kill(pid, 0) == nil; time.Sleep(10 * time.Millisecond) {
}
if err := syscall.Kill(pid, 0); err == nil {
syscall.Kill(pid, syscall.SIGKILL)
t.Errorf("the child %d outlived the timeout", pid)