Skip to content

Commit dcf18c8

Browse files
authored
Add test coverage to ensure ServiceBrowser ignores unrelated updates (#866)
1 parent 6ef65fc commit dcf18c8

1 file changed

Lines changed: 91 additions & 1 deletion

File tree

tests/test_aio.py

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,16 @@
1515
import pytest
1616

1717
from zeroconf.aio import AsyncServiceBrowser, AsyncServiceInfo, AsyncZeroconf, AsyncZeroconfServiceTypes
18-
from zeroconf import DNSIncoming, ServiceStateChange, Zeroconf, const
18+
from zeroconf import (
19+
DNSIncoming,
20+
DNSOutgoing,
21+
DNSPointer,
22+
DNSService,
23+
DNSAddress,
24+
ServiceStateChange,
25+
Zeroconf,
26+
const,
27+
)
1928
from zeroconf.const import _LISTENER_TIME
2029
from zeroconf._exceptions import BadTypeInNameException, NonUniqueNameException, ServiceNameAlreadyRegistered
2130
from zeroconf._services import ServiceListener
@@ -823,3 +832,84 @@ def send(out, addr=const._MDNS_ADDR, port=const._MDNS_PORT):
823832
assert second_outgoing.questions[0].unicast == False
824833
finally:
825834
await aiozc.async_close()
835+
836+
837+
@pytest.mark.asyncio
838+
async def test_service_browser_ignores_unrelated_updates():
839+
"""Test that the ServiceBrowser ignores unrelated updates."""
840+
841+
# instantiate a zeroconf instance
842+
aiozc = AsyncZeroconf(interfaces=['127.0.0.1'])
843+
zc = aiozc.zeroconf
844+
type_ = "_veryuniqueone._tcp.local."
845+
registration_name = "xxxyyy.%s" % type_
846+
callbacks = []
847+
848+
class MyServiceListener(ServiceListener):
849+
def add_service(self, zc, type_, name) -> None:
850+
nonlocal callbacks
851+
if name == registration_name:
852+
callbacks.append(("add", type_, name))
853+
854+
def remove_service(self, zc, type_, name) -> None:
855+
nonlocal callbacks
856+
if name == registration_name:
857+
callbacks.append(("remove", type_, name))
858+
859+
def update_service(self, zc, type_, name) -> None:
860+
nonlocal callbacks
861+
if name == registration_name:
862+
callbacks.append(("update", type_, name))
863+
864+
listener = MyServiceListener()
865+
866+
desc = {'path': '/~paulsm/'}
867+
address_parsed = "10.0.1.2"
868+
address = socket.inet_aton(address_parsed)
869+
info = ServiceInfo(type_, registration_name, 80, 0, 0, desc, "ash-2.local.", addresses=[address])
870+
zc.cache.async_add_records(
871+
[info.dns_pointer(), info.dns_service(), *info.dns_addresses(), info.dns_text()]
872+
)
873+
874+
browser = AsyncServiceBrowser(zc, type_, None, listener)
875+
876+
generated = DNSOutgoing(const._FLAGS_QR_RESPONSE)
877+
generated.add_answer_at_time(
878+
DNSPointer(
879+
"_unrelated._tcp.local.",
880+
const._TYPE_PTR,
881+
const._CLASS_IN,
882+
const._DNS_OTHER_TTL,
883+
"zoom._unrelated._tcp.local.",
884+
),
885+
0,
886+
)
887+
generated.add_answer_at_time(
888+
DNSAddress(
889+
"zoom._unrelated._tcp.local.", const._TYPE_A, const._CLASS_IN, const._DNS_HOST_TTL, b"1234"
890+
),
891+
0,
892+
)
893+
generated.add_answer_at_time(
894+
DNSService(
895+
"zoom._unrelated._tcp.local.",
896+
const._TYPE_SRV,
897+
const._CLASS_IN,
898+
const._DNS_HOST_TTL,
899+
0,
900+
0,
901+
81,
902+
'unrelated.local.',
903+
),
904+
0,
905+
)
906+
907+
zc.handle_response(DNSIncoming(generated.packets()[0]))
908+
909+
await browser.async_cancel()
910+
await asyncio.sleep(0)
911+
912+
assert callbacks == [
913+
('add', type_, registration_name),
914+
]
915+
await aiozc.async_close()

0 commit comments

Comments
 (0)