audio: Add more tests for audio events
This commit is contained in:
parent
a4315251ca
commit
6490d5bd2d
@ -352,6 +352,8 @@ class Audio(pykka.ThreadingActor):
|
||||
old_state, new_state)
|
||||
AudioListener.send(
|
||||
'state_changed', old_state=old_state, new_state=new_state)
|
||||
if new_state == PlaybackState.STOPPED:
|
||||
AudioListener.send('stream_changed', uri=None)
|
||||
|
||||
def _on_end_of_stream(self):
|
||||
logger.debug('Triggering event: reached_end_of_stream event')
|
||||
@ -484,18 +486,21 @@ class Audio(pykka.ThreadingActor):
|
||||
def wait_for_state_change(self):
|
||||
"""Block until any pending state changes are complete.
|
||||
|
||||
Should only be used by test.
|
||||
Should only be used by tests.
|
||||
"""
|
||||
self._playbin.get_state()
|
||||
|
||||
def process_messages(self):
|
||||
"""Manually process messages from bus.
|
||||
def enable_sync_handler(self):
|
||||
"""Enable manual processing of messages from bus.
|
||||
|
||||
Should only be used by test.
|
||||
Should only be used by tests.
|
||||
"""
|
||||
def sync_handler(bus, message):
|
||||
self._on_message(bus, message)
|
||||
return gst.BUS_DROP
|
||||
|
||||
bus = self._playbin.get_bus()
|
||||
while bus.have_pending():
|
||||
self._on_message(bus, bus.pop())
|
||||
bus.set_sync_handler(sync_handler)
|
||||
|
||||
def _set_state(self, state):
|
||||
"""
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import mock
|
||||
import threading
|
||||
import unittest
|
||||
|
||||
import pygst
|
||||
@ -13,6 +14,7 @@ gobject.threads_init()
|
||||
import pykka
|
||||
|
||||
from mopidy import audio
|
||||
from mopidy.audio.constants import PlaybackState
|
||||
from mopidy.utils.path import path_to_uri
|
||||
|
||||
from tests import path_to_data_dir
|
||||
@ -115,18 +117,157 @@ class AudioTest(unittest.TestCase):
|
||||
def test_invalid_output_raises_error(self):
|
||||
pass # TODO
|
||||
|
||||
@mock.patch.object(audio.AudioListener, 'send')
|
||||
def test_stream_changed_event(self, send_mock):
|
||||
|
||||
@mock.patch.object(audio.AudioListener, 'send')
|
||||
class AudioEventTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
config = {
|
||||
'audio': {
|
||||
'mixer': 'fakemixer track_max_volume=65536',
|
||||
'mixer_track': None,
|
||||
'mixer_volume': None,
|
||||
'output': 'fakesink',
|
||||
'visualizer': None,
|
||||
}
|
||||
}
|
||||
self.song_uri = path_to_uri(path_to_data_dir('song1.wav'))
|
||||
self.audio = audio.Audio.start(config=config).proxy()
|
||||
self.audio.enable_sync_handler().get()
|
||||
|
||||
def tearDown(self):
|
||||
pykka.ActorRegistry.stop_all()
|
||||
|
||||
# TODO: test wihtout uri set, with bad uri and gapless...
|
||||
|
||||
def test_state_change_stopped_to_playing_event(self, send_mock):
|
||||
self.audio.prepare_change()
|
||||
self.audio.set_uri(self.song_uri)
|
||||
self.audio.start_playback()
|
||||
|
||||
self.audio.wait_for_state_change().get()
|
||||
call = mock.call('state_changed', old_state=PlaybackState.STOPPED,
|
||||
new_state=PlaybackState.PLAYING)
|
||||
self.assertIn(call, send_mock.call_args_list)
|
||||
|
||||
def test_state_change_stopped_to_paused_event(self, send_mock):
|
||||
self.audio.prepare_change()
|
||||
self.audio.set_uri(self.song_uri)
|
||||
self.audio.pause_playback()
|
||||
|
||||
self.audio.wait_for_state_change().get()
|
||||
call = mock.call('state_changed', old_state=PlaybackState.STOPPED,
|
||||
new_state=PlaybackState.PAUSED)
|
||||
self.assertIn(call, send_mock.call_args_list)
|
||||
|
||||
def test_state_change_paused_to_playing_event(self, send_mock):
|
||||
self.audio.prepare_change()
|
||||
self.audio.set_uri(self.song_uri)
|
||||
self.audio.pause_playback()
|
||||
self.audio.wait_for_state_change()
|
||||
self.audio.process_messages().get()
|
||||
self.audio.start_playback()
|
||||
|
||||
self.audio.wait_for_state_change().get()
|
||||
call = mock.call('state_changed', old_state=PlaybackState.PAUSED,
|
||||
new_state=PlaybackState.PLAYING)
|
||||
self.assertIn(call, send_mock.call_args_list)
|
||||
|
||||
def test_state_change_paused_to_stopped_event(self, send_mock):
|
||||
self.audio.prepare_change()
|
||||
self.audio.set_uri(self.song_uri)
|
||||
self.audio.pause_playback()
|
||||
self.audio.wait_for_state_change()
|
||||
self.audio.stop_playback()
|
||||
|
||||
self.audio.wait_for_state_change().get()
|
||||
call = mock.call('state_changed', old_state=PlaybackState.PAUSED,
|
||||
new_state=PlaybackState.STOPPED)
|
||||
self.assertIn(call, send_mock.call_args_list)
|
||||
|
||||
def test_state_change_playing_to_paused_event(self, send_mock):
|
||||
self.audio.prepare_change()
|
||||
self.audio.set_uri(self.song_uri)
|
||||
self.audio.start_playback()
|
||||
self.audio.wait_for_state_change()
|
||||
self.audio.pause_playback()
|
||||
|
||||
self.audio.wait_for_state_change().get()
|
||||
call = mock.call('state_changed', old_state=PlaybackState.PLAYING,
|
||||
new_state=PlaybackState.PAUSED)
|
||||
self.assertIn(call, send_mock.call_args_list)
|
||||
|
||||
def test_state_change_playing_to_stopped_event(self, send_mock):
|
||||
self.audio.prepare_change()
|
||||
self.audio.set_uri(self.song_uri)
|
||||
self.audio.start_playback()
|
||||
self.audio.wait_for_state_change()
|
||||
self.audio.stop_playback()
|
||||
|
||||
self.audio.wait_for_state_change().get()
|
||||
call = mock.call('state_changed', old_state=PlaybackState.PLAYING,
|
||||
new_state=PlaybackState.STOPPED)
|
||||
self.assertIn(call, send_mock.call_args_list)
|
||||
|
||||
def test_stream_changed_event_on_playing(self, send_mock):
|
||||
self.audio.prepare_change()
|
||||
self.audio.set_uri(self.song_uri)
|
||||
self.audio.start_playback()
|
||||
|
||||
# Since we are going from stopped to playing, the state change is
|
||||
# enough to ensure the stream changed.
|
||||
self.audio.wait_for_state_change().get()
|
||||
|
||||
call = mock.call('stream_changed', uri=self.song_uri)
|
||||
self.assertIn(call, send_mock.call_args_list)
|
||||
|
||||
def test_stream_changed_event_on_paused_to_stopped(self, send_mock):
|
||||
self.audio.prepare_change()
|
||||
self.audio.set_uri(self.song_uri)
|
||||
self.audio.pause_playback()
|
||||
self.audio.wait_for_state_change()
|
||||
self.audio.stop_playback()
|
||||
|
||||
self.audio.wait_for_state_change().get()
|
||||
|
||||
call = mock.call('stream_changed', uri=None)
|
||||
self.assertIn(call, send_mock.call_args_list)
|
||||
|
||||
# Unlike the other events, having the state changed done is not
|
||||
# enough to ensure our event is called. So we setup a threading
|
||||
# event that we can wait for with a timeout while the track playback
|
||||
# completes.
|
||||
|
||||
def test_stream_changed_event_on_paused(self, send_mock):
|
||||
event = threading.Event()
|
||||
|
||||
def send(name, **kwargs):
|
||||
if name == 'stream_changed':
|
||||
event.set()
|
||||
send_mock.side_effect = send
|
||||
|
||||
self.audio.prepare_change()
|
||||
self.audio.set_uri(self.song_uri)
|
||||
self.audio.pause_playback().get()
|
||||
self.audio.wait_for_state_change().get()
|
||||
|
||||
if not event.wait(timeout=5.0):
|
||||
self.fail('Stream changed not reached within deadline')
|
||||
|
||||
def test_reached_end_of_stream_event(self, send_mock):
|
||||
event = threading.Event()
|
||||
|
||||
def send(name, **kwargs):
|
||||
if name == 'reached_end_of_stream':
|
||||
event.set()
|
||||
send_mock.side_effect = send
|
||||
|
||||
self.audio.prepare_change()
|
||||
self.audio.set_uri(self.song_uri)
|
||||
self.audio.start_playback()
|
||||
self.audio.wait_for_state_change().get()
|
||||
|
||||
if not event.wait(timeout=5.0):
|
||||
self.fail('End of stream not reached within deadline')
|
||||
|
||||
|
||||
class AudioStateTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user