From a58bee7355fac368ebade1df1f9959d54f125a63 Mon Sep 17 00:00:00 2001 From: James Lu Date: Sat, 29 Aug 2015 14:06:07 -0700 Subject: [PATCH] Modularize tests using common classes, add our custom test runner (#56) --- conf.py | 17 ++- runtests.py | 22 +++ tests/test_coreplugin.py | 35 +++++ tests/test_proto_inspircd.py | 281 +++++++++++------------------------ tests/tests_common.py | 96 ++++++++++++ 5 files changed, 250 insertions(+), 201 deletions(-) create mode 100755 runtests.py create mode 100644 tests/test_coreplugin.py create mode 100644 tests/tests_common.py diff --git a/conf.py b/conf.py index a70f37b..81bd6b6 100644 --- a/conf.py +++ b/conf.py @@ -23,7 +23,8 @@ testconf = {'bot': 'nick': 'PyLink', 'user': 'pylink', 'realname': 'PyLink Service Client', - 'loglevel': 'INFO', + # Suppress logging in the test output for the most part. + 'loglevel': 'CRITICAL', 'serverdesc': 'PyLink unit tests' }, 'servers': @@ -45,12 +46,12 @@ testconf = {'bot': with open(fname, 'r') as f: global conf - try: - conf = yaml.load(f) - except Exception as e: - if world.testing: - conf = testconf - confname = 'testconf' - else: + if world.testing: + conf = testconf + confname = 'testconf' + else: + try: + conf = yaml.load(f) + except Exception as e: print('ERROR: Failed to load config from %r: %s: %s' % (fname, type(e).__name__, e)) sys.exit(4) diff --git a/runtests.py b/runtests.py new file mode 100755 index 0000000..b5d3e74 --- /dev/null +++ b/runtests.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 + +import unittest +import glob +import imp +import os +import sys + +runner = unittest.TextTestRunner(verbosity=2) +fails = [] +suites = [] + +# Yay, import hacks! +sys.path.append(os.path.join(os.getcwd(), 'tests')) +for testfile in glob.glob('tests/test_*.py'): + # Strip the tests/ and .py extension: tests/test_whatever.py => test_whatever + module = testfile.replace('.py', '').replace('tests/', '') + module = __import__(module) + suites.append(unittest.defaultTestLoader.loadTestsFromModule(module)) + +testsuite = unittest.TestSuite(suites) +runner.run(testsuite) diff --git a/tests/test_coreplugin.py b/tests/test_coreplugin.py new file mode 100644 index 0000000..4480297 --- /dev/null +++ b/tests/test_coreplugin.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python + +import inspircd +import unittest +import world +import coreplugin + +import tests_common + +world.testing = inspircd + +class CorePluginTestCase(tests_common.PluginTestCase): + @unittest.skip("Test doesn't work yet.") + def testKillRespawn(self): + self.irc.run(':9PY KILL {u} :test'.format(u=self.u)) + hooks = self.irc.takeHooks() + + # Make sure we're respawning our PseudoClient when its killed + print(hooks) + spmain = [h for h in hooks if h[1] == 'PYLINK_SPAWNMAIN'] + self.assertTrue(spmain, 'PYLINK_SPAWNMAIN hook was never sent!') + + msgs = self.irc.takeMsgs() + commands = self.irc.takeCommands(msgs) + self.assertIn('UID', commands) + self.assertIn('FJOIN', commands) + + # Also make sure that we're updating the irc.pseudoclient field + self.assertNotEqual(self.irc.pseudoclient.uid, spmain[0]['olduser']) + + def testKickrejoin(self): + self.proto.kickClient(self.irc, self.u, '#pylink', self.u, 'test') + msgs = self.irc.takeMsgs() + commands = self.irc.takeCommands(msgs) + self.assertIn('FJOIN', commands) diff --git a/tests/test_proto_inspircd.py b/tests/test_proto_inspircd.py index 62ee417..3da1cc2 100644 --- a/tests/test_proto_inspircd.py +++ b/tests/test_proto_inspircd.py @@ -6,116 +6,40 @@ from collections import defaultdict import inspircd import classes -import utils -import coreplugin +import world -class TestProtoInspIRCd(unittest.TestCase): - def setUp(self): - self.irc = classes.FakeIRC('unittest', inspircd) - self.proto = self.irc.proto - self.sdata = self.irc.serverdata - # This is to initialize ourself as an internal PseudoServer, so we can spawn clients - self.irc.connect() - self.u = self.irc.pseudoclient.uid - self.maxDiff = None - self.initial_messages = self.irc.takeMsgs() - # Clear the hooks called at startup (spawnmain and possibly others) - self.irc.takeHooks() +import tests_common - def testConnect(self): - commands = self.irc.takeCommands(self.initial_messages) - # SERVER pylink.unittest abcd 0 9PY :PyLink Service - serverline = 'SERVER %s %s 0 %s :PyLink Service' % ( - self.sdata['hostname'], self.sdata['sendpass'], self.sdata['sid']) - self.assertIn(serverline, self.initial_messages) - self.assertIn('BURST', commands) - self.assertIn('ENDBURST', commands) - # Is it creating our lovely PyLink PseudoClient? - self.assertIn('UID', commands) - self.assertIn('FJOIN', commands) +world.testing = inspircd +class InspIRCdTestCase(tests_common.CommonProtoTestCase): def testCheckRecvpass(self): # Correct recvpass here. self.irc.run('SERVER somehow.someday abcd 0 0AL :Somehow Server - McMurdo Station, Antarctica') # Incorrect recvpass here; should raise ProtocolError. self.assertRaises(classes.ProtocolError, self.irc.run, 'SERVER somehow.someday BADPASS 0 0AL :Somehow Server - McMurdo Station, Antarctica') - def testSpawnClient(self): - u = self.proto.spawnClient(self.irc, 'testuser3', 'moo', 'hello.world').uid - # Check the server index and the user index - self.assertIn(u, self.irc.servers[self.irc.sid].users) - self.assertIn(u, self.irc.users) - # Raise ValueError when trying to spawn a client on a server that's not ours - self.assertRaises(ValueError, self.proto.spawnClient, self.irc, 'abcd', 'user', 'dummy.user.net', server='44A') - # Unfilled args should get placeholder fields and not error. - self.proto.spawnClient(self.irc, 'testuser4') - - def testJoinClient(self): - u = self.u - self.proto.joinClient(self.irc, u, '#Channel') - self.assertIn(u, self.irc.channels['#channel'].users) - # Non-existant user. - self.assertRaises(LookupError, self.proto.joinClient, self.irc, '9PYZZZZZZ', '#test') - - def testPartClient(self): - u = self.u - self.proto.joinClient(self.irc, u, '#channel') - self.proto.partClient(self.irc, u, '#channel') - self.assertNotIn(u, self.irc.channels['#channel'].users) - - def testQuitClient(self): - u = self.proto.spawnClient(self.irc, 'testuser3', 'moo', 'hello.world').uid - self.proto.joinClient(self.irc, u, '#channel') - self.assertRaises(LookupError, self.proto.quitClient, self.irc, '9PYZZZZZZ', 'quit reason') - self.proto.quitClient(self.irc, u, 'quit reason') - self.assertNotIn(u, self.irc.channels['#channel'].users) - self.assertNotIn(u, self.irc.users) - self.assertNotIn(u, self.irc.servers[self.irc.sid].users) - - def testKickClient(self): - target = self.proto.spawnClient(self.irc, 'soccerball', 'soccerball', 'abcd').uid - self.proto.joinClient(self.irc, target, '#pylink') - self.assertIn(self.u, self.irc.channels['#pylink'].users) - self.assertIn(target, self.irc.channels['#pylink'].users) - self.proto.kickClient(self.irc, self.u, '#pylink', target, 'Pow!') - self.assertNotIn(target, self.irc.channels['#pylink'].users) - - def testNickClient(self): - self.proto.nickClient(self.irc, self.u, 'NotPyLink') - self.assertEqual('NotPyLink', self.irc.users[self.u].nick) - - def testModeClient(self): - testuser = self.proto.spawnClient(self.irc, 'testcakes') - self.irc.takeMsgs() - self.proto.modeClient(self.irc, self.u, testuser.uid, [('+i', None), ('+w', None)]) - self.assertEqual({('i', None), ('w', None)}, testuser.modes) - - self.proto.modeClient(self.irc, self.u, '#pylink', [('+s', None), ('+l', '30')]) - self.assertEqual({('s', None), ('l', '30')}, self.irc.channels['#pylink'].modes) - - cmds = self.irc.takeCommands(self.irc.takeMsgs()) - self.assertEqual(cmds, ['MODE', 'FMODE']) + def testConnect(self): + self.proto.connect(self.irc) + initial_messages = self.irc.takeMsgs() + commands = self.irc.takeCommands(initial_messages) + # SERVER pylink.unittest abcd 0 9PY :PyLink Service + serverline = 'SERVER %s %s 0 %s :%s' % ( + self.sdata['hostname'], self.sdata['sendpass'], self.sdata['sid'], + self.irc.botdata['serverdesc']) + self.assertIn(serverline, initial_messages) + self.assertIn('BURST', commands) + self.assertIn('ENDBURST', commands) + # Is it creating our lovely PyLink PseudoClient? + self.assertIn('UID', commands) + self.assertIn('FJOIN', commands) def testSpawnServer(self): - # Incorrect SID length - self.assertRaises(Exception, self.proto.spawnServer, self.irc, 'subserver.pylink', '34Q0') - self.proto.spawnServer(self.irc, 'subserver.pylink', '34Q') - # Duplicate server name - self.assertRaises(Exception, self.proto.spawnServer, self.irc, 'Subserver.PyLink', '34Z') - # Duplicate SID - self.assertRaises(Exception, self.proto.spawnServer, self.irc, 'another.Subserver.PyLink', '34Q') - self.assertIn('34Q', self.irc.servers) + super(InspIRCdTestCase, self).testSpawnServer() # Are we bursting properly? self.assertIn(':34Q ENDBURST', self.irc.takeMsgs()) - def testSpawnClientOnServer(self): - self.proto.spawnServer(self.irc, 'subserver.pylink', '34Q') - u = self.proto.spawnClient(self.irc, 'person1', 'person', 'users.overdrive.pw', server='34Q') - # We're spawning clients on the right server, hopefully... - self.assertIn(u.uid, self.irc.servers['34Q'].users) - self.assertNotIn(u.uid, self.irc.servers[self.irc.sid].users) - - def testSquit(self): + def testHandleSQuit(self): # Spawn a messy network map, just because! self.proto.spawnServer(self.irc, 'level1.pylink', '34P') self.proto.spawnServer(self.irc, 'level2.pylink', '34Q', uplink='34P') @@ -145,124 +69,122 @@ class TestProtoInspIRCd(unittest.TestCase): self.assertEqual('test.server', self.irc.servers['0AL'].name) def testHandleUID(self): - self.irc.run('SERVER whatever.net abcd 0 10X :something') self.irc.run(':10X UID 10XAAAAAB 1429934638 GL 0::1 hidden-7j810p.9mdf.lrek.0000.0000.IP gl 0::1 1429934638 +Wioswx +ACGKNOQXacfgklnoqvx :realname') self.assertIn('10XAAAAAB', self.irc.servers['10X'].users) - self.assertIn('10XAAAAAB', self.irc.users) u = self.irc.users['10XAAAAAB'] self.assertEqual('GL', u.nick) + expected = {'uid': '10XAAAAAB', 'ts': '1429934638', 'nick': 'GL', + 'realhost': '0::1', 'ident': 'gl', 'ip': '0::1', + 'host': 'hidden-7j810p.9mdf.lrek.0000.0000.IP'} + hookdata = self.irc.takeHooks()[0][-1] + self.assertEqual(hookdata, expected) + def testHandleKill(self): self.irc.takeMsgs() # Ignore the initial connect messages - utils.add_hook(self.irc.dummyhook, 'KILL') - olduid = self.irc.pseudoclient.uid - self.irc.run(':{u} KILL {u} :killed'.format(u=olduid)) + self.u = self.irc.pseudoclient.uid + self.irc.run(':{u} KILL {u} :killed'.format(u=self.u)) msgs = self.irc.takeMsgs() commands = self.irc.takeCommands(msgs) - hookdata = self.irc.takeHooks()[0] - del hookdata['ts'] - self.assertEqual({'target': olduid, 'text': 'killed'}, hookdata) - # Make sure we're respawning our PseudoClient when its killed - self.assertIn('UID', commands) - self.assertIn('FJOIN', commands) - # Also make sure that we're updating the irc.pseudoclient field - self.assertNotEqual(self.irc.pseudoclient.uid, olduid) + hookdata = self.irc.takeHooks()[0][-1] + self.assertEqual(hookdata['target'], self.u) + self.assertEqual(hookdata['text'], 'killed') + self.assertNotIn(self.u, self.irc.users) def testHandleKick(self): self.irc.takeMsgs() # Ignore the initial connect messages - utils.add_hook(self.irc.dummyhook, 'KICK') self.irc.run(':{u} KICK #pylink {u} :kicked'.format(u=self.irc.pseudoclient.uid)) - hookdata = self.irc.takeHooks()[0] - del hookdata['ts'] - self.assertEqual({'target': self.u, 'text': 'kicked', 'channel': '#pylink'}, hookdata) + hookdata = self.irc.takeHooks()[0][-1] + self.assertEqual(hookdata['target'], self.u) + self.assertEqual(hookdata['text'], 'kicked') + self.assertEqual(hookdata['channel'], '#pylink') - # Ditto above - msgs = self.irc.takeMsgs() - commands = self.irc.takeCommands(msgs) - self.assertIn('FJOIN', commands) - - def testHandleFjoinUsers(self): + def testHandleFJoinUsers(self): self.irc.run(':10X FJOIN #Chat 1423790411 + :,10XAAAAAA ,10XAAAAAB') self.assertEqual({'10XAAAAAA', '10XAAAAAB'}, self.irc.channels['#chat'].users) - # self.assertIn('10XAAAAAB', self.irc.channels['#chat'].users) + self.assertIn('#chat', self.irc.users['10XAAAAAA'].channels) # Sequential FJOINs must NOT remove existing users self.irc.run(':10X FJOIN #Chat 1423790412 + :,10XAAAAAC') # Join list can be empty too, in the case of permanent channels with 0 users. self.irc.run(':10X FJOIN #Chat 1423790413 +nt :') - def testHandleFjoinModes(self): + def testHandleFJoinModes(self): self.irc.run(':10X FJOIN #Chat 1423790411 +nt :,10XAAAAAA ,10XAAAAAB') self.assertEqual({('n', None), ('t', None)}, self.irc.channels['#chat'].modes) # Sequential FJOINs must NOT remove existing modes self.irc.run(':10X FJOIN #Chat 1423790412 + :,10XAAAAAC') self.assertEqual({('n', None), ('t', None)}, self.irc.channels['#chat'].modes) - def testHandleFjoinModesWithArgs(self): + def testHandleFJoinModesWithArgs(self): self.irc.run(':10X FJOIN #Chat 1423790414 +nlks 10 t0psekrit :,10XAAAAAA ,10XAAAAAB') self.assertEqual({('n', None), ('s', None), ('l', '10'), ('k', 't0psekrit')}, self.irc.channels['#chat'].modes) - def testHandleFjoinPrefixes(self): + def testHandleFJoinPrefixes(self): self.irc.run(':10X FJOIN #Chat 1423790418 +nt :ov,10XAAAAAA v,10XAAAAAB ,10XAAAAAC') self.assertEqual({('n', None), ('t', None)}, self.irc.channels['#chat'].modes) self.assertEqual({'10XAAAAAA', '10XAAAAAB', '10XAAAAAC'}, self.irc.channels['#chat'].users) self.assertIn('10XAAAAAA', self.irc.channels['#chat'].prefixmodes['ops']) self.assertEqual({'10XAAAAAA', '10XAAAAAB'}, self.irc.channels['#chat'].prefixmodes['voices']) - def testHandleFjoinHook(self): - utils.add_hook(self.irc.dummyhook, 'JOIN') + def testHandleFJoinHook(self): self.irc.run(':10X FJOIN #PyLink 1423790418 +ls 10 :ov,10XAAAAAA v,10XAAAAAB ,10XAAAAAC') - hookdata = self.irc.takeHooks()[0] + hookdata = self.irc.takeHooks()[0][-1] expected = {'modes': [('+l', '10'), ('+s', None)], 'channel': '#pylink', 'users': ['10XAAAAAA', '10XAAAAAB', '10XAAAAAC'], 'ts': 1423790418} self.assertEqual(expected, hookdata) - def testHandleFmode(self): - self.irc.run(':10X FJOIN #pylink 1423790411 +n :o,10XAAAAAA ,10XAAAAAB') - utils.add_hook(self.irc.dummyhook, 'MODE') + def testHandleFMode(self): self.irc.run(':70M FMODE #pylink 1423790412 +ikl herebedragons 100') - self.assertEqual({('i', None), ('k', 'herebedragons'), ('l', '100'), ('n', None)}, self.irc.channels['#pylink'].modes) + self.assertEqual({('i', None), ('k', 'herebedragons'), ('l', '100')}, self.irc.channels['#pylink'].modes) self.irc.run(':70M FMODE #pylink 1423790413 -ilk+m herebedragons') - self.assertEqual({('m', None), ('n', None)}, self.irc.channels['#pylink'].modes) + self.assertEqual({('m', None)}, self.irc.channels['#pylink'].modes) hookdata = self.irc.takeHooks() - expected = [{'target': '#pylink', 'modes': [('+i', None), ('+k', 'herebedragons'), ('+l', '100')], 'ts': 1423790412}, - {'target': '#pylink', 'modes': [('-i', None), ('-l', None), ('-k', 'herebedragons'), ('+m', None)], 'ts': 1423790413}] + expected = [['70M', 'FMODE', {'target': '#pylink', 'modes': + [('+i', None), ('+k', 'herebedragons'), + ('+l', '100')], 'ts': 1423790412} + ], + ['70M', 'FMODE', {'target': '#pylink', 'modes': + [('-i', None), ('-l', None), + ('-k', 'herebedragons'), ('+m', None)], + 'ts': 1423790413}] + ] self.assertEqual(expected, hookdata) - def testHandleFmodeWithPrefixes(self): - self.irc.run(':70M FJOIN #pylink 1423790411 +n :o,10XAAAAAA ,10XAAAAAB') - utils.add_hook(self.irc.dummyhook, 'MODE') + def testHandleFModeWithPrefixes(self): + self.irc.run(':70M FJOIN #pylink 123 +n :o,10XAAAAAA ,10XAAAAAB') # Prefix modes are stored separately, so they should never show up in .modes self.assertNotIn(('o', '10XAAAAAA'), self.irc.channels['#pylink'].modes) self.assertEqual({'10XAAAAAA'}, self.irc.channels['#pylink'].prefixmodes['ops']) - self.irc.run(':70M FMODE #pylink 1423790412 +lot 50 %s' % self.u) + self.irc.run(':70M FMODE #pylink 123 +lot 50 %s' % self.u) self.assertIn(self.u, self.irc.channels['#pylink'].prefixmodes['ops']) modes = {('l', '50'), ('n', None), ('t', None)} self.assertEqual(modes, self.irc.channels['#pylink'].modes) - self.irc.run(':70M FMODE #pylink 1423790413 -o %s' % self.u) + self.irc.run(':70M FMODE #pylink 123 -o %s' % self.u) self.assertEqual(modes, self.irc.channels['#pylink'].modes) self.assertNotIn(self.u, self.irc.channels['#pylink'].prefixmodes['ops']) # Test hooks hookdata = self.irc.takeHooks() - expected = [{'target': '#pylink', 'modes': [('+l', '50'), ('+o', '9PYAAAAAA'), ('+t', None)], 'ts': 1423790412}, - {'target': '#pylink', 'modes': [('-o', '9PYAAAAAA')], 'ts': 1423790413}] + expected = [['70M', 'FJOIN', {'channel': '#pylink', 'ts': 123, 'modes': [('+n', None)], + 'users': ['10XAAAAAA', '10XAAAAAB']}], + ['70M', 'FMODE', {'target': '#pylink', 'modes': [('+l', '50'), ('+o', '9PYAAAAAA'), ('+t', None)], 'ts': 123}], + ['70M', 'FMODE', {'target': '#pylink', 'modes': [('-o', '9PYAAAAAA')], 'ts': 123}]] self.assertEqual(expected, hookdata) - def testFmodeRemovesOldParams(self): - utils.add_hook(self.irc.dummyhook, 'MODE') + def testHandleFModeRemovesOldParams(self): self.irc.run(':70M FMODE #pylink 1423790412 +l 50') self.assertEqual({('l', '50')}, self.irc.channels['#pylink'].modes) self.irc.run(':70M FMODE #pylink 1423790412 +l 30') self.assertEqual({('l', '30')}, self.irc.channels['#pylink'].modes) hookdata = self.irc.takeHooks() - expected = [{'target': '#pylink', 'modes': [('+l', '50')], 'ts': 1423790412}, - {'target': '#pylink', 'modes': [('+l', '30')], 'ts': 1423790412}] + expected = [['70M', 'FMODE', {'target': '#pylink', 'modes': [('+l', '50')], 'ts': 1423790412}], + ['70M', 'FMODE', {'target': '#pylink', 'modes': [('+l', '30')], 'ts': 1423790412}]] self.assertEqual(expected, hookdata) - def testFjoinResetsTS(self): + def testHandleFJoinResetsTS(self): curr_ts = self.irc.channels['#pylink'].ts self.irc.run(':70M FJOIN #pylink 5 + :') self.assertEqual(self.irc.channels['#pylink'].ts, 5) @@ -273,87 +195,60 @@ class TestProtoInspIRCd(unittest.TestCase): def testHandleTopic(self): self.irc.connect() - utils.add_hook(self.irc.dummyhook, 'TOPIC') self.irc.run(':9PYAAAAAA TOPIC #PyLink :test') self.assertEqual(self.irc.channels['#pylink'].topic, 'test') - hookdata = self.irc.takeHooks()[0] - # Setter is a nick here, not an UID - this is to be consistent - # with FTOPIC above, which sends the nick/prefix of the topic setter. - self.assertTrue(utils.isNick(hookdata.get('setter'))) + hookdata = self.irc.takeHooks()[0][-1] self.assertEqual(type(hookdata['ts']), int) self.assertEqual(hookdata['topic'], 'test') self.assertEqual(hookdata['channel'], '#pylink') - def testMsgHooks(self): + def testHandleMessages(self): for m in ('NOTICE', 'PRIVMSG'): - utils.add_hook(self.irc.dummyhook, m) self.irc.run(':70MAAAAAA %s #dev :afasfsa' % m) - hookdata = self.irc.takeHooks()[0] - del hookdata['ts'] - self.assertEqual({'target': '#dev', 'text': 'afasfsa'}, hookdata) + hookdata = self.irc.takeHooks()[0][-1] + self.assertEqual(hookdata['target'], '#dev') + self.assertEqual(hookdata['text'], 'afasfsa') def testHandlePart(self): - utils.add_hook(self.irc.dummyhook, 'PART') + hookdata = self.irc.takeHooks() self.irc.run(':9PYAAAAAA PART #pylink') - hookdata = self.irc.takeHooks()[0] - del hookdata['ts'] - self.assertEqual({'channel': '#pylink', 'text': ''}, hookdata) - - def testUIDHook(self): - utils.add_hook(self.irc.dummyhook, 'UID') - # Create the server so we won't KeyError on processing UID - self.irc.run('SERVER whatever. abcd 0 10X :Whatever Server - Hellas Planitia, Mars') - self.irc.run(':10X UID 10XAAAAAB 1429934638 GL 0::1 ' - 'hidden-7j810p.9mdf.lrek.0000.0000.IP gl 0::1 1429934638 ' - '+Wioswx +ACGKNOQXacfgklnoqvx :realname') - expected = {'uid': '10XAAAAAB', 'ts': '1429934638', 'nick': 'GL', - 'realhost': '0::1', 'ident': 'gl', 'ip': '0::1', - 'host': 'hidden-7j810p.9mdf.lrek.0000.0000.IP'} - hookdata = self.irc.takeHooks()[0] - self.assertEqual(hookdata, expected) + hookdata = self.irc.takeHooks()[0][-1] + self.assertEqual(hookdata['channels'], ['#pylink']) + self.assertEqual(hookdata['text'], '') def testHandleQuit(self): - utils.add_hook(self.irc.dummyhook, 'QUIT') - self.irc.run('SERVER whatever. abcd 0 10X :Whatever Server - Hellas Planitia, Mars') - self.irc.run(':10X UID 10XAAAAAB 1429934638 GL 0::1 ' - 'hidden-7j810p.9mdf.lrek.0000.0000.IP gl 0::1 1429934638 ' - '+Wioswx +ACGKNOQXacfgklnoqvx :realname') + self.irc.takeHooks() self.irc.run(':10XAAAAAB QUIT :Quit: quit message goes here') - hookdata = self.irc.takeHooks()[0] - del hookdata['ts'] - self.assertEqual(hookdata, {'text': 'Quit: quit message goes here'}) + hookdata = self.irc.takeHooks()[0][-1] + self.assertEqual(hookdata['text'], 'Quit: quit message goes here') self.assertNotIn('10XAAAAAB', self.irc.users) self.assertNotIn('10XAAAAAB', self.irc.servers['10X'].users) def testHandleServer(self): - utils.add_hook(self.irc.dummyhook, 'SERVER') self.irc.run(':00A SERVER test.server * 1 00C :testing raw message syntax') - hookdata = self.irc.takeHooks()[0] - del hookdata['ts'] - self.assertEqual(hookdata, {'name': 'test.server', 'sid': '00C', - 'text': 'testing raw message syntax'}) + hookdata = self.irc.takeHooks()[-1][-1] + self.assertEqual(hookdata['name'], 'test.server') + self.assertEqual(hookdata['sid'], '00C') + self.assertEqual(hookdata['text'], 'testing raw message syntax') self.assertIn('00C', self.irc.servers) def testHandleNick(self): - utils.add_hook(self.irc.dummyhook, 'NICK') self.irc.run(':9PYAAAAAA NICK PyLink-devel 1434744242') - hookdata = self.irc.takeHooks()[0] + hookdata = self.irc.takeHooks()[0][-1] expected = {'newnick': 'PyLink-devel', 'oldnick': 'PyLink', 'ts': 1434744242} self.assertEqual(hookdata, expected) self.assertEqual('PyLink-devel', self.irc.users['9PYAAAAAA'].nick) def testHandleSave(self): - utils.add_hook(self.irc.dummyhook, 'SAVE') self.irc.run(':9PYAAAAAA NICK Derp_ 1433728673') self.irc.run(':70M SAVE 9PYAAAAAA 1433728673') - hookdata = self.irc.takeHooks()[0] - self.assertEqual(hookdata, {'target': '9PYAAAAAA', 'ts': 1433728673}) + hookdata = self.irc.takeHooks()[-1][-1] + self.assertEqual(hookdata, {'target': '9PYAAAAAA', 'ts': 1433728673, 'oldnick': 'Derp_'}) self.assertEqual('9PYAAAAAA', self.irc.users['9PYAAAAAA'].nick) - def testInviteHook(self): - utils.add_hook(self.irc.dummyhook, 'INVITE') + def testHandleInvite(self): self.irc.run(':10XAAAAAA INVITE 9PYAAAAAA #blah 0') - hookdata = self.irc.takeHooks()[0] + hookdata = self.irc.takeHooks()[-1][-1] del hookdata['ts'] self.assertEqual(hookdata, {'target': '9PYAAAAAA', 'channel': '#blah'}) diff --git a/tests/tests_common.py b/tests/tests_common.py new file mode 100644 index 0000000..b3f19f2 --- /dev/null +++ b/tests/tests_common.py @@ -0,0 +1,96 @@ +import sys +import os +sys.path += [os.getcwd(), os.path.join(os.getcwd(), 'protocols')] +import unittest + +import world +import classes + +world.started.set() + +class PluginTestCase(unittest.TestCase): + def setUp(self): + self.irc = classes.FakeIRC('unittest', world.testing) + self.proto = self.irc.proto + self.irc.connect() + self.sdata = self.irc.serverdata + self.u = self.irc.pseudoclient.uid + self.maxDiff = None + # Dummy servers/users used in tests below. + self.proto.spawnServer(self.irc, 'whatever.', sid='10X') + for x in range(3): + self.proto.spawnClient(self.irc, 'user%s' % x, server='10X') + +class CommonProtoTestCase(PluginTestCase): + def testJoinClient(self): + u = self.u + self.proto.joinClient(self.irc, u, '#Channel') + self.assertIn(u, self.irc.channels['#channel'].users) + # Non-existant user. + self.assertRaises(LookupError, self.proto.joinClient, self.irc, '9PYZZZZZZ', '#test') + + def testKickClient(self): + target = self.proto.spawnClient(self.irc, 'soccerball', 'soccerball', 'abcd').uid + self.proto.joinClient(self.irc, target, '#pylink') + self.assertIn(self.u, self.irc.channels['#pylink'].users) + self.assertIn(target, self.irc.channels['#pylink'].users) + self.proto.kickClient(self.irc, self.u, '#pylink', target, 'Pow!') + self.assertNotIn(target, self.irc.channels['#pylink'].users) + + def testModeClient(self): + testuser = self.proto.spawnClient(self.irc, 'testcakes') + self.irc.takeMsgs() + self.proto.modeClient(self.irc, self.u, testuser.uid, [('+i', None), ('+w', None)]) + self.assertEqual({('i', None), ('w', None)}, testuser.modes) + + self.proto.modeClient(self.irc, self.u, '#pylink', [('+s', None), ('+l', '30')]) + self.assertEqual({('s', None), ('l', '30')}, self.irc.channels['#pylink'].modes) + + cmds = self.irc.takeCommands(self.irc.takeMsgs()) + self.assertEqual(cmds, ['MODE', 'FMODE']) + + def testNickClient(self): + self.proto.nickClient(self.irc, self.u, 'NotPyLink') + self.assertEqual('NotPyLink', self.irc.users[self.u].nick) + + def testPartClient(self): + u = self.u + self.proto.joinClient(self.irc, u, '#channel') + self.proto.partClient(self.irc, u, '#channel') + self.assertNotIn(u, self.irc.channels['#channel'].users) + + def testQuitClient(self): + u = self.proto.spawnClient(self.irc, 'testuser3', 'moo', 'hello.world').uid + self.proto.joinClient(self.irc, u, '#channel') + self.assertRaises(LookupError, self.proto.quitClient, self.irc, '9PYZZZZZZ', 'quit reason') + self.proto.quitClient(self.irc, u, 'quit reason') + self.assertNotIn(u, self.irc.channels['#channel'].users) + self.assertNotIn(u, self.irc.users) + self.assertNotIn(u, self.irc.servers[self.irc.sid].users) + + def testSpawnClient(self): + u = self.proto.spawnClient(self.irc, 'testuser3', 'moo', 'hello.world').uid + # Check the server index and the user index + self.assertIn(u, self.irc.servers[self.irc.sid].users) + self.assertIn(u, self.irc.users) + # Raise ValueError when trying to spawn a client on a server that's not ours + self.assertRaises(ValueError, self.proto.spawnClient, self.irc, 'abcd', 'user', 'dummy.user.net', server='44A') + # Unfilled args should get placeholder fields and not error. + self.proto.spawnClient(self.irc, 'testuser4') + + def testSpawnClientOnServer(self): + self.proto.spawnServer(self.irc, 'subserver.pylink', '34Q') + u = self.proto.spawnClient(self.irc, 'person1', 'person', 'users.overdrive.pw', server='34Q') + # We're spawning clients on the right server, hopefully... + self.assertIn(u.uid, self.irc.servers['34Q'].users) + self.assertNotIn(u.uid, self.irc.servers[self.irc.sid].users) + + def testSpawnServer(self): + # Incorrect SID length + self.assertRaises(Exception, self.proto.spawnServer, self.irc, 'subserver.pylink', '34Q0') + self.proto.spawnServer(self.irc, 'subserver.pylink', '34Q') + # Duplicate server name + self.assertRaises(Exception, self.proto.spawnServer, self.irc, 'Subserver.PyLink', '34Z') + # Duplicate SID + self.assertRaises(Exception, self.proto.spawnServer, self.irc, 'another.Subserver.PyLink', '34Q') + self.assertIn('34Q', self.irc.servers)