@@ -102,6 +102,15 @@ func overrideTimeAfterFuncWithChannel(t *testing.T) (durChan chan time.Duration,
102
102
return durChan , timeChan
103
103
}
104
104
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
+
105
114
func enableSRVLookups (t * testing.T ) {
106
115
origEnableSRVLookups := dns .EnableSRVLookups
107
116
dns .EnableSRVLookups = true
@@ -1292,16 +1301,12 @@ func (s) TestMinResolutionInterval(t *testing.T) {
1292
1301
}
1293
1302
1294
1303
// 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
1301
1308
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 )
1305
1310
tr := & testNetResolver {
1306
1311
hostLookupTable : map [string ][]string {
1307
1312
"foo.bar.com" : {"1.2.3.4" , "5.6.7.8" },
@@ -1311,34 +1316,44 @@ func (s) TestMinResolutionInterval_NoExtraDelay(t *testing.T) {
1311
1316
},
1312
1317
}
1313
1318
overrideNetResolver (t , tr )
1319
+ var minResolutionInterval = 1 * time .Second
1320
+ overrideResolutionInterval (t , minResolutionInterval )
1314
1321
1315
- r , stateCh , _ := buildResolverWithTestClientConn (t , target )
1322
+ r , stateCh , errorCh := buildResolverWithTestClientConn (t , "foo.bar.com" )
1316
1323
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
+ }
1324
1333
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 {})
1331
1338
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 " )
1340
1347
}
1348
+ }
1341
1349
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 )
1343
1358
}
1344
1359
}
0 commit comments