summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-13 14:35:27 +0300
committerPaul Buetow <paul@buetow.org>2026-05-13 14:35:27 +0300
commit306b9eb1c1054992506dd36fc9f1b64e11276598 (patch)
tree51cb6690961e64035bf85e95c212fbe34a5ea7d5 /internal
parented7cf2505d92e05411d476b445bda45cab9aaf89 (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')
-rw-r--r--internal/ior_mode_test.go15
-rw-r--r--internal/probemanager/manager_test.go24
2 files changed, 24 insertions, 15 deletions
diff --git a/internal/ior_mode_test.go b/internal/ior_mode_test.go
index 81fd314..a7c3bee 100644
--- a/internal/ior_mode_test.go
+++ b/internal/ior_mode_test.go
@@ -943,16 +943,17 @@ func testTracePair(seq uint64, comm string) *event.Pair {
return pair
}
+// waitForStreamRows asserts that buffer.Len() equals want immediately.
+// starter() returns only after the trace goroutine closes the started channel,
+// which happens after all printCb calls have completed and pushed their rows
+// into the buffer. The channel close forms a happens-before edge that makes all
+// prior writes visible to the test goroutine, so no polling or sleeping is
+// needed.
func waitForStreamRows(t *testing.T, buffer *streamrow.RingBuffer, want int) {
t.Helper()
- deadline := time.Now().Add(2 * time.Second)
- for time.Now().Before(deadline) {
- if buffer.Len() == want {
- return
- }
- time.Sleep(time.Millisecond)
+ if got := buffer.Len(); got != want {
+ t.Fatalf("stream buffer len = %d, want %d", got, want)
}
- t.Fatalf("stream buffer len = %d, want %d", buffer.Len(), want)
}
func readRecordedParquet(t *testing.T, path string) []parquet.Record {
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 {