220 lines
9.7 KiB
Python
220 lines
9.7 KiB
Python
try:
|
|
from django.utils.unittest import TestCase
|
|
except ImportError:
|
|
from django.test import TestCase
|
|
|
|
try:
|
|
from django.utils import unittest
|
|
except ImportError:
|
|
import unittest
|
|
|
|
import string
|
|
import mock
|
|
from mock import Mock, MagicMock
|
|
from evennia.server.portal import irc
|
|
|
|
from twisted.conch.telnet import IAC, WILL, DONT, SB, SE, NAWS, DO
|
|
from twisted.test import proto_helpers
|
|
from twisted.trial.unittest import TestCase as TwistedTestCase
|
|
|
|
from .telnet import TelnetServerFactory, TelnetProtocol
|
|
from .portal import PORTAL_SESSIONS
|
|
from .suppress_ga import SUPPRESS_GA
|
|
from .naws import DEFAULT_HEIGHT, DEFAULT_WIDTH
|
|
from .ttype import TTYPE, IS
|
|
from .mccp import MCCP
|
|
from .mssp import MSSP
|
|
from .mxp import MXP
|
|
from .telnet_oob import MSDP, MSDP_VAL, MSDP_VAR
|
|
|
|
from .amp import AMPMultiConnectionProtocol, MsgServer2Portal, MsgPortal2Server, AMP_MAXLEN
|
|
from .amp_server import AMPServerFactory
|
|
|
|
|
|
class TestAMPServer(TwistedTestCase):
|
|
"""
|
|
Test AMP communication
|
|
"""
|
|
def setUp(self):
|
|
super(TestAMPServer, self).setUp()
|
|
portal = Mock()
|
|
factory = AMPServerFactory(portal)
|
|
self.proto = factory.buildProtocol(("localhost", 0))
|
|
self.transport = MagicMock() # proto_helpers.StringTransport()
|
|
self.transport.client = ["localhost"]
|
|
self.transport.write = MagicMock()
|
|
|
|
def test_amp_out(self):
|
|
self.proto.makeConnection(self.transport)
|
|
|
|
self.proto.data_to_server(MsgServer2Portal, 1, test=2)
|
|
byte_out = (b'\x00\x04_ask\x00\x011\x00\x08_command\x00\x10MsgServer2Portal\x00\x0b'
|
|
b'packed_data\x00 x\xdak`\x99*\xc8\x00\x01\xde\x8c\xb5SzXJR'
|
|
b'\x8bK\xa6x3\x15\xb7M\xd1\x03\x00V:\x07t\x00\x00')
|
|
self.transport.write.assert_called_with(byte_out)
|
|
with mock.patch("evennia.server.portal.amp.amp.AMP.dataReceived") as mocked_amprecv:
|
|
self.proto.dataReceived(byte_out)
|
|
mocked_amprecv.assert_called_with(byte_out)
|
|
|
|
def test_amp_in(self):
|
|
self.proto.makeConnection(self.transport)
|
|
|
|
self.proto.data_to_server(MsgPortal2Server, 1, test=2)
|
|
byte_out = (b'\x00\x04_ask\x00\x011\x00\x08_command\x00\x10MsgPortal2Server\x00\x0b'
|
|
b'packed_data\x00 x\xdak`\x99*\xc8\x00\x01\xde\x8c\xb5SzXJR'
|
|
b'\x8bK\xa6x3\x15\xb7M\xd1\x03\x00V:\x07t\x00\x00')
|
|
self.transport.write.assert_called_with(byte_out)
|
|
with mock.patch("evennia.server.portal.amp.amp.AMP.dataReceived") as mocked_amprecv:
|
|
self.proto.dataReceived(byte_out)
|
|
mocked_amprecv.assert_called_with(byte_out)
|
|
|
|
def test_large_msg(self):
|
|
"""
|
|
Send message larger than AMP_MAXLEN - should be split into several
|
|
"""
|
|
self.proto.makeConnection(self.transport)
|
|
outstr = 'test' * AMP_MAXLEN
|
|
self.proto.data_to_server(MsgServer2Portal, 1, test=outstr)
|
|
self.transport.write.assert_called_with(
|
|
b'\x00\x04_ask\x00\x011\x00\x08_command\x00\x10MsgServer2Portal\x00\x0bpacked_data'
|
|
b'\x00xx\xda\xed\xc6\xc1\t\x800\x10\x00\xc1\x13\xaf\x01\xeb\xb2\x01\x1bH'
|
|
b'\x05\xe6+X\x80\xcf\xd8m@I\x1d\x99\x85\x81\xbd\xf3\xdd"c\xb4/W{'
|
|
b'\xb2\x96\xb3\xb6\xa3\x7fk\x8c\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x0e?Pv\x02\x16\x00\r'
|
|
b'packed_data.2\x00Zx\xda\xed\xc3\x01\r\x00\x00\x08\xc0\xa0\xb4&\xf0\xfdg\x10a'
|
|
b'\xa3\xd9RUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU\xf5\xfb\x03'
|
|
b'm\xe0\x06\x1d\x00\rpacked_data.3\x00Zx\xda\xed\xc3\x01\r\x00\x00\x08\xc0\xa0'
|
|
b'\xb4&\xf0\xfdg\x10a\xa3fSUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU'
|
|
b'UUUUU\xf5\xfb\x03n\x1c\x06\x1e\x00\rpacked_data.4\x00Zx\xda\xed\xc3\x01\t\x00'
|
|
b'\x00\x0c\x03\xa0\xb4O\xb0\xf5gA\xae`\xda\x8b\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa'
|
|
b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa'
|
|
b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa'
|
|
b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xdf\x0fnI'
|
|
b'\x06,\x00\rpacked_data.5\x00\x14x\xdaK-.)I\xc5\x8e\xa7\x14\xb7M\xd1\x03\x00'
|
|
b'\xe7s\x0e\x1c\x00\x00')
|
|
|
|
|
|
class TestIRC(TestCase):
|
|
|
|
def test_plain_ansi(self):
|
|
"""
|
|
Test that printable characters do not get mangled.
|
|
"""
|
|
irc_ansi = irc.parse_ansi_to_irc(string.printable)
|
|
ansi_irc = irc.parse_irc_to_ansi(string.printable)
|
|
self.assertEqual(irc_ansi, string.printable)
|
|
self.assertEqual(ansi_irc, string.printable)
|
|
|
|
def test_bold(self):
|
|
s_irc = "\x02thisisatest"
|
|
s_eve = r'|hthisisatest'
|
|
self.assertEqual(irc.parse_ansi_to_irc(s_eve), s_irc)
|
|
self.assertEqual(s_eve, irc.parse_irc_to_ansi(s_irc))
|
|
|
|
def test_italic(self):
|
|
s_irc = "\x02thisisatest"
|
|
s_eve = r'|hthisisatest'
|
|
self.assertEqual(irc.parse_ansi_to_irc(s_eve), s_irc)
|
|
|
|
def test_colors(self):
|
|
color_map = (("\0030", r'|w'),
|
|
("\0031", r'|X'),
|
|
("\0032", r'|B'),
|
|
("\0033", r'|G'),
|
|
("\0034", r'|r'),
|
|
("\0035", r'|R'),
|
|
("\0036", r'|M'),
|
|
("\0037", r'|Y'),
|
|
("\0038", r'|y'),
|
|
("\0039", r'|g'),
|
|
("\00310", r'|C'),
|
|
("\00311", r'|c'),
|
|
("\00312", r'|b'),
|
|
("\00313", r'|m'),
|
|
("\00314", r'|x'),
|
|
("\00315", r'|W'),
|
|
("\00399,5", r'|[r'),
|
|
("\00399,3", r'|[g'),
|
|
("\00399,7", r'|[y'),
|
|
("\00399,2", r'|[b'),
|
|
("\00399,6", r'|[m'),
|
|
("\00399,10", r'|[c'),
|
|
("\00399,15", r'|[w'),
|
|
("\00399,1", r'|[x'))
|
|
|
|
for m in color_map:
|
|
self.assertEqual(irc.parse_irc_to_ansi(m[0]), m[1])
|
|
self.assertEqual(m[0], irc.parse_ansi_to_irc(m[1]))
|
|
|
|
def test_identity(self):
|
|
"""
|
|
Test that the composition of the function and
|
|
its inverse gives the correct string.
|
|
"""
|
|
|
|
s = r'|wthis|Xis|gis|Ma|C|complex|*string'
|
|
|
|
self.assertEqual(irc.parse_irc_to_ansi(irc.parse_ansi_to_irc(s)), s)
|
|
|
|
|
|
class TestTelnet(TwistedTestCase):
|
|
def setUp(self):
|
|
super(TestTelnet, self).setUp()
|
|
factory = TelnetServerFactory()
|
|
factory.protocol = TelnetProtocol
|
|
factory.sessionhandler = PORTAL_SESSIONS
|
|
factory.sessionhandler.portal = Mock()
|
|
self.proto = factory.buildProtocol(("localhost", 0))
|
|
self.transport = proto_helpers.StringTransport()
|
|
self.addCleanup(factory.sessionhandler.disconnect_all)
|
|
|
|
def test_mudlet_ttype(self):
|
|
self.transport.client = ["localhost"]
|
|
self.transport.setTcpKeepAlive = Mock()
|
|
d = self.proto.makeConnection(self.transport)
|
|
# test suppress_ga
|
|
self.assertTrue(self.proto.protocol_flags["NOGOAHEAD"])
|
|
self.proto.dataReceived(IAC + DONT + SUPPRESS_GA)
|
|
self.assertFalse(self.proto.protocol_flags["NOGOAHEAD"])
|
|
self.assertEqual(self.proto.handshakes, 7)
|
|
# test naws
|
|
self.assertEqual(self.proto.protocol_flags['SCREENWIDTH'], {0: DEFAULT_WIDTH})
|
|
self.assertEqual(self.proto.protocol_flags['SCREENHEIGHT'], {0: DEFAULT_HEIGHT})
|
|
self.proto.dataReceived(IAC + WILL + NAWS)
|
|
self.proto.dataReceived(b"".join([IAC, SB, NAWS, b'', b'x', b'', b'd', IAC, SE]))
|
|
self.assertEqual(self.proto.protocol_flags['SCREENWIDTH'][0], 78)
|
|
self.assertEqual(self.proto.protocol_flags['SCREENHEIGHT'][0], 45)
|
|
self.assertEqual(self.proto.handshakes, 6)
|
|
# test ttype
|
|
self.assertTrue(self.proto.protocol_flags["FORCEDENDLINE"])
|
|
self.assertFalse(self.proto.protocol_flags["TTYPE"])
|
|
self.assertTrue(self.proto.protocol_flags["ANSI"])
|
|
self.proto.dataReceived(IAC + WILL + TTYPE)
|
|
self.proto.dataReceived(b"".join([IAC, SB, TTYPE, IS, b"MUDLET", IAC, SE]))
|
|
self.assertTrue(self.proto.protocol_flags["XTERM256"])
|
|
self.assertEqual(self.proto.protocol_flags["CLIENTNAME"], "MUDLET")
|
|
self.proto.dataReceived(b"".join([IAC, SB, TTYPE, IS, b"XTERM", IAC, SE]))
|
|
self.proto.dataReceived(b"".join([IAC, SB, TTYPE, IS, b"MTTS 137", IAC, SE]))
|
|
self.assertEqual(self.proto.handshakes, 5)
|
|
# test mccp
|
|
self.proto.dataReceived(IAC + DONT + MCCP)
|
|
self.assertFalse(self.proto.protocol_flags['MCCP'])
|
|
self.assertEqual(self.proto.handshakes, 4)
|
|
# test mssp
|
|
self.proto.dataReceived(IAC + DONT + MSSP)
|
|
self.assertEqual(self.proto.handshakes, 3)
|
|
# test oob
|
|
self.proto.dataReceived(IAC + DO + MSDP)
|
|
self.proto.dataReceived(b"".join([IAC, SB, MSDP, MSDP_VAR, b"LIST", MSDP_VAL, b"COMMANDS", IAC, SE]))
|
|
self.assertTrue(self.proto.protocol_flags['OOB'])
|
|
self.assertEqual(self.proto.handshakes, 2)
|
|
# test mxp
|
|
self.proto.dataReceived(IAC + DONT + MXP)
|
|
self.assertFalse(self.proto.protocol_flags['MXP'])
|
|
self.assertEqual(self.proto.handshakes, 1)
|
|
# clean up to prevent Unclean reactor
|
|
self.proto.nop_keep_alive.stop()
|
|
self.proto._handshake_delay.cancel()
|
|
return d
|