1
18
19 package clusterresolver
20
21 import (
22 "bytes"
23 "encoding/json"
24 "fmt"
25 "sort"
26 "testing"
27 "time"
28
29 "github.com/google/go-cmp/cmp"
30 "google.golang.org/grpc/attributes"
31 "google.golang.org/grpc/balancer"
32 "google.golang.org/grpc/balancer/roundrobin"
33 "google.golang.org/grpc/balancer/weightedroundrobin"
34 "google.golang.org/grpc/internal/hierarchy"
35 iserviceconfig "google.golang.org/grpc/internal/serviceconfig"
36 "google.golang.org/grpc/resolver"
37 "google.golang.org/grpc/xds/internal"
38 "google.golang.org/grpc/xds/internal/balancer/clusterimpl"
39 "google.golang.org/grpc/xds/internal/balancer/outlierdetection"
40 "google.golang.org/grpc/xds/internal/balancer/priority"
41 "google.golang.org/grpc/xds/internal/balancer/ringhash"
42 "google.golang.org/grpc/xds/internal/balancer/wrrlocality"
43 "google.golang.org/grpc/xds/internal/xdsclient/xdsresource"
44 )
45
46 const (
47 testLRSServer = "test-lrs-server"
48 testMaxRequests = 314
49 testEDSServiceName = "service-name-from-parent"
50 testDropCategory = "test-drops"
51 testDropOverMillion = 1
52
53 localityCount = 5
54 addressPerLocality = 2
55 )
56
57 var (
58 testLocalityIDs []internal.LocalityID
59 testAddressStrs [][]string
60 testEndpoints [][]xdsresource.Endpoint
61
62 testLocalitiesP0, testLocalitiesP1 []xdsresource.Locality
63
64 addrCmpOpts = cmp.Options{
65 cmp.AllowUnexported(attributes.Attributes{}),
66 cmp.Transformer("SortAddrs", func(in []resolver.Address) []resolver.Address {
67 out := append([]resolver.Address(nil), in...)
68 sort.Slice(out, func(i, j int) bool {
69 return out[i].Addr < out[j].Addr
70 })
71 return out
72 }),
73 }
74
75 noopODCfg = outlierdetection.LBConfig{
76 Interval: iserviceconfig.Duration(10 * time.Second),
77 BaseEjectionTime: iserviceconfig.Duration(30 * time.Second),
78 MaxEjectionTime: iserviceconfig.Duration(300 * time.Second),
79 MaxEjectionPercent: 10,
80 }
81 )
82
83 func init() {
84 for i := 0; i < localityCount; i++ {
85 testLocalityIDs = append(testLocalityIDs, internal.LocalityID{Zone: fmt.Sprintf("test-zone-%d", i)})
86 var (
87 addrs []string
88 ends []xdsresource.Endpoint
89 )
90 for j := 0; j < addressPerLocality; j++ {
91 addr := fmt.Sprintf("addr-%d-%d", i, j)
92 addrs = append(addrs, addr)
93 ends = append(ends, xdsresource.Endpoint{
94 Address: addr,
95 HealthStatus: xdsresource.EndpointHealthStatusHealthy,
96 })
97 }
98 testAddressStrs = append(testAddressStrs, addrs)
99 testEndpoints = append(testEndpoints, ends)
100 }
101
102 testLocalitiesP0 = []xdsresource.Locality{
103 {
104 Endpoints: testEndpoints[0],
105 ID: testLocalityIDs[0],
106 Weight: 20,
107 Priority: 0,
108 },
109 {
110 Endpoints: testEndpoints[1],
111 ID: testLocalityIDs[1],
112 Weight: 80,
113 Priority: 0,
114 },
115 }
116 testLocalitiesP1 = []xdsresource.Locality{
117 {
118 Endpoints: testEndpoints[2],
119 ID: testLocalityIDs[2],
120 Weight: 20,
121 Priority: 1,
122 },
123 {
124 Endpoints: testEndpoints[3],
125 ID: testLocalityIDs[3],
126 Weight: 80,
127 Priority: 1,
128 },
129 }
130 }
131
132
133
134 func TestBuildPriorityConfigJSON(t *testing.T) {
135 gotConfig, _, err := buildPriorityConfigJSON([]priorityConfig{
136 {
137 mechanism: DiscoveryMechanism{
138 Cluster: testClusterName,
139 LoadReportingServer: testLRSServerConfig,
140 MaxConcurrentRequests: newUint32(testMaxRequests),
141 Type: DiscoveryMechanismTypeEDS,
142 EDSServiceName: testEDSServiceName,
143 },
144 edsResp: xdsresource.EndpointsUpdate{
145 Drops: []xdsresource.OverloadDropConfig{
146 {
147 Category: testDropCategory,
148 Numerator: testDropOverMillion,
149 Denominator: million,
150 },
151 },
152 Localities: []xdsresource.Locality{
153 testLocalitiesP0[0],
154 testLocalitiesP0[1],
155 testLocalitiesP1[0],
156 testLocalitiesP1[1],
157 },
158 },
159 childNameGen: newNameGenerator(0),
160 },
161 {
162 mechanism: DiscoveryMechanism{
163 Type: DiscoveryMechanismTypeLogicalDNS,
164 },
165 addresses: testAddressStrs[4],
166 childNameGen: newNameGenerator(1),
167 },
168 }, nil)
169 if err != nil {
170 t.Fatalf("buildPriorityConfigJSON(...) failed: %v", err)
171 }
172
173 var prettyGot bytes.Buffer
174 if err := json.Indent(&prettyGot, gotConfig, ">>> ", " "); err != nil {
175 t.Fatalf("json.Indent() failed: %v", err)
176 }
177
178 t.Log(prettyGot.String())
179
180 priorityB := balancer.Get(priority.Name)
181 if _, err = priorityB.(balancer.ConfigParser).ParseConfig(gotConfig); err != nil {
182 t.Fatalf("ParseConfig(%+v) failed: %v", gotConfig, err)
183 }
184 }
185
186
187
188
189 func TestBuildPriorityConfig(t *testing.T) {
190 gotConfig, _, _ := buildPriorityConfig([]priorityConfig{
191 {
192
193
194
195
196
197 mechanism: DiscoveryMechanism{
198 Cluster: testClusterName,
199 Type: DiscoveryMechanismTypeEDS,
200 EDSServiceName: testEDSServiceName,
201 outlierDetection: noopODCfg,
202 },
203 edsResp: xdsresource.EndpointsUpdate{
204 Localities: []xdsresource.Locality{
205 testLocalitiesP0[0],
206 testLocalitiesP0[1],
207 testLocalitiesP1[0],
208 testLocalitiesP1[1],
209 },
210 },
211 childNameGen: newNameGenerator(0),
212 },
213 {
214
215 mechanism: DiscoveryMechanism{
216 Cluster: testClusterName2,
217 Type: DiscoveryMechanismTypeLogicalDNS,
218 outlierDetection: noopODCfg,
219 },
220 addresses: testAddressStrs[4],
221 childNameGen: newNameGenerator(1),
222 },
223 }, nil)
224
225 wantConfig := &priority.LBConfig{
226 Children: map[string]*priority.Child{
227 "priority-0-0": {
228 Config: &iserviceconfig.BalancerConfig{
229 Name: outlierdetection.Name,
230 Config: &outlierdetection.LBConfig{
231 Interval: iserviceconfig.Duration(10 * time.Second),
232 BaseEjectionTime: iserviceconfig.Duration(30 * time.Second),
233 MaxEjectionTime: iserviceconfig.Duration(300 * time.Second),
234 MaxEjectionPercent: 10,
235 ChildPolicy: &iserviceconfig.BalancerConfig{
236 Name: clusterimpl.Name,
237 Config: &clusterimpl.LBConfig{
238 Cluster: testClusterName,
239 EDSServiceName: testEDSServiceName,
240 DropCategories: []clusterimpl.DropConfig{},
241 },
242 },
243 },
244 },
245 IgnoreReresolutionRequests: true,
246 },
247 "priority-0-1": {
248 Config: &iserviceconfig.BalancerConfig{
249 Name: outlierdetection.Name,
250 Config: &outlierdetection.LBConfig{
251 Interval: iserviceconfig.Duration(10 * time.Second),
252 BaseEjectionTime: iserviceconfig.Duration(30 * time.Second),
253 MaxEjectionTime: iserviceconfig.Duration(300 * time.Second),
254 MaxEjectionPercent: 10,
255 ChildPolicy: &iserviceconfig.BalancerConfig{
256 Name: clusterimpl.Name,
257 Config: &clusterimpl.LBConfig{
258 Cluster: testClusterName,
259 EDSServiceName: testEDSServiceName,
260 DropCategories: []clusterimpl.DropConfig{},
261 },
262 },
263 },
264 },
265 IgnoreReresolutionRequests: true,
266 },
267 "priority-1": {
268 Config: &iserviceconfig.BalancerConfig{
269 Name: outlierdetection.Name,
270 Config: &outlierdetection.LBConfig{
271 Interval: iserviceconfig.Duration(10 * time.Second),
272 BaseEjectionTime: iserviceconfig.Duration(30 * time.Second),
273 MaxEjectionTime: iserviceconfig.Duration(300 * time.Second),
274 MaxEjectionPercent: 10,
275 ChildPolicy: &iserviceconfig.BalancerConfig{
276 Name: clusterimpl.Name,
277 Config: &clusterimpl.LBConfig{
278 Cluster: testClusterName2,
279 ChildPolicy: &iserviceconfig.BalancerConfig{Name: "pick_first"},
280 },
281 },
282 },
283 },
284 IgnoreReresolutionRequests: false,
285 },
286 },
287 Priorities: []string{"priority-0-0", "priority-0-1", "priority-1"},
288 }
289 if diff := cmp.Diff(gotConfig, wantConfig); diff != "" {
290 t.Errorf("buildPriorityConfig() diff (-got +want) %v", diff)
291 }
292 }
293
294 func TestBuildClusterImplConfigForDNS(t *testing.T) {
295 gotName, gotConfig, gotAddrs := buildClusterImplConfigForDNS(newNameGenerator(3), testAddressStrs[0], DiscoveryMechanism{Cluster: testClusterName2, Type: DiscoveryMechanismTypeLogicalDNS})
296 wantName := "priority-3"
297 wantConfig := &clusterimpl.LBConfig{
298 Cluster: testClusterName2,
299 ChildPolicy: &iserviceconfig.BalancerConfig{
300 Name: "pick_first",
301 },
302 }
303 wantAddrs := []resolver.Address{
304 hierarchy.Set(resolver.Address{Addr: testAddressStrs[0][0]}, []string{"priority-3"}),
305 hierarchy.Set(resolver.Address{Addr: testAddressStrs[0][1]}, []string{"priority-3"}),
306 }
307
308 if diff := cmp.Diff(gotName, wantName); diff != "" {
309 t.Errorf("buildClusterImplConfigForDNS() diff (-got +want) %v", diff)
310 }
311 if diff := cmp.Diff(gotConfig, wantConfig); diff != "" {
312 t.Errorf("buildClusterImplConfigForDNS() diff (-got +want) %v", diff)
313 }
314 if diff := cmp.Diff(gotAddrs, wantAddrs, addrCmpOpts); diff != "" {
315 t.Errorf("buildClusterImplConfigForDNS() diff (-got +want) %v", diff)
316 }
317 }
318
319 func TestBuildClusterImplConfigForEDS(t *testing.T) {
320 gotNames, gotConfigs, gotAddrs, _ := buildClusterImplConfigForEDS(
321 newNameGenerator(2),
322 xdsresource.EndpointsUpdate{
323 Drops: []xdsresource.OverloadDropConfig{
324 {
325 Category: testDropCategory,
326 Numerator: testDropOverMillion,
327 Denominator: million,
328 },
329 },
330 Localities: []xdsresource.Locality{
331 {
332 Endpoints: testEndpoints[3],
333 ID: testLocalityIDs[3],
334 Weight: 80,
335 Priority: 1,
336 }, {
337 Endpoints: testEndpoints[1],
338 ID: testLocalityIDs[1],
339 Weight: 80,
340 Priority: 0,
341 }, {
342 Endpoints: testEndpoints[2],
343 ID: testLocalityIDs[2],
344 Weight: 20,
345 Priority: 1,
346 }, {
347 Endpoints: testEndpoints[0],
348 ID: testLocalityIDs[0],
349 Weight: 20,
350 Priority: 0,
351 },
352 },
353 },
354 DiscoveryMechanism{
355 Cluster: testClusterName,
356 MaxConcurrentRequests: newUint32(testMaxRequests),
357 LoadReportingServer: testLRSServerConfig,
358 Type: DiscoveryMechanismTypeEDS,
359 EDSServiceName: testEDSServiceName,
360 },
361 nil,
362 )
363
364 wantNames := []string{
365 fmt.Sprintf("priority-%v-%v", 2, 0),
366 fmt.Sprintf("priority-%v-%v", 2, 1),
367 }
368 wantConfigs := map[string]*clusterimpl.LBConfig{
369 "priority-2-0": {
370 Cluster: testClusterName,
371 EDSServiceName: testEDSServiceName,
372 LoadReportingServer: testLRSServerConfig,
373 MaxConcurrentRequests: newUint32(testMaxRequests),
374 DropCategories: []clusterimpl.DropConfig{
375 {
376 Category: testDropCategory,
377 RequestsPerMillion: testDropOverMillion,
378 },
379 },
380 },
381 "priority-2-1": {
382 Cluster: testClusterName,
383 EDSServiceName: testEDSServiceName,
384 LoadReportingServer: testLRSServerConfig,
385 MaxConcurrentRequests: newUint32(testMaxRequests),
386 DropCategories: []clusterimpl.DropConfig{
387 {
388 Category: testDropCategory,
389 RequestsPerMillion: testDropOverMillion,
390 },
391 },
392 },
393 }
394 wantAddrs := []resolver.Address{
395 testAddrWithAttrs(testAddressStrs[0][0], 20, 1, "priority-2-0", &testLocalityIDs[0]),
396 testAddrWithAttrs(testAddressStrs[0][1], 20, 1, "priority-2-0", &testLocalityIDs[0]),
397 testAddrWithAttrs(testAddressStrs[1][0], 80, 1, "priority-2-0", &testLocalityIDs[1]),
398 testAddrWithAttrs(testAddressStrs[1][1], 80, 1, "priority-2-0", &testLocalityIDs[1]),
399 testAddrWithAttrs(testAddressStrs[2][0], 20, 1, "priority-2-1", &testLocalityIDs[2]),
400 testAddrWithAttrs(testAddressStrs[2][1], 20, 1, "priority-2-1", &testLocalityIDs[2]),
401 testAddrWithAttrs(testAddressStrs[3][0], 80, 1, "priority-2-1", &testLocalityIDs[3]),
402 testAddrWithAttrs(testAddressStrs[3][1], 80, 1, "priority-2-1", &testLocalityIDs[3]),
403 }
404
405 if diff := cmp.Diff(gotNames, wantNames); diff != "" {
406 t.Errorf("buildClusterImplConfigForEDS() diff (-got +want) %v", diff)
407 }
408 if diff := cmp.Diff(gotConfigs, wantConfigs); diff != "" {
409 t.Errorf("buildClusterImplConfigForEDS() diff (-got +want) %v", diff)
410 }
411 if diff := cmp.Diff(gotAddrs, wantAddrs, addrCmpOpts); diff != "" {
412 t.Errorf("buildClusterImplConfigForEDS() diff (-got +want) %v", diff)
413 }
414
415 }
416
417 func TestGroupLocalitiesByPriority(t *testing.T) {
418 tests := []struct {
419 name string
420 localities []xdsresource.Locality
421 wantLocalities [][]xdsresource.Locality
422 }{
423 {
424 name: "1 locality 1 priority",
425 localities: []xdsresource.Locality{testLocalitiesP0[0]},
426 wantLocalities: [][]xdsresource.Locality{
427 {testLocalitiesP0[0]},
428 },
429 },
430 {
431 name: "2 locality 1 priority",
432 localities: []xdsresource.Locality{testLocalitiesP0[0], testLocalitiesP0[1]},
433 wantLocalities: [][]xdsresource.Locality{
434 {testLocalitiesP0[0], testLocalitiesP0[1]},
435 },
436 },
437 {
438 name: "1 locality in each",
439 localities: []xdsresource.Locality{testLocalitiesP0[0], testLocalitiesP1[0]},
440 wantLocalities: [][]xdsresource.Locality{
441 {testLocalitiesP0[0]},
442 {testLocalitiesP1[0]},
443 },
444 },
445 {
446 name: "2 localities in each sorted",
447 localities: []xdsresource.Locality{
448 testLocalitiesP0[0], testLocalitiesP0[1],
449 testLocalitiesP1[0], testLocalitiesP1[1]},
450 wantLocalities: [][]xdsresource.Locality{
451 {testLocalitiesP0[0], testLocalitiesP0[1]},
452 {testLocalitiesP1[0], testLocalitiesP1[1]},
453 },
454 },
455 {
456
457
458
459 name: "2 localities in each needs to sort",
460 localities: []xdsresource.Locality{
461 testLocalitiesP1[1], testLocalitiesP0[1],
462 testLocalitiesP1[0], testLocalitiesP0[0]},
463 wantLocalities: [][]xdsresource.Locality{
464 {testLocalitiesP0[1], testLocalitiesP0[0]},
465 {testLocalitiesP1[1], testLocalitiesP1[0]},
466 },
467 },
468 }
469 for _, tt := range tests {
470 t.Run(tt.name, func(t *testing.T) {
471 gotLocalities := groupLocalitiesByPriority(tt.localities)
472 if diff := cmp.Diff(gotLocalities, tt.wantLocalities); diff != "" {
473 t.Errorf("groupLocalitiesByPriority() diff(-got +want) %v", diff)
474 }
475 })
476 }
477 }
478
479 func TestDedupSortedIntSlice(t *testing.T) {
480 tests := []struct {
481 name string
482 a []int
483 want []int
484 }{
485 {
486 name: "empty",
487 a: []int{},
488 want: []int{},
489 },
490 {
491 name: "no dup",
492 a: []int{0, 1, 2, 3},
493 want: []int{0, 1, 2, 3},
494 },
495 {
496 name: "with dup",
497 a: []int{0, 0, 1, 1, 1, 2, 3},
498 want: []int{0, 1, 2, 3},
499 },
500 }
501 for _, tt := range tests {
502 t.Run(tt.name, func(t *testing.T) {
503 if got := dedupSortedIntSlice(tt.a); !cmp.Equal(got, tt.want) {
504 t.Errorf("dedupSortedIntSlice() = %v, want %v, diff %v", got, tt.want, cmp.Diff(got, tt.want))
505 }
506 })
507 }
508 }
509
510 func TestPriorityLocalitiesToClusterImpl(t *testing.T) {
511 tests := []struct {
512 name string
513 localities []xdsresource.Locality
514 priorityName string
515 mechanism DiscoveryMechanism
516 childPolicy *iserviceconfig.BalancerConfig
517 wantConfig *clusterimpl.LBConfig
518 wantAddrs []resolver.Address
519 wantErr bool
520 }{{
521 name: "round robin as child, no LRS",
522 localities: []xdsresource.Locality{
523 {
524 Endpoints: []xdsresource.Endpoint{
525 {Address: "addr-1-1", HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 90},
526 {Address: "addr-1-2", HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 10},
527 },
528 ID: internal.LocalityID{Zone: "test-zone-1"},
529 Weight: 20,
530 },
531 {
532 Endpoints: []xdsresource.Endpoint{
533 {Address: "addr-2-1", HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 90},
534 {Address: "addr-2-2", HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 10},
535 },
536 ID: internal.LocalityID{Zone: "test-zone-2"},
537 Weight: 80,
538 },
539 },
540 priorityName: "test-priority",
541 childPolicy: &iserviceconfig.BalancerConfig{Name: roundrobin.Name},
542 mechanism: DiscoveryMechanism{
543 Cluster: testClusterName,
544 Type: DiscoveryMechanismTypeEDS,
545 EDSServiceName: testEDSService,
546 },
547
548 wantConfig: &clusterimpl.LBConfig{
549 Cluster: testClusterName,
550 EDSServiceName: testEDSService,
551 ChildPolicy: &iserviceconfig.BalancerConfig{Name: roundrobin.Name},
552 },
553 wantAddrs: []resolver.Address{
554 testAddrWithAttrs("addr-1-1", 20, 90, "test-priority", &internal.LocalityID{Zone: "test-zone-1"}),
555 testAddrWithAttrs("addr-1-2", 20, 10, "test-priority", &internal.LocalityID{Zone: "test-zone-1"}),
556 testAddrWithAttrs("addr-2-1", 80, 90, "test-priority", &internal.LocalityID{Zone: "test-zone-2"}),
557 testAddrWithAttrs("addr-2-2", 80, 10, "test-priority", &internal.LocalityID{Zone: "test-zone-2"}),
558 },
559 },
560 {
561 name: "ring_hash as child",
562 localities: []xdsresource.Locality{
563 {
564 Endpoints: []xdsresource.Endpoint{
565 {Address: "addr-1-1", HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 90},
566 {Address: "addr-1-2", HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 10},
567 },
568 ID: internal.LocalityID{Zone: "test-zone-1"},
569 Weight: 20,
570 },
571 {
572 Endpoints: []xdsresource.Endpoint{
573 {Address: "addr-2-1", HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 90},
574 {Address: "addr-2-2", HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 10},
575 },
576 ID: internal.LocalityID{Zone: "test-zone-2"},
577 Weight: 80,
578 },
579 },
580 priorityName: "test-priority",
581 childPolicy: &iserviceconfig.BalancerConfig{Name: ringhash.Name, Config: &ringhash.LBConfig{MinRingSize: 1, MaxRingSize: 2}},
582
583 wantConfig: &clusterimpl.LBConfig{
584 ChildPolicy: &iserviceconfig.BalancerConfig{
585 Name: ringhash.Name,
586 Config: &ringhash.LBConfig{MinRingSize: 1, MaxRingSize: 2},
587 },
588 },
589 wantAddrs: []resolver.Address{
590 testAddrWithAttrs("addr-1-1", 20, 90, "test-priority", &internal.LocalityID{Zone: "test-zone-1"}),
591 testAddrWithAttrs("addr-1-2", 20, 10, "test-priority", &internal.LocalityID{Zone: "test-zone-1"}),
592 testAddrWithAttrs("addr-2-1", 80, 90, "test-priority", &internal.LocalityID{Zone: "test-zone-2"}),
593 testAddrWithAttrs("addr-2-2", 80, 10, "test-priority", &internal.LocalityID{Zone: "test-zone-2"}),
594 },
595 },
596 }
597 for _, tt := range tests {
598 t.Run(tt.name, func(t *testing.T) {
599 got, got1, err := priorityLocalitiesToClusterImpl(tt.localities, tt.priorityName, tt.mechanism, nil, tt.childPolicy)
600 if (err != nil) != tt.wantErr {
601 t.Fatalf("priorityLocalitiesToClusterImpl() error = %v, wantErr %v", err, tt.wantErr)
602 }
603 if diff := cmp.Diff(got, tt.wantConfig); diff != "" {
604 t.Errorf("localitiesToWeightedTarget() diff (-got +want) %v", diff)
605 }
606 if diff := cmp.Diff(got1, tt.wantAddrs, cmp.AllowUnexported(attributes.Attributes{})); diff != "" {
607 t.Errorf("localitiesToWeightedTarget() diff (-got +want) %v", diff)
608 }
609 })
610 }
611 }
612
613 func assertString(f func() (string, error)) string {
614 s, err := f()
615 if err != nil {
616 panic(err.Error())
617 }
618 return s
619 }
620
621 func testAddrWithAttrs(addrStr string, localityWeight, endpointWeight uint32, priority string, lID *internal.LocalityID) resolver.Address {
622 addr := resolver.Address{Addr: addrStr}
623 path := []string{priority}
624 if lID != nil {
625 path = append(path, assertString(lID.ToString))
626 addr = internal.SetLocalityID(addr, *lID)
627 }
628 addr = hierarchy.Set(addr, path)
629 addr = wrrlocality.SetAddrInfo(addr, wrrlocality.AddrInfo{LocalityWeight: localityWeight})
630 addr = weightedroundrobin.SetAddrInfo(addr, weightedroundrobin.AddrInfo{Weight: localityWeight * endpointWeight})
631 return addr
632 }
633
634 func TestConvertClusterImplMapToOutlierDetection(t *testing.T) {
635 tests := []struct {
636 name string
637 ciCfgsMap map[string]*clusterimpl.LBConfig
638 odCfg outlierdetection.LBConfig
639 wantODCfgs map[string]*outlierdetection.LBConfig
640 }{
641 {
642 name: "single-entry-noop",
643 ciCfgsMap: map[string]*clusterimpl.LBConfig{
644 "child1": {
645 Cluster: "cluster1",
646 },
647 },
648 odCfg: outlierdetection.LBConfig{
649 Interval: 1<<63 - 1,
650 },
651 wantODCfgs: map[string]*outlierdetection.LBConfig{
652 "child1": {
653 Interval: 1<<63 - 1,
654 ChildPolicy: &iserviceconfig.BalancerConfig{
655 Name: clusterimpl.Name,
656 Config: &clusterimpl.LBConfig{
657 Cluster: "cluster1",
658 },
659 },
660 },
661 },
662 },
663 {
664 name: "multiple-entries-noop",
665 ciCfgsMap: map[string]*clusterimpl.LBConfig{
666 "child1": {
667 Cluster: "cluster1",
668 },
669 "child2": {
670 Cluster: "cluster2",
671 },
672 },
673 odCfg: outlierdetection.LBConfig{
674 Interval: 1<<63 - 1,
675 },
676 wantODCfgs: map[string]*outlierdetection.LBConfig{
677 "child1": {
678 Interval: 1<<63 - 1,
679 ChildPolicy: &iserviceconfig.BalancerConfig{
680 Name: clusterimpl.Name,
681 Config: &clusterimpl.LBConfig{
682 Cluster: "cluster1",
683 },
684 },
685 },
686 "child2": {
687 Interval: 1<<63 - 1,
688 ChildPolicy: &iserviceconfig.BalancerConfig{
689 Name: clusterimpl.Name,
690 Config: &clusterimpl.LBConfig{
691 Cluster: "cluster2",
692 },
693 },
694 },
695 },
696 },
697 }
698 for _, test := range tests {
699 t.Run(test.name, func(t *testing.T) {
700 got := convertClusterImplMapToOutlierDetection(test.ciCfgsMap, test.odCfg)
701 if diff := cmp.Diff(got, test.wantODCfgs); diff != "" {
702 t.Fatalf("convertClusterImplMapToOutlierDetection() diff(-got +want) %v", diff)
703 }
704 })
705 }
706 }
707
View as plain text