From 706e794df61a492f3feec1f541b6dc458603819a Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Wed, 21 Oct 2020 11:08:14 -0400 Subject: [PATCH] test for mute extban --- irctest/cases.py | 25 +++++- irctest/irc_utils/junkdrawer.py | 6 +- irctest/irc_utils/random.py | 4 - .../server_tests/test_channel_operations.py | 84 +++++++++++++++++++ irctest/server_tests/test_chathistory.py | 3 +- irctest/server_tests/test_echo_message.py | 2 +- irctest/server_tests/test_relaymsg.py | 2 +- irctest/server_tests/test_roleplay.py | 2 +- irctest/server_tests/test_statusmsg.py | 13 +-- irctest/server_tests/test_znc_playback.py | 2 +- 10 files changed, 118 insertions(+), 25 deletions(-) delete mode 100644 irctest/irc_utils/random.py diff --git a/irctest/cases.py b/irctest/cases.py index 91565d5..79632a6 100644 --- a/irctest/cases.py +++ b/irctest/cases.py @@ -9,7 +9,7 @@ from . import runner from . import client_mock from .irc_utils import capabilities from .irc_utils import message_parser -from .irc_utils.junkdrawer import normalizeWhitespace +from .irc_utils.junkdrawer import normalizeWhitespace, random_name from .irc_utils.sasl import sasl_plain_blob from .exceptions import ConnectionClosed from .specifications import Specifications @@ -327,7 +327,7 @@ class BaseServerTestCase(_IrcTestCase): return result def connectClient(self, nick, name=None, capabilities=None, - skip_if_cap_nak=False, show_io=None, password=None): + skip_if_cap_nak=False, show_io=None, password=None, ident='username'): client = self.addClient(name, show_io=show_io) if capabilities is not None and 0 < len(capabilities): self.sendLine(client, 'CAP REQ :{}'.format(' '.join(capabilities))) @@ -348,7 +348,7 @@ class BaseServerTestCase(_IrcTestCase): self.sendLine(client, 'AUTHENTICATE PLAIN') self.sendLine(client, sasl_plain_blob(nick, password)) self.sendLine(client, 'NICK {}'.format(nick)) - self.sendLine(client, 'USER username * * :Realname') + self.sendLine(client, 'USER %s * * :Realname' % (ident,)) welcome = self.skipToWelcome(client) self.sendLine(client, 'PING foo') @@ -388,6 +388,25 @@ class BaseServerTestCase(_IrcTestCase): joined = True break + def getISupport(self): + cn = random_name('bar') + self.addClient(name=cn) + self.sendLine(cn, 'NICK %s' % (cn,)) + self.sendLine(cn, 'USER u s e r') + messages = self.getMessages(cn) + isupport = {} + for message in messages: + if message.command != '005': + continue + # 005 nick :are supported by this server + tokens = message.params[1:-1] + for token in tokens: + name, _, value = token.partition('=') + isupport[name] = value + self.sendLine(cn, 'QUIT') + self.assertDisconnected(cn) + return isupport + class OptionalityHelper: def checkSaslSupport(self): if self.controller.supported_sasl_mechanisms: diff --git a/irctest/irc_utils/junkdrawer.py b/irctest/irc_utils/junkdrawer.py index 25b4ac5..3428dc6 100644 --- a/irctest/irc_utils/junkdrawer.py +++ b/irctest/irc_utils/junkdrawer.py @@ -1,5 +1,6 @@ import datetime import re +import secrets from collections import namedtuple HistoryMessage = namedtuple('HistoryMessage', ['time', 'msgid', 'target', 'text']) @@ -13,6 +14,9 @@ IRCV3_FORMAT_STRFTIME = "%Y-%m-%dT%H:%M:%S.%f%z" def ircv3_timestamp_to_unixtime(timestamp): return datetime.datetime.strptime(timestamp, IRCV3_FORMAT_STRFTIME).timestamp() +def random_name(base): + return base + '-' + secrets.token_hex(8) + """ Stolen from supybot: """ @@ -46,4 +50,4 @@ def normalizeWhitespace(s, removeNewline=True): s = ' ' + s if ends_with_space: s += ' ' - retur + return s diff --git a/irctest/irc_utils/random.py b/irctest/irc_utils/random.py deleted file mode 100644 index c3d954b..0000000 --- a/irctest/irc_utils/random.py +++ /dev/null @@ -1,4 +0,0 @@ -import secrets - -def random_name(base): - return base + '-' + secrets.token_hex(8) diff --git a/irctest/server_tests/test_channel_operations.py b/irctest/server_tests/test_channel_operations.py index 10dd962..9a90b69 100644 --- a/irctest/server_tests/test_channel_operations.py +++ b/irctest/server_tests/test_channel_operations.py @@ -878,3 +878,87 @@ class OpModerated(cases.BaseServerTestCase): self.assertMessageEqual(echo, command='PRIVMSG', params=['#chan', 'hi again from qux']) self.assertEqual([msg for msg in self.getMessages('chanop') if msg.command == 'PRIVMSG'], [echo]) self.assertEqual([msg for msg in self.getMessages('baz') if msg.command == 'PRIVMSG'], [echo]) + + +class MuteExtban(cases.BaseServerTestCase): + + @cases.SpecificationSelector.requiredBySpecification('Oragono') + def testISupport(self): + isupport = self.getISupport() + token = isupport['EXTBAN'] + prefix, comma, types = token.partition(',') + self.assertEqual(prefix, '') + self.assertEqual(comma, ',') + self.assertIn('m', types) + + @cases.SpecificationSelector.requiredBySpecification('Oragono') + def testMuteExtban(self): + clients = ('chanop', 'bar', 'qux') + + self.connectClient('chanop', name='chanop', capabilities=MODERN_CAPS) + self.joinChannel('chanop', '#chan') + self.getMessages('chanop') + self.sendLine('chanop', 'MODE #chan +b m:bar!*@*') + self.sendLine('chanop', 'MODE #chan +b m:qux!*@*') + replies = {msg.command for msg in self.getMessages('chanop')} + self.assertIn('MODE', replies) + self.assertNotIn(ERR_CHANOPRIVSNEEDED, replies) + + self.connectClient('bar', name='bar', capabilities=MODERN_CAPS) + self.joinChannel('bar', '#chan') + self.connectClient('qux', name='qux', capabilities=MODERN_CAPS, ident='evan') + self.joinChannel('qux', '#chan') + + for client in clients: + self.getMessages(client) + + self.sendLine('bar', 'PRIVMSG #chan :hi from bar') + replies = self.getMessages('bar') + replies_cmds = {msg.command for msg in replies} + self.assertNotIn('PRIVMSG', replies_cmds) + self.assertIn(ERR_CANNOTSENDTOCHAN, replies_cmds) + self.assertEqual(self.getMessages('chanop'), []) + + self.sendLine('qux', 'PRIVMSG #chan :hi from qux') + replies = self.getMessages('qux') + replies_cmds = {msg.command for msg in replies} + self.assertNotIn('PRIVMSG', replies_cmds) + self.assertIn(ERR_CANNOTSENDTOCHAN, replies_cmds) + self.assertEqual(self.getMessages('chanop'), []) + + # remove mute with -b + self.sendLine('chanop', 'MODE #chan -b m:bar!*@*') + self.getMessages('chanop') + self.sendLine('bar', 'PRIVMSG #chan :hi again from bar') + replies = self.getMessages('bar') + replies_cmds = {msg.command for msg in replies} + self.assertIn('PRIVMSG', replies_cmds) + self.assertNotIn(ERR_CANNOTSENDTOCHAN, replies_cmds) + self.assertEqual(self.getMessages('chanop'), [msg for msg in replies if msg.command == 'PRIVMSG']) + + for client in clients: + self.getMessages(client) + + # +v grants an exemption to +b + self.sendLine('chanop', 'MODE #chan +v qux') + self.getMessages('chanop') + self.sendLine('qux', 'PRIVMSG #chan :hi again from qux') + replies = self.getMessages('qux') + replies_cmds = {msg.command for msg in replies} + self.assertIn('PRIVMSG', replies_cmds) + self.assertNotIn(ERR_CANNOTSENDTOCHAN, replies_cmds) + self.assertEqual(self.getMessages('chanop'), [msg for msg in replies if msg.command == 'PRIVMSG']) + + self.sendLine('qux', 'PART #chan') + self.sendLine('qux', 'JOIN #chan') + self.getMessages('qux') + self.sendLine('chanop', 'MODE #chan +e m:*!~evan@*') + self.getMessages('chanop') + + # +e grants an exemption to +b + self.sendLine('qux', 'PRIVMSG #chan :thanks for mute-excepting me') + replies = self.getMessages('qux') + replies_cmds = {msg.command for msg in replies} + self.assertIn('PRIVMSG', replies_cmds) + self.assertNotIn(ERR_CANNOTSENDTOCHAN, replies_cmds) + self.assertEqual(self.getMessages('chanop'), [msg for msg in replies if msg.command == 'PRIVMSG']) diff --git a/irctest/server_tests/test_chathistory.py b/irctest/server_tests/test_chathistory.py index a7e51e8..797ae54 100644 --- a/irctest/server_tests/test_chathistory.py +++ b/irctest/server_tests/test_chathistory.py @@ -2,8 +2,7 @@ import secrets import time from irctest import cases -from irctest.irc_utils.junkdrawer import to_history_message -from irctest.irc_utils.random import random_name +from irctest.irc_utils.junkdrawer import to_history_message, random_name CHATHISTORY_CAP = 'draft/chathistory' EVENT_PLAYBACK_CAP = 'draft/event-playback' diff --git a/irctest/server_tests/test_echo_message.py b/irctest/server_tests/test_echo_message.py index 84eebcc..8de1b82 100644 --- a/irctest/server_tests/test_echo_message.py +++ b/irctest/server_tests/test_echo_message.py @@ -4,7 +4,7 @@ from irctest import cases from irctest.basecontrollers import NotImplementedByController -from irctest.irc_utils.random import random_name +from irctest.irc_utils.junkdrawer import random_name class DMEchoMessageTestCase(cases.BaseServerTestCase): diff --git a/irctest/server_tests/test_relaymsg.py b/irctest/server_tests/test_relaymsg.py index 5322529..407e9c7 100644 --- a/irctest/server_tests/test_relaymsg.py +++ b/irctest/server_tests/test_relaymsg.py @@ -1,5 +1,5 @@ from irctest import cases -from irctest.irc_utils.random import random_name +from irctest.irc_utils.junkdrawer import random_name from irctest.server_tests.test_chathistory import CHATHISTORY_CAP, EVENT_PLAYBACK_CAP diff --git a/irctest/server_tests/test_roleplay.py b/irctest/server_tests/test_roleplay.py index 4261730..4ef9ce5 100644 --- a/irctest/server_tests/test_roleplay.py +++ b/irctest/server_tests/test_roleplay.py @@ -1,6 +1,6 @@ from irctest import cases from irctest.numerics import ERR_CANNOTSENDRP -from irctest.irc_utils.random import random_name +from irctest.irc_utils.junkdrawer import random_name class RoleplayTestCase(cases.BaseServerTestCase): diff --git a/irctest/server_tests/test_statusmsg.py b/irctest/server_tests/test_statusmsg.py index ae31249..7414908 100644 --- a/irctest/server_tests/test_statusmsg.py +++ b/irctest/server_tests/test_statusmsg.py @@ -1,5 +1,4 @@ from irctest import cases -from irctest.numerics import RPL_ISUPPORT from irctest.numerics import RPL_NAMREPLY class StatusmsgTestCase(cases.BaseServerTestCase): @@ -7,16 +6,8 @@ class StatusmsgTestCase(cases.BaseServerTestCase): @cases.SpecificationSelector.requiredBySpecification('Oragono') def testInIsupport(self): """Check that the expected STATUSMSG parameter appears in our isupport list.""" - self.addClient() - self.sendLine(1, 'USER foo foo foo :foo') - self.sendLine(1, 'NICK bar') - self.skipToWelcome(1) - messages = self.getMessages(1) - isupport = set() - for message in messages: - if message.command == RPL_ISUPPORT: - isupport.update(message.params) - self.assertIn('STATUSMSG=~&@%+', isupport) + isupport = self.getISupport() + self.assertEqual(isupport['STATUSMSG'], '~&@%+') @cases.SpecificationSelector.requiredBySpecification('Oragono') def testStatusmsg(self): diff --git a/irctest/server_tests/test_znc_playback.py b/irctest/server_tests/test_znc_playback.py index 9237ef9..bffe888 100644 --- a/irctest/server_tests/test_znc_playback.py +++ b/irctest/server_tests/test_znc_playback.py @@ -3,7 +3,7 @@ import time from irctest import cases from irctest.irc_utils.junkdrawer import ircv3_timestamp_to_unixtime from irctest.irc_utils.junkdrawer import to_history_message -from irctest.irc_utils.random import random_name +from irctest.irc_utils.junkdrawer import random_name def extract_playback_privmsgs(messages):