1
18
19 package balancer
20
21 import (
22 "testing"
23
24 "google.golang.org/grpc/connectivity"
25 "google.golang.org/grpc/internal/grpctest"
26 )
27
28 type s struct {
29 grpctest.Tester
30 }
31
32 func Test(t *testing.T) {
33 grpctest.RunSubTests(t, s{})
34 }
35
36
37
38
39 func (s) TestRecordTransition_FirstStateChange(t *testing.T) {
40 tests := []struct {
41 newState connectivity.State
42 wantState connectivity.State
43 }{
44 {
45 newState: connectivity.Idle,
46 wantState: connectivity.Idle,
47 },
48 {
49 newState: connectivity.Connecting,
50 wantState: connectivity.Connecting,
51 },
52 {
53 newState: connectivity.Ready,
54 wantState: connectivity.Ready,
55 },
56 {
57 newState: connectivity.TransientFailure,
58 wantState: connectivity.TransientFailure,
59 },
60 {
61 newState: connectivity.Shutdown,
62 wantState: connectivity.TransientFailure,
63 },
64 }
65 for _, test := range tests {
66 cse := &ConnectivityStateEvaluator{}
67 if gotState := cse.RecordTransition(connectivity.Shutdown, test.newState); gotState != test.wantState {
68 t.Fatalf("RecordTransition(%v, %v) = %v, want %v", connectivity.Shutdown, test.newState, gotState, test.wantState)
69 }
70 }
71 }
72
73
74
75 func (s) TestRecordTransition_SameState(t *testing.T) {
76 tests := []struct {
77 newState connectivity.State
78 wantState connectivity.State
79 }{
80 {
81 newState: connectivity.Idle,
82 wantState: connectivity.Idle,
83 },
84 {
85 newState: connectivity.Connecting,
86 wantState: connectivity.Connecting,
87 },
88 {
89 newState: connectivity.Ready,
90 wantState: connectivity.Ready,
91 },
92 {
93 newState: connectivity.TransientFailure,
94 wantState: connectivity.TransientFailure,
95 },
96 {
97 newState: connectivity.Shutdown,
98 wantState: connectivity.TransientFailure,
99 },
100 }
101 const numStateChanges = 5
102 for _, test := range tests {
103 cse := &ConnectivityStateEvaluator{}
104 var prevState, gotState connectivity.State
105 prevState = connectivity.Shutdown
106 for i := 0; i < numStateChanges; i++ {
107 gotState = cse.RecordTransition(prevState, test.newState)
108 prevState = test.newState
109 }
110 if gotState != test.wantState {
111 t.Fatalf("RecordTransition() = %v, want %v", gotState, test.wantState)
112 }
113 }
114 }
115
116
117
118 func (s) TestRecordTransition_SingleSubConn_DifferentStates(t *testing.T) {
119 tests := []struct {
120 name string
121 states []connectivity.State
122 wantState connectivity.State
123 }{
124 {
125 name: "regular transition to ready",
126 states: []connectivity.State{connectivity.Idle, connectivity.Connecting, connectivity.Ready},
127 wantState: connectivity.Ready,
128 },
129 {
130 name: "regular transition to transient failure",
131 states: []connectivity.State{connectivity.Idle, connectivity.Connecting, connectivity.TransientFailure},
132 wantState: connectivity.TransientFailure,
133 },
134 {
135 name: "regular transition to ready",
136 states: []connectivity.State{connectivity.Idle, connectivity.Connecting, connectivity.Ready, connectivity.Idle},
137 wantState: connectivity.Idle,
138 },
139 {
140 name: "transition from ready to transient failure",
141 states: []connectivity.State{connectivity.Idle, connectivity.Connecting, connectivity.Ready, connectivity.TransientFailure},
142 wantState: connectivity.TransientFailure,
143 },
144 {
145 name: "transition from transient failure back to ready",
146 states: []connectivity.State{connectivity.Idle, connectivity.Connecting, connectivity.Ready, connectivity.TransientFailure, connectivity.Ready},
147 wantState: connectivity.Ready,
148 },
149 {
150
151
152 name: "transition from transient failure back to idle",
153 states: []connectivity.State{connectivity.Idle, connectivity.Connecting, connectivity.Ready, connectivity.TransientFailure, connectivity.Idle},
154 wantState: connectivity.Idle,
155 },
156 {
157
158
159 name: "transition from transient failure back to connecting",
160 states: []connectivity.State{connectivity.Idle, connectivity.Connecting, connectivity.Ready, connectivity.TransientFailure, connectivity.Connecting},
161 wantState: connectivity.Connecting,
162 },
163 }
164
165 for _, test := range tests {
166 t.Run(test.name, func(t *testing.T) {
167 cse := &ConnectivityStateEvaluator{}
168 var prevState, gotState connectivity.State
169 prevState = connectivity.Shutdown
170 for _, newState := range test.states {
171 gotState = cse.RecordTransition(prevState, newState)
172 prevState = newState
173 }
174 if gotState != test.wantState {
175 t.Fatalf("RecordTransition() = %v, want %v", gotState, test.wantState)
176 }
177 })
178 }
179 }
180
181
182
183
184 func (s) TestRecordTransition_MultipleSubConns_DifferentStates(t *testing.T) {
185 tests := []struct {
186 name string
187
188
189 subConnStates [][]connectivity.State
190 wantState connectivity.State
191 }{
192 {
193 name: "atleast one ready",
194 subConnStates: [][]connectivity.State{
195 {connectivity.Idle, connectivity.Connecting, connectivity.Ready},
196 {connectivity.Idle},
197 {connectivity.Idle, connectivity.Connecting},
198 {connectivity.Idle, connectivity.Connecting, connectivity.TransientFailure},
199 },
200 wantState: connectivity.Ready,
201 },
202 {
203 name: "atleast one connecting",
204 subConnStates: [][]connectivity.State{
205 {connectivity.Idle, connectivity.Connecting, connectivity.Ready, connectivity.Connecting},
206 {connectivity.Idle},
207 {connectivity.Idle, connectivity.Connecting, connectivity.TransientFailure},
208 },
209 wantState: connectivity.Connecting,
210 },
211 {
212 name: "atleast one idle",
213 subConnStates: [][]connectivity.State{
214 {connectivity.Idle, connectivity.Connecting, connectivity.Ready, connectivity.Idle},
215 {connectivity.Idle, connectivity.Connecting, connectivity.TransientFailure},
216 },
217 wantState: connectivity.Idle,
218 },
219 {
220 name: "atleast one transient failure",
221 subConnStates: [][]connectivity.State{
222 {connectivity.Idle, connectivity.Connecting, connectivity.Ready, connectivity.TransientFailure},
223 {connectivity.TransientFailure},
224 },
225 wantState: connectivity.TransientFailure,
226 },
227 }
228
229 for _, test := range tests {
230 t.Run(test.name, func(t *testing.T) {
231 cse := &ConnectivityStateEvaluator{}
232 var prevState, gotState connectivity.State
233 for _, scStates := range test.subConnStates {
234 prevState = connectivity.Shutdown
235 for _, newState := range scStates {
236 gotState = cse.RecordTransition(prevState, newState)
237 prevState = newState
238 }
239 }
240 if gotState != test.wantState {
241 t.Fatalf("RecordTransition() = %v, want %v", gotState, test.wantState)
242 }
243 })
244 }
245 }
246
View as plain text