pydle/tests/mocks.py

159 lines
4.3 KiB
Python
Raw Permalink Normal View History

2014-03-13 15:49:37 +00:00
import json
import pydle
2014-03-13 15:55:34 +00:00
try:
from unittest.mock import Mock
except:
from mock import Mock
2014-03-13 15:49:37 +00:00
class MockServer:
2014-03-13 15:55:34 +00:00
"""
A mock server that will receive data and messages from the client,
and can send its own data and messages.
"""
2014-03-13 15:49:37 +00:00
def __init__(self):
self.connection = None
self.recvbuffer = ""
2014-03-13 15:49:37 +00:00
self.msgbuffer = []
def receive(self, *args, **kwargs):
self.msgbuffer.append((args, kwargs))
def receivedata(self, data):
self.recvbuffer += data
def received(self, *args, **kwargs):
if (args, kwargs) in self.msgbuffer:
self.msgbuffer.remove((args, kwargs))
return True
return False
def receiveddata(self, data):
if data in self.recvbuffer:
self.recvbuffer.replace(data, "", 1)
2014-03-13 15:49:37 +00:00
return True
return False
async def send(self, *args, **kwargs):
2014-03-13 15:49:37 +00:00
msg = self.connection._mock_client._create_message(*args, **kwargs)
await self.connection._mock_client.on_raw(msg)
2014-03-13 15:49:37 +00:00
def sendraw(self, data):
self.connection._mock_client.on_data(data)
class MockClient(pydle.client.BasicClient):
"""A client that subtitutes its own connection for a mock connection to MockServer."""
2014-03-13 15:55:34 +00:00
2014-03-13 15:49:37 +00:00
def __init__(self, *args, mock_server=None, **kwargs):
self._mock_server = mock_server
self._mock_logger = Mock()
super().__init__(*args, **kwargs)
@property
def logger(self):
return self._mock_logger
@logger.setter
def logger(self, val):
pass
2014-03-13 15:49:37 +00:00
async def _connect(self, hostname, port, *args, **kwargs):
self.connection = MockConnection(
hostname,
port,
mock_client=self,
mock_server=self._mock_server,
eventloop=self.eventloop,
)
2022-03-29 01:34:36 +00:00
await self.connection.connect()
await self.on_connect()
2014-03-13 15:49:37 +00:00
2022-03-29 01:34:36 +00:00
async def raw(self, data):
2014-03-13 15:49:37 +00:00
self.connection._mock_server.receivedata(data)
2022-03-29 01:34:36 +00:00
async def rawmsg(self, *args, **kwargs):
2014-03-13 15:49:37 +00:00
self.connection._mock_server.receive(*args, **kwargs)
def _create_message(self, *args, **kwargs):
return MockMessage(*args, **kwargs)
def _has_message(self):
return b"\r\n" in self._receive_buffer
def _parse_message(self):
message, _, data = self._receive_buffer.partition(b"\r\n")
self._receive_buffer = data
return MockMessage.parse(message + b"\r\n", encoding=self.encoding)
2014-03-13 15:49:37 +00:00
class MockConnection(pydle.connection.Connection):
"""A mock connection between a client and a server."""
2014-03-13 15:55:34 +00:00
2014-03-13 15:49:37 +00:00
def __init__(self, *args, mock_client=None, mock_server=None, **kwargs):
super().__init__(*args, **kwargs)
2014-03-13 15:49:37 +00:00
self._mock_connected = False
self._mock_server = mock_server
self._mock_client = mock_client
def on(self, *args, **kwargs):
pass
def off(self, *args, **kwargs):
pass
@property
def connected(self):
return self._mock_connected
2022-03-29 01:34:36 +00:00
async def connect(self, *args, **kwargs):
2014-03-13 15:49:37 +00:00
self._mock_server.connection = self
self._mock_connected = True
2022-03-29 01:34:36 +00:00
async def disconnect(self, *args, **kwargs):
2014-03-13 15:49:37 +00:00
self._mock_server.connection = None
self._mock_connected = False
class MockMessage(pydle.protocol.Message):
def __init__(self, command, *params, source=None, **kw):
self.command = command
self.params = params
self.source = source
self.kw = kw
self._valid = True
@classmethod
def parse(cls, line, encoding=pydle.protocol.DEFAULT_ENCODING):
# Decode message.
line = line.strip()
try:
message = line.decode(encoding)
except UnicodeDecodeError:
# Try our fallback encoding.
message = line.decode(pydle.protocol.FALLBACK_ENCODING)
try:
val = json.loads(message)
except:
raise pydle.protocol.ProtocolViolation("Invalid JSON")
2014-03-13 15:49:37 +00:00
return MockMessage(
val["command"], *val["params"], source=val["source"], **val["kw"]
)
2014-03-13 15:49:37 +00:00
def construct(self):
return (
json.dumps(
{
"command": self.command,
"params": self.params,
"source": self.source,
"kw": self.kw,
}
)
+ "\r\n"
)