X-Git-Url: http://git.kaliko.me/?p=python-musicpd.git;a=blobdiff_plain;f=test.py;h=70ac203ccdfdcd69696bbe9607b9fb2283937a54;hp=ba3132b14689efa63c8164331bf702c74716253a;hb=c45cc084b0543af12fe815f6dee14303eac20e2a;hpb=7cb6ba6bfc1dfae2be3ef0047dfeaabc87b81df7 diff --git a/test.py b/test.py index ba3132b..70ac203 100755 --- a/test.py +++ b/test.py @@ -36,24 +36,66 @@ TEST_MPD_HOST, TEST_MPD_PORT = ('example.com', 10000) class testEnvVar(unittest.TestCase): def test_envvar(self): - os.environ.pop('MPD_HOST', None) - os.environ.pop('MPD_PORT', None) - client = musicpd.MPDClient() - self.assertEqual(client.host, 'localhost') - self.assertEqual(client.port, '6600') + # mock "os.path.exists" here to ensure there are no socket in + # XDG_RUNTIME_DIR/mpd or /run/mpd since with test defaults fallbacks + # when : + # * neither MPD_HOST nor XDG_RUNTIME_DIR are not set + # * /run/mpd does not expose a socket + with mock.patch('os.path.exists', return_value=False): + os.environ.pop('MPD_HOST', None) + os.environ.pop('MPD_PORT', None) + client = musicpd.MPDClient() + self.assertEqual(client.host, 'localhost') + self.assertEqual(client.port, '6600') + os.environ.pop('MPD_HOST', None) + os.environ['MPD_PORT'] = '6666' + client = musicpd.MPDClient() + self.assertEqual(client.pwd, None) + self.assertEqual(client.host, 'localhost') + self.assertEqual(client.port, '6666') + + # Test password extraction os.environ['MPD_HOST'] = 'pa55w04d@example.org' client = musicpd.MPDClient() self.assertEqual(client.pwd, 'pa55w04d') self.assertEqual(client.host, 'example.org') - self.assertEqual(client.port, '6600') - os.environ.pop('MPD_HOST', None) - os.environ['MPD_PORT'] = '6666' + # Test host alone + os.environ['MPD_HOST'] = 'example.org' client = musicpd.MPDClient() + self.assertFalse(client.pwd) + self.assertEqual(client.host, 'example.org') + + # Test password extraction (no host) + os.environ['MPD_HOST'] = 'pa55w04d@' + with mock.patch('os.path.exists', return_value=False): + client = musicpd.MPDClient() + self.assertEqual(client.pwd, 'pa55w04d') + self.assertEqual(client.host, 'localhost') + + # Test badly formatted MPD_HOST + os.environ['MPD_HOST'] = '@' + with mock.patch('os.path.exists', return_value=False): + client = musicpd.MPDClient() self.assertEqual(client.pwd, None) self.assertEqual(client.host, 'localhost') - self.assertEqual(client.port, '6666') + + # Test unix socket extraction + os.environ['MPD_HOST'] = 'pa55w04d@/unix/sock' + client = musicpd.MPDClient() + self.assertEqual(client.host, '/unix/sock') + + # Test plain abstract socket extraction + os.environ['MPD_HOST'] = '@abstract' + client = musicpd.MPDClient() + self.assertEqual(client.host, '@abstract') + + # Test password and abstract socket extraction + os.environ['MPD_HOST'] = 'pass@@abstract' + client = musicpd.MPDClient() + self.assertEqual(client.pwd, 'pass') + self.assertEqual(client.host, '@abstract') # Test unix socket fallback os.environ.pop('MPD_HOST', None) @@ -62,6 +104,9 @@ class testEnvVar(unittest.TestCase): with mock.patch('os.path.exists', return_value=True): client = musicpd.MPDClient() self.assertEqual(client.host, '/run/mpd/socket') + os.environ['XDG_RUNTIME_DIR'] = '/run/user/1000' + client = musicpd.MPDClient() + self.assertEqual(client.host, '/run/user/1000/mpd/socket') os.environ.pop('MPD_HOST', None) os.environ.pop('MPD_PORT', None) @@ -70,10 +115,24 @@ class testEnvVar(unittest.TestCase): client = musicpd.MPDClient() self.assertEqual(client.host, '/run/user/1000/mpd/socket') + # Test MPD_TIMEOUT + os.environ.pop('MPD_TIMEOUT', None) + client = musicpd.MPDClient() + self.assertEqual(client.mpd_timeout, musicpd.CONNECTION_TIMEOUT) + os.environ['MPD_TIMEOUT'] = 'garbage' + client = musicpd.MPDClient() + self.assertEqual(client.mpd_timeout, + musicpd.CONNECTION_TIMEOUT, + 'Garbage\'s not silently ignore to use default value') + os.environ['MPD_TIMEOUT'] = '42' + client = musicpd.MPDClient() + self.assertEqual(client.mpd_timeout, 42) + + class TestMPDClient(unittest.TestCase): longMessage = True - # last sync: musicpd 0.4.2 unreleased / Mon Nov 17 21:45:22 CET 2014 + # last sync: musicpd 0.6.0 unreleased / Fri Feb 19 15:34:53 CET 2021 commands = { # Status Commands 'clearerror': 'nothing', @@ -90,6 +149,7 @@ class TestMPDClient(unittest.TestCase): 'random': 'nothing', 'repeat': 'nothing', 'setvol': 'nothing', + 'getvol': 'object', 'single': 'nothing', 'replay_gain_mode': 'nothing', 'replay_gain_status': 'item', @@ -104,7 +164,7 @@ class TestMPDClient(unittest.TestCase): 'seekid': 'nothing', 'seekcur': 'nothing', 'stop': 'nothing', - # Playlist Commands + # Queue Commands 'add': 'nothing', 'addid': 'item', 'clear': 'nothing', @@ -140,19 +200,23 @@ class TestMPDClient(unittest.TestCase): 'rm': 'nothing', 'save': 'nothing', # Database Commands + 'albumart': 'composite', 'count': 'object', + 'getfingerprint': 'object', 'find': 'songs', 'findadd': 'nothing', 'list': 'list', 'listall': 'database', 'listallinfo': 'database', + 'listfiles': 'database', 'lsinfo': 'database', + 'readcomments': 'object', + 'readpicture': 'composite', 'search': 'songs', 'searchadd': 'nothing', 'searchaddpl': 'nothing', 'update': 'item', 'rescan': 'item', - 'readcomments': 'object', # Mounts and neighbors 'mount': 'nothing', 'unmount': 'nothing', @@ -169,20 +233,28 @@ class TestMPDClient(unittest.TestCase): 'kill': None, 'password': 'nothing', 'ping': 'nothing', + 'binarylimit': 'nothing', + 'tagtypes': 'list', + 'tagtypes disable': 'nothing', + 'tagtypes enable': 'nothing', + 'tagtypes clear': 'nothing', + 'tagtypes all': 'nothing', # Partition Commands 'partition': 'nothing', 'listpartitions': 'list', 'newpartition': 'nothing', + 'delpartition': 'nothing', + 'moveoutput': 'nothing', # Audio Output Commands 'disableoutput': 'nothing', 'enableoutput': 'nothing', 'toggleoutput': 'nothing', 'outputs': 'outputs', + 'outputset': 'nothing', # Reflection Commands 'config': 'object', 'commands': 'list', 'notcommands': 'list', - 'tagtypes': 'list', 'urlhandlers': 'list', 'decoders': 'plugins', # Client to Client @@ -223,15 +295,14 @@ class TestMPDClient(unittest.TestCase): def MPDWillReturnBinary(self, lines): data = bytearray(b''.join(lines)) - print(data) - def recv(amount): + def read(amount): val = bytearray() while amount > 0: amount -= 1 - _ = data.pop(0) - print(hex(_)) - val.append(_) + # _ = data.pop(0) + # print(hex(_)) + val.append(data.pop(0)) return val def readline(): @@ -240,7 +311,7 @@ class TestMPDClient(unittest.TestCase): val.append(data.pop(0)) return val self.client._rbfile.readline.side_effect = readline - self.client._rbfile.recv.side_effect = recv + self.client._rbfile.read.side_effect = read def assertMPDReceived(self, *lines): self.client._wfile.write.assert_called_with(*lines) @@ -280,6 +351,16 @@ class TestMPDClient(unittest.TestCase): self.assertMPDReceived('stats\n') self.assertIsInstance(stats, dict) + output = ['outputid: 0\n', + 'outputname: default detected output\n', + 'plugin: sndio\n', + 'outputenabled: 1\n'] + self.MPDWillReturn(*output, 'OK\n') + outputs = self.client.outputs() + self.assertMPDReceived('outputs\n') + self.assertIsInstance(outputs, list) + self.assertEqual([{'outputid': '0', 'outputname': 'default detected output', 'plugin': 'sndio', 'outputenabled': '1'}], outputs) + def test_fetch_songs(self): self.MPDWillReturn('file: my-song.ogg\n', 'Pos: 0\n', 'Id: 66\n', 'OK\n') playlist = self.client.playlistinfo() @@ -345,8 +426,6 @@ class TestMPDClient(unittest.TestCase): self.assertRaises(musicpd.CommandError, self.client.noidle) def test_client_to_client(self): - # client to client is at this time in beta! - self.MPDWillReturn('OK\n') self.assertIsNone(self.client.subscribe("monty")) self.assertMPDReceived('subscribe "monty"\n') @@ -451,6 +530,77 @@ class TestMPDClient(unittest.TestCase): res = self.client.albumart('muse/Raised Fist/2002-Dedication/', 0) self.assertEqual(res.get('data'), data) + def test_reading_binary(self): + # readpicture when there are no picture returns empty object + self.MPDWillReturnBinary([b'OK\n']) + res = self.client.readpicture('muse/Raised Fist/2002-Dedication/', 0) + self.assertEqual(res, {}) + + def test_command_list(self): + self.MPDWillReturn('updating_db: 42\n', + f'{musicpd.NEXT}\n', + 'repeat: 0\n', + 'random: 0\n', + f'{musicpd.NEXT}\n', + f'{musicpd.NEXT}\n', + 'OK\n') + self.client.command_list_ok_begin() + self.client.update() + self.client.status() + self.client.repeat(1) + self.client.command_list_end() + self.assertMPDReceived('command_list_end\n') + + def test_two_word_commands(self): + self.MPDWillReturn('OK\n') + self.client.tagtypes_clear() + self.assertMPDReceived('tagtypes clear\n') + self.MPDWillReturn('OK\n') + with self.assertRaises(AttributeError): + self.client.foo_bar() + +class testConnection(unittest.TestCase): + + def test_exposing_fileno(self): + with mock.patch('musicpd.socket') as socket_mock: + sock = mock.MagicMock(name='socket') + socket_mock.socket.return_value = sock + cli = musicpd.MPDClient() + cli.connect() + cli.fileno() + cli._sock.fileno.assert_called_with() + + def test_connect_abstract(self): + os.environ['MPD_HOST'] = '@abstract' + with mock.patch('musicpd.socket') as socket_mock: + sock = mock.MagicMock(name='socket') + socket_mock.socket.return_value = sock + cli = musicpd.MPDClient() + cli.connect() + sock.connect.assert_called_with('\0abstract') + + def test_connect_unix(self): + os.environ['MPD_HOST'] = '/run/mpd/socket' + with mock.patch('musicpd.socket') as socket_mock: + sock = mock.MagicMock(name='socket') + socket_mock.socket.return_value = sock + cli = musicpd.MPDClient() + cli.connect() + sock.connect.assert_called_with('/run/mpd/socket') + + +class testException(unittest.TestCase): + + def test_CommandError_on_newline(self): + os.environ['MPD_HOST'] = '/run/mpd/socket' + with mock.patch('musicpd.socket') as socket_mock: + sock = mock.MagicMock(name='socket') + socket_mock.socket.return_value = sock + cli = musicpd.MPDClient() + cli.connect() + with self.assertRaises(musicpd.CommandError): + cli.find('(album == "foo\nbar")') + if __name__ == '__main__': unittest.main()