1
18
19 package clusterresolver
20
21 import (
22 "encoding/json"
23 "testing"
24 "time"
25
26 "github.com/google/go-cmp/cmp"
27 "github.com/google/go-cmp/cmp/cmpopts"
28 "google.golang.org/grpc/balancer"
29 "google.golang.org/grpc/balancer/roundrobin"
30 iserviceconfig "google.golang.org/grpc/internal/serviceconfig"
31 "google.golang.org/grpc/internal/xds/bootstrap"
32 "google.golang.org/grpc/xds/internal/balancer/outlierdetection"
33 "google.golang.org/grpc/xds/internal/balancer/ringhash"
34 )
35
36 func TestDiscoveryMechanismTypeMarshalJSON(t *testing.T) {
37 tests := []struct {
38 name string
39 typ DiscoveryMechanismType
40 want string
41 }{
42 {
43 name: "eds",
44 typ: DiscoveryMechanismTypeEDS,
45 want: `"EDS"`,
46 },
47 {
48 name: "dns",
49 typ: DiscoveryMechanismTypeLogicalDNS,
50 want: `"LOGICAL_DNS"`,
51 },
52 }
53 for _, tt := range tests {
54 t.Run(tt.name, func(t *testing.T) {
55 if got, err := json.Marshal(tt.typ); err != nil || string(got) != tt.want {
56 t.Fatalf("DiscoveryMechanismTypeEDS.MarshalJSON() = (%v, %v), want (%s, nil)", string(got), err, tt.want)
57 }
58 })
59 }
60 }
61 func TestDiscoveryMechanismTypeUnmarshalJSON(t *testing.T) {
62 tests := []struct {
63 name string
64 js string
65 want DiscoveryMechanismType
66 wantErr bool
67 }{
68 {
69 name: "eds",
70 js: `"EDS"`,
71 want: DiscoveryMechanismTypeEDS,
72 },
73 {
74 name: "dns",
75 js: `"LOGICAL_DNS"`,
76 want: DiscoveryMechanismTypeLogicalDNS,
77 },
78 {
79 name: "error",
80 js: `"1234"`,
81 wantErr: true,
82 },
83 }
84 for _, tt := range tests {
85 t.Run(tt.name, func(t *testing.T) {
86 var got DiscoveryMechanismType
87 err := json.Unmarshal([]byte(tt.js), &got)
88 if (err != nil) != tt.wantErr {
89 t.Fatalf("DiscoveryMechanismTypeEDS.UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
90 }
91 if diff := cmp.Diff(got, tt.want); diff != "" {
92 t.Fatalf("DiscoveryMechanismTypeEDS.UnmarshalJSON() got unexpected output, diff (-got +want): %v", diff)
93 }
94 })
95 }
96 }
97
98 const (
99 testJSONConfig1 = `{
100 "discoveryMechanisms": [{
101 "cluster": "test-cluster-name",
102 "lrsLoadReportingServer": {
103 "server_uri": "trafficdirector.googleapis.com:443",
104 "channel_creds": [ { "type": "google_default" } ]
105 },
106 "maxConcurrentRequests": 314,
107 "type": "EDS",
108 "edsServiceName": "test-eds-service-name",
109 "outlierDetection": {}
110 }],
111 "xdsLbPolicy":[{"round_robin":{}}]
112 }`
113 testJSONConfig2 = `{
114 "discoveryMechanisms": [{
115 "cluster": "test-cluster-name",
116 "lrsLoadReportingServer": {
117 "server_uri": "trafficdirector.googleapis.com:443",
118 "channel_creds": [ { "type": "google_default" } ]
119 },
120 "maxConcurrentRequests": 314,
121 "type": "EDS",
122 "edsServiceName": "test-eds-service-name",
123 "outlierDetection": {}
124 },{
125 "type": "LOGICAL_DNS",
126 "outlierDetection": {}
127 }],
128 "xdsLbPolicy":[{"round_robin":{}}]
129 }`
130 testJSONConfig3 = `{
131 "discoveryMechanisms": [{
132 "cluster": "test-cluster-name",
133 "lrsLoadReportingServer": {
134 "server_uri": "trafficdirector.googleapis.com:443",
135 "channel_creds": [ { "type": "google_default" } ]
136 },
137 "maxConcurrentRequests": 314,
138 "type": "EDS",
139 "edsServiceName": "test-eds-service-name",
140 "outlierDetection": {}
141 }],
142 "xdsLbPolicy":[{"round_robin":{}}]
143 }`
144 testJSONConfig4 = `{
145 "discoveryMechanisms": [{
146 "cluster": "test-cluster-name",
147 "lrsLoadReportingServer": {
148 "server_uri": "trafficdirector.googleapis.com:443",
149 "channel_creds": [ { "type": "google_default" } ]
150 },
151 "maxConcurrentRequests": 314,
152 "type": "EDS",
153 "edsServiceName": "test-eds-service-name",
154 "outlierDetection": {}
155 }],
156 "xdsLbPolicy":[{"ring_hash_experimental":{}}]
157 }`
158 testJSONConfig5 = `{
159 "discoveryMechanisms": [{
160 "cluster": "test-cluster-name",
161 "lrsLoadReportingServer": {
162 "server_uri": "trafficdirector.googleapis.com:443",
163 "channel_creds": [ { "type": "google_default" } ]
164 },
165 "maxConcurrentRequests": 314,
166 "type": "EDS",
167 "edsServiceName": "test-eds-service-name",
168 "outlierDetection": {}
169 }],
170 "xdsLbPolicy":[{"round_robin":{}}]
171 }`
172 )
173
174 var testLRSServerConfig = &bootstrap.ServerConfig{
175 ServerURI: "trafficdirector.googleapis.com:443",
176 Creds: bootstrap.ChannelCreds{
177 Type: "google_default",
178 },
179 }
180
181 func TestParseConfig(t *testing.T) {
182 tests := []struct {
183 name string
184 js string
185 want *LBConfig
186 wantErr bool
187 }{
188 {
189 name: "empty json",
190 js: "",
191 want: nil,
192 wantErr: true,
193 },
194 {
195 name: "OK with one discovery mechanism",
196 js: testJSONConfig1,
197 want: &LBConfig{
198 DiscoveryMechanisms: []DiscoveryMechanism{
199 {
200 Cluster: testClusterName,
201 LoadReportingServer: testLRSServerConfig,
202 MaxConcurrentRequests: newUint32(testMaxRequests),
203 Type: DiscoveryMechanismTypeEDS,
204 EDSServiceName: testEDSService,
205 outlierDetection: outlierdetection.LBConfig{
206 Interval: iserviceconfig.Duration(10 * time.Second),
207 BaseEjectionTime: iserviceconfig.Duration(30 * time.Second),
208 MaxEjectionTime: iserviceconfig.Duration(300 * time.Second),
209 MaxEjectionPercent: 10,
210
211 },
212 },
213 },
214 xdsLBPolicy: iserviceconfig.BalancerConfig{
215 Name: roundrobin.Name,
216 Config: nil,
217 },
218 },
219 wantErr: false,
220 },
221 {
222 name: "OK with multiple discovery mechanisms",
223 js: testJSONConfig2,
224 want: &LBConfig{
225 DiscoveryMechanisms: []DiscoveryMechanism{
226 {
227 Cluster: testClusterName,
228 LoadReportingServer: testLRSServerConfig,
229 MaxConcurrentRequests: newUint32(testMaxRequests),
230 Type: DiscoveryMechanismTypeEDS,
231 EDSServiceName: testEDSService,
232 outlierDetection: outlierdetection.LBConfig{
233 Interval: iserviceconfig.Duration(10 * time.Second),
234 BaseEjectionTime: iserviceconfig.Duration(30 * time.Second),
235 MaxEjectionTime: iserviceconfig.Duration(300 * time.Second),
236 MaxEjectionPercent: 10,
237
238 },
239 },
240 {
241 Type: DiscoveryMechanismTypeLogicalDNS,
242 outlierDetection: outlierdetection.LBConfig{
243 Interval: iserviceconfig.Duration(10 * time.Second),
244 BaseEjectionTime: iserviceconfig.Duration(30 * time.Second),
245 MaxEjectionTime: iserviceconfig.Duration(300 * time.Second),
246 MaxEjectionPercent: 10,
247
248 },
249 },
250 },
251 xdsLBPolicy: iserviceconfig.BalancerConfig{
252 Name: roundrobin.Name,
253 Config: nil,
254 },
255 },
256 wantErr: false,
257 },
258 {
259 name: "OK with picking policy round_robin",
260 js: testJSONConfig3,
261 want: &LBConfig{
262 DiscoveryMechanisms: []DiscoveryMechanism{
263 {
264 Cluster: testClusterName,
265 LoadReportingServer: testLRSServerConfig,
266 MaxConcurrentRequests: newUint32(testMaxRequests),
267 Type: DiscoveryMechanismTypeEDS,
268 EDSServiceName: testEDSService,
269 outlierDetection: outlierdetection.LBConfig{
270 Interval: iserviceconfig.Duration(10 * time.Second),
271 BaseEjectionTime: iserviceconfig.Duration(30 * time.Second),
272 MaxEjectionTime: iserviceconfig.Duration(300 * time.Second),
273 MaxEjectionPercent: 10,
274
275 },
276 },
277 },
278 xdsLBPolicy: iserviceconfig.BalancerConfig{
279 Name: roundrobin.Name,
280 Config: nil,
281 },
282 },
283 wantErr: false,
284 },
285 {
286 name: "OK with picking policy ring_hash",
287 js: testJSONConfig4,
288 want: &LBConfig{
289 DiscoveryMechanisms: []DiscoveryMechanism{
290 {
291 Cluster: testClusterName,
292 LoadReportingServer: testLRSServerConfig,
293 MaxConcurrentRequests: newUint32(testMaxRequests),
294 Type: DiscoveryMechanismTypeEDS,
295 EDSServiceName: testEDSService,
296 outlierDetection: outlierdetection.LBConfig{
297 Interval: iserviceconfig.Duration(10 * time.Second),
298 BaseEjectionTime: iserviceconfig.Duration(30 * time.Second),
299 MaxEjectionTime: iserviceconfig.Duration(300 * time.Second),
300 MaxEjectionPercent: 10,
301
302 },
303 },
304 },
305 xdsLBPolicy: iserviceconfig.BalancerConfig{
306 Name: ringhash.Name,
307 Config: &ringhash.LBConfig{MinRingSize: 1024, MaxRingSize: 4096},
308 },
309 },
310 wantErr: false,
311 },
312 {
313 name: "noop-outlier-detection",
314 js: testJSONConfig5,
315 want: &LBConfig{
316 DiscoveryMechanisms: []DiscoveryMechanism{
317 {
318 Cluster: testClusterName,
319 LoadReportingServer: testLRSServerConfig,
320 MaxConcurrentRequests: newUint32(testMaxRequests),
321 Type: DiscoveryMechanismTypeEDS,
322 EDSServiceName: testEDSService,
323 outlierDetection: outlierdetection.LBConfig{
324 Interval: iserviceconfig.Duration(10 * time.Second),
325 BaseEjectionTime: iserviceconfig.Duration(30 * time.Second),
326 MaxEjectionTime: iserviceconfig.Duration(300 * time.Second),
327 MaxEjectionPercent: 10,
328
329 },
330 },
331 },
332 xdsLBPolicy: iserviceconfig.BalancerConfig{
333 Name: roundrobin.Name,
334 Config: nil,
335 },
336 },
337 wantErr: false,
338 },
339 }
340 for _, tt := range tests {
341 b := balancer.Get(Name)
342 if b == nil {
343 t.Fatalf("LB policy %q not registered", Name)
344 }
345 cfgParser, ok := b.(balancer.ConfigParser)
346 if !ok {
347 t.Fatalf("LB policy %q does not support config parsing", Name)
348 }
349 t.Run(tt.name, func(t *testing.T) {
350 got, err := cfgParser.ParseConfig([]byte(tt.js))
351 if (err != nil) != tt.wantErr {
352 t.Fatalf("parseConfig() error = %v, wantErr %v", err, tt.wantErr)
353 }
354 if tt.wantErr {
355 return
356 }
357 if diff := cmp.Diff(got, tt.want, cmp.AllowUnexported(LBConfig{}), cmpopts.IgnoreFields(LBConfig{}, "XDSLBPolicy")); diff != "" {
358 t.Errorf("parseConfig() got unexpected output, diff (-got +want): %v", diff)
359 }
360 })
361 }
362 }
363
364 func newUint32(i uint32) *uint32 {
365 return &i
366 }
367
View as plain text