Add manufacturer matching support to zeroconf (#48810)

We plan on matching with _airplay which means we need
to able to limit to specific manufacturers to avoid
generating flows for integrations with the wrong
manufacturer
This commit is contained in:
J. Nick Koston
2021-04-08 09:03:10 -10:00
committed by GitHub
parent c2d98f1905
commit 493bd4cdca
2 changed files with 99 additions and 1 deletions

View File

@@ -104,6 +104,24 @@ def get_zeroconf_info_mock(macaddress):
return mock_zc_info
def get_zeroconf_info_mock_manufacturer(manufacturer):
"""Return info for get_service_info for an zeroconf device."""
def mock_zc_info(service_type, name):
return ServiceInfo(
service_type,
name,
addresses=[b"\n\x00\x00\x14"],
port=80,
weight=0,
priority=0,
server="name.local.",
properties={b"manufacturer": manufacturer.encode()},
)
return mock_zc_info
async def test_setup(hass, mock_zeroconf):
"""Test configured options for a device are loaded via config entry."""
with patch.object(
@@ -237,7 +255,7 @@ async def test_service_with_invalid_name(hass, mock_zeroconf, caplog):
assert "Failed to get info for device name" in caplog.text
async def test_zeroconf_match(hass, mock_zeroconf):
async def test_zeroconf_match_macaddress(hass, mock_zeroconf):
"""Test configured options for a device are loaded via config entry."""
def http_only_service_update_mock(zeroconf, services, handlers):
@@ -274,6 +292,39 @@ async def test_zeroconf_match(hass, mock_zeroconf):
assert mock_config_flow.mock_calls[0][1][0] == "shelly"
async def test_zeroconf_match_manufacturer(hass, mock_zeroconf):
"""Test configured options for a device are loaded via config entry."""
def http_only_service_update_mock(zeroconf, services, handlers):
"""Call service update handler."""
handlers[0](
zeroconf,
"_airplay._tcp.local.",
"s1000._airplay._tcp.local.",
ServiceStateChange.Added,
)
with patch.dict(
zc_gen.ZEROCONF,
{"_airplay._tcp.local.": [{"domain": "samsungtv", "manufacturer": "samsung*"}]},
clear=True,
), patch.object(
hass.config_entries.flow, "async_init"
) as mock_config_flow, patch.object(
zeroconf, "HaServiceBrowser", side_effect=http_only_service_update_mock
) as mock_service_browser:
mock_zeroconf.get_service_info.side_effect = (
get_zeroconf_info_mock_manufacturer("Samsung Electronics")
)
assert await async_setup_component(hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {}})
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
await hass.async_block_till_done()
assert len(mock_service_browser.mock_calls) == 1
assert len(mock_config_flow.mock_calls) == 1
assert mock_config_flow.mock_calls[0][1][0] == "samsungtv"
async def test_zeroconf_no_match(hass, mock_zeroconf):
"""Test configured options for a device are loaded via config entry."""
@@ -306,6 +357,38 @@ async def test_zeroconf_no_match(hass, mock_zeroconf):
assert len(mock_config_flow.mock_calls) == 0
async def test_zeroconf_no_match_manufacturer(hass, mock_zeroconf):
"""Test configured options for a device are loaded via config entry."""
def http_only_service_update_mock(zeroconf, services, handlers):
"""Call service update handler."""
handlers[0](
zeroconf,
"_airplay._tcp.local.",
"s1000._airplay._tcp.local.",
ServiceStateChange.Added,
)
with patch.dict(
zc_gen.ZEROCONF,
{"_airplay._tcp.local.": [{"domain": "samsungtv", "manufacturer": "samsung*"}]},
clear=True,
), patch.object(
hass.config_entries.flow, "async_init"
) as mock_config_flow, patch.object(
zeroconf, "HaServiceBrowser", side_effect=http_only_service_update_mock
) as mock_service_browser:
mock_zeroconf.get_service_info.side_effect = (
get_zeroconf_info_mock_manufacturer("Not Samsung Electronics")
)
assert await async_setup_component(hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {}})
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
await hass.async_block_till_done()
assert len(mock_service_browser.mock_calls) == 1
assert len(mock_config_flow.mock_calls) == 0
async def test_homekit_match_partial_space(hass, mock_zeroconf):
"""Test configured options for a device are loaded via config entry."""
with patch.dict(