Make assertion messages readable by people who are not me.

This commit is contained in:
Valentin Lorentz 2015-12-21 21:48:59 +01:00
parent 8cdd6d4d9e
commit 647894b50f
5 changed files with 85 additions and 32 deletions

View File

@ -32,7 +32,7 @@ class _IrcTestCase(unittest.TestCase):
if self.show_io:
print('---- new test ----')
def assertMessageEqual(self, msg, subcommand=None, subparams=None,
target=None, **kwargs):
target=None, fail_msg=None, **kwargs):
"""Helper for partially comparing a message.
Takes the message as first arguments, and comparisons to be made
@ -41,19 +41,27 @@ class _IrcTestCase(unittest.TestCase):
Deals with subcommands (eg. `CAP`) if any of `subcommand`,
`subparams`, and `target` are given."""
for (key, value) in kwargs.items():
#with self.subTest(key=key):
self.assertEqual(getattr(msg, key), value, msg)
self.assertEqual(getattr(msg, key), value, msg, fail_msg)
if subcommand is not None or subparams is not None:
self.assertGreater(len(msg.params), 2, msg)
self.assertGreater(len(msg.params), 2, fail_msg)
msg_target = msg.params[0]
msg_subcommand = msg.params[1]
msg_subparams = msg.params[2:]
if subcommand:
with self.subTest(key='subcommand'):
self.assertEqual(msg_subcommand, subcommand, msg)
self.assertEqual(msg_subcommand, subcommand, msg, fail_msg)
if subparams is not None:
with self.subTest(key='subparams'):
self.assertEqual(msg_subparams, subparams, msg)
self.assertEqual(msg_subparams, subparams, msg, fail_msg)
def assertIn(self, got, expects, msg=None, fail_msg=None):
if fail_msg:
fail_msg = fail_msg.format(got=got, expects=expects, msg=msg)
super().assertIn(got, expects, fail_msg)
def assertEqual(self, got, expects, msg=None, fail_msg=None):
if fail_msg:
fail_msg = fail_msg.format(got=got, expects=expects, msg=msg)
super().assertEqual(got, expects, fail_msg)
class BaseClientTestCase(_IrcTestCase):
"""Basic class for client tests. Handles spawning a client and exchanging

View File

@ -17,7 +17,8 @@ class CapTestCase(cases.BaseServerTestCase):
self.sendLine(1, 'NICK foo')
self.sendLine(1, 'CAP END')
m = self.getRegistrationMessage(1)
self.assertMessageEqual(m, command='001')
self.assertMessageEqual(m, command='001',
fail_msg='Expected 001 after sending CAP END, got {msg}.')
def testReqUnavailable(self):
"""Test the server handles gracefully clients which request
@ -32,10 +33,13 @@ class CapTestCase(cases.BaseServerTestCase):
self.sendLine(1, 'CAP REQ :foo')
m = self.getRegistrationMessage(1)
self.assertMessageEqual(m, command='CAP',
subcommand='NAK', subparams=['foo'])
subcommand='NAK', subparams=['foo'],
fail_msg='Expected CAP NAK after requesting non-existing '
'capability, got {msg}.')
self.sendLine(1, 'CAP END')
m = self.getRegistrationMessage(1)
self.assertEqual(m.command, '001')
self.assertMessageEqual(m, command='001',
fail_msg='Expected 001 after sending CAP END, got {msg}.')
def testNakExactString(self):
"""“The argument of the NAK subcommand MUST consist of at least the
@ -48,10 +52,12 @@ class CapTestCase(cases.BaseServerTestCase):
self.getCapLs(1)
# Five should be enough to check there is no reordering, even
# alphabetical
self.sendLine(1, 'CAP REQ :foo bar baz qux quux')
self.sendLine(1, 'CAP REQ :foo qux bar baz qux quux')
m = self.getRegistrationMessage(1)
self.assertMessageEqual(m, command='CAP',
subcommand='NAK', subparams=['foo bar baz qux quux'])
subcommand='NAK', subparams=['foo qux bar baz qux quux'],
fail_msg='Expected “CAP NAK :foo qux bar baz qux quux” after '
'sending “CAP REQ :foo qux bar baz qux quux”, but got {msg}.')
def testNakWhole(self):
"""“The capability identifier set must be accepted as a whole, or
@ -64,17 +70,25 @@ class CapTestCase(cases.BaseServerTestCase):
self.sendLine(1, 'CAP REQ :foo multi-prefix bar')
m = self.getRegistrationMessage(1)
self.assertMessageEqual(m, command='CAP',
subcommand='NAK', subparams=['foo multi-prefix bar'])
subcommand='NAK', subparams=['foo multi-prefix bar'],
fail_msg='Expected “CAP NAK :foo multi-prefix bar” after '
'sending “CAP REQ :foo multi-prefix bar”, but got {msg}.')
self.sendLine(1, 'CAP REQ :multi-prefix bar')
m = self.getRegistrationMessage(1)
self.assertMessageEqual(m, command='CAP',
subcommand='NAK', subparams=['multi-prefix bar'])
subcommand='NAK', subparams=['multi-prefix bar'],
fail_msg='Expected “CAP NAK :foo multi-prefix bar” after '
'sending “CAP REQ :foo multi-prefix bar”, but got {msg}.')
self.sendLine(1, 'CAP REQ :foo multi-prefix')
m = self.getRegistrationMessage(1)
self.assertMessageEqual(m, command='CAP',
subcommand='NAK', subparams=['foo multi-prefix'])
subcommand='NAK', subparams=['foo multi-prefix'],
fail_msg='Expected “CAP NAK :foo multi-prefix bar” after '
'sending “CAP REQ :foo multi-prefix bar”, but got {msg}.')
# TODO: make sure multi-prefix is not enabled at this point
self.sendLine(1, 'CAP REQ :multi-prefix')
m = self.getRegistrationMessage(1)
self.assertMessageEqual(m, command='CAP',
subcommand='ACK', subparams=['multi-prefix'])
subcommand='ACK', subparams=['multi-prefix'],
fail_msg='Expected “CAP NAK :foo multi-prefix bar” after '
'sending “CAP REQ :foo multi-prefix bar”, but got {msg}.')

