gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/xds/internal/balancer/clusterresolver/resource_resolver_test.go (about) 1 /* 2 * 3 * Copyright 2021 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package clusterresolver 20 21 import ( 22 "context" 23 "fmt" 24 "net/url" 25 "testing" 26 27 "gitee.com/ks-custle/core-gm/grpc/resolver" 28 "gitee.com/ks-custle/core-gm/grpc/resolver/manual" 29 "gitee.com/ks-custle/core-gm/grpc/xds/internal/testutils" 30 "gitee.com/ks-custle/core-gm/grpc/xds/internal/testutils/fakeclient" 31 "gitee.com/ks-custle/core-gm/grpc/xds/internal/xdsclient/xdsresource" 32 "github.com/google/go-cmp/cmp" 33 ) 34 35 const ( 36 testDNSTarget = "dns.com" 37 ) 38 39 var ( 40 testEDSUpdates []xdsresource.EndpointsUpdate 41 ) 42 43 func init() { 44 clab1 := testutils.NewClusterLoadAssignmentBuilder(testClusterNames[0], nil) 45 clab1.AddLocality(testSubZones[0], 1, 0, testEndpointAddrs[:1], nil) 46 testEDSUpdates = append(testEDSUpdates, parseEDSRespProtoForTesting(clab1.Build())) 47 clab2 := testutils.NewClusterLoadAssignmentBuilder(testClusterNames[0], nil) 48 clab2.AddLocality(testSubZones[1], 1, 0, testEndpointAddrs[1:2], nil) 49 testEDSUpdates = append(testEDSUpdates, parseEDSRespProtoForTesting(clab2.Build())) 50 } 51 52 // Test the simple case with one EDS resource to watch. 53 func (s) TestResourceResolverOneEDSResource(t *testing.T) { 54 for _, test := range []struct { 55 name string 56 clusterName, edsName string 57 wantName string 58 edsUpdate xdsresource.EndpointsUpdate 59 want []priorityConfig 60 }{ 61 {name: "watch EDS", 62 clusterName: testClusterName, 63 edsName: testEDSServcie, 64 wantName: testEDSServcie, 65 edsUpdate: testEDSUpdates[0], 66 want: []priorityConfig{{ 67 mechanism: DiscoveryMechanism{ 68 Type: DiscoveryMechanismTypeEDS, 69 Cluster: testClusterName, 70 EDSServiceName: testEDSServcie, 71 }, 72 edsResp: testEDSUpdates[0], 73 }}, 74 }, 75 { 76 name: "watch EDS no EDS name", // Will watch for cluster name. 77 clusterName: testClusterName, 78 wantName: testClusterName, 79 edsUpdate: testEDSUpdates[1], 80 want: []priorityConfig{{ 81 mechanism: DiscoveryMechanism{ 82 Type: DiscoveryMechanismTypeEDS, 83 Cluster: testClusterName, 84 }, 85 edsResp: testEDSUpdates[1], 86 }}, 87 }, 88 } { 89 t.Run(test.name, func(t *testing.T) { 90 fakeClient := fakeclient.NewClient() 91 rr := newResourceResolver(&clusterResolverBalancer{xdsClient: fakeClient}) 92 rr.updateMechanisms([]DiscoveryMechanism{{ 93 Type: DiscoveryMechanismTypeEDS, 94 Cluster: test.clusterName, 95 EDSServiceName: test.edsName, 96 }}) 97 ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout) 98 defer ctxCancel() 99 gotEDSName, err := fakeClient.WaitForWatchEDS(ctx) 100 if err != nil { 101 t.Fatalf("xdsClient.WatchCDS failed with error: %v", err) 102 } 103 if gotEDSName != test.wantName { 104 t.Fatalf("xdsClient.WatchEDS called for cluster: %v, want: %v", gotEDSName, test.wantName) 105 } 106 107 // Invoke callback, should get an update. 108 fakeClient.InvokeWatchEDSCallback("", test.edsUpdate, nil) 109 select { 110 case u := <-rr.updateChannel: 111 if diff := cmp.Diff(u.priorities, test.want, cmp.AllowUnexported(priorityConfig{})); diff != "" { 112 t.Fatalf("got unexpected resource update, diff (-got, +want): %v", diff) 113 } 114 case <-ctx.Done(): 115 t.Fatal("Timed out waiting for update from update channel.") 116 } 117 // Close the resource resolver. Should stop EDS watch. 118 rr.stop() 119 edsNameCanceled, err := fakeClient.WaitForCancelEDSWatch(ctx) 120 if err != nil { 121 t.Fatalf("xdsClient.CancelCDS failed with error: %v", err) 122 } 123 if edsNameCanceled != test.wantName { 124 t.Fatalf("xdsClient.CancelEDS called for %v, want: %v", edsNameCanceled, testEDSServcie) 125 } 126 }) 127 } 128 } 129 130 func setupDNS() (chan resolver.Target, chan struct{}, chan resolver.ResolveNowOptions, *manual.Resolver, func()) { 131 dnsTargetCh := make(chan resolver.Target, 1) 132 dnsCloseCh := make(chan struct{}, 1) 133 resolveNowCh := make(chan resolver.ResolveNowOptions, 1) 134 135 mr := manual.NewBuilderWithScheme("dns") 136 mr.BuildCallback = func(target resolver.Target, _ resolver.ClientConn, _ resolver.BuildOptions) { dnsTargetCh <- target } 137 mr.CloseCallback = func() { dnsCloseCh <- struct{}{} } 138 mr.ResolveNowCallback = func(opts resolver.ResolveNowOptions) { resolveNowCh <- opts } 139 oldNewDNS := newDNS 140 newDNS = func(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) { 141 return mr.Build(target, cc, opts) 142 } 143 return dnsTargetCh, dnsCloseCh, resolveNowCh, mr, func() { newDNS = oldNewDNS } 144 } 145 146 // Test the simple case of one DNS resolver. 147 func (s) TestResourceResolverOneDNSResource(t *testing.T) { 148 for _, test := range []struct { 149 name string 150 target string 151 wantTarget resolver.Target 152 addrs []resolver.Address 153 want []priorityConfig 154 }{ 155 { 156 name: "watch DNS", 157 target: testDNSTarget, 158 // Target.Scheme、Target.Endpoint are deprecated, use URL.Scheme、URL.Path instead. 159 //wantTarget: resolver.Target{Scheme: "dns", Endpoint: testDNSTarget}, 160 wantTarget: resolver.Target{URL: url.URL{Scheme: "dns", Path: testDNSTarget}}, 161 addrs: []resolver.Address{{Addr: "1.1.1.1"}, {Addr: "2.2.2.2"}}, 162 want: []priorityConfig{{ 163 mechanism: DiscoveryMechanism{ 164 Type: DiscoveryMechanismTypeLogicalDNS, 165 DNSHostname: testDNSTarget, 166 }, 167 addresses: []string{"1.1.1.1", "2.2.2.2"}, 168 }}, 169 }, 170 } { 171 t.Run(test.name, func(t *testing.T) { 172 dnsTargetCh, dnsCloseCh, _, dnsR, cleanup := setupDNS() 173 defer cleanup() 174 fakeClient := fakeclient.NewClient() 175 rr := newResourceResolver(&clusterResolverBalancer{xdsClient: fakeClient}) 176 rr.updateMechanisms([]DiscoveryMechanism{{ 177 Type: DiscoveryMechanismTypeLogicalDNS, 178 DNSHostname: test.target, 179 }}) 180 ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout) 181 defer ctxCancel() 182 select { 183 case target := <-dnsTargetCh: 184 if diff := cmp.Diff(target, test.wantTarget); diff != "" { 185 t.Fatalf("got unexpected DNS target to watch, diff (-got, +want): %v", diff) 186 } 187 case <-ctx.Done(): 188 t.Fatal("Timed out waiting for building DNS resolver") 189 } 190 191 // Invoke callback, should get an update. 192 dnsR.UpdateState(resolver.State{Addresses: test.addrs}) 193 select { 194 case u := <-rr.updateChannel: 195 if diff := cmp.Diff(u.priorities, test.want, cmp.AllowUnexported(priorityConfig{})); diff != "" { 196 t.Fatalf("got unexpected resource update, diff (-got, +want): %v", diff) 197 } 198 case <-ctx.Done(): 199 t.Fatal("Timed out waiting for update from update channel.") 200 } 201 // Close the resource resolver. Should close the underlying resolver. 202 rr.stop() 203 select { 204 case <-dnsCloseCh: 205 case <-ctx.Done(): 206 t.Fatal("Timed out waiting for closing DNS resolver") 207 } 208 }) 209 } 210 } 211 212 // Test that changing EDS name would cause a cancel and a new watch. 213 // 214 // Also, changes that don't actually change EDS names (e.g. changing cluster 215 // name but not service name, or change circuit breaking count) doesn't do 216 // anything. 217 // 218 // - update DiscoveryMechanism 219 // - same EDS name to watch, but different MaxCurrentCount: no new watch 220 // - different cluster name, but same EDS name: no new watch 221 func (s) TestResourceResolverChangeEDSName(t *testing.T) { 222 fakeClient := fakeclient.NewClient() 223 rr := newResourceResolver(&clusterResolverBalancer{xdsClient: fakeClient}) 224 rr.updateMechanisms([]DiscoveryMechanism{{ 225 Type: DiscoveryMechanismTypeEDS, 226 Cluster: testClusterName, 227 EDSServiceName: testEDSServcie, 228 }}) 229 ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout) 230 defer ctxCancel() 231 gotEDSName1, err := fakeClient.WaitForWatchEDS(ctx) 232 if err != nil { 233 t.Fatalf("xdsClient.WatchCDS failed with error: %v", err) 234 } 235 if gotEDSName1 != testEDSServcie { 236 t.Fatalf("xdsClient.WatchEDS called for cluster: %v, want: %v", gotEDSName1, testEDSServcie) 237 } 238 239 // Invoke callback, should get an update. 240 fakeClient.InvokeWatchEDSCallback(gotEDSName1, testEDSUpdates[0], nil) 241 select { 242 case u := <-rr.updateChannel: 243 if diff := cmp.Diff(u.priorities, []priorityConfig{{ 244 mechanism: DiscoveryMechanism{ 245 Type: DiscoveryMechanismTypeEDS, 246 Cluster: testClusterName, 247 EDSServiceName: testEDSServcie, 248 }, 249 edsResp: testEDSUpdates[0], 250 }}, cmp.AllowUnexported(priorityConfig{})); diff != "" { 251 t.Fatalf("got unexpected resource update, diff (-got, +want): %v", diff) 252 } 253 case <-ctx.Done(): 254 t.Fatal("Timed out waiting for update from update channel.") 255 } 256 257 // Change name to watch. 258 rr.updateMechanisms([]DiscoveryMechanism{{ 259 Type: DiscoveryMechanismTypeEDS, 260 Cluster: testClusterName, 261 }}) 262 edsNameCanceled1, err := fakeClient.WaitForCancelEDSWatch(ctx) 263 if err != nil { 264 t.Fatalf("xdsClient.CancelCDS failed with error: %v", err) 265 } 266 if edsNameCanceled1 != gotEDSName1 { 267 t.Fatalf("xdsClient.CancelEDS called for %v, want: %v", edsNameCanceled1, testEDSServcie) 268 } 269 gotEDSName2, err := fakeClient.WaitForWatchEDS(ctx) 270 if err != nil { 271 t.Fatalf("xdsClient.WatchCDS failed with error: %v", err) 272 } 273 if gotEDSName2 != testClusterName { 274 t.Fatalf("xdsClient.WatchEDS called for cluster: %v, want: %v", gotEDSName2, testClusterName) 275 } 276 // Shouldn't get any update, because the new resource hasn't received any 277 // update. 278 shortCtx, shortCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 279 defer shortCancel() 280 select { 281 case u := <-rr.updateChannel: 282 t.Fatalf("get unexpected update %+v", u) 283 case <-shortCtx.Done(): 284 } 285 286 // Invoke callback, should get an update. 287 fakeClient.InvokeWatchEDSCallback(gotEDSName2, testEDSUpdates[1], nil) 288 select { 289 case u := <-rr.updateChannel: 290 if diff := cmp.Diff(u.priorities, []priorityConfig{{ 291 mechanism: DiscoveryMechanism{ 292 Type: DiscoveryMechanismTypeEDS, 293 Cluster: testClusterName, 294 }, 295 edsResp: testEDSUpdates[1], 296 }}, cmp.AllowUnexported(priorityConfig{})); diff != "" { 297 t.Fatalf("got unexpected resource update, diff (-got, +want): %v", diff) 298 } 299 case <-ctx.Done(): 300 t.Fatal("Timed out waiting for update from update channel.") 301 } 302 303 // Change circuit breaking count, should get an update with new circuit 304 // breaking count, but shouldn't trigger new watch. 305 rr.updateMechanisms([]DiscoveryMechanism{{ 306 Type: DiscoveryMechanismTypeEDS, 307 Cluster: testClusterName, 308 MaxConcurrentRequests: newUint32(123), 309 }}) 310 shortCtx, shortCancel = context.WithTimeout(context.Background(), defaultTestShortTimeout) 311 defer shortCancel() 312 if n, err := fakeClient.WaitForWatchEDS(shortCtx); err == nil { 313 t.Fatalf("unexpected watch started for EDS: %v", n) 314 } 315 select { 316 case u := <-rr.updateChannel: 317 if diff := cmp.Diff(u.priorities, []priorityConfig{{ 318 mechanism: DiscoveryMechanism{ 319 Type: DiscoveryMechanismTypeEDS, 320 Cluster: testClusterName, 321 MaxConcurrentRequests: newUint32(123), 322 }, 323 edsResp: testEDSUpdates[1], 324 }}, cmp.AllowUnexported(priorityConfig{})); diff != "" { 325 t.Fatalf("got unexpected resource update, diff (-got, +want): %v", diff) 326 } 327 case <-ctx.Done(): 328 t.Fatal("Timed out waiting for update from update channel.") 329 } 330 331 // Close the resource resolver. Should stop EDS watch. 332 rr.stop() 333 edsNameCanceled, err := fakeClient.WaitForCancelEDSWatch(ctx) 334 if err != nil { 335 t.Fatalf("xdsClient.CancelCDS failed with error: %v", err) 336 } 337 if edsNameCanceled != gotEDSName2 { 338 t.Fatalf("xdsClient.CancelEDS called for %v, want: %v", edsNameCanceled, gotEDSName2) 339 } 340 } 341 342 // Test the case that same resources with the same priority should not add new 343 // EDS watch, and also should not trigger an update. 344 func (s) TestResourceResolverNoChangeNoUpdate(t *testing.T) { 345 fakeClient := fakeclient.NewClient() 346 rr := newResourceResolver(&clusterResolverBalancer{xdsClient: fakeClient}) 347 rr.updateMechanisms([]DiscoveryMechanism{ 348 { 349 Type: DiscoveryMechanismTypeEDS, 350 Cluster: testClusterNames[0], 351 }, 352 { 353 Type: DiscoveryMechanismTypeEDS, 354 Cluster: testClusterNames[1], 355 MaxConcurrentRequests: newUint32(100), 356 }, 357 }) 358 ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout) 359 defer ctxCancel() 360 gotEDSName1, err := fakeClient.WaitForWatchEDS(ctx) 361 if err != nil { 362 t.Fatalf("xdsClient.WatchCDS failed with error: %v", err) 363 } 364 if gotEDSName1 != testClusterNames[0] { 365 t.Fatalf("xdsClient.WatchEDS called for cluster: %v, want: %v", gotEDSName1, testClusterNames[0]) 366 } 367 gotEDSName2, err := fakeClient.WaitForWatchEDS(ctx) 368 if err != nil { 369 t.Fatalf("xdsClient.WatchCDS failed with error: %v", err) 370 } 371 if gotEDSName2 != testClusterNames[1] { 372 t.Fatalf("xdsClient.WatchEDS called for cluster: %v, want: %v", gotEDSName2, testClusterNames[1]) 373 } 374 375 // Invoke callback, should get an update. 376 fakeClient.InvokeWatchEDSCallback(gotEDSName1, testEDSUpdates[0], nil) 377 // Shouldn't send update, because only one resource received an update. 378 shortCtx, shortCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 379 defer shortCancel() 380 select { 381 case u := <-rr.updateChannel: 382 t.Fatalf("get unexpected update %+v", u) 383 case <-shortCtx.Done(): 384 } 385 fakeClient.InvokeWatchEDSCallback(gotEDSName2, testEDSUpdates[1], nil) 386 select { 387 case u := <-rr.updateChannel: 388 if diff := cmp.Diff(u.priorities, []priorityConfig{ 389 { 390 mechanism: DiscoveryMechanism{ 391 Type: DiscoveryMechanismTypeEDS, 392 Cluster: testClusterNames[0], 393 }, 394 edsResp: testEDSUpdates[0], 395 }, 396 { 397 mechanism: DiscoveryMechanism{ 398 Type: DiscoveryMechanismTypeEDS, 399 Cluster: testClusterNames[1], 400 MaxConcurrentRequests: newUint32(100), 401 }, 402 edsResp: testEDSUpdates[1], 403 }, 404 }, cmp.AllowUnexported(priorityConfig{})); diff != "" { 405 t.Fatalf("got unexpected resource update, diff (-got, +want): %v", diff) 406 } 407 case <-ctx.Done(): 408 t.Fatal("Timed out waiting for update from update channel.") 409 } 410 411 // Send the same resources with the same priorities, shouldn't any change. 412 rr.updateMechanisms([]DiscoveryMechanism{ 413 { 414 Type: DiscoveryMechanismTypeEDS, 415 Cluster: testClusterNames[0], 416 }, 417 { 418 Type: DiscoveryMechanismTypeEDS, 419 Cluster: testClusterNames[1], 420 MaxConcurrentRequests: newUint32(100), 421 }, 422 }) 423 shortCtx, shortCancel = context.WithTimeout(context.Background(), defaultTestShortTimeout) 424 defer shortCancel() 425 if n, err := fakeClient.WaitForWatchEDS(shortCtx); err == nil { 426 t.Fatalf("unexpected watch started for EDS: %v", n) 427 } 428 shortCtx, shortCancel = context.WithTimeout(context.Background(), defaultTestShortTimeout) 429 defer shortCancel() 430 select { 431 case u := <-rr.updateChannel: 432 t.Fatalf("unexpected update: %+v", u) 433 case <-shortCtx.Done(): 434 } 435 436 // Close the resource resolver. Should stop EDS watch. 437 rr.stop() 438 edsNameCanceled1, err := fakeClient.WaitForCancelEDSWatch(ctx) 439 if err != nil { 440 t.Fatalf("xdsClient.CancelCDS failed with error: %v", err) 441 } 442 if edsNameCanceled1 != gotEDSName1 && edsNameCanceled1 != gotEDSName2 { 443 t.Fatalf("xdsClient.CancelEDS called for %v, want: %v or %v", edsNameCanceled1, gotEDSName1, gotEDSName2) 444 } 445 edsNameCanceled2, err := fakeClient.WaitForCancelEDSWatch(ctx) 446 if err != nil { 447 t.Fatalf("xdsClient.CancelCDS failed with error: %v", err) 448 } 449 if edsNameCanceled2 != gotEDSName2 && edsNameCanceled2 != gotEDSName1 { 450 t.Fatalf("xdsClient.CancelEDS called for %v, want: %v or %v", edsNameCanceled2, gotEDSName1, gotEDSName2) 451 } 452 } 453 454 // Test the case that same resources are watched, but with different priority. 455 // Should not add new EDS watch, but should trigger an update with the new 456 // priorities. 457 func (s) TestResourceResolverChangePriority(t *testing.T) { 458 fakeClient := fakeclient.NewClient() 459 rr := newResourceResolver(&clusterResolverBalancer{xdsClient: fakeClient}) 460 rr.updateMechanisms([]DiscoveryMechanism{ 461 { 462 Type: DiscoveryMechanismTypeEDS, 463 Cluster: testClusterNames[0], 464 }, 465 { 466 Type: DiscoveryMechanismTypeEDS, 467 Cluster: testClusterNames[1], 468 }, 469 }) 470 ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout) 471 defer ctxCancel() 472 gotEDSName1, err := fakeClient.WaitForWatchEDS(ctx) 473 if err != nil { 474 t.Fatalf("xdsClient.WatchCDS failed with error: %v", err) 475 } 476 if gotEDSName1 != testClusterNames[0] { 477 t.Fatalf("xdsClient.WatchEDS called for cluster: %v, want: %v", gotEDSName1, testClusterNames[0]) 478 } 479 gotEDSName2, err := fakeClient.WaitForWatchEDS(ctx) 480 if err != nil { 481 t.Fatalf("xdsClient.WatchCDS failed with error: %v", err) 482 } 483 if gotEDSName2 != testClusterNames[1] { 484 t.Fatalf("xdsClient.WatchEDS called for cluster: %v, want: %v", gotEDSName2, testClusterNames[1]) 485 } 486 487 // Invoke callback, should get an update. 488 fakeClient.InvokeWatchEDSCallback(gotEDSName1, testEDSUpdates[0], nil) 489 // Shouldn't send update, because only one resource received an update. 490 shortCtx, shortCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 491 defer shortCancel() 492 select { 493 case u := <-rr.updateChannel: 494 t.Fatalf("get unexpected update %+v", u) 495 case <-shortCtx.Done(): 496 } 497 fakeClient.InvokeWatchEDSCallback(gotEDSName2, testEDSUpdates[1], nil) 498 select { 499 case u := <-rr.updateChannel: 500 if diff := cmp.Diff(u.priorities, []priorityConfig{ 501 { 502 mechanism: DiscoveryMechanism{ 503 Type: DiscoveryMechanismTypeEDS, 504 Cluster: testClusterNames[0], 505 }, 506 edsResp: testEDSUpdates[0], 507 }, 508 { 509 mechanism: DiscoveryMechanism{ 510 Type: DiscoveryMechanismTypeEDS, 511 Cluster: testClusterNames[1], 512 }, 513 edsResp: testEDSUpdates[1], 514 }, 515 }, cmp.AllowUnexported(priorityConfig{})); diff != "" { 516 t.Fatalf("got unexpected resource update, diff (-got, +want): %v", diff) 517 } 518 case <-ctx.Done(): 519 t.Fatal("Timed out waiting for update from update channel.") 520 } 521 522 // Send the same resources with different priorities, shouldn't trigger 523 // watch, but should trigger an update with the new priorities. 524 rr.updateMechanisms([]DiscoveryMechanism{ 525 { 526 Type: DiscoveryMechanismTypeEDS, 527 Cluster: testClusterNames[1], 528 }, 529 { 530 Type: DiscoveryMechanismTypeEDS, 531 Cluster: testClusterNames[0], 532 }, 533 }) 534 shortCtx, shortCancel = context.WithTimeout(context.Background(), defaultTestShortTimeout) 535 defer shortCancel() 536 if n, err := fakeClient.WaitForWatchEDS(shortCtx); err == nil { 537 t.Fatalf("unexpected watch started for EDS: %v", n) 538 } 539 select { 540 case u := <-rr.updateChannel: 541 if diff := cmp.Diff(u.priorities, []priorityConfig{ 542 { 543 mechanism: DiscoveryMechanism{ 544 Type: DiscoveryMechanismTypeEDS, 545 Cluster: testClusterNames[1], 546 }, 547 edsResp: testEDSUpdates[1], 548 }, 549 { 550 mechanism: DiscoveryMechanism{ 551 Type: DiscoveryMechanismTypeEDS, 552 Cluster: testClusterNames[0], 553 }, 554 edsResp: testEDSUpdates[0], 555 }, 556 }, cmp.AllowUnexported(priorityConfig{})); diff != "" { 557 t.Fatalf("got unexpected resource update, diff (-got, +want): %v", diff) 558 } 559 case <-ctx.Done(): 560 t.Fatal("Timed out waiting for update from update channel.") 561 } 562 563 // Close the resource resolver. Should stop EDS watch. 564 rr.stop() 565 edsNameCanceled1, err := fakeClient.WaitForCancelEDSWatch(ctx) 566 if err != nil { 567 t.Fatalf("xdsClient.CancelCDS failed with error: %v", err) 568 } 569 if edsNameCanceled1 != gotEDSName1 && edsNameCanceled1 != gotEDSName2 { 570 t.Fatalf("xdsClient.CancelEDS called for %v, want: %v or %v", edsNameCanceled1, gotEDSName1, gotEDSName2) 571 } 572 edsNameCanceled2, err := fakeClient.WaitForCancelEDSWatch(ctx) 573 if err != nil { 574 t.Fatalf("xdsClient.CancelCDS failed with error: %v", err) 575 } 576 if edsNameCanceled2 != gotEDSName2 && edsNameCanceled2 != gotEDSName1 { 577 t.Fatalf("xdsClient.CancelEDS called for %v, want: %v or %v", edsNameCanceled2, gotEDSName1, gotEDSName2) 578 } 579 } 580 581 // Test the case that covers resource for both EDS and DNS. 582 func (s) TestResourceResolverEDSAndDNS(t *testing.T) { 583 dnsTargetCh, dnsCloseCh, _, dnsR, cleanup := setupDNS() 584 defer cleanup() 585 fakeClient := fakeclient.NewClient() 586 rr := newResourceResolver(&clusterResolverBalancer{xdsClient: fakeClient}) 587 rr.updateMechanisms([]DiscoveryMechanism{ 588 { 589 Type: DiscoveryMechanismTypeEDS, 590 Cluster: testClusterName, 591 }, 592 { 593 Type: DiscoveryMechanismTypeLogicalDNS, 594 DNSHostname: testDNSTarget, 595 }, 596 }) 597 ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout) 598 defer ctxCancel() 599 gotEDSName1, err := fakeClient.WaitForWatchEDS(ctx) 600 if err != nil { 601 t.Fatalf("xdsClient.WatchCDS failed with error: %v", err) 602 } 603 if gotEDSName1 != testClusterName { 604 t.Fatalf("xdsClient.WatchEDS called for cluster: %v, want: %v", gotEDSName1, testClusterName) 605 } 606 select { 607 case target := <-dnsTargetCh: 608 // Target.Scheme、Target.Endpoint are deprecated, use URL.Scheme、URL.Path instead. 609 //if diff := cmp.Diff(target, resolver.Target{Scheme: "dns", Endpoint: testDNSTarget}); diff != "" { 610 if diff := cmp.Diff(target, resolver.Target{URL: url.URL{Scheme: "dns", Path: testDNSTarget}}); diff != "" { 611 t.Fatalf("got unexpected DNS target to watch, diff (-got, +want): %v", diff) 612 } 613 case <-ctx.Done(): 614 t.Fatal("Timed out waiting for building DNS resolver") 615 } 616 617 fakeClient.InvokeWatchEDSCallback(gotEDSName1, testEDSUpdates[0], nil) 618 // Shouldn't send update, because only one resource received an update. 619 shortCtx, shortCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 620 defer shortCancel() 621 select { 622 case u := <-rr.updateChannel: 623 t.Fatalf("get unexpected update %+v", u) 624 case <-shortCtx.Done(): 625 } 626 // Invoke DNS, should get an update. 627 dnsR.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: "1.1.1.1"}, {Addr: "2.2.2.2"}}}) 628 select { 629 case u := <-rr.updateChannel: 630 if diff := cmp.Diff(u.priorities, []priorityConfig{ 631 { 632 mechanism: DiscoveryMechanism{ 633 Type: DiscoveryMechanismTypeEDS, 634 Cluster: testClusterName, 635 }, 636 edsResp: testEDSUpdates[0], 637 }, 638 { 639 mechanism: DiscoveryMechanism{ 640 Type: DiscoveryMechanismTypeLogicalDNS, 641 DNSHostname: testDNSTarget, 642 }, 643 addresses: []string{"1.1.1.1", "2.2.2.2"}, 644 }, 645 }, cmp.AllowUnexported(priorityConfig{})); diff != "" { 646 t.Fatalf("got unexpected resource update, diff (-got, +want): %v", diff) 647 } 648 case <-ctx.Done(): 649 t.Fatal("Timed out waiting for update from update channel.") 650 } 651 652 // Close the resource resolver. Should stop EDS watch. 653 rr.stop() 654 edsNameCanceled1, err := fakeClient.WaitForCancelEDSWatch(ctx) 655 if err != nil { 656 t.Fatalf("xdsClient.CancelCDS failed with error: %v", err) 657 } 658 if edsNameCanceled1 != gotEDSName1 { 659 t.Fatalf("xdsClient.CancelEDS called for %v, want: %v", edsNameCanceled1, gotEDSName1) 660 } 661 select { 662 case <-dnsCloseCh: 663 case <-ctx.Done(): 664 t.Fatal("Timed out waiting for closing DNS resolver") 665 } 666 } 667 668 // Test the case that covers resource changing between EDS and DNS. 669 func (s) TestResourceResolverChangeFromEDSToDNS(t *testing.T) { 670 dnsTargetCh, dnsCloseCh, _, dnsR, cleanup := setupDNS() 671 defer cleanup() 672 fakeClient := fakeclient.NewClient() 673 rr := newResourceResolver(&clusterResolverBalancer{xdsClient: fakeClient}) 674 rr.updateMechanisms([]DiscoveryMechanism{{ 675 Type: DiscoveryMechanismTypeEDS, 676 Cluster: testClusterName, 677 }}) 678 ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout) 679 defer ctxCancel() 680 gotEDSName1, err := fakeClient.WaitForWatchEDS(ctx) 681 if err != nil { 682 t.Fatalf("xdsClient.WatchCDS failed with error: %v", err) 683 } 684 if gotEDSName1 != testClusterName { 685 t.Fatalf("xdsClient.WatchEDS called for cluster: %v, want: %v", gotEDSName1, testClusterName) 686 } 687 688 // Invoke callback, should get an update. 689 fakeClient.InvokeWatchEDSCallback(gotEDSName1, testEDSUpdates[0], nil) 690 select { 691 case u := <-rr.updateChannel: 692 if diff := cmp.Diff(u.priorities, []priorityConfig{{ 693 mechanism: DiscoveryMechanism{ 694 Type: DiscoveryMechanismTypeEDS, 695 Cluster: testClusterName, 696 }, 697 edsResp: testEDSUpdates[0], 698 }}, cmp.AllowUnexported(priorityConfig{})); diff != "" { 699 t.Fatalf("got unexpected resource update, diff (-got, +want): %v", diff) 700 } 701 case <-ctx.Done(): 702 t.Fatal("Timed out waiting for update from update channel.") 703 } 704 705 // Update to watch DNS instead. Should cancel EDS, and start DNS. 706 rr.updateMechanisms([]DiscoveryMechanism{{ 707 Type: DiscoveryMechanismTypeLogicalDNS, 708 DNSHostname: testDNSTarget, 709 }}) 710 select { 711 case target := <-dnsTargetCh: 712 // Target.Scheme、Target.Endpoint are deprecated, use URL.Scheme、URL.Path instead. 713 //if diff := cmp.Diff(target, resolver.Target{Scheme: "dns", Endpoint: testDNSTarget}); diff != "" { 714 if diff := cmp.Diff(target, resolver.Target{URL: url.URL{Scheme: "dns", Path: testDNSTarget}}); diff != "" { 715 t.Fatalf("got unexpected DNS target to watch, diff (-got, +want): %v", diff) 716 } 717 case <-ctx.Done(): 718 t.Fatal("Timed out waiting for building DNS resolver") 719 } 720 edsNameCanceled1, err := fakeClient.WaitForCancelEDSWatch(ctx) 721 if err != nil { 722 t.Fatalf("xdsClient.CancelCDS failed with error: %v", err) 723 } 724 if edsNameCanceled1 != gotEDSName1 { 725 t.Fatalf("xdsClient.CancelEDS called for %v, want: %v", edsNameCanceled1, gotEDSName1) 726 } 727 728 dnsR.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: "1.1.1.1"}, {Addr: "2.2.2.2"}}}) 729 select { 730 case u := <-rr.updateChannel: 731 if diff := cmp.Diff(u.priorities, []priorityConfig{{ 732 mechanism: DiscoveryMechanism{ 733 Type: DiscoveryMechanismTypeLogicalDNS, 734 DNSHostname: testDNSTarget, 735 }, 736 addresses: []string{"1.1.1.1", "2.2.2.2"}, 737 }}, cmp.AllowUnexported(priorityConfig{})); diff != "" { 738 t.Fatalf("got unexpected resource update, diff (-got, +want): %v", diff) 739 } 740 case <-ctx.Done(): 741 t.Fatal("Timed out waiting for update from update channel.") 742 } 743 744 // Close the resource resolver. Should stop DNS. 745 rr.stop() 746 select { 747 case <-dnsCloseCh: 748 case <-ctx.Done(): 749 t.Fatal("Timed out waiting for closing DNS resolver") 750 } 751 } 752 753 // Test the case that covers errors for both EDS and DNS. 754 func (s) TestResourceResolverError(t *testing.T) { 755 dnsTargetCh, dnsCloseCh, _, dnsR, cleanup := setupDNS() 756 defer cleanup() 757 fakeClient := fakeclient.NewClient() 758 rr := newResourceResolver(&clusterResolverBalancer{xdsClient: fakeClient}) 759 rr.updateMechanisms([]DiscoveryMechanism{ 760 { 761 Type: DiscoveryMechanismTypeEDS, 762 Cluster: testClusterName, 763 }, 764 { 765 Type: DiscoveryMechanismTypeLogicalDNS, 766 DNSHostname: testDNSTarget, 767 }, 768 }) 769 ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout) 770 defer ctxCancel() 771 gotEDSName1, err := fakeClient.WaitForWatchEDS(ctx) 772 if err != nil { 773 t.Fatalf("xdsClient.WatchCDS failed with error: %v", err) 774 } 775 if gotEDSName1 != testClusterName { 776 t.Fatalf("xdsClient.WatchEDS called for cluster: %v, want: %v", gotEDSName1, testClusterName) 777 } 778 select { 779 case target := <-dnsTargetCh: 780 // Target.Scheme、Target.Endpoint are deprecated, use URL.Scheme、URL.Path instead. 781 //if diff := cmp.Diff(target, resolver.Target{Scheme: "dns", Endpoint: testDNSTarget}); diff != "" { 782 if diff := cmp.Diff(target, resolver.Target{URL: url.URL{Scheme: "dns", Path: testDNSTarget}}); diff != "" { 783 t.Fatalf("got unexpected DNS target to watch, diff (-got, +want): %v", diff) 784 } 785 case <-ctx.Done(): 786 t.Fatal("Timed out waiting for building DNS resolver") 787 } 788 789 // Invoke callback with an error, should get an update. 790 edsErr := fmt.Errorf("EDS error") 791 fakeClient.InvokeWatchEDSCallback(gotEDSName1, xdsresource.EndpointsUpdate{}, edsErr) 792 select { 793 case u := <-rr.updateChannel: 794 if u.err != edsErr { 795 t.Fatalf("got unexpected error from update, want %v, got %v", edsErr, u.err) 796 } 797 case <-ctx.Done(): 798 t.Fatal("Timed out waiting for update from update channel.") 799 } 800 801 // Invoke DNS with an error, should get an update. 802 dnsErr := fmt.Errorf("DNS error") 803 dnsR.ReportError(dnsErr) 804 select { 805 case u := <-rr.updateChannel: 806 if u.err != dnsErr { 807 t.Fatalf("got unexpected error from update, want %v, got %v", dnsErr, u.err) 808 } 809 case <-ctx.Done(): 810 t.Fatal("Timed out waiting for update from update channel.") 811 } 812 813 // Close the resource resolver. Should stop EDS watch. 814 rr.stop() 815 edsNameCanceled1, err := fakeClient.WaitForCancelEDSWatch(ctx) 816 if err != nil { 817 t.Fatalf("xdsClient.CancelCDS failed with error: %v", err) 818 } 819 if edsNameCanceled1 != gotEDSName1 { 820 t.Fatalf("xdsClient.CancelEDS called for %v, want: %v", edsNameCanceled1, gotEDSName1) 821 } 822 select { 823 case <-dnsCloseCh: 824 case <-ctx.Done(): 825 t.Fatal("Timed out waiting for closing DNS resolver") 826 } 827 } 828 829 // Test re-resolve of the DNS resolver. 830 func (s) TestResourceResolverDNSResolveNow(t *testing.T) { 831 dnsTargetCh, dnsCloseCh, resolveNowCh, dnsR, cleanup := setupDNS() 832 defer cleanup() 833 fakeClient := fakeclient.NewClient() 834 rr := newResourceResolver(&clusterResolverBalancer{xdsClient: fakeClient}) 835 rr.updateMechanisms([]DiscoveryMechanism{{ 836 Type: DiscoveryMechanismTypeLogicalDNS, 837 DNSHostname: testDNSTarget, 838 }}) 839 ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout) 840 defer ctxCancel() 841 select { 842 case target := <-dnsTargetCh: 843 // Target.Scheme、Target.Endpoint are deprecated, use URL.Scheme、URL.Path instead. 844 //if diff := cmp.Diff(target, resolver.Target{Scheme: "dns", Endpoint: testDNSTarget}); diff != "" { 845 if diff := cmp.Diff(target, resolver.Target{URL: url.URL{Scheme: "dns", Path: testDNSTarget}}); diff != "" { 846 t.Fatalf("got unexpected DNS target to watch, diff (-got, +want): %v", diff) 847 } 848 case <-ctx.Done(): 849 t.Fatal("Timed out waiting for building DNS resolver") 850 } 851 852 // Invoke callback, should get an update. 853 dnsR.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: "1.1.1.1"}, {Addr: "2.2.2.2"}}}) 854 select { 855 case u := <-rr.updateChannel: 856 if diff := cmp.Diff(u.priorities, []priorityConfig{{ 857 mechanism: DiscoveryMechanism{ 858 Type: DiscoveryMechanismTypeLogicalDNS, 859 DNSHostname: testDNSTarget, 860 }, 861 addresses: []string{"1.1.1.1", "2.2.2.2"}, 862 }}, cmp.AllowUnexported(priorityConfig{})); diff != "" { 863 t.Fatalf("got unexpected resource update, diff (-got, +want): %v", diff) 864 } 865 case <-ctx.Done(): 866 t.Fatal("Timed out waiting for update from update channel.") 867 } 868 rr.resolveNow() 869 select { 870 case <-resolveNowCh: 871 case <-ctx.Done(): 872 t.Fatal("Timed out waiting for re-resolve") 873 } 874 // Close the resource resolver. Should close the underlying resolver. 875 rr.stop() 876 select { 877 case <-dnsCloseCh: 878 case <-ctx.Done(): 879 t.Fatal("Timed out waiting for closing DNS resolver") 880 } 881 }