|
14 | 14 | import pytest |
15 | 15 |
|
16 | 16 | import zeroconf as r |
17 | | -from zeroconf import DNSPointer, DNSQuestion, const, current_time_millis |
| 17 | +from zeroconf import DNSPointer, DNSQuestion, const, current_time_millis, millis_to_seconds |
18 | 18 | import zeroconf._services.browser as _services_browser |
19 | 19 | from zeroconf import Zeroconf |
20 | 20 | from zeroconf._services import ServiceStateChange |
@@ -453,7 +453,11 @@ def send(out, addr=const._MDNS_ADDR, port=const._MDNS_PORT): |
453 | 453 | # patch the backoff limit to prevent test running forever |
454 | 454 | with unittest.mock.patch.object(zeroconf_browser, "async_send", send), unittest.mock.patch.object( |
455 | 455 | _services_browser, "current_time_millis", current_time_millis |
456 | | - ), unittest.mock.patch.object(_services_browser, "_BROWSER_BACKOFF_LIMIT", 10): |
| 456 | + ), unittest.mock.patch.object( |
| 457 | + _services_browser, "_BROWSER_BACKOFF_LIMIT", 10 |
| 458 | + ), unittest.mock.patch.object( |
| 459 | + _services_browser, "_FIRST_QUERY_DELAY_RANDOM_INTERVAL", (0, 0) |
| 460 | + ): |
457 | 461 | # dummy service callback |
458 | 462 | def on_service_state_change(zeroconf, service_type, state_change, name): |
459 | 463 | pass |
@@ -498,6 +502,44 @@ def on_service_state_change(zeroconf, service_type, state_change, name): |
498 | 502 | zeroconf_browser.close() |
499 | 503 |
|
500 | 504 |
|
| 505 | +def test_first_query_delay(): |
| 506 | + """Verify the first query is delayed. |
| 507 | +
|
| 508 | + https://datatracker.ietf.org/doc/html/rfc6762#section-5.2 |
| 509 | + """ |
| 510 | + type_ = "_http._tcp.local." |
| 511 | + zeroconf_browser = Zeroconf(interfaces=['127.0.0.1']) |
| 512 | + |
| 513 | + # we are going to patch the zeroconf send to check query transmission |
| 514 | + old_send = zeroconf_browser.async_send |
| 515 | + |
| 516 | + first_query_time = None |
| 517 | + |
| 518 | + def send(out, addr=const._MDNS_ADDR, port=const._MDNS_PORT): |
| 519 | + """Sends an outgoing packet.""" |
| 520 | + nonlocal first_query_time |
| 521 | + if first_query_time is None: |
| 522 | + first_query_time = current_time_millis() |
| 523 | + old_send(out, addr=addr, port=port) |
| 524 | + |
| 525 | + # patch the zeroconf send |
| 526 | + with unittest.mock.patch.object(zeroconf_browser, "async_send", send): |
| 527 | + # dummy service callback |
| 528 | + def on_service_state_change(zeroconf, service_type, state_change, name): |
| 529 | + pass |
| 530 | + |
| 531 | + start_time = current_time_millis() |
| 532 | + browser = ServiceBrowser(zeroconf_browser, type_, [on_service_state_change]) |
| 533 | + time.sleep(millis_to_seconds(_services_browser._FIRST_QUERY_DELAY_RANDOM_INTERVAL[1] + 5)) |
| 534 | + try: |
| 535 | + assert ( |
| 536 | + current_time_millis() - start_time > _services_browser._FIRST_QUERY_DELAY_RANDOM_INTERVAL[0] |
| 537 | + ) |
| 538 | + finally: |
| 539 | + browser.cancel() |
| 540 | + zeroconf_browser.close() |
| 541 | + |
| 542 | + |
501 | 543 | def test_integration(): |
502 | 544 | service_added = Event() |
503 | 545 | service_removed = Event() |
|
0 commit comments