bpd: add tests for idle command

This commit is contained in:
Carl Suster 2019-04-05 11:18:42 +11:00
parent 699de94f4f
commit d05ca2c2b0

View file

@ -23,6 +23,7 @@ from test.helper import TestHelper
import os
import sys
import multiprocessing as mp
import threading
import socket
import time
import yaml
@ -37,18 +38,19 @@ from beetsplug import bpd
import mock
import imp
gstplayer = imp.new_module("beetsplug.bpd.gstplayer")
def _gstplayer_play(_): # noqa: 42
def _gstplayer_play(*_): # noqa: 42
bpd.gstplayer._GstPlayer.playing = True
return mock.DEFAULT
gstplayer._GstPlayer = mock.MagicMock(
spec_set=[
"time", "volume", "playing", "run", "play_file", "pause", "stop",
"seek"
"seek", "play"
], **{
'playing': False,
'volume': 0,
'time.return_value': (0, 0),
'play_file.side_effect': _gstplayer_play,
'play.side_effect': _gstplayer_play,
})
gstplayer.GstPlayer = lambda _: gstplayer._GstPlayer
sys.modules["beetsplug.bpd.gstplayer"] = gstplayer
@ -259,7 +261,7 @@ class BPDTestHelper(unittest.TestCase, TestHelper):
@contextmanager
def run_bpd(self, host='localhost', port=9876, password=None,
do_hello=True):
do_hello=True, second_client=False):
""" Runs BPD in another process, configured with the same library
database as we created in the setUp method. Exposes a client that is
connected to the server, and kills the server at the end.
@ -290,7 +292,7 @@ class BPDTestHelper(unittest.TestCase, TestHelper):
server.start()
# Wait until the socket is connected:
sock = None
sock, sock2 = None, None
for _ in range(20):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if sock.connect_ex((host, port)) == 0:
@ -302,9 +304,16 @@ class BPDTestHelper(unittest.TestCase, TestHelper):
raise RuntimeError('Timed out waiting for the BPD server')
try:
yield MPCClient(sock, do_hello)
if second_client:
sock2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock2.connect((host, port))
yield MPCClient(sock, do_hello), MPCClient(sock2, do_hello)
else:
yield MPCClient(sock, do_hello)
finally:
sock.close()
if sock2:
sock2.close()
server.terminate()
server.join(timeout=0.2)
@ -375,8 +384,8 @@ class BPDTest(BPDTestHelper):
class BPDQueryTest(BPDTestHelper):
test_implements_query = implements({
'clearerror', 'currentsong', 'idle', 'stats',
}, expectedFailure=True)
'clearerror', 'currentsong', 'stats',
})
def test_cmd_status(self):
with self.run_bpd() as client:
@ -397,6 +406,41 @@ class BPDQueryTest(BPDTestHelper):
}
self.assertEqual(fields_playing, set(responses[2].data.keys()))
def test_cmd_idle(self):
def _toggle(c):
for _ in range(3):
rs = c.send_commands(('play',), ('pause',))
# time.sleep(0.05) # uncomment if test is flaky
if any(not r.ok for r in rs):
raise RuntimeError('Toggler failed')
with self.run_bpd(second_client=True) as (client, client2):
self._bpd_add(client, self.item1, self.item2)
toggler = threading.Thread(target=_toggle, args=(client2,))
toggler.start()
# Idling will hang until the toggler thread changes the play state.
# Since the client sockets have a 1s timeout set at worst this will
# raise a socket.timeout and fail the test if the toggler thread
# manages to finish before the idle command is sent here.
response = client.send_command('idle', 'player')
toggler.join()
self._assert_ok(response)
def test_cmd_idle_with_pending(self):
with self.run_bpd(second_client=True) as (client, client2):
response1 = client.send_command('random', '1')
response2 = client2.send_command('idle')
self._assert_ok(response1, response2)
self.assertEqual('options', response2.data['changed'])
def test_cmd_noidle(self):
with self.run_bpd() as client:
# Manually send a command without reading a response.
request = client.serialise_command('idle')
client.sock.sendall(request)
time.sleep(0.01)
response = client.send_command('noidle')
self._assert_ok(response)
class BPDPlaybackTest(BPDTestHelper):
test_implements_playback = implements({