3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-11-27 21:19:31 +01:00
PyLink/test/test_irc_parsers.py
2021-12-25 00:33:36 -08:00

119 lines
4.8 KiB
Python

"""
Runs IRC parser tests from ircdocs/parser-tests.
This test suite runs static code only.
"""
from pathlib import Path
import unittest
import yaml
PARSER_DATA_PATH = Path(__file__).parent.resolve() / 'parser-tests' / 'tests'
print(PARSER_DATA_PATH)
from pylinkirc import utils
from pylinkirc.protocols.ircs2s_common import IRCCommonProtocol
class MessageParserTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
with open(PARSER_DATA_PATH / 'msg-split.yaml') as f:
cls.MESSAGE_SPLIT_TEST_DATA = yaml.safe_load(f)
with open(PARSER_DATA_PATH / 'userhost-split.yaml') as f:
cls.USER_HOST_SPLIT_TEST_DATA = yaml.safe_load(f)
with open(PARSER_DATA_PATH / 'mask-match.yaml') as f:
cls.MASK_MATCH_TEST_DATA = yaml.safe_load(f)
with open(PARSER_DATA_PATH / 'validate-hostname.yaml') as f:
cls.VALIDATE_HOSTNAME_TEST_DATA = yaml.safe_load(f)
def testMessageSplit(self):
for testdata in self.MESSAGE_SPLIT_TEST_DATA['tests']:
inp = testdata['input']
atoms = testdata['atoms']
with self.subTest():
expected = []
has_source = False
if 'source' in atoms:
has_source = True
expected.append(atoms['source'])
if 'verb' in atoms:
expected.append(atoms['verb'])
if 'params' in atoms:
expected.extend(atoms['params'])
if 'tags' in atoms:
# Remove message tags before parsing
_, inp = inp.split(" ", 1)
if has_source:
parts = IRCCommonProtocol.parse_prefixed_args(inp)
else:
parts = IRCCommonProtocol.parse_args(inp)
self.assertEqual(expected, parts, "Parse test failed for string: %r" % inp)
@unittest.skip("Not quite working yet")
def testMessageTags(self):
for testdata in self.MESSAGE_SPLIT_TEST_DATA['tests']:
inp = testdata['input']
atoms = testdata['atoms']
with self.subTest():
if 'tags' in atoms:
self.assertEqual(atoms['tags'], IRCCommonProtocol.parse_message_tags(inp.split(" ")),
"Parse test failed for message tags: %r" % inp)
def testUserHostSplit(self):
for test in self.USER_HOST_SPLIT_TEST_DATA['tests']:
inp = test['source']
atoms = test['atoms']
with self.subTest():
if 'nick' not in atoms or 'user' not in atoms or 'host' not in atoms:
# Trying to parse a hostmask with missing atoms is an error in split_hostmask()
with self.assertRaises(ValueError):
utils.split_hostmask(inp)
else:
expected = [atoms['nick'], atoms['user'], atoms['host']]
self.assertEqual(expected, utils.split_hostmask(inp))
def testHostMatch(self):
for test in self.MASK_MATCH_TEST_DATA['tests']:
mask = test['mask']
# N.B.: utils.match_text() does Unicode case-insensitive match by default,
# which might not be the right thing to do on IRC.
# But irc.to_lower() isn't a static function so we're not testing it here...
for match in test['matches']:
with self.subTest():
self.assertTrue(utils.match_text(mask, match))
for fail in test['fails']:
with self.subTest():
self.assertFalse(utils.match_text(mask, fail))
def testValidateHostname(self):
for test in self.VALIDATE_HOSTNAME_TEST_DATA['tests']:
with self.subTest():
self.assertEqual(test['valid'], IRCCommonProtocol.is_server_name(test['host']),
"Failed test for %r; should be %s" % (test['host'], test['valid']))
# N.B. skipping msg-join tests because PyLink doesn't think about messages that way
### Custom test cases
def testMessageSplitSpaces(self):
# Test that tokenization ignores empty fields, but doesn't strip away other types of whitespace
f = IRCCommonProtocol.parse_prefixed_args
self.assertEqual(f(":foo PRIVMSG #test :message"), ["foo", "PRIVMSG", "#test", "message"])
self.assertEqual(f(":123LOLWUT NICK cursed\u3000nickname"), ["123LOLWUT", "NICK", "cursed\u3000nickname"])
self.assertEqual(f(":123LOLWUT MODE ## +ov \x1f checking"),
["123LOLWUT", "MODE", "##", "+ov", "\x1f", "checking"])
self.assertEqual(f(":123LOLWUT MODE ## +ov \u3000 checking"),
["123LOLWUT", "MODE", "##", "+ov", "\u3000", "checking"])
if __name__ == '__main__':
unittest.main()