Skip to content

Commit dd4c0ad

Browse files
authored
internal/testutils: add a new test type that implements resolver.ClientConn (#6668)
1 parent 32e3ef1 commit dd4c0ad

File tree

17 files changed

+1158
-1370
lines changed

17 files changed

+1158
-1370
lines changed

balancer/weightedtarget/weightedtarget_test.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ func init() {
167167
// glue code in weighted_target. It also tests an empty target config update,
168168
// which should trigger a transient failure state update.
169169
func (s) TestWeightedTarget(t *testing.T) {
170-
cc := testutils.NewTestClientConn(t)
170+
cc := testutils.NewBalancerClientConn(t)
171171
wtb := wtbBuilder.Build(cc, balancer.BuildOptions{})
172172
defer wtb.Close()
173173

@@ -329,7 +329,7 @@ func (s) TestWeightedTarget(t *testing.T) {
329329
// have a weighted target balancer will one sub-balancer, and we add and remove
330330
// backends from the subBalancer.
331331
func (s) TestWeightedTarget_OneSubBalancer_AddRemoveBackend(t *testing.T) {
332-
cc := testutils.NewTestClientConn(t)
332+
cc := testutils.NewBalancerClientConn(t)
333333
wtb := wtbBuilder.Build(cc, balancer.BuildOptions{})
334334
defer wtb.Close()
335335

@@ -427,7 +427,7 @@ func (s) TestWeightedTarget_OneSubBalancer_AddRemoveBackend(t *testing.T) {
427427
// TestWeightedTarget_TwoSubBalancers_OneBackend tests the case where we have a
428428
// weighted target balancer with two sub-balancers, each with one backend.
429429
func (s) TestWeightedTarget_TwoSubBalancers_OneBackend(t *testing.T) {
430-
cc := testutils.NewTestClientConn(t)
430+
cc := testutils.NewBalancerClientConn(t)
431431
wtb := wtbBuilder.Build(cc, balancer.BuildOptions{})
432432
defer wtb.Close()
433433

@@ -493,7 +493,7 @@ func (s) TestWeightedTarget_TwoSubBalancers_OneBackend(t *testing.T) {
493493
// a weighted target balancer with two sub-balancers, each with more than one
494494
// backend.
495495
func (s) TestWeightedTarget_TwoSubBalancers_MoreBackends(t *testing.T) {
496-
cc := testutils.NewTestClientConn(t)
496+
cc := testutils.NewBalancerClientConn(t)
497497
wtb := wtbBuilder.Build(cc, balancer.BuildOptions{})
498498
defer wtb.Close()
499499

@@ -637,7 +637,7 @@ func (s) TestWeightedTarget_TwoSubBalancers_MoreBackends(t *testing.T) {
637637
// case where we have a weighted target balancer with two sub-balancers of
638638
// differing weights.
639639
func (s) TestWeightedTarget_TwoSubBalancers_DifferentWeight_MoreBackends(t *testing.T) {
640-
cc := testutils.NewTestClientConn(t)
640+
cc := testutils.NewBalancerClientConn(t)
641641
wtb := wtbBuilder.Build(cc, balancer.BuildOptions{})
642642
defer wtb.Close()
643643

@@ -718,7 +718,7 @@ func (s) TestWeightedTarget_TwoSubBalancers_DifferentWeight_MoreBackends(t *test
718718
// have a weighted target balancer with three sub-balancers and we remove one of
719719
// the subBalancers.
720720
func (s) TestWeightedTarget_ThreeSubBalancers_RemoveBalancer(t *testing.T) {
721-
cc := testutils.NewTestClientConn(t)
721+
cc := testutils.NewBalancerClientConn(t)
722722
wtb := wtbBuilder.Build(cc, balancer.BuildOptions{})
723723
defer wtb.Close()
724724

@@ -879,7 +879,7 @@ func (s) TestWeightedTarget_ThreeSubBalancers_RemoveBalancer(t *testing.T) {
879879
// where we have a weighted target balancer with two sub-balancers, and we
880880
// change the weight of these subBalancers.
881881
func (s) TestWeightedTarget_TwoSubBalancers_ChangeWeight_MoreBackends(t *testing.T) {
882-
cc := testutils.NewTestClientConn(t)
882+
cc := testutils.NewBalancerClientConn(t)
883883
wtb := wtbBuilder.Build(cc, balancer.BuildOptions{})
884884
defer wtb.Close()
885885

@@ -997,7 +997,7 @@ func (s) TestWeightedTarget_TwoSubBalancers_ChangeWeight_MoreBackends(t *testing
997997
// the picks won't fail with transient_failure, and should instead wait for the
998998
// other sub-balancer.
999999
func (s) TestWeightedTarget_InitOneSubBalancerTransientFailure(t *testing.T) {
1000-
cc := testutils.NewTestClientConn(t)
1000+
cc := testutils.NewBalancerClientConn(t)
10011001
wtb := wtbBuilder.Build(cc, balancer.BuildOptions{})
10021002
defer wtb.Close()
10031003

@@ -1059,7 +1059,7 @@ func (s) TestWeightedTarget_InitOneSubBalancerTransientFailure(t *testing.T) {
10591059
// connecting, the overall state stays in transient_failure, and all picks
10601060
// return transient failure error.
10611061
func (s) TestBalancerGroup_SubBalancerTurnsConnectingFromTransientFailure(t *testing.T) {
1062-
cc := testutils.NewTestClientConn(t)
1062+
cc := testutils.NewBalancerClientConn(t)
10631063
wtb := wtbBuilder.Build(cc, balancer.BuildOptions{})
10641064
defer wtb.Close()
10651065

@@ -1141,7 +1141,7 @@ func (s) TestBalancerGroup_SubBalancerTurnsConnectingFromTransientFailure(t *tes
11411141

11421142
// Verify that a SubConn is created with the expected address and hierarchy
11431143
// path cleared.
1144-
func verifyAddressInNewSubConn(t *testing.T, cc *testutils.TestClientConn, addr resolver.Address) {
1144+
func verifyAddressInNewSubConn(t *testing.T, cc *testutils.BalancerClientConn, addr resolver.Address) {
11451145
t.Helper()
11461146

11471147
gotAddr := <-cc.NewSubConnAddrsCh
@@ -1163,7 +1163,7 @@ type subConnWithAddr struct {
11631163
//
11641164
// Returned value is a map from subBalancer (identified by its config) to
11651165
// subConns created by it.
1166-
func waitForNewSubConns(t *testing.T, cc *testutils.TestClientConn, num int) map[string][]subConnWithAddr {
1166+
func waitForNewSubConns(t *testing.T, cc *testutils.BalancerClientConn, num int) map[string][]subConnWithAddr {
11671167
t.Helper()
11681168

11691169
scs := make(map[string][]subConnWithAddr)
@@ -1233,7 +1233,7 @@ func init() {
12331233
// TestInitialIdle covers the case that if the child reports Idle, the overall
12341234
// state will be Idle.
12351235
func (s) TestInitialIdle(t *testing.T) {
1236-
cc := testutils.NewTestClientConn(t)
1236+
cc := testutils.NewBalancerClientConn(t)
12371237
wtb := wtbBuilder.Build(cc, balancer.BuildOptions{})
12381238
defer wtb.Close()
12391239

@@ -1274,7 +1274,7 @@ func (s) TestInitialIdle(t *testing.T) {
12741274
// TestIgnoreSubBalancerStateTransitions covers the case that if the child reports a
12751275
// transition from TF to Connecting, the overall state will still be TF.
12761276
func (s) TestIgnoreSubBalancerStateTransitions(t *testing.T) {
1277-
cc := &tcc{TestClientConn: testutils.NewTestClientConn(t)}
1277+
cc := &tcc{BalancerClientConn: testutils.NewBalancerClientConn(t)}
12781278

12791279
wtb := wtbBuilder.Build(cc, balancer.BuildOptions{})
12801280
defer wtb.Close()
@@ -1314,17 +1314,17 @@ func (s) TestIgnoreSubBalancerStateTransitions(t *testing.T) {
13141314
// tcc wraps a testutils.TestClientConn but stores all state transitions in a
13151315
// slice.
13161316
type tcc struct {
1317-
*testutils.TestClientConn
1317+
*testutils.BalancerClientConn
13181318
states []balancer.State
13191319
}
13201320

13211321
func (t *tcc) UpdateState(bs balancer.State) {
13221322
t.states = append(t.states, bs)
1323-
t.TestClientConn.UpdateState(bs)
1323+
t.BalancerClientConn.UpdateState(bs)
13241324
}
13251325

13261326
func (s) TestUpdateStatePauses(t *testing.T) {
1327-
cc := &tcc{TestClientConn: testutils.NewTestClientConn(t)}
1327+
cc := &tcc{BalancerClientConn: testutils.NewBalancerClientConn(t)}
13281328

13291329
balFuncs := stub.BalancerFuncs{
13301330
UpdateClientConnState: func(bd *stub.BalancerData, s balancer.ClientConnState) error {

clientconn.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ import (
4848
"google.golang.org/grpc/status"
4949

5050
_ "google.golang.org/grpc/balancer/roundrobin" // To register roundrobin.
51-
_ "google.golang.org/grpc/internal/resolver/dns" // To register dns resolver.
5251
_ "google.golang.org/grpc/internal/resolver/passthrough" // To register passthrough resolver.
5352
_ "google.golang.org/grpc/internal/resolver/unix" // To register unix resolver.
53+
_ "google.golang.org/grpc/resolver/dns" // To register dns resolver.
5454
)
5555

5656
const (

internal/balancer/gracefulswitch/gracefulswitch_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ func Test(t *testing.T) {
4949
grpctest.RunSubTests(t, s{})
5050
}
5151

52-
func setup(t *testing.T) (*testutils.TestClientConn, *Balancer) {
53-
tcc := testutils.NewTestClientConn(t)
52+
func setup(t *testing.T) (*testutils.BalancerClientConn, *Balancer) {
53+
tcc := testutils.NewBalancerClientConn(t)
5454
return tcc, NewBalancer(tcc, balancer.BuildOptions{})
5555
}
5656

internal/balancergroup/balancergroup_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func Test(t *testing.T) {
7373
// - b3, weight 1, backends [1,2]
7474
// Start the balancer group again and check for behavior.
7575
func (s) TestBalancerGroup_start_close(t *testing.T) {
76-
cc := testutils.NewTestClientConn(t)
76+
cc := testutils.NewBalancerClientConn(t)
7777
gator := weightedaggregator.New(cc, nil, testutils.NewTestWRR)
7878
gator.Start()
7979
bg := New(Options{
@@ -176,7 +176,7 @@ func (s) TestBalancerGroup_start_close_deadlock(t *testing.T) {
176176
stub.Register(balancerName, stub.BalancerFuncs{})
177177
builder := balancer.Get(balancerName)
178178

179-
cc := testutils.NewTestClientConn(t)
179+
cc := testutils.NewBalancerClientConn(t)
180180
gator := weightedaggregator.New(cc, nil, testutils.NewTestWRR)
181181
gator.Start()
182182
bg := New(Options{
@@ -203,8 +203,8 @@ func (s) TestBalancerGroup_start_close_deadlock(t *testing.T) {
203203
// Two rr balancers are added to bg, each with 2 ready subConns. A sub-balancer
204204
// is removed later, so the balancer group returned has one sub-balancer in its
205205
// own map, and one sub-balancer in cache.
206-
func initBalancerGroupForCachingTest(t *testing.T, idleCacheTimeout time.Duration) (*weightedaggregator.Aggregator, *BalancerGroup, *testutils.TestClientConn, map[resolver.Address]*testutils.TestSubConn) {
207-
cc := testutils.NewTestClientConn(t)
206+
func initBalancerGroupForCachingTest(t *testing.T, idleCacheTimeout time.Duration) (*weightedaggregator.Aggregator, *BalancerGroup, *testutils.BalancerClientConn, map[resolver.Address]*testutils.TestSubConn) {
207+
cc := testutils.NewBalancerClientConn(t)
208208
gator := weightedaggregator.New(cc, nil, testutils.NewTestWRR)
209209
gator.Start()
210210
bg := New(Options{
@@ -503,7 +503,7 @@ func (s) TestBalancerGroupBuildOptions(t *testing.T) {
503503
return nil
504504
},
505505
})
506-
cc := testutils.NewTestClientConn(t)
506+
cc := testutils.NewBalancerClientConn(t)
507507
bg := New(Options{
508508
CC: cc,
509509
BuildOpts: bOpts,
@@ -531,7 +531,7 @@ func (s) TestBalancerExitIdleOne(t *testing.T) {
531531
exitIdleCh <- struct{}{}
532532
},
533533
})
534-
cc := testutils.NewTestClientConn(t)
534+
cc := testutils.NewBalancerClientConn(t)
535535
bg := New(Options{
536536
CC: cc,
537537
BuildOpts: balancer.BuildOptions{},
@@ -561,7 +561,7 @@ func (s) TestBalancerExitIdleOne(t *testing.T) {
561561
// for the second passed in address and also only picks that created SubConn.
562562
// The new aggregated picker should reflect this change for the child.
563563
func (s) TestBalancerGracefulSwitch(t *testing.T) {
564-
cc := testutils.NewTestClientConn(t)
564+
cc := testutils.NewBalancerClientConn(t)
565565
gator := weightedaggregator.New(cc, nil, testutils.NewTestWRR)
566566
gator.Start()
567567
bg := New(Options{

internal/resolver/dns/dns_resolver.go

Lines changed: 20 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ package dns
2323
import (
2424
"context"
2525
"encoding/json"
26-
"errors"
2726
"fmt"
2827
"net"
2928
"os"
@@ -37,6 +36,7 @@ import (
3736
"google.golang.org/grpc/internal/backoff"
3837
"google.golang.org/grpc/internal/envconfig"
3938
"google.golang.org/grpc/internal/grpcrand"
39+
"google.golang.org/grpc/internal/resolver/dns/internal"
4040
"google.golang.org/grpc/resolver"
4141
"google.golang.org/grpc/serviceconfig"
4242
)
@@ -47,15 +47,11 @@ var EnableSRVLookups = false
4747

4848
var logger = grpclog.Component("dns")
4949

50-
// Globals to stub out in tests. TODO: Perhaps these two can be combined into a
51-
// single variable for testing the resolver?
52-
var (
53-
newTimer = time.NewTimer
54-
newTimerDNSResRate = time.NewTimer
55-
)
56-
5750
func init() {
5851
resolver.Register(NewBuilder())
52+
internal.TimeAfterFunc = time.After
53+
internal.NewNetResolver = newNetResolver
54+
internal.AddressDialer = addressDialer
5955
}
6056

6157
const (
@@ -70,31 +66,18 @@ const (
7066
txtAttribute = "grpc_config="
7167
)
7268

73-
var (
74-
errMissingAddr = errors.New("dns resolver: missing address")
75-
76-
// Addresses ending with a colon that is supposed to be the separator
77-
// between host and port is not allowed. E.g. "::" is a valid address as
78-
// it is an IPv6 address (host only) and "[::]:" is invalid as it ends with
79-
// a colon as the host and port separator
80-
errEndsWithColon = errors.New("dns resolver: missing port after port-separator colon")
81-
)
82-
83-
var (
84-
defaultResolver netResolver = net.DefaultResolver
85-
// To prevent excessive re-resolution, we enforce a rate limit on DNS
86-
// resolution requests.
87-
minDNSResRate = 30 * time.Second
88-
)
89-
9069
var addressDialer = func(address string) func(context.Context, string, string) (net.Conn, error) {
9170
return func(ctx context.Context, network, _ string) (net.Conn, error) {
9271
var dialer net.Dialer
9372
return dialer.DialContext(ctx, network, address)
9473
}
9574
}
9675

97-
var newNetResolver = func(authority string) (netResolver, error) {
76+
var newNetResolver = func(authority string) (internal.NetResolver, error) {
77+
if authority == "" {
78+
return net.DefaultResolver, nil
79+
}
80+
9881
host, port, err := parseTarget(authority, defaultDNSSvrPort)
9982
if err != nil {
10083
return nil, err
@@ -104,7 +87,7 @@ var newNetResolver = func(authority string) (netResolver, error) {
10487

10588
return &net.Resolver{
10689
PreferGo: true,
107-
Dial: addressDialer(authorityWithPort),
90+
Dial: internal.AddressDialer(authorityWithPort),
10891
}, nil
10992
}
11093

@@ -142,13 +125,9 @@ func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts
142125
disableServiceConfig: opts.DisableServiceConfig,
143126
}
144127

145-
if target.URL.Host == "" {
146-
d.resolver = defaultResolver
147-
} else {
148-
d.resolver, err = newNetResolver(target.URL.Host)
149-
if err != nil {
150-
return nil, err
151-
}
128+
d.resolver, err = internal.NewNetResolver(target.URL.Host)
129+
if err != nil {
130+
return nil, err
152131
}
153132

154133
d.wg.Add(1)
@@ -161,12 +140,6 @@ func (b *dnsBuilder) Scheme() string {
161140
return "dns"
162141
}
163142

164-
type netResolver interface {
165-
LookupHost(ctx context.Context, host string) (addrs []string, err error)
166-
LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*net.SRV, err error)
167-
LookupTXT(ctx context.Context, name string) (txts []string, err error)
168-
}
169-
170143
// deadResolver is a resolver that does nothing.
171144
type deadResolver struct{}
172145

@@ -178,7 +151,7 @@ func (deadResolver) Close() {}
178151
type dnsResolver struct {
179152
host string
180153
port string
181-
resolver netResolver
154+
resolver internal.NetResolver
182155
ctx context.Context
183156
cancel context.CancelFunc
184157
cc resolver.ClientConn
@@ -223,29 +196,27 @@ func (d *dnsResolver) watcher() {
223196
err = d.cc.UpdateState(*state)
224197
}
225198

226-
var timer *time.Timer
199+
var waitTime time.Duration
227200
if err == nil {
228201
// Success resolving, wait for the next ResolveNow. However, also wait 30
229202
// seconds at the very least to prevent constantly re-resolving.
230203
backoffIndex = 1
231-
timer = newTimerDNSResRate(minDNSResRate)
204+
waitTime = internal.MinResolutionRate
232205
select {
233206
case <-d.ctx.Done():
234-
timer.Stop()
235207
return
236208
case <-d.rn:
237209
}
238210
} else {
239211
// Poll on an error found in DNS Resolver or an error received from
240212
// ClientConn.
241-
timer = newTimer(backoff.DefaultExponential.Backoff(backoffIndex))
213+
waitTime = backoff.DefaultExponential.Backoff(backoffIndex)
242214
backoffIndex++
243215
}
244216
select {
245217
case <-d.ctx.Done():
246-
timer.Stop()
247218
return
248-
case <-timer.C:
219+
case <-internal.TimeAfterFunc(waitTime):
249220
}
250221
}
251222
}
@@ -387,7 +358,7 @@ func formatIP(addr string) (addrIP string, ok bool) {
387358
// target: ":80" defaultPort: "443" returns host: "localhost", port: "80"
388359
func parseTarget(target, defaultPort string) (host, port string, err error) {
389360
if target == "" {
390-
return "", "", errMissingAddr
361+
return "", "", internal.ErrMissingAddr
391362
}
392363
if ip := net.ParseIP(target); ip != nil {
393364
// target is an IPv4 or IPv6(without brackets) address
@@ -397,7 +368,7 @@ func parseTarget(target, defaultPort string) (host, port string, err error) {
397368
if port == "" {
398369
// If the port field is empty (target ends with colon), e.g. "[::1]:",
399370
// this is an error.
400-
return "", "", errEndsWithColon
371+
return "", "", internal.ErrEndsWithColon
401372
}
402373
// target has port, i.e ipv4-host:port, [ipv6-host]:port, host-name:port
403374
if host == "" {

0 commit comments

Comments
 (0)