From f110204d241a422eb7239a281728bd941c229707 Mon Sep 17 00:00:00 2001 From: Michael Fletcher Date: Fri, 10 Apr 2026 15:17:38 +0100 Subject: [PATCH 1/2] fix(test): prevent goroutine leak in PausableTicker and CronTicker tests PausableTicker.Destroy() stops the ticker but doesn't close the channel. Goroutines running for-range on Ticks() block forever, accumulating across -count=N iterations. Add done channels so goroutines exit when the test completes. Also reduce CronTicker verification sleep from 1s to 200ms. Fixes: CORE-2401 --- core/utils/utils_test.go | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/core/utils/utils_test.go b/core/utils/utils_test.go index 50ba08477b4..c11ff704af0 100644 --- a/core/utils/utils_test.go +++ b/core/utils/utils_test.go @@ -390,10 +390,21 @@ func TestPausableTicker(t *testing.T) { assert.Nil(t, pt.Ticks()) defer pt.Destroy() + done := make(chan struct{}) + defer close(done) + followNTicks := func(n int32, awaiter cltest.Awaiter) { - for range pt.Ticks() { - if counter.Add(1) == n { - awaiter.ItHappened() + for { + select { + case <-done: + return + case _, ok := <-pt.Ticks(): + if !ok { + return + } + if counter.Add(1) == n { + awaiter.ItHappened() + } } } } @@ -425,11 +436,20 @@ func TestCronTicker(t *testing.T) { assert.NoError(t, err) awaiter := cltest.NewAwaiter() + done := make(chan struct{}) go func() { - for range ct.Ticks() { - if counter.Add(1) == 2 { - awaiter.ItHappened() + for { + select { + case <-done: + return + case _, ok := <-ct.Ticks(): + if !ok { + return + } + if counter.Add(1) == 2 { + awaiter.ItHappened() + } } } }() @@ -443,8 +463,9 @@ func TestCronTicker(t *testing.T) { awaiter.AwaitOrFail(t) assert.True(t, ct.Stop()) + close(done) c := counter.Load() - time.Sleep(1 * time.Second) + time.Sleep(200 * time.Millisecond) assert.Equal(t, c, counter.Load()) } From 20facf3f9f425509f4934486aa10902c6e1b4c09 Mon Sep 17 00:00:00 2001 From: Michael Fletcher Date: Fri, 10 Apr 2026 18:41:53 +0100 Subject: [PATCH 2/2] revert CronTicker verification sleep back to 1s --- core/utils/utils_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/utils/utils_test.go b/core/utils/utils_test.go index c11ff704af0..cc518ce9a9c 100644 --- a/core/utils/utils_test.go +++ b/core/utils/utils_test.go @@ -465,7 +465,7 @@ func TestCronTicker(t *testing.T) { assert.True(t, ct.Stop()) close(done) c := counter.Load() - time.Sleep(200 * time.Millisecond) + time.Sleep(1 * time.Second) assert.Equal(t, c, counter.Load()) }