@@ -996,6 +996,9 @@ def send(out, addr=const._MDNS_ADDR, port=const._MDNS_PORT, v6_flow_scope=()):
996
996
# Increase simulated time shift by 1/4 of the TTL in seconds
997
997
time_offset += expected_ttl / 4
998
998
now = _new_current_time_millis ()
999
+ # Force the next query to be sent since we are testing
1000
+ # to see if the query contains answers and not the scheduler
1001
+ browser .query_scheduler ._next_time [type_ ] = now + (1000 * expected_ttl )
999
1002
browser .reschedule_type (type_ , now , now )
1000
1003
sleep_count += 1
1001
1004
await asyncio .wait_for (got_query .wait (), 1 )
@@ -1244,3 +1247,67 @@ def update_service(self, zc, type_, name) -> None: # type: ignore[no-untyped-de
1244
1247
('add' , '_http._tcp.local.' , 'ShellyPro4PM-94B97EC07650._http._tcp.local.' ),
1245
1248
('update' , '_http._tcp.local.' , 'ShellyPro4PM-94B97EC07650._http._tcp.local.' ),
1246
1249
]
1250
+
1251
+
1252
+ @pytest .mark .asyncio
1253
+ async def test_service_browser_does_not_try_to_send_if_not_ready ():
1254
+ """Test that the service browser does not try to send if not ready when rescheduling a type."""
1255
+ service_added = asyncio .Event ()
1256
+ type_ = "_http._tcp.local."
1257
+ registration_name = "nosend.%s" % type_
1258
+
1259
+ def on_service_state_change (zeroconf , service_type , state_change , name ):
1260
+ if name == registration_name :
1261
+ if state_change is ServiceStateChange .Added :
1262
+ service_added .set ()
1263
+
1264
+ aiozc = AsyncZeroconf (interfaces = ['127.0.0.1' ])
1265
+ zeroconf_browser = aiozc .zeroconf
1266
+ await zeroconf_browser .async_wait_for_start ()
1267
+
1268
+ expected_ttl = const ._DNS_HOST_TTL
1269
+ time_offset = 0.0
1270
+
1271
+ def _new_current_time_millis ():
1272
+ """Current system time in milliseconds"""
1273
+ return (time .monotonic () * 1000 ) + (time_offset * 1000 )
1274
+
1275
+ assert len (zeroconf_browser .engine .protocols ) == 2
1276
+
1277
+ aio_zeroconf_registrar = AsyncZeroconf (interfaces = ['127.0.0.1' ])
1278
+ zeroconf_registrar = aio_zeroconf_registrar .zeroconf
1279
+ await aio_zeroconf_registrar .zeroconf .async_wait_for_start ()
1280
+ assert len (zeroconf_registrar .engine .protocols ) == 2
1281
+ with patch ("zeroconf._services.browser.current_time_millis" , _new_current_time_millis ):
1282
+ service_added = asyncio .Event ()
1283
+ browser = AsyncServiceBrowser (zeroconf_browser , type_ , [on_service_state_change ])
1284
+ desc = {'path' : '/~paulsm/' }
1285
+ info = ServiceInfo (
1286
+ type_ , registration_name , 80 , 0 , 0 , desc , "ash-2.local." , addresses = [socket .inet_aton ("10.0.1.2" )]
1287
+ )
1288
+ task = await aio_zeroconf_registrar .async_register_service (info )
1289
+ await task
1290
+
1291
+ try :
1292
+ await asyncio .wait_for (service_added .wait (), 1 )
1293
+ time_offset = 1000 * expected_ttl # set the time to the end of the ttl
1294
+ now = _new_current_time_millis ()
1295
+ browser .query_scheduler ._next_time [type_ ] = now + (1000 * expected_ttl )
1296
+ # Make sure the query schedule is to a time in the future
1297
+ # so we will reschedule
1298
+ with patch .object (
1299
+ browser , "_async_send_ready_queries"
1300
+ ) as _async_send_ready_queries , patch .object (
1301
+ browser , "_async_send_ready_queries_schedule_next"
1302
+ ) as _async_send_ready_queries_schedule_next :
1303
+ # Reschedule the type to be sent in 1ms in the future
1304
+ # to make sure the query is not sent
1305
+ browser .reschedule_type (type_ , now , now + 1 )
1306
+ assert not _async_send_ready_queries .called
1307
+ await asyncio .sleep (0.01 )
1308
+ # Make sure it does happen after the sleep
1309
+ assert _async_send_ready_queries_schedule_next .called
1310
+ finally :
1311
+ await aio_zeroconf_registrar .async_close ()
1312
+ await browser .async_cancel ()
1313
+ await aiozc .async_close ()
0 commit comments