83 lines
2.5 KiB
Python
83 lines
2.5 KiB
Python
import socket
|
|
import threading
|
|
import time
|
|
import unittest
|
|
|
|
from vitapad.protocol import Buttons, InputState, encode_packet
|
|
from vitapad.receiver import Receiver
|
|
|
|
|
|
class FakeBackend:
|
|
name = "fake"
|
|
|
|
def __init__(self) -> None:
|
|
self.states: list[InputState] = []
|
|
self.closed = False
|
|
|
|
def update(self, state: InputState) -> None:
|
|
self.states.append(state)
|
|
|
|
def close(self) -> None:
|
|
self.closed = True
|
|
|
|
|
|
def unused_udp_port() -> int:
|
|
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
|
|
sock.bind(("127.0.0.1", 0))
|
|
return sock.getsockname()[1]
|
|
|
|
|
|
class ReceiverTests(unittest.TestCase):
|
|
def test_receive_and_failsafe(self) -> None:
|
|
backend = FakeBackend()
|
|
port = unused_udp_port()
|
|
receiver = Receiver(
|
|
backend,
|
|
bind="127.0.0.1",
|
|
port=port,
|
|
discovery_port=unused_udp_port(),
|
|
timeout_ms=50,
|
|
)
|
|
thread = threading.Thread(target=receiver.run)
|
|
thread.start()
|
|
try:
|
|
state = InputState(sequence=7, buttons=Buttons.A, lx=200)
|
|
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sender:
|
|
# Give the receiver thread time to bind.
|
|
time.sleep(0.02)
|
|
sender.sendto(encode_packet(state), ("127.0.0.1", port))
|
|
deadline = time.monotonic() + 1.0
|
|
while len(backend.states) < 2 and time.monotonic() < deadline:
|
|
time.sleep(0.01)
|
|
self.assertEqual(backend.states[0], state)
|
|
self.assertEqual(backend.states[1], InputState.neutral())
|
|
finally:
|
|
receiver.stop()
|
|
thread.join(timeout=2)
|
|
self.assertFalse(thread.is_alive())
|
|
self.assertTrue(backend.closed)
|
|
|
|
def test_rejects_old_sequence(self) -> None:
|
|
backend = FakeBackend()
|
|
receiver = Receiver(backend)
|
|
receiver._connected_address = "127.0.0.1"
|
|
receiver._last_sequence = 20
|
|
listener = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
try:
|
|
listener.bind(("127.0.0.1", 0))
|
|
listener.settimeout(1)
|
|
sender.sendto(
|
|
encode_packet(InputState(sequence=19, buttons=Buttons.B)),
|
|
listener.getsockname(),
|
|
)
|
|
receiver._receive_once(listener)
|
|
finally:
|
|
listener.close()
|
|
sender.close()
|
|
self.assertEqual(backend.states, [])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|