audio: Add more tests for audio events

This commit is contained in:
Thomas Adamcik 2014-01-27 22:34:42 +01:00
parent a4315251ca
commit 6490d5bd2d
2 changed files with 155 additions and 9 deletions

View File

@ -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):
"""

View File

@ -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):