-
Notifications
You must be signed in to change notification settings - Fork 0
/
healthchecker_test.go
134 lines (125 loc) · 3.53 KB
/
healthchecker_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package goodroutine
import "testing"
import "errors"
func TestHealthChecker(t *testing.T) {
type testRun struct {
zerr error
numRuns int
current bool
expected bool
}
tests := []struct {
name string
initial bool
thresholdUp int
thresholdDown int
runs []testRun
}{
{"updownup", true, 3, 5, []testRun{
{nil, 10, true, true},
{errors.New("error"), 10, true, false},
{nil, 10, false, true},
}},
{"staydown", true, 3, 3, []testRun{
{errors.New("error"), 10, true, false},
{nil, 2, false, false},
{errors.New("error"), 10, false, false},
{nil, 2, false, false},
{errors.New("error"), 10, false, false},
{nil, 3, false, true},
}},
{"stayup", false, 3, 3, []testRun{
{nil, 10, false, true},
{errors.New("error"), 2, true, true},
{nil, 10, true, true},
{errors.New("error"), 2, true, true},
{nil, 10, true, true},
{errors.New("error"), 3, true, false},
}},
{"nothreshold", false, 0, -42, []testRun{
{nil, 1, false, true},
{errors.New("error"), 1, true, false},
{nil, 1, false, true},
{errors.New("error"), 1, true, false},
{nil, 10, false, true},
{errors.New("error"), 3, true, false},
}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f := func() error {
return nil
}
hc := NewHealthChecker(RunnerFunc(f), tt.initial, tt.thresholdUp, tt.thresholdDown)
hc.FastStart = false
// test default
hc.OnUp = func(numUps int, numDowns int) {
t.Errorf("Should not be called, numUps=%d, numDowns=%d", numUps, numDowns)
}
hc.OnDown = func(numUps int, numDowns int, lastErr error) {
t.Errorf("Should not be called, numUps=%d, numDowns=%d", numUps, numDowns)
}
if g, w := hc.IsUp(), tt.initial; g != w {
t.Errorf("Initial state invalid, got=%v, want=%v", g, w)
}
for _, run := range tt.runs {
testStateChange(t, hc, run.zerr, run.numRuns, run.current, run.expected)
}
})
}
}
func testStateChange(t *testing.T, hc *HealthChecker, checkErr error, numRuns int, current bool, expected bool) {
hc.runner = RunnerFunc(func() error {
return checkErr
})
callback := false
hc.OnUp = func(numUps int, numDowns int) {
if expected && !current {
callback = true
if g, w := numUps, hc.thresholdUp; g != w {
t.Errorf("Incorrect param, got=%v, want=%v", g, w)
}
} else {
t.Errorf("Should not be called, numUps=%d, numDowns=%d", numUps, numDowns)
}
}
hc.OnDown = func(numUps int, numDowns int, lastErr error) {
if !expected && current {
callback = true
if g, w := numDowns, hc.thresholdDown; g != w {
t.Errorf("Incorrect param, got=%v, want=%v", g, w)
}
} else {
t.Errorf("Should not be called, numUps=%d, numDowns=%d", numUps, numDowns)
}
}
for i := 0; i < numRuns; i++ {
err := hc.IntervalRun()
if g, w := err, checkErr; g != w {
t.Errorf("Error does not match, got=%v, want=%v", g, w)
}
if expected != current {
// it will take until threshold
threshold := hc.thresholdUp
if !expected {
threshold = hc.thresholdDown
}
if i < threshold-1 {
if g, w := hc.IsUp(), !expected; g != w {
t.Errorf("State changed too quickly at i=%d, got=%v, want=%v", i, g, w)
}
} else {
if g, w := hc.IsUp(), expected; g != w {
t.Errorf("State should have changed at i=%d, got=%v, want=%v", i, g, w)
}
}
} else {
if g, w := hc.IsUp(), expected; g != w {
t.Errorf("State should not have changed at i=%d, got=%v, want=%v", i, g, w)
}
}
}
if expected != current && !callback {
t.Errorf("Callback not called")
}
}