From 2eb6ea18b942ae2ac3ed54f09d4dab3032788d46 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Thu, 28 May 2026 10:26:53 +0300 Subject: fix(random): remove deprecated rand seeding (hq) --- internal/cli/throttle.go | 3 +-- internal/cli/throttle_test.go | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) (limited to 'internal/cli') diff --git a/internal/cli/throttle.go b/internal/cli/throttle.go index 5241782..3b85d10 100644 --- a/internal/cli/throttle.go +++ b/internal/cli/throttle.go @@ -162,8 +162,7 @@ func recordRepoSync(repoName string, st *state.State, throttle bool) { } func randomThrottleDuration() time.Duration { - rng := rand.New(rand.NewSource(time.Now().UnixNano())) - days := throttleMinDays + rng.Intn(throttleMaxDays-throttleMinDays+1) + days := throttleMinDays + rand.Intn(throttleMaxDays-throttleMinDays+1) return time.Duration(days) * 24 * time.Hour } diff --git a/internal/cli/throttle_test.go b/internal/cli/throttle_test.go index 6833fe4..57ed8ba 100644 --- a/internal/cli/throttle_test.go +++ b/internal/cli/throttle_test.go @@ -106,3 +106,26 @@ func TestRecordRepoSync_SetsThrottleWindowWhenThrottleEnabled(t *testing.T) { t.Fatalf("expected throttle window between %s and %s, got %s", minAllowed, maxAllowed, nextAllowed) } } + +func TestRandomThrottleDuration_WithinBoundsAndNotDegenerate(t *testing.T) { + const draws = 200 + + seen := map[time.Duration]struct{}{} + minDuration := time.Duration(throttleMinDays) * 24 * time.Hour + maxDuration := time.Duration(throttleMaxDays) * 24 * time.Hour + + for i := 0; i < draws; i++ { + d := randomThrottleDuration() + if d < minDuration || d > maxDuration { + t.Fatalf("expected duration between %s and %s, got %s", minDuration, maxDuration, d) + } + if d%(24*time.Hour) != 0 { + t.Fatalf("expected whole-day duration, got %s", d) + } + seen[d] = struct{}{} + } + + if len(seen) < 2 { + t.Fatalf("expected at least 2 distinct durations across %d draws, got %d", draws, len(seen)) + } +} -- cgit v1.2.3