Ensure zeroconf does not generate config flows when matching attributes are missing (#50208)
If macaddress, name, or manufacturer were missing from the discovery info, the matcher would accept instead of reject.pull/50506/head
parent
c037ebb27c
commit
dd3965e4e2
|
@ -348,32 +348,29 @@ async def _async_start_zeroconf_browser(
|
|||
|
||||
# Not all homekit types are currently used for discovery
|
||||
# so not all service type exist in zeroconf_types
|
||||
for entry in zeroconf_types.get(service_type, []):
|
||||
if len(entry) > 1:
|
||||
if (
|
||||
uppercase_mac is not None
|
||||
and "macaddress" in entry
|
||||
and not fnmatch.fnmatch(uppercase_mac, entry["macaddress"])
|
||||
for matcher in zeroconf_types.get(service_type, []):
|
||||
if len(matcher) > 1:
|
||||
if "macaddress" in matcher and (
|
||||
uppercase_mac is None
|
||||
or not fnmatch.fnmatch(uppercase_mac, matcher["macaddress"])
|
||||
):
|
||||
continue
|
||||
if (
|
||||
lowercase_name is not None
|
||||
and "name" in entry
|
||||
and not fnmatch.fnmatch(lowercase_name, entry["name"])
|
||||
if "name" in matcher and (
|
||||
lowercase_name is None
|
||||
or not fnmatch.fnmatch(lowercase_name, matcher["name"])
|
||||
):
|
||||
continue
|
||||
if (
|
||||
lowercase_manufacturer is not None
|
||||
and "manufacturer" in entry
|
||||
and not fnmatch.fnmatch(
|
||||
lowercase_manufacturer, entry["manufacturer"]
|
||||
if "manufacturer" in matcher and (
|
||||
lowercase_manufacturer is None
|
||||
or not fnmatch.fnmatch(
|
||||
lowercase_manufacturer, matcher["manufacturer"]
|
||||
)
|
||||
):
|
||||
continue
|
||||
|
||||
hass.add_job(
|
||||
hass.config_entries.flow.async_init(
|
||||
entry["domain"], context={"source": DOMAIN}, data=info
|
||||
matcher["domain"], context={"source": DOMAIN}, data=info
|
||||
) # type: ignore
|
||||
)
|
||||
|
||||
|
|
|
@ -346,6 +346,38 @@ async def test_zeroconf_match_manufacturer(hass, mock_zeroconf):
|
|||
assert mock_config_flow.mock_calls[0][1][0] == "samsungtv"
|
||||
|
||||
|
||||
async def test_zeroconf_match_manufacturer_not_present(hass, mock_zeroconf):
|
||||
"""Test matchers reject when a property is missing."""
|
||||
|
||||
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(
|
||||
"aa:bb:cc:dd:ee:ff"
|
||||
)
|
||||
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_zeroconf_no_match(hass, mock_zeroconf):
|
||||
"""Test configured options for a device are loaded via config entry."""
|
||||
|
||||
|
|
Loading…
Reference in New Issue