1 package task
2
3 import (
4 "errors"
5 "testing"
6 "time"
7 )
8
9 func TestRetryable_RetryWithSchedule(t *testing.T) {
10 var empty struct{}
11 for _, tt := range []struct {
12 name string
13 runner func(nbInvocations int) (exitCondition bool, result interface{}, err error)
14 errorIfTimeout bool
15 schedule []time.Duration
16 wantErr bool
17 wantInvocations int
18 }{
19 {
20 name: "no schedule with runner returning no error",
21 runner: func(_ int) (exitCondition bool, result interface{}, err error) {
22 return false, empty, nil
23 },
24 wantInvocations: 1,
25 },
26 {
27 name: "no schedule with runner returning an error",
28 runner: func(_ int) (exitCondition bool, result interface{}, err error) {
29 return false, empty, errors.New("some error")
30 },
31 wantErr: true,
32 wantInvocations: 1,
33 },
34 {
35 name: "schedule with runner returning no error and exit condition never matched",
36 runner: func(_ int) (exitCondition bool, result interface{}, err error) {
37 return false, empty, nil
38 },
39 schedule: []time.Duration{
40 10 * time.Millisecond,
41 30 * time.Millisecond,
42 50 * time.Millisecond,
43 },
44 wantInvocations: 3,
45 },
46 {
47 name: "schedule with runner returning an error and exit condition never matched",
48 runner: func(_ int) (exitCondition bool, result interface{}, err error) {
49 return false, empty, errors.New("some error")
50 },
51 schedule: []time.Duration{
52 10 * time.Millisecond,
53 30 * time.Millisecond,
54 50 * time.Millisecond,
55 },
56 wantInvocations: 3,
57 wantErr: true,
58 },
59 {
60 name: "schedule with runner returning no error and exit condition never matched and error if timeout set to true",
61 runner: func(_ int) (exitCondition bool, result interface{}, err error) {
62 return false, empty, nil
63 },
64 schedule: []time.Duration{
65 10 * time.Millisecond,
66 30 * time.Millisecond,
67 50 * time.Millisecond,
68 },
69 wantInvocations: 3,
70 errorIfTimeout: true,
71 wantErr: true,
72 },
73 {
74 name: "schedule with runner returning an error and exit condition never matched and error if timeout set to true",
75 runner: func(_ int) (exitCondition bool, result interface{}, err error) {
76 return false, empty, errors.New("some error")
77 },
78 schedule: []time.Duration{
79 10 * time.Millisecond,
80 30 * time.Millisecond,
81 50 * time.Millisecond,
82 },
83 wantInvocations: 3,
84 errorIfTimeout: true,
85 wantErr: true,
86 },
87 {
88 name: "schedule with runner return no error and matching exit condition after 2nd invocation",
89 runner: func(n int) (exitCondition bool, result interface{}, err error) {
90 if n == 2 {
91 return true, empty, nil
92 }
93 return false, empty, nil
94 },
95 schedule: []time.Duration{
96 10 * time.Millisecond,
97 30 * time.Millisecond,
98 50 * time.Millisecond,
99 100 * time.Millisecond,
100 },
101 wantInvocations: 2,
102 },
103 {
104 name: "schedule with runner return an error and matching exit condition after 2nd invocation",
105 runner: func(n int) (exitCondition bool, result interface{}, err error) {
106 err = errors.New("some error")
107 if n == 2 {
108 return true, empty, err
109 }
110 return false, empty, err
111 },
112 schedule: []time.Duration{
113 10 * time.Millisecond,
114 30 * time.Millisecond,
115 50 * time.Millisecond,
116 100 * time.Millisecond,
117 },
118 wantInvocations: 2,
119 wantErr: true,
120 },
121 } {
122 t.Run(tt.name, func(t *testing.T) {
123 var nbRunnerInvocations int
124 _, err := NewRetryable(tt.name, func() (exitCondition bool, result interface{}, err error) {
125 nbRunnerInvocations++
126 return tt.runner(nbRunnerInvocations)
127 }).RetryWithSchedule(tt.schedule, tt.errorIfTimeout)
128
129 if tt.wantErr != (err != nil) {
130 t.Errorf("unexpected error %v, wantErr %v", err, tt.wantErr)
131 }
132 if tt.wantInvocations != nbRunnerInvocations {
133 t.Errorf("expected %d, got %d", tt.wantInvocations, nbRunnerInvocations)
134 }
135 })
136 }
137 }
138
View as plain text