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  }