mirror of
https://github.com/lingble/talos.git
synced 2025-12-02 22:03:50 +00:00
This package provides a consistent way for us to retry arbitrary logic. It provides the following backoff algorithms: - exponential - linear - constant Signed-off-by: Andrew Rynhard <andrew@andrewrynhard.com>
173 lines
3.4 KiB
Go
173 lines
3.4 KiB
Go
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
// nolint: dupl
|
|
package retry
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// nolint: scopelint
|
|
func Test_linearRetryer_Retry(t *testing.T) {
|
|
type fields struct {
|
|
retryer retryer
|
|
}
|
|
|
|
type args struct {
|
|
f RetryableFunc
|
|
}
|
|
|
|
count := 0
|
|
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
args args
|
|
expectedCount int
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "test expected number of retries",
|
|
fields: fields{
|
|
retryer: retryer{
|
|
duration: 1 * time.Second,
|
|
options: NewDefaultOptions(WithUnits(100 * time.Millisecond)),
|
|
},
|
|
},
|
|
args: args{
|
|
f: func() error {
|
|
count++
|
|
return ExpectedError(fmt.Errorf("expected"))
|
|
},
|
|
},
|
|
expectedCount: 4,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "test expected number of retries with units",
|
|
fields: fields{
|
|
retryer: retryer{
|
|
duration: 2 * time.Second,
|
|
options: NewDefaultOptions(WithUnits(50 * time.Millisecond)),
|
|
},
|
|
},
|
|
args: args{
|
|
f: func() error {
|
|
count++
|
|
return ExpectedError(fmt.Errorf("expected"))
|
|
},
|
|
},
|
|
expectedCount: 9,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "test unexpected error",
|
|
fields: fields{
|
|
retryer: retryer{
|
|
duration: 2 * time.Second,
|
|
options: NewDefaultOptions(),
|
|
},
|
|
},
|
|
args: args{
|
|
f: func() error {
|
|
count++
|
|
return UnexpectedError(fmt.Errorf("unexpected"))
|
|
},
|
|
},
|
|
expectedCount: 1,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "test conditional unexpected error",
|
|
fields: fields{
|
|
retryer: retryer{
|
|
duration: 10 * time.Second,
|
|
options: NewDefaultOptions(),
|
|
},
|
|
},
|
|
args: args{
|
|
f: func() error {
|
|
count++
|
|
if count == 1 {
|
|
return UnexpectedError(fmt.Errorf("unexpected"))
|
|
}
|
|
return ExpectedError(fmt.Errorf("unexpected"))
|
|
},
|
|
},
|
|
expectedCount: 1,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "test conditional no error",
|
|
fields: fields{
|
|
retryer: retryer{
|
|
duration: 10 * time.Second,
|
|
options: NewDefaultOptions(),
|
|
},
|
|
},
|
|
args: args{
|
|
f: func() error {
|
|
count++
|
|
if count == 2 {
|
|
return nil
|
|
}
|
|
return ExpectedError(fmt.Errorf("unexpected"))
|
|
},
|
|
},
|
|
expectedCount: 2,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "no error",
|
|
fields: fields{
|
|
retryer: retryer{
|
|
duration: 1 * time.Second,
|
|
options: NewDefaultOptions(),
|
|
},
|
|
},
|
|
args: args{
|
|
f: func() error {
|
|
return nil
|
|
},
|
|
},
|
|
expectedCount: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "test timeout",
|
|
fields: fields{
|
|
retryer: retryer{
|
|
duration: 1 * time.Second,
|
|
options: NewDefaultOptions(WithUnits(10 * time.Second)),
|
|
},
|
|
},
|
|
args: args{
|
|
f: func() error {
|
|
count++
|
|
return ExpectedError(fmt.Errorf("expected"))
|
|
},
|
|
},
|
|
expectedCount: 1,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
l := linearRetryer{
|
|
retryer: tt.fields.retryer,
|
|
}
|
|
count = 0
|
|
if err := l.Retry(tt.args.f); (err != nil) != tt.wantErr {
|
|
t.Errorf("linearRetryer.Retry() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if count != tt.expectedCount {
|
|
t.Errorf("expected count of %d, got %d", tt.expectedCount, count)
|
|
}
|
|
})
|
|
}
|
|
}
|