google.golang.org/grpc@v1.72.2/internal/resolver/delegatingresolver/delegatingresolver_ext_test.go (about) 1 /* 2 * 3 * Copyright 2024 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 delegatingresolver_test 20 21 import ( 22 "context" 23 "errors" 24 "net/http" 25 "net/url" 26 "testing" 27 "time" 28 29 "github.com/google/go-cmp/cmp" 30 "google.golang.org/grpc/internal/grpctest" 31 "google.golang.org/grpc/internal/proxyattributes" 32 "google.golang.org/grpc/internal/resolver/delegatingresolver" 33 "google.golang.org/grpc/internal/testutils" 34 "google.golang.org/grpc/internal/transport/networktype" 35 "google.golang.org/grpc/resolver" 36 "google.golang.org/grpc/resolver/manual" 37 "google.golang.org/grpc/serviceconfig" 38 39 _ "google.golang.org/grpc/resolver/dns" // To register dns resolver. 40 ) 41 42 type s struct { 43 grpctest.Tester 44 } 45 46 func Test(t *testing.T) { 47 grpctest.RunSubTests(t, s{}) 48 } 49 50 const ( 51 defaultTestTimeout = 10 * time.Second 52 defaultTestShortTimeout = 10 * time.Millisecond 53 ) 54 55 // createTestResolverClientConn initializes a [testutils.ResolverClientConn] and 56 // returns it along with channels for resolver state updates and errors. 57 func createTestResolverClientConn(t *testing.T) (*testutils.ResolverClientConn, chan resolver.State, chan error) { 58 t.Helper() 59 stateCh := make(chan resolver.State, 1) 60 errCh := make(chan error, 1) 61 62 tcc := &testutils.ResolverClientConn{ 63 Logger: t, 64 UpdateStateF: func(s resolver.State) error { stateCh <- s; return nil }, 65 ReportErrorF: func(err error) { errCh <- err }, 66 } 67 return tcc, stateCh, errCh 68 } 69 70 // Tests the scenario where no proxy environment variables are set or proxying 71 // is disabled by the `NO_PROXY` environment variable. The test verifies that 72 // the delegating resolver creates only a target resolver and that the 73 // addresses returned by the delegating resolver exactly match those returned 74 // by the target resolver. 75 func (s) TestDelegatingResolverNoProxyEnvVarsSet(t *testing.T) { 76 hpfe := func(req *http.Request) (*url.URL, error) { return nil, nil } 77 originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment 78 delegatingresolver.HTTPSProxyFromEnvironment = hpfe 79 defer func() { 80 delegatingresolver.HTTPSProxyFromEnvironment = originalhpfe 81 }() 82 83 const ( 84 targetTestAddr = "test.com" 85 resolvedTargetTestAddr1 = "1.1.1.1:8080" 86 resolvedTargetTestAddr2 = "2.2.2.2:8080" 87 ) 88 89 // Set up a manual resolver to control the address resolution. 90 targetResolver := manual.NewBuilderWithScheme("test") 91 target := targetResolver.Scheme() + ":///" + targetTestAddr 92 93 // Create a delegating resolver with no proxy configuration 94 tcc, stateCh, _ := createTestResolverClientConn(t) 95 if _, err := delegatingresolver.New(resolver.Target{URL: *testutils.MustParseURL(target)}, tcc, resolver.BuildOptions{}, targetResolver, false); err != nil { 96 t.Fatalf("Failed to create delegating resolver: %v", err) 97 } 98 99 // Update the manual resolver with a test address. 100 targetResolver.UpdateState(resolver.State{ 101 Addresses: []resolver.Address{ 102 {Addr: resolvedTargetTestAddr1}, 103 {Addr: resolvedTargetTestAddr2}, 104 }, 105 ServiceConfig: &serviceconfig.ParseResult{}, 106 }) 107 108 // Verify that the delegating resolver outputs the same addresses, as returned 109 // by the target resolver. 110 wantState := resolver.State{ 111 Addresses: []resolver.Address{ 112 {Addr: resolvedTargetTestAddr1}, 113 {Addr: resolvedTargetTestAddr2}, 114 }, 115 ServiceConfig: &serviceconfig.ParseResult{}, 116 } 117 118 var gotState resolver.State 119 select { 120 case gotState = <-stateCh: 121 case <-time.After(defaultTestTimeout): 122 t.Fatal("Timeout when waiting for a state update from the delegating resolver") 123 } 124 125 if diff := cmp.Diff(gotState, wantState); diff != "" { 126 t.Fatalf("Unexpected state from delegating resolver. Diff (-got +want):\n%v", diff) 127 } 128 } 129 130 // setupDNS registers a new manual resolver for the DNS scheme, effectively 131 // overwriting the previously registered DNS resolver. This allows the test to 132 // mock the DNS resolution for the proxy resolver. It also registers the 133 // original DNS resolver after the test is done. 134 func setupDNS(t *testing.T) (*manual.Resolver, chan struct{}) { 135 t.Helper() 136 mr := manual.NewBuilderWithScheme("dns") 137 138 dnsResolverBuilder := resolver.Get("dns") 139 resolver.Register(mr) 140 141 resolverBuilt := make(chan struct{}) 142 mr.BuildCallback = func(resolver.Target, resolver.ClientConn, resolver.BuildOptions) { 143 close(resolverBuilt) 144 } 145 146 t.Cleanup(func() { resolver.Register(dnsResolverBuilder) }) 147 return mr, resolverBuilt 148 } 149 150 func mustBuildResolver(ctx context.Context, t *testing.T, buildCh chan struct{}) { 151 t.Helper() 152 select { 153 case <-buildCh: 154 case <-ctx.Done(): 155 t.Fatalf("Context timed out waiting for resolver to be built.") 156 } 157 } 158 159 // proxyAddressWithTargetAttribute creates a resolver.Address for the proxy, 160 // adding the target address as an attribute. 161 func proxyAddressWithTargetAttribute(proxyAddr string, targetAddr string) resolver.Address { 162 addr := resolver.Address{Addr: proxyAddr} 163 addr = proxyattributes.Set(addr, proxyattributes.Options{ConnectAddr: targetAddr}) 164 return addr 165 } 166 167 func overrideTestHTTPSProxy(t *testing.T, proxyAddr string) { 168 t.Helper() 169 hpfe := func(req *http.Request) (*url.URL, error) { 170 return &url.URL{ 171 Scheme: "https", 172 Host: proxyAddr, 173 }, nil 174 } 175 originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment 176 delegatingresolver.HTTPSProxyFromEnvironment = hpfe 177 t.Cleanup(func() { delegatingresolver.HTTPSProxyFromEnvironment = originalhpfe }) 178 } 179 180 // Tests the scenario where proxy is configured and the target URI contains the 181 // "dns" scheme and target resolution is enabled. The test verifies that the 182 // addresses returned by the delegating resolver combines the addresses 183 // returned by the proxy resolver and the target resolver. 184 func (s) TestDelegatingResolverwithDNSAndProxyWithTargetResolution(t *testing.T) { 185 const ( 186 targetTestAddr = "test.com" 187 resolvedTargetTestAddr1 = "1.1.1.1:8080" 188 resolvedTargetTestAddr2 = "2.2.2.2:8080" 189 envProxyAddr = "proxytest.com" 190 resolvedProxyTestAddr1 = "11.11.11.11:7687" 191 ) 192 overrideTestHTTPSProxy(t, envProxyAddr) 193 194 // Manual resolver to control the target resolution. 195 targetResolver := manual.NewBuilderWithScheme("dns") 196 target := targetResolver.Scheme() + ":///" + targetTestAddr 197 // Set up a manual DNS resolver to control the proxy address resolution. 198 proxyResolver, proxyResolverBuilt := setupDNS(t) 199 200 tcc, stateCh, _ := createTestResolverClientConn(t) 201 if _, err := delegatingresolver.New(resolver.Target{URL: *testutils.MustParseURL(target)}, tcc, resolver.BuildOptions{}, targetResolver, true); err != nil { 202 t.Fatalf("Failed to create delegating resolver: %v", err) 203 } 204 205 targetResolver.UpdateState(resolver.State{ 206 Addresses: []resolver.Address{ 207 {Addr: resolvedTargetTestAddr1}, 208 {Addr: resolvedTargetTestAddr2}, 209 }, 210 ServiceConfig: &serviceconfig.ParseResult{}, 211 }) 212 213 select { 214 case <-stateCh: 215 t.Fatalf("Delegating resolver invoked UpdateState before both the proxy and target resolvers had updated their states.") 216 case <-time.After(defaultTestShortTimeout): 217 } 218 219 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 220 defer cancel() 221 222 // Wait for the proxy resolver to be built before calling UpdateState. 223 mustBuildResolver(ctx, t, proxyResolverBuilt) 224 proxyResolver.UpdateState(resolver.State{ 225 Addresses: []resolver.Address{{Addr: resolvedProxyTestAddr1}}, 226 ServiceConfig: &serviceconfig.ParseResult{}, 227 }) 228 229 // Verify that the delegating resolver outputs the expected address. 230 wantState := resolver.State{ 231 Addresses: []resolver.Address{ 232 proxyAddressWithTargetAttribute(resolvedProxyTestAddr1, resolvedTargetTestAddr1), 233 proxyAddressWithTargetAttribute(resolvedProxyTestAddr1, resolvedTargetTestAddr2), 234 }, 235 ServiceConfig: &serviceconfig.ParseResult{}, 236 } 237 var gotState resolver.State 238 select { 239 case gotState = <-stateCh: 240 case <-ctx.Done(): 241 t.Fatal("Context timeed out when waiting for a state update from the delegating resolver") 242 } 243 244 if diff := cmp.Diff(gotState, wantState); diff != "" { 245 t.Fatalf("Unexpected state from delegating resolver. Diff (-got +want):\n%v", diff) 246 } 247 } 248 249 // Tests the scenario where a proxy is configured, the target URI contains the 250 // "dns" scheme, and target resolution is disabled(default behavior). The test 251 // verifies that the addresses returned by the delegating resolver include the 252 // proxy resolver's addresses, with the unresolved target URI as an attribute 253 // of the proxy address. 254 func (s) TestDelegatingResolverwithDNSAndProxyWithNoTargetResolution(t *testing.T) { 255 const ( 256 targetTestAddr = "test.com" 257 envProxyAddr = "proxytest.com" 258 resolvedProxyTestAddr1 = "11.11.11.11:7687" 259 ) 260 overrideTestHTTPSProxy(t, envProxyAddr) 261 262 targetResolver := manual.NewBuilderWithScheme("dns") 263 target := targetResolver.Scheme() + ":///" + targetTestAddr 264 // Set up a manual DNS resolver to control the proxy address resolution. 265 proxyResolver, proxyResolverBuilt := setupDNS(t) 266 267 tcc, stateCh, _ := createTestResolverClientConn(t) 268 if _, err := delegatingresolver.New(resolver.Target{URL: *testutils.MustParseURL(target)}, tcc, resolver.BuildOptions{}, targetResolver, false); err != nil { 269 t.Fatalf("Failed to create delegating resolver: %v", err) 270 } 271 272 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 273 defer cancel() 274 275 // Wait for the proxy resolver to be built before calling UpdateState. 276 mustBuildResolver(ctx, t, proxyResolverBuilt) 277 proxyResolver.UpdateState(resolver.State{ 278 Addresses: []resolver.Address{ 279 {Addr: resolvedProxyTestAddr1}, 280 }, 281 }) 282 283 wantState := resolver.State{ 284 Addresses: []resolver.Address{proxyAddressWithTargetAttribute(resolvedProxyTestAddr1, targetTestAddr)}, 285 Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{proxyAddressWithTargetAttribute(resolvedProxyTestAddr1, targetTestAddr)}}}, 286 } 287 288 var gotState resolver.State 289 select { 290 case gotState = <-stateCh: 291 case <-ctx.Done(): 292 t.Fatal("Context timed out when waiting for a state update from the delegating resolver") 293 } 294 295 if diff := cmp.Diff(gotState, wantState); diff != "" { 296 t.Fatalf("Unexpected state from delegating resolver. Diff (-got +want):\n%v", diff) 297 } 298 } 299 300 // Tests the scenario where a proxy is configured, and the target URI scheme is 301 // not "dns". The test verifies that the addresses returned by the delegating 302 // resolver include the resolved proxy address and the custom resolved target 303 // address as attributes of the proxy address. 304 func (s) TestDelegatingResolverwithCustomResolverAndProxy(t *testing.T) { 305 const ( 306 targetTestAddr = "test.com" 307 resolvedTargetTestAddr1 = "1.1.1.1:8080" 308 resolvedTargetTestAddr2 = "2.2.2.2:8080" 309 envProxyAddr = "proxytest.com" 310 resolvedProxyTestAddr1 = "11.11.11.11:7687" 311 ) 312 overrideTestHTTPSProxy(t, envProxyAddr) 313 314 // Manual resolver to control the target resolution. 315 targetResolver := manual.NewBuilderWithScheme("test") 316 target := targetResolver.Scheme() + ":///" + targetTestAddr 317 // Set up a manual DNS resolver to control the proxy address resolution. 318 proxyResolver, proxyResolverBuilt := setupDNS(t) 319 320 tcc, stateCh, _ := createTestResolverClientConn(t) 321 if _, err := delegatingresolver.New(resolver.Target{URL: *testutils.MustParseURL(target)}, tcc, resolver.BuildOptions{}, targetResolver, false); err != nil { 322 t.Fatalf("Failed to create delegating resolver: %v", err) 323 } 324 325 targetResolver.UpdateState(resolver.State{ 326 Addresses: []resolver.Address{ 327 {Addr: resolvedTargetTestAddr1}, 328 {Addr: resolvedTargetTestAddr2}, 329 }, 330 ServiceConfig: &serviceconfig.ParseResult{}, 331 }) 332 333 select { 334 case <-stateCh: 335 t.Fatalf("Delegating resolver invoked UpdateState before both the proxy and target resolvers had updated their states.") 336 case <-time.After(defaultTestShortTimeout): 337 } 338 339 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 340 defer cancel() 341 342 // Wait for the proxy resolver to be built before calling UpdateState. 343 mustBuildResolver(ctx, t, proxyResolverBuilt) 344 proxyResolver.UpdateState(resolver.State{ 345 Addresses: []resolver.Address{{Addr: resolvedProxyTestAddr1}}, 346 ServiceConfig: &serviceconfig.ParseResult{}, 347 }) 348 349 wantState := resolver.State{ 350 Addresses: []resolver.Address{ 351 proxyAddressWithTargetAttribute(resolvedProxyTestAddr1, resolvedTargetTestAddr1), 352 proxyAddressWithTargetAttribute(resolvedProxyTestAddr1, resolvedTargetTestAddr2), 353 }, 354 ServiceConfig: &serviceconfig.ParseResult{}, 355 } 356 var gotState resolver.State 357 select { 358 case gotState = <-stateCh: 359 case <-ctx.Done(): 360 t.Fatal("Context timed out when waiting for a state update from the delegating resolver") 361 } 362 363 if diff := cmp.Diff(gotState, wantState); diff != "" { 364 t.Fatalf("Unexpected state from delegating resolver. Diff (-got +want):\n%v", diff) 365 } 366 } 367 368 // Tests the scenario where a proxy is configured, the target URI scheme is not 369 // "dns," and both the proxy and target resolvers return endpoints. The test 370 // verifies that the delegating resolver combines resolved proxy and target 371 // addresses correctly, returning endpoints with the proxy address populated 372 // and the target address included as an attribute of the proxy address for 373 // each combination of proxy and target endpoints. 374 func (s) TestDelegatingResolverForEndpointsWithProxy(t *testing.T) { 375 const ( 376 targetTestAddr = "test.com" 377 resolvedTargetTestAddr1 = "1.1.1.1:8080" 378 resolvedTargetTestAddr2 = "2.2.2.2:8080" 379 resolvedTargetTestAddr3 = "3.3.3.3:8080" 380 resolvedTargetTestAddr4 = "4.4.4.4:8080" 381 envProxyAddr = "proxytest.com" 382 resolvedProxyTestAddr1 = "11.11.11.11:7687" 383 resolvedProxyTestAddr2 = "22.22.22.22:7687" 384 ) 385 overrideTestHTTPSProxy(t, envProxyAddr) 386 387 // Manual resolver to control the target resolution. 388 targetResolver := manual.NewBuilderWithScheme("test") 389 target := targetResolver.Scheme() + ":///" + targetTestAddr 390 // Set up a manual DNS resolver to control the proxy address resolution. 391 proxyResolver, proxyResolverBuilt := setupDNS(t) 392 393 tcc, stateCh, _ := createTestResolverClientConn(t) 394 if _, err := delegatingresolver.New(resolver.Target{URL: *testutils.MustParseURL(target)}, tcc, resolver.BuildOptions{}, targetResolver, false); err != nil { 395 t.Fatalf("Failed to create delegating resolver: %v", err) 396 } 397 398 targetResolver.UpdateState(resolver.State{ 399 Endpoints: []resolver.Endpoint{ 400 { 401 Addresses: []resolver.Address{ 402 {Addr: resolvedTargetTestAddr1}, 403 {Addr: resolvedTargetTestAddr2}}, 404 }, 405 { 406 Addresses: []resolver.Address{ 407 {Addr: resolvedTargetTestAddr3}, 408 {Addr: resolvedTargetTestAddr4}}, 409 }, 410 }, 411 ServiceConfig: &serviceconfig.ParseResult{}, 412 }) 413 select { 414 case <-stateCh: 415 t.Fatalf("Delegating resolver invoked UpdateState before both the proxy and target resolvers had updated their states.") 416 case <-time.After(defaultTestShortTimeout): 417 } 418 419 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 420 defer cancel() 421 422 // Wait for the proxy resolver to be built before calling UpdateState. 423 mustBuildResolver(ctx, t, proxyResolverBuilt) 424 proxyResolver.UpdateState(resolver.State{ 425 Endpoints: []resolver.Endpoint{ 426 {Addresses: []resolver.Address{{Addr: resolvedProxyTestAddr1}}}, 427 {Addresses: []resolver.Address{{Addr: resolvedProxyTestAddr2}}}, 428 }, 429 ServiceConfig: &serviceconfig.ParseResult{}, 430 }) 431 wantState := resolver.State{ 432 Endpoints: []resolver.Endpoint{ 433 { 434 Addresses: []resolver.Address{ 435 proxyAddressWithTargetAttribute(resolvedProxyTestAddr1, resolvedTargetTestAddr1), 436 proxyAddressWithTargetAttribute(resolvedProxyTestAddr2, resolvedTargetTestAddr1), 437 proxyAddressWithTargetAttribute(resolvedProxyTestAddr1, resolvedTargetTestAddr2), 438 proxyAddressWithTargetAttribute(resolvedProxyTestAddr2, resolvedTargetTestAddr2), 439 }, 440 }, 441 { 442 Addresses: []resolver.Address{ 443 proxyAddressWithTargetAttribute(resolvedProxyTestAddr1, resolvedTargetTestAddr3), 444 proxyAddressWithTargetAttribute(resolvedProxyTestAddr2, resolvedTargetTestAddr3), 445 proxyAddressWithTargetAttribute(resolvedProxyTestAddr1, resolvedTargetTestAddr4), 446 proxyAddressWithTargetAttribute(resolvedProxyTestAddr2, resolvedTargetTestAddr4), 447 }, 448 }, 449 }, 450 ServiceConfig: &serviceconfig.ParseResult{}, 451 } 452 var gotState resolver.State 453 select { 454 case gotState = <-stateCh: 455 case <-ctx.Done(): 456 t.Fatal("Contex timed out when waiting for a state update from the delegating resolver") 457 } 458 459 if diff := cmp.Diff(gotState, wantState); diff != "" { 460 t.Fatalf("Unexpected state from delegating resolver. Diff (-got +want):\n%v", diff) 461 } 462 } 463 464 // Tests the scenario where a proxy is configured, the target URI scheme is not 465 // "dns," and both the proxy and target resolvers return multiple addresses. 466 // The test verifies that the delegating resolver combines unresolved proxy 467 // host and target addresses correctly, returning addresses with the proxy host 468 // populated and the target address included as an attribute. 469 func (s) TestDelegatingResolverForMultipleProxyAddress(t *testing.T) { 470 const ( 471 targetTestAddr = "test.com" 472 resolvedTargetTestAddr1 = "1.1.1.1:8080" 473 resolvedTargetTestAddr2 = "2.2.2.2:8080" 474 envProxyAddr = "proxytest.com" 475 resolvedProxyTestAddr1 = "11.11.11.11:7687" 476 resolvedProxyTestAddr2 = "22.22.22.22:7687" 477 ) 478 overrideTestHTTPSProxy(t, envProxyAddr) 479 480 // Manual resolver to control the target resolution. 481 targetResolver := manual.NewBuilderWithScheme("test") 482 target := targetResolver.Scheme() + ":///" + targetTestAddr 483 // Set up a manual DNS resolver to control the proxy address resolution. 484 proxyResolver, proxyResolverBuilt := setupDNS(t) 485 tcc, stateCh, _ := createTestResolverClientConn(t) 486 if _, err := delegatingresolver.New(resolver.Target{URL: *testutils.MustParseURL(target)}, tcc, resolver.BuildOptions{}, targetResolver, false); err != nil { 487 t.Fatalf("Failed to create delegating resolver: %v", err) 488 } 489 490 targetResolver.UpdateState(resolver.State{ 491 Addresses: []resolver.Address{ 492 {Addr: resolvedTargetTestAddr1}, 493 {Addr: resolvedTargetTestAddr2}, 494 }, 495 ServiceConfig: &serviceconfig.ParseResult{}, 496 }) 497 498 select { 499 case <-stateCh: 500 t.Fatalf("Delegating resolver invoked UpdateState before both the proxy and target resolvers had updated their states.") 501 case <-time.After(defaultTestShortTimeout): 502 } 503 504 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 505 defer cancel() 506 507 // Wait for the proxy resolver to be built before calling UpdateState. 508 mustBuildResolver(ctx, t, proxyResolverBuilt) 509 proxyResolver.UpdateState(resolver.State{ 510 Addresses: []resolver.Address{ 511 {Addr: resolvedProxyTestAddr1}, 512 {Addr: resolvedProxyTestAddr2}, 513 }, 514 ServiceConfig: &serviceconfig.ParseResult{}, 515 }) 516 517 wantState := resolver.State{ 518 Addresses: []resolver.Address{ 519 proxyAddressWithTargetAttribute(envProxyAddr, resolvedTargetTestAddr1), 520 proxyAddressWithTargetAttribute(envProxyAddr, resolvedTargetTestAddr2), 521 }, 522 ServiceConfig: &serviceconfig.ParseResult{}, 523 } 524 var gotState resolver.State 525 select { 526 case gotState = <-stateCh: 527 case <-ctx.Done(): 528 t.Fatal("Context timed out when waiting for a state update from the delegating resolver") 529 } 530 531 if diff := cmp.Diff(gotState, wantState); diff != "" { 532 t.Fatalf("Unexpected state from delegating resolver. Diff (-got +want):\n%v", diff) 533 } 534 } 535 536 // Tests that delegatingresolver doesn't panic when the channel closes the 537 // resolver while it's handling an update from it's child. The test closes the 538 // delegating resolver, verifies the target resolver is closed and blocks the 539 // proxy resolver from being closed. The test sends an update from the proxy 540 // resolver and verifies that the target resolver's ResolveNow method is not 541 // called after the channels returns an error. 542 func (s) TestDelegatingResolverUpdateStateDuringClose(t *testing.T) { 543 const envProxyAddr = "proxytest.com" 544 545 overrideTestHTTPSProxy(t, envProxyAddr) 546 547 // Manual resolver to control the target resolution. 548 targetResolver := manual.NewBuilderWithScheme("test") 549 targetResolverCalled := make(chan struct{}) 550 targetResolver.ResolveNowCallback = func(resolver.ResolveNowOptions) { 551 close(targetResolverCalled) 552 } 553 targetResolverCloseCalled := make(chan struct{}) 554 targetResolver.CloseCallback = func() { 555 close(targetResolverCloseCalled) 556 t.Log("Target resolver is closed.") 557 } 558 559 target := targetResolver.Scheme() + ":///" + "ignored" 560 // Set up a manual DNS resolver to control the proxy address resolution. 561 proxyResolver, proxyResolverBuilt := setupDNS(t) 562 563 unblockProxyResolverClose := make(chan struct{}, 1) 564 proxyResolver.CloseCallback = func() { 565 <-unblockProxyResolverClose 566 t.Log("Proxy resolver is closed.") 567 } 568 569 tcc, _, _ := createTestResolverClientConn(t) 570 tcc.UpdateStateF = func(resolver.State) error { 571 return errors.New("test error") 572 } 573 dr, err := delegatingresolver.New(resolver.Target{URL: *testutils.MustParseURL(target)}, tcc, resolver.BuildOptions{}, targetResolver, false) 574 if err != nil { 575 t.Fatalf("Failed to create delegating resolver: %v", err) 576 } 577 578 targetResolver.UpdateState(resolver.State{ 579 Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: "1.1.1.1"}}}}, 580 }) 581 582 // Wait for the proxy resolver to be built before calling Close. 583 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 584 defer cancel() 585 mustBuildResolver(ctx, t, proxyResolverBuilt) 586 // Closing the delegating resolver will block until the test writes to the 587 // unblockProxyResolverClose channel. 588 go dr.Close() 589 select { 590 case <-targetResolverCloseCalled: 591 case <-ctx.Done(): 592 t.Fatalf("Context timed out waiting for target resolver's Close method to be called.") 593 } 594 595 // Updating the channel will result in an error being returned. Since the 596 // target resolver's Close method is already called, the delegating resolver 597 // must not call "ResolveNow" on it. 598 proxyUpdateCh := make(chan struct{}) 599 go func() { 600 proxyResolver.UpdateState(resolver.State{ 601 Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: "1.1.1.1"}}}}, 602 }) 603 close(proxyUpdateCh) 604 }() 605 unblockProxyResolverClose <- struct{}{} 606 607 select { 608 case <-targetResolverCalled: 609 t.Fatalf("targetResolver.ResolveNow() called unexpectedly.") 610 case <-time.After(defaultTestShortTimeout): 611 } 612 // Wait for the proxy update to complete before returning from the test and 613 // before the deferred reassignment of 614 // delegatingresolver.HTTPSProxyFromEnvironment. This ensures that we read 615 // from the function before it is reassigned, preventing a race condition. 616 select { 617 case <-proxyUpdateCh: 618 case <-ctx.Done(): 619 t.Fatalf("Context timed out waiting for proxyResolver.UpdateState() to be called.") 620 } 621 } 622 623 // Tests that calling cc.UpdateState in a blocking manner from a child resolver 624 // while handling a ResolveNow call doesn't result in a deadlock. The test uses 625 // a fake ClientConn that returns an error when calling cc.UpdateState. The test 626 // makes the proxy resolver update the resolver state. The test verifies that 627 // the delegating resolver calls ResolveNow on the target resolver when the 628 // ClientConn returns an error. 629 func (s) TestDelegatingResolverUpdateStateFromResolveNow(t *testing.T) { 630 const envProxyAddr = "proxytest.com" 631 632 overrideTestHTTPSProxy(t, envProxyAddr) 633 634 // Manual resolver to control the target resolution. 635 targetResolver := manual.NewBuilderWithScheme("test") 636 targetResolverCalled := make(chan struct{}) 637 targetResolver.ResolveNowCallback = func(resolver.ResolveNowOptions) { 638 // Updating the resolver state should not deadlock. 639 targetResolver.CC().UpdateState(resolver.State{ 640 Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: "1.1.1.1"}}}}, 641 }) 642 close(targetResolverCalled) 643 } 644 645 target := targetResolver.Scheme() + ":///" + "ignored" 646 // Set up a manual DNS resolver to control the proxy address resolution. 647 proxyResolver, proxyResolverBuilt := setupDNS(t) 648 649 tcc, _, _ := createTestResolverClientConn(t) 650 tcc.UpdateStateF = func(resolver.State) error { 651 return errors.New("test error") 652 } 653 _, err := delegatingresolver.New(resolver.Target{URL: *testutils.MustParseURL(target)}, tcc, resolver.BuildOptions{}, targetResolver, false) 654 if err != nil { 655 t.Fatalf("Failed to create delegating resolver: %v", err) 656 } 657 658 targetResolver.UpdateState(resolver.State{ 659 Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: "1.1.1.1"}}}}, 660 }) 661 662 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 663 defer cancel() 664 665 // Wait for the proxy resolver to be built before calling UpdateState. 666 mustBuildResolver(ctx, t, proxyResolverBuilt) 667 668 // Updating the channel will result in an error being returned. The 669 // delegating resolver should call call "ResolveNow" on the target resolver. 670 proxyResolver.UpdateState(resolver.State{ 671 Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: "1.1.1.1"}}}}, 672 }) 673 674 select { 675 case <-targetResolverCalled: 676 case <-ctx.Done(): 677 t.Fatalf("context timed out waiting for targetResolver.ResolveNow() to be called.") 678 } 679 } 680 681 // Tests that calling cc.UpdateState in a blocking manner from child resolvers 682 // doesn't result in deadlocks. 683 func (s) TestDelegatingResolverResolveNow(t *testing.T) { 684 const envProxyAddr = "proxytest.com" 685 686 overrideTestHTTPSProxy(t, envProxyAddr) 687 688 // Manual resolver to control the target resolution. 689 targetResolver := manual.NewBuilderWithScheme("test") 690 targetResolverCalled := make(chan struct{}, 1) 691 targetResolver.ResolveNowCallback = func(resolver.ResolveNowOptions) { 692 // Updating the resolver state should not deadlock. 693 targetResolver.CC().UpdateState(resolver.State{ 694 Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: "1.1.1.1"}}}}, 695 }) 696 targetResolverCalled <- struct{}{} 697 } 698 699 target := targetResolver.Scheme() + ":///" + "ignored" 700 // Set up a manual DNS resolver to control the proxy address resolution. 701 proxyResolver, proxyResolverBuilt := setupDNS(t) 702 703 proxyResolverCalled := make(chan struct{}) 704 proxyResolver.ResolveNowCallback = func(resolver.ResolveNowOptions) { 705 // Updating the resolver state should not deadlock. 706 proxyResolver.CC().UpdateState(resolver.State{ 707 Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: "1.1.1.1"}}}}, 708 }) 709 close(proxyResolverCalled) 710 } 711 712 tcc, _, _ := createTestResolverClientConn(t) 713 dr, err := delegatingresolver.New(resolver.Target{URL: *testutils.MustParseURL(target)}, tcc, resolver.BuildOptions{}, targetResolver, false) 714 if err != nil { 715 t.Fatalf("Failed to create delegating resolver: %v", err) 716 } 717 718 // ResolveNow of manual proxy resolver will not be called. Proxy resolver is 719 // only built when we get the first update from target resolver. Therefore 720 // in the first ResolveNow, proxy resolver will be a no-op resolver and only 721 // target resolver's ResolveNow will be called. 722 dr.ResolveNow(resolver.ResolveNowOptions{}) 723 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 724 defer cancel() 725 select { 726 case <-targetResolverCalled: 727 case <-ctx.Done(): 728 t.Fatalf("context timed out waiting for targetResolver.ResolveNow() to be called.") 729 } 730 731 mustBuildResolver(ctx, t, proxyResolverBuilt) 732 733 dr.ResolveNow(resolver.ResolveNowOptions{}) 734 735 select { 736 case <-targetResolverCalled: 737 case <-ctx.Done(): 738 t.Fatalf("context timed out waiting for targetResolver.ResolveNow() to be called.") 739 } 740 select { 741 case <-proxyResolverCalled: 742 case <-ctx.Done(): 743 t.Fatalf("context timed out waiting for proxyResolver.ResolveNow() to be called.") 744 } 745 } 746 747 // Tests the scenario where a proxy is configured, and the resolver returns a 748 // network type other than tcp for all addresses. The test verifies that the 749 // delegating resolver avoids the proxy build and directly sends the update 750 // from target resolver to clientconn. 751 func (s) TestDelegatingResolverForNonTCPTarget(t *testing.T) { 752 const ( 753 targetTestAddr = "test.target" 754 resolvedTargetTestAddr1 = "1.1.1.1:8080" 755 envProxyAddr = "proxytest.com" 756 ) 757 overrideTestHTTPSProxy(t, envProxyAddr) 758 759 // Manual resolver to control the target resolution. 760 targetResolver := manual.NewBuilderWithScheme("test") 761 target := targetResolver.Scheme() + ":///" + targetTestAddr 762 // Set up a manual DNS resolver to control the proxy address resolution. 763 _, proxyResolverBuilt := setupDNS(t) 764 765 tcc, stateCh, _ := createTestResolverClientConn(t) 766 if _, err := delegatingresolver.New(resolver.Target{URL: *testutils.MustParseURL(target)}, tcc, resolver.BuildOptions{}, targetResolver, false); err != nil { 767 t.Fatalf("Failed to create delegating resolver: %v", err) 768 } 769 770 // Set network to anything other than tcp. 771 nonTCPAddr := networktype.Set(resolver.Address{Addr: resolvedTargetTestAddr1}, "unix") 772 targetResolver.UpdateState(resolver.State{ 773 Addresses: []resolver.Address{nonTCPAddr}, 774 Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{nonTCPAddr}}}, 775 ServiceConfig: &serviceconfig.ParseResult{}, 776 }) 777 778 var gotState resolver.State 779 select { 780 case gotState = <-stateCh: 781 case <-time.After(defaultTestTimeout): 782 t.Fatal("Timeout when waiting for a state update from the delegating resolver") 783 } 784 785 // Verify that the delegating resolver doesn't call proxy resolver's 786 // UpdateState since we have no tcp address 787 select { 788 case <-proxyResolverBuilt: 789 t.Fatal("Unexpected call to proxy resolver update state") 790 case <-time.After(defaultTestShortTimeout): 791 } 792 793 wantState := resolver.State{ 794 Addresses: []resolver.Address{nonTCPAddr}, 795 Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{nonTCPAddr}}}, 796 ServiceConfig: &serviceconfig.ParseResult{}, 797 } 798 799 // Verify that the state clientconn receives is same as updated by target 800 // resolver, since we want to avoid proxy for any network type apart from 801 // tcp. 802 if diff := cmp.Diff(gotState, wantState); diff != "" { 803 t.Fatalf("Unexpected state from delegating resolver. Diff (-got +want):\n%s", diff) 804 } 805 } 806 807 // Tests the scenario where a proxy is configured, and the resolver returns tcp 808 // and non-tcp addresses. The test verifies that the delegating resolver doesn't 809 // add proxyatrribute to adresses with network type other than tcp, but adds 810 // the proxyattribute to addresses with network type tcp. 811 func (s) TestDelegatingResolverForMixNetworkType(t *testing.T) { 812 const ( 813 targetTestAddr = "test.target" 814 resolvedTargetTestAddr1 = "1.1.1.1:8080" 815 resolvedTargetTestAddr2 = "2.2.2.2:8080" 816 envProxyAddr = "proxytest.com" 817 ) 818 overrideTestHTTPSProxy(t, envProxyAddr) 819 820 // Manual resolver to control the target resolution. 821 targetResolver := manual.NewBuilderWithScheme("test") 822 target := targetResolver.Scheme() + ":///" + targetTestAddr 823 // Set up a manual DNS resolver to control the proxy address resolution. 824 proxyResolver, proxyResolverBuilt := setupDNS(t) 825 826 tcc, stateCh, _ := createTestResolverClientConn(t) 827 if _, err := delegatingresolver.New(resolver.Target{URL: *testutils.MustParseURL(target)}, tcc, resolver.BuildOptions{}, targetResolver, false); err != nil { 828 t.Fatalf("Failed to create delegating resolver: %v", err) 829 } 830 // Set network to anything other than tcp. 831 nonTCPAddr := networktype.Set(resolver.Address{Addr: resolvedTargetTestAddr1}, "unix") 832 targetResolver.UpdateState(resolver.State{ 833 Addresses: []resolver.Address{nonTCPAddr, {Addr: resolvedTargetTestAddr2}}, 834 Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{nonTCPAddr, {Addr: resolvedTargetTestAddr2}}}}, 835 ServiceConfig: &serviceconfig.ParseResult{}, 836 }) 837 838 select { 839 case <-stateCh: 840 t.Fatalf("Delegating resolver invoked UpdateState before both the proxy and target resolvers had updated their states.") 841 case <-time.After(defaultTestShortTimeout): 842 } 843 844 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 845 defer cancel() 846 847 // Wait for the proxy resolver to be built before calling UpdateState. 848 mustBuildResolver(ctx, t, proxyResolverBuilt) 849 proxyResolver.UpdateState(resolver.State{ 850 Addresses: []resolver.Address{{Addr: envProxyAddr}}, 851 ServiceConfig: &serviceconfig.ParseResult{}, 852 }) 853 854 var gotState resolver.State 855 select { 856 case gotState = <-stateCh: 857 case <-ctx.Done(): 858 t.Fatal("Context timed out when waiting for a state update from the delegating resolver") 859 } 860 wantState := resolver.State{ 861 Addresses: []resolver.Address{nonTCPAddr, proxyAddressWithTargetAttribute(envProxyAddr, resolvedTargetTestAddr2)}, 862 Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{nonTCPAddr, proxyAddressWithTargetAttribute(envProxyAddr, resolvedTargetTestAddr2)}}}, 863 ServiceConfig: &serviceconfig.ParseResult{}, 864 } 865 866 if diff := cmp.Diff(gotState, wantState); diff != "" { 867 t.Fatalf("Unexpected state from delegating resolver. Diff (-got +want):\n%v", diff) 868 } 869 } 870 871 // Tests the scenario where a proxy is configured but some addresses are 872 // excluded (by using the NO_PROXY environment variable). The test verifies that 873 // the delegating resolver doesn't add proxyatrribute to adresses excluded, but 874 // adds the proxyattribute to all other addresses. 875 func (s) TestDelegatingResolverWithNoProxyEnvUsed(t *testing.T) { 876 const ( 877 targetTestAddr = "test.target" 878 noproxyresolvedTargetAddr = "1.1.1.1:8080" 879 resolvedTargetTestAddr = "2.2.2.2:8080" 880 envProxyAddr = "proxytest.com" 881 ) 882 hpfe := func(req *http.Request) (*url.URL, error) { 883 // return nil to mimick the scenario where the address is excluded using 884 // `NO_PROXY` env variable. 885 if req.URL.Host == noproxyresolvedTargetAddr { 886 return nil, nil 887 } 888 return &url.URL{ 889 Scheme: "https", 890 Host: envProxyAddr, 891 }, nil 892 } 893 originalhpfe := delegatingresolver.HTTPSProxyFromEnvironment 894 delegatingresolver.HTTPSProxyFromEnvironment = hpfe 895 defer func() { 896 delegatingresolver.HTTPSProxyFromEnvironment = originalhpfe 897 }() 898 899 // Manual resolver to control the target resolution. 900 targetResolver := manual.NewBuilderWithScheme("test") 901 target := targetResolver.Scheme() + ":///" + targetTestAddr 902 // Set up a manual DNS resolver to control the proxy address resolution. 903 proxyResolver, proxyResolverBuilt := setupDNS(t) 904 905 tcc, stateCh, _ := createTestResolverClientConn(t) 906 if _, err := delegatingresolver.New(resolver.Target{URL: *testutils.MustParseURL(target)}, tcc, resolver.BuildOptions{}, targetResolver, false); err != nil { 907 t.Fatalf("Failed to create delegating resolver: %v", err) 908 } 909 910 targetResolver.UpdateState(resolver.State{ 911 Addresses: []resolver.Address{{Addr: noproxyresolvedTargetAddr}, {Addr: resolvedTargetTestAddr}}, 912 Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: noproxyresolvedTargetAddr}, {Addr: resolvedTargetTestAddr}}}}, 913 ServiceConfig: &serviceconfig.ParseResult{}, 914 }) 915 916 select { 917 case <-stateCh: 918 t.Fatalf("Delegating resolver invoked UpdateState before both the proxy and target resolvers had updated their states.") 919 case <-time.After(defaultTestShortTimeout): 920 } 921 922 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 923 defer cancel() 924 925 // Wait for the proxy resolver to be built before calling UpdateState. 926 mustBuildResolver(ctx, t, proxyResolverBuilt) 927 proxyResolver.UpdateState(resolver.State{ 928 Addresses: []resolver.Address{{Addr: envProxyAddr}}, 929 ServiceConfig: &serviceconfig.ParseResult{}, 930 }) 931 932 var gotState resolver.State 933 select { 934 case gotState = <-stateCh: 935 case <-ctx.Done(): 936 t.Fatal("Context timed out when waiting for a state update from the delegating resolver") 937 } 938 wantState := resolver.State{ 939 Addresses: []resolver.Address{{Addr: noproxyresolvedTargetAddr}, proxyAddressWithTargetAttribute(envProxyAddr, resolvedTargetTestAddr)}, 940 Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: noproxyresolvedTargetAddr}, proxyAddressWithTargetAttribute(envProxyAddr, resolvedTargetTestAddr)}}}, 941 ServiceConfig: &serviceconfig.ParseResult{}, 942 } 943 944 if diff := cmp.Diff(gotState, wantState); diff != "" { 945 t.Fatalf("Unexpected state from delegating resolver. Diff (-got +want):\n%v", diff) 946 } 947 }