@@ -212,34 +212,36 @@ def test_same_name(self):
212212 r .DNSIncoming (generated .packet ())
213213
214214 def test_lots_of_names (self ):
215+
215216 # instantiate a zeroconf instance
216- zeroconf = Zeroconf (interfaces = ['127.0.0.1' ])
217+ zc = Zeroconf (interfaces = ['127.0.0.1' ])
217218
218219 # we are going to monkey patch the zeroconf send to check packet sizes
219- old_send = zeroconf .send
220+ old_send = zc .send
220221
221222 # needs to be a list so that we can modify it in our phony send
222- longest_packet = [0 ]
223+ longest_packet = [0 , None ]
223224
224225 def send (out , addr = r ._MDNS_ADDR , port = r ._MDNS_PORT ):
225226 """Sends an outgoing packet."""
226227 packet = out .packet ()
227228 if longest_packet [0 ] < len (packet ):
228229 longest_packet [0 ] = len (packet )
230+ longest_packet [1 ] = out
229231 old_send (out , addr = addr , port = port )
230232
231233 # monkey patch the zeroconf send
232- zeroconf .send = send
234+ zc .send = send
233235
234236 # create a bunch of servers
235237 type_ = "_my-service._tcp.local."
236238 server_count = 300
237239 records_per_server = 2
238240 for i in range (int (server_count / 10 )):
239- self .generate_many_hosts (zeroconf , type_ , 10 )
241+ self .generate_many_hosts (zc , type_ , 10 )
240242 sleep_count = 0
241- while sleep_count < 20 and server_count * records_per_server > len (
242- zeroconf .cache .entries_with_name (type_ )):
243+ while sleep_count < 100 and server_count * records_per_server > len (
244+ zc .cache .entries_with_name (type_ )):
243245 sleep_count += 1
244246 time .sleep (0.01 )
245247
@@ -248,13 +250,88 @@ def on_service_state_change(zeroconf, service_type, state_change, name):
248250 pass
249251
250252 # start a browser and run for a bit
251- browser = ServiceBrowser (zeroconf , type_ , [on_service_state_change ])
252- time .sleep (0.1 )
253+ browser = ServiceBrowser (zc , type_ , [on_service_state_change ])
254+ sleep_count = 0
255+ while sleep_count < 100 and \
256+ longest_packet [0 ] < r ._MAX_MSG_ABSOLUTE - 100 :
257+ sleep_count += 1
258+ time .sleep (0.1 )
259+
253260 browser .cancel ()
254- zeroconf .close ()
261+ time .sleep (0.5 )
262+
263+ import zeroconf
264+ zeroconf .log .debug ('sleep_count %d, sized %d' ,
265+ sleep_count , longest_packet [0 ])
255266
256267 # now the browser has sent at least one request, verify the size
257268 assert longest_packet [0 ] < r ._MAX_MSG_ABSOLUTE
269+ assert longest_packet [0 ] >= r ._MAX_MSG_ABSOLUTE - 100
270+
271+ # mock zeroconf's logger warning() and debug()
272+ from mock import patch
273+ patch_warn = patch ('zeroconf.log.warning' )
274+ patch_debug = patch ('zeroconf.log.debug' )
275+ mocked_log_warn = patch_warn .start ()
276+ mocked_log_debug = patch_debug .start ()
277+
278+ # now that we have a long packet in our possession, let's verify the
279+ # exception handling.
280+ out = longest_packet [1 ]
281+ out .data .append (b'\0 ' * 1000 )
282+
283+ # mock the zeroconf logger and check for the correct logging backoff
284+ call_counts = mocked_log_warn .call_count , mocked_log_debug .call_count
285+ # try to send an oversized packet
286+ zc .send (out )
287+ assert mocked_log_warn .call_count == call_counts [0 ] + 1
288+ assert mocked_log_debug .call_count == call_counts [0 ]
289+ zc .send (out )
290+ assert mocked_log_warn .call_count == call_counts [0 ] + 1
291+ assert mocked_log_debug .call_count == call_counts [0 ] + 1
292+
293+ # force a receive of an oversized packet
294+ packet = out .packet ()
295+ s = zc ._respond_sockets [0 ]
296+
297+ # mock the zeroconf logger and check for the correct logging backoff
298+ call_counts = mocked_log_warn .call_count , mocked_log_debug .call_count
299+ # force receive on oversized packet
300+ s .sendto (packet , 0 , (r ._MDNS_ADDR , r ._MDNS_PORT ))
301+ s .sendto (packet , 0 , (r ._MDNS_ADDR , r ._MDNS_PORT ))
302+ time .sleep (2.0 )
303+ zeroconf .log .debug ('warn %d debug %d was %s' ,
304+ mocked_log_warn .call_count ,
305+ mocked_log_debug .call_count ,
306+ call_counts )
307+ assert mocked_log_debug .call_count > call_counts [0 ]
308+
309+ # close our zeroconf which will close the sockets
310+ zc .close ()
311+
312+ # pop the big chunk off the end of the data and send on a closed socket
313+ out .data .pop ()
314+ zc ._GLOBAL_DONE = False
315+
316+ # mock the zeroconf logger and check for the correct logging backoff
317+ call_counts = mocked_log_warn .call_count , mocked_log_debug .call_count
318+ # send on a closed socket (force a socket error)
319+ zc .send (out )
320+ zeroconf .log .debug ('warn %d debug %d was %s' ,
321+ mocked_log_warn .call_count ,
322+ mocked_log_debug .call_count ,
323+ call_counts )
324+ assert mocked_log_warn .call_count > call_counts [0 ]
325+ assert mocked_log_debug .call_count > call_counts [0 ]
326+ zc .send (out )
327+ zeroconf .log .debug ('warn %d debug %d was %s' ,
328+ mocked_log_warn .call_count ,
329+ mocked_log_debug .call_count ,
330+ call_counts )
331+ assert mocked_log_debug .call_count > call_counts [0 ] + 2
332+
333+ mocked_log_warn .stop ()
334+ mocked_log_debug .stop ()
258335
259336 def generate_many_hosts (self , zc , type_ , number_hosts ):
260337 import random
0 commit comments