From f801252e3d221e95b5c24c18c0f691a1d2f2fcef Mon Sep 17 00:00:00 2001 From: David Sansome Date: Sun, 13 Feb 2011 18:37:45 +0000 Subject: [PATCH] Refactor Player and PlaylistManagers to have interfaces and add more MPRIS1 tests --- src/core/mpris1.cpp | 4 +- src/core/player.cpp | 3 +- src/core/player.h | 11 +- src/playlist/playlistmanager.cpp | 4 +- src/playlist/playlistmanager.h | 103 ++++++++++--- src/scripting/python/player.sip | 2 +- src/scripting/python/playlistmanager.sip | 4 +- src/scripting/python/pythonengine.cpp | 2 +- src/scripting/python/scriptinterface.sip | 2 +- tests/CMakeLists.txt | 3 +- tests/mock_engine.h | 48 ++++++ tests/mock_player.cpp | 5 - tests/mock_player.h | 4 +- tests/mock_playlistmanager.h | 76 ++++++++++ tests/mpris1_test.cpp | 184 ++++++++++++++++++++++- 15 files changed, 405 insertions(+), 50 deletions(-) create mode 100644 tests/mock_engine.h delete mode 100644 tests/mock_player.cpp create mode 100644 tests/mock_playlistmanager.h diff --git a/src/core/mpris1.cpp b/src/core/mpris1.cpp index 2ebca3e7f..cd7bb9cbd 100644 --- a/src/core/mpris1.cpp +++ b/src/core/mpris1.cpp @@ -189,7 +189,7 @@ DBusStatus Mpris1Player::GetStatus(Engine::State state) const { break; } - PlaylistManager* playlists_ = player_->playlists(); + PlaylistManagerInterface* playlists_ = player_->playlists(); PlaylistSequence::RepeatMode repeat_mode = playlists_->sequence()->repeat_mode(); status.random = playlists_->sequence()->shuffle_mode() == PlaylistSequence::Shuffle_Off ? 0 : 1; @@ -228,7 +228,7 @@ int Mpris1Player::GetCaps() const { int Mpris1Player::GetCaps(Engine::State state) const { int caps = CAN_HAS_TRACKLIST; PlaylistItemPtr current_item = player_->GetCurrentItem(); - PlaylistManager* playlists = player_->playlists(); + PlaylistManagerInterface* playlists = player_->playlists(); // play is disabled when playlist is empty or when last.fm stream is already playing if (playlists->active()->rowCount() != 0 diff --git a/src/core/player.cpp b/src/core/player.cpp index 1605bba4e..e800e9d5f 100644 --- a/src/core/player.cpp +++ b/src/core/player.cpp @@ -36,7 +36,8 @@ using boost::shared_ptr; -Player::Player(PlaylistManager* playlists, LastFMService* lastfm, QObject* parent) +Player::Player(PlaylistManagerInterface* playlists, LastFMService* lastfm, + QObject* parent) : PlayerInterface(parent), playlists_(playlists), lastfm_(lastfm), diff --git a/src/core/player.h b/src/core/player.h index dfd91d61f..0592ca08b 100644 --- a/src/core/player.h +++ b/src/core/player.h @@ -30,7 +30,7 @@ #include "playlist/playlistitem.h" class LastFMService; -class PlaylistManager; +class PlaylistManagerInterface; class Settings; class MainWindow; @@ -47,7 +47,7 @@ public: virtual PlaylistItemPtr GetCurrentItem() const = 0; virtual PlaylistItemPtr GetItemAt(int pos) const = 0; - virtual PlaylistManager* playlists() const = 0; + virtual PlaylistManagerInterface* playlists() const = 0; public slots: virtual void ReloadSettings() = 0; @@ -99,7 +99,8 @@ class Player : public PlayerInterface { Q_OBJECT public: - Player(PlaylistManager* playlists, LastFMService* lastfm, QObject* parent = 0); + Player(PlaylistManagerInterface* playlists, LastFMService* lastfm, + QObject* parent = 0); ~Player(); void Init(); @@ -110,7 +111,7 @@ public: PlaylistItemPtr GetCurrentItem() const { return current_item_; } PlaylistItemPtr GetItemAt(int pos) const; - PlaylistManager* playlists() const { return playlists_; } + PlaylistManagerInterface* playlists() const { return playlists_; } public slots: void ReloadSettings(); @@ -147,7 +148,7 @@ public slots: void NextInternal(Engine::TrackChangeType); private: - PlaylistManager* playlists_; + PlaylistManagerInterface* playlists_; LastFMService* lastfm_; QSettings settings_; diff --git a/src/playlist/playlistmanager.cpp b/src/playlist/playlistmanager.cpp index a3fd170db..d268f119c 100644 --- a/src/playlist/playlistmanager.cpp +++ b/src/playlist/playlistmanager.cpp @@ -31,7 +31,7 @@ using smart_playlists::GeneratorPtr; PlaylistManager::PlaylistManager(TaskManager* task_manager, QObject *parent) - : QObject(parent), + : PlaylistManagerInterface(parent), task_manager_(task_manager), playlist_backend_(NULL), library_backend_(NULL), @@ -70,7 +70,7 @@ void PlaylistManager::Init(LibraryBackend* library_backend, emit PlaylistManagerInitialized(); } -const QList PlaylistManager::GetAllPlaylists() const { +QList PlaylistManager::GetAllPlaylists() const { QList result; foreach(const Data& data, playlists_.values()) { diff --git a/src/playlist/playlistmanager.h b/src/playlist/playlistmanager.h index 42583afa8..0d68fc389 100644 --- a/src/playlist/playlistmanager.h +++ b/src/playlist/playlistmanager.h @@ -35,7 +35,85 @@ class TaskManager; class QModelIndex; class QUrl; -class PlaylistManager : public QObject { +class PlaylistManagerInterface : public QObject { + Q_OBJECT + +public: + PlaylistManagerInterface(QObject* parent) : QObject(parent) {} + + virtual int current_id() const = 0; + virtual int active_id() const = 0; + + virtual Playlist* playlist(int id) const = 0; + virtual Playlist* current() const = 0; + virtual Playlist* active() const = 0; + + // Returns the collection of playlists managed by this PlaylistManager. + virtual QList GetAllPlaylists() const = 0; + + virtual const QItemSelection& selection(int id) const = 0; + virtual const QItemSelection& current_selection() const = 0; + virtual const QItemSelection& active_selection() const = 0; + + virtual QString name(int index) const = 0; + + virtual TaskManager* task_manager() const = 0; + virtual LibraryBackend* library_backend() const = 0; + virtual PlaylistBackend* playlist_backend() const = 0; + virtual PlaylistSequence* sequence() const = 0; + virtual PlaylistParser* parser() const = 0; + +public slots: + virtual void New(const QString& name, const SongList& songs = SongList()) = 0; + virtual void Load(const QString& filename) = 0; + virtual void Save(int id, const QString& filename) = 0; + virtual void Rename(int id, const QString& new_name) = 0; + virtual void Remove(int id) = 0; + virtual void ChangePlaylistOrder(const QList& ids) = 0; + + virtual void SetCurrentPlaylist(int id) = 0; + virtual void SetActivePlaylist(int id) = 0; + virtual void SetActiveToCurrent() = 0; + + virtual void SelectionChanged(const QItemSelection& selection) = 0; + + // Convenience slots that defer to either current() or active() + virtual void ClearCurrent() = 0; + virtual void ShuffleCurrent() = 0; + virtual void SetActivePlaying() = 0; + virtual void SetActivePaused() = 0; + virtual void SetActiveStopped() = 0; + virtual void SetActiveStreamMetadata(const QUrl& url, const Song& song) = 0; + // Rate current song using 0.0 - 1.0 scale. + virtual void RateCurrentSong(double rating) = 0; + // Rate current song using 0 - 5 scale. + virtual void RateCurrentSong(int rating) = 0; + + virtual void PlaySmartPlaylist(smart_playlists::GeneratorPtr generator, bool as_new, bool clear) = 0; + +signals: + void PlaylistManagerInitialized(); + + void PlaylistAdded(int id, const QString& name); + void PlaylistRemoved(int id); + void PlaylistRenamed(int id, const QString& new_name); + void CurrentChanged(Playlist* new_playlist); + void ActiveChanged(Playlist* new_playlist); + + void Error(const QString& message); + void SummaryTextChanged(const QString& summary); + + // Forwarded from individual playlists + void CurrentSongChanged(const Song& song); + + // Signals that one of manager's playlists has changed (new items, new + // ordering etc.) - the argument shows which. + void PlaylistChanged(Playlist* playlist); + void EditingFinished(const QModelIndex& index); + void PlayRequested(const QModelIndex& index); +}; + +class PlaylistManager : public PlaylistManagerInterface { Q_OBJECT public: @@ -50,7 +128,7 @@ public: Playlist* active() const { return playlist(active_id()); } // Returns the collection of playlists managed by this PlaylistManager. - const QList GetAllPlaylists() const; + QList GetAllPlaylists() const; const QItemSelection& selection(int id) const; const QItemSelection& current_selection() const { return selection(current_id()); } @@ -95,27 +173,6 @@ public slots: void PlaySmartPlaylist(smart_playlists::GeneratorPtr generator, bool as_new, bool clear); -signals: - void PlaylistManagerInitialized(); - - void PlaylistAdded(int id, const QString& name); - void PlaylistRemoved(int id); - void PlaylistRenamed(int id, const QString& new_name); - void CurrentChanged(Playlist* new_playlist); - void ActiveChanged(Playlist* new_playlist); - - void Error(const QString& message); - void SummaryTextChanged(const QString& summary); - - // Forwarded from individual playlists - void CurrentSongChanged(const Song& song); - - // Signals that one of manager's playlists has changed (new items, new - // ordering etc.) - the argument shows which. - void PlaylistChanged(Playlist* playlist); - void EditingFinished(const QModelIndex& index); - void PlayRequested(const QModelIndex& index); - private slots: void OneOfPlaylistsChanged(); void UpdateSummaryText(); diff --git a/src/scripting/python/player.sip b/src/scripting/python/player.sip index 571ece8ab..6a842c264 100644 --- a/src/scripting/python/player.sip +++ b/src/scripting/python/player.sip @@ -10,7 +10,7 @@ public: PlaylistItemPtr GetCurrentItem() const; PlaylistItemPtr GetItemAt(int pos) const; - PlaylistManager* playlists() const; + PlaylistManagerInterface* playlists() const; public slots: // Manual track change to the specified track diff --git a/src/scripting/python/playlistmanager.sip b/src/scripting/python/playlistmanager.sip index c7eb16499..73a9a627a 100644 --- a/src/scripting/python/playlistmanager.sip +++ b/src/scripting/python/playlistmanager.sip @@ -1,4 +1,4 @@ -class PlaylistManager : QObject { +class PlaylistManagerInterface : QObject { %TypeHeaderCode #include "playlist/playlistmanager.h" @@ -73,5 +73,5 @@ signals: void PlayRequested(const QModelIndex& index); private: - PlaylistManager(); + PlaylistManagerInterface(); }; diff --git a/src/scripting/python/pythonengine.cpp b/src/scripting/python/pythonengine.cpp index a484f23d7..ed456c2bf 100644 --- a/src/scripting/python/pythonengine.cpp +++ b/src/scripting/python/pythonengine.cpp @@ -133,7 +133,7 @@ Script* PythonEngine::CreateScript(const ScriptInfo& info) { AddObject(manager()->data().library_->backend(), sipType_LibraryBackend, "library"); AddObject(manager()->data().library_view_, sipType_LibraryView, "library_view"); AddObject(manager()->data().player_, sipType_PlayerInterface, "player"); - AddObject(manager()->data().playlists_, sipType_PlaylistManager, "playlists"); + AddObject(manager()->data().playlists_, sipType_PlaylistManagerInterface, "playlists"); AddObject(manager()->data().radio_model_, sipType_RadioModel, "radio_model"); AddObject(manager()->data().settings_dialog_, sipType_SettingsDialog, "settings_dialog"); AddObject(manager()->data().task_manager_, sipType_TaskManager, "task_manager"); diff --git a/src/scripting/python/scriptinterface.sip b/src/scripting/python/scriptinterface.sip index 14280921b..da65f04c0 100644 --- a/src/scripting/python/scriptinterface.sip +++ b/src/scripting/python/scriptinterface.sip @@ -18,7 +18,7 @@ class ScriptInterface : QObject { CLASS(ParserBase), CLASS(PlayerInterface), CLASS(Playlist), - CLASS(PlaylistManager), + CLASS(PlaylistManagerInterface), CLASS(PlaylistParser), CLASS(PlaylistSequence), CLASS(Queue), diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d2ed675a5..a2e0bc868 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -42,7 +42,6 @@ set(TESTUTILS-SOURCES test_utils.cpp mock_networkaccessmanager.cpp mock_taglib.cpp - mock_player.cpp mock_playlistitem.cpp ) @@ -115,7 +114,7 @@ add_test_file(organiseformat_test.cpp false) add_test_file(playlist_test.cpp true) add_test_file(plsparser_test.cpp false) add_test_file(python_test.cpp true) -add_test_file(mpris1_test.cpp false) +add_test_file(mpris1_test.cpp true) add_test_file(scopedtransaction_test.cpp false) add_test_file(songloader_test.cpp false) add_test_file(songplaylistitem_test.cpp false) diff --git a/tests/mock_engine.h b/tests/mock_engine.h new file mode 100644 index 000000000..929307864 --- /dev/null +++ b/tests/mock_engine.h @@ -0,0 +1,48 @@ +/* This file is part of Clementine. + Copyright 2010, David Sansome + + Clementine is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Clementine is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Clementine. If not, see . +*/ + +#ifndef MOCK_ENGINE_H +#define MOCK_ENGINE_H + +#include + +#include "engines/enginebase.h" + +class MockEngine : public Engine::Base { +public: + MOCK_METHOD0(Init, bool()); + MOCK_METHOD1(CanDecode, bool(const QUrl&)); + + MOCK_METHOD1(StartPreloading, void(const QUrl&)); + MOCK_METHOD1(Play, bool(quint64)); + MOCK_METHOD0(Stop, void()); + MOCK_METHOD0(Pause, void()); + MOCK_METHOD0(Unpause, void()); + MOCK_METHOD1(Seek, void(quint64)); + + MOCK_METHOD1(AddBackgroundStream, int(const QUrl&)); + MOCK_METHOD1(StopBackgroundStream, void(int)); + MOCK_METHOD2(SetBackgroundStreamVolume, void(int, int)); + + MOCK_CONST_METHOD0(state, Engine::State()); + MOCK_CONST_METHOD0(position_nanosec, qint64()); + MOCK_CONST_METHOD0(length_nanosec, qint64()); + + MOCK_METHOD1(SetVolumeSW, void(uint)); +}; + +#endif // MOCK_ENGINE_H diff --git a/tests/mock_player.cpp b/tests/mock_player.cpp deleted file mode 100644 index e28d2f750..000000000 --- a/tests/mock_player.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "mock_player.h" - -MockPlayer::MockPlayer() -{ -} diff --git a/tests/mock_player.h b/tests/mock_player.h index 2e4238fa5..3aa41bea2 100644 --- a/tests/mock_player.h +++ b/tests/mock_player.h @@ -27,7 +27,7 @@ class MockPlayer : public PlayerInterface { public: - MockPlayer(); + MockPlayer() {} MOCK_CONST_METHOD0(engine, EngineBase*()); MOCK_CONST_METHOD0(GetState, Engine::State()); @@ -35,7 +35,7 @@ public: MOCK_CONST_METHOD0(GetCurrentItem, PlaylistItemPtr()); MOCK_CONST_METHOD1(GetItemAt, PlaylistItemPtr(int)); - MOCK_CONST_METHOD0(playlists, PlaylistManager*()); + MOCK_CONST_METHOD0(playlists, PlaylistManagerInterface*()); MOCK_METHOD0(ReloadSettings, void()); diff --git a/tests/mock_playlistmanager.h b/tests/mock_playlistmanager.h new file mode 100644 index 000000000..ec1c1e9ae --- /dev/null +++ b/tests/mock_playlistmanager.h @@ -0,0 +1,76 @@ +/* This file is part of Clementine. + Copyright 2010, David Sansome + + Clementine is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Clementine is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Clementine. If not, see . +*/ + +#ifndef MOCK_PLAYLISTMANAGER_H +#define MOCK_PLAYLISTMANAGER_H + +#include "playlist/playlistmanager.h" + +class MockPlaylistManager : public PlaylistManagerInterface { +public: + MockPlaylistManager(QObject* parent = NULL) : PlaylistManagerInterface(parent) {} + + MOCK_CONST_METHOD0(current_id, int()); + MOCK_CONST_METHOD0(active_id, int()); + + MOCK_CONST_METHOD1(playlist, Playlist*(int)); + MOCK_CONST_METHOD0(current, Playlist*()); + MOCK_CONST_METHOD0(active, Playlist*()); + + MOCK_CONST_METHOD0(GetAllPlaylists, QList()); + + MOCK_CONST_METHOD1(selection, const QItemSelection&(int)); + MOCK_CONST_METHOD0(current_selection, const QItemSelection&()); + MOCK_CONST_METHOD0(active_selection, const QItemSelection&()); + + MOCK_CONST_METHOD1(name, QString(int)); + MOCK_CONST_METHOD0(task_manager, TaskManager*()); + MOCK_CONST_METHOD0(library_backend, LibraryBackend*()); + MOCK_CONST_METHOD0(playlist_backend, PlaylistBackend*()); + MOCK_CONST_METHOD0(sequence, PlaylistSequence*()); + MOCK_CONST_METHOD0(parser, PlaylistParser*()); + + MOCK_METHOD2(New, void(const QString&, const SongList&)); + MOCK_METHOD1(Load, void(const QString&)); + MOCK_METHOD2(Save, void(int, const QString&)); + MOCK_METHOD2(Rename, void(int, const QString&)); + MOCK_METHOD1(Remove, void(int)); + MOCK_METHOD1(ChangePlaylistOrder, void(const QList&)); + + MOCK_METHOD1(SetCurrentPlaylist, void(int)); + MOCK_METHOD1(SetActivePlaylist, void(int)); + MOCK_METHOD0(SetActiveToCurrent, void()); + + MOCK_METHOD1(SelectionChanged, void(const QItemSelection&)); + + MOCK_METHOD0(ClearCurrent, void()); + MOCK_METHOD0(ShuffleCurrent, void()); + MOCK_METHOD0(SetActivePlaying, void()); + MOCK_METHOD0(SetActivePaused, void()); + MOCK_METHOD0(SetActiveStopped, void()); + MOCK_METHOD2(SetActiveStreamMetadata, void(const QUrl&, const Song&)); + MOCK_METHOD1(RateCurrentSong, void(double)); + MOCK_METHOD1(RateCurrentSong, void(int)); + + MOCK_METHOD3(PlaySmartPlaylist, void(smart_playlists::GeneratorPtr, bool, bool)); + + void EmitPlaylistManagerInitialized() { + emit PlaylistManagerInitialized(); + } +}; + +#endif // MOCK_PLAYLISTMANAGER_H diff --git a/tests/mpris1_test.cpp b/tests/mpris1_test.cpp index 30f12e666..511af1d1f 100644 --- a/tests/mpris1_test.cpp +++ b/tests/mpris1_test.cpp @@ -18,6 +18,8 @@ #include "core/encoding.h" #include "core/mpris1.h" #include "core/song.h" +#include "playlist/playlistmanager.h" +#include "playlist/playlistsequence.h" #include "radio/fixlastfm.h" #include @@ -25,20 +27,31 @@ #include "gtest/gtest.h" #include "test_utils.h" +#include "mock_engine.h" #include "mock_player.h" +#include "mock_playlistmanager.h" #include #include +#include #include #include #include +using ::testing::_; +using ::testing::Return; + namespace { -class Mpris1Test : public ::testing::Test { +class Mpris1BasicTest : public ::testing::Test { protected: void SetUp() { + sequence_.reset(new PlaylistSequence); + + EXPECT_CALL(player_, engine()).WillRepeatedly(Return(&engine_)); + EXPECT_CALL(player_, playlists()).WillRepeatedly(Return(&playlists_)); + EXPECT_CALL(playlists_, sequence()).WillRepeatedly(Return(sequence_.get())); } QString service_name() const { @@ -46,11 +59,14 @@ protected: QString::number(QCoreApplication::applicationPid()); } + MockEngine engine_; MockPlayer player_; + MockPlaylistManager playlists_; + + boost::scoped_ptr sequence_; }; - -TEST_F(Mpris1Test, CreatesDBusService) { +TEST_F(Mpris1BasicTest, CreatesDBusService) { EXPECT_FALSE(QDBusConnection::sessionBus().interface()-> isServiceRegistered(service_name())); @@ -64,5 +80,167 @@ TEST_F(Mpris1Test, CreatesDBusService) { isServiceRegistered(service_name())); } + +class Mpris1Test : public Mpris1BasicTest { +protected: + void SetUp() { + Mpris1BasicTest::SetUp(); + + mpris_.reset(new mpris::Mpris1(&player_, NULL, NULL, service_name())); + } + + boost::scoped_ptr mpris_; +}; + +TEST_F(Mpris1Test, CorrectNameAndVersion) { + QCoreApplication::setApplicationName("Banana"); + QCoreApplication::setApplicationVersion("Cheese"); + EXPECT_EQ("Banana Cheese", mpris_->root()->Identity()); + + Version version = mpris_->root()->MprisVersion(); + EXPECT_EQ(1, version.major); + EXPECT_EQ(0, version.minor); +} + +TEST_F(Mpris1Test, Mutes) { + EXPECT_CALL(player_, Mute()); + mpris_->player()->Mute(); +} + +TEST_F(Mpris1Test, GetsVolume) { + EXPECT_CALL(player_, GetVolume()).WillOnce(Return(50)); + EXPECT_EQ(50, mpris_->player()->VolumeGet()); +} + +TEST_F(Mpris1Test, SetsVolume) { + EXPECT_CALL(player_, SetVolume(42)); + mpris_->player()->VolumeSet(42); +} + +TEST_F(Mpris1Test, RaisesVolume) { + EXPECT_CALL(player_, GetVolume()).WillOnce(Return(50)); + EXPECT_CALL(player_, SetVolume(51)); + mpris_->player()->VolumeUp(1); +} + +TEST_F(Mpris1Test, LowersVolume) { + EXPECT_CALL(player_, GetVolume()).WillOnce(Return(50)); + EXPECT_CALL(player_, SetVolume(49)); + mpris_->player()->VolumeDown(1); +} + +TEST_F(Mpris1Test, Pauses) { + EXPECT_CALL(player_, Pause()); + mpris_->player()->Pause(); +} + +TEST_F(Mpris1Test, Stops) { + EXPECT_CALL(player_, Stop()); + mpris_->player()->Stop(); +} + +TEST_F(Mpris1Test, Plays) { + EXPECT_CALL(player_, Play()); + mpris_->player()->Play(); +} + +TEST_F(Mpris1Test, GoesPrevious) { + EXPECT_CALL(player_, Previous()); + mpris_->player()->Prev(); +} + +TEST_F(Mpris1Test, GoesNext) { + EXPECT_CALL(player_, Next()); + mpris_->player()->Next(); +} + +TEST_F(Mpris1Test, SetsPosition) { + EXPECT_CALL(player_, SeekTo(42)); + mpris_->player()->PositionSet(42000); +} + +TEST_F(Mpris1Test, GetsStatus) { + // Engine statuses + EXPECT_CALL(player_, GetState()).WillOnce(Return(Engine::Empty)); + DBusStatus status = mpris_->player()->GetStatus(); + EXPECT_EQ(DBusStatus::Mpris_Stopped, status.play); + + EXPECT_CALL(player_, GetState()).WillOnce(Return(Engine::Idle)); + status = mpris_->player()->GetStatus(); + EXPECT_EQ(DBusStatus::Mpris_Stopped, status.play); + + EXPECT_CALL(player_, GetState()).WillOnce(Return(Engine::Paused)); + status = mpris_->player()->GetStatus(); + EXPECT_EQ(DBusStatus::Mpris_Paused, status.play); + + EXPECT_CALL(player_, GetState()).WillOnce(Return(Engine::Playing)); + status = mpris_->player()->GetStatus(); + EXPECT_EQ(DBusStatus::Mpris_Playing, status.play); + + EXPECT_CALL(player_, GetState()).WillRepeatedly(Return(Engine::Empty)); + + // Repeat modes + sequence_->SetRepeatMode(PlaylistSequence::Repeat_Off); + status = mpris_->player()->GetStatus(); + EXPECT_EQ(0, status.repeat); + EXPECT_EQ(0, status.repeat_playlist); + + sequence_->SetRepeatMode(PlaylistSequence::Repeat_Album); + status = mpris_->player()->GetStatus(); + EXPECT_EQ(0, status.repeat); + EXPECT_EQ(1, status.repeat_playlist); + + sequence_->SetRepeatMode(PlaylistSequence::Repeat_Playlist); + status = mpris_->player()->GetStatus(); + EXPECT_EQ(0, status.repeat); + EXPECT_EQ(1, status.repeat_playlist); + + sequence_->SetRepeatMode(PlaylistSequence::Repeat_Track); + status = mpris_->player()->GetStatus(); + EXPECT_EQ(1, status.repeat); + EXPECT_EQ(1, status.repeat_playlist); + + // Shuffle modes + sequence_->SetShuffleMode(PlaylistSequence::Shuffle_Off); + status = mpris_->player()->GetStatus(); + EXPECT_EQ(0, status.random); + + sequence_->SetShuffleMode(PlaylistSequence::Shuffle_Album); + status = mpris_->player()->GetStatus(); + EXPECT_EQ(1, status.random); + + sequence_->SetShuffleMode(PlaylistSequence::Shuffle_All); + status = mpris_->player()->GetStatus(); + EXPECT_EQ(1, status.random); +} + +TEST_F(Mpris1Test, HandlesShuffleModeChanged) { + sequence_->SetShuffleMode(PlaylistSequence::Shuffle_Off); + EXPECT_CALL(player_, GetState()).WillRepeatedly(Return(Engine::Empty)); + + QSignalSpy spy(mpris_->player(), SIGNAL(StatusChange(DBusStatus))); + + playlists_.EmitPlaylistManagerInitialized(); + EXPECT_EQ(0, spy.count()); + + sequence_->SetShuffleMode(PlaylistSequence::Shuffle_All); + ASSERT_EQ(1, spy.count()); + EXPECT_EQ(1, spy[0][0].value().random); + spy.clear(); + + sequence_->SetShuffleMode(PlaylistSequence::Shuffle_All); + ASSERT_EQ(0, spy.count()); + + sequence_->SetShuffleMode(PlaylistSequence::Shuffle_Album); + ASSERT_EQ(1, spy.count()); + EXPECT_EQ(1, spy[0][0].value().random); + spy.clear(); + + sequence_->SetShuffleMode(PlaylistSequence::Shuffle_Off); + ASSERT_EQ(1, spy.count()); + EXPECT_EQ(0, spy[0][0].value().random); + spy.clear(); +} + } // namespace