From 8cefae503fba61805e59ab5cb16acafb2c49b706 Mon Sep 17 00:00:00 2001 From: William Dillon Date: Thu, 26 Feb 2026 19:55:48 -0500 Subject: [PATCH] debugging DefaltApplyJitter, adding tests --- fibonacci/fibonacci.go | 2 ++ fibonacci/fibonacci_test.go | 8 ----- utilities/jitter.go | 59 +++++++++++++++++++++++++++++++++---- utilities/jitter_test.go | 23 +++++++++++++++ 4 files changed, 79 insertions(+), 13 deletions(-) create mode 100644 utilities/jitter_test.go diff --git a/fibonacci/fibonacci.go b/fibonacci/fibonacci.go index d94c0fe..b790bfe 100644 --- a/fibonacci/fibonacci.go +++ b/fibonacci/fibonacci.go @@ -93,6 +93,8 @@ func Fibonacci(n int64) int64 { case n >= int64(len(TheFibonacciSequence)): panic(fmt.Sprintf("invalid input: %d overflows int64\n", n)) + case n < 0: + panic(fmt.Sprintf("invalid input: %d would cause index out of range panic\n", n)) default: return TheFibonacciSequence[n] } diff --git a/fibonacci/fibonacci_test.go b/fibonacci/fibonacci_test.go index 6b731f5..7d03840 100644 --- a/fibonacci/fibonacci_test.go +++ b/fibonacci/fibonacci_test.go @@ -2,19 +2,12 @@ package fibonacci import ( "context" - "fmt" - "math/big" "testing" "time" "code.wmdillon.com/wmdillon/backoff/utilities" ) -func wouldOverflow(a, b int64) (product int64, overflows bool) { - results := new(big.Int).Mul(big.NewInt(a), big.NewInt(b)) - return results.Int64(), results.IsInt64() -} - func fibonacci(n int64) int64 { switch { case n <= 0: @@ -129,7 +122,6 @@ func TestFibonacciPauseLimit(t *testing.T) { t.Fatalf("error for %d: expected value in range %s - %s; got %s\n", input, min, max, got) } } - fmt.Printf("finished\n") } func TestFibonacciBackoffAfter(t *testing.T) { diff --git a/utilities/jitter.go b/utilities/jitter.go index 2d0d923..40a409d 100644 --- a/utilities/jitter.go +++ b/utilities/jitter.go @@ -10,15 +10,64 @@ var ( ApplyJitter = DefaultApplyJitter ) +const ( + maxInt64 = math.MaxInt64 + minInt64 = math.MinInt64 +) + +func satAdd(a, b int64) int64 { + switch { + case b > 0 && a > maxInt64-b: + return maxInt64 + case b < 0 && a < minInt64-b: + return minInt64 + default: + return a + b + } +} + +func satSub(a, b int64) int64 { + switch { + case b > 0 && a < minInt64+b: + return minInt64 + case b < 0 && a > maxInt64+b: + return maxInt64 + default: + return a - b + } +} + func DefaultApplyJitter(pauseDuration time.Duration, jitter time.Duration) time.Duration { switch { - case jitter == 0, pauseDuration == 0: + case pauseDuration <= 0: + return 0 + case jitter == 0: return pauseDuration + case jitter < 0: + jitter = -jitter case jitter > pauseDuration: pauseDuration, jitter = jitter, pauseDuration } - min := pauseDuration.Nanoseconds() - jitter.Nanoseconds() - max := pauseDuration.Nanoseconds() + jitter.Nanoseconds() - rnd := int64(math.Max(float64(rand.Int64N(max-min)+min), 0)) - return time.Duration(rnd) + min := satSub(pauseDuration.Nanoseconds(), jitter.Nanoseconds()) + if min < 0 { + min = 0 + } + max := satAdd(pauseDuration.Nanoseconds(), jitter.Nanoseconds()) + if max <= min { + return time.Duration(min) + } + + var maxExcl int64 + if max == math.MaxInt64 { + span := max - min + if span == math.MaxInt64 { + return time.Duration(rand.Int64N(math.MaxInt64) + min) + } + n := rand.Int64N(span + 1) + return time.Duration(min + n) + } + + maxExcl = max + 1 + return time.Duration(min + rand.Int64N(maxExcl-min)) + } diff --git a/utilities/jitter_test.go b/utilities/jitter_test.go new file mode 100644 index 0000000..95059e7 --- /dev/null +++ b/utilities/jitter_test.go @@ -0,0 +1,23 @@ +package utilities + +import ( + "testing" + "time" +) + +func TestDefaultApplyJitterIsAlwaysGEZero(t *testing.T) { + if got := DefaultApplyJitter(maxInt64, time.Nanosecond); got < 0 { + t.Fatalf("error: wanted >= 0; got %s\n", got) + } + if got := DefaultApplyJitter(maxInt64, maxInt64); got < 0 { + t.Fatalf("error: wanted >= 0; got %s\n", got) + } +} + +func TestDefaultApplyJitterWithZeroPauseAlwaysZero(t *testing.T) { + for i := 0; i < 10; i++ { + if got := DefaultApplyJitter(0, time.Duration(i)); got != 0 { + t.Fatalf("error: wanted 0; got %s\n", got) + } + } +}