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  }