File: test_plcnetapi.py

package info (click to toggle)
devolo-plc-api 1.5.1%2Bgit20260208.5d3989e-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 504 kB
  • sloc: python: 1,616; makefile: 6
file content (136 lines) | stat: -rw-r--r-- 6,866 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
"""Test communicating with a the plcnet API."""

import sys
from http import HTTPStatus
from unittest.mock import patch

import pytest
from httpx import ConnectTimeout
from pytest_httpx import HTTPXMock

from devolo_plc_api import Device
from devolo_plc_api.exceptions import DevicePasswordProtected, DeviceUnavailable
from devolo_plc_api.plcnet_api import LogicalNetwork, PlcNetApi
from devolo_plc_api.plcnet_api.getnetworkoverview_pb2 import GetNetworkOverview
from devolo_plc_api.plcnet_api.identifydevice_pb2 import IdentifyDeviceResponse
from devolo_plc_api.plcnet_api.pairdevice_pb2 import PairDeviceStart
from devolo_plc_api.plcnet_api.setuserdevicename_pb2 import SetUserDeviceNameResponse

from . import DeviceType


@pytest.mark.skipif(sys.version_info < (3, 9), reason="Tests with httpx_mock need at least Python 3.9")
class TestPlcApi:
    """Test devolo_plc_api.plcnet_api.plcnetapi.PlcNetApi class."""

    @pytest.mark.asyncio
    @pytest.mark.parametrize("device_type", [DeviceType.PLC])
    @pytest.mark.usefixtures("block_communication", "service_browser")
    @pytest.mark.httpx_mock(can_send_already_matched_responses=True)
    async def test_wrong_password_type(self, httpx_mock: HTTPXMock, mock_device: Device):
        """Test using different password hash if original password failed."""
        await mock_device.async_connect()
        assert mock_device.plcnet
        mock_device.password = "password"

        httpx_mock.add_response(status_code=HTTPStatus.UNAUTHORIZED)
        with pytest.raises(DevicePasswordProtected):
            await mock_device.plcnet.async_set_user_device_name("Test")
            assert mock_device.plcnet.password == "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"

        httpx_mock.add_response(status_code=HTTPStatus.UNAUTHORIZED)
        with pytest.raises(DevicePasswordProtected):
            await mock_device.plcnet.async_set_user_device_name("Test")
            assert mock_device.plcnet.password == "113459eb7bb31bddee85ade5230d6ad5d8b2fb52879e00a84ff6ae1067a210d3"

        await mock_device.async_disconnect()

    @pytest.mark.asyncio
    async def test_async_get_network_overview(self, plcnet_api: PlcNetApi, httpx_mock: HTTPXMock, network: LogicalNetwork):
        """Test getting the network overview asynchronously."""
        network_overview = GetNetworkOverview(network=network)
        httpx_mock.add_response(content=network_overview.SerializeToString())
        overview = await plcnet_api.async_get_network_overview()
        assert overview == network

    def test_get_network_overview(self, plcnet_api: PlcNetApi, httpx_mock: HTTPXMock, network: LogicalNetwork):
        """Test getting the network overview synchronously."""
        network_overview = GetNetworkOverview(network=network)
        httpx_mock.add_response(content=network_overview.SerializeToString())
        overview = plcnet_api.get_network_overview()
        assert overview == network

    @pytest.mark.asyncio
    async def test_async_identify_device_start(self, plcnet_api: PlcNetApi, httpx_mock: HTTPXMock):
        """Test starting identifying a device asynchronously."""
        identify_device = IdentifyDeviceResponse()
        httpx_mock.add_response(content=identify_device.SerializeToString())
        assert await plcnet_api.async_identify_device_start()

    def test_identify_device_start(self, plcnet_api: PlcNetApi, httpx_mock: HTTPXMock):
        """Test starting identifying a device synchronously."""
        identify_device = IdentifyDeviceResponse()
        httpx_mock.add_response(content=identify_device.SerializeToString())
        assert plcnet_api.identify_device_start()

    @pytest.mark.asyncio
    async def test_async_identify_device_stop(self, plcnet_api: PlcNetApi, httpx_mock: HTTPXMock):
        """Test stopping identifying a device asynchronously."""
        identify_device = IdentifyDeviceResponse()
        httpx_mock.add_response(content=identify_device.SerializeToString())
        assert await plcnet_api.async_identify_device_stop()

    def test_identify_device_stop(self, plcnet_api: PlcNetApi, httpx_mock: HTTPXMock):
        """Test stopping identifying a device synchronously."""
        identify_device = IdentifyDeviceResponse()
        httpx_mock.add_response(content=identify_device.SerializeToString())
        assert plcnet_api.identify_device_stop()

    @pytest.mark.asyncio
    async def test_async_pair_device(self, plcnet_api: PlcNetApi, httpx_mock: HTTPXMock):
        """Test pairing a device asynchronously."""
        pair_device = PairDeviceStart()
        httpx_mock.add_response(content=pair_device.SerializeToString())
        assert await plcnet_api.async_pair_device()

    def test_pair_device(self, plcnet_api: PlcNetApi, httpx_mock: HTTPXMock):
        """Test pairing a device synchronously."""
        pair_device = PairDeviceStart()
        httpx_mock.add_response(content=pair_device.SerializeToString())
        assert plcnet_api.pair_device()

    @pytest.mark.asyncio
    async def test_async_set_user_device_name(self, plcnet_api: PlcNetApi, httpx_mock: HTTPXMock):
        """Test setting a device name asynchronously."""
        user_device_name_set = SetUserDeviceNameResponse()
        httpx_mock.add_response(content=user_device_name_set.SerializeToString())
        assert await plcnet_api.async_set_user_device_name("Test")

    def test_set_user_device_name(self, plcnet_api: PlcNetApi, httpx_mock: HTTPXMock):
        """Test setting a device name synchronously."""
        user_device_name_set = SetUserDeviceNameResponse()
        httpx_mock.add_response(content=user_device_name_set.SerializeToString())
        assert plcnet_api.set_user_device_name("Test")

    @pytest.mark.asyncio
    @pytest.mark.parametrize("device_type", [DeviceType.PLC])
    @pytest.mark.usefixtures("block_communication", "service_browser")
    async def test_device_unavailable(self, httpx_mock: HTTPXMock, mock_device: Device):
        """Test device being unavailable."""
        await mock_device.async_connect()
        assert mock_device.plcnet
        httpx_mock.add_exception(ConnectTimeout(""), is_reusable=True)
        with pytest.raises(DeviceUnavailable), patch("asyncio.sleep"):
            await mock_device.plcnet.async_get_network_overview()
        await mock_device.async_disconnect()
        assert len(httpx_mock.get_requests()) == 3

    @pytest.mark.asyncio
    @pytest.mark.parametrize("device_type", [DeviceType.PLC])
    @pytest.mark.usefixtures("block_communication", "service_browser")
    async def test_attribute_error(self, mock_device: Device):
        """Test raising on calling not existing method."""
        await mock_device.async_connect()
        assert mock_device.plcnet
        with pytest.raises(AttributeError):
            mock_device.plcnet.test()  # type: ignore[union-attr]