mirror of
https://github.com/home-assistant/core.git
synced 2025-05-13 18:39:14 +00:00

* Add WebSocket API to zeroconf to observe discovery * Add WebSocket API to zeroconf to observe discovery * increase timeout * cover * cover * cover * cover * cover * cover * fix lasting side effects * cleanup merge * format
195 lines
5.8 KiB
Python
195 lines
5.8 KiB
Python
"""The tests for the zeroconf WebSocket API."""
|
|
|
|
import asyncio
|
|
import socket
|
|
from unittest.mock import patch
|
|
|
|
from zeroconf import (
|
|
DNSAddress,
|
|
DNSPointer,
|
|
DNSService,
|
|
DNSText,
|
|
RecordUpdate,
|
|
const,
|
|
current_time_millis,
|
|
)
|
|
|
|
from homeassistant.components.zeroconf import DOMAIN, async_get_async_instance
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.generated import zeroconf as zc_gen
|
|
from homeassistant.setup import async_setup_component
|
|
|
|
from tests.typing import WebSocketGenerator
|
|
|
|
|
|
async def test_subscribe_discovery(
|
|
hass: HomeAssistant,
|
|
hass_ws_client: WebSocketGenerator,
|
|
) -> None:
|
|
"""Test zeroconf subscribe_discovery."""
|
|
instance = await async_get_async_instance(hass)
|
|
instance.zeroconf.cache.async_add_records(
|
|
[
|
|
DNSPointer(
|
|
"_fakeservice._tcp.local.",
|
|
const._TYPE_PTR,
|
|
const._CLASS_IN,
|
|
const._DNS_OTHER_TTL,
|
|
"wrong._wrongservice._tcp.local.",
|
|
),
|
|
DNSPointer(
|
|
"_fakeservice._tcp.local.",
|
|
const._TYPE_PTR,
|
|
const._CLASS_IN,
|
|
const._DNS_OTHER_TTL,
|
|
"foo2._fakeservice._tcp.local.",
|
|
),
|
|
DNSService(
|
|
"foo2._fakeservice._tcp.local.",
|
|
const._TYPE_SRV,
|
|
const._CLASS_IN,
|
|
const._DNS_OTHER_TTL,
|
|
0,
|
|
0,
|
|
1234,
|
|
"foo2.local.",
|
|
),
|
|
DNSAddress(
|
|
"foo2.local.",
|
|
const._TYPE_A,
|
|
const._CLASS_IN,
|
|
const._DNS_HOST_TTL,
|
|
socket.inet_aton("127.0.0.1"),
|
|
),
|
|
DNSText(
|
|
"foo2.local.",
|
|
const._TYPE_TXT,
|
|
const._CLASS_IN,
|
|
const._DNS_HOST_TTL,
|
|
b"\x13md=HASS Bridge W9DN\x06pv=1.0\x14id=11:8E:DB:5B:5C:C5"
|
|
b"\x05c#=12\x04s#=1",
|
|
),
|
|
DNSPointer(
|
|
"_fakeservice._tcp.local.",
|
|
const._TYPE_PTR,
|
|
const._CLASS_IN,
|
|
const._DNS_OTHER_TTL,
|
|
"foo3._fakeservice._tcp.local.",
|
|
),
|
|
DNSService(
|
|
"foo3._fakeservice._tcp.local.",
|
|
const._TYPE_SRV,
|
|
const._CLASS_IN,
|
|
const._DNS_OTHER_TTL,
|
|
0,
|
|
0,
|
|
1234,
|
|
"foo3.local.",
|
|
),
|
|
DNSText(
|
|
"foo3.local.",
|
|
const._TYPE_TXT,
|
|
const._CLASS_IN,
|
|
const._DNS_HOST_TTL,
|
|
b"\x13md=HASS Bridge W9DN\x06pv=1.0\x14id=11:8E:DB:5B:5C:C5"
|
|
b"\x05c#=12\x04s#=1",
|
|
),
|
|
]
|
|
)
|
|
with patch.dict(
|
|
zc_gen.ZEROCONF,
|
|
{"_fakeservice._tcp.local.": []},
|
|
clear=True,
|
|
):
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
|
await hass.async_block_till_done()
|
|
client = await hass_ws_client()
|
|
await client.send_json(
|
|
{
|
|
"id": 1,
|
|
"type": "zeroconf/subscribe_discovery",
|
|
}
|
|
)
|
|
async with asyncio.timeout(1):
|
|
response = await client.receive_json()
|
|
assert response["success"]
|
|
|
|
async with asyncio.timeout(1):
|
|
response = await client.receive_json()
|
|
assert response["event"] == {
|
|
"add": [
|
|
{
|
|
"ip_addresses": ["127.0.0.1"],
|
|
"name": "foo2._fakeservice._tcp.local.",
|
|
"port": 1234,
|
|
"properties": {},
|
|
"type": "_fakeservice._tcp.local.",
|
|
}
|
|
]
|
|
}
|
|
|
|
# now late inject the address record
|
|
records = [
|
|
DNSAddress(
|
|
"foo3.local.",
|
|
const._TYPE_A,
|
|
const._CLASS_IN,
|
|
const._DNS_HOST_TTL,
|
|
socket.inet_aton("127.0.0.1"),
|
|
),
|
|
]
|
|
instance.zeroconf.cache.async_add_records(records)
|
|
instance.zeroconf.record_manager.async_updates(
|
|
current_time_millis(),
|
|
[RecordUpdate(record, None) for record in records],
|
|
)
|
|
# Now for the add
|
|
async with asyncio.timeout(1):
|
|
response = await client.receive_json()
|
|
assert response["event"] == {
|
|
"add": [
|
|
{
|
|
"ip_addresses": ["127.0.0.1"],
|
|
"name": "foo3._fakeservice._tcp.local.",
|
|
"port": 1234,
|
|
"properties": {},
|
|
"type": "_fakeservice._tcp.local.",
|
|
}
|
|
]
|
|
}
|
|
# Now for the update
|
|
async with asyncio.timeout(1):
|
|
response = await client.receive_json()
|
|
assert response["event"] == {
|
|
"add": [
|
|
{
|
|
"ip_addresses": ["127.0.0.1"],
|
|
"name": "foo3._fakeservice._tcp.local.",
|
|
"port": 1234,
|
|
"properties": {},
|
|
"type": "_fakeservice._tcp.local.",
|
|
}
|
|
]
|
|
}
|
|
|
|
# now move time forward and remove the record
|
|
future = current_time_millis() + (4500 * 1000)
|
|
records = instance.zeroconf.cache.async_expire(future)
|
|
record_updates = [RecordUpdate(record, record) for record in records]
|
|
instance.zeroconf.record_manager.async_updates(future, record_updates)
|
|
instance.zeroconf.record_manager.async_updates_complete(True)
|
|
|
|
removes: set[str] = set()
|
|
for _ in range(3):
|
|
async with asyncio.timeout(1):
|
|
response = await client.receive_json()
|
|
assert "remove" in response["event"]
|
|
removes.add(next(iter(response["event"]["remove"]))["name"])
|
|
|
|
assert len(removes) == 3
|
|
assert removes == {
|
|
"foo2._fakeservice._tcp.local.",
|
|
"foo3._fakeservice._tcp.local.",
|
|
"wrong._wrongservice._tcp.local.",
|
|
}
|