"""Test NetwrokInterface.""" from ipaddress import IPv4Address, IPv4Interface, IPv6Address, IPv6Interface from dbus_fast.aio.message_bus import MessageBus import pytest from supervisor.dbus.const import DeviceType, InterfaceMethod from supervisor.dbus.network import NetworkManager from supervisor.dbus.network.interface import NetworkInterface from tests.common import mock_dbus_services from tests.const import TEST_INTERFACE, TEST_INTERFACE_WLAN from tests.dbus_service_mocks.base import DBusServiceMock from tests.dbus_service_mocks.network_device import Device as DeviceService @pytest.fixture(name="device_eth0_service") async def fixture_device_eth0_service( network_manager_services: dict[str, DBusServiceMock] ) -> DeviceService: """Mock Device eth0 service.""" yield network_manager_services["network_device"][0] @pytest.fixture(name="device_wlan0_service") async def fixture_device_wlan0_service( network_manager_services: dict[str, DBusServiceMock] ) -> DeviceService: """Mock Device wlan0 service.""" yield network_manager_services["network_device"][1] @pytest.fixture(name="device_unmanaged_service") async def fixture_device_unmanaged_service( dbus_session_bus: MessageBus, ) -> DeviceService: """Mock Device unmanaged service.""" yield ( await mock_dbus_services( {"network_device": "/org/freedesktop/NetworkManager/Devices/35"}, dbus_session_bus, ) )["network_device"] async def test_network_interface_ethernet( device_eth0_service: DeviceService, dbus_session_bus: MessageBus ): """Test network interface.""" interface = NetworkInterface("/org/freedesktop/NetworkManager/Devices/1") assert interface.sync_properties is False assert interface.name is None assert interface.type is None await interface.connect(dbus_session_bus) assert interface.sync_properties is True assert interface.name == TEST_INTERFACE assert interface.type == DeviceType.ETHERNET assert interface.managed is True assert interface.wireless is None assert interface.connection.state == 2 assert interface.connection.uuid == "0c23631e-2118-355c-bbb0-8943229cb0d6" assert interface.connection.ipv4.address == [IPv4Interface("192.168.2.148/24")] assert interface.connection.ipv6.address == [ IPv6Interface("2a03:169:3df5:0:6be9:2588:b26a:a679/64"), IPv6Interface("2a03:169:3df5::2f1/128"), ] assert interface.connection.ipv4.gateway == IPv4Address("192.168.2.1") assert interface.connection.ipv6.gateway == IPv6Address("fe80::da58:d7ff:fe00:9c69") assert interface.connection.ipv4.nameservers == [IPv4Address("192.168.2.2")] assert interface.connection.ipv6.nameservers == [ IPv6Address("2001:1620:2777:1::10"), IPv6Address("2001:1620:2777:2::20"), ] assert interface.settings.ipv4.method == InterfaceMethod.AUTO assert interface.settings.ipv6.method == InterfaceMethod.AUTO assert interface.settings.connection.id == "Wired connection 1" device_eth0_service.emit_properties_changed({"Managed": False}) await device_eth0_service.ping() assert interface.managed is False device_eth0_service.emit_properties_changed({}, ["Managed"]) await device_eth0_service.ping() await device_eth0_service.ping() assert interface.managed is True async def test_network_interface_wlan( device_wlan0_service: DeviceService, dbus_session_bus: MessageBus ): """Test wlan network interface.""" interface = NetworkInterface("/org/freedesktop/NetworkManager/Devices/3") assert interface.wireless is None await interface.connect(dbus_session_bus) assert interface.sync_properties is True assert interface.name == TEST_INTERFACE_WLAN assert interface.type == DeviceType.WIRELESS assert interface.wireless is not None assert interface.wireless.bitrate == 0 async def test_old_connection_disconnect( network_manager: NetworkManager, device_eth0_service: DeviceService ): """Test old connection disconnects on connection change.""" interface = network_manager.interfaces[TEST_INTERFACE] connection = interface.connection assert connection.is_connected is True device_eth0_service.emit_properties_changed({"ActiveConnection": "/"}) await device_eth0_service.ping() assert interface.connection is None assert connection.is_connected is False async def test_old_wireless_disconnect( network_manager: NetworkManager, device_wlan0_service: DeviceService ): """Test old wireless disconnects on type change.""" interface = network_manager.interfaces[TEST_INTERFACE_WLAN] wireless = interface.wireless assert wireless.is_connected is True device_wlan0_service.emit_properties_changed({"DeviceType": DeviceType.ETHERNET}) await device_wlan0_service.ping() assert interface.wireless is None assert wireless.is_connected is False async def test_unmanaged_interface( device_unmanaged_service: DeviceService, dbus_session_bus: MessageBus ): """Test unmanaged interfaces don't sync properties.""" interface = NetworkInterface("/org/freedesktop/NetworkManager/Devices/35") await interface.connect(dbus_session_bus) assert interface.managed is False assert interface.connection is None assert interface.driver == "veth" assert interface.sync_properties is False device_unmanaged_service.emit_properties_changed({"Driver": "test"}) await device_unmanaged_service.ping() assert interface.driver == "veth" async def test_interface_becomes_unmanaged( network_manager: NetworkManager, device_eth0_service: DeviceService, device_wlan0_service: DeviceService, ): """Test managed objects disconnect when interface becomes unmanaged.""" eth0 = network_manager.interfaces[TEST_INTERFACE] connection = eth0.connection wlan0 = network_manager.interfaces[TEST_INTERFACE_WLAN] wireless = wlan0.wireless assert connection.is_connected is True assert wireless.is_connected is True device_eth0_service.emit_properties_changed({"Managed": False}) await device_eth0_service.ping() device_wlan0_service.emit_properties_changed({"Managed": False}) await device_wlan0_service.ping() assert wlan0.wireless is None assert wireless.is_connected is False assert eth0.connection is None assert connection.is_connected is False