gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/internal/resolver/dns/dns_resolver_test.go (about) 1 /* 2 * 3 * Copyright 2018 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 dns 20 21 import ( 22 "context" 23 "errors" 24 "fmt" 25 "net" 26 "net/url" 27 "os" 28 "reflect" 29 "strings" 30 "sync" 31 "testing" 32 "time" 33 34 "gitee.com/ks-custle/core-gm/grpc/balancer" 35 grpclbstate "gitee.com/ks-custle/core-gm/grpc/balancer/grpclb/state" 36 "gitee.com/ks-custle/core-gm/grpc/internal/envconfig" 37 "gitee.com/ks-custle/core-gm/grpc/internal/leakcheck" 38 "gitee.com/ks-custle/core-gm/grpc/internal/testutils" 39 "gitee.com/ks-custle/core-gm/grpc/resolver" 40 "gitee.com/ks-custle/core-gm/grpc/serviceconfig" 41 "github.com/google/go-cmp/cmp" 42 "github.com/google/go-cmp/cmp/cmpopts" 43 ) 44 45 func TestMain(m *testing.M) { 46 // Set a non-zero duration only for tests which are actually testing that 47 // feature. 48 replaceDNSResRate(time.Duration(0)) // No nead to clean up since we os.Exit 49 overrideDefaultResolver(false) // No nead to clean up since we os.Exit 50 code := m.Run() 51 os.Exit(code) 52 } 53 54 const ( 55 txtBytesLimit = 255 56 defaultTestTimeout = 10 * time.Second 57 defaultTestShortTimeout = 10 * time.Millisecond 58 ) 59 60 type testClientConn struct { 61 resolver.ClientConn // For unimplemented functions 62 target string 63 m1 sync.Mutex 64 state resolver.State 65 updateStateCalls int 66 errChan chan error 67 updateStateErr error 68 } 69 70 func (t *testClientConn) UpdateState(s resolver.State) error { 71 t.m1.Lock() 72 defer t.m1.Unlock() 73 t.state = s 74 t.updateStateCalls++ 75 // This error determines whether DNS Resolver actually decides to exponentially backoff or not. 76 // This can be any error. 77 return t.updateStateErr 78 } 79 80 func (t *testClientConn) getState() (resolver.State, int) { 81 t.m1.Lock() 82 defer t.m1.Unlock() 83 return t.state, t.updateStateCalls 84 } 85 86 func scFromState(s resolver.State) string { 87 if s.ServiceConfig != nil { 88 if s.ServiceConfig.Err != nil { 89 return "" 90 } 91 return s.ServiceConfig.Config.(unparsedServiceConfig).config 92 } 93 return "" 94 } 95 96 type unparsedServiceConfig struct { 97 serviceconfig.Config 98 config string 99 } 100 101 func (t *testClientConn) ParseServiceConfig(s string) *serviceconfig.ParseResult { 102 return &serviceconfig.ParseResult{Config: unparsedServiceConfig{config: s}} 103 } 104 105 func (t *testClientConn) ReportError(err error) { 106 t.errChan <- err 107 } 108 109 type testResolver struct { 110 // A write to this channel is made when this resolver receives a resolution 111 // request. Tests can rely on reading from this channel to be notified about 112 // resolution requests instead of sleeping for a predefined period of time. 113 lookupHostCh *testutils.Channel 114 } 115 116 //goland:noinspection GoUnusedParameter 117 func (tr *testResolver) LookupHost(ctx context.Context, host string) ([]string, error) { 118 if tr.lookupHostCh != nil { 119 tr.lookupHostCh.Send(nil) 120 } 121 return hostLookup(host) 122 } 123 124 //goland:noinspection GoUnusedParameter 125 func (*testResolver) LookupSRV(ctx context.Context, service, proto, name string) (string, []*net.SRV, error) { 126 return srvLookup(service, proto, name) 127 } 128 129 //goland:noinspection GoUnusedParameter 130 func (*testResolver) LookupTXT(ctx context.Context, host string) ([]string, error) { 131 return txtLookup(host) 132 } 133 134 // overrideDefaultResolver overrides the defaultResolver used by the code with 135 // an instance of the testResolver. pushOnLookup controls whether the 136 // testResolver created here pushes lookupHost events on its channel. 137 func overrideDefaultResolver(pushOnLookup bool) func() { 138 oldResolver := defaultResolver 139 140 var lookupHostCh *testutils.Channel 141 if pushOnLookup { 142 lookupHostCh = testutils.NewChannel() 143 } 144 defaultResolver = &testResolver{lookupHostCh: lookupHostCh} 145 146 return func() { 147 defaultResolver = oldResolver 148 } 149 } 150 151 func replaceDNSResRate(d time.Duration) func() { 152 oldMinDNSResRate := minDNSResRate 153 minDNSResRate = d 154 155 return func() { 156 minDNSResRate = oldMinDNSResRate 157 } 158 } 159 160 var hostLookupTbl = struct { 161 sync.Mutex 162 tbl map[string][]string 163 }{ 164 tbl: map[string][]string{ 165 "foo.bar.com": {"1.2.3.4", "5.6.7.8"}, 166 "ipv4.single.fake": {"1.2.3.4"}, 167 "srv.ipv4.single.fake": {"2.4.6.8"}, 168 "srv.ipv4.multi.fake": {}, 169 "srv.ipv6.single.fake": {}, 170 "srv.ipv6.multi.fake": {}, 171 "ipv4.multi.fake": {"1.2.3.4", "5.6.7.8", "9.10.11.12"}, 172 "ipv6.single.fake": {"2607:f8b0:400a:801::1001"}, 173 "ipv6.multi.fake": {"2607:f8b0:400a:801::1001", "2607:f8b0:400a:801::1002", "2607:f8b0:400a:801::1003"}, 174 }, 175 } 176 177 func hostLookup(host string) ([]string, error) { 178 hostLookupTbl.Lock() 179 defer hostLookupTbl.Unlock() 180 if addrs, ok := hostLookupTbl.tbl[host]; ok { 181 return addrs, nil 182 } 183 return nil, &net.DNSError{ 184 Err: "hostLookup error", 185 Name: host, 186 Server: "fake", 187 IsTemporary: true, 188 } 189 } 190 191 var srvLookupTbl = struct { 192 sync.Mutex 193 tbl map[string][]*net.SRV 194 }{ 195 tbl: map[string][]*net.SRV{ 196 "_grpclb._tcp.srv.ipv4.single.fake": {&net.SRV{Target: "ipv4.single.fake", Port: 1234}}, 197 "_grpclb._tcp.srv.ipv4.multi.fake": {&net.SRV{Target: "ipv4.multi.fake", Port: 1234}}, 198 "_grpclb._tcp.srv.ipv6.single.fake": {&net.SRV{Target: "ipv6.single.fake", Port: 1234}}, 199 "_grpclb._tcp.srv.ipv6.multi.fake": {&net.SRV{Target: "ipv6.multi.fake", Port: 1234}}, 200 }, 201 } 202 203 func srvLookup(service, proto, name string) (string, []*net.SRV, error) { 204 cname := "_" + service + "._" + proto + "." + name 205 srvLookupTbl.Lock() 206 defer srvLookupTbl.Unlock() 207 if srvs, cnt := srvLookupTbl.tbl[cname]; cnt { 208 return cname, srvs, nil 209 } 210 return "", nil, &net.DNSError{ 211 Err: "srvLookup error", 212 Name: cname, 213 Server: "fake", 214 IsTemporary: true, 215 } 216 } 217 218 // scfs contains an array of service config file string in JSON format. 219 // Notes about the scfs contents and usage: 220 // scfs contains 4 service config file JSON strings for testing. Inside each 221 // service config file, there are multiple choices. scfs[0:3] each contains 5 222 // choices, and first 3 choices are nonmatching choices based on canarying rule, 223 // while the last two are matched choices. scfs[3] only contains 3 choices, and 224 // all of them are nonmatching based on canarying rule. For each of scfs[0:3], 225 // the eventually returned service config, which is from the first of the two 226 // matched choices, is stored in the corresponding scs element (e.g. 227 // scfs[0]->scs[0]). scfs and scs elements are used in pair to test the dns 228 // resolver functionality, with scfs as the input and scs used for validation of 229 // the output. For scfs[3], it corresponds to empty service config, since there 230 // isn't a matched choice. 231 var scfs = []string{ 232 `[ 233 { 234 "clientLanguage": [ 235 "CPP", 236 "JAVA" 237 ], 238 "serviceConfig": { 239 "loadBalancingPolicy": "grpclb", 240 "methodConfig": [ 241 { 242 "name": [ 243 { 244 "service": "all" 245 } 246 ], 247 "timeout": "1s" 248 } 249 ] 250 } 251 }, 252 { 253 "percentage": 0, 254 "serviceConfig": { 255 "loadBalancingPolicy": "grpclb", 256 "methodConfig": [ 257 { 258 "name": [ 259 { 260 "service": "all" 261 } 262 ], 263 "timeout": "1s" 264 } 265 ] 266 } 267 }, 268 { 269 "clientHostName": [ 270 "localhost" 271 ], 272 "serviceConfig": { 273 "loadBalancingPolicy": "grpclb", 274 "methodConfig": [ 275 { 276 "name": [ 277 { 278 "service": "all" 279 } 280 ], 281 "timeout": "1s" 282 } 283 ] 284 } 285 }, 286 { 287 "clientLanguage": [ 288 "GO" 289 ], 290 "percentage": 100, 291 "serviceConfig": { 292 "methodConfig": [ 293 { 294 "name": [ 295 { 296 "method": "bar" 297 } 298 ], 299 "maxRequestMessageBytes": 1024, 300 "maxResponseMessageBytes": 1024 301 } 302 ] 303 } 304 }, 305 { 306 "serviceConfig": { 307 "loadBalancingPolicy": "round_robin", 308 "methodConfig": [ 309 { 310 "name": [ 311 { 312 "service": "foo", 313 "method": "bar" 314 } 315 ], 316 "waitForReady": true 317 } 318 ] 319 } 320 } 321 ]`, 322 `[ 323 { 324 "clientLanguage": [ 325 "CPP", 326 "JAVA" 327 ], 328 "serviceConfig": { 329 "loadBalancingPolicy": "grpclb", 330 "methodConfig": [ 331 { 332 "name": [ 333 { 334 "service": "all" 335 } 336 ], 337 "timeout": "1s" 338 } 339 ] 340 } 341 }, 342 { 343 "percentage": 0, 344 "serviceConfig": { 345 "loadBalancingPolicy": "grpclb", 346 "methodConfig": [ 347 { 348 "name": [ 349 { 350 "service": "all" 351 } 352 ], 353 "timeout": "1s" 354 } 355 ] 356 } 357 }, 358 { 359 "clientHostName": [ 360 "localhost" 361 ], 362 "serviceConfig": { 363 "loadBalancingPolicy": "grpclb", 364 "methodConfig": [ 365 { 366 "name": [ 367 { 368 "service": "all" 369 } 370 ], 371 "timeout": "1s" 372 } 373 ] 374 } 375 }, 376 { 377 "clientLanguage": [ 378 "GO" 379 ], 380 "percentage": 100, 381 "serviceConfig": { 382 "methodConfig": [ 383 { 384 "name": [ 385 { 386 "service": "foo", 387 "method": "bar" 388 } 389 ], 390 "waitForReady": true, 391 "timeout": "1s", 392 "maxRequestMessageBytes": 1024, 393 "maxResponseMessageBytes": 1024 394 } 395 ] 396 } 397 }, 398 { 399 "serviceConfig": { 400 "loadBalancingPolicy": "round_robin", 401 "methodConfig": [ 402 { 403 "name": [ 404 { 405 "service": "foo", 406 "method": "bar" 407 } 408 ], 409 "waitForReady": true 410 } 411 ] 412 } 413 } 414 ]`, 415 `[ 416 { 417 "clientLanguage": [ 418 "CPP", 419 "JAVA" 420 ], 421 "serviceConfig": { 422 "loadBalancingPolicy": "grpclb", 423 "methodConfig": [ 424 { 425 "name": [ 426 { 427 "service": "all" 428 } 429 ], 430 "timeout": "1s" 431 } 432 ] 433 } 434 }, 435 { 436 "percentage": 0, 437 "serviceConfig": { 438 "loadBalancingPolicy": "grpclb", 439 "methodConfig": [ 440 { 441 "name": [ 442 { 443 "service": "all" 444 } 445 ], 446 "timeout": "1s" 447 } 448 ] 449 } 450 }, 451 { 452 "clientHostName": [ 453 "localhost" 454 ], 455 "serviceConfig": { 456 "loadBalancingPolicy": "grpclb", 457 "methodConfig": [ 458 { 459 "name": [ 460 { 461 "service": "all" 462 } 463 ], 464 "timeout": "1s" 465 } 466 ] 467 } 468 }, 469 { 470 "clientLanguage": [ 471 "GO" 472 ], 473 "percentage": 100, 474 "serviceConfig": { 475 "loadBalancingPolicy": "round_robin", 476 "methodConfig": [ 477 { 478 "name": [ 479 { 480 "service": "foo" 481 } 482 ], 483 "waitForReady": true, 484 "timeout": "1s" 485 }, 486 { 487 "name": [ 488 { 489 "service": "bar" 490 } 491 ], 492 "waitForReady": false 493 } 494 ] 495 } 496 }, 497 { 498 "serviceConfig": { 499 "loadBalancingPolicy": "round_robin", 500 "methodConfig": [ 501 { 502 "name": [ 503 { 504 "service": "foo", 505 "method": "bar" 506 } 507 ], 508 "waitForReady": true 509 } 510 ] 511 } 512 } 513 ]`, 514 `[ 515 { 516 "clientLanguage": [ 517 "CPP", 518 "JAVA" 519 ], 520 "serviceConfig": { 521 "loadBalancingPolicy": "grpclb", 522 "methodConfig": [ 523 { 524 "name": [ 525 { 526 "service": "all" 527 } 528 ], 529 "timeout": "1s" 530 } 531 ] 532 } 533 }, 534 { 535 "percentage": 0, 536 "serviceConfig": { 537 "loadBalancingPolicy": "grpclb", 538 "methodConfig": [ 539 { 540 "name": [ 541 { 542 "service": "all" 543 } 544 ], 545 "timeout": "1s" 546 } 547 ] 548 } 549 }, 550 { 551 "clientHostName": [ 552 "localhost" 553 ], 554 "serviceConfig": { 555 "loadBalancingPolicy": "grpclb", 556 "methodConfig": [ 557 { 558 "name": [ 559 { 560 "service": "all" 561 } 562 ], 563 "timeout": "1s" 564 } 565 ] 566 } 567 } 568 ]`, 569 } 570 571 // scs contains an array of service config string in JSON format. 572 var scs = []string{ 573 `{ 574 "methodConfig": [ 575 { 576 "name": [ 577 { 578 "method": "bar" 579 } 580 ], 581 "maxRequestMessageBytes": 1024, 582 "maxResponseMessageBytes": 1024 583 } 584 ] 585 }`, 586 `{ 587 "methodConfig": [ 588 { 589 "name": [ 590 { 591 "service": "foo", 592 "method": "bar" 593 } 594 ], 595 "waitForReady": true, 596 "timeout": "1s", 597 "maxRequestMessageBytes": 1024, 598 "maxResponseMessageBytes": 1024 599 } 600 ] 601 }`, 602 `{ 603 "loadBalancingPolicy": "round_robin", 604 "methodConfig": [ 605 { 606 "name": [ 607 { 608 "service": "foo" 609 } 610 ], 611 "waitForReady": true, 612 "timeout": "1s" 613 }, 614 { 615 "name": [ 616 { 617 "service": "bar" 618 } 619 ], 620 "waitForReady": false 621 } 622 ] 623 }`, 624 } 625 626 // scLookupTbl is a map, which contains targets that have service config to 627 // their configs. Targets not in this set should not have service config. 628 var scLookupTbl = map[string]string{ 629 "foo.bar.com": scs[0], 630 "srv.ipv4.single.fake": scs[1], 631 "srv.ipv4.multi.fake": scs[2], 632 } 633 634 // generateSC returns a service config string in JSON format for the input name. 635 func generateSC(name string) string { 636 return scLookupTbl[name] 637 } 638 639 // generateSCF generates a slice of strings (aggregately representing a single 640 // service config file) for the input config string, which mocks the result 641 // from a real DNS TXT record lookup. 642 func generateSCF(cfg string) []string { 643 b := append([]byte(txtAttribute), []byte(cfg)...) 644 645 // Split b into multiple strings, each with a max of 255 bytes, which is 646 // the DNS TXT record limit. 647 var r []string 648 for i := 0; i < len(b); i += txtBytesLimit { 649 if i+txtBytesLimit > len(b) { 650 r = append(r, string(b[i:])) 651 } else { 652 r = append(r, string(b[i:i+txtBytesLimit])) 653 } 654 } 655 return r 656 } 657 658 var txtLookupTbl = struct { 659 sync.Mutex 660 tbl map[string][]string 661 }{ 662 tbl: map[string][]string{ 663 txtPrefix + "foo.bar.com": generateSCF(scfs[0]), 664 txtPrefix + "srv.ipv4.single.fake": generateSCF(scfs[1]), 665 txtPrefix + "srv.ipv4.multi.fake": generateSCF(scfs[2]), 666 txtPrefix + "srv.ipv6.single.fake": generateSCF(scfs[3]), 667 txtPrefix + "srv.ipv6.multi.fake": generateSCF(scfs[3]), 668 }, 669 } 670 671 func txtLookup(host string) ([]string, error) { 672 txtLookupTbl.Lock() 673 defer txtLookupTbl.Unlock() 674 if scs, cnt := txtLookupTbl.tbl[host]; cnt { 675 return scs, nil 676 } 677 return nil, &net.DNSError{ 678 Err: "txtLookup error", 679 Name: host, 680 Server: "fake", 681 IsTemporary: true, 682 } 683 } 684 685 func TestResolve(t *testing.T) { 686 testDNSResolver(t) 687 testDNSResolverWithSRV(t) 688 testDNSResolveNow(t) 689 testIPResolver(t) 690 } 691 692 func testDNSResolver(t *testing.T) { 693 defer leakcheck.Check(t) 694 defer func(nt func(d time.Duration) *time.Timer) { 695 newTimer = nt 696 }(newTimer) 697 newTimer = func(_ time.Duration) *time.Timer { 698 // Will never fire on its own, will protect from triggering exponential backoff. 699 return time.NewTimer(time.Hour) 700 } 701 tests := []struct { 702 target string 703 addrWant []resolver.Address 704 scWant string 705 }{ 706 { 707 "foo.bar.com", 708 []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}, {Addr: "5.6.7.8" + colonDefaultPort}}, 709 generateSC("foo.bar.com"), 710 }, 711 { 712 "foo.bar.com:1234", 713 []resolver.Address{{Addr: "1.2.3.4:1234"}, {Addr: "5.6.7.8:1234"}}, 714 generateSC("foo.bar.com"), 715 }, 716 { 717 "srv.ipv4.single.fake", 718 []resolver.Address{{Addr: "2.4.6.8" + colonDefaultPort}}, 719 generateSC("srv.ipv4.single.fake"), 720 }, 721 { 722 "srv.ipv4.multi.fake", 723 nil, 724 generateSC("srv.ipv4.multi.fake"), 725 }, 726 { 727 "srv.ipv6.single.fake", 728 nil, 729 generateSC("srv.ipv6.single.fake"), 730 }, 731 { 732 "srv.ipv6.multi.fake", 733 nil, 734 generateSC("srv.ipv6.multi.fake"), 735 }, 736 } 737 738 for _, a := range tests { 739 b := NewBuilder() 740 cc := &testClientConn{target: a.target} 741 // Endpoint is deprecated, use URL.Path or URL.Opaque instead. 742 //r, err := b.Build(resolver.Target{Endpoint: a.target}, cc, resolver.BuildOptions{}) 743 r, err := b.Build(resolver.Target{URL: url.URL{Path: a.target}}, cc, resolver.BuildOptions{}) 744 if err != nil { 745 t.Fatalf("%v\n", err) 746 } 747 var state resolver.State 748 var cnt int 749 for i := 0; i < 2000; i++ { 750 state, cnt = cc.getState() 751 if cnt > 0 { 752 break 753 } 754 time.Sleep(time.Millisecond) 755 } 756 if cnt == 0 { 757 t.Fatalf("UpdateState not called after 2s; aborting") 758 } 759 if !cmp.Equal(a.addrWant, state.Addresses, cmpopts.EquateEmpty()) { 760 t.Errorf("Resolved addresses of target: %q = %+v, want %+v", a.target, state.Addresses, a.addrWant) 761 } 762 sc := scFromState(state) 763 if a.scWant != sc { 764 t.Errorf("Resolved service config of target: %q = %+v, want %+v", a.target, sc, a.scWant) 765 } 766 r.Close() 767 } 768 } 769 770 // DNS Resolver immediately starts polling on an error from grpc. This should continue until the ClientConn doesn't 771 // send back an error from updating the DNS Resolver's state. 772 func TestDNSResolverExponentialBackoff(t *testing.T) { 773 defer leakcheck.Check(t) 774 defer func(nt func(d time.Duration) *time.Timer) { 775 newTimer = nt 776 }(newTimer) 777 timerChan := testutils.NewChannel() 778 newTimer = func(d time.Duration) *time.Timer { 779 // Will never fire on its own, allows this test to call timer immediately. 780 t := time.NewTimer(time.Hour) 781 timerChan.Send(t) 782 return t 783 } 784 tests := []struct { 785 name string 786 target string 787 addrWant []resolver.Address 788 scWant string 789 }{ 790 { 791 "happy case default port", 792 "foo.bar.com", 793 []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}, {Addr: "5.6.7.8" + colonDefaultPort}}, 794 generateSC("foo.bar.com"), 795 }, 796 { 797 "happy case specified port", 798 "foo.bar.com:1234", 799 []resolver.Address{{Addr: "1.2.3.4:1234"}, {Addr: "5.6.7.8:1234"}}, 800 generateSC("foo.bar.com"), 801 }, 802 { 803 "happy case another default port", 804 "srv.ipv4.single.fake", 805 []resolver.Address{{Addr: "2.4.6.8" + colonDefaultPort}}, 806 generateSC("srv.ipv4.single.fake"), 807 }, 808 } 809 for _, test := range tests { 810 t.Run(test.name, func(t *testing.T) { 811 b := NewBuilder() 812 cc := &testClientConn{target: test.target} 813 // Cause ClientConn to return an error. 814 cc.updateStateErr = balancer.ErrBadResolverState 815 // Endpoint is deprecated, use URL.Path or URL.Opaque instead. 816 //r, err := b.Build(resolver.Target{Endpoint: test.target}, cc, resolver.BuildOptions{}) 817 r, err := b.Build(resolver.Target{URL: url.URL{Path: test.target}}, cc, resolver.BuildOptions{}) 818 if err != nil { 819 t.Fatalf("Error building resolver for target %v: %v", test.target, err) 820 } 821 var state resolver.State 822 var cnt int 823 for i := 0; i < 2000; i++ { 824 state, cnt = cc.getState() 825 if cnt > 0 { 826 break 827 } 828 time.Sleep(time.Millisecond) 829 } 830 if cnt == 0 { 831 t.Fatalf("UpdateState not called after 2s; aborting") 832 } 833 if !reflect.DeepEqual(test.addrWant, state.Addresses) { 834 t.Errorf("Resolved addresses of target: %q = %+v, want %+v", test.target, state.Addresses, test.addrWant) 835 } 836 sc := scFromState(state) 837 if test.scWant != sc { 838 t.Errorf("Resolved service config of target: %q = %+v, want %+v", test.target, sc, test.scWant) 839 } 840 ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout) 841 defer ctxCancel() 842 // Cause timer to go off 10 times, and see if it calls updateState() correctly. 843 for i := 0; i < 10; i++ { 844 timer, err := timerChan.Receive(ctx) 845 if err != nil { 846 t.Fatalf("Error receiving timer from mock NewTimer call: %v", err) 847 } 848 timerPointer := timer.(*time.Timer) 849 timerPointer.Reset(0) 850 } 851 // Poll to see if DNS Resolver updated state the correct number of times, which allows time for the DNS Resolver to call 852 // ClientConn update state. 853 deadline := time.Now().Add(defaultTestTimeout) 854 for { 855 cc.m1.Lock() 856 got := cc.updateStateCalls 857 cc.m1.Unlock() 858 if got == 11 { 859 break 860 } 861 862 if time.Now().After(deadline) { 863 t.Fatalf("Exponential backoff is not working as expected - should update state 11 times instead of %d", got) 864 } 865 866 time.Sleep(time.Millisecond) 867 } 868 869 // Update resolver.ClientConn to not return an error anymore - this should stop it from backing off. 870 cc.updateStateErr = nil 871 timer, err := timerChan.Receive(ctx) 872 if err != nil { 873 t.Fatalf("Error receiving timer from mock NewTimer call: %v", err) 874 } 875 timerPointer := timer.(*time.Timer) 876 timerPointer.Reset(0) 877 // Poll to see if DNS Resolver updated state the correct number of times, which allows time for the DNS Resolver to call 878 // ClientConn update state the final time. The DNS Resolver should then stop polling. 879 deadline = time.Now().Add(defaultTestTimeout) 880 for { 881 cc.m1.Lock() 882 got := cc.updateStateCalls 883 cc.m1.Unlock() 884 if got == 12 { 885 break 886 } 887 888 if time.Now().After(deadline) { 889 t.Fatalf("Exponential backoff is not working as expected - should stop backing off at 12 total UpdateState calls instead of %d", got) 890 } 891 892 _, err := timerChan.ReceiveOrFail() 893 if err { 894 t.Fatalf("Should not poll again after Client Conn stops returning error.") 895 } 896 897 time.Sleep(time.Millisecond) 898 } 899 r.Close() 900 }) 901 } 902 } 903 904 //goland:noinspection GoDeferInLoop 905 func testDNSResolverWithSRV(t *testing.T) { 906 EnableSRVLookups = true 907 defer func() { 908 EnableSRVLookups = false 909 }() 910 defer leakcheck.Check(t) 911 defer func(nt func(d time.Duration) *time.Timer) { 912 newTimer = nt 913 }(newTimer) 914 newTimer = func(_ time.Duration) *time.Timer { 915 // Will never fire on its own, will protect from triggering exponential backoff. 916 return time.NewTimer(time.Hour) 917 } 918 tests := []struct { 919 target string 920 addrWant []resolver.Address 921 grpclbAddrs []resolver.Address 922 scWant string 923 }{ 924 { 925 "foo.bar.com", 926 []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}, {Addr: "5.6.7.8" + colonDefaultPort}}, 927 nil, 928 generateSC("foo.bar.com"), 929 }, 930 { 931 "foo.bar.com:1234", 932 []resolver.Address{{Addr: "1.2.3.4:1234"}, {Addr: "5.6.7.8:1234"}}, 933 nil, 934 generateSC("foo.bar.com"), 935 }, 936 { 937 "srv.ipv4.single.fake", 938 []resolver.Address{{Addr: "2.4.6.8" + colonDefaultPort}}, 939 []resolver.Address{{Addr: "1.2.3.4:1234", ServerName: "ipv4.single.fake"}}, 940 generateSC("srv.ipv4.single.fake"), 941 }, 942 { 943 "srv.ipv4.multi.fake", 944 nil, 945 []resolver.Address{ 946 {Addr: "1.2.3.4:1234", ServerName: "ipv4.multi.fake"}, 947 {Addr: "5.6.7.8:1234", ServerName: "ipv4.multi.fake"}, 948 {Addr: "9.10.11.12:1234", ServerName: "ipv4.multi.fake"}, 949 }, 950 generateSC("srv.ipv4.multi.fake"), 951 }, 952 { 953 "srv.ipv6.single.fake", 954 nil, 955 []resolver.Address{{Addr: "[2607:f8b0:400a:801::1001]:1234", ServerName: "ipv6.single.fake"}}, 956 generateSC("srv.ipv6.single.fake"), 957 }, 958 { 959 "srv.ipv6.multi.fake", 960 nil, 961 []resolver.Address{ 962 {Addr: "[2607:f8b0:400a:801::1001]:1234", ServerName: "ipv6.multi.fake"}, 963 {Addr: "[2607:f8b0:400a:801::1002]:1234", ServerName: "ipv6.multi.fake"}, 964 {Addr: "[2607:f8b0:400a:801::1003]:1234", ServerName: "ipv6.multi.fake"}, 965 }, 966 generateSC("srv.ipv6.multi.fake"), 967 }, 968 } 969 970 for _, a := range tests { 971 b := NewBuilder() 972 cc := &testClientConn{target: a.target} 973 // Endpoint is deprecated, use URL.Path or URL.Opaque instead. 974 //r, err := b.Build(resolver.Target{Endpoint: a.target}, cc, resolver.BuildOptions{}) 975 r, err := b.Build(resolver.Target{URL: url.URL{Path: a.target}}, cc, resolver.BuildOptions{}) 976 if err != nil { 977 t.Fatalf("%v\n", err) 978 } 979 defer r.Close() 980 var state resolver.State 981 var cnt int 982 for i := 0; i < 2000; i++ { 983 state, cnt = cc.getState() 984 if cnt > 0 { 985 break 986 } 987 time.Sleep(time.Millisecond) 988 } 989 if cnt == 0 { 990 t.Fatalf("UpdateState not called after 2s; aborting") 991 } 992 if !cmp.Equal(a.addrWant, state.Addresses, cmpopts.EquateEmpty()) { 993 t.Errorf("Resolved addresses of target: %q = %+v, want %+v", a.target, state.Addresses, a.addrWant) 994 } 995 gs := grpclbstate.Get(state) 996 if (gs == nil && len(a.grpclbAddrs) > 0) || 997 (gs != nil && !reflect.DeepEqual(a.grpclbAddrs, gs.BalancerAddresses)) { 998 t.Errorf("Resolved state of target: %q = %+v (State=%+v), want state.Attributes.State=%+v", a.target, state, gs, a.grpclbAddrs) 999 } 1000 sc := scFromState(state) 1001 if a.scWant != sc { 1002 t.Errorf("Resolved service config of target: %q = %+v, want %+v", a.target, sc, a.scWant) 1003 } 1004 } 1005 } 1006 1007 func mutateTbl(target string) func() { 1008 hostLookupTbl.Lock() 1009 oldHostTblEntry := hostLookupTbl.tbl[target] 1010 hostLookupTbl.tbl[target] = hostLookupTbl.tbl[target][:len(oldHostTblEntry)-1] 1011 hostLookupTbl.Unlock() 1012 txtLookupTbl.Lock() 1013 oldTxtTblEntry := txtLookupTbl.tbl[txtPrefix+target] 1014 txtLookupTbl.tbl[txtPrefix+target] = []string{txtAttribute + `[{"serviceConfig":{"loadBalancingPolicy": "grpclb"}}]`} 1015 txtLookupTbl.Unlock() 1016 1017 return func() { 1018 hostLookupTbl.Lock() 1019 hostLookupTbl.tbl[target] = oldHostTblEntry 1020 hostLookupTbl.Unlock() 1021 txtLookupTbl.Lock() 1022 if len(oldTxtTblEntry) == 0 { 1023 delete(txtLookupTbl.tbl, txtPrefix+target) 1024 } else { 1025 txtLookupTbl.tbl[txtPrefix+target] = oldTxtTblEntry 1026 } 1027 txtLookupTbl.Unlock() 1028 } 1029 } 1030 1031 //goland:noinspection GoDeferInLoop 1032 func testDNSResolveNow(t *testing.T) { 1033 defer leakcheck.Check(t) 1034 defer func(nt func(d time.Duration) *time.Timer) { 1035 newTimer = nt 1036 }(newTimer) 1037 newTimer = func(_ time.Duration) *time.Timer { 1038 // Will never fire on its own, will protect from triggering exponential backoff. 1039 return time.NewTimer(time.Hour) 1040 } 1041 tests := []struct { 1042 target string 1043 addrWant []resolver.Address 1044 addrNext []resolver.Address 1045 scWant string 1046 scNext string 1047 }{ 1048 { 1049 "foo.bar.com", 1050 []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}, {Addr: "5.6.7.8" + colonDefaultPort}}, 1051 []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}}, 1052 generateSC("foo.bar.com"), 1053 `{"loadBalancingPolicy": "grpclb"}`, 1054 }, 1055 } 1056 1057 for _, a := range tests { 1058 b := NewBuilder() 1059 cc := &testClientConn{target: a.target} 1060 // Endpoint is deprecated, use URL.Path or URL.Opaque instead. 1061 //r, err := b.Build(resolver.Target{Endpoint: a.target}, cc, resolver.BuildOptions{}) 1062 r, err := b.Build(resolver.Target{URL: url.URL{Path: a.target}}, cc, resolver.BuildOptions{}) 1063 if err != nil { 1064 t.Fatalf("%v\n", err) 1065 } 1066 defer r.Close() 1067 var state resolver.State 1068 var cnt int 1069 for i := 0; i < 2000; i++ { 1070 state, cnt = cc.getState() 1071 if cnt > 0 { 1072 break 1073 } 1074 time.Sleep(time.Millisecond) 1075 } 1076 if cnt == 0 { 1077 t.Fatalf("UpdateState not called after 2s; aborting. state=%v", state) 1078 } 1079 if !reflect.DeepEqual(a.addrWant, state.Addresses) { 1080 t.Errorf("Resolved addresses of target: %q = %+v, want %+v", a.target, state.Addresses, a.addrWant) 1081 } 1082 sc := scFromState(state) 1083 if a.scWant != sc { 1084 t.Errorf("Resolved service config of target: %q = %+v, want %+v", a.target, sc, a.scWant) 1085 } 1086 1087 revertTbl := mutateTbl(a.target) 1088 r.ResolveNow(resolver.ResolveNowOptions{}) 1089 for i := 0; i < 2000; i++ { 1090 state, cnt = cc.getState() 1091 if cnt == 2 { 1092 break 1093 } 1094 time.Sleep(time.Millisecond) 1095 } 1096 if cnt != 2 { 1097 t.Fatalf("UpdateState not called after 2s; aborting. state=%v", state) 1098 } 1099 sc = scFromState(state) 1100 if !reflect.DeepEqual(a.addrNext, state.Addresses) { 1101 t.Errorf("Resolved addresses of target: %q = %+v, want %+v", a.target, state.Addresses, a.addrNext) 1102 } 1103 if a.scNext != sc { 1104 t.Errorf("Resolved service config of target: %q = %+v, want %+v", a.target, sc, a.scNext) 1105 } 1106 revertTbl() 1107 } 1108 } 1109 1110 const colonDefaultPort = ":" + defaultPort 1111 1112 func testIPResolver(t *testing.T) { 1113 defer leakcheck.Check(t) 1114 defer func(nt func(d time.Duration) *time.Timer) { 1115 newTimer = nt 1116 }(newTimer) 1117 newTimer = func(_ time.Duration) *time.Timer { 1118 // Will never fire on its own, will protect from triggering exponential backoff. 1119 return time.NewTimer(time.Hour) 1120 } 1121 tests := []struct { 1122 target string 1123 want []resolver.Address 1124 }{ 1125 {"127.0.0.1", []resolver.Address{{Addr: "127.0.0.1" + colonDefaultPort}}}, 1126 {"127.0.0.1:12345", []resolver.Address{{Addr: "127.0.0.1:12345"}}}, 1127 {"::1", []resolver.Address{{Addr: "[::1]" + colonDefaultPort}}}, 1128 {"[::1]:12345", []resolver.Address{{Addr: "[::1]:12345"}}}, 1129 {"[::1]", []resolver.Address{{Addr: "[::1]:443"}}}, 1130 {"2001:db8:85a3::8a2e:370:7334", []resolver.Address{{Addr: "[2001:db8:85a3::8a2e:370:7334]" + colonDefaultPort}}}, 1131 {"[2001:db8:85a3::8a2e:370:7334]", []resolver.Address{{Addr: "[2001:db8:85a3::8a2e:370:7334]" + colonDefaultPort}}}, 1132 {"[2001:db8:85a3::8a2e:370:7334]:12345", []resolver.Address{{Addr: "[2001:db8:85a3::8a2e:370:7334]:12345"}}}, 1133 {"[2001:db8::1]:http", []resolver.Address{{Addr: "[2001:db8::1]:http"}}}, 1134 // TODO(yuxuanli): zone support? 1135 } 1136 1137 for _, v := range tests { 1138 b := NewBuilder() 1139 cc := &testClientConn{target: v.target} 1140 // Endpoint is deprecated, use URL.Path or URL.Opaque instead. 1141 //r, err := b.Build(resolver.Target{Endpoint: v.target}, cc, resolver.BuildOptions{}) 1142 r, err := b.Build(resolver.Target{URL: url.URL{Path: v.target}}, cc, resolver.BuildOptions{}) 1143 if err != nil { 1144 t.Fatalf("%v\n", err) 1145 } 1146 var state resolver.State 1147 var cnt int 1148 for { 1149 state, cnt = cc.getState() 1150 if cnt > 0 { 1151 break 1152 } 1153 time.Sleep(time.Millisecond) 1154 } 1155 if !reflect.DeepEqual(v.want, state.Addresses) { 1156 t.Errorf("Resolved addresses of target: %q = %+v, want %+v", v.target, state.Addresses, v.want) 1157 } 1158 r.ResolveNow(resolver.ResolveNowOptions{}) 1159 for i := 0; i < 50; i++ { 1160 state, cnt = cc.getState() 1161 if cnt > 1 { 1162 t.Fatalf("Unexpected second call by resolver to UpdateState. state: %v", state) 1163 } 1164 time.Sleep(time.Millisecond) 1165 } 1166 r.Close() 1167 } 1168 } 1169 1170 func TestResolveFunc(t *testing.T) { 1171 defer leakcheck.Check(t) 1172 defer func(nt func(d time.Duration) *time.Timer) { 1173 newTimer = nt 1174 }(newTimer) 1175 newTimer = func(d time.Duration) *time.Timer { 1176 // Will never fire on its own, will protect from triggering exponential backoff. 1177 return time.NewTimer(time.Hour) 1178 } 1179 tests := []struct { 1180 addr string 1181 want error 1182 }{ 1183 // TODO(yuxuanli): More false cases? 1184 {"www.google.com", nil}, 1185 {"foo.bar:12345", nil}, 1186 {"127.0.0.1", nil}, 1187 {"::", nil}, 1188 {"127.0.0.1:12345", nil}, 1189 {"[::1]:80", nil}, 1190 {"[2001:db8:a0b:12f0::1]:21", nil}, 1191 {":80", nil}, 1192 {"127.0.0...1:12345", nil}, 1193 {"[fe80::1%lo0]:80", nil}, 1194 {"golang.org:http", nil}, 1195 {"[2001:db8::1]:http", nil}, 1196 {"[2001:db8::1]:", errEndsWithColon}, 1197 {":", errEndsWithColon}, 1198 {"", errMissingAddr}, 1199 {"[2001:db8:a0b:12f0::1", fmt.Errorf("invalid target address [2001:db8:a0b:12f0::1, error info: address [2001:db8:a0b:12f0::1:443: missing ']' in address")}, 1200 } 1201 1202 b := NewBuilder() 1203 for _, v := range tests { 1204 cc := &testClientConn{target: v.addr, errChan: make(chan error, 1)} 1205 // Endpoint is deprecated, use URL.Path or URL.Opaque instead. 1206 //r, err := b.Build(resolver.Target{Endpoint: v.addr}, cc, resolver.BuildOptions{}) 1207 r, err := b.Build(resolver.Target{URL: url.URL{Path: v.addr}}, cc, resolver.BuildOptions{}) 1208 if err == nil { 1209 r.Close() 1210 } 1211 if !reflect.DeepEqual(err, v.want) { 1212 t.Errorf("Build(%q, cc, _) = %v, want %v", v.addr, err, v.want) 1213 } 1214 } 1215 } 1216 1217 //goland:noinspection GoDeferInLoop 1218 func TestDisableServiceConfig(t *testing.T) { 1219 defer leakcheck.Check(t) 1220 defer func(nt func(d time.Duration) *time.Timer) { 1221 newTimer = nt 1222 }(newTimer) 1223 newTimer = func(d time.Duration) *time.Timer { 1224 // Will never fire on its own, will protect from triggering exponential backoff. 1225 return time.NewTimer(time.Hour) 1226 } 1227 tests := []struct { 1228 target string 1229 scWant string 1230 disableServiceConfig bool 1231 }{ 1232 { 1233 "foo.bar.com", 1234 generateSC("foo.bar.com"), 1235 false, 1236 }, 1237 { 1238 "foo.bar.com", 1239 "", 1240 true, 1241 }, 1242 } 1243 1244 for _, a := range tests { 1245 b := NewBuilder() 1246 cc := &testClientConn{target: a.target} 1247 // Endpoint is deprecated, use URL.Path or URL.Opaque instead. 1248 //r, err := b.Build(resolver.Target{Endpoint: a.target}, cc, resolver.BuildOptions{DisableServiceConfig: a.disableServiceConfig}) 1249 r, err := b.Build(resolver.Target{URL: url.URL{Path: a.target}}, cc, resolver.BuildOptions{DisableServiceConfig: a.disableServiceConfig}) 1250 if err != nil { 1251 t.Fatalf("%v\n", err) 1252 } 1253 defer r.Close() 1254 var cnt int 1255 var state resolver.State 1256 for i := 0; i < 2000; i++ { 1257 state, cnt = cc.getState() 1258 if cnt > 0 { 1259 break 1260 } 1261 time.Sleep(time.Millisecond) 1262 } 1263 if cnt == 0 { 1264 t.Fatalf("UpdateState not called after 2s; aborting") 1265 } 1266 sc := scFromState(state) 1267 if a.scWant != sc { 1268 t.Errorf("Resolved service config of target: %q = %+v, want %+v", a.target, sc, a.scWant) 1269 } 1270 } 1271 } 1272 1273 //goland:noinspection GoDeferInLoop 1274 func TestTXTError(t *testing.T) { 1275 defer leakcheck.Check(t) 1276 defer func(nt func(d time.Duration) *time.Timer) { 1277 newTimer = nt 1278 }(newTimer) 1279 newTimer = func(d time.Duration) *time.Timer { 1280 // Will never fire on its own, will protect from triggering exponential backoff. 1281 return time.NewTimer(time.Hour) 1282 } 1283 defer func(v bool) { envconfig.TXTErrIgnore = v }(envconfig.TXTErrIgnore) 1284 for _, ignore := range []bool{false, true} { 1285 envconfig.TXTErrIgnore = ignore 1286 b := NewBuilder() 1287 cc := &testClientConn{target: "ipv4.single.fake"} // has A records but not TXT records. 1288 // Endpoint is deprecated, use URL.Path or URL.Opaque instead. 1289 //r, err := b.Build(resolver.Target{Endpoint: "ipv4.single.fake"}, cc, resolver.BuildOptions{}) 1290 r, err := b.Build(resolver.Target{URL: url.URL{Path: "ipv4.single.fake"}}, cc, resolver.BuildOptions{}) 1291 if err != nil { 1292 t.Fatalf("%v\n", err) 1293 } 1294 defer r.Close() 1295 var cnt int 1296 var state resolver.State 1297 for i := 0; i < 2000; i++ { 1298 state, cnt = cc.getState() 1299 if cnt > 0 { 1300 break 1301 } 1302 time.Sleep(time.Millisecond) 1303 } 1304 if cnt == 0 { 1305 t.Fatalf("UpdateState not called after 2s; aborting") 1306 } 1307 if !ignore && (state.ServiceConfig == nil || state.ServiceConfig.Err == nil) { 1308 t.Errorf("state.ServiceConfig = %v; want non-nil error", state.ServiceConfig) 1309 } else if ignore && state.ServiceConfig != nil { 1310 t.Errorf("state.ServiceConfig = %v; want nil", state.ServiceConfig) 1311 } 1312 } 1313 } 1314 1315 func TestDNSResolverRetry(t *testing.T) { 1316 defer func(nt func(d time.Duration) *time.Timer) { 1317 newTimer = nt 1318 }(newTimer) 1319 newTimer = func(d time.Duration) *time.Timer { 1320 // Will never fire on its own, will protect from triggering exponential backoff. 1321 return time.NewTimer(time.Hour) 1322 } 1323 b := NewBuilder() 1324 target := "ipv4.single.fake" 1325 cc := &testClientConn{target: target} 1326 // Endpoint is deprecated, use URL.Path or URL.Opaque instead. 1327 //r, err := b.Build(resolver.Target{Endpoint: target}, cc, resolver.BuildOptions{}) 1328 r, err := b.Build(resolver.Target{URL: url.URL{Path: target}}, cc, resolver.BuildOptions{}) 1329 if err != nil { 1330 t.Fatalf("%v\n", err) 1331 } 1332 defer r.Close() 1333 var state resolver.State 1334 for i := 0; i < 2000; i++ { 1335 state, _ = cc.getState() 1336 if len(state.Addresses) == 1 { 1337 break 1338 } 1339 time.Sleep(time.Millisecond) 1340 } 1341 if len(state.Addresses) != 1 { 1342 t.Fatalf("UpdateState not called with 1 address after 2s; aborting. state=%v", state) 1343 } 1344 want := []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}} 1345 if !reflect.DeepEqual(want, state.Addresses) { 1346 t.Errorf("Resolved addresses of target: %q = %+v, want %+v", target, state.Addresses, want) 1347 } 1348 // mutate the host lookup table so the target has 0 address returned. 1349 revertTbl := mutateTbl(target) 1350 // trigger a resolve that will get empty address list 1351 r.ResolveNow(resolver.ResolveNowOptions{}) 1352 for i := 0; i < 2000; i++ { 1353 state, _ = cc.getState() 1354 if len(state.Addresses) == 0 { 1355 break 1356 } 1357 time.Sleep(time.Millisecond) 1358 } 1359 if len(state.Addresses) != 0 { 1360 t.Fatalf("UpdateState not called with 0 address after 2s; aborting. state=%v", state) 1361 } 1362 revertTbl() 1363 // wait for the retry to happen in two seconds. 1364 r.ResolveNow(resolver.ResolveNowOptions{}) 1365 for i := 0; i < 2000; i++ { 1366 state, _ = cc.getState() 1367 if len(state.Addresses) == 1 { 1368 break 1369 } 1370 time.Sleep(time.Millisecond) 1371 } 1372 if !reflect.DeepEqual(want, state.Addresses) { 1373 t.Errorf("Resolved addresses of target: %q = %+v, want %+v", target, state.Addresses, want) 1374 } 1375 } 1376 1377 func TestCustomAuthority(t *testing.T) { 1378 defer leakcheck.Check(t) 1379 defer func(nt func(d time.Duration) *time.Timer) { 1380 newTimer = nt 1381 }(newTimer) 1382 newTimer = func(d time.Duration) *time.Timer { 1383 // Will never fire on its own, will protect from triggering exponential backoff. 1384 return time.NewTimer(time.Hour) 1385 } 1386 1387 tests := []struct { 1388 authority string 1389 authorityWant string 1390 expectError bool 1391 }{ 1392 { 1393 "4.3.2.1:" + defaultDNSSvrPort, 1394 "4.3.2.1:" + defaultDNSSvrPort, 1395 false, 1396 }, 1397 { 1398 "4.3.2.1:123", 1399 "4.3.2.1:123", 1400 false, 1401 }, 1402 { 1403 "4.3.2.1", 1404 "4.3.2.1:" + defaultDNSSvrPort, 1405 false, 1406 }, 1407 { 1408 "::1", 1409 "[::1]:" + defaultDNSSvrPort, 1410 false, 1411 }, 1412 { 1413 "[::1]", 1414 "[::1]:" + defaultDNSSvrPort, 1415 false, 1416 }, 1417 { 1418 "[::1]:123", 1419 "[::1]:123", 1420 false, 1421 }, 1422 { 1423 "dnsserver.com", 1424 "dnsserver.com:" + defaultDNSSvrPort, 1425 false, 1426 }, 1427 { 1428 ":123", 1429 "localhost:123", 1430 false, 1431 }, 1432 { 1433 ":", 1434 "", 1435 true, 1436 }, 1437 { 1438 "[::1]:", 1439 "", 1440 true, 1441 }, 1442 { 1443 "dnsserver.com:", 1444 "", 1445 true, 1446 }, 1447 } 1448 oldCustomAuthorityDialler := customAuthorityDialler 1449 defer func() { 1450 customAuthorityDialler = oldCustomAuthorityDialler 1451 }() 1452 1453 for _, a := range tests { 1454 errChan := make(chan error, 1) 1455 customAuthorityDialler = func(authority string) func(ctx context.Context, network, address string) (net.Conn, error) { 1456 if authority != a.authorityWant { 1457 errChan <- fmt.Errorf("wrong custom authority passed to resolver. input: %s expected: %s actual: %s", a.authority, a.authorityWant, authority) 1458 } else { 1459 errChan <- nil 1460 } 1461 return func(ctx context.Context, network, address string) (net.Conn, error) { 1462 return nil, errors.New("no need to dial") 1463 } 1464 } 1465 1466 b := NewBuilder() 1467 cc := &testClientConn{target: "foo.bar.com", errChan: make(chan error, 1)} 1468 // Endpoint is deprecated, use URL.Path or URL.Opaque instead. 1469 //r, err := b.Build(resolver.Target{Endpoint: "foo.bar.com", Authority: a.authority}, cc, resolver.BuildOptions{}) 1470 r, err := b.Build(resolver.Target{URL: url.URL{Path: "/foo.bar.com", Host: a.authority}}, cc, resolver.BuildOptions{}) 1471 if err == nil { 1472 r.Close() 1473 1474 err = <-errChan 1475 if err != nil { 1476 t.Errorf(err.Error()) 1477 } 1478 1479 if a.expectError { 1480 t.Errorf("custom authority should have caused an error: %s", a.authority) 1481 } 1482 } else if !a.expectError { 1483 t.Errorf("unexpected error using custom authority %s: %s", a.authority, err) 1484 } 1485 } 1486 } 1487 1488 // TestRateLimitedResolve exercises the rate limit enforced on re-resolution 1489 // requests. It sets the re-resolution rate to a small value and repeatedly 1490 // calls ResolveNow() and ensures only the expected number of resolution 1491 // requests are made. 1492 1493 func TestRateLimitedResolve(t *testing.T) { 1494 defer leakcheck.Check(t) 1495 defer func(nt func(d time.Duration) *time.Timer) { 1496 newTimer = nt 1497 }(newTimer) 1498 newTimer = func(d time.Duration) *time.Timer { 1499 // Will never fire on its own, will protect from triggering exponential 1500 // backoff. 1501 return time.NewTimer(time.Hour) 1502 } 1503 defer func(nt func(d time.Duration) *time.Timer) { 1504 newTimerDNSResRate = nt 1505 }(newTimerDNSResRate) 1506 1507 timerChan := testutils.NewChannel() 1508 newTimerDNSResRate = func(d time.Duration) *time.Timer { 1509 // Will never fire on its own, allows this test to call timer 1510 // immediately. 1511 t := time.NewTimer(time.Hour) 1512 timerChan.Send(t) 1513 return t 1514 } 1515 1516 // Create a new testResolver{} for this test because we want the exact count 1517 // of the number of times the resolver was invoked. 1518 nc := overrideDefaultResolver(true) 1519 defer nc() 1520 1521 target := "foo.bar.com" 1522 b := NewBuilder() 1523 cc := &testClientConn{target: target} 1524 1525 // Endpoint is deprecated, use URL.Path or URL.Opaque instead. 1526 //r, err := b.Build(resolver.Target{Endpoint: target}, cc, resolver.BuildOptions{}) 1527 r, err := b.Build(resolver.Target{URL: url.URL{Path: target}}, cc, resolver.BuildOptions{}) 1528 if err != nil { 1529 t.Fatalf("resolver.Build() returned error: %v\n", err) 1530 } 1531 defer r.Close() 1532 1533 dnsR, ok := r.(*dnsResolver) 1534 if !ok { 1535 t.Fatalf("resolver.Build() returned unexpected type: %T\n", dnsR) 1536 } 1537 1538 tr, ok := dnsR.resolver.(*testResolver) 1539 if !ok { 1540 t.Fatalf("delegate resolver returned unexpected type: %T\n", tr) 1541 } 1542 1543 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 1544 defer cancel() 1545 1546 // Wait for the first resolution request to be done. This happens as part 1547 // of the first iteration of the for loop in watcher(). 1548 if _, err := tr.lookupHostCh.Receive(ctx); err != nil { 1549 t.Fatalf("Timed out waiting for lookup() call.") 1550 } 1551 1552 // Call Resolve Now 100 times, shouldn't continue onto next iteration of 1553 // watcher, thus shouldn't lookup again. 1554 for i := 0; i <= 100; i++ { 1555 r.ResolveNow(resolver.ResolveNowOptions{}) 1556 } 1557 1558 continueCtx, continueCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 1559 defer continueCancel() 1560 1561 if _, err := tr.lookupHostCh.Receive(continueCtx); err == nil { 1562 t.Fatalf("Should not have looked up again as DNS Min Res Rate timer has not gone off.") 1563 } 1564 1565 // Make the DNSMinResRate timer fire immediately (by receiving it, then 1566 // resetting to 0), this will unblock the resolver which is currently 1567 // blocked on the DNS Min Res Rate timer going off, which will allow it to 1568 // continue to the next iteration of the watcher loop. 1569 timer, err := timerChan.Receive(ctx) 1570 if err != nil { 1571 t.Fatalf("Error receiving timer from mock NewTimer call: %v", err) 1572 } 1573 timerPointer := timer.(*time.Timer) 1574 timerPointer.Reset(0) 1575 1576 // Now that DNS Min Res Rate timer has gone off, it should lookup again. 1577 if _, err := tr.lookupHostCh.Receive(ctx); err != nil { 1578 t.Fatalf("Timed out waiting for lookup() call.") 1579 } 1580 1581 // Resolve Now 1000 more times, shouldn't lookup again as DNS Min Res Rate 1582 // timer has not gone off. 1583 for i := 0; i < 1000; i++ { 1584 r.ResolveNow(resolver.ResolveNowOptions{}) 1585 } 1586 1587 if _, err = tr.lookupHostCh.Receive(continueCtx); err == nil { 1588 t.Fatalf("Should not have looked up again as DNS Min Res Rate timer has not gone off.") 1589 } 1590 1591 // Make the DNSMinResRate timer fire immediately again. 1592 timer, err = timerChan.Receive(ctx) 1593 if err != nil { 1594 t.Fatalf("Error receiving timer from mock NewTimer call: %v", err) 1595 } 1596 timerPointer = timer.(*time.Timer) 1597 timerPointer.Reset(0) 1598 1599 // Now that DNS Min Res Rate timer has gone off, it should lookup again. 1600 if _, err = tr.lookupHostCh.Receive(ctx); err != nil { 1601 t.Fatalf("Timed out waiting for lookup() call.") 1602 } 1603 1604 wantAddrs := []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}, {Addr: "5.6.7.8" + colonDefaultPort}} 1605 var state resolver.State 1606 for { 1607 var cnt int 1608 state, cnt = cc.getState() 1609 if cnt > 0 { 1610 break 1611 } 1612 time.Sleep(time.Millisecond) 1613 } 1614 if !reflect.DeepEqual(state.Addresses, wantAddrs) { 1615 t.Errorf("Resolved addresses of target: %q = %+v, want %+v", target, state.Addresses, wantAddrs) 1616 } 1617 } 1618 1619 // DNS Resolver immediately starts polling on an error. This will cause the re-resolution to return another error. 1620 // Thus, test that it constantly sends errors to the grpc.ClientConn. 1621 func TestReportError(t *testing.T) { 1622 const target = "notfoundaddress" 1623 defer func(nt func(d time.Duration) *time.Timer) { 1624 newTimer = nt 1625 }(newTimer) 1626 timerChan := testutils.NewChannel() 1627 newTimer = func(d time.Duration) *time.Timer { 1628 // Will never fire on its own, allows this test to call timer immediately. 1629 t := time.NewTimer(time.Hour) 1630 timerChan.Send(t) 1631 return t 1632 } 1633 cc := &testClientConn{target: target, errChan: make(chan error)} 1634 totalTimesCalledError := 0 1635 b := NewBuilder() 1636 // Endpoint is deprecated, use URL.Path or URL.Opaque instead. 1637 //r, err := b.Build(resolver.Target{Endpoint: target}, cc, resolver.BuildOptions{}) 1638 r, err := b.Build(resolver.Target{URL: url.URL{Path: target}}, cc, resolver.BuildOptions{}) 1639 if err != nil { 1640 t.Fatalf("Error building resolver for target %v: %v", target, err) 1641 } 1642 // Should receive first error. 1643 err = <-cc.errChan 1644 if !strings.Contains(err.Error(), "hostLookup error") { 1645 t.Fatalf(`ReportError(err=%v) called; want err contains "hostLookupError"`, err) 1646 } 1647 totalTimesCalledError++ 1648 ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout) 1649 defer ctxCancel() 1650 timer, err := timerChan.Receive(ctx) 1651 if err != nil { 1652 t.Fatalf("Error receiving timer from mock NewTimer call: %v", err) 1653 } 1654 timerPointer := timer.(*time.Timer) 1655 timerPointer.Reset(0) 1656 defer r.Close() 1657 1658 // Cause timer to go off 10 times, and see if it matches DNS Resolver updating Error. 1659 for i := 0; i < 10; i++ { 1660 // Should call ReportError(). 1661 err = <-cc.errChan 1662 if !strings.Contains(err.Error(), "hostLookup error") { 1663 t.Fatalf(`ReportError(err=%v) called; want err contains "hostLookupError"`, err) 1664 } 1665 totalTimesCalledError++ 1666 timer, err := timerChan.Receive(ctx) 1667 if err != nil { 1668 t.Fatalf("Error receiving timer from mock NewTimer call: %v", err) 1669 } 1670 timerPointer := timer.(*time.Timer) 1671 timerPointer.Reset(0) 1672 } 1673 1674 if totalTimesCalledError != 11 { 1675 t.Errorf("ReportError() not called 11 times, instead called %d times.", totalTimesCalledError) 1676 } 1677 // Clean up final watcher iteration. 1678 <-cc.errChan 1679 _, err = timerChan.Receive(ctx) 1680 if err != nil { 1681 t.Fatalf("Error receiving timer from mock NewTimer call: %v", err) 1682 } 1683 }