148 lines
3.4 KiB
Go
148 lines
3.4 KiB
Go
package ws
|
|
|
|
import (
|
|
"github.com/stretchr/testify/assert"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestNewRetryManager(t *testing.T) {
|
|
config := &RetryConfig{
|
|
MaxRetries: 0,
|
|
}
|
|
|
|
mgr := NewRetryManager(config)
|
|
|
|
assert.Equal(t, config, mgr.config)
|
|
assert.Equal(t, 0, mgr.retryCount)
|
|
|
|
// Should accept nil config
|
|
mgr = NewRetryManager(nil)
|
|
assert.Nil(t, mgr.config)
|
|
assert.Equal(t, 0, mgr.retryCount)
|
|
}
|
|
|
|
func TestRecordRetry(t *testing.T) {
|
|
mgr := NewRetryManager(nil)
|
|
assert.Equal(t, mgr.retryCount, 0)
|
|
|
|
mgr.RecordRetry()
|
|
assert.Equal(t, mgr.retryCount, 1)
|
|
|
|
mgr.RecordRetry()
|
|
assert.Equal(t, mgr.retryCount, 2)
|
|
}
|
|
|
|
func TestShouldRetry(t *testing.T) {
|
|
// never retry if config is nil
|
|
mgr := NewRetryManager(nil)
|
|
assert.False(t, mgr.ShouldRetry())
|
|
|
|
// always retry if max attempt count is zero
|
|
mgr = &RetryManager{
|
|
config: &RetryConfig{
|
|
MaxRetries: 0,
|
|
},
|
|
retryCount: 1000,
|
|
}
|
|
assert.True(t, mgr.ShouldRetry())
|
|
|
|
// retry if below max attempt count
|
|
mgr = &RetryManager{
|
|
config: &RetryConfig{
|
|
MaxRetries: 10,
|
|
},
|
|
retryCount: 5,
|
|
}
|
|
assert.True(t, mgr.ShouldRetry())
|
|
|
|
// do not retry if above max attempt count
|
|
mgr = &RetryManager{
|
|
config: &RetryConfig{
|
|
MaxRetries: 10,
|
|
},
|
|
retryCount: 11,
|
|
}
|
|
assert.False(t, mgr.ShouldRetry())
|
|
}
|
|
|
|
func TestCalculateDelayDisabled(t *testing.T) {
|
|
// default delay if retry is disabled
|
|
mgr := NewRetryManager(nil)
|
|
assert.Equal(t, time.Second, mgr.CalculateDelay())
|
|
}
|
|
|
|
func TestCalculateDelayWithoutJitter(t *testing.T) {
|
|
mgr := NewRetryManager(&RetryConfig{
|
|
MaxRetries: 0,
|
|
InitialDelay: 1 * time.Second,
|
|
MaxDelay: 5 * time.Second,
|
|
JitterFactor: 0.0,
|
|
})
|
|
|
|
// Retry 0: immediate
|
|
assert.Equal(t, 0*time.Second, mgr.CalculateDelay())
|
|
mgr.RecordRetry()
|
|
|
|
// Retry 1: 1s * 2^0 = 1s
|
|
assert.Equal(t, 1*time.Second, mgr.CalculateDelay())
|
|
mgr.RecordRetry()
|
|
|
|
// Retry 2: 1s * 2^1 = 2s
|
|
assert.Equal(t, 2*time.Second, mgr.CalculateDelay())
|
|
mgr.RecordRetry()
|
|
|
|
// Retry 3: 1s * 2^2 = 4s
|
|
assert.Equal(t, 4*time.Second, mgr.CalculateDelay())
|
|
mgr.RecordRetry()
|
|
|
|
// Retry 4: 1s * 2^3 = 8s, capped at 5s
|
|
assert.Equal(t, 5*time.Second, mgr.CalculateDelay())
|
|
mgr.RecordRetry()
|
|
|
|
// Retry 5: Still capped at 5s
|
|
assert.Equal(t, 5*time.Second, mgr.CalculateDelay())
|
|
}
|
|
|
|
func TestCalculateDelayWithJitter(t *testing.T) {
|
|
mgr := NewRetryManager(&RetryConfig{
|
|
MaxRetries: 0,
|
|
InitialDelay: 1 * time.Second,
|
|
MaxDelay: 5 * time.Second,
|
|
JitterFactor: 0.5,
|
|
})
|
|
|
|
// Retry 0: immediate
|
|
assert.Equal(t, 0*time.Second, mgr.CalculateDelay())
|
|
mgr.RecordRetry()
|
|
|
|
// Retry 1: 1s * 2^0 = 1s (with jitter)
|
|
delay := mgr.CalculateDelay()
|
|
assert.GreaterOrEqual(t, delay, 750*time.Millisecond)
|
|
assert.LessOrEqual(t, delay, 1250*time.Millisecond)
|
|
mgr.RecordRetry()
|
|
|
|
// Retry 2: 1s * 2^1 = 2s (with jitter)
|
|
delay = mgr.CalculateDelay()
|
|
assert.GreaterOrEqual(t, delay, 1500*time.Millisecond)
|
|
assert.LessOrEqual(t, delay, 2500*time.Millisecond)
|
|
mgr.RecordRetry()
|
|
|
|
// Retry 3: 1s * 2^2 = 4s (with jitter)
|
|
delay = mgr.CalculateDelay()
|
|
assert.GreaterOrEqual(t, delay, 3*time.Second)
|
|
assert.LessOrEqual(t, delay, 5*time.Second)
|
|
mgr.RecordRetry()
|
|
|
|
// Retry 4: 1s * 2^3 = 8s, capped at 5s (with jitter)
|
|
delay = mgr.CalculateDelay()
|
|
assert.GreaterOrEqual(t, delay, 3750*time.Millisecond)
|
|
assert.LessOrEqual(t, delay, 5*time.Second)
|
|
mgr.RecordRetry()
|
|
|
|
// Retry 5: Still capped at 5s (with jitter)
|
|
delay = mgr.CalculateDelay()
|
|
assert.GreaterOrEqual(t, delay, 3750*time.Millisecond)
|
|
assert.LessOrEqual(t, delay, 5*time.Second)
|
|
}
|