* Factor out _is_dmr_device function * Use DMR device's MAC to match existing config entries Some DMR devices change their every time they boot, against the DMR specs. Try to match such devices to existing config entries by using their MAC addresses. * Add DMR device's MAC as a device_registry connection * Use doc-only IPs (RFC5737) for dlna_dmr tests
125 lines
4.8 KiB
Python
125 lines
4.8 KiB
Python
"""Tests for the DLNA DMR data module."""
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Iterable
|
|
from unittest.mock import ANY, Mock, patch
|
|
|
|
from async_upnp_client.aiohttp import AiohttpNotifyServer
|
|
from async_upnp_client.event_handler import UpnpEventHandler
|
|
import pytest
|
|
|
|
from homeassistant.components.dlna_dmr.const import DOMAIN
|
|
from homeassistant.components.dlna_dmr.data import EventListenAddr, get_domain_data
|
|
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
|
from homeassistant.core import Event, HomeAssistant
|
|
|
|
|
|
@pytest.fixture
|
|
def aiohttp_notify_servers_mock() -> Iterable[Mock]:
|
|
"""Construct mock AiohttpNotifyServer on demand, eliminating network use.
|
|
|
|
This fixture provides a list of the constructed servers.
|
|
"""
|
|
with patch(
|
|
"homeassistant.components.dlna_dmr.data.AiohttpNotifyServer"
|
|
) as mock_constructor:
|
|
servers = []
|
|
|
|
def make_server(*_args, **_kwargs):
|
|
server = Mock(spec=AiohttpNotifyServer)
|
|
servers.append(server)
|
|
server.event_handler = Mock(spec=UpnpEventHandler)
|
|
return server
|
|
|
|
mock_constructor.side_effect = make_server
|
|
|
|
yield mock_constructor
|
|
|
|
# Every server must be stopped if it was started
|
|
for server in servers:
|
|
assert (
|
|
server.async_start_server.call_count
|
|
== server.async_stop_server.call_count
|
|
)
|
|
|
|
|
|
async def test_get_domain_data(hass: HomeAssistant) -> None:
|
|
"""Test the get_domain_data function returns the same data every time."""
|
|
assert DOMAIN not in hass.data
|
|
domain_data = get_domain_data(hass)
|
|
assert domain_data is not None
|
|
assert get_domain_data(hass) is domain_data
|
|
|
|
|
|
async def test_event_notifier(
|
|
hass: HomeAssistant, aiohttp_notify_servers_mock: Mock
|
|
) -> None:
|
|
"""Test getting and releasing event notifiers."""
|
|
domain_data = get_domain_data(hass)
|
|
|
|
listen_addr = EventListenAddr(None, 0, None)
|
|
event_notifier = await domain_data.async_get_event_notifier(listen_addr, hass)
|
|
assert event_notifier is not None
|
|
|
|
# Check that the parameters were passed through to the AiohttpNotifyServer
|
|
aiohttp_notify_servers_mock.assert_called_with(
|
|
requester=ANY, source=("0.0.0.0", 0), callback_url=None, loop=ANY
|
|
)
|
|
|
|
# Same address should give same notifier
|
|
listen_addr_2 = EventListenAddr(None, 0, None)
|
|
event_notifier_2 = await domain_data.async_get_event_notifier(listen_addr_2, hass)
|
|
assert event_notifier_2 is event_notifier
|
|
|
|
# Different address should give different notifier
|
|
listen_addr_3 = EventListenAddr(
|
|
"198.51.100.4", 9999, "http://198.51.100.4:9999/notify"
|
|
)
|
|
event_notifier_3 = await domain_data.async_get_event_notifier(listen_addr_3, hass)
|
|
assert event_notifier_3 is not None
|
|
assert event_notifier_3 is not event_notifier
|
|
|
|
# Check that the parameters were passed through to the AiohttpNotifyServer
|
|
aiohttp_notify_servers_mock.assert_called_with(
|
|
requester=ANY,
|
|
source=("198.51.100.4", 9999),
|
|
callback_url="http://198.51.100.4:9999/notify",
|
|
loop=ANY,
|
|
)
|
|
|
|
# There should be 2 notifiers total, one with 2 references, and a stop callback
|
|
assert set(domain_data.event_notifiers.keys()) == {listen_addr, listen_addr_3}
|
|
assert domain_data.event_notifier_refs == {listen_addr: 2, listen_addr_3: 1}
|
|
assert domain_data.stop_listener_remove is not None
|
|
|
|
# Releasing notifiers should delete them when they have not more references
|
|
await domain_data.async_release_event_notifier(listen_addr)
|
|
assert set(domain_data.event_notifiers.keys()) == {listen_addr, listen_addr_3}
|
|
assert domain_data.event_notifier_refs == {listen_addr: 1, listen_addr_3: 1}
|
|
assert domain_data.stop_listener_remove is not None
|
|
|
|
await domain_data.async_release_event_notifier(listen_addr)
|
|
assert set(domain_data.event_notifiers.keys()) == {listen_addr_3}
|
|
assert domain_data.event_notifier_refs == {listen_addr: 0, listen_addr_3: 1}
|
|
assert domain_data.stop_listener_remove is not None
|
|
|
|
await domain_data.async_release_event_notifier(listen_addr_3)
|
|
assert set(domain_data.event_notifiers.keys()) == set()
|
|
assert domain_data.event_notifier_refs == {listen_addr: 0, listen_addr_3: 0}
|
|
assert domain_data.stop_listener_remove is None
|
|
|
|
|
|
async def test_cleanup_event_notifiers(
|
|
hass: HomeAssistant, aiohttp_notify_servers_mock: Mock
|
|
) -> None:
|
|
"""Test cleanup function clears all event notifiers."""
|
|
domain_data = get_domain_data(hass)
|
|
await domain_data.async_get_event_notifier(EventListenAddr(None, 0, None), hass)
|
|
await domain_data.async_get_event_notifier(
|
|
EventListenAddr(None, 0, "different"), hass
|
|
)
|
|
|
|
await domain_data.async_cleanup_event_notifiers(Event(EVENT_HOMEASSISTANT_STOP))
|
|
|
|
assert not domain_data.event_notifiers
|
|
assert not domain_data.event_notifier_refs
|