File: test_connection.py

package info (click to toggle)
pypck 0.9.10-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 492 kB
  • sloc: python: 5,099; makefile: 15
file content (171 lines) | stat: -rw-r--r-- 6,130 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
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()