From 79e51c87f2c28cb4de6a6547dc25520964111bd5 Mon Sep 17 00:00:00 2001 From: Vasanthdev2004 Date: Thu, 29 Oct 2026 14:32:35 +0530 Subject: [PATCH] test(swarm): wait for every slot to be released before checking the drain A finishing member's task reads Done before its slot is freed: the supervisor completes the task, removes the member and only then frees the slot in afterExit. The test waited for Done == 5 and checked the running count straight after, so a busy runner could see one slot still held. It now waits for the drain itself. --- internal/swarm/lifecycle_test.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/internal/swarm/lifecycle_test.go b/internal/swarm/lifecycle_test.go index 9f477bfb5..9f94d3665 100644 --- a/internal/swarm/lifecycle_test.go +++ b/internal/swarm/lifecycle_test.go @@ -148,10 +148,13 @@ func TestConcurrencyCapAndQueueDrains(t *testing.T) { } // Release everyone; the queue should drain one-per-slot until all are done. close(gate) - testutil.WaitFor(t, "all tasks done", func() bool { return sw.Coordinator().Summarize().Done == 5 }) - if team.Running() != 0 || team.QueueDepth() != 0 { - t.Fatalf("after drain running=%d queue=%d, want 0/0", team.Running(), team.QueueDepth()) - } + // A member's task reads Done before its slot is released: the supervisor + // completes the task, then removes the member and only then frees the slot + // in afterExit. So the counts are settled once the drain has finished, not + // the moment the fifth task reads Done, and the wait covers both. + testutil.WaitFor(t, "all tasks done and every slot released", func() bool { + return sw.Coordinator().Summarize().Done == 5 && team.Running() == 0 && team.QueueDepth() == 0 + }) if got := len(l.recorded()); got != 5 { t.Fatalf("launched %d members, want 5", got) }