View File

@ -38,17 +38,27 @@ class JoinTestCase(cases.BaseServerTestCase):
"( "=" / "*" / "@" ) <channel>
:[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )
-- <https://tools.ietf.org/html/rfc2812#section-5.2>
This test makes a user join and check what is sent to them.
"""
self.connectClient('foo')
self.sendLine(1, 'JOIN #chan')
for m in self.getMessages(1):
if m.command == '353':
self.assertIn(len(m.params), (3, 4), m)
self.assertIn(len(m.params), (3, 4), m,
fail_msg='RPL_NAM_REPLY with number of arguments '
'<3 or >4: {msg}')
params = ambiguities.normalize_namreply_params(m.params)
self.assertIn(params[1], '=*@', m)
self.assertEqual(params[2], '#chan', m)
self.assertIn(params[3], {'foo', '@foo', '+foo'}, m)
self.assertIn(params[1], '=*@', m,
fail_msg='Bad channel prefix: {got} not in {expects}: {msg}')
self.assertEqual(params[2], '#chan', m,
fail_msg='Bad channel name: {got} instead of '
'{expects}: {msg}')
self.assertIn(params[3], {'foo', '@foo', '+foo'}, m,
fail_msg='Bad user list: should contain only user '
'"foo" with an optional "+" or "@" prefix, but got: '
'{msg}')
def testPartNotInEmptyChannel(self):
@ -77,16 +87,24 @@ class JoinTestCase(cases.BaseServerTestCase):
self.connectClient('foo')
self.sendLine(1, 'PART #chan')
m = self.getMessage(1)
self.assertIn(m.command, {'442', '403'}) # ERR_NOTONCHANNEL, ERR_NOSUCHCHANNEL
self.assertIn(m.command, {'442', '403'}, m, # ERR_NOTONCHANNEL, ERR_NOSUCHCHANNEL
fail_msg='Expected ERR_NOTONCHANNEL (442) or '
'ERR_NOSUCHCHANNEL (403) after PARTing an empty channel '
'one is not on, but got: {msg}')
def testPartNotInNonEmptyChannel(self):
self.connectClient('foo')
self.connectClient('bar')
self.sendLine(1, 'JOIN #chan')
self.getMessages(1) # Synchronize
self.sendLine(2, 'PART #chan')
self.getMessages(1)
m = self.getMessage(2)
self.assertMessageEqual(m, command='442') # ERR_NOTONCHANNEL
self.assertMessageEqual(m, command='442', # ERR_NOTONCHANNEL
fail_msg='Expected ERR_NOTONCHANNEL (442) '
'after PARTing a non-empty channel '
'one is not on, but got: {msg}')
self.assertEqual(self.getMessages(2), [])
testPartNotInNonEmptyChannel.__doc__ = testPartNotInEmptyChannel.__doc__
def testJoinTwice(self):
self.connectClient('foo')

View File

@ -18,14 +18,16 @@ class PasswordedConnectionRegistrationTestCase(cases.BaseServerTestCase):
self.sendLine(1, 'USER username * * :Realname')
m = self.getRegistrationMessage(1)
self.assertMessageEqual(m, command='001')
self.assertMessageEqual(m, command='001',
fail_msg='Did not get 001 after correct PASS+NICK+USER: {msg}')
def testNoPassword(self):
self.addClient()
self.sendLine(1, 'NICK foo')
self.sendLine(1, 'USER username * * :Realname')
m = self.getRegistrationMessage(1)
self.assertNotEqual(m.command, '001')
self.assertNotEqual(m.command, '001',
msg='Got 001 NICK+USER but missing PASS')
def testPassAfterNickuser(self):
"""“The password can and must be set before any attempt to register
@ -43,7 +45,8 @@ class PasswordedConnectionRegistrationTestCase(cases.BaseServerTestCase):
self.sendLine(1, 'USER username * * :Realname')
self.sendLine(1, 'PASS {}'.format(self.password))
m = self.getRegistrationMessage(1)
self.assertNotEqual(m.command, '001')
self.assertNotEqual(m.command, '001',
'Got 001 NICK+USER but incorrect PASS')
class ConnectionRegistrationTestCase(cases.BaseServerTestCase):
def testQuitDisconnects(self):
@ -54,7 +57,7 @@ class ConnectionRegistrationTestCase(cases.BaseServerTestCase):
self.connectClient('foo')
self.getMessages(1)
self.sendLine(1, 'QUIT')
self.assertRaises(ConnectionClosed, self.getMessages, 1)
self.assertRaises(ConnectionClosed, self.getMessages, 1) # Connection was not closed after QUIT.
def testNickCollision(self):
"""A user connects and requests the same nickname as an already
@ -65,7 +68,9 @@ class ConnectionRegistrationTestCase(cases.BaseServerTestCase):
self.sendLine(2, 'NICK foo')
self.sendLine(2, 'USER username * * :Realname')
m = self.getRegistrationMessage(2)
self.assertNotEqual(m.command, '001')
self.assertNotEqual(m.command, '001',
'Received 001 after registering with the nick of a '
'registered user.')
def testEarlyNickCollision(self):
"""Two users register simultaneously with the same nick."""
@ -77,4 +82,6 @@ class ConnectionRegistrationTestCase(cases.BaseServerTestCase):
self.sendLine(2, 'USER username * * :Realname')
m1 = self.getRegistrationMessage(1)
m2 = self.getRegistrationMessage(2)
self.assertNotEqual((m1.command, m2.command), ('001', '001'))
self.assertNotEqual((m1.command, m2.command), ('001', '001'),
'Two concurrently registering requesting the same nickname '
'both got 001.')

View File

@ -15,13 +15,19 @@ class SaslTestCase(cases.BaseServerTestCase, cases.OptionalityHelper):
self.addClient()
self.sendLine(1, 'CAP LS 302')
capabilities = self.getCapLs(1)
self.assertIn('sasl', capabilities)
self.assertIn('sasl', capabilities,
fail_msg='Does not have SASL as the controller claims.')
if capabilities['sasl'] is not None:
self.assertIn('PLAIN', capabilities['sasl'])
self.sendLine(1, 'AUTHENTICATE PLAIN')
m = self.getMessage(1, filter_pred=lambda m:m.command != 'NOTICE')
self.assertMessageEqual(m, command='AUTHENTICATE', params=['+'])
self.assertMessageEqual(m, command='AUTHENTICATE', params=['+'],
fail_msg='Sent “AUTHENTICATE PLAIN”, server should have '
'replied with “AUTHENTICATE +”, but instead sent: {msg}')
self.sendLine(1, 'AUTHENTICATE amlsbGVzAGppbGxlcwBzZXNhbWU=')
m = self.getMessage(1, filter_pred=lambda m:m.command != 'NOTICE')
self.assertMessageEqual(m, command='900')
self.assertEqual(m.params[2], 'jilles', m)
self.assertMessageEqual(m, command='900',
fail_msg='Did not send 900 after correct SASL authentication.')
self.assertEqual(m.params[2], 'jilles', m,
fail_msg='900 should contain the account name as 3rd argument '
'({expected}), not {got}: {msg}')