mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 19:27:45 +00:00
Use fixtures for Network component tests (#135220)
This commit is contained in:
parent
63d294e58e
commit
3e716a1308
@ -1 +1,4 @@
|
||||
"""Tests for the Network Configuration integration."""
|
||||
|
||||
NO_LOOPBACK_IPADDR = "192.168.1.5"
|
||||
LOOPBACK_IPADDR = "127.0.0.1"
|
||||
|
@ -1,14 +1,51 @@
|
||||
"""Tests for the Network Configuration integration."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import _patch
|
||||
from unittest.mock import MagicMock, Mock, _patch, patch
|
||||
|
||||
import ifaddr
|
||||
import pytest
|
||||
|
||||
from . import LOOPBACK_IPADDR, NO_LOOPBACK_IPADDR
|
||||
|
||||
|
||||
def _generate_mock_adapters():
|
||||
mock_lo0 = Mock(spec=ifaddr.Adapter)
|
||||
mock_lo0.nice_name = "lo0"
|
||||
mock_lo0.ips = [ifaddr.IP(LOOPBACK_IPADDR, 8, "lo0")]
|
||||
mock_lo0.index = 0
|
||||
mock_eth0 = Mock(spec=ifaddr.Adapter)
|
||||
mock_eth0.nice_name = "eth0"
|
||||
mock_eth0.ips = [ifaddr.IP(("2001:db8::", 1, 1), 8, "eth0")]
|
||||
mock_eth0.index = 1
|
||||
mock_eth1 = Mock(spec=ifaddr.Adapter)
|
||||
mock_eth1.nice_name = "eth1"
|
||||
mock_eth1.ips = [ifaddr.IP(NO_LOOPBACK_IPADDR, 23, "eth1")]
|
||||
mock_eth1.index = 2
|
||||
mock_vtun0 = Mock(spec=ifaddr.Adapter)
|
||||
mock_vtun0.nice_name = "vtun0"
|
||||
mock_vtun0.ips = [ifaddr.IP("169.254.3.2", 16, "vtun0")]
|
||||
mock_vtun0.index = 3
|
||||
return [mock_eth0, mock_lo0, mock_eth1, mock_vtun0]
|
||||
|
||||
|
||||
def _mock_socket(sockname: list[str]) -> Generator[None]:
|
||||
"""Mock the network socket."""
|
||||
with patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=MagicMock(getsockname=Mock(return_value=sockname)),
|
||||
):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_network():
|
||||
def mock_network() -> Generator[None]:
|
||||
"""Override mock of network util's async_get_adapters."""
|
||||
with patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=_generate_mock_adapters(),
|
||||
):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
@ -19,3 +56,21 @@ def override_mock_get_source_ip(
|
||||
mock_get_source_ip.stop()
|
||||
yield
|
||||
mock_get_source_ip.start()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_socket(request: pytest.FixtureRequest) -> Generator[None]:
|
||||
"""Mock the network socket."""
|
||||
yield from _mock_socket(request.param)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_socket_loopback() -> Generator[None]:
|
||||
"""Mock the network socket with loopback address."""
|
||||
yield from _mock_socket([LOOPBACK_IPADDR])
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_socket_no_loopback() -> Generator[None]:
|
||||
"""Mock the network socket with loopback address."""
|
||||
yield from _mock_socket([NO_LOOPBACK_IPADDR])
|
||||
|
@ -4,7 +4,6 @@ from ipaddress import IPv4Address
|
||||
from typing import Any
|
||||
from unittest.mock import MagicMock, Mock, patch
|
||||
|
||||
import ifaddr
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import network
|
||||
@ -20,17 +19,10 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import LOOPBACK_IPADDR, NO_LOOPBACK_IPADDR
|
||||
|
||||
from tests.typing import WebSocketGenerator
|
||||
|
||||
_NO_LOOPBACK_IPADDR = "192.168.1.5"
|
||||
_LOOPBACK_IPADDR = "127.0.0.1"
|
||||
|
||||
|
||||
def _mock_socket(sockname):
|
||||
mock_socket = MagicMock()
|
||||
mock_socket.getsockname = Mock(return_value=sockname)
|
||||
return mock_socket
|
||||
|
||||
|
||||
def _mock_cond_socket(sockname):
|
||||
class CondMockSock(MagicMock):
|
||||
@ -54,42 +46,13 @@ def _mock_socket_exception(exc):
|
||||
return mock_socket
|
||||
|
||||
|
||||
def _generate_mock_adapters():
|
||||
mock_lo0 = Mock(spec=ifaddr.Adapter)
|
||||
mock_lo0.nice_name = "lo0"
|
||||
mock_lo0.ips = [ifaddr.IP("127.0.0.1", 8, "lo0")]
|
||||
mock_lo0.index = 0
|
||||
mock_eth0 = Mock(spec=ifaddr.Adapter)
|
||||
mock_eth0.nice_name = "eth0"
|
||||
mock_eth0.ips = [ifaddr.IP(("2001:db8::", 1, 1), 8, "eth0")]
|
||||
mock_eth0.index = 1
|
||||
mock_eth1 = Mock(spec=ifaddr.Adapter)
|
||||
mock_eth1.nice_name = "eth1"
|
||||
mock_eth1.ips = [ifaddr.IP("192.168.1.5", 23, "eth1")]
|
||||
mock_eth1.index = 2
|
||||
mock_vtun0 = Mock(spec=ifaddr.Adapter)
|
||||
mock_vtun0.nice_name = "vtun0"
|
||||
mock_vtun0.ips = [ifaddr.IP("169.254.3.2", 16, "vtun0")]
|
||||
mock_vtun0.index = 3
|
||||
return [mock_eth0, mock_lo0, mock_eth1, mock_vtun0]
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_socket_no_loopback")
|
||||
async def test_async_detect_interfaces_setting_non_loopback_route(
|
||||
hass: HomeAssistant, hass_storage: dict[str, Any]
|
||||
) -> None:
|
||||
"""Test without default interface config and the route returns a non-loopback address."""
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_socket([_NO_LOOPBACK_IPADDR]),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=_generate_mock_adapters(),
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
network_obj = hass.data[DOMAIN]
|
||||
assert network_obj.configured_adapters == []
|
||||
@ -141,22 +104,13 @@ async def test_async_detect_interfaces_setting_non_loopback_route(
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_socket_loopback")
|
||||
async def test_async_detect_interfaces_setting_loopback_route(
|
||||
hass: HomeAssistant, hass_storage: dict[str, Any]
|
||||
) -> None:
|
||||
"""Test without default interface config and the route returns a loopback address."""
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_socket([_LOOPBACK_IPADDR]),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=_generate_mock_adapters(),
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
network_obj = hass.data[DOMAIN]
|
||||
assert network_obj.configured_adapters == []
|
||||
@ -207,22 +161,14 @@ async def test_async_detect_interfaces_setting_loopback_route(
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_socket", [[]], indirect=True)
|
||||
@pytest.mark.usefixtures("mock_socket")
|
||||
async def test_async_detect_interfaces_setting_empty_route(
|
||||
hass: HomeAssistant, hass_storage: dict[str, Any]
|
||||
) -> None:
|
||||
"""Test without default interface config and the route returns nothing."""
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_socket([]),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=_generate_mock_adapters(),
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
network_obj = hass.data[DOMAIN]
|
||||
assert network_obj.configured_adapters == []
|
||||
@ -277,15 +223,9 @@ async def test_async_detect_interfaces_setting_exception(
|
||||
hass: HomeAssistant, hass_storage: dict[str, Any]
|
||||
) -> None:
|
||||
"""Test without default interface config and the route throws an exception."""
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_socket_exception(AttributeError),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=_generate_mock_adapters(),
|
||||
),
|
||||
with patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_socket_exception(AttributeError),
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
@ -339,6 +279,7 @@ async def test_async_detect_interfaces_setting_exception(
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_socket_no_loopback")
|
||||
async def test_interfaces_configured_from_storage(
|
||||
hass: HomeAssistant, hass_storage: dict[str, Any]
|
||||
) -> None:
|
||||
@ -348,18 +289,9 @@ async def test_interfaces_configured_from_storage(
|
||||
"key": STORAGE_KEY,
|
||||
"data": {ATTR_CONFIGURED_ADAPTERS: ["eth0", "eth1", "vtun0"]},
|
||||
}
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_socket([_NO_LOOPBACK_IPADDR]),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=_generate_mock_adapters(),
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
network_obj = hass.data[DOMAIN]
|
||||
assert network_obj.configured_adapters == ["eth0", "eth1", "vtun0"]
|
||||
@ -422,15 +354,9 @@ async def test_interfaces_configured_from_storage_websocket_update(
|
||||
"key": STORAGE_KEY,
|
||||
"data": {ATTR_CONFIGURED_ADAPTERS: ["eth0", "eth1", "vtun0"]},
|
||||
}
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_socket([_NO_LOOPBACK_IPADDR]),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=_generate_mock_adapters(),
|
||||
),
|
||||
with patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=MagicMock(getsockname=Mock(return_value=[NO_LOOPBACK_IPADDR])),
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
@ -546,6 +472,7 @@ async def test_interfaces_configured_from_storage_websocket_update(
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_socket_no_loopback")
|
||||
async def test_async_get_source_ip_matching_interface(
|
||||
hass: HomeAssistant, hass_storage: dict[str, Any]
|
||||
) -> None:
|
||||
@ -556,22 +483,13 @@ async def test_async_get_source_ip_matching_interface(
|
||||
"data": {ATTR_CONFIGURED_ADAPTERS: ["eth1"]},
|
||||
}
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=_generate_mock_adapters(),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_socket(["192.168.1.5"]),
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert await network.async_get_source_ip(hass, MDNS_TARGET_IP) == "192.168.1.5"
|
||||
assert await network.async_get_source_ip(hass, MDNS_TARGET_IP) == NO_LOOPBACK_IPADDR
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_socket_no_loopback")
|
||||
async def test_async_get_source_ip_interface_not_match(
|
||||
hass: HomeAssistant, hass_storage: dict[str, Any]
|
||||
) -> None:
|
||||
@ -582,22 +500,14 @@ async def test_async_get_source_ip_interface_not_match(
|
||||
"data": {ATTR_CONFIGURED_ADAPTERS: ["vtun0"]},
|
||||
}
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=_generate_mock_adapters(),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_socket(["192.168.1.5"]),
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert await network.async_get_source_ip(hass, MDNS_TARGET_IP) == "169.254.3.2"
|
||||
assert await network.async_get_source_ip(hass, MDNS_TARGET_IP) == "169.254.3.2"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_socket", [[None]], indirect=True)
|
||||
@pytest.mark.usefixtures("mock_socket")
|
||||
async def test_async_get_source_ip_cannot_determine_target(
|
||||
hass: HomeAssistant, hass_storage: dict[str, Any]
|
||||
) -> None:
|
||||
@ -608,22 +518,13 @@ async def test_async_get_source_ip_cannot_determine_target(
|
||||
"data": {ATTR_CONFIGURED_ADAPTERS: ["eth1"]},
|
||||
}
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=_generate_mock_adapters(),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_socket([None]),
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert await network.async_get_source_ip(hass, MDNS_TARGET_IP) == "192.168.1.5"
|
||||
assert await network.async_get_source_ip(hass, MDNS_TARGET_IP) == NO_LOOPBACK_IPADDR
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_socket_no_loopback")
|
||||
async def test_async_get_ipv4_broadcast_addresses_default(
|
||||
hass: HomeAssistant, hass_storage: dict[str, Any]
|
||||
) -> None:
|
||||
@ -634,24 +535,15 @@ async def test_async_get_ipv4_broadcast_addresses_default(
|
||||
"data": {ATTR_CONFIGURED_ADAPTERS: ["eth1"]},
|
||||
}
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_socket(["192.168.1.5"]),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=_generate_mock_adapters(),
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert await network.async_get_ipv4_broadcast_addresses(hass) == {
|
||||
IPv4Address("255.255.255.255")
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_socket_loopback")
|
||||
async def test_async_get_ipv4_broadcast_addresses_multiple(
|
||||
hass: HomeAssistant, hass_storage: dict[str, Any]
|
||||
) -> None:
|
||||
@ -662,18 +554,8 @@ async def test_async_get_ipv4_broadcast_addresses_multiple(
|
||||
"data": {ATTR_CONFIGURED_ADAPTERS: ["eth1", "vtun0"]},
|
||||
}
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_socket([_LOOPBACK_IPADDR]),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=_generate_mock_adapters(),
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert await network.async_get_ipv4_broadcast_addresses(hass) == {
|
||||
IPv4Address("255.255.255.255"),
|
||||
@ -682,6 +564,7 @@ async def test_async_get_ipv4_broadcast_addresses_multiple(
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_socket_no_loopback")
|
||||
async def test_async_get_source_ip_no_enabled_addresses(
|
||||
hass: HomeAssistant, hass_storage: dict[str, Any], caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
@ -692,24 +575,23 @@ async def test_async_get_source_ip_no_enabled_addresses(
|
||||
"data": {ATTR_CONFIGURED_ADAPTERS: ["eth1"]},
|
||||
}
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=[],
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_socket(["192.168.1.5"]),
|
||||
),
|
||||
with patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=[],
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert await network.async_get_source_ip(hass, MDNS_TARGET_IP) == "192.168.1.5"
|
||||
assert (
|
||||
await network.async_get_source_ip(hass, MDNS_TARGET_IP)
|
||||
== NO_LOOPBACK_IPADDR
|
||||
)
|
||||
|
||||
assert "source address detection may be inaccurate" in caplog.text
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_socket", [[None]], indirect=True)
|
||||
@pytest.mark.usefixtures("mock_socket")
|
||||
async def test_async_get_source_ip_cannot_be_determined_and_no_enabled_addresses(
|
||||
hass: HomeAssistant, hass_storage: dict[str, Any], caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
@ -720,15 +602,9 @@ async def test_async_get_source_ip_cannot_be_determined_and_no_enabled_addresses
|
||||
"data": {ATTR_CONFIGURED_ADAPTERS: ["eth1"]},
|
||||
}
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=[],
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_socket([None]),
|
||||
),
|
||||
with patch(
|
||||
"homeassistant.components.network.util.ifaddr.get_adapters",
|
||||
return_value=[],
|
||||
):
|
||||
assert not await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
@ -753,7 +629,7 @@ async def test_async_get_source_ip_no_ip_loopback(
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.network.util.socket.socket",
|
||||
return_value=_mock_cond_socket(_LOOPBACK_IPADDR),
|
||||
return_value=_mock_cond_socket(LOOPBACK_IPADDR),
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
|
Loading…
x
Reference in New Issue
Block a user