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 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
"""Connection tests."""
import asyncio
from unittest.mock import AsyncMock, Mock, call, patch
import pytest
from pypck.connection import (
PchkAuthenticationError,
PchkConnectionFailedError,
PchkConnectionManager,
PchkConnectionRefusedError,
PchkLicenseError,
)
from pypck.lcn_addr import LcnAddr
from pypck.lcn_defs import AcknowledgeErrorCode, LcnEvent
from pypck.pck_commands import PckGenerator
from pypck import inputs
from .conftest import HOST, PASSWORD, PORT, USERNAME, MockPchkConnectionManager
async def test_close_without_connect(pypck_client: MockPchkConnectionManager) -> None:
"""Test closing of PchkConnectionManager without connecting."""
await pypck_client.async_close()
@patch.object(PchkConnectionManager, "open_connection")
@patch.object(PchkConnectionManager, "scan_segment_couplers")
async def test_async_connect(
mock_scan_segment_couplers: AsyncMock,
mock_open_connection: AsyncMock,
) -> None:
"""Test successful connection."""
pypck_client = PchkConnectionManager(HOST, PORT, USERNAME, PASSWORD)
connect_task = asyncio.create_task(pypck_client.async_connect())
await asyncio.sleep(0)
pypck_client.license_error_future.set_result(True)
pypck_client.authentication_completed_future.set_result(True)
pypck_client.segment_scan_completed_event.set()
await connect_task
mock_scan_segment_couplers.assert_awaited()
mock_open_connection.assert_awaited()
assert pypck_client.is_ready()
@patch.object(PchkConnectionManager, "ping")
@patch.object(PchkConnectionManager, "open_connection")
@patch.object(PchkConnectionManager, "scan_segment_couplers")
@patch.object(PchkConnectionManager, "send_command")
async def test_successful_connection_procedure(
mock_send_command: AsyncMock,
mock_scan_segment_couplers: AsyncMock,
mock_open_connection: AsyncMock,
mock_ping: AsyncMock,
) -> None:
"""Test successful connection procedure."""
pypck_client = PchkConnectionManager(HOST, PORT, USERNAME, PASSWORD)
connect_task = asyncio.create_task(pypck_client.async_connect())
await asyncio.sleep(0)
await pypck_client.async_process_input(inputs.AuthUsername())
mock_send_command.assert_awaited_with(USERNAME, to_host=True)
await pypck_client.async_process_input(inputs.AuthPassword())
mock_send_command.assert_awaited_with(PASSWORD, to_host=True)
await pypck_client.async_process_input(inputs.AuthOk())
mock_send_command.assert_awaited_with(PckGenerator.set_dec_mode(), to_host=True)
assert pypck_client.authentication_completed_future.result()
await pypck_client.async_process_input(inputs.DecModeSet())
mock_send_command.assert_awaited_with(
PckGenerator.set_operation_mode(
pypck_client.dim_mode, pypck_client.status_mode
),
to_host=True,
)
assert pypck_client.license_error_future.result()
await connect_task
mock_open_connection.assert_awaited()
mock_scan_segment_couplers.assert_awaited()
mock_ping.assert_awaited()
@pytest.mark.parametrize("side_effect", [ConnectionRefusedError, OSError])
async def test_connection_error(side_effect: ConnectionRefusedError | OSError) -> None:
"""Test connection error."""
with (
patch.object(PchkConnectionManager, "open_connection", side_effect=side_effect),
pytest.raises(PchkConnectionRefusedError),
):
pypck_client = PchkConnectionManager(HOST, PORT, USERNAME, PASSWORD)
await pypck_client.async_connect()
@patch.object(PchkConnectionManager, "open_connection")
async def test_authentication_error(mock_open_connection: AsyncMock) -> None:
"""Test wrong login credentials."""
pypck_client = PchkConnectionManager(HOST, PORT, USERNAME, PASSWORD)
connect_task = asyncio.create_task(pypck_client.async_connect())
await asyncio.sleep(0)
await pypck_client.async_process_input(inputs.AuthFailed())
with (
pytest.raises(PchkAuthenticationError),
):
await connect_task
@patch.object(PchkConnectionManager, "open_connection")
async def test_license_error(mock_open_connection: AsyncMock) -> None:
"""Test wrong login credentials."""
pypck_client = PchkConnectionManager(HOST, PORT, USERNAME, PASSWORD)
connect_task = asyncio.create_task(pypck_client.async_connect())
await asyncio.sleep(0)
await pypck_client.async_process_input(inputs.LicenseError())
with (
pytest.raises(PchkLicenseError),
):
await connect_task
@patch.object(PchkConnectionManager, "open_connection")
async def test_timeout_error(mock_open_connection: AsyncMock) -> None:
"""Test timeout when connecting."""
with pytest.raises(PchkConnectionFailedError):
pypck_client = PchkConnectionManager(HOST, PORT, USERNAME, PASSWORD)
await pypck_client.async_connect(timeout=0)
async def test_lcn_connected(pypck_client: MockPchkConnectionManager) -> None:
"""Test lcn connected events."""
event_callback = Mock()
pypck_client.register_for_events(event_callback)
await pypck_client.async_connect()
# bus disconnected
await pypck_client.async_process_input(inputs.LcnConnState(is_lcn_connected=False))
assert not pypck_client.is_lcn_connected
event_callback.assert_has_calls(
(call(LcnEvent.BUS_CONNECTION_STATUS_CHANGED), call(LcnEvent.BUS_DISCONNECTED))
)
# bus connected
await pypck_client.async_process_input(inputs.LcnConnState(is_lcn_connected=True))
assert pypck_client.is_lcn_connected
event_callback.assert_has_calls(
(call(LcnEvent.BUS_CONNECTION_STATUS_CHANGED), call(LcnEvent.BUS_CONNECTED))
)
async def test_new_module_on_input(
pypck_client: MockPchkConnectionManager,
) -> None:
"""Test new module detection on serial input."""
await pypck_client.async_connect()
address = LcnAddr(0, 7, False)
assert address not in pypck_client.device_connections.keys()
await pypck_client.async_process_input(
inputs.ModAck(address, AcknowledgeErrorCode.OK)
)
assert address in pypck_client.device_connections.keys()
|