0f3e935228
* feat: calculate retry wait time with exponential back-off * test: add test for getWaitTime method * feat: enforce random jitter between min value from previous iteration and current * extract randomStagger to simplify tests and use Milliseconds to avoid float math. * rename variables * add test and rename comment --------- Co-authored-by: Poonam Jadhav <poonam.jadhav@hashicorp.com>
199 lines
4.4 KiB
Go
199 lines
4.4 KiB
Go
package lib
|
|
|
|
import (
|
|
"github.com/stretchr/testify/require"
|
|
"math"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestDurationMinusBuffer(t *testing.T) {
|
|
tests := []struct {
|
|
Duration time.Duration
|
|
Buffer time.Duration
|
|
Jitter int64
|
|
}{
|
|
{
|
|
Duration: 1 * time.Minute,
|
|
Buffer: 10 * time.Second,
|
|
Jitter: 16,
|
|
},
|
|
{
|
|
Duration: 1 * time.Second,
|
|
Buffer: 500 * time.Millisecond,
|
|
Jitter: 4,
|
|
},
|
|
{
|
|
Duration: 1 * time.Second,
|
|
Buffer: 1 * time.Second,
|
|
Jitter: 4,
|
|
},
|
|
{
|
|
Duration: 1 * time.Second,
|
|
Buffer: 1 * time.Second,
|
|
Jitter: 0,
|
|
},
|
|
{
|
|
Duration: 1 * time.Second,
|
|
Buffer: 1 * time.Second,
|
|
Jitter: 1,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
min, max := DurationMinusBufferDomain(test.Duration, test.Buffer, test.Jitter)
|
|
for i := 0; i < 10; i++ {
|
|
d := DurationMinusBuffer(test.Duration, test.Buffer, test.Jitter)
|
|
if d < min || d > max {
|
|
t.Fatalf("Bad: %v", d)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDurationMinusBufferDomain(t *testing.T) {
|
|
tests := []struct {
|
|
Duration time.Duration
|
|
Buffer time.Duration
|
|
Jitter int64
|
|
Min time.Duration
|
|
Max time.Duration
|
|
}{
|
|
{
|
|
Duration: 60 * time.Second,
|
|
Buffer: 10 * time.Second,
|
|
Jitter: 16,
|
|
Min: 46*time.Second + 875*time.Millisecond,
|
|
Max: 50 * time.Second,
|
|
},
|
|
{
|
|
Duration: 60 * time.Second,
|
|
Buffer: 0 * time.Second,
|
|
Jitter: 16,
|
|
Min: 56*time.Second + 250*time.Millisecond,
|
|
Max: 60 * time.Second,
|
|
},
|
|
{
|
|
Duration: 60 * time.Second,
|
|
Buffer: 0 * time.Second,
|
|
Jitter: 0,
|
|
Min: 60 * time.Second,
|
|
Max: 60 * time.Second,
|
|
},
|
|
{
|
|
Duration: 60 * time.Second,
|
|
Buffer: 0 * time.Second,
|
|
Jitter: 1,
|
|
Min: 0 * time.Second,
|
|
Max: 60 * time.Second,
|
|
},
|
|
{
|
|
Duration: 60 * time.Second,
|
|
Buffer: 0 * time.Second,
|
|
Jitter: 2,
|
|
Min: 30 * time.Second,
|
|
Max: 60 * time.Second,
|
|
},
|
|
{
|
|
Duration: 60 * time.Second,
|
|
Buffer: 0 * time.Second,
|
|
Jitter: 4,
|
|
Min: 45 * time.Second,
|
|
Max: 60 * time.Second,
|
|
},
|
|
{
|
|
Duration: 0 * time.Second,
|
|
Buffer: 0 * time.Second,
|
|
Jitter: 0,
|
|
Min: 0 * time.Second,
|
|
Max: 0 * time.Second,
|
|
},
|
|
{
|
|
Duration: 60 * time.Second,
|
|
Buffer: 120 * time.Second,
|
|
Jitter: 8,
|
|
Min: -1 * (52*time.Second + 500*time.Millisecond),
|
|
Max: -1 * 60 * time.Second,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
min, max := DurationMinusBufferDomain(test.Duration, test.Buffer, test.Jitter)
|
|
if min != test.Min {
|
|
t.Errorf("Bad min: %v != %v", min, test.Min)
|
|
}
|
|
|
|
if max != test.Max {
|
|
t.Errorf("Bad max: %v != %v", max, test.Max)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRandomStagger(t *testing.T) {
|
|
intv := time.Minute
|
|
for i := 0; i < 10; i++ {
|
|
stagger := RandomStagger(intv)
|
|
if stagger < 0 || stagger >= intv {
|
|
t.Fatalf("Bad: %v", stagger)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRateScaledInterval(t *testing.T) {
|
|
const min = 1 * time.Second
|
|
rate := 200.0
|
|
if v := RateScaledInterval(rate, min, 0); v != min {
|
|
t.Fatalf("Bad: %v", v)
|
|
}
|
|
if v := RateScaledInterval(rate, min, 100); v != min {
|
|
t.Fatalf("Bad: %v", v)
|
|
}
|
|
if v := RateScaledInterval(rate, min, 200); v != 1*time.Second {
|
|
t.Fatalf("Bad: %v", v)
|
|
}
|
|
if v := RateScaledInterval(rate, min, 1000); v != 5*time.Second {
|
|
t.Fatalf("Bad: %v", v)
|
|
}
|
|
if v := RateScaledInterval(rate, min, 5000); v != 25*time.Second {
|
|
t.Fatalf("Bad: %v", v)
|
|
}
|
|
if v := RateScaledInterval(rate, min, 10000); v != 50*time.Second {
|
|
t.Fatalf("Bad: %v", v)
|
|
}
|
|
halfMin := minRate / 2.0
|
|
if v := RateScaledInterval(halfMin, min, 100); v != min {
|
|
t.Fatalf("Bad: %v", v)
|
|
}
|
|
if v := RateScaledInterval(0, min, 10000); v != min {
|
|
t.Fatalf("Bad: %v", v)
|
|
}
|
|
if v := RateScaledInterval(0.0, min, 10000); v != min {
|
|
t.Fatalf("Bad: %v", v)
|
|
}
|
|
if v := RateScaledInterval(-1, min, 10000); v != min {
|
|
t.Fatalf("Bad: %v", v)
|
|
}
|
|
}
|
|
|
|
func TestRandomStaggerWithRange(t *testing.T) {
|
|
type args struct {
|
|
min time.Duration
|
|
max time.Duration
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
}{
|
|
{"min-max 0", args{time.Duration(0), time.Duration(0)}},
|
|
{"min-max big", args{time.Duration(math.MaxInt64), time.Duration(math.MaxInt64)}},
|
|
{"normal case", args{time.Duration(3), time.Duration(7)}},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := RandomStaggerWithRange(tt.args.min, tt.args.max)
|
|
require.GreaterOrEqual(t, got, tt.args.min)
|
|
require.LessOrEqual(t, got, tt.args.max)
|
|
})
|
|
}
|
|
}
|