From 75b30c22100af8956f27b9f388d8fa6a2250db02 Mon Sep 17 00:00:00 2001 From: Seth Hoenig Date: Thu, 8 Sep 2022 09:13:35 -0500 Subject: [PATCH] helper: guard against negative inputs into random stagger This PR modifies RandomStagger to protect against negative input values. If the given interval is negative, the value returned will be somewhere in the stratosphere. Instead, treat negative inputs like zero, returning zero. --- .changelog/14497.txt | 3 +++ helper/cluster.go | 7 +++---- helper/cluster_test.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 .changelog/14497.txt create mode 100644 helper/cluster_test.go diff --git a/.changelog/14497.txt b/.changelog/14497.txt new file mode 100644 index 000000000..4b233f0ac --- /dev/null +++ b/.changelog/14497.txt @@ -0,0 +1,3 @@ +```release-note:bug +helpers: Fixed a bug where random stagger func did not protect against negative inputs +``` diff --git a/helper/cluster.go b/helper/cluster.go index e3fda8b23..1abca1481 100644 --- a/helper/cluster.go +++ b/helper/cluster.go @@ -1,4 +1,3 @@ -// These functions are coming from consul/lib/cluster.go package helper import ( @@ -13,11 +12,11 @@ const ( ) // RandomStagger returns an interval between 0 and the duration -func RandomStagger(intv time.Duration) time.Duration { - if intv == 0 { +func RandomStagger(interval time.Duration) time.Duration { + if interval <= 0 { return 0 } - return time.Duration(uint64(rand.Int63()) % uint64(intv)) + return time.Duration(uint64(rand.Int63()) % uint64(interval)) } // RateScaledInterval is used to choose an interval to perform an action in diff --git a/helper/cluster_test.go b/helper/cluster_test.go new file mode 100644 index 000000000..028db0b46 --- /dev/null +++ b/helper/cluster_test.go @@ -0,0 +1,29 @@ +package helper + +import ( + "testing" + "time" + + "github.com/shoenig/test/must" +) + +func TestCluster_RandomStagger(t *testing.T) { + cases := []struct { + name string + input time.Duration + }{ + {name: "positive", input: 1 * time.Second}, + {name: "negative", input: -1 * time.Second}, + {name: "zero", input: 0}, + } + + abs := func(d time.Duration) time.Duration { + return Max(d, -d) + } + + for _, tc := range cases { + result := RandomStagger(tc.input) + must.GreaterEq(t, result, 0) + must.LessEq(t, result, abs(tc.input)) + } +}