From ded7bcb2c947341a829a92dc9a2d49322c948125 Mon Sep 17 00:00:00 2001 From: Andrew Wormald Date: Thu, 30 Apr 2026 12:24:15 +0100 Subject: [PATCH] adaptertest: fix goroutine/test lifecycle race in testReleasing require.NoError and require.ErrorIs were called inside goroutines that could outlive the test when the 5-second timeout path fired. Move all assertions into the test goroutine by communicating results back via buffered error channels. Co-Authored-By: Claude Sonnet 4.6 --- adapters/adaptertest/rolescheduler.go | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/adapters/adaptertest/rolescheduler.go b/adapters/adaptertest/rolescheduler.go index 6732473..8644070 100644 --- a/adapters/adaptertest/rolescheduler.go +++ b/adapters/adaptertest/rolescheduler.go @@ -76,18 +76,20 @@ func testReleasing(t *testing.T, factory func(t *testing.T, instances int) []wor ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) - passed := make(chan bool) + outerErr := make(chan error, 1) + innerErr := make(chan error, 1) + go func() { _, _, err := rs[0].Await(ctx, "leader-releasing") - require.NoError(t, err) + outerErr <- err + if err != nil { + return + } ctx2, cancel2 := context.WithCancel(context.Background()) go func() { _, _, err := rs[1].Await(ctx2, "leader-releasing") - require.ErrorIs(t, err, context.Canceled) - - // Record that the execution got here. - passed <- true + innerErr <- err }() // Cancel the other caller to test that it unlocks on context cancellation @@ -99,9 +101,10 @@ func testReleasing(t *testing.T, factory func(t *testing.T, instances int) []wor select { case <-timeout: require.FailNow(t, "not all instances obtained the lock") - return - case <-passed: - // Expected call stack executed + case err := <-outerErr: + require.NoError(t, err) + case err := <-innerErr: + require.ErrorIs(t, err, context.Canceled) return } }