mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-24 03:29:28 +01:00
Many fixes to test API, utils.reverseModes stub
This commit is contained in:
parent
ab4cb4d895
commit
ad5fc97e21
30
classes.py
30
classes.py
@ -311,29 +311,6 @@ class IrcChannel():
|
|||||||
|
|
||||||
### FakeIRC classes, used for test cases
|
### FakeIRC classes, used for test cases
|
||||||
|
|
||||||
global testconf
|
|
||||||
testconf = {'bot':
|
|
||||||
{
|
|
||||||
'nick': 'PyLink',
|
|
||||||
'user': 'pylink',
|
|
||||||
'realname': 'PyLink Service Client',
|
|
||||||
'loglevel': 'DEBUG',
|
|
||||||
},
|
|
||||||
'servers':
|
|
||||||
{'unittest':
|
|
||||||
{
|
|
||||||
'ip': '0.0.0.0',
|
|
||||||
'port': 7000,
|
|
||||||
'recvpass': "abcd",
|
|
||||||
'sendpass': "abcd",
|
|
||||||
'protocol': "null",
|
|
||||||
'hostname': "pylink.unittest",
|
|
||||||
'sid': "9PY",
|
|
||||||
'channels': ["#pylink"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
class FakeIRC(Irc):
|
class FakeIRC(Irc):
|
||||||
def connect(self):
|
def connect(self):
|
||||||
self.messages = []
|
self.messages = []
|
||||||
@ -382,11 +359,16 @@ class FakeIRC(Irc):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def dummyhook(irc, source, command, parsed_args):
|
def dummyhook(irc, source, command, parsed_args):
|
||||||
"""Dummy function to bind to hooks."""
|
"""Dummy function to bind to hooks. This is what allows takeHooks() to work."""
|
||||||
irc.hookmsgs.append(parsed_args)
|
irc.hookmsgs.append(parsed_args)
|
||||||
|
|
||||||
class FakeProto():
|
class FakeProto():
|
||||||
"""Dummy protocol module for testing purposes."""
|
"""Dummy protocol module for testing purposes."""
|
||||||
|
def __init__(self):
|
||||||
|
self.hook_map = {}
|
||||||
|
self.casemapping = 'rfc1459'
|
||||||
|
self.__name__ = 'FakeProto'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handle_events(irc, data):
|
def handle_events(irc, data):
|
||||||
pass
|
pass
|
||||||
|
37
conf.py
37
conf.py
@ -1,5 +1,8 @@
|
|||||||
import yaml
|
import yaml
|
||||||
import sys
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
import world
|
||||||
|
|
||||||
global confname
|
global confname
|
||||||
try:
|
try:
|
||||||
@ -14,6 +17,40 @@ except IndexError:
|
|||||||
confname = 'pylink'
|
confname = 'pylink'
|
||||||
fname = 'config.yml'
|
fname = 'config.yml'
|
||||||
|
|
||||||
|
global testconf
|
||||||
|
testconf = {'bot':
|
||||||
|
{
|
||||||
|
'nick': 'PyLink',
|
||||||
|
'user': 'pylink',
|
||||||
|
'realname': 'PyLink Service Client',
|
||||||
|
'loglevel': 'DEBUG',
|
||||||
|
'serverdesc': 'PyLink unit tests'
|
||||||
|
},
|
||||||
|
'servers':
|
||||||
|
# Wildcard defaultdict! This means that
|
||||||
|
# any network name you try will work and return
|
||||||
|
# this basic template:
|
||||||
|
defaultdict(lambda: {
|
||||||
|
'ip': '0.0.0.0',
|
||||||
|
'port': 7000,
|
||||||
|
'recvpass': "abcd",
|
||||||
|
'sendpass': "chucknorris",
|
||||||
|
'protocol': "null",
|
||||||
|
'hostname': "pylink.unittest",
|
||||||
|
'sid': "9PY",
|
||||||
|
'channels': ["#pylink"],
|
||||||
|
'maxnicklen': 20
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
with open(fname, 'r') as f:
|
with open(fname, 'r') as f:
|
||||||
global conf
|
global conf
|
||||||
|
try:
|
||||||
conf = yaml.load(f)
|
conf = yaml.load(f)
|
||||||
|
except Exception as e:
|
||||||
|
if world.testing:
|
||||||
|
conf = testconf
|
||||||
|
confname = 'testconf'
|
||||||
|
else:
|
||||||
|
print('ERROR: Failed to load config from %r: %s: %s' % (fname, type(e).__name__, e))
|
||||||
|
sys.exit(4)
|
||||||
|
2
main.py
2
main.py
@ -9,8 +9,10 @@ import conf
|
|||||||
import classes
|
import classes
|
||||||
import utils
|
import utils
|
||||||
import coreplugin
|
import coreplugin
|
||||||
|
import world
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
world.testing = False
|
||||||
log.info('PyLink starting...')
|
log.info('PyLink starting...')
|
||||||
if conf.conf['login']['password'] == 'changeme':
|
if conf.conf['login']['password'] == 'changeme':
|
||||||
log.critical("You have not set the login details correctly! Exiting...")
|
log.critical("You have not set the login details correctly! Exiting...")
|
||||||
|
@ -7,34 +7,41 @@ import unittest
|
|||||||
import utils
|
import utils
|
||||||
import classes
|
import classes
|
||||||
import relay
|
import relay
|
||||||
|
import conf
|
||||||
|
|
||||||
def dummyf():
|
def dummyf():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class TestRelay(unittest.TestCase):
|
class TestRelay(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.irc = classes.FakeIRC('unittest', classes.FakeProto(), classes.testconf)
|
self.irc = classes.FakeIRC('unittest', classes.FakeProto(), conf.testconf)
|
||||||
self.irc.maxnicklen = 20
|
self.irc.maxnicklen = 20
|
||||||
self.irc.proto.__name__ = "test"
|
self.f = lambda nick: relay.normalizeNick(self.irc, 'unittest', nick)
|
||||||
self.f = relay.normalizeNick
|
# Fake our protocol name to something that supports slashes in nicks.
|
||||||
|
# relay uses a whitelist for this to prevent accidentally introducing
|
||||||
|
# bad nicks:
|
||||||
|
self.irc.proto.__name__ = "inspircd"
|
||||||
|
|
||||||
def testNormalizeNick(self):
|
def testNormalizeNick(self):
|
||||||
# Second argument simply states the suffix.
|
# Second argument simply states the suffix.
|
||||||
self.assertEqual(self.f(self.irc, 'unittest', 'helloworld'), 'helloworld/unittest')
|
self.assertEqual(self.f('helloworld'), 'helloworld/unittest')
|
||||||
self.assertEqual(self.f(self.irc, 'unittest', 'ObnoxiouslyLongNick'), 'Obnoxiously/unittest')
|
self.assertEqual(self.f('ObnoxiouslyLongNick'), 'Obnoxiously/unittest')
|
||||||
self.assertEqual(self.f(self.irc, 'unittest', '10XAAAAAA'), '_10XAAAAAA/unittest')
|
self.assertEqual(self.f('10XAAAAAA'), '_10XAAAAAA/unittest')
|
||||||
|
|
||||||
def testNormalizeNickConflict(self):
|
def testNormalizeNickConflict(self):
|
||||||
self.assertEqual(self.f(self.irc, 'unittest', 'helloworld'), 'helloworld/unittest')
|
self.assertEqual(self.f('helloworld'), 'helloworld/unittest')
|
||||||
self.irc.users['10XAAAAAA'] = classes.IrcUser('helloworld/unittest', 1234, '10XAAAAAA')
|
self.irc.users['10XAAAAAA'] = classes.IrcUser('helloworld/unittest', 1234, '10XAAAAAA')
|
||||||
# Increase amount of /'s by one
|
# Increase amount of /'s by one
|
||||||
self.assertEqual(self.f(self.irc, 'unittest', 'helloworld'), 'helloworld//unittest')
|
self.assertEqual(self.f('helloworld'), 'helloworld//unittest')
|
||||||
self.irc.users['10XAAAAAB'] = classes.IrcUser('helloworld//unittest', 1234, '10XAAAAAB')
|
self.irc.users['10XAAAAAB'] = classes.IrcUser('helloworld//unittest', 1234, '10XAAAAAB')
|
||||||
# Cut off the nick, not the suffix if the result is too long.
|
# Cut off the nick, not the suffix if the result is too long.
|
||||||
self.assertEqual(self.f(self.irc, 'unittest', 'helloworld'), 'helloworl///unittest')
|
self.assertEqual(self.f('helloworld'), 'helloworl///unittest')
|
||||||
|
|
||||||
def testNormalizeNickRemovesSlashes(self):
|
def testNormalizeNickRemovesSlashes(self):
|
||||||
self.irc.proto.__name__ = "charybdis"
|
self.irc.proto.__name__ = "charybdis"
|
||||||
self.assertEqual(self.f(self.irc, 'unittest', 'helloworld'), 'helloworld|unittest')
|
try:
|
||||||
self.assertEqual(self.f(self.irc, 'unittest', 'abcde/eJanus'), 'abcde|eJanu|unittest')
|
self.assertEqual(self.f('helloworld'), 'helloworld|unittest')
|
||||||
self.assertEqual(self.f(self.irc, 'unittest', 'ObnoxiouslyLongNick'), 'Obnoxiously|unittest')
|
self.assertEqual(self.f('abcde/eJanus'), 'abcde|eJanu|unittest')
|
||||||
|
self.assertEqual(self.f('ObnoxiouslyLongNick'), 'Obnoxiously|unittest')
|
||||||
|
finally:
|
||||||
|
self.irc.proto.__name__ = "inspircd"
|
||||||
|
@ -5,11 +5,16 @@ import unittest
|
|||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
import utils
|
import utils
|
||||||
|
import classes
|
||||||
|
import conf
|
||||||
|
|
||||||
def dummyf():
|
def dummyf():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class TestUtils(unittest.TestCase):
|
class TestUtils(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.irc = classes.FakeIRC('fakeirc', classes.FakeProto(), conf.testconf)
|
||||||
|
|
||||||
def testTS6UIDGenerator(self):
|
def testTS6UIDGenerator(self):
|
||||||
uidgen = utils.TS6UIDGenerator('9PY')
|
uidgen = utils.TS6UIDGenerator('9PY')
|
||||||
self.assertEqual(uidgen.next_uid(), '9PYAAAAAA')
|
self.assertEqual(uidgen.next_uid(), '9PYAAAAAA')
|
||||||
@ -96,5 +101,19 @@ class TestUtils(unittest.TestCase):
|
|||||||
('+b', '*!*@*.badisp.net')])
|
('+b', '*!*@*.badisp.net')])
|
||||||
self.assertEqual(res, '-o+l-nm+kb 9PYAAAAAA 50 hello *!*@*.badisp.net')
|
self.assertEqual(res, '-o+l-nm+kb 9PYAAAAAA 50 hello *!*@*.badisp.net')
|
||||||
|
|
||||||
|
@unittest.skip('Wait, we need to work out the kinks first! (reversing changes of modes with arguments)')
|
||||||
|
def testReverseModes(self):
|
||||||
|
f = lambda x: utils.reverseModes(self.irc, '#test', x)
|
||||||
|
# Strings.
|
||||||
|
self.assertEqual(f("+nt-lk"), "-nt+lk")
|
||||||
|
self.assertEqual(f("nt-k"), "-nt+k")
|
||||||
|
# Lists.
|
||||||
|
self.assertEqual(f([('+m', None), ('+t', None), ('+l', '3'), ('-o', 'person')]),
|
||||||
|
[('-m', None), ('-t', None), ('-l', '3'), ('+o', 'person')])
|
||||||
|
# Sets.
|
||||||
|
self.assertEqual(f({('s', None), ('+o', 'whoever')}), {('-s', None), ('-o', 'whoever')})
|
||||||
|
# Combining modes with an initial + and those without
|
||||||
|
self.assertEqual(f({('s', None), ('+n', None)}), {('-s', None), ('-n', None)})
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
30
utils.py
30
utils.py
@ -165,7 +165,7 @@ def isServerName(s):
|
|||||||
return _isASCII(s) and '.' in s and not s.startswith('.')
|
return _isASCII(s) and '.' in s and not s.startswith('.')
|
||||||
|
|
||||||
def parseModes(irc, target, args):
|
def parseModes(irc, target, args):
|
||||||
"""Parses a mode string into a list of (mode, argument) tuples.
|
"""Parses a modestring list into a list of (mode, argument) tuples.
|
||||||
['+mitl-o', '3', 'person'] => [('+m', None), ('+i', None), ('+t', None), ('+l', '3'), ('-o', 'person')]
|
['+mitl-o', '3', 'person'] => [('+m', None), ('+i', None), ('+t', None), ('+l', '3'), ('-o', 'person')]
|
||||||
"""
|
"""
|
||||||
# http://www.irc.org/tech_docs/005.html
|
# http://www.irc.org/tech_docs/005.html
|
||||||
@ -337,6 +337,34 @@ def joinModes(modes):
|
|||||||
modelist += ' %s' % ' '.join(args)
|
modelist += ' %s' % ' '.join(args)
|
||||||
return modelist
|
return modelist
|
||||||
|
|
||||||
|
def reverseModes(irc, target, modes):
|
||||||
|
"""<mode string/mode list>
|
||||||
|
|
||||||
|
Reverses/Inverts the mode string or mode list given.
|
||||||
|
|
||||||
|
"+nt-lk" => "-nt+lk"
|
||||||
|
"nt-k" => "-nt+k"
|
||||||
|
[('+m', None), ('+t', None), ('+l', '3'), ('-o', 'person')] =>
|
||||||
|
[('-m', None), ('-t', None), ('-l', '3'), ('+o', 'person')]
|
||||||
|
[('s', None), ('+n', None)] => [('-s', None), ('-n', None)]
|
||||||
|
"""
|
||||||
|
origtype = type(modes)
|
||||||
|
# Operate on joined modestrings only; it's easier.
|
||||||
|
if origtype != str:
|
||||||
|
modes = joinModes(modes)
|
||||||
|
# Swap the +'s and -'s by replacing one with a dummy character, and then changing it back.
|
||||||
|
assert '\x00' not in modes, 'NUL cannot be in the mode list (it is a reserved character)!'
|
||||||
|
if not modes.startswith(('+', '-')):
|
||||||
|
modes = '+' + modes
|
||||||
|
newmodes = modes.replace('+', '\x00')
|
||||||
|
newmodes = newmodes.replace('-', '+')
|
||||||
|
newmodes = newmodes.replace('\x00', '-')
|
||||||
|
if origtype != str:
|
||||||
|
# If the original query isn't a string, send back the parseModes() output.
|
||||||
|
return parseModes(irc, target, newmodes.split(" "))
|
||||||
|
else:
|
||||||
|
return newmodes
|
||||||
|
|
||||||
def isInternalClient(irc, numeric):
|
def isInternalClient(irc, numeric):
|
||||||
"""<irc object> <client numeric>
|
"""<irc object> <client numeric>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user