277 lines
10 KiB
Python
277 lines
10 KiB
Python
# encoding: utf-8
|
|
|
|
from __future__ import absolute_import, unicode_literals
|
|
|
|
import unittest
|
|
|
|
from mopidy.mpd import exceptions, protocol
|
|
|
|
|
|
class TestConverts(unittest.TestCase):
|
|
|
|
def test_integer(self):
|
|
self.assertEqual(123, protocol.INT('123'))
|
|
self.assertEqual(-123, protocol.INT('-123'))
|
|
self.assertEqual(123, protocol.INT('+123'))
|
|
self.assertRaises(ValueError, protocol.INT, '3.14')
|
|
self.assertRaises(ValueError, protocol.INT, '')
|
|
self.assertRaises(ValueError, protocol.INT, 'abc')
|
|
self.assertRaises(ValueError, protocol.INT, '12 34')
|
|
|
|
def test_unsigned_integer(self):
|
|
self.assertEqual(123, protocol.UINT('123'))
|
|
self.assertRaises(ValueError, protocol.UINT, '-123')
|
|
self.assertRaises(ValueError, protocol.UINT, '+123')
|
|
self.assertRaises(ValueError, protocol.UINT, '3.14')
|
|
self.assertRaises(ValueError, protocol.UINT, '')
|
|
self.assertRaises(ValueError, protocol.UINT, 'abc')
|
|
self.assertRaises(ValueError, protocol.UINT, '12 34')
|
|
|
|
def test_boolean(self):
|
|
self.assertEqual(True, protocol.BOOL('1'))
|
|
self.assertEqual(False, protocol.BOOL('0'))
|
|
self.assertRaises(ValueError, protocol.BOOL, '3.14')
|
|
self.assertRaises(ValueError, protocol.BOOL, '')
|
|
self.assertRaises(ValueError, protocol.BOOL, 'true')
|
|
self.assertRaises(ValueError, protocol.BOOL, 'false')
|
|
self.assertRaises(ValueError, protocol.BOOL, 'abc')
|
|
self.assertRaises(ValueError, protocol.BOOL, '12 34')
|
|
|
|
def test_range(self):
|
|
self.assertEqual(slice(1, 2), protocol.RANGE('1'))
|
|
self.assertEqual(slice(0, 1), protocol.RANGE('0'))
|
|
self.assertEqual(slice(0, None), protocol.RANGE('0:'))
|
|
self.assertEqual(slice(1, 3), protocol.RANGE('1:3'))
|
|
self.assertRaises(ValueError, protocol.RANGE, '3.14')
|
|
self.assertRaises(ValueError, protocol.RANGE, '1:abc')
|
|
self.assertRaises(ValueError, protocol.RANGE, 'abc:1')
|
|
self.assertRaises(ValueError, protocol.RANGE, '2:1')
|
|
self.assertRaises(ValueError, protocol.RANGE, '-1:2')
|
|
self.assertRaises(ValueError, protocol.RANGE, '1 : 2')
|
|
self.assertRaises(ValueError, protocol.RANGE, '')
|
|
self.assertRaises(ValueError, protocol.RANGE, 'true')
|
|
self.assertRaises(ValueError, protocol.RANGE, 'false')
|
|
self.assertRaises(ValueError, protocol.RANGE, 'abc')
|
|
self.assertRaises(ValueError, protocol.RANGE, '12 34')
|
|
|
|
|
|
class TestCommands(unittest.TestCase):
|
|
|
|
def setUp(self): # noqa: N802
|
|
self.commands = protocol.Commands()
|
|
|
|
def test_add_as_a_decorator(self):
|
|
@self.commands.add('test')
|
|
def test(context):
|
|
pass
|
|
|
|
def test_register_second_command_to_same_name_fails(self):
|
|
def func(context):
|
|
pass
|
|
|
|
self.commands.add('foo')(func)
|
|
with self.assertRaises(Exception):
|
|
self.commands.add('foo')(func)
|
|
|
|
def test_function_only_takes_context_succeeds(self):
|
|
sentinel = object()
|
|
self.commands.add('bar')(lambda context: sentinel)
|
|
self.assertEqual(sentinel, self.commands.call(['bar']))
|
|
|
|
def test_function_has_required_arg_succeeds(self):
|
|
sentinel = object()
|
|
self.commands.add('bar')(lambda context, required: sentinel)
|
|
self.assertEqual(sentinel, self.commands.call(['bar', 'arg']))
|
|
|
|
def test_function_has_optional_args_succeeds(self):
|
|
sentinel = object()
|
|
self.commands.add('bar')(lambda context, optional=None: sentinel)
|
|
self.assertEqual(sentinel, self.commands.call(['bar']))
|
|
self.assertEqual(sentinel, self.commands.call(['bar', 'arg']))
|
|
|
|
def test_function_has_required_and_optional_args_succeeds(self):
|
|
sentinel = object()
|
|
|
|
def func(context, required, optional=None):
|
|
return sentinel
|
|
|
|
self.commands.add('bar')(func)
|
|
self.assertEqual(sentinel, self.commands.call(['bar', 'arg']))
|
|
self.assertEqual(sentinel, self.commands.call(['bar', 'arg', 'arg']))
|
|
|
|
def test_function_has_varargs_succeeds(self):
|
|
sentinel, args = object(), []
|
|
self.commands.add('bar')(lambda context, *args: sentinel)
|
|
for i in range(10):
|
|
self.assertEqual(sentinel, self.commands.call(['bar'] + args))
|
|
args.append('test')
|
|
|
|
def test_function_has_only_varags_succeeds(self):
|
|
sentinel = object()
|
|
self.commands.add('baz')(lambda *args: sentinel)
|
|
self.assertEqual(sentinel, self.commands.call(['baz']))
|
|
|
|
def test_function_has_no_arguments_fails(self):
|
|
with self.assertRaises(TypeError):
|
|
self.commands.add('test')(lambda: True)
|
|
|
|
def test_function_has_required_and_varargs_fails(self):
|
|
with self.assertRaises(TypeError):
|
|
def func(context, required, *args):
|
|
pass
|
|
|
|
self.commands.add('test')(func)
|
|
|
|
def test_function_has_optional_and_varargs_fails(self):
|
|
with self.assertRaises(TypeError):
|
|
def func(context, optional=None, *args):
|
|
pass
|
|
|
|
self.commands.add('test')(func)
|
|
|
|
def test_function_hash_keywordargs_fails(self):
|
|
with self.assertRaises(TypeError):
|
|
self.commands.add('test')(lambda context, **kwargs: True)
|
|
|
|
def test_call_chooses_correct_handler(self):
|
|
sentinel1, sentinel2, sentinel3 = object(), object(), object()
|
|
self.commands.add('foo')(lambda context: sentinel1)
|
|
self.commands.add('bar')(lambda context: sentinel2)
|
|
self.commands.add('baz')(lambda context: sentinel3)
|
|
|
|
self.assertEqual(sentinel1, self.commands.call(['foo']))
|
|
self.assertEqual(sentinel2, self.commands.call(['bar']))
|
|
self.assertEqual(sentinel3, self.commands.call(['baz']))
|
|
|
|
def test_call_with_nonexistent_handler(self):
|
|
with self.assertRaises(exceptions.MpdUnknownCommand):
|
|
self.commands.call(['bar'])
|
|
|
|
def test_call_passes_context(self):
|
|
sentinel = object()
|
|
self.commands.add('foo')(lambda context: context)
|
|
self.assertEqual(
|
|
sentinel, self.commands.call(['foo'], context=sentinel))
|
|
|
|
def test_call_without_args_fails(self):
|
|
with self.assertRaises(exceptions.MpdNoCommand):
|
|
self.commands.call([])
|
|
|
|
def test_call_passes_required_argument(self):
|
|
self.commands.add('foo')(lambda context, required: required)
|
|
self.assertEqual('test123', self.commands.call(['foo', 'test123']))
|
|
|
|
def test_call_passes_optional_argument(self):
|
|
sentinel = object()
|
|
self.commands.add('foo')(lambda context, optional=sentinel: optional)
|
|
self.assertEqual(sentinel, self.commands.call(['foo']))
|
|
self.assertEqual('test', self.commands.call(['foo', 'test']))
|
|
|
|
def test_call_passes_required_and_optional_argument(self):
|
|
def func(context, required, optional=None):
|
|
return (required, optional)
|
|
|
|
self.commands.add('foo')(func)
|
|
self.assertEqual(('arg', None), self.commands.call(['foo', 'arg']))
|
|
self.assertEqual(
|
|
('arg', 'kwarg'), self.commands.call(['foo', 'arg', 'kwarg']))
|
|
|
|
def test_call_passes_varargs(self):
|
|
self.commands.add('foo')(lambda context, *args: args)
|
|
|
|
def test_call_incorrect_args(self):
|
|
self.commands.add('foo')(lambda context: context)
|
|
with self.assertRaises(exceptions.MpdArgError):
|
|
self.commands.call(['foo', 'bar'])
|
|
|
|
self.commands.add('bar')(lambda context, required: context)
|
|
with self.assertRaises(exceptions.MpdArgError):
|
|
self.commands.call(['bar', 'bar', 'baz'])
|
|
|
|
self.commands.add('baz')(lambda context, optional=None: context)
|
|
with self.assertRaises(exceptions.MpdArgError):
|
|
self.commands.call(['baz', 'bar', 'baz'])
|
|
|
|
def test_validator_gets_applied_to_required_arg(self):
|
|
sentinel = object()
|
|
|
|
def func(context, required):
|
|
return required
|
|
|
|
self.commands.add('test', required=lambda v: sentinel)(func)
|
|
self.assertEqual(sentinel, self.commands.call(['test', 'foo']))
|
|
|
|
def test_validator_gets_applied_to_optional_arg(self):
|
|
sentinel = object()
|
|
|
|
def func(context, optional=None):
|
|
return optional
|
|
|
|
self.commands.add('foo', optional=lambda v: sentinel)(func)
|
|
|
|
self.assertEqual(sentinel, self.commands.call(['foo', '123']))
|
|
|
|
def test_validator_skips_optional_default(self):
|
|
sentinel = object()
|
|
|
|
def func(context, optional=sentinel):
|
|
return optional
|
|
|
|
self.commands.add('foo', optional=lambda v: None)(func)
|
|
|
|
self.assertEqual(sentinel, self.commands.call(['foo']))
|
|
|
|
def test_validator_applied_to_non_existent_arg_fails(self):
|
|
self.commands.add('foo')(lambda context, arg: arg)
|
|
with self.assertRaises(TypeError):
|
|
def func(context, wrong_arg):
|
|
return wrong_arg
|
|
|
|
self.commands.add('bar', arg=lambda v: v)(func)
|
|
|
|
def test_validator_called_context_fails(self):
|
|
return # TODO: how to handle this
|
|
with self.assertRaises(TypeError):
|
|
def func(context):
|
|
pass
|
|
|
|
self.commands.add('bar', context=lambda v: v)(func)
|
|
|
|
def test_validator_value_error_is_converted(self):
|
|
def validdate(value):
|
|
raise ValueError
|
|
|
|
def func(context, arg):
|
|
pass
|
|
|
|
self.commands.add('bar', arg=validdate)(func)
|
|
|
|
with self.assertRaises(exceptions.MpdArgError):
|
|
self.commands.call(['bar', 'test'])
|
|
|
|
def test_auth_required_gets_stored(self):
|
|
def func1(context):
|
|
pass
|
|
|
|
def func2(context):
|
|
pass
|
|
|
|
self.commands.add('foo')(func1)
|
|
self.commands.add('bar', auth_required=False)(func2)
|
|
|
|
self.assertTrue(self.commands.handlers['foo'].auth_required)
|
|
self.assertFalse(self.commands.handlers['bar'].auth_required)
|
|
|
|
def test_list_command_gets_stored(self):
|
|
def func1(context):
|
|
pass
|
|
|
|
def func2(context):
|
|
pass
|
|
|
|
self.commands.add('foo')(func1)
|
|
self.commands.add('bar', list_command=False)(func2)
|
|
|
|
self.assertTrue(self.commands.handlers['foo'].list_command)
|
|
self.assertFalse(self.commands.handlers['bar'].list_command)
|