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:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
+1
-1
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user