Skip to content

Commit e6304b1

Browse files
committed
Modified TestMinResolutionInterval_NoExtraDelay to avoid running for 4s
1 parent 16c904d commit e6304b1

File tree

3 files changed

+56
-34
lines changed

3 files changed

+56
-34
lines changed

internal/resolver/dns/dns_resolver.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ var (
6363
func init() {
6464
resolver.Register(NewBuilder())
6565
internal.TimeAfterFunc = time.After
66+
internal.TimeUntilFunc = time.Until
6667
internal.NewNetResolver = newNetResolver
6768
internal.AddressDialer = addressDialer
6869
}
@@ -229,7 +230,7 @@ func (d *dnsResolver) watcher() {
229230
select {
230231
case <-d.ctx.Done():
231232
return
232-
case <-internal.TimeAfterFunc(time.Until(nextResolutionTime)):
233+
case <-internal.TimeAfterFunc(internal.TimeUntilFunc(nextResolutionTime)):
233234
}
234235
}
235236
}

internal/resolver/dns/dns_resolver_test.go

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,15 @@ func overrideTimeAfterFuncWithChannel(t *testing.T) (durChan chan time.Duration,
102102
return durChan, timeChan
103103
}
104104

105+
// Override the remaining time used by the DNS resolver to allow resolution
106+
func overrideTimeUntilFunc(t *testing.T, now time.Time) {
107+
origTimeUntil := dnsinternal.TimeUntilFunc
108+
dnsinternal.TimeUntilFunc = func(tm time.Time) time.Duration {
109+
return now.Sub(tm)
110+
}
111+
t.Cleanup(func() { dnsinternal.TimeUntilFunc = origTimeUntil })
112+
}
113+
105114
func enableSRVLookups(t *testing.T) {
106115
origEnableSRVLookups := dns.EnableSRVLookups
107116
dns.EnableSRVLookups = true
@@ -1292,16 +1301,12 @@ func (s) TestMinResolutionInterval(t *testing.T) {
12921301
}
12931302

12941303
// TestMinResolutionInterval_NoExtraDelay verifies that there is no extra delay
1295-
// between two resolution requests apart from [MinResolutionInterval]
1296-
// i.e. if a request is made after [MinResolutionInterval], it should resolve
1297-
// immediately. Test sets [MinResolutionInterval] to 1 second and calls
1298-
// ResolveNow() 4 times with a wait of 1 second between each request.
1299-
// A correct implementation should resolve all requests without timing out in
1300-
// test duration of 5 seconds.
1304+
// between two resolution requests apart from [minResolutionInterval].
1305+
// It sets the minResolutionInterval 1s and overrides timeUntilFunc to
1306+
// calculate remaining time to allow resolution after 1s and verifies that
1307+
// remaining time to allow resolution is very small
13011308
func (s) TestMinResolutionInterval_NoExtraDelay(t *testing.T) {
1302-
const target = "foo.bar.com"
1303-
1304-
overrideResolutionInterval(t, 1*time.Second)
1309+
durChan, timeChan := overrideTimeAfterFuncWithChannel(t)
13051310
tr := &testNetResolver{
13061311
hostLookupTable: map[string][]string{
13071312
"foo.bar.com": {"1.2.3.4", "5.6.7.8"},
@@ -1311,34 +1316,44 @@ func (s) TestMinResolutionInterval_NoExtraDelay(t *testing.T) {
13111316
},
13121317
}
13131318
overrideNetResolver(t, tr)
1319+
var minResolutionInterval = 1 * time.Second
1320+
overrideResolutionInterval(t, minResolutionInterval)
13141321

1315-
r, stateCh, _ := buildResolverWithTestClientConn(t, target)
1322+
r, stateCh, errorCh := buildResolverWithTestClientConn(t, "foo.bar.com")
13161323

1317-
wantAddrs := []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}, {Addr: "5.6.7.8" + colonDefaultPort}}
1318-
wantSC := scJSON
1319-
1320-
// set context timeout to test duration of 5 seconds
1321-
// to make sure all 4 resolutions happen successfully
1322-
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
1323-
defer cancel()
1324+
ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
1325+
defer ctxCancel()
1326+
select {
1327+
case <-ctx.Done():
1328+
t.Fatal("Timeout when waiting for an error from the resolver")
1329+
case <-stateCh:
1330+
case err := <-errorCh:
1331+
t.Fatalf("Unexpected error from resolver, %v", err)
1332+
}
13241333

1325-
// We chose to make 4 requests to strike a balance between coverage and
1326-
// test duration. This number is sufficiently large to validate the
1327-
// behavior across multiple resolution attempts, while also reducing
1328-
// the likelihood of flakiness due to timing issues.
1329-
for i := 1; i <= 4; i++ {
1330-
verifyUpdateFromResolver(ctx, t, stateCh, wantAddrs, nil, wantSC)
1334+
// Make next resolution request after 1s.
1335+
var now = time.Now().Add(minResolutionInterval)
1336+
overrideTimeUntilFunc(t, now)
1337+
r.ResolveNow(resolver.ResolveNowOptions{})
13311338

1332-
// Wait for 1 second to respect [MinResolutionInterval]
1333-
// before sending another resolution request
1334-
select {
1335-
case <-dnsinternal.TimeAfterFunc(1 * time.Second):
1336-
// Waited for 1 second
1337-
case <-ctx.Done():
1338-
// If the context is done, exit the loop
1339-
t.Fatal("Timeout when waiting for a state update from the resolver")
1339+
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
1340+
defer cancel()
1341+
select {
1342+
case <-ctx.Done():
1343+
t.Fatal("Timeout when waiting for an error from the resolver")
1344+
case dur := <-durChan:
1345+
if dur > 1*time.Millisecond {
1346+
t.Fatalf("Remaining time duration to allow next resolution is higher than expected")
13401347
}
1348+
}
13411349

1342-
r.ResolveNow(resolver.ResolveNowOptions{})
1350+
// Unblock the DNS resolver's backoff by pushing the current time.
1351+
timeChan <- time.Now()
1352+
1353+
select {
1354+
case <-ctx.Done():
1355+
t.Fatal("Timeout when waiting for an error from the resolver")
1356+
case err := <-errorCh:
1357+
t.Fatalf("Unexpected error from resolver, %v", err)
13431358
}
13441359
}

internal/resolver/dns/internal/internal.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,17 @@ var (
5151
// The following vars are overridden from tests.
5252
var (
5353
// TimeAfterFunc is used by the DNS resolver to wait for the given duration
54-
// to elapse. In non-test code, this is implemented by time.After. In test
54+
// to elapse. In non-test code, this is implemented by time.After. In test
5555
// code, this can be used to control the amount of time the resolver is
5656
// blocked waiting for the duration to elapse.
5757
TimeAfterFunc func(time.Duration) <-chan time.Time
5858

59+
// TimeUntilFunc is used by the DNS resolver to get the time remaining
60+
// to allow next resolution. In non-test code, this is implemented by
61+
// time.Until. In test code, this can be used to control the remaining
62+
// time for resolver to allow next resolution.
63+
TimeUntilFunc func(time.Time) time.Duration
64+
5965
// NewNetResolver returns the net.Resolver instance for the given target.
6066
NewNetResolver func(string) (NetResolver, error)
6167

0 commit comments

Comments
 (0)