generated from mononoki/pyproj
115 lines
4.6 KiB
Python
115 lines
4.6 KiB
Python
"""Check the real test client independently of the server implementation."""
|
|
|
|
import asyncio
|
|
import json
|
|
|
|
import pytest
|
|
|
|
|
|
async def send_packet(writer, packet):
|
|
writer.write((json.dumps(packet) + "\n").encode())
|
|
await writer.drain()
|
|
|
|
|
|
def test_client_waits_for_handshake_and_checks_heartbeat(client_module):
|
|
"""Проверяет порядок handshake и сохранение данных, пришедших до heartbeat-ответа."""
|
|
async def scenario():
|
|
finished = asyncio.get_running_loop().create_future()
|
|
|
|
async def peer(reader, writer):
|
|
try:
|
|
packet = json.loads(await reader.readline())
|
|
assert packet == {
|
|
"command": "connection",
|
|
"payload": {"name": "rover", "type": "robot", "in": ["control"], "out": ["telemetry"]},
|
|
}
|
|
await send_packet(writer, {"command": "token_ask", "payload": 123, "upf": 456})
|
|
assert json.loads(await reader.readline()) == {
|
|
"command": "token_answer", "payload": {"token": None, "upf": None},
|
|
}
|
|
await send_packet(writer, {"command": "handshake_ask"})
|
|
assert json.loads(await reader.readline()) == {
|
|
"command": "handshake_answer", "payload": {"status": True, "state": None},
|
|
}
|
|
assert json.loads(await reader.readline()) == {"command": "heartbeat_ask", "payload": {}}
|
|
await send_packet(writer, {"command": "control", "payload": {"turn": 1}})
|
|
await send_packet(writer, {"command": "heartbeat_answer"})
|
|
assert json.loads(await reader.readline()) == {
|
|
"command": "telemetry", "payload": {"temperature": 42.0, "battery": 87},
|
|
}
|
|
assert await reader.read() == b""
|
|
except BaseException as error:
|
|
finished.set_exception(error)
|
|
else:
|
|
finished.set_result(None)
|
|
finally:
|
|
writer.close()
|
|
await writer.wait_closed()
|
|
|
|
server = await asyncio.start_server(peer, "127.0.0.1", 0)
|
|
async with server:
|
|
client = client_module.Client(
|
|
"rover", port=server.sockets[0].getsockname()[1],
|
|
node_type="robot", inputs=["control"],
|
|
)
|
|
try:
|
|
await client.connect()
|
|
assert (client.uid, client.upf) == (123, 456)
|
|
assert await client.recv() == {"command": "control", "payload": {"turn": 1}}
|
|
await client.telemetry()
|
|
finally:
|
|
await client.close()
|
|
await finished
|
|
|
|
asyncio.run(asyncio.wait_for(scenario(), 5))
|
|
|
|
|
|
def test_client_times_out_when_server_does_not_answer(client_module):
|
|
"""Проверяет таймаут молчащего сервера и освобождение клиентского соединения."""
|
|
async def scenario():
|
|
finished = asyncio.Event()
|
|
|
|
async def peer(reader, writer):
|
|
try:
|
|
await reader.read()
|
|
finally:
|
|
writer.close()
|
|
await writer.wait_closed()
|
|
finished.set()
|
|
|
|
server = await asyncio.start_server(peer, "127.0.0.1", 0)
|
|
async with server:
|
|
client = client_module.Client(port=server.sockets[0].getsockname()[1], timeout=0.1)
|
|
with pytest.raises(TimeoutError):
|
|
await client.connect()
|
|
assert client.writer is None
|
|
await finished.wait()
|
|
|
|
asyncio.run(asyncio.wait_for(scenario(), 5))
|
|
|
|
|
|
def test_client_reports_wrong_handshake_packet(client_module):
|
|
"""Проверяет понятную ошибку и закрытие клиента при неверном ответе handshake."""
|
|
async def scenario():
|
|
finished = asyncio.Event()
|
|
|
|
async def peer(reader, writer):
|
|
try:
|
|
await reader.readline()
|
|
await send_packet(writer, {"command": "handshake_ask"})
|
|
await reader.read()
|
|
finally:
|
|
writer.close()
|
|
await writer.wait_closed()
|
|
finished.set()
|
|
|
|
server = await asyncio.start_server(peer, "127.0.0.1", 0)
|
|
async with server:
|
|
client = client_module.Client(port=server.sockets[0].getsockname()[1])
|
|
with pytest.raises(client_module.ProtocolError, match="Expected token_ask"):
|
|
await client.connect()
|
|
assert client.writer is None
|
|
await finished.wait()
|
|
|
|
asyncio.run(asyncio.wait_for(scenario(), 5))
|