diff --git a/src/core/songloader.cpp b/src/core/songloader.cpp index b5a895823..87231709a 100644 --- a/src/core/songloader.cpp +++ b/src/core/songloader.cpp @@ -34,7 +34,7 @@ QSet SongLoader::sRawUriSchemes; const int SongLoader::kDefaultTimeout = 5000; -SongLoader::SongLoader(LibraryBackend* library, QObject *parent) +SongLoader::SongLoader(LibraryBackendInterface* library, QObject *parent) : QObject(parent), timeout_timer_(new QTimer(this)), playlist_parser_(new PlaylistParser(this)), @@ -173,7 +173,7 @@ void SongLoader::LoadLocalDirectory(const QString& filename) { while (it.hasNext()) { // This is in another thread so we can do blocking calls. - LoadLocal(filename, true); + LoadLocal(it.next(), true); } qStableSort(songs_.begin(), songs_.end(), CompareSongs); diff --git a/src/core/songloader.h b/src/core/songloader.h index ab9fbc1ec..b6f01c28f 100644 --- a/src/core/songloader.h +++ b/src/core/songloader.h @@ -29,14 +29,14 @@ # include #endif -class LibraryBackend; +class LibraryBackendInterface; class ParserBase; class PlaylistParser; class SongLoader : public QObject { Q_OBJECT public: - SongLoader(LibraryBackend* library, QObject* parent = 0); + SongLoader(LibraryBackendInterface* library, QObject* parent = 0); ~SongLoader(); enum Result { @@ -107,7 +107,7 @@ private: ParserBase* parser_; QString mime_type_; QByteArray buffer_; - LibraryBackend* library_; + LibraryBackendInterface* library_; #ifdef HAVE_GSTREAMER boost::shared_ptr pipeline_; diff --git a/src/library/librarybackend.cpp b/src/library/librarybackend.cpp index a546cf17c..bf7f5dae4 100644 --- a/src/library/librarybackend.cpp +++ b/src/library/librarybackend.cpp @@ -27,7 +27,7 @@ #include LibraryBackend::LibraryBackend(QObject *parent) - : QObject(parent) + : LibraryBackendInterface(parent) { } diff --git a/src/library/librarybackend.h b/src/library/librarybackend.h index 3668ce73a..bcf47f6fd 100644 --- a/src/library/librarybackend.h +++ b/src/library/librarybackend.h @@ -28,16 +28,10 @@ class Database; -class LibraryBackend : public QObject { - Q_OBJECT - +class LibraryBackendInterface : public QObject { public: - Q_INVOKABLE LibraryBackend(QObject* parent = 0); - void Init(boost::shared_ptr db, const QString& songs_table, - const QString& dirs_table, const QString& subdirs_table, - const QString& fts_table); - - boost::shared_ptr db() const { return db_; } + LibraryBackendInterface(QObject* parent = 0) : QObject(parent) {} + virtual ~LibraryBackendInterface() {} struct Album { Album() {} @@ -57,6 +51,51 @@ class LibraryBackend : public QObject { }; typedef QList AlbumList; + // Get a list of directories in the library. Emits DirectoriesDiscovered. + virtual void LoadDirectoriesAsync() = 0; + + // Counts the songs in the library. Emits TotalSongCountUpdated + virtual void UpdateTotalSongCountAsync() = 0; + + virtual SongList FindSongsInDirectory(int id) = 0; + virtual SubdirectoryList SubdirsInDirectory(int id) = 0; + virtual DirectoryList GetAllDirectories() = 0; + virtual void ChangeDirPath(int id, const QString& new_path) = 0; + + virtual QStringList GetAllArtists(const QueryOptions& opt = QueryOptions()) = 0; + virtual QStringList GetAllArtistsWithAlbums(const QueryOptions& opt = QueryOptions()) = 0; + virtual SongList GetSongs( + const QString& artist, const QString& album, const QueryOptions& opt = QueryOptions()) = 0; + + virtual bool HasCompilations(const QueryOptions& opt = QueryOptions()) = 0; + virtual SongList GetCompilationSongs(const QString& album, const QueryOptions& opt = QueryOptions()) = 0; + + virtual AlbumList GetAllAlbums(const QueryOptions& opt = QueryOptions()) = 0; + virtual AlbumList GetAlbumsByArtist(const QString& artist, const QueryOptions& opt = QueryOptions()) = 0; + virtual AlbumList GetCompilationAlbums(const QueryOptions& opt = QueryOptions()) = 0; + + virtual void UpdateManualAlbumArtAsync(const QString& artist, const QString& album, const QString& art) = 0; + virtual Album GetAlbumArt(const QString& artist, const QString& album) = 0; + + virtual Song GetSongById(int id) = 0; + + virtual void AddDirectory(const QString& path) = 0; + virtual void RemoveDirectory(const Directory& dir) = 0; + + virtual bool ExecQuery(LibraryQuery* q) = 0; +}; + +class LibraryBackend : public LibraryBackendInterface { + Q_OBJECT + + public: + Q_INVOKABLE LibraryBackend(QObject* parent = 0); + void Init(boost::shared_ptr db, const QString& songs_table, + const QString& dirs_table, const QString& subdirs_table, + const QString& fts_table); + + boost::shared_ptr db() const { return db_; } + QString songs_table() const { return songs_table_; } QString dirs_table() const { return dirs_table_; } QString subdirs_table() const { return subdirs_table_; } diff --git a/src/playlist/songloaderinserter.cpp b/src/playlist/songloaderinserter.cpp index ed9796f17..3536d0c4c 100644 --- a/src/playlist/songloaderinserter.cpp +++ b/src/playlist/songloaderinserter.cpp @@ -20,7 +20,7 @@ #include "core/taskmanager.h" SongLoaderInserter::SongLoaderInserter( - TaskManager* task_manager, LibraryBackend* library, QObject *parent) + TaskManager* task_manager, LibraryBackendInterface* library, QObject *parent) : QObject(parent), task_manager_(task_manager), destination_(NULL), diff --git a/src/playlist/songloaderinserter.h b/src/playlist/songloaderinserter.h index 9c1f98298..ee16a8b6b 100644 --- a/src/playlist/songloaderinserter.h +++ b/src/playlist/songloaderinserter.h @@ -23,7 +23,7 @@ #include "core/song.h" -class LibraryBackend; +class LibraryBackendInterface; class Playlist; class SongLoader; class TaskManager; @@ -33,7 +33,7 @@ class QModelIndex; class SongLoaderInserter : public QObject { Q_OBJECT public: - SongLoaderInserter(TaskManager* task_manager, LibraryBackend* library, QObject* parent = 0); + SongLoaderInserter(TaskManager* task_manager, LibraryBackendInterface* library, QObject* parent = 0); ~SongLoaderInserter(); void Load(Playlist* destination, int row, bool play_now, const QList& urls); @@ -60,7 +60,7 @@ private: QSet pending_; int async_load_id_; int async_progress_; - LibraryBackend* library_; + LibraryBackendInterface* library_; }; #endif // SONGLOADERINSERTER_H diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 577ddf4b7..ff7cff5c3 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -30,6 +30,7 @@ #include "devices/devicestatefiltermodel.h" #include "engines/enginebase.h" #include "library/groupbydialog.h" +#include "library/librarybackend.h" #include "library/libraryconfig.h" #include "library/librarydirectorymodel.h" #include "library/library.h" diff --git a/tests/mock_librarybackend.h b/tests/mock_librarybackend.h new file mode 100644 index 000000000..1158c03fc --- /dev/null +++ b/tests/mock_librarybackend.h @@ -0,0 +1,43 @@ +#ifndef MOCKLIBRARYBACKEND_H +#define MOCKLIBRARYBACKEND_H + +#include + +#include "library/librarybackend.h" + +class MockLibraryBackend : public LibraryBackendInterface { + public: + // Get a list of directories in the library. Emits DirectoriesDiscovered. + MOCK_METHOD0(LoadDirectoriesAsync, void()); + + // Counts the songs in the library. Emits TotalSongCountUpdated + MOCK_METHOD0(UpdateTotalSongCountAsync, void()); + + MOCK_METHOD1(FindSongsInDirectory, SongList(int)); + MOCK_METHOD1(SubdirsInDirectory, SubdirectoryList(int)); + MOCK_METHOD0(GetAllDirectories, DirectoryList()); + MOCK_METHOD2(ChangeDirPath, void(int, const QString&)); + + MOCK_METHOD1(GetAllArtists, QStringList(const QueryOptions&)); + MOCK_METHOD1(GetAllArtistsWithAlbums, QStringList(const QueryOptions&)); + MOCK_METHOD3(GetSongs, SongList(const QString&, const QString&, const QueryOptions&)); + + MOCK_METHOD1(HasCompilations, bool(const QueryOptions&)); + MOCK_METHOD2(GetCompilationSongs, SongList(const QString&, const QueryOptions&)); + + MOCK_METHOD1(GetAllAlbums, AlbumList(const QueryOptions&)); + MOCK_METHOD2(GetAlbumsByArtist, AlbumList(const QString&, const QueryOptions&)); + MOCK_METHOD1(GetCompilationAlbums, AlbumList(const QueryOptions&)); + + MOCK_METHOD3(UpdateManualAlbumArtAsync, void(const QString&, const QString&, const QString&)); + MOCK_METHOD2(GetAlbumArt, Album(const QString&, const QString&)); + + MOCK_METHOD1(GetSongById, Song(int)); + + MOCK_METHOD1(AddDirectory, void(const QString&)); + MOCK_METHOD1(RemoveDirectory, void(const Directory&)); + + MOCK_METHOD1(ExecQuery, bool(LibraryQuery*)); +}; + +#endif diff --git a/tests/playlist_test.cpp b/tests/playlist_test.cpp index 9bb84b02c..5ff50ea6b 100644 --- a/tests/playlist_test.cpp +++ b/tests/playlist_test.cpp @@ -33,7 +33,7 @@ namespace { class PlaylistTest : public ::testing::Test { protected: PlaylistTest() - : playlist_(NULL, NULL, NULL), + : playlist_(NULL, NULL, NULL, NULL), sequence_(NULL, new DummySettingsProvider) { } diff --git a/tests/songloader_test.cpp b/tests/songloader_test.cpp index 958b18fd8..50d51249b 100644 --- a/tests/songloader_test.cpp +++ b/tests/songloader_test.cpp @@ -17,6 +17,7 @@ #include "test_utils.h" #include "gmock/gmock-matchers.h" #include "gtest/gtest.h" +#include "mock_librarybackend.h" #include "core/songloader.h" #include "engines/gstengine.h" @@ -30,6 +31,9 @@ #include #include +using ::testing::_; +using ::testing::Return; + class SongLoaderTest : public ::testing::Test { public: static void SetUpTestCase() { @@ -45,7 +49,8 @@ public: protected: void SetUp() { - loader_.reset(new SongLoader); + library_.reset(new MockLibraryBackend); + loader_.reset(new SongLoader(library_.get())); loader_->set_timeout(20000); } @@ -55,6 +60,7 @@ protected: static GstEngine* sGstEngine; boost::scoped_ptr loader_; + boost::scoped_ptr library_; }; const char* SongLoaderTest::kRemoteUrl = "http://remotetestdata.clementine-player.org"; @@ -70,6 +76,17 @@ TEST_F(SongLoaderTest, LoadLocalMp3) { EXPECT_EQ("Beep mp3", loader_->songs()[0].title()); } +TEST_F(SongLoaderTest, LoadLocalFileQueryExecutesButEmpty) { + EXPECT_CALL(*library_.get(), ExecQuery(_)).WillOnce(Return(true)); + TemporaryResource file(":/testdata/beep.mp3"); + SongLoader::Result ret = loader_->Load(QUrl::fromLocalFile(file.fileName())); + + ASSERT_EQ(SongLoader::Success, ret); + ASSERT_EQ(1, loader_->songs().count()); + EXPECT_TRUE(loader_->songs()[0].is_valid()); + EXPECT_EQ("Beep mp3", loader_->songs()[0].title()); +} + TEST_F(SongLoaderTest, LoadLocalPls) { TemporaryResource file(":/testdata/pls_one.pls"); SongLoader::Result ret = loader_->Load(QUrl::fromLocalFile(file.fileName()));