diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-13 14:35:27 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-13 14:35:27 +0300 |
| commit | 306b9eb1c1054992506dd36fc9f1b64e11276598 (patch) | |
| tree | 51cb6690961e64035bf85e95c212fbe34a5ea7d5 /internal/probemanager | |
| parent | ed7cf2505d92e05411d476b445bda45cab9aaf89 (diff) | |
test: replace time.Sleep with deterministic synchronization in unit tests
Replace three time.Sleep usages in tests with channel-based and
happens-before reasoning:
- internal/ior_mode_test.go: waitForStreamRows no longer polls with
time.Sleep(1ms); starter() only returns after the trace goroutine
closes the started channel, which happens after all printCb pushes,
forming a happens-before edge that guarantees the rows are visible.
- internal/probemanager/manager_test.go: the intermediate attach-count
assertions (enter==1, exit==0) are now checked immediately after
<-enterBlocked, which is itself a happens-before edge, rather than
after a 50ms sleep. The concurrent goroutine 2 is started afterwards;
the final count assertions after both goroutines complete verify the
serialization invariant.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/probemanager')
| -rw-r--r-- | internal/probemanager/manager_test.go | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/internal/probemanager/manager_test.go b/internal/probemanager/manager_test.go index 2beb11e..b75a579 100644 --- a/internal/probemanager/manager_test.go +++ b/internal/probemanager/manager_test.go @@ -158,19 +158,27 @@ func TestManagerAttachSerializesConcurrentCalls(t *testing.T) { t.Fatal("first attach did not start") } - errCh2 := make(chan error, 1) - go func() { - errCh2 <- mgr.Attach("close") - }() - - time.Sleep(50 * time.Millisecond) + // Goroutine 1 is now blocked inside AttachTracepoint for the enter probe. + // Enter has been called exactly once; exit has not been called yet because + // attachPair calls enter then exit sequentially. These assertions are safe + // without any sleep: enterBlocked being closed is a happens-before edge that + // makes the attach-count writes visible here. if got := enter.attachCalls(); got != 1 { - t.Fatalf("expected only one enter attach while first call was in flight, got %d", got) + t.Fatalf("expected enter attach to be in flight (called once), got %d", got) } if got := exit.attachCalls(); got != 0 { - t.Fatalf("expected exit attach to wait for enter completion, got %d", got) + t.Fatalf("expected exit attach to not have started while enter is blocked, got %d", got) } + // Start a second concurrent Attach. It will acquire m.mu briefly then + // block on entry.attachMu (held by goroutine 1) before it can reach + // AttachTracepoint. The final count assertions below confirm it never ran + // a second attach. + errCh2 := make(chan error, 1) + go func() { + errCh2 <- mgr.Attach("close") + }() + close(releaseEnter) if err := <-errCh1; err != nil { |
